Make Anonymity Coherent Again: Proposal for privacy as first-class citizen in JAM


Polkadot’s transition to JAM provides a unique opportunity to solve the “Original Sin” of smart contract blockchains: the lack of native privacy. However, simply deploying privacy protocols (like Aztec or Tornado Cash clones) as isolated Services / Parachains (manta?) will lead to fragmented anonymity sets and poor UX.

Recently I heard Gavin Wood advocate for client-side zk-proofs generation, and I agree with tihs. But it is clear that privacy requires state contention management (preventing double spends without revealing the spender) which the Account model doesn’t handle natively. When writting Noir on top of EVM this becomes clear right away, and you have to turn up to projects that do, like Aztec.

I propose that JAM must deploy a Canonized Privacy Service. This service should provide the bare-metal primitives for a Global Anonymity Set, specifically managing the UTXO/Nullifier state and Merkle Frontiers, while leaving the application logic to upper-layer services.

1. Private State

The Account Model while efficient for transparency, is fundamentally hostile to privacy.

Privacy protocols like Zcash and Aztec utilize an Encrypted UTXO model managed by a Nullifier Set. State is not modified in place, it is appended. This prevents double-spende without revealing the user, etc. But implementing this on general-purpose chains is a nightmare. Developers are forced to deploy custom Merkle contracts and build complex, centralized off-chain indexers to reconstruct paths, leading to “Indexing Hell.”

2. JAM: opportunity for a Global Anonymity Set

The transition to JAM shifts us from asynchronous chains to synchronous services. If we treat privacy as just another “App” layer, we risk two failures:

  • Fragmentation: A user on “Privacy App A” is not hidden among users of “Privacy App B.” The anonymity sets remain small and statistically vulnerable.

  • Broken Composability: Without a shared Nullifier standard, distinct privacy services fracture the anonymity set. A shared System Service allows distinct applications to share a unified ‘Shielded Pool’ of liquidity, even if the application logic differs. Otherwise it’s back to incoherence.

3. Proposed Architecture: JAM Privacy System Service

A Native System Service that implements the UTXO/Nullifier logic within the CoreJAM workflow. This decouples the heavy cryptography (ZK verification) from the state management (Nullifier tracking).

  • Refine (Stateless Verification): This phase acts as a massively parallel verifier. It ingests client-generated Work Packages containing ZK proofs. It executes the raw verification logic on the PVM, filtering out invalid proofs without touching the global state.
  • Accumulate (Nullifier Sequencer) This phase maintains the canonical Nullifier Set and the Merkle Tree Root.
    • Input: Validated Work Results from the Refine phase.

    • Logic: It checks for Nullifier collisions (Double Spends) and updates the Merkle Frontier.

    • Concurrency: To handle the parallel generation of proofs against moving state, the service must implement a State Root History (Ring Buffer), allowing proofs generated against recent roots to settle validly.

  • Data Lake: this service could publish encrypted note ciphertexts directly to the JAM Distributed Data Lake. This creates a canonical, high-throughput stream that wallets can sync from without bloating the scarce Accumulate state with history.

Technical Requirements: For this Service to be viable, the PVM (RISC-V) may have expose Host Functions for pairing-friendly curves (BN254 or BLS12-381). Without these specific ecalls, SNARK verification may exhaust Core limits (unsure), rendering the service economically nonviable.

For privacy to be a first-class citizen, the JAM implementation must expose Host Functions for EC Pairings.


Note: Everything proposed here is admittedly above my paygrade. Contrary to @polka.dom’s advice to be assertive, I can’t say to be an expert on these topics. I’m a simple Solidity dev with some introduction to Noir and previous work in infrastructure.

However, I care deeply about privacy, JAM, and the core values of this ecosystem. I’m bringing this forward because I’m worried we might miss a critical train, one that is essential for societies relying on truly resilient sovereign systems.

This architecture might be complete bollocks. But from I’ve started to see, having some private state management as first-class citizen will become essential for blockchain tech. It may also be the case that all of this was already considered.

2 Likes

I think this is what Kusama is for and I would like to see submissions of this kind to the privacy bounty once available :slight_smile:

2 Likes

