Spend Descriptions

Each spend contains an SpendBody and a zk-SNARK spend proof.

Invariants

The invariants that the Spend upholds are described below.

Local Invariants

  1. You must have spend authority over the note to spend

  2. You can’t spend a positioned note twice.

    2.1. Each positioned note has exactly one valid nullifier for it.

    2.2. No two spends on the ledger, even in the same transaction, can have the same nullifier.

  3. You can’t spend a note that has not been created, unless the amount of that note is 0.

  4. The spend does not reveal the amount, asset type, sender identity, or recipient identity.

    4.1 The spend data included in a transaction preserves this property.

    4.2 The integrity checks as described above are done privately.

    4.3 Spends should not be linkable.

  5. The balance contribution of the value of the note being spent is private.

Local Justification

  1. We verify the auth_sig using the randomized verification key, which must not be 0, provided on the spend body, even if the amount of the note is 0. A note’s transmission key binds the authority.

  2. The following checks prevent spending a positioned note twice:

    2.1. A note’s transmission key binds to the nullifier key in circuit as described in the Diversified Address Integrity section, and all components of a positioned note, along with this key are hashed to derive the nullifier in circuit as described below in the Nullifier Integrity section.

    2.2. This is in the ActionHandler implementation on check_stateful, and an external check about the integrity of each transaction.

  3. The circuit verifies for non-zero amounts that there is a valid Merkle authentication path to the note in the global state commitment tree.

  4. The privacy of a spend is enforced via:

    4.1 The nullifier appears in public, but the nullifier does not reveal anything about the note commitment it nullifies. The spender demonstrates knowledge of the pre-image of the hash used for nullifier derivation in zero-knowledge.

    4.2 Merkle path verification, and all other integrity checks involving private data about the note (address, amount, asset type) are done in zero-knowledge.

    4.3 A randomized verification key (provided on each spend) is used to prevent linkability of spends. The spender demonstrates in zero-knowledge that this randomized verification key was derived from the spend authorization key given a witnessed spend authorization randomizer. The spender also demonstrates in zero-knowledge that the spend authorization key is associated with the address on the note being spent.

  5. The balance contribution of the value of the note being spent is hidden via the hiding property of the balance commitment scheme. Knowledge of the opening of the balance commitment is done in zero-knowledge.

Global Justification

1.1. This action destroys the value of the note spent, and is reflected in the balance by adding the value to the transaction value balance. Value is not created due to system level invariant 1, which ensures that transactions contribute a 0 value balance. We do not create value, because of 3.

Spend zk-SNARK Statements

The spend proof demonstrates the properties enumerated below for the following private witnesses known by the prover:

  • Note amount (interpreted as an , constrained to fit in 128 bits) and asset ID
  • Note blinding factor used to blind the note commitment
  • Address associated with the note being spent, consisting of diversified basepoint , transmission key , and clue key
  • Note commitment
  • Blinding factor used to blind the balance commitment
  • Spend authorization randomizer used for generating the randomized spend authorization key
  • Spend authorization key
  • Nullifier deriving key
  • Merkle proof of inclusion for the note commitment, consisting of a position pos constrained to fit in 48 bits, and an authentication path consisting of 72 elements (3 siblings each per 24 levels)

And the corresponding public inputs:

  • Merkle anchor of the state commitment tree
  • Balance commitment to the value balance
  • Nullifier of the note to be spent
  • Randomized verification key

Note Commitment Integrity

The zk-SNARK certifies that the note commitment was derived as:

.

using the above witnessed values and where ds is a constant domain separator:

ds = from_le_bytes(BLAKE2b-512(b"penumbra.notecommit")) mod q

Balance Commitment Integrity

The zk-SNARK certifies that the public input balance commitment was derived from the witnessed values as:

where is a constant generator and is an asset-specific generator point derived in-circuit as described in Assets and Values.

Nullifier Integrity

The zk-SNARK certifies that the revealed nullifier was derived as:

using the witnessed values above and where ds is a constant domain separator:

ds = from_le_bytes(BLAKE2b-512(b"penumbra.nullifier")) mod q

as described in Nullifiers.

Diversified address Integrity

The zk-SNARK certifies that the diversified address associated with the note being spent was derived as:

where is the witnessed diversified basepoint and is the incoming viewing key computed using a rate-2 Poseidon hash from the witnessed and as:

ivk = hash_2(from_le_bytes(b"penumbra.derive.ivk"), nk, decaf377_s(ak)) mod r

as described in Viewing Keys.

Randomized verification key Integrity

The zk-SNARK certifies that the randomized verification key was derived using the witnessed and spend auth randomizer as:

where is the conventional decaf377 basepoint as described in The Decaf377 Group.

Merkle auth path verification

The zk-SNARK certifies that for non-zero values , the witnessed Merkle authentication path is a valid Merkle path to the provided public anchor. Only for notes with non-zero values , the note is unrooted from the state commitment tree to allow for these “dummy” spends to pass stateless verification. Dummy spends may be added for metadata resistance (e.g. to ensure there are two spends and two outputs in each transaction).

Diversified Base is not Identity

The zk-SNARK certifies that the diversified basepoint associated with the address on the note is not identity.

The spend authorization key is not Identity

The zk-SNARK certifies that the spend authorization key is not identity.