03DarkBook documentation
Privacy model
Two fields are sealed and everything else is published. This page lists each one, says when it becomes public, and ends with the claims this venue does not make.
The claim is narrow on purpose. DarkBook hides the pre-trade exact size of an order and nothing else. Side, price, leverage, declared band and trader pubkey are on the order account from the moment it is placed, and the position that opens at settlement carries the exact size in the clear. A reader who wants to know whether this venue protects something they care about should find that thing in the tables below rather than infer it from the word private.
Order fields
Read from programs/darkbook/src/state.rs:244-256. Every field listed as public
is on the OrderBook account and in the OrderPlaced event, so a mempool
observer and a competing trader reading the book see the same set.
| Field | Status | Public from | Why it is there |
|---|---|---|---|
order_id | Public | place_order | matching and cancel lookup |
trader | Public | place_order | collateral lock and settlement binding |
side | Public | place_order | a CLOB cannot match without it |
price_ticks | Public | place_order | a CLOB cannot match without it |
size_band | Public | place_order | lets a maker price a worst case, and sets the collateral taken |
leverage_bps | Public | place_order | collateral math and risk |
commitment | Public | place_order | binds the exact size without revealing it |
placed_slot | Public | place_order | time priority |
size_lots | Hidden | claim_fill | the value the whole design exists to seal |
salt | Hidden | claim_fill | without it the commitment is brute-forceable over plausible sizes |
size_lots and salt are never written to the order account at all. They exist
off-chain with the trader and reach the chain once, as arguments to claim_fill.
Fill fields
Read from programs/darkbook/src/state.rs:281-296. A fill is written by
match_orders on the rollup and lives in the committed OrderBook account, so
every field on it is public from the match, before any claim. This is the table
people usually assume is smaller than it is.
| Field | Status | Public from | Why it is there |
|---|---|---|---|
fill_id | Public | match_orders | claim lookup |
taker_order_id | Public | match_orders | book provenance |
maker_order_id | Public | match_orders | book provenance |
taker | Public | match_orders | binds the user account at claim |
maker | Public | match_orders | binds the user account at claim |
price_ticks | Public | match_orders | the matched price |
taker_size_band | Public | match_orders | bounds the taker's revealed size at claim |
maker_size_band | Public | match_orders | bounds the maker's revealed size at claim |
claimed | Public | match_orders | replay guard |
matched_slot | Public | match_orders | ordering |
Both legs' declared ceilings are on every fill. An observer watching the tape between the match and the claim knows the counterparties, the price, and a factor-of-8 bound on each side's size.
Threat model
The question each row answers is whether that adversary can size a sandwich exactly, which is the attack the commitment is aimed at.
| Adversary | Sees | Can read the exact size |
|---|---|---|
| Public mempool observer | place_order instruction fields and events | No, commitment only |
| Competing trader reading the book | every Order field | No, not until the claim |
| MagicBlock rollup validator | the full delegated OrderBook account | No, unless it is given the salt |
| Fill-tape observer, post-match pre-claim | every Fill field, both legs' bands | No, bounded to within a factor of 8 |
| Settler service | the plaintext size, by construction | Yes. This is trusted, not defended |
| Post-settlement observer | the Position account | Yes. The profit and loss path is public by design |
The commitment
Computed off-chain by the trader, published on the order, recomputed by the program at cancel and at settlement. The same helper produces it in all three places.
// programs/darkbook/src/ix/orders.rs
pub fn compute_commitment(
salt: &[u8; 32],
size_lots: u64,
leverage_bps: u16,
trader: &Pubkey,
) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(salt);
hasher.update(size_lots.to_le_bytes());
hasher.update(leverage_bps.to_le_bytes());
hasher.update(trader.to_bytes());
hasher.finalize().into()
}
Leverage appears both in the clear on the order and inside the hash, so a trader cannot swap leverage at reveal time and change the collateral arithmetic after the fact. The trader pubkey is inside the hash too, which is what makes a cancel self-authorising: the order's own trader is the single party who can produce a matching preimage.
What is not claimed
These are the claims this venue is not making. They are listed here and in
docs/PRIVACY_MODEL.md, which is the file any marketing copy has to stay inside.
- Not a dark pool. Price and side are public on every order from placement.
- Not identity privacy. The trader pubkey is on the order and on both legs of the fill. There is no zero-knowledge identity layer.
- Not flow privacy. The fill tape after settlement leaks magnitude, and since the per-leg band fix each fill publishes both sides' declared ceilings. Pre-trade exact size is the entire claim.
- Not trustless. A settler holds plaintext sizes to submit a claim, and a compromised rollup operator is outside the guarantee.
- Not free. Size privacy costs the taker about 0.2 bps of half-spread on the live schedule, measured rather than assumed.
- Not a benefit sold to makers. Under size blindness makers quote wider, not tighter. The study found the opposite of the comfortable version of this story.