Operator-blind multilateral compression: how it's built, and three things I'd like criticism on
I built CompressRail during Encode’s Build on Canton hackathon and it has been running against my own DevNet validator since July, so I’d rather post the architecture here and get it shot at than keep polishing it alone.
The problem. Multilateral compression releases initial margin trapped in offsetting derivatives trades, but to find the offsetting cycle every participant has to hand its whole book to a central operator that then sees everyone’s positions. Large dealers accept that; much of the mid-tier and buy-side does not, and stays out. The blocker is privacy, not computation.
The design. The operator coordinates a cycle without ever seeing a position, a notional or a rate, and two layers enforce that together:
- No operator party is a signatory or observer on a position-bearing contract, so projection alone keeps
BilateralTradeout of its view. - Every economic field is written on-ledger only as authenticated-encryption ciphertext, with the content key wrapped per counterparty (and per auditor where disclosed). The operator holds no key.
Matching runs outside the operator party. Each participant reads its own projection, verifies post-cycle risk on its own node and authorises only its own legs. The CompressionCycle contract carries cycle coordination and teardown references but no economic terms, and the whole rebalance commits in one transaction — every leg or none. A participant can grant its regulator a decryption scope for one trade, recorded on-ledger, and nothing beyond it.
What is actually live. Real party allocation, encrypted trades, matching, per-node risk checks and atomic execute against DevNet through the global synchronizer (JSON Ledger API 3.5.4). The privacy claim is measured rather than asserted: every cell of the privacy matrix is read from that party’s own projection, and there is a control that acts as the operator and genuinely attempts to decrypt a participant’s book against the live ledger. It fails, because the operator’s own projection holds zero bilateral trades. An end-to-end suite runs against the same public endpoint the demo uses.
Stated boundary. The operator does see cycle topology — which parties net with whom — never the terms behind it. It runs on a single participant node today, with demo-grade keys, and it is not audited.
Three things I’d genuinely like criticism on:
-
Multi-node. The obvious next step is a cycle across separate participant nodes, one per counterparty. For those who have done this in anger: what actually bites — party hosting and onboarding, synchronizer connectivity, or operational overhead per participant? Is a NaaS provider per counterparty the sane path for a pilot, or does that recreate a trust problem I am trying to remove?
-
Teardown authorisation. Today teardown is authorised by each participant on its own legs, with the cycle contract referencing the trades. I also modelled an explicit nomination choice but did not put it in the live flow. Is there a cleaner Daml pattern for multi-party teardown authorisation where no party — including the coordinator — learns the other side’s terms?
-
External signing. Would adopting external signing / interactive submission materially strengthen the “operator holds no participant key” property, or is projection plus application-layer encryption already the right boundary for this shape of workflow?
Demo: https://demo.compressrail.com (seeds a book and runs a cycle, no signup)
Docs: https://docs.compressrail.com
Code: https://github.com/LevCey/CompressRail
3-minute walkthrough: https://youtu.be/8XmG6ss5XuY
Happy to be told that part of this is wrong — that is the point of posting it.