This section states the tree information that a wallet retains in order to spend its notes. It shows that the witness maintenance of ZIP 307 forces a scan from each note to its anchor; decomposes each note commitment tree at level into subtrees and a cap built from downloaded subtree roots; shows that a frontier seeds every later witness; defines the information a wallet retains and proves it sufficient; states exactly when a witness is computable; and states the detection of reorganisations and the recovery from them, with the bound on the rollback height, the safety theorem and the correctness theorem of synchronisation.
Throughout, ranges over the shielded pools , and , with the chain state of Definition 6.1, the birthday of Definition 6.2, and the commitment count and end size of a compact block (Definition 4.11). Assumption 5.2 is the server assumption; only its clause (a) is used here.
A detected note is not yet spendable. A spend needs, besides the note, its position and the authentication path of to the anchor of a block at or after the note’s block (Ironwood Guide, §“Authentication paths”, Construction “Authentication path”; anchors as in §“Anchors”, Definition “Treestate and anchor”). By the Ironwood Guide’s Lemma “Authentication paths from public data” (§“Authentication paths”), that path is a function of and of the first leaves of the pool’s tree, being the tree size at the anchor. Path construction and anchor selection are cited, not re-derived; the anchor height is fixed in “Anchors, confirmations, and expiry” (§9). The lemma is stated for the trees of the Orchard protocol; its proof uses only the recurrence of the tree and applies unchanged to the Sapling tree, which has the same depth and the same layer convention (protocol specification, §“Note Commitment Trees” and §“Merkle Path Validity”). Everything below applies to each pool separately.
An incremental witness of a note at position , after leaves have been appended to the pool’s tree, is the information from which the authentication path of in the tree of size is computed: the position , the siblings of the path whose ranges lie below , and the frontier of the leaves appended after (ZIP 307, “Local processing”, “Creating and updating note witnesses”; Crypto Guide, §“Append-only and incrementally updatable trees”, Definition “Frontier”).
ZIP 307, “Local processing”, “Creating and updating note witnesses”, states the protocol for the Sapling pool and its commitments ; it applies to each pool with that pool’s commitments, for Actions. Compact blocks are processed in increasing height, with the order of transactions and outputs preserved. The wallet holds its copy of the pool’s tree as a frontier and one incremental witness per tracked note. For each note commitment of the block, in order:
append to the tree;
append to every held witness;
if the output of is accepted by Definition 4.9, create a witness of it from the current tree.
A witness updated through block yields the authentication path of its note to the anchor of block . No ZIP specifies any other tree-maintenance protocol.
Under linear witness maintenance, let a note be created in block and let . The wallet holds the authentication path of the note to the anchor of block only after it has processed, in order, every note commitment of the pool in every block from through . It creates the note’s witness only after it holds the tree state at the end of block , obtained either by processing every earlier block or from a chain state (Definition 6.1). In particular, a wallet restored from a seed spends no note created at before it has scanned forward from to the anchor.
By induction on the processed commitments. Steps (i) and (ii) are the only operations on the tree and the witnesses, and each consumes the next commitment in chain order; step (iii) creates a witness from the current tree, which after the commitment of the note is the tree state at the end of block followed by the commitments of up to that of the note. A witness therefore reflects block only after every commitment through has passed through step (ii), and it yields no path to the anchor of before it reflects block . □
The method of “Subtree roots and the cap” (§7.2) to “Witness readiness” (§7.5) removes the constraint of Lemma 7.3. It replaces per-note witnesses by subtree roots, obtained through the query (Definition 5.10), and a frontier, so that the path of a note needs the commitments of its own subtree only. The method is designed but unspecified (Definition 1.1): no ZIP specifies it or the subtree-root query.
Fix a pool and its note commitment tree of depth , with nodes in layer counted from the root (Ironwood Guide, §“The Merkle hash and the tree”, Definition “Note commitment tree”; protocol specification, §“Merkle Path Validity”). Let be its Merkle hash, for Sapling and for either Orchard-protocol pool, and its unused-leaf value, or (protocol specification, §“Constants”). For and , the node at level and index is
the root over the positions ; its range is that interval. The nodes satisfy the first line below, and the second defines the values :
for . Each is the root over a range of unused leaves (Ironwood Guide, §“Authentication paths”, Lemma “Authentication paths from public data”, for Orchard-protocol trees; the same recurrence for Sapling). Subtree is the node with its range, and its completeness, root and completing height are those of Definition 5.8. There are subtrees, with indices to , each over positions. The subtree of a position is . The cap is the tree formed by the nodes with ; its leaves are the level- nodes, and its root is the root of the tree. The same geometry holds for the Sapling, Orchard-pool and Ironwood-pool trees.
For a pool and a list of level- values, the cap over is the append-only Merkle tree of depth (Crypto Guide, §“Append-only and incrementally updatable trees”, Definition “Append-only Merkle tree”) whose cap-level- labels are the , whose empty-leaf value is , and whose combination of two cap-level- labels into a cap-level- label is
the tree’s Merkle hash at level , that is, in layer . Complete subtree roots obtained from enter at cap positions in index order.
Let the tree of hold leaves, and for each let of that tree: the complete root when ; the root over the appended leaves of subtree padded with when ; and when . Then the cap-level- node of index of the cap over equals for . In particular the root of the cap equals , the anchor of the pool for that tree (Ironwood Guide, §“Anchors”, Definition “Treestate and anchor”).
Induction on . For the claim is the definition of . For the step, the cap combines the cap-level- nodes of indices and with ; by the induction hypothesis they are and , and the recurrence of the tree gives , in the same layer . The value for an unused subtree follows from the leaf rule, by which unused positions hold (Ironwood Guide, §“The Merkle hash and the tree”, Definition “Note commitment tree”, item “Leaves”), and from the induction in the proof of the Ironwood Guide’s Lemma “Authentication paths from public data” (§“Authentication paths”). The empty labels of the cap, , are then by the same induction, so the cap’s labels of empty ranges agree with the tree’s. □
Let the tree hold leaves, let and , and let be the authentication path of (Ironwood Guide, §“Authentication paths”, Construction “Authentication path”), with .
For , the range of lies inside subtree , and is a function of the leaves of subtree below ; it is if its range starts at or beyond .
For , is the cap node of cap level and index , a function of the level- nodes with in its range and . These are complete subtree roots; the root over the incomplete subtree when is not a multiple of , a function of the frontier of the tree after its -th leaf; and .
Hence the leaves of subtree , the roots of the complete subtrees other than and the frontier of the tree of size suffice for the path, and the wallet needs the commitments of no subtree other than .
The range of is , and is a function of the leaves in its range (Ironwood Guide, §“Authentication paths”, Lemma “Authentication paths from public data”, whose proof shows this for every node). For the range lies inside , since and have the same quotient by , which is . For the range is a union of whole subtree ranges, and it excludes because and ; Lemma 7.7 computes from the level- nodes of its range. The root of the incomplete subtree is the fold, with the values as right siblings, of the carries below level of the frontier of the tree of size , one for each set bit of (Crypto Guide, §“Append-only and incrementally updatable trees”, Proposition “Incremental append in logarithmic time”, proof). □
At each synchronisation the wallet queries for each pool (Table 4) and records, for each complete subtree , the pair (root, completing height) of Definition 5.8; the roots enter the cap at index (Construction 7.6). The roots are trusted under clause (a) of Assumption 5.2: no root is checked against a header, and a root is verified only if the wallet also computes it from scanned commitments (Proposition 5.3, item (iv)). The acquisition is designed but unspecified (Definition 1.1).
Let be the frontier of the tree of pool after block (Crypto Guide, §“Append-only and incrementally updatable trees”, Definition “Frontier”), holding leaves, with carries for the set bits of , and let be the note commitments of in blocks in chain order. From and these commitments alone the wallet computes
the root of the tree after every block , and
for every position appended by a block at most , the authentication path of to that root.
The commitments at positions below are not needed. Consequently the chain state stored with the birthday of an account (Definitions 6.1 and 6.2) seeds every later witness of the account.
(i) Repeated application of the Crypto Guide’s Proposition “Incremental append in logarithmic time” (§“Append-only and incrementally updatable trees”), each append producing the next frontier and root.
(ii) By the Ironwood Guide’s Lemma “Authentication paths from public data” (§“Authentication paths”), a right sibling of () has a range above , hence over later leaves or unused positions, and is computed from the with values. A left sibling () has the range . If the range starts at or above , it is computed from later leaves. If it lies below , then and give , which is odd since ; so bit of is set and the range is the block of the frontier at level , whose root is the carry . If the range contains , its part below is the union of the frontier’s blocks at the set bits of below , since the range is aligned at level ; its root is the fold of those carries with the later leaves of the range. □
A batch of consecutive blocks , of heights increasing by one, is seeded with the chain state of the block preceding (Definition 6.1), with frontiers of sizes . Before any retained information is modified, the wallet accepts the batch only if continues the seed in the sense of Definition 6.10: , , and for each pool (Definition 4.2, Lemma 4.12); each later block is checked against its predecessor in the same way. A violation is a continuity error (Definition 6.10), handled in “Reorganisation detection and recovery” (§7.6). Under clause (a) of Assumption 5.2, the root of each seed frontier equals the anchor of block in ; nothing else checks it, since the abstract format does not guarantee a header (Proposition 5.3). The per-block sizes are designed but unspecified (Definition 4.2, Remark 4.1).
The retained tree information of a wallet is adjoined to its note state (Definition 6.7). It comprises a finite set of heights, the retained block boundaries, chosen by the wallet and the same for every pool, which contains , and for each pool :
for each unspent note of the wallet in , its position and its leaf, and each sibling with of the path of (Lemma 7.8(i)) from the moment its range lies wholly below the tree size; such a node is a function of appended leaves and does not change thereafter (Ironwood Guide, §“Authentication paths”, Lemma “Authentication paths from public data”, items (i) and (ii) and proof);
the complete subtree roots with their completing heights (Definition 5.8), and the frontier of the tree after the last scanned block;
for each , the chain state , whose frontiers are the tree states after block : the anchors of the blocks in are the wallet’s candidate anchors, and the heights in are its rollback points.
The rollback window is the span of . Because is common to the pools, a rollback restores all trees to one block. Any other node may be discarded once no retained path needs it. An anchor older than the window is retained only by explicit choice: ZIP 318, “Anchor-height bucketing and cohorts”, requires the anchor of each migration transaction to be the tree state at a shared network-wide boundary height, so a wallet that follows it retains those boundaries; any other retention of old anchors is wallet policy. The definition fixes information, not a representation, and is designed but unspecified (Definition 1.1).
Fix a pool .
Let be the position of a retained note, , and a retained block boundary with tree size . If the blocks that hold the commitments of subtree below and at or above the birthday seed are scanned, the authentication path of to the anchor of is computable from the retained information.
For every height at which the wallet holds a chain state for all pools, with the size of the tree of after , discard every retained node over a range that meets , every note position at or above , every subtree root with completing height above and every with , and take the frontier of as the frontier after the last scanned block. The result is a function of the blocks at heights at most , and it is information that a wallet which scanned only those blocks retains.
(i) By Lemma 7.8, each sibling is of one of the following sorts. A sibling whose range lies below is the same node at every later tree state: for it is in item (a), or, where its range lies below the birthday seed, it is a carry of the seed frontier (Lemma 7.10); for it is a cap node over complete subtree roots of item (b) (Lemma 7.7). The sibling ranges are pairwise disjoint, so at most one contains without lying below . That sibling is the root over its range, whose part below is the union of the blocks of the frontier of at the set bits of below its level; it is the fold of those carries with values, and the frontier of is in item (c). A sibling whose range starts at or beyond is .
(ii) After the discards, every retained node lies over a range below and is a function of the leaves appended through block (Ironwood Guide, §“Authentication paths”, Lemma “Authentication paths from public data”); every retained subtree root has completing height at most , and is likewise such a function; the retained chain states are those at heights at most ; and the frontier after is that of , which the wallet holds for every pool at the same . A wallet that scanned only the blocks at most can hold each of these items, and item (a) is satisfied, since a sibling whose range is not below is not yet due. □
Let be a retained block boundary with tree size in pool , let be a position, , and let be the authentication path of to the anchor of . If , the Ironwood Guide’s Construction “Authentication path” (§“Authentication paths”) defines no path, and by its Proposition “Membership soundness” (§“Anchors”), item (iii), no valid path to that anchor with position exists, except with negligible probability, for the Orchard-protocol pools; for Sapling, by the same argument under the collision resistance of that the protocol specification requires of (§“ Hash Function”), since is not in the range of (§“Windowed Pedersen commitments”). Otherwise the path is computable from the wallet’s information if every is of one of the following kinds:
, and is computable from the commitments of subtree below that the wallet has scanned or holds summarised in a carry, whose range lies below , of a seed frontier (Lemma 7.10) or in the frontier of ;
, and is a complete subtree root that the wallet holds;
, and is a cap node computed from held complete roots, carries at levels at least of the frontier of or, with range below , of a seed frontier, and, where its range meets the incomplete subtree, the root over that subtree’s leaves below , computed from the frontier of ;
the range of starts at or beyond , and ;
, and is a carry of the frontier of or a carry, whose range lies below , of a seed frontier.
Kinds (a) to (d) are the sorts of sibling in the proof of Proposition 7.13(i), extended in kind (c) by frontier carries, and a sibling of kind (e) is a retained node. □
Let , so , and let the anchor’s tree hold leaves, so that subtrees to are complete and subtree is incomplete. The siblings are of kind (a); , the root of subtree , is of kind (b); , over subtrees and , and , over subtrees to , which meets the incomplete subtree, are of kind (c); and , whose ranges start at or beyond, are of kind (d).
For pool and subtree , let be the completing height of subtree (Definition 5.8), and let be the activation height of . The block extent of subtree is the interval of heights , both ends included, the part below being summarised by the chain state (Lemma 7.10); for the incomplete last subtree the interval ends at the anchor height. After detecting a note at position , the wallet scans the extent of subtree beyond the ranges it has already scanned. The incomplete subtree of every pool is covered by the range from to the tip, where is the least, over the pools, of the completing height of the pool’s last complete subtree, or of the pool’s activation height if it has none.
The start of an extent is inclusive because the completing block of subtree may also hold the first commitments of subtree ; the positions within that block are fixed by Lemma 4.12.
Let a note of pool lie at position , , and let the anchor block , of height , have tree size and complete subtrees. The witness of at is computable if
the blocks of subtree are scanned from the start of its extent (Definition 7.16) up to , or through its completing height if ;
the wallet holds the root of every complete subtree with , including those after ; and
the frontier of is retained, which scanning the extent of subtree through yields when is not a multiple of .
Condition (2) can be weakened through frontier carries: every complete subtree lies under a sibling of the path of , and the root of subtree is not needed when its range lies inside a carry, at a level at least and at most that of the sibling, of the frontier of or, provided the carry’s range lies below , of a seed frontier. Note eligibility, anchor choice and confirmation depth are separate conditions (“Spendable notes”, §9.5).
Each condition supplies one kind of Theorem 7.14: condition (1) kind (a); condition (2) kind (b) and the complete part of kind (c); condition (3) the incomplete part of kind (c). Kind (d) needs nothing. For condition (3), the carries of the frontier at levels are cap nodes over complete roots, and those below level are functions of the leaves of subtree below , appended in its extent. For the last claim, the ranges of partition the subtree indices other than ; if the range of subtree lies inside such a carry, which is the same node at , its range lying below , the sibling over it is that carry, of kind (e), or a cap node computed from it, of kind (c), without the root of subtree . □
Under the hypotheses of Lemma 6.13, a schedule of ranges that covers in any order yields, for every note and every retained anchor, the witness of a scan in increasing height from , provided a note enters a witness only once the extent of its subtree (Definition 7.16) is scanned up to the anchor and the conditions of Proposition 7.17 hold.
By the Ironwood Guide’s Lemma “Authentication paths from public data” (§“Authentication paths”), the path is a function of the position and of the leaves below , which do not depend on the scan order. Positions are local to their blocks by Lemma 4.12, and the detection of the note is order-independent by Lemma 6.13. Once the stated extents are scanned, Theorem 7.14 makes the path computable. □
A restored wallet seeds each tree from the chain state (Lemma 7.10), holds one root per complete subtree (Construction 7.6), and scans for witnesses only the extents of the subtrees of its notes and the tip range, instead of replaying the tree from the pool’s first block. By Proposition 7.17, the witness of a found note is ready once those ranges are scanned. The trial decryption of every block from onward (Proposition 6.17) remains, and so does the scanning of the extents.
A reorganisation (Ironwood Guide, §“Anchors”, Definition “Reorganisation”) makes three kinds of wallet information wrong: the transactions of the wallet mined in replaced blocks become unmined; the anchors of replaced blocks vanish; and tree information over positions appended in replaced blocks no longer describes the chain.
Each synchronisation after the first requests blocks from its previously synchronised height inclusive and checks that the hash of the received block equals the stored one; a mismatch implies that block was orphaned by a reorganisation (ZIP 307, “Client-server interaction”, phases B and D). This volume extends the check to every block and to both sides of every range boundary (Definition 6.10). Failure of the continuity predicate is a continuity error and triggers recovery (Construction 7.24). A malformed field, or a tree size that is absent, outside or below the block’s own commitment count (Lemma 4.12(b)), is an error of the response and triggers none. The extension beyond ZIP 307’s comparison is designed but unspecified (Definition 1.1).
Rollback to a height at which the wallet holds a chain state consists of the following changes.
The chain state of the wallet becomes , and each pool’s retained tree information becomes that of Proposition 7.13(ii) for .
Every transaction mined above is marked unmined. The spend marks that such transactions set, on shielded notes and on transparent outputs, are cleared, and the nullifier of each note so unmarked returns to the tracked set of its pool.
Scan results above are discarded: the unlinked nullifiers of revealed above , and the scanned ranges above , so that the scanned heights of Definition 6.11 are at most . A note whose creating transaction is now unmined loses its position and, for Sapling, its nullifier, which depends on the position; both are derived again if a later scan detects the note.
The knowledge of rule (R4) of Definition 6.4 is cut back as that rule states; the evidence of rule (R2) stands.
Local-only data is kept: sent and received notes stay recorded, since the memos and transactions that the wallet created may be unrecoverable from the chain, while a note whose transaction is unmined is excluded from balances and from spendability (“Spendable notes”, §9.5).
Let be an offset, a wallet parameter. On a continuity error at height , that is, when a block of height fails Definition 6.10 against the wallet’s chain state , the wallet runs the following steps.
If , it obtains , replaces its stored chain state at by , rolls back to (Definition 7.23), and goes to step (4).
Otherwise let be the greatest height with that is a retained block boundary () or at which the wallet has recorded the hash of its scanned block. The height qualifies, since .
If , the wallet rolls back to . Otherwise it obtains (Definition 6.1), trusted under clause (a) of Assumption 5.2. If the hash of equals the recorded hash, the wallet takes the frontiers of as its tree states after , discards every retained node over a position at or above their sizes, and rolls back to . If the hashes differ, its block is off the server’s chain, and it repeats step (1) with .
It restarts synchronisation from the query .
A fetched chain state extends the depth to which the wallet recovers beyond its rollback window, but only at a height whose hash the wallet has recorded: without that comparison, a fetched chain state cannot show that the wallet’s blocks at most lie on the server’s chain, and results from replaced blocks below would survive. The construction is designed but unspecified (Definition 1.1).
Assume clause (a) of Assumption 5.2, let the server’s best chain be unchanged during recovery, and exclude collisions of the block hash. Let the wallet’s scanned heights below form the interval , as in a scan in increasing height. The wallet’s block at a height is the block it scanned at , or for the block of its stored . The fork point is the greatest at which the wallet’s block is the server’s block at , and if there is none. Agreement at a height implies agreement at every lower height of : the wallet’s blocks are linked by the checks of Definition 6.10, and each header contains the hash of its parent (protocol specification, §“Block Header Encoding and Consensus”).
A continuity error at implies .
Repeated recovery by Construction 7.24 strictly decreases the rollback height until , or until step (1) replaces the stored chain state at ; after either, no continuity error recurs.
No offset below guarantees progress: a rollback to keeps the orphaned block, and the next scan fails again at .
(i) Under clause (a) the server’s block has the requested height, so the failing clause of Definition 6.10 is (ii) or (iii). The server’s block has as parent its chain’s block , and its sizes are functions of that chain’s prefix (Lemma 4.12(a)). If the wallet’s block were the server’s block , its hash and its sizes, which the wallet computed from the same prefix, would satisfy both clauses. So the chains disagree at , and .
(ii) Consider one recovery, with rollback height . If is a retained boundary and , the wallet’s block is off the server’s chain, so the server’s block , whose is the hash of the server’s block , fails continuity at , and the next rollback height is at most . If is a recorded height and the hashes differ, step (3) repeats with and the next height is at most . If the hashes agree, by the definition of the fork point. Heights are bounded below by , and a rollback height that would lie below it is replaced by step (1). Once , the wallet’s block is on the server’s chain, and every later block of that chain continues its predecessor. After step (1) the wallet’s chain state at is the server’s and every result above it is discarded, so the same holds.
(iii) After a rollback to the wallet’s block is unchanged, and by (i) it is off the server’s chain; the server’s block fails against it again. □
Under the hypotheses of Proposition 7.25, recovery by Construction 7.24 ends at a height such that every block of the wallet at most is a block of the server’s chain: either a retained boundary or a recorded height , the latter with the chain state , or with the chain state . Scanning the server’s chain from then yields the note state and the retained tree information of a scan of that chain from the birthday, with local-only data kept.
Proposition 7.25 gives the end height and its property. After the rollback, the retained information is a function of the blocks at most (Proposition 7.13(ii), Definition 7.23), and those blocks are shared by both chains; where a fetched chain state is used, its frontiers are those of the server’s chain under clause (a). Theorem 6.14 and Lemma 7.10 then apply to the server’s chain from , seeded with . □
Assume clause (a) of Assumption 5.2 and exclude collisions of the block hash. Let the server’s best chain be unchanged from some time on, the final chain, and let be the height of a tip of the final chain that the wallet obtains after that time. Let the wallet
check continuity before applying the results of a range (Definition 6.10), on both sides of every range boundary;
retain unlinked nullifiers as Lemma 6.12 requires;
take positions from consistent sizes (Lemma 4.12);
recover from every continuity error by Construction 7.24, scanning a height again only after a rollback below it;
enter a note into a witness only once the extent of its subtree is scanned up to the anchor (Definition 7.16);
scan the range that contains after obtaining , with continuity checked at its lower boundary (Definition 6.10), and discard scan results above ; and
hold, as its complete subtree roots, those returned by a query made after obtaining , restricted to completing height at most .
If, after its last rollback, its scanned ranges cover , in any order, the wallet holds the note state and the retained tree information of a scan of the final chain in increasing height from .
The theorem composes earlier results and adds no mechanism. By (6) the range that contains was requested after the tip query that returned , so under clause (a) the wallet’s block is that of the final chain. By (1), each block of was checked against the wallet’s chain state of its predecessor, and by (4) no height below it was scanned again afterwards without a rollback that also discarded the block; so the wallet’s blocks of are linked by , and by the hash chain of the headers each of them is the final chain’s block at its height. By (4) a height is scanned again only after a rollback below it, which discards the earlier result at that height (Definition 7.23 (iii)), so every kept result of is that of the wallet’s current block; by (6) no result above is kept. The scan of is therefore one of the final chain without a continuity error. By (7) and clause (a), the retained subtree roots are those of the final chain with completing height at most . Lemma 6.13 gives the note state of the scan in increasing height, Corollary 7.19 the witnesses, and Theorem 6.14 characterises the notes found. □
Consensus bounds no reorganisation depth, and node rollback windows are local policy (Consensus Guide, §“Reorg rails, maturity, and the finality floor”). ZIP 307, “Local processing”, advises caching tree and witness state for recent blocks, on the ground that no full node rolls back the chain by more than blocks. That ground no longer holds: ZIP 218, “Block-count-based constants”, recommends a node rollback limit of blocks at its -second target spacing and keeps coinbase maturity at blocks, and neither figure bounds the window of a wallet. The depth that a wallet repairs from its retained information is the span of its retained block boundaries, a wallet parameter; a chain state fetched by at a height whose hash the wallet has recorded extends it under clause (a) of Assumption 5.2 (Construction 7.24).