This section states the compact block as an abstract message format: the records of a block and of a transaction, the compact outputs, spends and Actions and the fields they omit, the compact variant of trial decryption with the soundness of accepting a plaintext that no tag authenticates, and the placement of notes in the note commitment trees from per-block tree sizes. The service that delivers compact blocks is the subject of “The light-client service” (§5).
A compact block carries only the data of a block that a wallet needs to detect payments to its addresses, to detect spends of its notes and to maintain the witnesses of its notes (ZIP 307, “Compact Stream Format”); for the transparent pool it carries, on request, the data needed to detect spends of the wallet’s transparent coins.
ZIP 307, “Compact Stream Format”, “Output Compression” and “Spend Compression”, specifies the compact format for the Sapling pool only: a compact block of height, block hash and transactions, and a compact transaction of index, transaction identifier, spends and outputs. It names neither the Orchard pool nor the Ironwood pool, nor per-block tree sizes, nor transparent data. ZIP 318 and ZIP 326 address light wallets and specify no compact format. The remainder of the format below (the parent hash of a block, the tree sizes, the compact Actions of both Orchard-protocol pools, the transparent part and pool selection) is designed but unspecified (Definition 1.1). The volume states the format as an abstract message format, not as a serialisation, and states no field number, field width or encoded size. The status of each ZIP cited is that of Table 1.
A compact block of height is a tuple
where
is the block height;
and are the -byte hashes of the block and of its parent block (protocol specification, §“Block Header Encoding and Consensus”);
is either the encoded block header or empty; the abstract format does not guarantee that it is present;
is the sequence of compact transactions (Definition 4.3) of the block, in block order;
gives, for each shielded pool , the number of leaves of that pool’s note commitment tree after every transaction of the block has been appended, written .
Each is an integer in , where is the leaf capacity of a tree of depth (Ironwood Guide, §“The Merkle hash and the tree”, Definition “Note commitment tree”; protocol specification, §“Constants”). The width of any serialisation of lies outside the abstract format.
A compact transaction is a tuple
where
is the index of the transaction in its block;
is the -byte transaction identifier in protocol byte order, the form in which it is computed, not the byte-reversed form used for display (Ironwood Guide, §“Transaction digests and signatures”, Definition “Transaction identifier”; protocol specification, §“Transaction Identifiers”);
is an optional transparent part : is the sequence of outpoints spent by the transaction’s transparent inputs, in input order, and the sequence of pairs of its transparent outputs, in output order, with in zatoshi.
The coinbase transaction of a block is its first transaction and the one whose single transparent input has a null previous outpoint (protocol specification, §“Coinbase Transactions”); it spends no outpoint, its is empty, and it is recognised by . No fee field is part of the abstract format.
Let . The compact block restricted to is obtained from a compact block by keeping, in each compact transaction, only the components of the pools in ( and for Sapling, the sequence for an Orchard-protocol pool, and only when ), and by omitting every compact transaction left with no component. The tuple is kept whole, and a compact block is returned for every block of a requested range, possibly with empty . The default is . The range query of “The query interface” (§5.2) takes as an argument. Pool selection is designed but unspecified (Definition 1.1); ZIP 307 includes by default only the transactions that have Sapling spends or outputs (ZIP 307, “Block header validation”).
For every shielded pool in the restriction keeps every commitment of that pool in its order, since an omitted compact transaction has no component of the pool. The per-pool counts and offsets of Definition 4.11 are therefore the same on a restricted block as on the unrestricted one.
Let be the note ciphertext of a Sapling output or of an Action: bytes, the encryption of the -byte note plaintext followed by the -byte tag. Its split at the offsets and is that of the Ironwood Guide, §“Transaction digests and signatures”, Definition “Transaction identifier”.
A compact Sapling spend is the -byte nullifier of a Spend description.
A compact Sapling output is the triple , a payload of bytes.
A compact Action, of the Orchard pool and of the Ironwood pool alike, is the tuple , a payload of bytes.
Parts (a) and (b) are specified (ZIP 307, “Output Compression” and “Spend Compression”); part (c) is designed but unspecified (Definition 1.1). The fields are those of the protocol specification, §“Spend Description Encoding and Consensus”, §“Output Description Encoding and Consensus” and §“Action Description Encoding and Consensus”. Only payload sizes are stated; the size of any serialisation lies outside the abstract format.
The nullifier of a compact Action has two roles. It detects a spend of the note that the Action consumes, and it is the element of the note that the Action creates (Ironwood Guide, §“Nullifier chaining”, Construction “Chaining rule”), an input of , and and hence of the commitment that acceptance recomputes (Definition 4.9). A compact Action without therefore cannot be accepted.
A compact block omits the memo , the tag , the outgoing ciphertext , value commitments, randomised validating keys, anchors, proofs and signatures (ZIP 307, “Output Compression”, “Spend Compression” and “Transaction privacy”). Recovery of a memo or of an outgoing plaintext requires the full transaction, fetched by its identifier (“Leakage of transaction queries”, §8.4).
Let be a compact block of height , and let a wallet hold incoming viewing keys and the nullifiers of its notes.
Receipt detection, that is compact decryption and acceptance of an output (§4.3), is a function of the key, of , and of the record of a Sapling output or of an Action.
Spend detection is a function of the fields of , and .
Note placement is a function of the order of the commitments in and of (§4.4).
No field omitted by the compact block enters (i) to (iii).
(i) Trial decryption and acceptance read the ephemeral key, the ciphertext prefix that encrypts the lead byte, diversifier, value and note seed, the commitment, the height through the admissible lead bytes, and, for an Action, as (Ironwood Guide, §“Trial decryption and note acceptance”, Constructions “Trial decryption” and “Acceptance of an Ironwood-pool output”; ZIP 307, “Scanning for relevant transactions” for Sapling); the memo and the tag enter only the full decryption. (ii) A spend of a note is detected by membership of its nullifier among the published ones (ZIP 307, “Detecting spends”). (iii) The chain appends each pool’s commitments in block, transaction and description order to the least unused leaf (Ironwood Guide, §“The Merkle hash and the tree”, Definition “Note commitment tree”; protocol specification, §“Note Commitment Trees”), so positions follow from that order and a tree size. □
The omitted fields serve the verification of the chain, which the client delegates to the server; that delegation and its assumption are stated in “Architecture and authority” (§5.1).
Trial decryption and acceptance of full outputs are those of the Ironwood Guide, §“Trial decryption and note acceptance” (Constructions “Trial decryption” and “Acceptance of an Ironwood-pool output”), cited and not re-derived. This subsection states the compact variant.
The compact note plaintext is the tuple , encoded as
of bytes: the note plaintext of the Ironwood Guide, §“The note plaintext”, Definition “Note plaintext”, without its memo (protocol specification, §“Note Plaintexts and Memo Fields” and §“Encodings of Note Plaintexts and Memo Fields”). The AEAD encryption is a stream-cipher encryption followed by a tag, so is the encryption of exactly these bytes, which are the contents and the opening of the note commitment (ZIP 307, “Output Compression”).
Input: an incoming viewing key of the pool’s protocol and a compact output or compact Action with fields and .
Compute on the pool’s curve, on Jubjub for Sapling and on Pallas for either Orchard-protocol pool; return if .
Compute with the key agreement and key derivation of the pool’s protocol.
Compute , where is the first bytes of the ChaCha20 keystream under key and the all-zero nonce of the protocol specification, §“Symmetric Encryption”, starting at block counter , the counter from which ChaCha20-Poly1305 encrypts (block yields the Poly1305 key; Crypto Guide, §“The ChaCha20-Poly1305 AEAD”, Construction “ChaCha20-Poly1305”; RFC 8439, §2.8); equivalently, bytes to of the keystream from counter .
Return parsed as a compact note plaintext (Definition 4.7).
The tag is never checked. The result is a candidate, not an accepted note (ZIP 307, “Scanning for relevant transactions”).
Let be the candidate returned by Construction 4.8 under for an output of pool in a compact block of height . Let be the Canopy activation height and blocks (protocol specification, §“Constants”). The set of admissible lead bytes is
(protocol specification, §“Note Plaintexts and Memo Fields”), so that an Orchard-pool note has lead byte and an Ironwood-pool note . The wallet accepts if and only if every check passes:
; for Sapling, moreover, and , with read as an integer for lead byte ;
with , and with of the same Action for either Orchard-protocol pool, the note commitment recomputed from , where and are derived from as the pool and the lead byte prescribe ( and absent for Sapling), is not and extracts to the record’s (Sapling) or (either Orchard-protocol pool);
for every lead byte other than , the field equals the encoding of , with re-derived from , and from for either Orchard-protocol pool.
The accepted note is without memo, with and absent for a Sapling note. The derivations of , and are cited and not restated: for Sapling and the Orchard pool to the protocol specification, §“Decryption using an Incoming Viewing Key (Sapling and Orchard)” (ZIP 212, “Changes to the process of sending Sapling or Orchard notes”); for the Ironwood pool to the Ironwood Guide, §“Trial decryption and note acceptance”, Construction “Acceptance of an Ironwood-pool output”, whose checks (i), (ii) with (iv), and (iii) are checks (i), (ii) and (iii) here (ZIP 2005, “Changes to the Protocol Specification”). The method of comparison is not part of the rule.
Check (iii) is a step of the specification’s decryption procedure and of ZIP 307, not an addition (ZIP 212, “Changes to the process of receiving Sapling or Orchard notes”). For an Ironwood-pool note it is made directly after the computation of , in the order of ZIP 2005. Without it a sender could agree the key with one address of a recipient while naming the diversifier of another, and link the two addresses by observing acceptance (Ironwood Guide, §“Trial decryption and note acceptance”, Remark “Role of check (iii)”; ZIP 212, “Motivation”). A Sapling note with lead byte , created under the rules before ZIP 212, skips check (iii), since its is not derivable from .
For a note the commitment input is the pair of committed values and trapdoor from which check (ii) computes its commitment: for Sapling and for either Orchard-protocol pool. An address of is a pair with .
Let be the commitment, or , that a compact output or compact Action carries.
Every note accepted by Definition 4.9 is an opening of . For every efficient sender, which chooses , and the keys under which they are formed, the probability that the wallet accepts while the sender outputs a note whose commitment input differs from that of and whose commitment extracts to is negligible, under the binding of the pool’s note commitment scheme. The tag of the AEAD gives no integrity against the sender, who holds , so its omission loses none.
For an output honestly formed for a note whose address is not an address of , the probability that accepts a candidate is negligible under the same assumption.
Whether is the commitment of an output of the best chain is not a property of decryption; it is settled under the assumption of “Architecture and authority” (§5.1).
(a) Check (ii) recomputes the commitment of deterministically from its commitment input and compares it with , whatever the ciphertext and whichever key decrypted it, so opens . Consider the algorithm that generates the wallet’s key, runs the sender and the compact decryption and acceptance, and outputs the commitment inputs of and . When the event of (a) occurs it outputs two distinct commitment inputs whose commitments extract to the same . For either Orchard-protocol pool this is excluded, except with negligible probability, by the argument of the Ironwood Guide, §“Trial decryption and note acceptance”, Proposition “Consistency of accepted notes”, part (c), under Proposition “Hiding and binding of note commitments” (§“Note commitments”). That proof uses neither the integrity of ChaCha20-Poly1305 nor key commitment, so it applies unchanged to a candidate decrypted from the -byte prefix; and binding holds for every , hence also for the trapdoor derivation of the Orchard pool. For Sapling the named assumption is the computational binding of , the security requirement of the protocol specification, §“Windowed Pedersen commitments”, together with the injectivity of on (protocol specification, §“Coordinate Extractor for Jubjub”).
(b) Let be accepted. By check (ii) its address is with , an address of . Suppose the commitment inputs of and were equal. Then the diversified base of the address of equals , and , so is an address of , contrary to the hypothesis. The commitment inputs therefore differ, and the honest sender outputs , whose commitment extracts to ; the honest sender is an efficient sender of (a), which bounds the probability. □
For each shielded pool, every note commitment of a block, not only those of the wallet’s notes, is appended to the wallet’s copy of that pool’s note commitment tree in block order, transaction order and description order: of each Action of the pool and of each Sapling output (ZIP 307, “Creating and updating note witnesses”; Ironwood Guide, §“The Merkle hash and the tree”, Definition “Note commitment tree”; protocol specification, §“Note Commitment Trees”). The leaf of each accepted note is marked for witness retention. The part of the tree a wallet must retain is fixed in “Commitment-tree synchronisation” (§7).
Let be a shielded pool, a block height with compact block , and the number of commitments of in . The start size of is
the wallet knowing when it holds the compact block of height or a tree state of at the end of ; in the third case the value is taken from alone, and the block is rejected if it is negative. For the -th output of , counted from , of a compact transaction of ,
where is the number of commitments of in the compact transactions of before . Positions are per pool. A block scanned out of order thus places its notes from its own compact block. Note positions are designed but unspecified (Definition 1.1).
For a pool outside the pool set of the query that returned , the count is not served, and neither position nor check is defined.
The position of a note is the leaf index of its commitment (Ironwood Guide, §“The Merkle hash and the tree”, Definition “Note commitment tree”, item 1). Every spend needs it for the authentication path. A Sapling nullifier depends on it, through (protocol specification, §“Computing values and Nullifiers”), while the nullifier of an Orchard-protocol note does not.
Let the wallet reject a block unless, for each shielded pool of the pool set of the query that returned ,
If every reported size is the true size, no block is rejected, and every position of Definition 4.11 is the leaf index of the commitment in the pool’s tree.
A reported that is inconsistent with the block’s own commitment count, or with the known end size of , is rejected.
A block with and reported size is rejected. A size read as zero therefore yields a position only where is consistent with the block, and the check needs no means of telling an absent size from zero.
A size that is false but consistent with both conditions is not detected; its exclusion is clause (a) of the server assumption of “Architecture and authority” (§5.1).
(a) The chain appends the commitments of a pool in block, transaction and description order, each to the least unused index (Ironwood Guide, §“The Merkle hash and the tree”, Definition “Note commitment tree”). The true start size of is thus the true end size of , which equals , so both conditions hold in every case of the start size; and the -th commitment of lands at index . (b) A size fails the first condition. With a known start size, a size that differs from fails the second. (c) A size with fails the first condition. (d) Let the wallet not know the end size of , and let lie at or above the activation of , so that its start size is that of the third case of Definition 4.11. Adding one integer to and to the end sizes of all later scanned blocks, such that every shifted size stays in and at least the count of its block, preserves both conditions for , whose start size is computed from its own end size, and for every later block, whose start and end sizes shift by together. □
Comparison of the running position with identifies the last commitment of in , at position . The tree after that commitment, or for the tree at the end of , is the tree state at the end of . Its root is the anchor that a later spend against height uses (Ironwood Guide, §“Anchors”; protocol specification, §“Transactions and Treestates”), and the wallet records it as a candidate anchor.