Skip to content
ZIPs.tools

ZIP 318

Orchard to Ironwood Migration

  • Draft
Proposal metadata
ID
318
Status
Draft
Category
Wallet
Owners
  • Schell Carl Scivally
  • Pacu Gindre
  • Kris Nuttycombe
Created
2026-06-16
License
MIT
Contents
  1. Terminology
  2. Abstract
  3. Motivation
  4. Requirements
  5. Non-requirements
  6. Specification
  7. Overview, two-phase architecture
  8. Migration entry point and user consent
  9. Phase 1, Note preparation
  10. Phase 2, Scheduled migration transactions
  11. Destination
  12. Network-layer privacy
Preamble
ZIP
318
Title
Orchard to Ironwood Migration
Status
Draft
Category
Wallet
Created
2026-06-16
License
MIT

Terminology

The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", "MAY", and "RECOMMENDED" in this document are to be interpreted as described in BCP 14 1 when, and only when, they appear in all capitals.

The terms "Orchard pool" and "Ironwood pool" are to be interpreted as described in ZIP 229 2. Following the convention in the protocol specification 3, we use slanted text to refer to pool names, in order to more clearly distinguish them from shielded protocols.

The term "network upgrade" is to be interpreted as described in ZIP 200. 4

The terms "Mainnet" and "Testnet" are to be interpreted as defined in the Zcash protocol specification. 5

The terms "trusted TXO", "untrusted TXO", "known-spendable", and "confirmed-spendable" are to be interpreted as defined in ZIP 315. 6

The terms below are to be interpreted as follows:

Migration : The process by which a wallet transfers a user's funds from the Orchard pool to the Ironwood pool.

Pool-crossing transfer : A transaction that moves value from one shielded pool to another. The net amount crossing between the pools is revealed on-chain. 7

Note preparation : A wallet-internal send-to-self transaction (or set of such transactions) whose purpose is to restructure the wallet's existing notes — dividing larger notes, combining smaller ones, or both — into notes that exactly fund the planned migration transactions, so that the entire migration schedule can be pre-signed and broadcast without waiting for change from earlier transactions to confirm.

Migration transaction (or part) : A single pool-crossing transfer that moves part of the user's Orchard-pool balance to the Ironwood pool as part of a migration. In the recommended scheme each migration transaction spends exactly one Orchard-pool note and moves exactly one denomination to a single Ironwood output.

Denomination : A canonical amount of the form n×10kn \times 10^k ZEC with n∈{1,2,5}n \in \{1, 2, 5\} (for example 100, 50, 20, 10, 5, 2, 1, 0.5 ZEC), bounded below by the maximum residual value and above by a cap specified in Amount selection, canonical quantization.

Maximum residual value : The value below which any remainder of the balance is left unmigrated, in order to prevent small, user-identifying amounts from being leaked in pool-crossing transactions.

Anchor-height bucket (boundary) : A shared, network-wide interval of block heights delimited by boundaries: blocks whose height is ≡0(modM)\equiv 0 \pmod{M} for a network-wide modulus MM (provisionally 144). The anchor height of a migration transaction is drawn at random from among past boundaries rather than derived from the wallet's own chain tip, so that the anchor does not reveal when a particular wallet last synchronized.

Cohort : The set of all migration transactions, from all wallets, that share the same boundary anchor.

Multiplicity (kk) : The number of migration transactions a single wallet contributes to one cohort.

Migration schedule : The ordered set of migration transactions, together with their scheduled broadcast heights, that a wallet plans in order to complete a migration.

Background scheduling : The use of platform mechanisms (for example, BGTaskScheduler on iOS or WorkManager on Android) to broadcast a migration transaction at an approximate future time without requiring the user to have the application in the foreground.

Abstract

This ZIP specifies best practices for wallets migrating funds from the Orchard pool to the Ironwood pool introduced by the NU6.3 network upgrade 8. It is written with light client wallets in mind, because their reliance on a light wallet server and on mobile background scheduling makes the privacy and reliability concerns most acute, but the same practices apply to desktop and full-node wallets.

