QOMM: query-oblivious market making
Quote without disclosing the request, the pricing rule, or the market. Sixteen makers' pricing rules are applied to a request nobody sees, inside a seven-node multiparty computation with an honest majority. One key is opened: the winner and its committed price. Anyone can verify afterwards that it was the minimum of those offered.
source: qomm/README.md, AUDIT.md, DEPLOYMENT.md, BINDING.md, POSITION.md · MP-SPDZ malicious-shamir, N=7, T=2
The problem it removes
An investor wants to sell ten thousand shares and asks sixteen market makers for a price. Fifteen lose, and the fifteen who lost still know who wanted what, which way, how much, and when. That is not an implementation defect; it is what asking for a price costs in any system where asking means telling. QOMM makes asking not mean telling.
What it does
flowchart TB
U["a user's request
asset, size, side"]
subgraph transport["fixed cadence, additive shares, relay hops"]
REL["every user sends the same bytes
every slot, whether or not they asked"]
end
subgraph mpc["seven computing nodes, malicious Shamir"]
direction TB
PRICE["price every maker at once
this is width, and it is free"]
GATE["eligibility
one comparison layer"]
TOUR["binary tournament
log2(M) comparison layers"]
PRICE --> GATE --> TOUR
end
OUT["one opened key:
the winning price and the winner"]
U --> REL --> PRICE
TOUR --> OUT
NOTE["the trace is the same
whether or not anyone asked"]
REL -.- NOTE
mpc -.- NOTE
classDef secret stroke:#f2b880,stroke-width:2px
classDef mech stroke:#9bb0ff,stroke-width:2px
classDef ok stroke:#5ee0c1,stroke-width:2px
class U,REL secret
class PRICE,GATE,TOUR mech
class OUT ok
Transport
One message of the same length to each node every slot, whether or not there is an order; in a design that speaks only when it needs to, speaking is itself the announcement. The request is split into one additive share per node before it leaves the device, so a single share is uniform noise. Relay hops hold until the slot boundary and reshuffle. Inside the circuit a secret is_real bit decides only whether the makers' state moves; a real slot and a cover slot have identical round counts (286), identical bytes per party (22.2045 MB) and a wall-clock gap of 0.01 s inside a 0.085 s repeat spread.
Pricing rules
A maker's rule is written in a small expression language. The checker derives, with no proof, the bit width the circuit needs, that the output range is bounded, and the audit obligations; then generates the .mpc program for the MP-SPDZ compiler. The qomm-mpc crate links the engine and reads its own counters, so rounds are broken out by communication channel rather than estimated.
Audit
The quote proof (qomm-proofs/src/quote_proof.rs) instantiates Baum–Damgård–Orlandi: input providers publish Pedersen commitments, and the SPDZ online phase is linear operations an auditor replays on the commitments. What is audited is not "the circuit was evaluated correctly" but a market statement: for each maker i, key_i is the committed policy applied to the committed request, and the opened winner is the smallest of those keys. Minimality plus membership is best execution. 152 ms to prove and 173 ms to verify at four makers; 307 and 350 at eight.
C_winner − g·value; details on Cryptography in use and the status page.Node misbehaviour is caught by receipts: every node emits one every slot, so "it did not answer" can be shown to a third party. Fault injection over 7 nodes and 6 slots caught equivocation, omitted makers, stale state and a missing receipt, with zero misses and zero honest nodes accused, and slashed each by the nature of the fault (a double signature is self-contained evidence and heaviest; a missing receipt happens to honest nodes and is lightest).
What auditability costs
Everyone in this line pays something to make the outcome checkable, and only two of six systems measured it.
| what it buys | measured cost | |
|---|---|---|
| Rivinius et al. 2022 | public verifiability + accountability + robustness | 11× to 20× the online phase against plain SPDZ |
| QOMM | public verifiability | 1.07× wall clock, 2.00× traffic, 1.00× rounds |
The gap is where the audit attaches. Rivinius commits to every share of every wire, so the commitment scheme is inside the multiplication. Here the commitment is to a maker's policy, and one proof afterwards shows the mechanism was applied to it, so the MPC only has to run in a wider field: 16-byte elements become 32, and that is the whole 2.00×. Their construction also delivers blame and robustness; this one delivers neither in the deployed engine. Both halves belong in the comparison.
Where the nodes sit decides more than the cryptography
The round count is 70, flat, independent of the number of makers and of the number of assets, so the wall clock carries 70 × RTT of pure waiting on whichever link is slowest.
| node placement (M=16, 31 bits) | one-way delay | one quote |
|---|---|---|
| same rack | 0 ms | 0.166 s |
| same metro | 1 ms | 0.617 s |
| domestic wide area | 5 ms | 1.619 s |
| Tokyo to Singapore | 15 ms | 3.876 s |
| six near, one far (120 ms) | 120 ms | 22.998 s |
| all far (120 ms) | 120 ms | 26.148 s |
artifacts: placement.json, sites.json · delay proxy on one machine; reproduces round trips, not jitter, loss or clock skew
Putting the seven nodes in one metro is six times more effective than any stack of cryptographic improvements, and it raises the correlation of collusion, which is governance, not technology. The obvious compromise, six near and one far, costs 86% of moving all seven far: independence cannot be bought inside a committee one node at a time. The linear model that predicted 18 s at 120 ms measured 23 s, a 28% under-prediction at eight times the distance it was validated at, and that miss is recorded.
Whether 26 s matters is a different question, answered against UniswapX fills: the price drift across two Ethereum blocks (3.6 to 8.6 bp) is the same size as the dispersion the market shows within a single block (4.8 to 7.5 bp). A quote that took 26 s is not distinguishable from an instantaneous one because the price was never that precisely defined, and that is the harshest case available.
What is published is noised
A venue publishing exact winning quotes leaks the policy through repetition, so the quote is disclosed under a differential-privacy budget. The production publication path draws its noise inside the seven MP-SPDZ processes and binds the result, the entity-level budget transition and a 3-of-7 certificate in one atomic operation. The mechanism has finite support and states its measured (ε, δ) explicitly (δ 2.5e-4 at support 8) rather than relabelling itself as pure DP. The noise is 92.9% of the rounds: 28 rounds and 63.9 MB against 2 rounds and 0.0022 MB with no mechanism. A cheaper construction (each party drawing a Pólya share at home, 2 rounds, 1.18× the standard deviation) is known and deliberately not implemented.
What is not noised is the count of settled trades, which is already exact and public on chain. What is secret is the request count: a request that settles nothing leaves no trace, and it is the denominator a maker cannot get any other way. BlockRangeQuery sells distinct-entity counts over a block range at sensitivity 1; on 150,000 UniswapX fills the public fill count explains R² 0.95 to 0.97 of it, and the residual, flow concentration, is what the ε actually buys. Activity is free; concentration is what is for sale.
The gap that is still open
A maker deals its policy to seven nodes and is not one of them. The transport layer proves a node received a committed share; nothing proves the node fed that share to MP-SPDZ. The per-party input check now names the node that fed a value other than the one it was dealt, in the circuit, for one extra round and 0.39% more traffic at soundness 2⁻²⁴⁵, after an earlier version of that check was found unsound while writing its proof (a node could choose an error in the kernel of coefficients it could read; the challenge is now drawn after the input phase). A verdict is not a repair: both name, neither prevents. The security page places each mechanism on the accountability ladder.
The demo is seats
One screen showing everything is the one presentation that cannot make a claim about who knows what. So the demo hands out seats: a browser holds one role and is sent what that role would see, and the developer console shows the same thing a person without one is shown. The taker seat alone gets a price. The maker seat never sees the order and after a match receives only its own fill. The node seat holds shares and can cheat, and what happens then splits three ways. The observer seat shows everything and says on every frame that it is a view no deployment has.
cargo run -j 4 --release --manifest-path rust/Cargo.toml -p qomm-harness --bin serve_demo
http://<host>:8800/?seat=node:3&label=Rin
http://<host>:8800/?seat=maker:1&label=Ann
http://<host>:8800/?seat=observer
What QOMM does not claim
- It is not faster than Prime Match. A quote is 3.6 s at 15 ms RTT and 23 s intercontinental at sixteen makers over four assets; Prime Match runs every 30 minutes at J.P. Morgan with a semi-honest hub. The units differ and the ratio should not be reduced to one number, but on any reading nothing here is faster.
- It does not make MPC publicly auditable; Baum, Damgård and Orlandi did in 2014. It instantiates their construction.
- Privacy does not survive three colluding nodes. Correctness of the quote proof survives all seven.
- There has never been a seven-site deployment. Cross-region figures come from a delay proxy on one machine.
- The staleness measurement has selection bias: UniswapX fills are the trades that happened.
The audit page has the machinery in detail, the binding page the field question, and the deployment page what to pick.
From the technical deck to implementation
The 37-topic cryptography catalogue maps purpose, equations, actors and limitations. Follow the settlement lifecycle for state transitions and optimistic assurance for the two demos and their native settlement boundary.