Proposal: A Native ZK System for Radix

Proposal: A Native ZK System for Radix

Zero-Knowledge Properties — without Zero-Knowledge Proofs

Proposal for the Radix community
Status: Concept — Open for discussion
Builds on: Proposal: A Native Privacy System for Radix


TL;DR

Radix already has all the primitives needed to offer Zero-Knowledge properties without Zero-Knowledge proofs: standard asymmetric cryptography, hash functions, Scrypto smart contracts, and a resource-oriented model that allows proofs to be materialised as physical objects.

By adding two new native object types — the Stealth Vault and the Stealth Proof Token (StPT) — to the previously published privacy proposal, Radix can cover 9 of the 12 most important ZK use cases documented in the industry, without the years of R&D that classical ZK systems require.

This is not a replacement for ZK-proofs in all cases — the most complex cases will require future cryptographic advances. But it is a pragmatic solution, buildable today, and progressively extensible.

The architecture is modular and composable: each StPT instance is independent, each application can combine several, and new types can be added without modifying the existing foundation.

The question is not whether Radix can have Zero-Knowledge properties. The question is: when do we start?


1. Background: the privacy system

This proposal builds on the privacy system published previously, which introduces three complementary tools:

Tool 1 — Stealth Addresses Each payment is sent to a unique ephemeral address derived from the recipient’s stealth_meta_address, published in their Persona. The recipient scans the network to recognise their payments. An observer sees a random address with no link to any identity.

Tool 2 — Validator Level 1 A validator’s stakers can obtain superfungible XRD — whose traceability link has been broken — via a deposit/withdrawal mechanism based on an NFT Claim Ticket and a random delay. Reserved for stakers, this level is regulatorily defensible and creates a staking incentive.

Tool 3 — Validator Level 2 The same mechanism, open to all users without any staking requirement. Anyone can deposit pseudofungible (traceable) XRD and withdraw superfungible (history-free) XRD.

These three tools form the foundation on which this proposal builds.


2. Zero-Knowledge Properties: what are we talking about?

The general principle

A Zero-Knowledge Proof (ZK-proof) allows one to prove that a statement is true without revealing the information that makes it true.

Classic example:
  "I prove that I know the password"
  → without revealing the password

In a blockchain context:
  "I prove that I have at least 1000 XRD of collateral"
  → without revealing that I have 847,000

  "I prove that I am a member of an eligible group"
  → without revealing who I am within that group

Why it is difficult to implement

Existing ZK systems (Zcash, Aztec, StarkNet…) require:

  • Arithmetic circuits — representing computations as mathematical constraints

  • A trusted setup — costly initial cryptographic ceremony

  • Special cryptographic opcodes — elliptic curves, ZK-friendly hash functions

  • Costly on-chain verification — even optimised, far heavier than an ordinary transaction

This is why every ZK project has required years of R&D and deep protocol modifications.

Our approach: the same properties, without the machinery

This document proposes obtaining the properties of ZK-proofs — proving without revealing — using exclusively existing cryptographic primitives in Radix: hashing, standard asymmetric cryptography, and smart contract logic.

What we use:
  ✅ Hash functions (already in Radix)
  ✅ Standard asymmetric cryptography (already in Radix)
  ✅ Scrypto smart contracts (already in Radix)
  ✅ Two new native object types (this proposal)

What we do not use:
  ❌ ZK arithmetic circuits
  ❌ Trusted setup
  ❌ Special cryptographic opcodes
  ❌ Deep protocol modification


3. Elegant integration into Radix

Why Radix is particularly well positioned

Radix’s resource-oriented model — vaults, badges, NonFungibleResources — offers primitives that make this approach natural:

  • Resources are physical objects: they cannot be duplicated, they actually move between vaults. This conservation property is exactly what is needed to materialise proofs.

  • Authorisation rules allow precise definition of who can do what with an object — including DenyAll for transfers, which makes a proof non-transferable.

  • Personas and stealth addresses (previous proposal) provide the pseudonymous identity infrastructure on which our proofs rely.