Because a pool-crossing transfer reveals the migrated amount on-chain, directly sending from one pool to another can reveal the wallet balance. A naive migration risks linking transfers to a single wallet and to the user's activity, again potentially revealing balance, and also risking that migration transactions could be linked to personally identifying information such as IP addresses. To mitigate this, wallets should decompose the balance into notes with values drawn from a fixed set of denominations, which may then be sent across the turnstile as multiple transactions submitted to the chain over time using a network anonymity layer. In order to avoid linking transactions via anchor selection, proofs are made and updated against anchors drawn from shared, network-wide boundary heights, forming cohorts that mix many wallets and de-correlate transfers from when the user opens the application.

The migration runs as a two-phase process: a note-preparation phase followed by a scheduled transaction-creation phase. Migration transactions are pre-signed, persisted, and then have their proofs updated and are broadcast by best-effort background tasks, with a fallback that prompts the user on the next application open when a scheduled window is missed. Synchronization is kept decoupled in time from broadcast. This ZIP also specifies user-consent, network-privacy, progress-reporting, and error-handling requirements.

Motivation

The Ironwood pool, introduced by the NU6.3 network upgrade 8, enables verification of the Zcash shielded supply after NU6.2 mitigated a soundness flaw in the Orchard circuit 9. To that end, NU6.3 enables a rule that disables ordinary payments within the old Orchard pool while still permitting change 10; therefore, wallets are required to add functionality to migrate Orchard funds to the Ironwood pool.

Migrating funds between shielded pools is fundamentally different from spending within a single pool. Within a pool, both balances and the relationships between transactions remain private; a pool-crossing transfer, however, necessarily reveals the net amount crossing between the pools on-chain 7, so the only privacy levers available to a wallet are the shape of the amounts it migrates and the timing of their broadcast. If a wallet migrates a user's entire balance in a single transaction, that amount, its timing, and (via network-layer metadata) potentially the user's IP address are all exposed at once, and the transfer can be correlated with the wallet's other activity.

ZIP 315 6 already establishes that the user's consent is needed to reveal amounts publicly, and that wallets should minimize pool crossing. A mass migration event is a case where many users perform pool-crossing transfers in a relatively short window. This both creates an opportunity (many simultaneous migrations form an anonymity set) and a risk, because an observer who can distinguish one user's transfers from the crowd learns a great deal.

A precedent exists in ZIP 308 11, which defined a privacy-preserving procedure for the Sprout-to-Sapling migration by sending a bounded amount per period and hiding individual migration transactions among those of all migrating users. This ZIP adapts that idea to the light-client setting, where the wallet does not run a full validator, scheduling is constrained by mobile operating systems, and synchronization happens against a light wallet server whose operator is a potential observer. The security analysis of migration strategies is subtle, and the more obvious strategies leak significant information; this document records the analysis behind the chosen strategy, including several rejected alternatives (see Alternatives).

The goal of this ZIP is therefore to document how a light client wallet SHOULD perform the Orchard-to-Ironwood migration so that, by default, individual transfers are as hard as practical to correlate to a specific wallet or to the user's behaviour, while still completing the migration reliably and giving the user enough information to consent to any residual information leakage. The separate NU6.3 routing change — that new payments to Orchard receivers (inside existing unified addresses) are sent via the Ironwood pool 10 — is a general send-path concern and is out of scope, although the migration destination is the same Ironwood receiver.

