# JoinSplit Circuit

### 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](https://nocturne-xyz.gitbook.io/nocturne/protocol-concepts/operations).

### Public Inputs

The JoinSplit circuit has a total of 13 public inputs:

1. `operationDigest`: The hash of the [operation](https://nocturne-xyz.gitbook.io/nocturne/protocol-concepts/operations) the JoinSplit is associated with. The hash is computed outside the circuit using `keccak256` and is reduced modulo $$p$$ to an element of $$\mathbb{F}\_p$$.
2. `encodedAssetId`: The the [`encodedAssetId`](#asset-encoding) field of the encoded asset being spent
3. `encodedAssetAddrWithSignBits`: The [`encodedAssetAddr`](#asset-encoding) 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](https://nocturne-xyz.gitbook.io/nocturne/encodings#compressed-point-encoding) of the first component of the refund address in the associated operation
5. `refundAddrH2CompressedY`: The Y-coordinate of the [compressed encoding](https://nocturne-xyz.gitbook.io/nocturne/encodings#compressed-point-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](https://nocturne-xyz.gitbook.io/nocturne/protocol-concepts/notes-commitment-tree-nullifiers-and-joinsplits)
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

* `vk`: the [viewing key](https://nocturne-xyz.gitbook.io/nocturne/keys-and-key-derivation#key-derivation)
* `vkNonce`: the [nonce used in viewing key derivation](https://nocturne-xyz.gitbook.io/nocturne/keys-and-key-derivation#key-derivation)
* `spendPK`: the [spending public key](https://nocturne-xyz.gitbook.io/nocturne/keys-and-key-derivation#key-derivation)
* `(c, z)`: a [Schnorr signature](https://nocturne-xyz.gitbook.io/nocturne/keys-and-key-derivation#signatures) of `opDigest`
* `oldNoteA`: an [`EncodedNote`](https://nocturne-xyz.gitbook.io/nocturne/encodings#note-encoding) representing the first input note
* `oldNoteB`: an [`EncodedNote`](https://nocturne-xyz.gitbook.io/nocturne/encodings#note-encoding) representing the second input note
* `newNoteA`: an [`EncodedNote`](https://nocturne-xyz.gitbook.io/nocturne/encodings#note-encoding) representing the first output note
* `newNoteB`: an [`EncodedNote`](https://nocturne-xyz.gitbook.io/nocturne/encodings#note-encoding) representing the second output note
* `MembershipProofA`: a Merkle membership proof for `oldNoteA`'s [note commitment](https://nocturne-xyz.gitbook.io/nocturne/protocol-concepts/notes-commitment-tree-nullifiers-and-joinsplits) in the commitment tree
* `MembershipProofB`: a Merkle membership proof for `oldNoteB`'s [note commitment](https://nocturne-xyz.gitbook.io/nocturne/protocol-concepts/notes-commitment-tree-nullifiers-and-joinsplits#notes) in the commitment tree
* `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`
* `oldNoteA.owner` and `oldNoteB.owner` are well-formed [stealth addresses](https://nocturne-xyz.gitbook.io/nocturne/keys-and-key-derivation#addresses)
* `oldNoteA.owner` and `oldNoteB.owner` are both [owned](https://nocturne-xyz.gitbook.io/nocturne/protocol-details/stealth-addresses) by `vk`
* the refund address provided via `refundAddrH1CompressedY`, `refundAddrH2CompressedY`, and their associated sign bits from `encodedAssetAddrWithSignBits` is a valid [stealth address](https://nocturne-xyz.gitbook.io/nocturne/protocol-details/stealth-addresses) 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](https://nocturne-xyz.gitbook.io/nocturne/keys-and-key-derivation#addresses)
* `newNoteB.owner` is the receiver's [canonical stealth address](https://nocturne-xyz.gitbook.io/nocturne/keys-and-key-derivation#addresses)
* `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
