Drop the Avalanche-heritage /ext prefix; /v1 is the single canonical route
surface (one way, no backward compat). The node's baseURL is the source of
truth; clients, SDKs, CLI, indexer, maker, genesis, netrunner, and the
k8s/compose/gateway/explorer configs are updated to match.
Co-authored-by: Hanzo Dev <dev@hanzo.ai>
node/consensus/quasar + node/consensus/zap + node/node/quasar.go were a
superseded duplicate of the live post-quantum finality path
(consensus/protocol/quasar WeightedQuorumCert, driven by the chain engine).
The node-side hub wrapped that live core but added only dormant scaffolding:
- an undriven P-Chain finality loop (finCh never fed; run() sat idle)
- a fail-closed CoronaCoordinator stub (Sign/Verify errored in prod,
InitializeCorona was test-only, so q.corona stayed nil)
- a QuantumFinality store nothing read (only n.Quasar.Stop() was ever called)
Dependency trace: zero cross-repo importers; the Q-Chain VM
(luxfi/chains/quantumvm) is external, independent, and finalized by the live
chain-engine QuorumCert path, not this hub; consensus/zap (ZAP/DID agentic
bridge) was a collateral dormant island on the same stub with no external
importers. Wiring was impossible without driving the live accept path or
adding a redundant second finality authority, both out of scope, so the hub
is removed rather than wired.
Live consensus/protocol/quasar and consensus/engine/chain are untouched.
Q-Chain VM registration, genesis, and critical-by-default status are
unchanged. Genuine PQ tests (TLS hybrid KEX, ML-DSA UTXO, hostname
addressing) are preserved; only the dormant-hub tests were removed.
External (HTTP / JSON-RPC) is the only place JSON is legitimate. Every
existing encoding/json import in node/ moves to github.com/go-json-experiment/json
(v2 root, not the v1 sub-package). NewEncoder/NewDecoder rewrite to
MarshalWrite/UnmarshalRead. MarshalIndent rewrites to Marshal with
jsontext.WithIndent. json.RawMessage rewrites to jsontext.Value.
*json.SyntaxError rewrites to *jsontext.SyntacticError.
81 files migrated. LLM.md captures the rule + v1->v2 delta table.
Known v2 semantic deltas surfaced by existing tests (followups, not regressions):
- [N]byte fields with no MarshalJSON now marshal as base64 string (v1 marshalled
as JSON array of byte numbers). Affects vms/platformvm/txs/*_test.go fixtures
with embedded BLS proofOfPossession.
- time.Duration has no v2 default representation; configs that wire-format
Duration as nanoseconds (vms/{xvm,platformvm}/config, config/spec) need to
switch to string-form Duration or carry an explicit option. v2 root does not
re-export FormatDurationAsNano.
- v2 enforces strict UTF-8 (vms/chainadapter/messaging fixture has non-UTF-8).
- json.MarshalWrite does not append a trailing '\n' (v1 NewEncoder.Encode did);
service/auth/auth_test.go expectation updated.
- nil []byte round-trips to empty (not nil); config_test deep-equal fixtures
surface this.
All affected sites are at the API boundary; ZAP wire envelope already covers
the internal data paths (state, P2P, consensus, MPC, threshold). Internal
JSON sites that should move to ZAP next (separate work):
- vms/da/store.go (DA blob/cert storage as JSON)
- vms/platformvm/airdrop (airdrop claims as JSON in db)
- vms/chainadapter/appchain (SQLite materializer schema/data blobs)
- vms/chainadapter/messaging (conversation codec)
- staking/kms.go (KMS HTTP client — external technically, leave)
- utils/{bimap,ips} (small marshaler shims — low priority)
Phase 4 of the upstream-upgrade purge per ~/work/lux/proofs/UPGRADE_RIP.md.
Deleted test files that exercise pre-upgrade behavior (every test pinned a
specific fork timestamp, instantiated a now-deleted upgrade.Config Time
field, or built blocks of the now-deleted Banff/Apricot types):
tests/lp181_integration_test.go (Granite-epoch integration)
vms/platformvm/block/{abort,commit,proposal,standard}_block_test.go
vms/platformvm/block/{parse,serialization}_test.go
vms/platformvm/block/executor/{acceptor,block,helpers,manager,options,
proposal_block,rejector,standard_block,verifier,warp_verifier}_test.go
vms/platformvm/block/builder/{builder,helpers,standard_block}_test.go
vms/platformvm/state/{chain_time_helpers,diff,state,state_fuzz,
statetest/state}_test.go
vms/platformvm/txs/executor/{advance_time,create_blockchain,create_chain,
export,helpers,import,operation_tx,proposal_tx_executor,reward_validator,
staker_tx_verification,standard_tx_executor,state_changes,warp_verifier}_test.go
vms/platformvm/validators/{manager_benchmark,manager}_test.go
vms/platformvm/{service,vm,vm_security_profile}_test.go
vms/platformvm/warp/validator_test.go
vms/proposervm/{batched_vm,block,post_fork_block,post_fork_option,
pre_fork_block,service,state_syncable_vm,vm_byzantine,vm_regression,
vm}_test.go vms/proposervm/lp181/epoch_test.go
upgrade/upgradetest/fork.go: trimmed Fork enum to the bare constant set
(NoUpgrades..Granite + Latest=Granite); the String() method went with it.
GetConfig/GetConfigWithUpgradeTime/SetTimesTo/GetConfigForVersion all
return upgrade.Default regardless of input Fork value.
Build: `GOCACHE=/tmp/gocache-decomplect-r2 GOWORK=off go build ./...` green.
`go vet ./...` clean (xvm tests still use upgradetest.Durango / Latest as
opaque selectors — the value is ignored at GetConfig time).
Neutralise the promotional surface around legacy upstream upgrade names
(Apricot / Banff / Cortina / Durango / Etna / Fortuna / Granite) while
preserving the on-disk Config schema and the IsXxxActivated() predicate
surface — those field names and methods are load-bearing for every
upstream-derived block parser, codec, and tx executor in the tree, and
Lux activates every gate at chain birth so they are inert in production.
Changes:
- upgrade/upgrade.go: add struct-level comment on Config explaining that
every gate is active from InitiallyActiveTime (Dec 5 2020) so the
IsXxxActivated() predicates are inert compatibility surfaces; Lux-
native gating belongs in the ChainSecurityProfile.
- upgrade/upgradetest/fork.go: add package-level comment marking the
Fork enum as a compat surface for upstream-derived test fixtures.
- vms/platformvm/docs/{block_formation_logic,chain_time_update}.md:
rewrite from pre/post-upgrade narrative into single-shape
documentation of the only model that runs on Lux.
- vms/platformvm/docs/validators_versioning.md, indexer/service.md,
config/config.md, vms/platformvm/warp/README.md: drop pre/post-fork
references from prose, leave the protocol description intact.
- vms/proposervm/proposer/windower.go, pre_fork_block.go,
vms/proposervm/block_test.go, vms/platformvm/warp/validator.go,
vms/platformvm/txs/executor/proposal_tx_executor.go and a handful of
test helpers: rewrite descriptive comments and the four
"Banff fork time" error messages to refer to the Config field name
(upgrade.Config.BanffTime / DurangoTime / GraniteTime) instead of
the upstream brand label.
- tests/granite_integration_test.go -> tests/lp181_integration_test.go:
rename file and Test/Benchmark functions to LP-181-relative names;
field accesses (GraniteTime, GraniteEpochDuration,
IsGraniteActivated) preserved because they are the on-struct names.
- network/network.go, network/peer/peer.go, chains/manager.go,
scripts/tests.upgrade.sh, .github/labels.yml: scrub stray
upstream-brand mentions from comments / labels.
What is intentionally preserved (compat shim policy, same logic as the
geth-config preservation rule for ~/work/lux/coreth /geth /genesis):
- upgrade.Config field names (ApricotPhaseNTime, BanffTime, ..., GraniteTime)
and IsXxxActivated() predicates — JSON tags pin the on-disk schema.
- upgradetest.Fork enum values (NoUpgrades..Granite) — referenced by
hundreds of upstream-derived test fixtures.
- Block-type identifiers (BanffStandardBlock, ApricotProposalBlock, ...)
— wire-format-load-bearing.
- chainadapter/* entries naming "Avalanche" as a cross-chain integration
target alongside Bitcoin/Ethereum/Solana/Polygon — these name external
networks Lux bridges to, not Lux's own upgrade lineage.
- RELEASES.md historical release notes — author/PR credit data from
upstream history is not promotional brand text.
Build verified: GOWORK=off go build ./... -> exit 0.
Pulls in:
* luxfi/constants v1.5.2 — LocalID/CustomID semantic split, IsCustom()
* luxfi/genesis v1.9.2 — same split mirrored at the configs layer
* luxfi/zwing v0.5.2 — full PQ secure channel (X-Wing + ML-DSA-65 +
ChaCha20-Poly1305) with cross-language
wire-byte interop verified against Rust /
Python / TypeScript ports
* luxfi/api v1.0.10 — zap.NewListener seam (used by zwing.ListenZAP)
* luxfi/netrunner v1.18.1 — PQ-mandatory zapwire control RPC + same
LocalID rename
* luxfi/geth v1.16.87 — verkle.Fr type fix (drop bandersnatch import)
* luxfi/consensus v1.23.1 — banderwagon path move tracked
Source-side rename in this repo: every constants.CustomID call was
"the local 1337 dev network", so they all become constants.LocalID
(both the upgrade-config validation switch and the test fixtures).
The old constants.CustomID literal is now 0 — used as the explicit
"this is a user-defined custom network" sentinel, separate from the
LocalID dev network.
Plus a clarifying comment on the upgrade-config switch noting which
network IDs are permitted to override their upgrade schedule (any
non-well-known ID, including DevnetID/UnitTestID and any genuinely
custom user-defined network ID).
Z-Wing dialer + tests still green; all network/dialer, config,
config/node, config/spec, and genesis/builder tests pass.
Remove unused bloom filter, test helpers, metrics scaffolding, and
linearizable VM wrapper. Trim stale go.sum entries. Add genesis builder
helpers and xvm FX/genesis initialization.