Requirements

  • The user can migrate Orchard-pool funds to the Ironwood pool, and is informed that using a privacy preserving migration method is necessary for the user to be able to preserve the privacy of transaction amounts when spending Orchard funds.

  • Before any funds leave the Orchard pool, the wallet obtains the user's consent to the public revelation of pool-crossing amounts, consistent with ZIP 315. 6

  • All Orchard-pool funds, except a residual value, are eventually transferred to the Ironwood pool.

  • The migration process, by default, preserves the following privacy invariants, to the extent practical on the target platform:

    • Transfer unlinkability. An observer cannot cluster the migration transactions of a single wallet — by value, structure, anchor, expiry, or timing — into a per-wallet set.

    • Behavioural de-correlation. Broadcasts of migration transactions are de-correlated from the user's interaction with the application and from wallet synchronization, so that transfers reveal neither when the user opens the application nor when the wallet has synchronized.

    • Balance privacy. Neither any single transfer nor the observable set of transfers reveals any wallet's total Orchard-pool balance.

    • Note-distribution privacy. The migration does not reveal the distribution of individual note values held by the wallet.

    • Holdings-concentration privacy. The migration does not reveal the number of users that hold funds in the Orchard pool or how funds are distributed between those users' holdings.

    • Migration-status privacy. A chain-observing adversary who knows the values of notes a wallet has received — including an adversary who has deliberately targeted a victim by sending notes of attacker-chosen values — cannot determine whether or when the wallet has migrated those funds.

  • The user can authorize the migration in a small number of signing sessions — a single session for typical balances and note distributions. Additional sessions are needed only when multi-layer note preparation is required and the wallet does not pre-sign the layers as a chain; this affects wallets holding very many notes and wallets with very large balances identically.

  • The migration completes reliably even when best-effort background scheduling does not run, without requiring the user to keep the application in the foreground.

  • Before the migration begins, the user is given an informed choice about network-layer privacy options (Tor, VPN, or Nym).

  • The wallet reports migration progress, and does not present the fallback (prompting on the next application open) as an error.

  • The migration adapts safely when the user spends Orchard-pool funds outside the migration, when scheduled transactions expire, or when the application is reinstalled.

Non-requirements

The following are explicitly not requirements of this flow:

  • Statelessness. The migration is permitted to rely on locally persisted state (the migration schedule and pre-signed transactions). It is not required to be reconstructible from on-chain data alone. (The tradeoff against a stateless, chain-recoverable design is discussed in Rationale for the stateful design.)

  • Multi-device and recovery continuity. A migration in progress is not required to be resumable on another device, nor after restoring from seed on a new device. A wallet that detects unspent Orchard-pool funds after such a restore may treat the situation as requiring a fresh migration.

  • Guaranteed background execution. Background scheduling is best-effort. Wallets are not required to guarantee that any transfer is broadcast without the user ever opening the application.

  • Network-layer anonymity. Network-layer anonymity (for example, Tor) is offered as an opt-in but is not mandated; the user MAY proceed without it but this option should not be recommended except in cases where the user is confident in the privacy provided by the attached lightwalletd server, e.g. Tor should not be required if the user connects to their own private lightwalletd.

  • Provably leak-free migration. The procedure does not have to provably leak no information; migration transactions need only be hidden among the population of canonical-shaped Orchard→Ironwood spends (see Rationale for the canonical transaction shape), and a small residual amount is left unmigrated.

Specification

Overview, two-phase architecture

A wallet performing a privacy-preserving migration SHOULD implement it as two phases:

  1. Note preparation (see Phase 1, Note preparation): quantization of the migratable balance into canonical denominations, followed by one or more wallet-internal send-to-self transactions that restructure the Orchard-pool balance into notes that exactly fund the planned migration transactions.

  2. Scheduled migration transactions (see Phase 2, Scheduled migration transactions): pre-signed pool-crossing transfers, each transferring a canonical denomination at a scheduled broadcast height with a boundary anchor, broadcast by best-effort background tasks.

A wallet MAY offer an immediate single-transfer migration in addition to the privacy-preserving flow (see Migration entry point and user consent), but it SHOULD present the privacy trade-off of doing so.

Migration entry point and user consent

When a wallet detects a non-zero confirmed-spendable Orchard-pool balance once the NU6.3 network upgrade is scheduled or has activated, it SHOULD surface a dedicated migration entry point. (Surfacing the entry point before activation allows note preparation to begin early; see Phase 1, Note preparation.)

  • The entry point MUST display the Orchard-pool-specific balance at risk.

  • The wallet SHOULD offer the user a choice between:

    • Migrate immediately: a single pool-crossing transfer with no delay and minimal privacy; and
    • Migrate with privacy: the scheduled, quantized approach specified below.
  • Before any funds leave the Orchard pool, the wallet MUST present the full proposed migration schedule and obtain the user's confirmation. This confirmation constitutes the user's consent, required by ZIP 315 6, to the public revelation of the pool-crossing amounts.

  • Once the schedule is confirmed, individual transfers within it SHOULD be broadcast automatically when their scheduled broadcast height arrives, and SHOULD NOT require separate per-transfer confirmation.

