Shielded Transfers
A shielded transfer sends tokens privately from one address to another within the Nullmask privacy pool. The recipient must have a registered receiving key.
Transaction Nullifiers
Definition 6: Transaction Nullifier
For a transaction tx and nullifying key nk from account account:
nftx:=Poseidon2T4(nk,tx.nonce⋅232+tx.chainId,pk_hash)
The chain ID and nonce are compacted into a single field element, requiring only one Poseidon2T4 invocation.
Why Transaction Nullifiers?
Nullmask's design separates the signing authority (wallet) from the note selection (proxy). The wallet signs an intent ("send 1 ETH to Alice"), and the proxy chooses which notes fund the transaction.
This creates a replay risk: a malicious proxy could resubmit the same signed transaction with different funding notes. Transaction nullifiers prevent this — the contract stores all transaction nullifiers and rejects duplicates.
Comparison with Other Protocols
Nullmask's authorization model differs fundamentally from Zcash and Railgun:
Railgun and Zcash: The host selects notes that fund a shielded transaction; the wallet then signs the full shielded transaction data, which includes note nullifiers. The wallet has direct knowledge of which notes are being spent.
Nullmask: The wallet signs a standard transaction expressing an intent (e.g., "send 1 ETH to Alice"); the proxy then selects notes to fund the shielded transaction. The wallet has no knowledge of notes or nullifiers.
This separation introduces a fundamental problem: since the proxy controls note selection, a malicious proxy could replay the same signed intent with different funding notes. Transaction nullifiers solve this — each unique (chainId, address, nonce) triple can only be used once, and the contract rejects duplicates.
Circuit Verification Checklist
The shielded transfer circuit verifies all of the following:
1
Transaction Nullifier
Prevents replay attacks
2
Commitments of all funding notes
Proves note existence
3
Merkle tree paths of all funding notes
Proves notes are in the tree
4
Nullifiers of all funding notes
Enables double-spend prevention
5
Balance equation (input ≥ output + fee)
Prevents value creation
6
RLP deserialization of the virtual transaction
Parses the signed transaction
7
ECDSA signature of the virtual transaction
Proves user authorization
8
Sender matches shielded action sender
Links signature to action
9
Recipient matches shielded action recipient
Prevents recipient substitution
10
Gas fee matches the transaction
Prevents fee manipulation
11
Change note correctness
Ensures correct change
12
Recipient key in Key Registry (Merkle proof)
Verifies recipient registration
13
Output note encryption
Prevents unspendable notes
Public Inputs (45 fields)
The shielded transfer circuit produces 45 public output fields:
Output Notes
A shielded transfer produces 3 new notes:
Output note — For the recipient, containing the transferred value
Change note — For the sender, containing leftover action-asset value
Fee change note — For the sender, containing leftover fee-asset value
If the action asset and fee asset are the same token, one of the change notes may have zero value.
Last updated