Nocturne
  • Introduction
    • Introduction
    • Protocol Overview
    • Compliance
  • Protocol Concepts
    • Keys and Stealth Addresses
    • Notes, Commitment Tree, Nullifiers, and JoinSplits
    • Deposits
    • Operations
  • Protocol Details
    • Algebraic Primitives & Notation
    • Keys & Key Derivation
    • Stealth Addresses
    • Signatures
    • Encodings
    • Commitment Tree
      • Subtree Update Circuit
    • JoinSplit Circuit
    • Note Encryption
    • Contracts
      • Deposit Manager
      • Teller
      • Handler
      • ETH Adapters
      • Canonical Address Registry
    • Offchain Actors
      • Deposit Screener
      • Bundler
      • Subtree Updater
  • Users
    • MetaMask Snap
    • FAQ
  • Developers
    • Contract Addresses
    • Trusted Setup
    • Security
    • Guardrails
    • Source Code
Powered by GitBook
On this page
  • High-Level Statement
  • Public Inputs
  • Private Data
  • Constraints
  1. Protocol Details

JoinSplit Circuit

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

PreviousSubtree Update CircuitNextNote Encryption

Last updated 1 year ago

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 .

Public Inputs

The JoinSplit circuit has a total of 13 public inputs:

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

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

  3. encodedAssetAddrWithSignBits: The 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 of the first component of the refund address in the associated operation

  5. refundAddrH2CompressedY: The Y-coordinate of the 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

  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

  • receiverCanonAddr: the canonical address of the receiver

  • senderCanonAddr: the canonical address of the receiver

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

  • 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)

  • 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

vk: the

vkNonce: the

spendPK: the

(c, z): a of opDigest

oldNoteA: an representing the first input note

oldNoteB: an representing the second input note

newNoteA: an representing the first output note

newNoteB: an representing the second output note

MembershipProofA: a Merkle membership proof for oldNoteA's in the commitment tree

MembershipProofB: a Merkle membership proof for oldNoteB's in the commitment tree

oldNoteA.owner and oldNoteB.owner are well-formed

oldNoteA.owner and oldNoteB.owner are both by vk

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

newNoteA.owner is the sender's

newNoteB.owner is the receiver's

note commitment
owned
stealth address
operation
operation
commitment tree root
encodedAssetId
encodedAssetAddr
viewing key
nonce used in viewing key derivation
spending public key
Schnorr signature
stealth addresses
canonical stealth address
canonical stealth address
note commitment
compressed encoding
compressed encoding
EncodedNote
EncodedNote
EncodedNote
EncodedNote