To keep the choice tractable for users who may not know what is best, the wallet SHOULD minimize the number of privacy-tuning options exposed.

Phase 1, Note preparation

Note preparation begins with amount selection: quantization of the migratable balance into the canonical denominations that the Phase 2 migration transactions will transfer. Quantization is necessarily the first step, because the note-preparation transactions cannot be constructed without knowing the exact note values they must produce.

Amount selection, canonical quantization

The migratable Orchard-pool balance MUST be decomposed into a set of migration transactions, each transferring a single denomination. It is RECOMMENDED that the denominations be selected by canonical quantization rather than by random or arbitrary sizing. Canonical denominations collide across wallets and resist leaking information that can be used for wallet fingerprinting (see Why value collision provides privacy). A wallet MAY use a different amount-selection strategy provided it achieves the same effect, namely that migrated amounts collide across the migrating population rather than fingerprinting the wallet. Random arbitrary amounts do not achieve this and are a rejected alternative (see Alternatives).

  • Permitted denominations are the values v=n×10kv = n \times 10^k ZEC with n∈{1,2,5}n \in \{1, 2, 5\} and MAX_RESIDUAL_VALUE ≤v<\le v < DENOM_CAP, where:

    • MAX_RESIDUAL_VALUE, the smallest permitted denomination, is 0.01 ZEC; the portion of the balance smaller than this value should not be decomposed and is left unmigrated as the residual.
    • DENOM_CAP is 10000 ZEC plus the canonical fee, making 10000 ZEC the largest pool-crossing denomination; equivalently, DENOM_CAP caps the funding-note values (denomination plus fee) produced by note preparation.
  • The balance is decomposed by decimal digit expansion of the integer- and fractional-ZEC digits, each digit expanding greedily into parts drawn from {5,2,1}\{5, 2, 1\} times its place value (so a digit of 9 yields 5, 2, 2; 8 yields 5, 2, 1; 7 yields 5, 2; 6 yields 5, 1; 4 yields 2, 2; 3 yields 2, 1). Value in places above the largest denomination is decomposed into repeated maximal-denomination (10000 ZEC) parts. For example:

    123.45  ZEC -> [100, 20, 2, 1, 0.2, 0.2, 0.05]
    540     ZEC -> [500, 20, 20]
    25000   ZEC -> [10000, 10000, 5000]
    
  • The baseline quantization is a pure, deterministic function of the balance: there is no rare, high-entropy "remainder" output. Every emitted denomination is canonical and therefore collision-prone across wallets, whether the decomposition is deterministic or randomized (below). This is the key privacy property (see Privacy Implications).

  • A wallet MAY randomize the decomposition for improved balance hiding, substituting smaller denominations for the greedy choice. At each selection step the available options are the denominations n×10kn \times 10^k, for the magnitude 10k10^k of the value remaining, that do not exceed that value. Smaller denominations SHOULD be chosen with low frequency so that expected part counts stay small; provisionally: where all of {1,2,5}×10k\{1, 2, 5\} \times 10^k are available, 1×10k1 \times 10^k is chosen with 10% frequency and 2×10k2 \times 10^k with 25% frequency (5×10k5 \times 10^k otherwise); where only {1,2}×10k\{1, 2\} \times 10^k are available, 1×10k1 \times 10^k is chosen with 25% frequency. Randomization changes only which canonical denominations are emitted, never the values themselves.

  • A wallet SHOULD exclude any preexisting unspent notes that already have quantized values from the computation of balance to be migrated; this situation can arise from a migration that is resumed after a wallet restore and such notes can be used in a Migration Transaction directly.

  • The quantization leaves a deterministic residual of less than MAX_RESIDUAL_VALUE (the balance modulo the smallest denomination) unmigrated; this residual remains in the Orchard pool at the end of the migration. Notes individually smaller than MAX_RESIDUAL_VALUE are nonetheless migratable, because note preparation may combine them; whether consuming a given small note is economic is a ZIP 317 marginal-fee consideration. 12

The fee for each part is in addition to its denomination (the visible Orchard-out value of a part is its denomination plus the canonical fee; equivalently the Ironwood output equals the denomination). Each part is funded by a single note of exactly this value, produced by note preparation.