The approach: from specific to general

Rather than starting from a theoretical abstraction, we proceeded case by case:

Step 1 — Concrete case: proof of solvency How to prove that one has enough collateral to borrow, without revealing the exact balance? This question led to the design of the Stealth Vault and the Solvency Proof Token.

Step 2 — Generalisation By examining other ZK use cases documented in the industry (group membership, anonymous voting, credit score, timestamped commitment…), a common pattern emerged: all can be resolved by the same basic mechanism.

Step 3 — Generic primitive This pattern was formalised into a single primitive: the Stealth Proof Token (StPT), of which the specific cases are specialised instances.


4. The Stealth Vault

Problem solved

In classical DeFi, borrowing against collateral reveals everything:

Alice wants to borrow 500 USDC:
  → She deposits 1000 XRD into the lending protocol
  → Everyone sees that account_alice deposited 1000 XRD
  → The protocol sees her full wallet
  → Her wealth is exposed

The Stealth Vault solves this problem by allowing Alice to lock her collateral in a component not attributable to her real identity, while remaining verifiable by the lending protocol.

How it works — solvency proof example (SPT)

Alice creates a Stealth Vault via her stealth_meta_address
  → Deposits superfungible XRD (no traceability)
  → The vault automatically issues a StPT of type SPT
  → Alice presents the SPT to the lending protocol

At loan opening, the protocol:
  → Verifies the SPT: does the vault exist? is it locked? correct amount?
  → Creates a liquidation badge tied to this specific vault
    (only this protocol can use it to access the vault)
  → This badge also grants the right to modify lock_status
  → Records: vault_address ↔ loan (without knowing who Alice is)
  → Lends 500 USDC to a fresh stealth address of Alice

If liquidation (collateral/debt ratio insufficient):
  → The protocol uses the liquidation badge created at opening
  → Accesses the vault and liquidates the superfungible tokens
  → Repays the loan from the liquidation proceeds
  → The protocol destroys the liquidation badge
  → The Stealth Vault destroys the SPT

If normal repayment:
  → Any stealth address can repay by referencing the loan
    — the protocol does not verify who repays
  → The protocol uses its badge to set lock_status → "free"
  → The protocol destroys the liquidation badge
  → Alice proves control of her stealth_meta_address
    by signing with her spend_private_key stealth,
    directly with the Stealth Vault (not with the protocol)
  → The Stealth Vault releases the tokens to a fresh stealth address
  → The Stealth Vault destroys the SPT

Classic Vault vs Stealth Vault comparison

Property Classic vault Stealth Vault
Owner Named account (visible) Stealth address (non-attributable)
Resource type Visible Visible
Amount Visible Visible
Deposit history Traceable to origin Broken (superfungible tokens)
Link to an identity :white_check_mark: yes :cross_mark: no
Lifetime Permanent, tied to account Ephemeral — created for a specific purpose, destroyed after use or expiration
Authorisation rules Single private key Differentiated: owner key + optional protocol badge
Normal withdrawal Account private key spend_private_key stealth
Forced access (e.g. liquidation) N/A Via badge granted at loan opening

Stealth Vault metadata

Component "StealthVault":

  owner          : stealth_component_xyz   // non-attributable
  resource       : XRD_superfungible

  withdraw_roles : {
    normal      : RequireProof(spend_private_key_stealth)
    liquidation : RequireProof(badge_lending_protocol)
  }
  deposit_roles  : RequireProof(validator_contract)
  metadata_roles : {
    lock_status : RequireProof(badge_lending_protocol)
  }
  recall_roles   : DenyAll
  freeze_roles   : DenyAll

  metadata : {
    stealth_meta_address     : "02abc...03def..."
    lending_protocol_address : "component_lending_xyz"
    lock_status              : "free" | "locked"
    lock_expiry_epoch        : null | epoch
    stpt_issued              : null | hash(StPT_current)
    auto_return_epoch        : null | epoch
  }


