Auditing Daml privacy on Canton: divulgence, explicit disclosure and where data leaks
Sub-transaction privacy often gets read as “who can see this contract?”. On Canton, a party can learn about a contract in three different ways, and each one needs its own check:
- Stakeholder visibility: signatories and observers are told about the contract and every later event on it.
- Divulgence: a party that isn’t a stakeholder sees the contract because it witnessed a transaction that fetched it. That gives it a view, not a right to use the contract later.
- Explicit disclosure: someone passes the contract off-ledger as a
DisclosedContract, and the receiving party can use it while it’s active.
Below is where each one tends to leak, using a loan example: a bank lends to Bob, and a KYC provider verifies Bob’s identity.
1. Splitting data across templates doesn’t stop a fetch from exposing it
The loan terms sit in LoanProposal (bank + Bob) and the identity data in KycRecord (Bob + KYC provider), so they look separated. But if the bank-controlled Accept choice runs fetch kycCid, everyone who witnesses Accept also sees the KycRecord payload. That includes the bank, which isn’t a stakeholder of KycRecord.
Fix: the bank only needs a yes/no answer. Pass a boolean, or an attestation that carries only the boolean, instead of fetching the full record. Witnesses still learn who signed the attestation.
2. Observer lists are hard to undo
Contracts are immutable, so removing an observer means archiving the contract and creating it again. Every reject or withdraw path has to do this, or the party stays on the deal. Every create is also copied to every observer. If you only need one optional extra party, Optional Party is easier to reason about than an observer list that keeps growing.
3. Privacy doesn’t end at the Ledger API
- Explicit disclosure has no expiry: the same blob can be attached on every submit while the contract is active. Whoever runs the off-ledger channel (HTTPS, SFTP, email) decides who gets the data.
- Archiving a contract stops it being used, but copies already handed out stay where they are.
- Divulged copies stay in the participant store until pruning reaches them, and how far pruning goes is the operator’s choice.
- Payloads are encrypted on the wire, but informees, message size and required confirmers are still visible, and together they reveal the shape of a transaction.
Checklist before a review
- Make observers only the parties who must stay up to date, not the ones who need a single look.
- Prefer
Optional Partyover observer lists. - Don’t fetch sensitive contracts in widely witnessed choices. Use a boolean or a boolean-only attestation instead.
- Make sure no party depends on divulgence to act. Disclose explicitly, and name the channel that controls access.
- Write down what’s fully confidential (payloads), what’s partly visible (informees, shape, confirmers) and what stays after pruning.
Canton enforces whatever visibility your design sets up. It doesn’t check that this matches your business rules, so that part falls to design and review.
Full article with the code walkthrough: https://hacken.io/discover/auditing-daml-privacy-on-canton-network/
How do others handle KYC or compliance parties in their workflows: as an observer, through an attestation, or with explicit disclosure?