Note preparation transactions

A migration transaction spends exactly one Orchard-pool note (see Canonical migration transaction structure). The purpose of the note-preparation transactions is to ensure that a note of exactly the right value exists for every part of the schedule, so that every part can be funded independently of the others and the entire schedule can be pre-signed at once. After NU6.3, anchors are no longer committed to by signature digests and therefore migration transactions may be signed as soon as preparation transactions that construct the notes being spent have been constructed. Only the proving step requires that the funding notes have been mined and that a candidate boundary anchor exists (see Anchor-height bucketing and cohorts). Whether preparation divides larger notes into smaller ones, combines smaller notes into larger ones, or both, is purely a function of the wallet's existing note distribution, and the distinction is not visible on-chain (see Rationale for the canonical transaction shape).

  • Note preparation MUST be implemented as one or more wallet-internal send-to-self transactions with no external receiver.

  • Each note-preparation transaction SHOULD use the canonical expiry height specified for migration transactions in Canonical migration transaction structure, computed from the note-preparation transaction's scheduled broadcast height.

  • For mobile wallets, proving time is a concern. For that reason, and also for indistinguishability, Note preparation transactions SHOULD be constructed such that each preparation transaction contains exactly 16 Orchard actions, padding if necessary to reach this threshold. Because a bundle's action count is the sum of its spends and outputs (each is paired with a fabricated counterpart under NU6.3), a 16-action transaction can consume and produce at most 16 notes in total — for example, 15 spends and one output when consolidating, or one spend and 15 outputs when splitting.

  • The output notes of preparation are determined by the quantization above: one note per scheduled part, valued at exactly that part's denomination plus the canonical fee, together with at residual notes with cumulative value less than MAX_RESIDUAL_VALUE.

  • Where the number of notes involved exceeds what a single 16-action transaction can accommodate, preparation SHOULD be partitioned into multiple transactions with disjoint input notes wherever possible, so that the transactions can confirm in parallel rather than chaining through one another's outputs.

  • Partitioning with disjoint inputs is not always possible: a funding note that must combine value from more notes than one transaction can spend (consolidation), or a large note that must be divided into more funding notes than one transaction can produce (splitting), requires preparation to proceed in layers, with later preparation transactions spending the outputs of earlier ones. While all layers MAY be constructed and signed in a single session, each layer can be proved and broadcast only after the previous layer's outputs have been mined and witnessed, so each layer extends the preparation phase by mining and witness-synchronization latency — a handful of blocks, not an anchor-height bucket, since preparation transactions anchor at the wallet's ordinary near-tip depth (see below). The number of layers required is logarithmic in the number of notes consumed or produced, with base approximately 15 (the per-transaction fan-in or fan-out).

  • On-chain, layered splitting and layered consolidation are indistinguishable from each other and from parallel preparation of the same transaction count: preparation values and direction are fully shielded, so a large-balance wallet dividing a single note and a wallet consolidating many small notes present the same observable footprint (see Rationale for the canonical transaction shape).

  • A note-preparation transaction SHOULD anchor at the wallet's ordinary near-tip anchor depth (a small number of confirmations below the chain tip observed at proving time), not at a bucketed boundary height. The boundary-anchor machinery exists to protect the pool-crossing migration transactions, whose crossing values are public: their anchors must not reveal when a particular wallet synchronized. A preparation transaction is a fully shielded send-to-self — its values, direction, and linkage are hidden — so its anchor reveals only that some wallet recently synchronized, which broadcasting any transaction already reveals. Using the ordinary anchor keeps preparation proofs identical to those of routine shielded spends and lets successive layers proceed without waiting out boundary intervals.

  • The broadcasts of a wallet's preparation transactions SHOULD be temporally decoupled from one another: the delay from each preparation transaction to the next is drawn (using a CSPRNG) from an exponential distribution with mean PREP_MEAN_DELAY (16 blocks, about twenty minutes at 75-second block spacing), rounded to the nearest whole number of blocks, with any draw exceeding PREP_MAX_DELAY (96 blocks, about two hours) discarded and redrawn; a later layer's schedule begins after the previous layer's last scheduled transaction plus a small mining margin. Although preparation values are fully shielded, a burst of identically shaped padded transactions appearing at a single moment is itself a linkable cluster — by shape and timing — and such a burst would also visibly precede the wallet's scheduled transfers. The much tighter spacing relative to the transfers' MEAN_DELAY is possible precisely because no anchor bucketing constrains preparation, and keeps the preparation phase short while preventing the cluster.

  • If the wallet's existing notes already exactly fund every planned part, note preparation MAY be skipped.

  • Note preparation MAY be performed at any time after the user initiates the migration, including before the network upgrade that activates the Ironwood pool has finalized.

  • The wallet MUST wait until the boundary that closes the anchor-height bucket in which a note-preparation transaction was mined has passed before treating its output notes as available to fund the Phase 2 migration transactions. This is implied by the candidate anchor set (see Anchor-height bucketing and cohorts): no boundary at or after the notes' creation exists any earlier. Spending the notes across the turnstile sooner would require anchoring to a non-boundary tree state between the preparation transaction and the next boundary, making it possible for a lightwalletd-compromising adversary to correlate a user's synchronization behaviour (attached to a public IP address) with the anchor selected by their wallet. This constraint applies only to the pool-crossing spends: a later preparation layer may spend the notes as soon as they are mined and witnessed, per the ordinary-anchor rule above.