5. The Stealth Proof Token (StPT)

Principle

The StPT is a generic primitive: a non-transferable NonFungibleResource, linked to a stealth_meta_address, issued by a verifier contract, destroyed after use or expiration. It materialises on-chain any verifiable property without revealing the underlying information.

Property to prove
  → Verified by an appropriate verifier contract
  → Materialised in a non-transferable on-chain object
  → Linked to a non-attributable stealth_meta_address
  → Presented to the recipient without revealing identity
  → Destroyed after use or expiration

Each StPT carries a proof type (proof_type) indicating which property it certifies — solvency, membership, transaction, commitment, reputation… This type corresponds to the instances detailed below (SPT, MPT, TPT, CPT, RTP).

The verifier contract

The verifier contract is a Scrypto smart contract deployed on Radix whose role is to:

1. Receive a proof request from a user
2. Verify that the property to prove is actually true
   by consulting on-chain state (vault, history, group...)
3. If verification succeeds → mint a StPT to the stealth address
   provided by the user
4. Record the nullifier to prevent abuse

It performs no ZK cryptographic computation — it verifies an on-chain condition and materialises the result in a non-transferable object. The contract does not know who owns the destination stealth address: it verifies a condition, mints an object, and stops there.

Depending on the StPT type, the verifier contract is deployed by a different entity:

SPT  → deployed by the lending protocol or the Stealth Vault itself
MPT  → deployed by the DAO, the validator, or a KYC authority
TPT  → deployed by the validator + Radix Engine
CPT  → deployed by the auction or prediction protocol
RTP  → deployed by the loan history protocol

The contextual nullifier

A StPT must not be usable twice in the same context — for example voting twice in the same ballot, or borrowing twice with the same SPT. But we also want two legitimate uses in different contexts to be impossible to link to each other.

The solution is the contextual nullifier:

When used in context C:
  nullifier_C = hash(StPT_id + context_C + usage_epoch)
  → published on-chain, prevents reuse in this context
  → different for each context (vote, loan, access...)
  → two nullifiers from different contexts are mathematically
    unlinkable, even if they come from the same StPT

This is the functional equivalent of the nullifier in classical ZK systems — without arithmetic circuits.

Common structure

NonFungibleResource "StPT":

  transfer_roles : DenyAll          // non-transferable, always
  mint_roles     : verifier_contract only
  burn_roles     : automatic at expiration or use

  base_data : {
    stealth_meta_address : "02abc...03def..."
    proof_type           : SPT | MPT | TPT | CPT | RTP | ...
    commitment           : hash(proved_property + secret)
    context_nullifier    : null  ← filled at use
    usage_limit          : 1 | N
    issued_epoch         : N
    expiry_epoch         : N + duration
    verifier_address     : "verifier_component"
    authorized_verifier  : "recipient_component" | null
  }

  extended_data : { ... }  // specific to each instance

Coverage of known ZK use cases

The following table presents all ZK use cases documented in the industry, indicating for each whether our system covers them:

Case                             Instance   Trustless   Feasible
────────────────────────────────────────────────────────────────────
1.  Solvency                     SPT        ✅           ✅ today
2.  On-chain membership          MPT        ✅           ✅ today
3.  Legitimate transaction       TPT        ✅           ✅ today
4.  KYC / compliance             MPT        ⚠️ semi      ✅ today
5.  Credit score                 RTP        ✅           ✅ today
6.  Anonymous vote               MPT        ✅           ✅ today
7.  Confidential input exec.     —          ❌           ❌ out of scope
8.  Non-inclusion (sanctions)    —          ❌           ❌ out of scope
9.  On-chain anti-Sybil          MPT        ✅           ✅ today
10. Asset ownership              MPT/SPT    ✅           ✅ today
11. Timestamped commitment       CPT        ✅           ✅ today
12. Confidential smart contracts —          ❌           ❌ out of scope
────────────────────────────────────────────────────────────────────
9 out of 12 cases covered — 3 require real ZK-proofs

