DeFMI: a settlement layer that never reads the trade
DeFMI is a research implementation for verifying asset transfers without publishing amounts. It checks note spending authority, value conservation, reservation remainders and atomic delivery of securities and cash. It runs on a dedicated non-EVM Avalanche L1; it is not an independently operated FMI with established legal settlement finality.
Updated 2026-09-12. Current note and confidential-asset evidence is revision-pinned below. The earlier tables and charts are historical measurements from defmi/DEFMI.md, not performance results for the new path. Original environment: host-c, rustc 1.97.1, ed25519; scalar multiplication 38.4 ± 4.1 µs, 40-bit range proof 20.88 ms.
How notes settle while values stay committed
A note is the unit of asset management; a Pedersen commitment hides its quantity. Non-PQC notes still use additive homomorphism. With quantities expressed under the same generators, C(v;r) = vG + rH gives C(a;r1) + C(b;r2) = C(a+b;r1+r2). The asset-confidential path also verifies links between asset identities and values.
For example, consume a note worth 100 and create a recipient note worth 30 plus change worth 70. These are the parties' explanatory values, not public amounts. Validators check public commitments and proofs for conservation, non-negative ranges, ownership and asset consistency. A venue settlement also verifies quantity times price, reduces reservations and atomically creates securities and cash claims. Redeeming a claim produces a note that can be spent again.
Preventing reuse without naming the spent note
Every valid spend of the same input note must carry the same nullifier. The current Triptych-based proof binds ownership, value and serial_point to the same hidden input position. Validators check the proof and reject a previously used serial. A spender cannot choose another serial and produce a valid proof to spend that input again. Newly created output notes have their own spending tags.
Public records and wallet secrets
| Purpose | Public | Private |
|---|---|---|
| Quantity | Commitment and consistency proofs | Quantity, asset opening and blinding randomness |
| Receipt | One-time destination point and ciphertext | Decryption key and decrypted opening |
| Spend | Nullifier and spending proof | Spending key and private proof inputs |
Copying a public note does not grant spending authority. Decryption and spending are separate capabilities. Outputs created in one transaction, timing, output count, venue and reservation relationships remain observable. A sender knows what it sent. A cryptographic public format does not guarantee transaction unlinkability or resistance to metadata inference. See self-custody and client-asset management in Japan for the legal distinction.
Native confidential asset identities: 2026-09-12
A randomized commitment replaces the asset identifier, with a proof linking it to the same asset in a public eligible cohort. Cohorts contain 2–64 assets; recipient-encrypted openings identify even zero-quantity notes. Asset definitions and cohorts remain public, and a facility retains its randomized identity through reservation and settlement.
Five AvalancheGo validators on one Linux host executed issuance, reservation, partial fills, cancellation and expiry refunds, claim redemption and reuse of a delivered note. Wallet reads after restart recovered seller balances of 57 securities and 600 currency units, buyer balances of 53 and 410, and untouched refunded balances of 25 and 25. All validator state roots agreed.
Execution record and limits · Outcome · Restart readback
What is guaranteed, and what is not
DeFMI can check only what arithmetic settles without opening anything.
| Guarantee | What makes it hold |
|---|---|
| Value is neither created nor destroyed | per-asset commitment conservation, opening-knowledge and range proofs, canonical inputs and issuance authority |
| No balance goes negative | a range proof on the difference |
| The two legs move together | both are checked before either is applied |
| One instruction settles once | nullifier registration |
| Cash leg = quantity × price | a product proof over three commitments |
| The securities leg is the instructed quantity | an equality proof across generators |
DeFMI verifies asset linkage and consistency with the signed instruction. Economic fairness and legal validity are not consequences of arithmetic alone. Existing venue paths also retain trust in their authorized committee and application rules.
Historical balance-width benchmarks
The linear-backend proof is a bit decomposition of the ledger's balance range, so it should be linear in width. It is: 0.98 ms/bit to build, 0.80 ms/bit to settle, 896 B/bit on the wire. The settlement intercept, 2.1 ms, is the verification of the zkPI instruction itself. At 40 bits settlement costs 34.0 ms, of which about 6% is the instruction and the rest is the ledger's range proofs.
The consequence is a listing decision, not a cryptographic one: if settlement needs to be faster, reconsider the balance width. A quantity of securities and an amount of cash are orders of magnitude apart, so give each rail its own width. Securities at 24 bits and cash at 48 settles 24% faster than both at 48 and sends 10,752 B less, with no change to the cryptography.
The Bulletproof backend
The optimised backend uses the audited bulletproofs crate, changing proof size from linear to logarithmic. It loses fine-grained widths (power-of-two only), so the honest cross-width comparison is the 40-bit linear backend against the 64-bit Bulletproof one.
| balance width | linear settle | Bulletproof settle | speedup | linear package | Bulletproof package |
|---|---|---|---|---|---|
| 8 bit | 8.5 ms | 2.09 ms | 4.1× | 29,267 B | 2,656 B |
| 16 bit | 14.8 ms | 2.78 ms | 5.3× | 36,435 B | 2,912 B |
| 32 bit | 27.6 ms | 4.26 ms | 6.5× | 50,771 B | 3,168 B |
| 40 bit linear vs 64 bit BP | 34.0 ms | 7.02 ms | 4.8× | 57,939 B | 3,424 B |
artifacts: defmi.json, rust_bench.json · optimised backend on host-a (calibration 25.8 µs), baseline on host-c; rerun both on one host before using as promotion evidence
Per core that is 29.4 to 142.5 settlements per second. Verifications of independent packages share nothing, so they parallelise completely: one node measured 217 settlements/s on 8 workers (7.40× one worker). A settlement node's capacity is a procurement question.
Earlier asset-tag construction and measurements
The MPC hides which asset a request is for. Dropping the trade onto a per-instrument rail at settlement would give that back; putting every instrument on one rail makes conservation hold only across instruments, so asset A could be carried out as asset B.
The construction is an asset tag. Holding q units of asset a means holding A_a^q · h^r; each transfer publishes H = A_a · h^y under a fresh y, and every range proof is made against H. What binds the disguise to a real asset is the range proof on the difference: the payer's balance already sits under A_a, so no other tag can open it. Per settlement the addition is 32 B and one sigma proof across generators; the time cost is inside the measurement's 0.2 ms noise floor. The one-out-of-many membership proof (Groth–Kohlweiss) is needed once, when a balance is issued into an account, at 0.58 ms to verify for 4 instruments and 2.24 ms for 64.
Measured attack arms: carrying a balance out under a registered tag for another asset, and using a point that was never registered, are both rejected with "remainder does not equal balance minus amount". The package is byte-identical whichever of 64 instruments it is.
Netting: gross-gross, gross-net, net-net
These are BIS DvP models 1, 2 and 3, and at the same time a question of how many range proofs land and where. A gross rail proves at each order that the post-trade position is non-negative, so settlement failure cannot occur by construction; the price is order dependence. A net rail only accumulates homomorphically during the period and proves nothing until the close, where it shows coverage once per participant on the net. A commitment hides the sign as well as the magnitude, so an intermediate negative position leaks nothing.
| N | P | mode | verify per order | at close | total | vs gross-gross |
|---|---|---|---|---|---|---|
| 64 | 8 | gross-gross | 6.25 ms | 0 | 400.0 ms | 1.00× |
| 64 | 8 | gross-net | 4.84 ms | 10.3 ms | 320.1 ms | 1.25× |
| 64 | 8 | net-net | 3.54 ms | 20.7 ms | 247.5 ms | 1.62× |
| 64 | 8 | net-net + attested | 0.00 ms | 20.5 ms | 20.6 ms | 19.40× |
The first prediction was wrong. Counting range proofs alone said net-net would be an eighth of the work; measured, it is 1.62×, because 3.5 ms per order is the verification of the zkPI instruction itself, needed once per trade, and netting does not remove it. What removes it is changing the granularity of the instruction: if the quorum signs a whole cycle, the settlement layer's work stops depending on the number of trades. The allocation then becomes the quorum's attestation rather than a proof. That is what a central counterparty has always been; this only makes it explicit, and DeCCP is where it is made defensible.
An intraday overdraft as a commitment
Practice does not refuse every order that would take a net position negative; it grants a limit against pledged collateral, which is exactly the Bank of Japan's intraday overdraft. Here the limit is a commitment, and coverage is proved about position + limit, so the proof never says which side of zero the position was on. The limit is essentially free: 9.4 ms without, 9.2 ms with, the same range proof width against a different commitment. Granting one costs 9.4 ms to build and 1.3 ms to verify, once.
PositionBook::grant and Cycle::admit are separate calls, and there is no state that locks pledged collateral. The cost of the limit is measured; the atomicity is a written requirement that is not built.The default waterfall
A net rail can fail at the close, and the order in which that failure is worked through is the substance of the arrangement, so it is enforced. The condition that tranche k may be drawn only once tranche k−1 is exhausted is written draw_k × remaining_{k−1} = 0, with the product's commitment pinned to the identity. Cost is linear at 11.2 ms per tranche to build and about 1.4 ms to verify, once per default.
Interposing a clearing house
Under novation there is no bilateral split left to verify: a trade between A and B becomes A against the house and the house against B. An obligation is a commitment, so replacing one edge with two is two multiplications and no proof. The house's book is flat by the same construction. Measured at 8 participants, net-net grows with the trades (66 ms at 16 to 794 ms at 256) and the cleared cycle does not (19 ms to 38 ms). Novation costs 0.53 µs a trade. What it buys is that the attested arm becomes defensible: a named house took the other side, its book is checked flat by anyone, its margin is a committed cap, and its capital sits in the waterfall where CPMI-IOSCO and EMIR put it.
Four things it does not do: obligation graphs are per asset, so mixed-instrument novation is refused; positions at different providers are not cross-margined; arithmetic validity says nothing about legal validity; and the house can leave a trade out, though it can no longer invent one, because check_novation requires both counterparties' signatures on every edge of the before graph.
Hiding who paid whom: the note ledger
The current note format stores a one-time owner point, value commitment, ephemeral public key and recipient ciphertext separately. Version 2 uses a Triptych-based proof binding ownership and value to the same hidden input, publishing U/S as its nullifier rather than the public owner key. The following tables and charts describe the earlier implementation, not the performance or security of the current proof.
| ring size | prove (payer) | verify (node) | wire |
|---|---|---|---|
| 2 | 10.9 ms | 1.8 ms | 37,024 B |
| 16 | 11.7 ms | 2.6 ms | 37,696 B |
| 64 | 14.5 ms | 3.7 ms | 38,144 B |
| 512 | 40.3 ms | 9.3 ms | 38,816 B |
The asymmetry is the point. The wire grows 224 B per doubling and verification stays under 10 ms up to a ring of 512; what grows is proving, on the payer's own device. So the payer caps the anonymity set, not the settlement node. A payee scans the pool at 0.063 ms per note, one scalar multiplication, and that is the only cost proportional to the pool. One-time points do not directly name a permanent address; metadata can still link payments.
In the Rust port the same DvP over two note rails settles in 51.9 ms at a ring of 8 with a 5,476 B package, against 50,827 B for the retired implementation, the Bulletproofs-against-bit-decomposition effect again. The build column there includes the whole 3-of-7 FROST ceremony, so it is an end-to-end construction cost.
What the ring is actually worth
A ring is an anonymity set only if the decoys are indistinguishable from the real note. A real spend is of a note the spender was just paid, because that is what settling is. Uniform decoys are mostly older, so an observer who guesses the newest member of the ring beats 1/R for free. The strategy was stated before the run.
| decoys | ring | traffic 0 | traffic 4 | traffic 16 | nominal 1/R |
|---|---|---|---|---|---|
| uniform | 16 | 1.000 | 0.547 | 0.359 | 0.062 |
| recent | 16 | 1.000 | 0.062 | 0.062 | 0.062 |
artifact: rings.json (host-a) · "traffic" is other settlements landing between being paid and paying
An anonymity set on a note rail is other people's traffic, and the decoy rule only decides how much of it the ring can use.
With no other traffic the ring is worth nothing at any size under either rule. With sixteen settlements of traffic, recency-matched decoys (ring_recent, thirty lines) bring the observer to exactly the nominal figure where uniform decoys left it at 5.8× that.
A state root that stopped growing with history
The ring benchmark found verification climbing with the pool, and nothing in check_spend is proportional to the pool. The state root was: it re-compressed every note ever held and re-sorted every spent serial, four times a settlement. At 4,096 notes that was 61.3 ms of bookkeeping beside 8 ms of cryptography. Notes are only appended and serials only inserted, so the root is now a running hash extended once per change: 0.15 µs, flat, against 15.3 ms by walking.
Payment versus payment, across two ledgers
Two ledgers that share no state have no function that moves both legs, and fair exchange without a third party is impossible in general, so something has to pass between them. A hash lock passes a preimage that ends up in the clear on both ledgers, so anyone reading both can join the legs. What is used instead is an adaptor signature: the first mover's claim on one ledger hands the second mover a scalar, and what each ledger records is an ordinary signature with nothing in common with the other's.
1. Bob -> Alice : Y = g^y
2. Alice prepares leg A; her money leaves her account
Alice -> Bob : a pre-signature over "leg A", adapted to Y
3. Bob prepares leg B, and sends his own pre-signature
4. Bob claims on A -> he is paid, and y becomes readable
5. Alice reads A, recovers y, claims on B -> she is paid
Bob draws the secret and moves first, so Bob is never at risk. Alice is exposed in exactly one window, between steps 4 and 5, and safe if and only if the gap between the two deadlines covers her reaction. That gap is this arrangement's Herstatt risk. Measured on 32-bit rails: prepare a leg 1.29 ms, the first mover's claim 0.05 ms, the second mover's reaction 0.06 ms, unwind an expired leg 0.55 µs. The cryptography is not what puts the money at risk; the deadline gap is set by the settlement finality of the two ledgers, three to five orders of magnitude larger. A deployment that wants a short window should shop for finality rather than for faster proofs.
On one chain, two DeFMI venues can also be called from a single transaction: atomic for free, zero exposure, and the transaction is the link. The adaptor arm costs four times the calls and 3.0% more verification, and buys unlinkability only when handles are derived per venue. The table on the zkPI page shows the observer at 1.000 with one name everywhere and at 1/k with per-venue handles, with the cryptography unchanged.
Agreeing with the book of record
Under Japan's book-entry regime this ledger cannot be the register: title rests on the record the transfer agent and account management institutions keep. So DeFMI is a mirror, and reconciliation is the price of that arrangement. It is one line of algebra: commitments multiply, so the product of the balances is a commitment to their sum; divide out the register's figure under the asset tag and what remains must be a pure power of h. Proving knowledge of that exponent proves the totals agree and says nothing else. The proof is 96 B whatever the ledger holds; checking 4,096 positions takes 0.65 ms. A 3-of-7 quorum assembles the same statement from shares of the aggregate blinding in 4.5 ms, so nobody holds the sum, which matters because whoever holds it could open the whole ledger.
A break is pass or fail. Finding where needs subtotals, and every subtotal claimed becomes public down to one position, which is a balance. This is the only operation in DeFMI that discloses on purpose, and it is the one you reach for on the day something is wrong. A register that keeps a figure per position localises for free instead.
Showing an auditor one slice
A note wallet is a view key and a spend key. The scoping is not in the key; it is in the address. A scope (an instrument, a quarter, a mandate) derives its own address from the wallet's seeds by hashing, and notes sent there are found by that scope's view key and by nothing else. A grant is 0.08 ms to issue and 0.07 ms to check; the holder of a scope reaches exactly the fifth of the pool it was granted and recovers no serials, because a serial needs the spend key.
Three limits do not go away. A grant cannot be taken back, so revocation is moving to the next scope, which is an act of address management, and Rolling makes the schedule an object rather than a discipline. A view key is incoming only; outflows are a different disclosure. And scoping is only as fine as the payers cooperate: a payer using last quarter's address puts the note in last quarter's scope, which arrived_off_schedule detects and nothing prevents.
Who is allowed to hold a handle
Anyone can pick a handle. What needs permission is being vetted, and the vetting roll holds sealed envelopes C = a·G + r·h, not handles, so adding one reveals a uniformly random point and the timing of an onboarding says nothing about which entry is theirs. Membership is proved one-out-of-many over a fixed group; a fresh ring per proof would look more private and be less, because overlapping rings intersect. A Schnorr proof pins the handle to the one the envelope determines, so a vetting yields one handle and not a family. Roll::vetted() and Roll::crowd() are public so anyone can check the anonymity set's size; hiding the vetting event and proving the size of the crowd are the same information, and the design chooses the second.
Verification was predicted to double with the crowd and grows about 1.4× instead, the batched multi-scalar multiplication showing through. At a crowd of 128 the check is 3.84 ms and the proof 1,676 B, so 128 is the default (vetting::CROWD). A crowd of thousands needs a Merkle tree inside a circuit, a different proof system from the sigma protocols and Bulletproofs here.
The Avalanche L1
The deployed execution path is a dedicated non-EVM custom VM in avalanche/defmivm/, launched by AvalancheGo over RPCChainVM protocol 45. Native transitions: asset registration, account opening, pre-authorised reserves, atomic multi-leg settlement. The full acceptance gate covers account-free notes, pre-authorised reserves, seven-party MPC zkPI, atomic multi-RFQ settlement, shared legal-entity caps, restart recovery and state-root agreement.
| property | observed |
|---|---|
| local AvalancheGo processes | 5 |
| accepted heights | 1, 2, 3, 4, 5 |
| settlement acceptance | 207.3 ms |
| two account openings | 424.6 ms |
| node restart and state recovery | 1454.7 ms |
| same state root before and after restart | yes |
artifacts: avalanche_l1_acceptance.json, avalanche_qomm_full_acceptance.json (two RFQs in one atomic batch at height 53, claim materialisation at height 54, validator restart with identical roots)
The run uses five processes on one host. It proves native consensus acceptance, idempotent crash recovery and state-root agreement. It does not prove five independent organisations or public-network readiness.
What is still missing
- Validators verify the complete submitted proof suite but do not re-run the private MP-SPDZ transcript or prove the share-to-proof handoff. Removing that committee trust needs a proof of the whole private computation and a separate consensus benchmark.
- Admission, pledge, limit and payment are not one atomic event.
- The current nullifier does not give the sender the spending secret. Timing, candidate sets and reservation metadata can still link activity.
- Adding a second settlement currency is an account-opening decision, not a code change, because a tagged cash leg opens against the currency the account is denominated in.