Phase 2, Scheduled migration transactions

Canonical migration transaction structure

Each migration transaction SHOULD have:

  • exactly one Orchard spend, with the Orchard bundle padded to exactly two actions, so that the presence or absence of an Orchard change output is not observable;
  • exactly one Ironwood output, whose value is a single canonical denomination, in a single-action Ironwood bundle with no padding action (see Rationale for the canonical transaction shape);
  • no transparent inputs or outputs;
  • no spends from any pool other than Orchard;
  • the canonical fee (provisionally the ZIP 317 minimum fee) 12;
  • the canonical anchor described in Anchor-height bucketing and cohorts and the canonical expiry height described below;
  • lock_time = 0;
  • no nonstandard fee amount or any other outputs (this would partition the anonymity set between wallets that add such outputs and those that do not).

The canonical expiry height is computed from the transaction's scheduled broadcast height: take the most recent height at or below it that EXPIRY_MODULUS (the number of blocks corresponding to 30 days, 34560 blocks at 75-second block spacing) divides without remainder, and add 2 × EXPIRY_MODULUS (69120 blocks): a rolling window that guarantees every transaction between one and two months of validity from its scheduled broadcast. Unlike the anchor, the expiry height is committed by the transaction digest 2 and is therefore fixed when the schedule is signed; because the schedule precomputes every broadcast height (see Transfer scheduling), the expiry is nonetheless known at signing time. The bucketed rule makes the committed value identical for every migration transaction — from any wallet — whose scheduled broadcast falls within the same 30-day period, so an expiry height reveals only the coarse period in which its broadcast was scheduled, information the broadcast itself substantially makes public. (Deriving the expiry from the construction height instead would reveal the otherwise unobservable period in which the wallet's schedule was created, and would deny the late parts of a long schedule their full validity window, forcing needless rebuilds.) For example, NU6.3 activates at Mainnet height 3428143, so every migration transaction scheduled for broadcast before height 3456000 has expiry height 3490560, and one scheduled between heights 3456000 and 3490559 has expiry height 3525120. Parts still unbroadcast when their expiry height is reached are rebuilt with a fresh anchor and expiry (see Error handling).

This strict, uniform structure serves two audiences. To an observer, it makes every migration transaction structurally identical both to every other migration transaction and to an ordinary manually created Orchard→Ironwood spend, and it hides whether a change output is present (see Rationale for the canonical transaction shape). To the wallet that created it, the same structure serves as a canonical migration-transaction predicate for chain-based status recovery, with disambiguation from other conforming transactions provided by viewing-key information that an observer lacks: whether the Ironwood output belongs to the wallet's own account, and whether its value is a canonical denomination.

