Mainnet brand L2 cleanup is blocked on the HrJ→pmSJ fee-asset
fracture (deployer wallet holds HrJ UTXOs; CreateChainTx fee
verifier requires pmSJ). Document the three resolution options:
A — Full wipe: clean abstraction, total state loss
B — Verifier accepts HrJ: surgical, hides the bug
C — MigrateAssetTx: generalizable, largest scope
Decision deferred to owner. testnet+devnet are unblocked (luxfi/
genesis 3a072e7 + b448910, luxfi/universe 19ebe35c); mainnet
brand L2 chain.name re-bootstrap blocked until one of A/B/C lands.
5.3 KiB
Mainnet Brand L2 Wipe Proposal
Status: DRAFT — awaiting decision. Owner: TBD. Date opened: 2026-06-02. Blocker for: closing out the brand-L2 decomplection (luxfi/genesis 3a072e7).
Context
The testnet+devnet brand L2s (hanzo, zoo, spc, pars) carry stale
P-chain chain.name rows from the {brand}fix-{env}/ workaround
era. Those rows are now correctly aliased ("hanzo" only — no
"hanzofix" anywhere; commit luxfi/universe@7498301b). The chain.name
itself stays whatever-was-unique-at-CreateChainTx-time forever
(immutable on P-chain), but it is no longer surfaced to users.
Mainnet has an additional, distinct problem: a fee-asset fracture
between staking (asset pmSJ7BfZ…) and historical P-chain UTXOs
(asset HrJCm4yvN…). bootstrap-chain cannot fund CreateChainTx
because the wallet builder reads UTXOs in asset HrJ… but the fee
verifier requires pmSJ… — re-bootstrapping new mainnet brand L2s
under the new content-hash naming is blocked on this.
This document lays out the three options the project has to resolve mainnet. The user decides which to execute; no agent should take unilateral action.
Option A — Full mainnet wipe (Path B from the original spec)
What it does:
- Delete every PVC backing mainnet luxd (
data-luxd-{0..14}inlux-mainnetnamespace). - Let the operator re-create PVCs from
seedRestore— fresh genesis, no historical state. - Re-fire bootstrap-chain with content-hash naming. Brand L2s
come up under canonical
{brand}-<8hex>chain.name values. - Update chain-aliases CM to new BIDs.
Pros:
- Cleanest mainnet abstraction (no asset fracture; no orphan rows).
- Same code path as testnet/devnet — no per-env special case.
- Re-uses the decomplected bootstrap-chain with zero special flags.
Cons:
- Total mainnet state loss: validator stakes reset, all UTXOs reset to genesis alloc, historical transactions unrecoverable.
- All current mainnet token holders lose balance unless we honor the pre-wipe state via a new genesis alloc that mirrors current balance (manual reconciliation, audit risk).
- Hard fork — needs explicit user/owner approval. Bridge consumers must be coordinated (luxfi/bridge, third-party indexers).
Scope: large. Estimate: 2–4 weeks coordinated rollout including balance reconciliation and bridge resync.
Option B — Patch P-chain fee verifier to accept HrJ
What it does:
Add a runtime-configurable list of accepted fee-asset IDs to the
P-chain fee verifier (luxfi/node/vms/platformvm/txs/fee or
similar). Configure mainnet to accept BOTH pmSJ… (canonical) and
HrJ… (legacy) for the duration of the brand-L2 re-bootstrap, then
re-pin to pmSJ…-only after the fact.
Pros:
- Surgical. Touches one verifier component. No state mutation.
- Zero mainnet downtime.
- bootstrap-chain runs as-is once the verifier accepts the legacy asset for CreateChainTx fees.
Cons:
- Hides the asset fracture instead of resolving it. The fracture is
itself a bug that should be tracked (whoever flipped staking to
pmSJ…without migrating UTXOs introduced two-asset accounting). - Verifier list grows over time if more "legacy assets" appear.
- Per
~/.claude/CLAUDE.mdbrand discipline: "one and only one way to do everything" — having two valid fee assets violates this.
Scope: small (1-2 days). Estimate: 1 sprint.
Option C — Build an asset-migration tx mechanism
What it does:
Introduce a new tx type (MigrateAssetTx or similar) that lets a
holder atomically swap UTXOs of asset HrJ… for the equivalent
amount of asset pmSJ…. After holders migrate, the verifier
naturally rejects HrJ… going forward — and historical chains
stay legal.
Pros:
- Solves the asset fracture cleanly (single canonical fee asset going forward).
- No state loss, no fork, no verifier kludge.
- Generalizable: any future asset rename uses the same mechanism.
Cons:
- Largest scope. Needs:
- tx-type design + serialization
- wallet UX for migration
- operator coordination (holders must opt in)
- audit of the swap rate (is HrJ : pmSJ 1:1 or do we need a conversion factor?)
- Migration window required. Holders who never migrate are stuck (same risk as any forced-migration).
Scope: large. Estimate: 4-6 weeks including audit.
Recommendation (not a decision)
Hold mainnet brand L2 cleanup until one of these is chosen. In the interim:
- testnet + devnet are clean (this commit batch closes them out).
- mainnet brand L2 aliases still point at whatever live BIDs exist — no fix-suffix is surfaced, even if the on-P-chain chain.name values remain whatever was unique at creation time.
- bootstrap-chain is ready (luxfi/genesis 3a072e7). Re-running it on mainnet under any of the three options requires only that the P-chain fee path accept the deployer wallet's UTXO asset.
If forced to pick: Option B for the smallest blast radius + fastest unblock, with Option C queued as the proper long-term fix and Option A held in reserve for if the asset fracture turns out to have a corruption root cause that simple verification flag-flipping can't address.
Out-of-scope
- The content-hash chain.name patch (already shipped — luxfi/genesis 3a072e7).
- The {brand}fix-{env}/ symlink removal (already shipped — luxfi/ genesis b448910).
- chain-aliases naming hygiene (already shipped — luxfi/universe 7498301b).