Unshield circuit
The Unshield circuit proves note ownership and membership while binding the public amount, asset and recipient.
The production Unshield circuit has 7,147 constraints and 10 public field inputs. It shares the note, owner commitment, nullifier and Merkle conventions with Private Swap, but proves a withdrawal to an explicit recipient.
Public input order
| Index | Value |
|---|---|
| 0 | Unshield protocol domain 0x5a4b43504d4d0003 |
| 1–2 | Pool public key high and low limbs |
| 3–4 | Asset mint high and low limbs |
| 5 | Accepted Merkle root |
| 6 | Nullifier |
| 7 | Note amount |
| 8–9 | Recipient public key high and low limbs |
The instruction also carries the root sequence and tree generation. Core checks these against the selected TreeState, then verifies that the serialized public-input bytes match the values derived from the instruction and recipient account.
Witness and constraints
The private witness is the spend secret, note randomness and 16-sibling Merkle path with its leaf index. The circuit derives the owner commitment, note commitment, nullifier and membership root. It constrains amount to an unsigned 64-bit value and binds the recipient as public input.
After proof verification, Core checks the canonical unused nullifier PDA and recipient token accounts, then transfers the exact note amount from shielded custody. The event publishes the recipient and amount. This circuit does not hide either field.
See Unshield for the Solana account flow and Groth16 for verification details.