JoinSplit Circuit

Details of JoinSplit circuit, including PIs, encodings, and constraints (in english)

High-Level Statement

Prove that all of the following are true:

  1. both input notes exist in the commitment tree

  2. the user owns both input notes

  3. all four notes are for the same asset

  4. the total value of the input notes equals the total value of the output notes plus the amount being unwrapped (the "public spend")

  5. the owner of those assets could produce a valid signature over the hash of an associated operation.

Public Inputs

The JoinSplit circuit has a total of 13 public inputs:

  1. operationDigest: The hash of the operation the JoinSplit is associated with. The hash is computed outside the circuit using keccak256 and is reduced modulo pp to an element of Fp\mathbb{F}_p.

  2. encodedAssetId: The the encodedAssetId field of the encoded asset being spent

  3. encodedAssetAddrWithSignBits: The encodedAssetAddr field of the encoded asset being spent, but with the sign bits corresponding to refundAddrH1CompressedY and refundAddrH2CompressedY packed-in.

  4. refundAddrH1CompressedY: The Y-coordinate of the compressed encoding of the first component of the refund address in the associated operation

  5. refundAddrH2CompressedY: The Y-coordinate of the compressed encoding of the second component of the refund address in the associated operation

  6. newNoteACommitment: The note commitment for the first output note

  7. newNoteBCommitment: The note commitment for the second output note

  8. commitmentTreeRoot: The current commitment tree root

  9. publicSpend: The amount to unwrap publicly

  10. nullifierA: The nullifier for the first input note

  11. nullifierB: The nullifier for the second input note

  12. senderCommitment: A blinded commitment to the sender of the operation. This allows the recipient to know the canonical address of whoever is paying them.

  13. joinSplitInfoCommitment: A blinded commitment to the details of the JoinSplit (sender, recipient, notes being spent, etc.) enabling individuals to selectively disclose transaction details if they want to.

Private Data

Constraints

  • vk and vkNonce correctly correspond to spendPk

  • senderCanonAddr is indeed the canonical address corresponding to vk

  • the signature (c, z) is a valid signature of opDigest

  • oldNoteA.owner and oldNoteB.owner are well-formed stealth addresses

  • oldNoteA.owner and oldNoteB.owner are both owned by vk

  • the refund address provided via refundAddrH1CompressedY, refundAddrH2CompressedY, and their associated sign bits from encodedAssetAddrWithSignBits is a valid stealth address owned by vk

  • MembershipProofA.leaf is the note commitment for oldNoteA

  • MembershipProofB.leaf is the note commitment for oldNoteB, or oldNoteB.value = 0 (we don't care about oldNoteB if its value is 0)

  • MembershipProofA is a valid Merkle membership proof against commitmentTreeRoot

  • MembershipProofB is a valid Merkle membership proof against commitmentTreeRoot, or oldNoteB.value = 0 (we don't care about oldNoteB if its value is 0)

  • newNoteA.owner is the sender's canonical stealth address

  • newNoteB.owner is the receiver's canonical stealth address

  • oldNoteA.value + oldNoteB.value = newNoteA.value + newNoteB.value + publicSpend

  • newNoteACommitment is the correct note commitment for newNoteA

  • newNoteBCommitment is the note commitment for newNoteB

  • senderCommitment is computed correctly

  • joinSplitInfoCommitment is computed correctly

Last updated