# Orchard to Ironwood Migration

Orchard and Ironwood are tracked as separate value pools. An
Orchard-to-Ironwood transaction publishes two value balances: the amount
leaving Orchard and the amount entering Ironwood. The notes, receivers and
ownership remain shielded, but the amount moved between pools is public.

Moving an entire Orchard balance at once would reveal that balance. ZIP 318
instead divides it into common denominations and sends them over time. Every
migration amount is public, but using the same amounts and timing as other
wallets makes the transactions harder to group into one balance.

## Consensus context

ZIP 258 makes the old Orchard pool withdrawal-only at NU6.3:

- `valueBalanceOrchard` must be nonnegative, so value can leave Orchard but
  cannot enter it.
- Every Orchard Action has `enableCrossAddress = 0`, so its output expanded
  receiver must equal the expanded receiver of its spend.

These rules apply to V5 and V6 transactions. When a wallet spends a note worth
more than it needs, it returns the remainder to itself in a change note.
`enableOutputs = 0` would prohibit both payments and those change notes.
`enableCrossAddress = 0` instead permits an output back to the spent note's
expanded receiver while rejecting an Orchard output to another receiver.

Sources:
https://github.com/zcash/zips/blob/main/zips/zip-0258.md and
https://github.com/zcash/orchard/pull/504.

## Why amounts leak

An Orchard-style bundle publishes spends minus outputs. For a migration part
that moves `X` ZEC and pays fee `F` from Orchard, the public values are:

- `valueBalanceOrchard = +(X + F)`
- `valueBalanceIronwood = -X`
- fee `= F`

`X` is the canonical migration amount and `F` is the transaction fee. Both are
public. The proof binds hidden Actions to these values. Nodes use them to account
for each pool and enforce its turnstile. The wallet can vary only its migration
amounts and broadcast times.

Source: https://github.com/zcash/zips/blob/main/zips/zip-0229.md.

## Draft wallet strategy

ZIP 318 defines the two-phase wallet flow now being implemented. This page
tracks commit `4d46580`:
https://github.com/zcash/zips/commit/4d46580aa2e82997323da72629a3a38d84d9400d.

The current design has two phases.

First, an Orchard send-to-self transaction creates notes that can fund later
migration parts independently. This prevents each transaction from waiting for
change from the previous one. The split must confirm before its outputs can be
spent. A wallet can skip it when its existing notes already fit the schedule.
The split heuristic, denomination cap, dust floor, fee accounting and practical
Action limits are still being finalized.

Second, the wallet constructs one Orchard-to-Ironwood transaction per canonical
power-of-ten denomination. Each transaction has one Ironwood output, no
transparent or other shielded-pool component, a canonical fee and expiry, and
an Orchard anchor from a network-wide height bucket. Orchard outflow is the
denomination plus fee; the Ironwood output is the denomination.

The wallet saves and pre-authorizes the schedule. Best-effort background work
broadcasts the parts later, separately from synchronization. A missed
background window resumes on the next application open. Before anything leaves
Orchard, the wallet shows the complete schedule, obtains consent to the public
amounts under ZIP 315, and offers direct submission or a private network path
such as Tor or a VPN. A one-transaction migration is possible but less private.

Sources: https://github.com/zcash/zips/pull/1317 and
https://zips.z.cash/zip-0315.

## Privacy argument

A random-looking amount is likely to be unique on chain. Several unique parts
can also be searched for a sum that reconstructs a migrated balance. Powers of
ten work differently: if many wallets follow the rule, transactions collide by
value and the amount alone does not identify a wallet.

Timing can undo that ambiguity. ZIP 318 assigns each part to a future
anchor-height bucket and separates broadcasts from wallet synchronization and
application opens. The operating system chooses the exact execution time within
the requested window. Every wallet broadcasting in one bucket uses the previous
boundary as its Orchard anchor, so the anchor does not reveal an individual
wallet's synchronization height.

This is camouflage, not an anonymity proof. Amounts and block times remain
public. Small cohorts, known balances, large holdings, repeated denominations,
distinctive wallet behavior and network metadata can still link transactions.
The design leaves the denomination cap, bucket size and per-wallet multiplicity
open because those parameters depend on adoption and observed traffic.

## Restricted bundle construction

`enableCrossAddress` is bit 2 of the bundle flags. `1` permits an ordinary
cross-address transfer; `0` requires the spend and output in an Action to use
the same expanded receiver. The circuit exposes the opposite-polarity public
input as `disableCrossAddress`.

With the restriction active, the Orchard builder constructs complete pairs:

- Each real spend receives a fabricated zero-value output at the spent note's
  expanded receiver.
- Each change output receives a fabricated wallet-controlled zero-value spend
  at the change receiver.
- An Orchard output to another receiver fails construction.

The fabricated output paired with a real spend uses random `enc_ciphertext`
bytes. A normal ciphertext would let a holder of the incoming viewing key
decrypt an output in the same Action that publishes the spend nullifier, linking
the two. The concern also covers a future adversary that recovers the incoming
viewing key before the nullifier key.

Sources: https://github.com/zcash/orchard/pull/504 and
https://github.com/zcash/zips/blob/main/zips/zip-0326.md.

## PCZT and hardware-wallet support

Version 6 moves Sapling, Orchard and Ironwood anchors out of effecting data and
into authorizing data. Re-anchoring no longer changes the transaction ID. A
wallet can collect spending authorization before attaching the final witness,
anchor and proof.

The supporting `librustzcash` work includes:

- anchor updates: https://github.com/zcash/librustzcash/pull/2574
- witness updates: https://github.com/zcash/librustzcash/pull/2576
- batch-signing messages: https://github.com/zcash/librustzcash/pull/2602
- preverified signer path: https://github.com/zcash/librustzcash/pull/2535

Keystone reviews the PCZT batch atomically, displays one aggregate summary,
reuses verified state and returns signatures instead of full PCZTs. Its
ten-note development benchmark fell from roughly 15 minutes to 2.5 minutes end
to end. This is a firmware benchmark, not a protocol performance claim.

Sources: https://github.com/zcash/zips/blob/main/zips/zip-0229.md,
https://github.com/KeystoneHQ/keystone3-firmware/pull/2198 and
https://github.com/KeystoneHQ/keystone3-firmware/pull/2208.

Ironwood notes also carry the material required by a future recovery protocol
if the current discrete-log-based protocols have to be suspended. Orchard notes
do not. Source: https://zips.z.cash/zip-2005.

## Specification status

ZIPs 258 and 229 define the deployed consensus rules. ZIP 318 defines the wallet
procedure now being implemented. Its split algorithm, `DENOM_CAP`,
`DUST_FLOOR`, anchor-bucket modulus, expiry policy and multiplicity limits are
still being finalized. ZIP 2006 is currently a reserved stub, so the detailed
cross-address behavior is documented in ZIPs 229 and 258 and in the Orchard
implementation.

The full source catalog is at https://zakura.com/ironwood/resources/ (markdown:
https://zakura.com/ironwood/resources.md).

---

Canonical HTML version: https://zakura.com/ironwood/migration/