Anchor-height bucketing and cohorts

  • The anchor height of each migration transaction MUST be a shared, network-wide boundary height, rather than a value derived from the wallet's own chain tip, so that the anchor does not reveal precisely when this wallet last synchronized.

  • Buckets are delimited by boundaries: blocks whose height is ≡0(modM)\equiv 0 \pmod{M}, with MM provisionally 144. At the current target block spacing of 75 seconds, a boundary occurs approximately every 144×75 s=3144 \times 75\,\text{s} = 3 hours. This interval concentrates migration transactions onto fewer shared anchors, enlarging per-anchor cohorts. EXPIRY_MODULUS (34560 blocks) is an exact multiple of MM (240 buckets), so expiry buckets align with anchor buckets.

  • Each migration transaction MUST take, as its Orchard anchor, the tree state as of a boundary drawn from the candidate anchor set: those boundaries that are above the NU6.3 activation height, at or after the height at which the transaction's funding note was created, and at or before the most recent boundary the wallet has observed at proving time. An anchor therefore reveals only that its creator had scanned beyond that boundary at some time before broadcast, and sharing it does not link a wallet's transactions to one another (see Rationale for anchor selection).

  • The draw MUST be recency-weighted: the anchor's age a≥1a \geq 1, measured in boundaries before the most recent boundary the wallet has observed at proving time, is drawn (using a CSPRNG) from a geometric distribution with parameter 1/2 — so the most recent boundary is never used, the most probable age is one boundary, and the mean age is two boundaries (about six hours). A draw exceeding ANCHOR_AGE_CAP (provisionally 4 boundaries, about twelve hours) or falling outside the candidate set MUST be discarded and redrawn; equivalently, the distribution is truncated to the candidate set.

  • The set of all migration transactions sharing a boundary anchor forms a cohort. A wallet MAY contribute several migration transactions to the same cohort (multiplicity k≥1k \geq 1), because all denominations are canonical and therefore not attributable to a single wallet by their values (see On multiplicity and cohorts).

Transfer scheduling

The schedule is constructed in block deltas: starting from the height at which the schedule is committed (lower-bounded so that every part can anchor; see below), the wallet assigns each part a scheduled broadcast height by advancing a running height by an independently drawn delay per part, so that a wallet's broadcasts approximate a Poisson process.

  • The wallet MUST first shuffle the quantized parts into a uniformly random order, so that the temporal sequence of denominations a wallet emits is not a predictable function of its balance (for example, a largest-first ordering would let an observer infer migration progress from any part it could attribute, and would make the sequence predictable to a targeted adversary who knows the balance).

  • The delay to each successive migration transaction MUST be drawn from an exponential distribution with rate λ=1/\lambda = 1 / MEAN_DELAY, so that the expected delay is MEAN_DELAY (provisionally 66 blocks, about 82 minutes at 75-second block spacing), rounded to a whole number of blocks; any draw exceeding MAX_DELAY (provisionally 576 blocks, about twelve hours) MUST be discarded and redrawn.

  • The schedule MUST place every migration transaction at a scheduled height whose candidate anchor set (see Anchor-height bucketing and cohorts) is non-empty, so that no transaction can ever lack a valid boundary to anchor to and no fallback anchor-selection rule is needed. Concretely, the running height from which the delays accumulate MUST start no earlier than one full bucket interval past the lowest candidate boundary — the first boundary strictly above the NU6.3 activation height and at or after the estimated creation height of the funding notes (the last scheduled note-preparation transaction plus a small mining margin). Lower-bounding the starting height, rather than clamping individual transactions, preserves the drawn inter-arrival gaps and hence the schedule's Poisson character.

  • All randomness used in scheduling — the shuffle, the delay draws, and the anchor-age draws — and in the randomized decomposition of Amount selection, canonical quantization MUST be generated by a cryptographically secure random number generator.

  • The wallet MUST propose the complete schedule to the user before any transfer is sent, obtaining confirmation of the whole schedule (see Migration entry point and user consent).

  • Each migration transaction takes a canonical anchor drawn from the recency-weighted distribution over the candidate anchor set (see Anchor-height bucketing and cohorts). Because the version 6 transaction format commits the anchor as authorizing data rather than in the signature hash 2, the wallet can attach or update a pre-signed transaction's anchor and proof without re-signing.

  • Whenever the application is granted background processing time, the wallet SHOULD synchronize and construct the proofs of upcoming scheduled transactions, drawing each transaction's anchor from the candidate anchor set as observed at proving time, but MUST NOT broadcast a migration transaction within the same background processing window in which a synchronization is performed (see Decoupling synchronization from broadcast).

  • Spreading a wallet's transfers over time with memoryless inter-transfer delays, and drawing each transfer's anchor independently, are the primary means by which the wallet's own transfers are kept from being linked to one another; distinct per-wallet anchor heights are not required, because a shared boundary anchor carries no per-wallet information.