Cases 7, 8 and 12 require homomorphic cryptography or real ZK-proofs. They remain out of scope for this proposal.

Each StPT instance presented below is a conceptual starting point. Each would require detailed specification and implementation work to become a real application — this document aims to open the discussion, not to provide a complete implementation.

The instances

SPT — Solvency Proof Token

Case 1: proof of solvency

proof_type    : SPT
duration      : ~24h
extended_data : {
  threshold          : 1000
  resource_type      : XRD
  vault_address      : "component_stealth_xyz"
  lending_protocol   : "component_lending_xyz"
}

Verifier: stealth vault (trustless, automatic) Usage: DeFi borrowing, guarantee, bond, collateral


MPT — Membership Proof Token

Cases 2, 4, 6, 9: group membership, KYC, vote, anti-Sybil

proof_type    : MPT
duration      : variable by context
extended_data : {
  group_id         : hash(group_definition)
  group_commitment : hash(member_list + group_secret)
  subtype          : STAKER | KYC | VOTER | HUMAN | MEMBER | ...
}

Verifier: group contract (trustless if on-chain, semi-trust if external authority) Usage: DAO governance, pooled KYC, anonymous vote, restricted access


TPT — Transaction Proof Token

Case 3: proof of legitimate transaction

proof_type    : TPT
duration      : ~1h
extended_data : {
  transaction_commitment : hash(amount + recipient + secret)
  legitimacy_proof       : hash(radix_engine_validation)
  superfungibility_proof : hash(nft_claim_ticket_used)
}

Verifier: validator + Radix Engine (trustless) Usage: confidential payment proof, basic regulatory compliance


CPT — Commitment Proof Token

Case 11: timestamped commitment

proof_type    : CPT
duration      : long (until reveal)
extended_data : {
  commitment       : hash(commitment + secret + timestamp)
  reveal_condition : epoch | event | manual
  revealed         : false
  revealed_value   : null  ← filled at reveal
}

Verifier: auction or prediction contract Usage: sealed-bid auctions, predictions, timestamped contracts


RTP — Reputation Proof Token

Case 5: credit score / reputation

proof_type    : RTP
duration      : ~7 days
extended_data : {
  score_threshold    : 700
  score_category     : CREDIT | REPAYMENT | ACTIVITY
  history_commitment : hash(history + secret)
  sample_size        : 5
}

Verifier: stealth loan history contract Usage: preferential rates, increased borrowing limits, seller reputation


6. Possible applications

When an application combines multiple StPT types, this implies creating multiple distinct verifier contracts — and possibly multiple Stealth Vaults — each managing its own proof type. These components interact via the badges and nullifiers described above, but remain independent at the protocol level.

BtoC

Decentralised credit scoring (RTP) A user accumulates an on-chain repayment history. Their wallet generates an RTP “score ≥ X” presentable to any lending protocol for better rates — without revealing their identity or full history.

Confidential subscriptions and access (MPT) A user proves they have paid for a subscription without revealing their identity to the service. The service cannot track their activity. Applicable to media, premium services, on-chain private clubs.

Private DAO governance (MPT) DAO members vote without revealing their individual vote. Only the aggregated result is visible. Eliminates strategic voting and social pressure.

Confidential decentralised insurance (SPT + TPT) A policyholder proves that a claim occurred (TPT, via a verifier contract) and exceeds the deductible threshold (SPT, via a separate Stealth Vault), without revealing the details or their identity to the insurance pool. Automatic and trustless settlement.

Decentralised digital identity (MPT — multiple subtypes) A portfolio of MPTs represents a user’s digital identity: “adult ✓”, “EU citizen ✓”, “not sanctioned ✓”… Selectively presentable by context — a casino receives just “adult”, a bank receives “not sanctioned”, without ever revealing the name.