But we are not a utxo chain, the usecase for an utxo chain that has one function like zcash is that you have a nullifier set that customized based on one thing, but we want privacy for general compute, like for risc-v programs with pvm, but you should not hardcode logic for one circuit/zk program, needs to be more generic. I think you should think more widely about PVM and zk(we can do more than an UTXO chain can, like a lot more, especially with jam that suppose to be 2m x faster than evm), maybe checkout zexe paper: https://eprint.iacr.org/2018/962.pdf . The question should be how can we make generic privacy for PVM. Regarding global anonymity set, in order to compete with Zcash 1b+ shielded pool size, you need to have a zk shielded pool that spreads accross different chains, there are several “universal privacy sets“ that people can opt into to such as https://shield.markets , privacypools.com etc.

Agreed, but my point goes beyond what a grant could do, as it’s directly related to JAM specification I guess. The Graypaper explicitly states that lookup_preimage is the only opinionated host function allowed in Refine. But it does not list the calls for elliptic curve pairings (like `bls12_381_multi_miller_loop` or `bn254_pairing`) that are standard in Ethereum’s EIP-197.. from what I understand, only sr25519 and ed25519 are allowed, which wouldn’t work to verify Groth16 or plonk on them (may be wrong here). Aztec, for example, strictly requires this. I may be wrong on this..

ZEXE would still reqiure native elliptic curve pairings right?
Also, not sure I understand how ZEXE disproves this, as they seem to use UTXO and explain why this is the way to go themselves:

Remark 2.3 (working in the UTXO model). In the records nano-kernel, applications update their state by consuming records containing the old state, and producing new records that contain the updated state (…) through the (UTXO) model. This is in contrast to the “account-based” model which is used by many other smart contract systems. At present, it is not known how to efficiently achieve strong privacy properties in this model even for the simple case of privacy-preserving payments among any number of users (…) On the other hand, we show in this paper that these properties can be achieved in the UTXO model at a modest cost.

My argument isn’t about hardcoding a specific circuit; it’s that generic privacy requires generic cryptographic primitives (pairings) which the PVM currently excludes. And that UTXO is the standard of what is being done and working. Why re-invent the wheel everytime.

I guess that BLS precompiles aligned Ethereum standards will be a good thing to implement in Asset Hub.

In the enshrinement of ZK based privacy at a core level I’m not that sure. Maybe a simpler solution like ZK wrapped privacy tokens has more upside, clearly cleaner than utxo-like bills approach. Full composability and just a burn proof for reissuance. ERC‑8065: Zero Knowledge Token Wrapper - ERCs - Fellowship of Ethereum Magicians

We need(/would be really nice to have) the bn256 precompiles(which would be BN256Add, BN256Mul and BN255Pairing) but this would be added as extra functions in the runtime not really Jam related. Maybe Jam implementors could add functionality to tap into to private states(?).

“ZEXE would still reqiure native elliptic curve pairings right?“

Yeah, the concept of zexe i like a lot but implementation needs to be wider and modified a lot.

@GENGE with Zexe my line of thought is How can substrate chains utilize zk for privacy friendly generic pallet calls(/compute). How can do more than token transfers? can we make a privacy sets that is as wide as possible?

So my main questions are:

1 how can we make function/pallet calls more privacy friendly in a generic way, a way that would be much more generic than what is shipped by utxo chains. Like instead of only token transfers, could a user make a system remark in a privacy friendly way wrapped in Zk on the hub?

2 How can we make the hub a place that runs zk verifiers, what would attrack zk developers to come to the hub, rn most implemented ZK stuff is using plonk and/or groth16 with either Circom or other zk dsl, better than “yet another evm chain“ does.

What is the unique selling point for developers to come and deploy there dapp on the Hub when they have a shitload of EVM chains to pick from?

Also like how can we enable developers to write zk ciruits that are better than on EVM chains(enable precompiles/focus on risc-v rust implementations) and that are Quantum safe, we dont want to make zk programs that are good for 2 years(see optimistic timeline: https://quantumdoomclock.com/ ) than gets eaten up by quantum machines.

I’m all for privacy in Jam and the hub, but not sure exactly how we get there(since there are alot more talented zk ppl on the forum than me, maybe they have some ideas?). Focusing on adding more precompiles and making it more easy/friendly for zk dapp developers and people that want to run/interact with on-chain custom circuits/zk verifiers seems to be a good step 1

~

flipchan