Pre-signed transaction storage

  • Once the schedule is committed, migration transactions SHOULD be pre-signed and persisted, reusing the wallet's existing transaction-resubmission storage mechanism where one exists.

  • Under the version 6 transaction format, the anchor is committed as authorizing data rather than by the signature hash 2, so a pre-signed transaction's anchor and proof can be updated at (or near) broadcast time without re-signing. This is what allows the entire schedule to be signed in a single session while each transaction carries a boundary anchor drawn from the shared candidate set (see Rationale for anchor selection).

  • If a stored transaction becomes invalid (for example, because its input notes were spent outside the migration, or it expired), the wallet MUST detect this and prompt the user to re-initiate the affected step (see Error handling).

Background scheduling

  • Background scheduling MUST be treated as best-effort. The operating system chooses the exact execution time within the requested window.

  • A single background processing window MUST be used either to synchronize (updating the anchors and proofs of upcoming transactions) or to broadcast, never both (see Decoupling synchronization from broadcast).

  • If a scheduled window is missed, the wallet MAY fall back to prompting the user on the next application open (see Fallback on application open).

Platform-specific guidance is given in Platform considerations.

Decoupling synchronization from broadcast

A background session is defined as a period of time wherein the wallet is performing computation and network interaction decoupled from any user interaction with the wallet interface. While a background session and user interaction with the wallet interface may coincide, the wallet MUST NOT permit the user's behavior to influence the execution of the background operations.

  • The wallet MUST NOT perform a wallet synchronization in the same background session as a migration broadcast, because doing so would let an observer correlate the synchronization (which may leak wallet-identifying data) with the broadcast.

  • Where a synchronization is needed, it MUST be separated in time from any broadcast. In the recommended flow migration transactions produce no Orchard-pool change, so the required synchronizations are the one that witnesses the notes produced by note preparation before the first scheduled send, and the routine background synchronizations that allow the proofs of upcoming transactions to be constructed (see Transfer scheduling). A migration transaction that produces change in the Orchard pool (for example, one rebuilt during error recovery) requires the wallet to synchronize before that change can be spent; the wallet MUST schedule that synchronization decoupled in time from the broadcast of the next migration transaction.

How a wallet determines when a synchronization is needed is implementation-defined.

Fallback on application open

  • On every application launch, the wallet MUST reconcile the scheduled broadcast times against the transfers actually completed, and MUST surface any overdue transfers. This on-launch reconciliation is the primary catch-up mechanism and MUST NOT rely on notification delivery.

  • When the user is prompted to send overdue transfers, the wallet SHOULD disclose that sending them at application-open time correlates the broadcasts with the wallet's sync activity, weakening the privacy of those transfers.

  • The wallet MUST NOT send more than one overdue transfer at wallet open. While this may delay the migration of user funds, the alternative (sending multiple transactions with pool-crossing value within the same session) leaks balance.

  • When a window is missed and the remaining transfers are rescheduled, the wallet SHOULD shift the remaining schedule by the offset, or redraw the delays of the remaining transfers.

  • A slip of up to approximately two hours in which the background task eventually runs SHOULD be treated as normal operation and SHOULD NOT be surfaced as an error.

Destination

  • The destination of a migration MUST be the user's internal change address in the Ironwood pool. Migration to the Sapling pool MUST NOT be offered or recommended as part of this flow.

Network-layer privacy

Before the schedule is committed, the wallet MUST present a network-privacy step.

Citation graph

Hover or tap a node to see its title and citations.
Loading citation graph…
ZIP 318: Orchard to Ironwood Migration · ZIPs.tools