Association sets

This is the mechanism behind proof of innocence. Alongside proving that a spend is valid, every private spend also proves that the money's origin is on an approved list — without revealing which origin it is.

Origins

When you veil funds, the program stamps that deposit with an origin: a lineage label that says which deposit this money descends from.

  • The program assigns it, you don't. The label is computed from your depositing address plus a counter the program keeps for that address, so a depositor can never pick their own origin — and dirty money can never borrow a clean lineage.
  • It's sealed inside the note. The origin is part of the note's commitment, so it can't be swapped out later.
  • It travels with the money. Change notes, notes you receive from someone else, and notes you get out of a swap all inherit the origin of the note they came from. The proof enforces that one hop at a time — nobody has to reconstruct the chain of ownership to make it work.

The origin of a deposit is visible on-chain, because the deposit itself is public. The origin of a spend is not: in every private transfer, swap, consolidation and withdrawal, the origin is a hidden input to the proof. Nothing on-chain links a spend back to the deposit it came from.

The approved set

An association set provider (ASP) maintains the list of approved origins off-chain and publishes only a short cryptographic summary of it — a Merkle root — on-chain. The full list is public and can be read from Murk's API, so anyone can check what's on it and reproduce the root themselves.

The program keeps the last 64 published roots, each with the time it was posted, and accepts a spend proving against any root posted within the last 3 hours. Two reasons for that window:

  • In-flight proofs don't go stale. You can be a few minutes behind the newest list and your spend still lands.
  • Junk can't crowd out the truth. Roots expire by time, not by being pushed out of a queue, so flooding the ring with roots cannot invalidate an honest one.

Every private spend proves, in zero knowledge, that its note's origin is a leaf of a recently published set. Nothing else about the origin is revealed — not its position in the list, not which entry it is.

With no revocations in effect — the normal state — every deposited origin is approved, so honest users never notice this layer at all.

Your anonymity set

Because your proof says "my origin is one of the approved entries", the crowd you hide in is everyone whose origin is on the same list.

Your anonymity set is the pool ∩ the approved set — not every note in the pool.

In the steady state, where nothing has been revoked, those two are the same thing. Each revocation makes the approved set slightly smaller than the pool. See How privacy works for what else shapes your anonymity.

Spending across origins

One membership proof covers one origin. So a normal transfer, withdrawal, swap or consolidation needs all of its real inputs to share a single origin. If your balance is split across several deposits, it has to be brought together first.

  • SOL — the wallet runs a combine: up to 4 SOL notes with different origins are merged into one note carrying a fresh, program-assigned origin. This fires automatically (with your consent) when you try to spend more than any one source covers; you'll see a "your funds are spread across several sources" prompt. It goes through the relayer.
  • Other tokens — cross-source combining is not available yet. A token balance split across N origins is spendable up to the largest single origin, in one action. Notes within one origin still consolidate normally, and Murk tells you the amount you can send rather than failing partway through.

Full detail on both paths is on Combine notes.

How a combine stays revocable. So that the ASP can still act on a merged note, a combine emits the list of input origins encrypted to the ASP's own key, on-chain. Only the ASP can read it; anyone can verify it exists. That means the ASP can reconstruct the lineage graph straight from the chain — including after a total loss of its own database — and revoking any ancestor automatically drops every descendant. It also means the ASP learns which origins you combined; it does not learn the amounts, the owner, or your balance.

The honest trade-offs

  • Your anonymity set is the approved crowd, not the whole crowd.
  • The ASP is a censorship lever, not a custody lever. It can deny future private spends of a lineage. It cannot mint, take, freeze, redirect, deanonymise or read your funds — and the emergency exit guarantees nothing can be trapped. See How the ASP works.
  • Retroactive flagging only catches money still unspent. A deposit flagged after its funds have already moved on has already escaped. See Revocation.
  • Cross-source spending is limited for tokens today, as described above.

How the ASP works · Deposit screening · Revocation · Emergency exit

results matching ""

    No results matching ""