Safer Ironwood migration IP from Nozywallet

Hello everyone,

We’ve been focused on Ironwood migration, and for Nozy the bar is a “safer” migration not just a working one. This note is how we’re practicing that against ZIP 318.

Status today: CLI Ironwood migrate path is testnet-validated (v2.4.0). Safer-migration Priority 1 (local-node default + broadcast gate; Nym/Tor as Advanced attestation) is in CLI and desktop status. Priorities 2–3 are partially wired (ZIP 318 buckets/denoms + cover warnings); cross-user cohort health and the {1,2,5} alignment are next.

This is a short product/engineering note from NozyWallet on how we are thinking about practicing an safe Orchard - Ironwood migration at the stage we are at now.

What we already agree with in ZIP 318

We are building against the wallet migration draft in ZIP 318 PR #1317 (Orchard to Ironwood migration).

That draft is doing the hard on-chain privacy work:

  • note splitting into canonical denominations

  • scheduled / bucketed migration transactions (cohorts, shared anchors)

  • sync decoupled from broadcast

  • explicit user consent

  • and — importantly — a required network-privacy step before the schedule is committed (Tor toggle, VPN fallback, IP-correlation disclaimer)

We treat that as the right shape for migration. A one-shot “move everything now” path is not good enough for a privacy-first wallet.

On Nozy’s side, the CLI Ironwood path (scan, split, turnstile schedule/prebuild, Ironwood send) is already testnet-validated in v2.4.0. Desktop/API migration UX is still being wired. So we are past “can we migrate at all?” and into “can we migrate safely in the sense users actually care about?”

For us, safer migration has three priorities after the ZIP 318 mechanism itself:

  1. Protect the broadcasting IP (Nym / Tor / local node)

  2. Coordinate users so migration cover traffic is shared (real cohorts, not lonely turnstiles)

  3. Get the amounts and timing selection algorithm right (Zooko-style / ZIP 318 amount–timing research, as in our coordination-migration writeup)

Priority 1 — IP / network metadata (Nym / Tor / local node)

ZIP 318 correctly notes a residual leak: Without network-level privacy, the server or network operator that receives a broadcast can correlate the broadcasting IP address with the on-chain pool-crossing event.

Canonical amounts and shared timing buckets reduce on-chain fingerprinting. They do not by themselves stop:

  • ISP / local network observers seeing wallet egress

  • a lightwalletd or submit endpoint logging IP ↔ migration broadcast

  • timing joins between “this IP synced / opened the wallet” and “this cohort got a turnstile”

If we only ship beautiful turnstiles over clearnet, we have improved the chain graph and still left a track for attackers who watch the wire the nozy people.

At this stage we are not proposing to replace ZIP 318. We are proposing to take its network-privacy step seriously in product and stand of our name Nozy wallet.

  1. Prefer a local Zebrad for desktop when possible

    Strongest default for Nozy’s architecture: wallet → local JSON-RPC, not a public light server, for sensitive migration traffic.

  2. Offer / require private egress for migration broadcast

    Align with ZIP 318’s Tor opt-in — and treat Nym (e.g. NymVPN / mixnet) and Tor as first-class ways to protect the broadcasting IP.
    Practical v1 for us: guidance + a hard warn / gate before migrate-broadcast unless local node is healthy or the user attests they are on Nym/Tor (we are still deciding detection vs attestation).

  3. Do not default “skip network privacy”

    ZIP 318 says no network-privacy option may be pre-selected. We agree. For high-risk flows we may go further than “MAY proceed without” and make clearnet an explicit, discouraged exception.

  4. Keep claims honest

    Nym/Tor reduce IP↔session linkage; they do not erase KYC history, subset-sum on revealed migration amounts, or a compromised device. Orchard/Ironwood hide note plaintexts; mixnets hide who talked to the network.

Priority 2 — Shared migration cover traffic across users

ZIP 318’s privacy story for pool-crossing amounts is value collision + cohorts: many wallets emit the same canonical denominations into the same anchor-height buckets, so one user’s turnstile is hidden among others.

That only works if other people are actually there.

A perfectly scheduled, Nym-routed migration that lands alone in an empty bucket is still a lonely fingerprint. So our second priority is making cover traffic real:

  • Implement ZIP 318 bucketing faithfully so Nozy users land in the same network-wide cohorts as other ZIP 318 wallets (shared boundaries, canonical denoms, bounded multiplicity).

  • Avoid “migrate whenever the app is open” behavior that pulls users out of shared windows and into wallet-specific timing.

  • Explore light coordination so users (and ideally multiple wallet implementations) can prefer the same upcoming buckets when privacy matters — without building a centralized “migration server” that becomes a new metadata honeypot.

  • The honest part about thin cohorts early after activation: if a bucket is sparse, the wallet should warn, delay to a fuller window, or increase multiplicity carefully within K_MAX — not pretend one isolated turnstile is private.

Priority 3 — Amounts and timing

Even with private egress and other users in the cohort, which amounts you publish and when still decides whether an observer can reassemble you.

Pool-crossing transfers reveal migrated value on-chain. A naive schedule (full balance, unique leftovers, wallet-specific jitter) hands attackers:

  • subset-sum / amount fingerprinting against a known prior withdrawal or KYC’d size

  • timing fingerprints that separate one wallet’s schedule from the cohort

  • whale / residual shapes that do not collide with anyone else

This is where we want to stay aligned with:

  • ZIP 318 amount-selection and anchor-bucket timing (canonical denominations, shared boundaries, bounded multiplicity)

  • Zooko’s migration amount/timing proposal and the coordination-migration writeup we have been working from — including ideas such as {1,2,5}×10^k-style chunking, concurrency / same-decade overlap checks before large rounds, and never one-shotting a full tagged balance

Priority 3 is the algorithm layer: given a balance and a threat model, choose a sequence of (amount, bucket/window) pairs that maximize collision and cover, not just “empty the Orchard pool somehow.”

In product terms for Nozy that means:

  • Prefer collision-prone denominations over high-entropy custom sizes

  • Separate split from turnstile so we do not fake privacy with weird migration shapes

  • Gate large or sensitive rounds on cover / concurrency where the writeup calls for it

  • Warn when the only remaining path would publish an exact residual that completes a known subset-sum

  • Keep researching alignment between ZIP 318’s power-of-ten scheme and Zooko-style {1,2,5}×10^k heuristics so wallets do not fragment the anonymity set by disagreeing on “canonical”

None replaces the others. IP protection without cover still leaves on-chain loneliness. Cover without a good amount/timing algorithm still leaves subset-sum and schedule fingerprints. A perfect algorithm on clearnet still paints your IP on the wire.

2 Likes