17 Commits
Author SHA1 Message Date
zeekay 71d5afb016 fix(devnet): canonical EVM chainID 96370 -> 96367 2026-06-23 14:00:16 -07:00
Hanzo AI 3294cbaa64 configs: move brand L1 genesis out of luxfi/genesis (Task #109)
luxfi/genesis only owns Lux primary-network genesis (mainnet/testnet/
devnet/localnet). Brand L1 genesis blobs now live next to the brand
that owns them, in each brand's universe repo:

  hanzo: hanzoai/universe → configs/genesis/{mainnet,testnet,devnet}/
  zoo:   zooai/universe   → configs/genesis/{mainnet,testnet,devnet}/

The pars-* and spc-* dirs have no separate universe repo yet — they
cohabitate this repo under configs/_orphan-l2/ until one is spun up,
explicitly marked as orphans (see configs/_orphan-l2/README.md).

This commit:
  - removes configs/hanzo-{mainnet,testnet,devnet}/genesis.json
    and configs/zoo-{mainnet,testnet,devnet}/genesis.{json,upgrade.json}
  - leaves MOVED.txt tombstones at each old path pointing at the
    new canonical home
  - moves configs/{pars,spc}-{mainnet,testnet,devnet}/ to
    configs/_orphan-l2/ (git mv — history preserved)
  - adds pkg/genesis/no_brand_shadow_test.go which fails if any
    genesis.json reappears under configs/hanzo-* / zoo-* / pars-* /
    spc-* at the top level
  - updates LLM.md + configs/mainnet/UPGRADE_NOTES.md doc refs to
    point at the new locations

Zero Go code references the moved paths — configs/configs.go
//go:embed only covers Lux primary (mainnet testnet devnet localnet),
not brand dirs. Verified by full pkg/genesis test pass.
2026-06-05 09:06:44 -07:00
Hanzo AI af356f789a rename: Etna → Quasar Edition
- pkg/genesis/types.go ChainConfig.EtnaTimestamp → QuasarTimestamp
    json tag etnaTimestamp → quasarTimestamp
  - configs/{mainnet,testnet,devnet}/{cchain,upgrade}.json
    "etnaTimestamp" → "quasarTimestamp"
  - configs/{hanzo,zoo,pars,spc}-{mainnet,testnet,devnet}/genesis.json
    "etnaTimestamp" → "quasarTimestamp"
  - configs/zoo-mainnet/upgrade.json
    "etnaTimestamp" → "quasarTimestamp"
  - scripts/gen-localnet.py + LLM.md docs cleanup

No backcompat aliases — forwards-only. All embedded genesis +
upgrade JSON blobs flipped in-place.
2026-06-02 23:11:39 -07:00
Hanzo AI 30f300f9ea genesis: scrub Avalanche residue from pkg + cmd + LLM.md prose
Comment-only scrub of upstream-fork residue in user-facing docstrings,
CLI help text, and LLM.md prose. No behavior change; no wire-format
change.

pkg/genesis/keys.go:
- DefaultNumAccounts doc: drop "AvalancheJS" from canonical-BIP44 wallet
  list (was "Core, MetaMask, AvalancheJS, lux key derive" -> now
  "Lux Wallet, MetaMask, lux key derive").
- LoadKeysFromMnemonic doc: drop "Avalanche/Lux BIP44 path" (just
  "Lux BIP44 path") and "Core Wallet, AvalancheJS" wallet list (now
  "MetaMask, Lux Wallet").
- LoadKeysFromMnemonic inner loop comment: same scrub
  ("Standard Avalanche/Lux secp256k1 child" -> "Standard Lux ...";
  "matches Core Wallet, MetaMask, cast" -> "matches Lux Wallet, ...").
- BuildBIP44WalletAllocations doc: drop "SLIP-0044 coin type Lux
  inherits from its upstream lineage" prose. Replaced with brand-
  neutral "BIP44 coin type Lux uses by canonical convention".

cmd/genesis/main.go:
- bip44-wallet-keys flag help: drop "SLIP-0044 coin type 9000" ->
  "BIP44 coin type 9000 canonical convention".

LLM.md:
- "Fortuna Timestamp Fix" prose: drop "Fortuna, Etna, and Granite
  upgrades" naming. Replaced with "pre-Quasar Edition upgrades"
  framing. The JSON field names (etnaTimestamp / fortunaTimestamp /
  graniteTimestamp) are preserved in the example block because they
  are the wire format consumed by luxfi/evm.

Intentionally kept (per task scope and forward-compat realities):
- params_test.go:33 + params.go:303 "avax HRP" rejection guards —
  these are protective security tests/comments, not residue. The whole
  point is to refuse "avax"-HRP bech32 addresses synthesized from a
  canonical lux validator's 20 bytes. Stripping the "Avalanche" prose
  would obscure why the guard exists.
- pkg/genesis/types.go:229 EtnaTimestamp uint64 field — this Go field
  is a downstream mirror of the wire-format identifier defined at the
  source of truth in luxfi/evm/params/extras/network_upgrades.go and
  consumed by ~95 JSON genesis blobs, K8s startup manifests, academy
  docs, and migration tooling. Renaming the genesis-repo mirror alone
  would break JSON round-trip with every other consumer in the
  ecosystem. A wire-format rename of EtnaTimestamp -> QuasarTimestamp
  must originate in luxfi/evm and migrate every embedded genesis
  config + every k8s manifest + every doc in one coordinated PR series.
  That migration is OUT OF SCOPE for this commit and is reported back
  to the dispatcher; see external-caller surprises below.

Verification:
- go build ./...           -> clean
- go vet ./...             -> clean
- go test ./... -count=1   -> ok configs, ok pkg/genesis
- grep '[Aa]valanche\|AvalancheJS\|Core Wallet\|SLIP-0044' pkg/genesis
  cmd LLM.md
    -> only 2 lines remain (params.go:303 + params_test.go:33),
       both inside the protective HRP-rejection guard prose.
2026-06-02 22:41:28 -07:00
Hanzo AI 4383ad4583 genesis: unify mnemonic env to LUX_MNEMONIC + kill vesting docstring rot
One env, one way. The genesis mnemonic is now read from exactly one
env var: LUX_MNEMONIC. The prior two-env fallback chain
(MNEMONIC > LIGHT_MNEMONIC) is gone. Per-env isolation is by a
DIFFERENT mnemonic per env (loaded from KMS), not by env-var name.

pkg/genesis/keys.go:
- New MnemonicEnvVar = "LUX_MNEMONIC" constant.
- getMnemonicEnv() reads only LUX_MNEMONIC; no fallback.
- LightMnemonic constant kept (it's the well-known dev seed VALUE;
  pass it as the value of LUX_MNEMONIC for local nets).
- IsProductionNetwork docstring updated to spell out the canonical 4:
  mainnet(1) / testnet(2) / devnet(3) refuse public mnemonics;
  local(1337)+ allows LightMnemonic.
- Docstring rot purged: the prior "50M free + 50M vesting at 1%/year
  over 100y" claim was a lie — buildConfigFromKeyInfos never wired the
  100-period schedule (the code admits the schedule "overflows zapdb
  batch limit"). Replaced with the truth: 1000 × 50M LUX on X-Chain
  AND P-Chain, immediate spend; C-Chain is treasury-only (2T LUX).
- Dead code deleted: StakingStartTime, UnlockInterval consts,
  buildUnlockSchedule() function.

pkg/genesis/allocations.go:
- VestingConfig struct removed.
- DefaultVesting() removed.
- WithVesting() builder method removed.
- Vesting branches in PChain() / PChainMap() collapsed to immediate-only.
- MainnetAllocations no longer calls WithVesting(DefaultVesting()).

pkg/genesis/validator_keys.go:
- VestingPeriods const removed.
- GeneratePChainAllocationsWithVesting() removed.

pkg/genesis/networks.go (new):
- Canonical primary-network-id table: MainnetID / TestnetID / DevnetID
  / LocalID = 1 / 2 / 3 / 1337. Matching C-Chain (EVM) chain IDs:
  96369 / 96368 / 96370 / 31337.
- IsCanonicalPrimaryNetwork helper.

cmd/checkkeys/main.go:
- Reads LUX_MNEMONIC via genesis.MnemonicEnvVar (no fallback).

cmd/derive100/main.go:
- Usage hint updated: mnemonic-env: LUX_MNEMONIC.

cmd/genesis/main.go:
- Flag help, env-var docs, examples, and error messages all reference
  LUX_MNEMONIC.

pkg/genesis/light_mnemonic_guard_test.go:
- All t.Setenv calls use LUX_MNEMONIC.
- Test labels reference LightMnemonic (the constant) not the dead env name.

configs/getgenesis_test.go:
- Comment updated: LightMnemonic instead of LIGHT_MNEMONIC.

CHANGELOG.md + LLM.md:
- Documented the unification + the dead-code removal.

The validator stake-lock (3-entry 5y/10y/20y schedule attached to the
validator's UTXO inside buildConfigFromKeyInfos at keys.go:1077-1083)
is unchanged — that locked-stake bucket is the only UnlockSchedule in
the canonical genesis path and the ProtocolVM needs it.

External-caller sweep: grepped ~/work/lux, ~/work/hanzo, ~/work/zoo,
~/work/luxfi for genesis.VestingConfig / genesis.DefaultVesting /
genesis.GeneratePChainAllocationsWithVesting / genesis.StakingStartTime
/ genesis.UnlockInterval — zero hits. Safe to delete. (luxfi/keys at
~/work/lux/keys has its own MainnetAllocations copy — separate repo,
not affected.)

Verification:
- go build ./... → clean
- go vet ./... → clean
- go test ./... -count=1 → ok configs, ok pkg/genesis
- grep '[^_X]MNEMONIC\|LIGHT_MNEMONIC' under pkg/genesis cmd configs →
  zero matches (only CHANGELOG history + Python script local vars).
- grep VestingConfig|buildUnlockSchedule|GeneratePChainAllocationsWithVesting
  under source → zero matches.
2026-06-02 22:21:27 -07:00
Hanzo AI b69c33a8f8 scrub: subnet/l2 → chain (canonical vocabulary, forward-only)
Wire-format codec IDs unchanged. CLI aliases deleted; chain is the
command. No backwards-compat shims, no deprecation comments.
2026-05-31 14:49:54 -07:00
Hanzo AI f6ba5aef36 consume crypto/keccak256 (was crypto/keccak) — bump crypto v1.19.14 2026-05-23 16:21:45 -07:00
Hanzo AI 8948b4e1cb EVMAddr (Go) + UTXOAddr (Go) — pure chain-model naming, no eth/lux branding
Renames Go struct field ETHAddr → EVMAddr across types.go, keys.go,
allocations.go, validator_keys.go, config.go, builder/builder.go,
cmd/genesis, cmd/checkkeys. JSON tags stayed evmAddr already (from
v1.12.6). Result: matched pair EVMAddr+UTXOAddr on both Go and JSON
sides.

Kept ParseETHAddress as the input-parsing function name — it describes
what it parses (an Ethereum-format hex address), not the field it
populates (an EVMAddr).

LLM.md updated to state the canonical pair plainly; no rename history.
2026-05-22 20:37:30 -07:00
Hanzo AI 2a829c0af2 JSON tags: ethAddr → evmAddr (chain-model name, paired with utxoAddr)
Go field stays ETHAddr (names the H160 byte format, which IS Ethereum's
address spec — we're wire-compatible, not branded). JSON tag changes to
evmAddr so the user-facing pair (evmAddr / utxoAddr) describes our chain
models symmetrically without branding us as Ethereum.

This is the hybrid that fell out of the linter pass: Go identifier =
format-name, JSON tag = chain-model-name. Documented in LLM.md so we
don't regress.

Touches: pkg/genesis/{types,keys,allocations,validator_keys,config}.go,
configs/*/genesis.json + pchain.json + getgenesis_test.go,
scripts/gen-localnet.py. Tests green.
2026-05-22 20:10:48 -07:00
Hanzo AI 28d59d9dcc docs: refresh testnet+devnet C-Chain hashes to current canonical
Live deployed hashes verified byte-equal to current canonical cchain.json:
  testnet: 0xfc909f7e992d9cb91485f114f6d333f3823a12f2c72bbf51ed2c8eea749b2d2e
  devnet:  0x836f6053473e4331bb347afc45b641f12075c63a302f4e56e64239a3ba4acd4b

Previous values were from before commits ae1c52b (Shanghai/Cancun/Prague
at genesis) and 88b6561 (gasLimit 1B). testnet+devnet were both "block 0
fresh" with no committed historical state, so the hash update is in-spec.

Mainnet hash unchanged — its cChainGenesis is locked by the 1.08M-block
historical chain.
2026-05-21 18:43:51 -07:00
Hanzo AI 2259308ffd feat: bake all 10 primary letter-chains into mainnet/testnet/devnet/localnet genesis
Every primary network now ships all 10 chain shards (X, C, D, Q, A, B, T, Z, G, K).
Each chain spawns at startup with zero post-launch CreateBlockchainTx — chain set
is fully data-driven by which shards the operator ships.

Per-letter EVM chainIds locked at 96369 + 100*Δ_from_C (mainnet base) with the
familiar testnet=-1 / devnet=+1 triple inherited from C-Chain:

  C 96369/96368/96370   D 96469/96468/96470   Q 96569/96568/96570
  A 96669/96668/96670   B 96769/96768/96770   T 96869/96868/96870
  Z 96969/96968/96970   G 97069/97068/97070   K 97169/97168/97170

Localnet uses a parallel 31337 + 110*Δ series.

F-Chain ≡ T-Chain (threshold FHE) and M-Chain ≡ K-Chain (KMS-MPC) wired in via
builder alias lists — letter taxonomy decomplected from canonical VM IDs.

Each shard carries:
  - chainId / networkId / timestamp (chain identity at boot)
  - vm + description (operator transparency)
  - per-VM seed extras (DEX fee config, T-Chain DKG params, B-Chain signer set,
    Q-Chain pq scheme pin, K-Chain MPC topology — all empty/default initial state)

Contract locked by configs.TestGetGenesis_AllPrimaryChainsBakedIn — every primary
network must ship all 10 letter-chain shards. Removing a chain on any network is
now a load-bearing test edit, not a silent operator switch.

Mainnet C-Chain invariants preserved: chainId=96369, genesisHash unchanged,
stateRoot=0x2d1cedac…, warp precompile in alloc, warpConfig.blockTimestamp=
1730446786, treasury 2T LUX.
2026-05-19 11:23:16 -07:00
Hanzo AI a4b05b40f5 genesis: shard-driven primary chain set (X opt-in like C/Q/Z)
Make every primary-network chain (X/C/D/Q/A/B/T/Z/G/K) opt-in via its
own <x>chain.json shard. Absent shard -> empty ConfigOutput field ->
builder skips the CreateChainTx -> daemon doesn't start that chain.

Lux mainnet/testnet/devnet ship full chain set as shards; localnet and
local ship the same canonical X asset shard. P-only sovereign L1 boot
shape (<tenant> etc.) is achieved by shipping pchain.json+network.json
only — no env knob, no special builder branch.

X-Chain genesis was previously hardcoded inside FromConfig as a literal
{Symbol:"LUX",Name:"Lux",Denomination:9}. Now sourced from xchain.json
shard, which keeps the same canonical asset for Lux but lets a sibling
network (lqd / <tenant>) ship its own descriptor or ship none and
boot a P-only primary network.

builder.FromConfig:
  - HRP hoisted above the X-Chain conditional (used on both branches).
  - X-Chain construction gated on config.XChainGenesis != "".
  - Returns ids.Empty for xAssetID when X is absent.
  - Single chainEntries table replaces the per-chain switch and the
    DefaultChainGenesis stub-data fallback.
  - "platform" alias renamed to "protocol" (PChainAliases / VMAliases /
    Aliases output) — value is "P-Chain", served by ProtocolVM.

configs.loadAllChainShards / readAllChainShards:
  - Single dispatch over primaryChainShardFiles in canonical order
    (X,C,D,Q,A,B,T,Z,G,K). Adding a new primary chain is one entry +
    one slot, not a new env knob and not a new builder branch.

pkg/genesis/types.go:
  - ConfigOutput.XChainGenesis (omitempty) added; threaded through
    Config <-> ConfigOutput conversions.

Tests:
  - builder/builder_test.go: TestFromConfig_ChainSetIsShardDriven pins
    the contract — full mainnet emits 10 chains + non-empty xAssetID;
    same config with all chain shards stripped emits 0 chains + empty
    xAssetID, validators + UTXOs intact.
  - configs/chain_shards_test.go: TestGetGenesis_XChainShardPresent...
    asserts every Lux network embeds the canonical {LUX,Lux,9} asset;
    AbsentShardEmptyOptIn extended to cover xChainGenesis.
2026-05-14 12:32:53 -07:00
Hanzo AI 72b5bbcbb2 configs: LUX_DISABLE_ZCHAIN / LUX_DISABLE_QCHAIN env knobs
Mirror the LUX_DISABLE_CCHAIN three-precedence pattern for Q-Chain
(Quantum VM) and Z-Chain (ZK VM). Downstream forks that run only
P+X on the primary network (<tenant> is the first) set
LUX_DISABLE_QCHAIN=1 and LUX_DISABLE_ZCHAIN=1 to omit those entries
from the marshalled primary genesis, and builder.FromConfig's
'if config.QChainGenesis != ""' / 'ZChainGenesis' guards skip the
entries at build time.

Precedence (identical to C-Chain knob):
  1. LUX_DISABLE_<X>CHAIN=1 → empty (omit from primary genesis)
  2. LUX_<X>CHAIN_GENESIS_FILE=<path> → file contents verbatim
  3. unset → DefaultPlaceholderGenesis

Q-Chain is the post-quantum primitives chain; Z-Chain is the
zero-knowledge primitives chain. Both are Lux Network-specific and
have no place in the primary genesis of downstream L1s.
2026-05-11 14:43:04 -07:00
Hanzo AI 20150c0ec2 canonical: drop SubnetEVMTimestamp alias — single evmTimestamp field
Lux EVM activation is gated by a single canonical chain config field:
  EVMTimestamp / json:'evmTimestamp'

The legacy 'SubnetEVMTimestamp' / 'subnetEVMTimestamp' field was a duplicate
alias for the same activation. Removed:
  - geth/params/config.go: ChainConfig.SubnetEVMTimestamp field
  - geth/params/config.go: IsEVM() now checks EVMTimestamp only
  - geth/params/config.go: isLuxL2Chain check uses EVMTimestamp only
  - all genesis JSON configs (mainnet/testnet/devnet × all chains)
  - all helm chart genesis files (charts/lux/genesis/*.json)
  - all docs (LLM.md, *.mdx)

One field, one way.
2026-05-05 21:30:08 -07:00
Hanzo AI 1c0d11b5de docs: scrub upstream 'Subnet-EVM' brand; rename 'Subnet Chains' → 'L2 Chains' 2026-05-05 20:26:10 -07:00
Hanzo AI 7d6f991fbd docs: canonical EVM VM ID = mgj786NP… (single, no aliases) 2026-05-05 20:16:26 -07:00
Hanzo AI 1fd6379752 genesis: regenerate all network configs
- mainnet: 100 accounts x 500M LUX, 5 stakers, P-lux1 HRP, real IPs
- testnet: 100 accounts x 500M LUX, 2 stakers, P-test1 HRP, networkID=2
- devnet: 100 accounts x 500M LUX, 3 stakers, P-dev1 HRP, networkID=3
- bootstrappers: real validator IPs
- fix mnemonic env priority: MNEMONIC > LUX_MNEMONIC > LIGHT_MNEMONIC
- remove stale .bak files
2026-04-04 11:22:32 -07:00