Confidential marketplace (CPT + TPT) Buyer and seller commit a price off-chain via CPT (auction contract), then prove via TPT (separate verifier contract) that the exact payment occurred. The real price is never visible on-chain — eliminates front-running on NFT or real-asset token markets.

Decentralised payroll and HR (SPT + TPT) An employer proves payroll funds are available (SPT via Stealth Vault) without revealing total treasury. Each salary is provable (TPT via separate verifier contract) without revealing other employees’ salaries. Applicable to DAOs paying anonymous contributors.

Confidential seller reputation (RTP) On a decentralised marketplace, a seller proves their reputation score without revealing their full sales history or volumes. The buyer has confidence, the seller keeps their competitive edge confidential.


BtoB

Confidential invoicing (TPT + CPT) Two companies prove that a payment corresponds to an invoice without revealing amounts or identities. The CPT timestamps the commitment to the invoice before payment, the TPT proves the payment occurred — each proof managed by its own verifier contract. Applicable to NDA contracts and tenders.

Supply chain financing (SPT + RTP) A supplier proves their solvency (SPT via Stealth Vault) and payment history (RTP via history contract) to a factor without revealing their other clients or order book. Two distinct verifier contracts, a single stealth identity.

Selective financial audit (SPT + TPT) A company proves to an auditor that its reserves exceed a regulatory threshold (SPT via Stealth Vault) and that its transactions are legitimate (TPT), without revealing exact balances. Applicable for Basel III, Solvency II, stablecoin reserves.

Sealed-bid B2B auctions (CPT) Multiple companies bid for a contract. Bids are committed on-chain via CPT and revealed simultaneously — nobody can adjust their bid based on competitors’ offers.

Confidential market data sharing (MPT) A consortium of companies shares aggregated data. Each member proves membership via MPT without revealing their identity to others or the group composition to outsiders.

Anonymous interbank lending (SPT + RTP) A bank proves its solvency (SPT via Stealth Vault) and credit score (RTP) to a counterparty for an overnight loan without revealing its full balance sheet. Reduces the risk of bank run contagion.

Pooled KYC compliance (MPT — KYC subtype) A client proves to a new institution that they have already been verified by a member of a KYC consortium, without revealing which one or the details of their verification.


7. What is needed to implement

At the Radix protocol level:
  ✅ Builds on stealth addresses and validators
     (see privacy proposal)
  ✅ No core protocol modification for the StPT
  ✅ No core protocol modification for the Stealth Vault

Two new native object types to create (new standards):
  ✨ NonFungibleResource "StPT" — new resource definition
     with its authorisation rules and data schema
  ✨ Component "StealthVault" — new Scrypto component type
     with its differentiated withdraw rules and metadata

These two objects are primitives in the Radix sense:
  reusable, standardised building blocks
  on which applications can rely.
  They do not require modifying the Radix Engine —
  they are expressed in the existing Scrypto language.

At the smart contract level:
  ✅ Verifier contracts per StPT type (Scrypto)
  ✅ Contextual nullifier contract (Scrypto)
  ✅ Specialised instances per type (Scrypto)

At the wallet level:
  ✅ Management of StPTs received on stealth addresses
  ✅ Presentation interface to the recipient
  ✅ Automatic rotation after use

Dependencies:
  ✅ Stealth address system (Tool 1)
  ✅ Superfungible tokens for SPT and TPT (Tools 2 & 3)
  ❌ No ZK-proofs
  ❌ No deep protocol modification


This document is a conceptual proposal open for discussion. Each described mechanism would require detailed technical specification and a security audit before any production implementation. Community contributions are welcome.

1 Like

This is a nice idea and i think for crypto adoption by businesses in general, we need some sort of privacy for payments and accounts.

What I don’t get from this text exactly is what kind of upgrades need to be done at network, wallet, nodes, etc. to recognize these new types. Should they be introduced also at Scrypto level?

I ask because while this is a cool feature to have I’m wondering who’s gonna update all these things and at what cost?