Zoo and Hanzo have their own networks, so the P-chain does not carry them

Asked to register both with CreateChainTx on Lux mainnet. Neither was created,
and the record now says why rather than leaving the next reader to rediscover it.

Each brand already holds a chain identity elsewhere: hanzod serves 36963 on its
own primary network, bootstrapped, and Zoo's C-chain carries 13,348 blocks on
network 200200 since the 2026-07-14 cutover. A CreateChainTx here would mint a
second identity for the same brand and orphan that history. It also could not
have run: platformvm now serves one handler at /ops and nothing at the chain
base, so the JSON-RPC client both tools open with returns 404 before it reads
anything, and every genesis allocation that could pay the fee is either staked
or behind a mnemonic that is not on this machine.

Records the eleven blockchain ids the primary network does carry, read from the
P-chain rather than from a manifest. T is gone; F and M are there in its place,
which the 2026-06-02 inventory predates. Marks that inventory and the brand-L2
follow-on it promised as superseded, since both still read as the plan.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-09-09 01:41:46 -07:00
co-authored by Hanzo Dev
parent 9ab3ac661d
commit 655f5a3a5c
+104
View File
@@ -786,6 +786,8 @@ Both genesis blobs:
`~/work/lux/genesis/configs/{testnet,devnet}/cchain.json` (canonical)
- No L2 chains (`chains: []`) — brand L2s (Hanzo/Zoo/SPC/Pars) re-created
via CreateChainTx as a separate follow-up
(that follow-up was dropped 2026-06-27; brands run their own network —
see "Zoo and Hanzo are not chains on the Lux primary network")
Genesis CLI gotchas:
1. `LoadKeysFromDir` scans EVERY subdirectory of KEYS_DIR including
@@ -829,6 +831,10 @@ All six results expect `isBootstrapped: true`. Confirmed 2026-06-02.
## Brand L2 chain registration on test+dev primaries — 2026-06-02 (closes #168)
Superseded 2026-06-27. The record below is what was done and is kept for
provenance; it is not the model. Brands run their own network — see "Zoo and
Hanzo are not chains on the Lux primary network".
The 4 brand L2 EVMs (hanzo/zoo/spc/pars) are now registered on the fresh
testnet + devnet primary networks via `IssueCreateChainTx` (P-chain
canonical tx, codec name unchanged from upstream). One pair = one chain
@@ -1136,3 +1142,101 @@ from here on:
three fleets.
- `k8s/` never redeclares what `deploy/` declares. A k8s manifest that
duplicated a values file is deleted, not merged back.
## Zoo and Hanzo are not chains on the Lux primary network — measured 2026-09-09
Asked to create `zoo` and `hanzo` with CreateChainTx on Lux mainnet and bootstrap
them. Neither was created. Three independent reasons, each measured against the
live fleet on evo (10.0.0.21, five validators on 9730–9770,
`ghcr.io/luxfi/node:v1.36.181`, `--network-id=1`).
**They already exist, elsewhere, with their own identities.** `hanzod-mv-0..4`
(ns `hanzo-mainnet`) serves `eth_chainId` `0x9063` = 36963 with
`info.isBootstrapped(C)=true`, on its own primary network 36963 — its genesis
ConfigMap `hanzod-mv-genesis` is a primary genesis (`networkID: 36963`,
`initialStakers`, `cChainGenesis.config.chainId: 36963`), not a CreateChainTx
blob. Zoo mainnet's C-chain is `23hNkQEfXaGfVVJjDPEPGgvHNfGW5BXWx47kxe67fn1qgL2fsP`
on sovereign network 200200, carrying 13,348 blocks (genesis `0x7c548af4`, tip
13,347 `0x891a539c`, 729 settlements) — see `zoo/universe` LLM.md, cut over
2026-07-14. Creating either on the Lux P-chain mints a second, competing chain
identity for the same brand and abandons that history.
**The primary network's chain set is closed to brands by decision.**
`brand_sovereign_node_one_way` (2026-06-27): luxd runs the Lux primary network
only. `cmd/bootstrap-chain` enforces it — the names hanzo/zoo/pars/spc/osage are
refused before any P-chain spend. `k8s/lux-mainnet/chain-aliases.yaml` records
the same finding: the brand aliases pointed at chains never created.
**The P-chain has no JSON-RPC surface left, so the tooling cannot reach it.**
`platformvm.CreateHandlers` returns exactly one handler, at `/ops`
(`node/vms/platformvm/vm.go`) — the base is deliberately unserved. Measured
through `luxfi/[email protected]`, the client path both tools use:
```
platform.getHeight → /v1/chain/P → 404 (also via api.lux.cloud)
info.getNetworkID → /v1/info → 404
primary.FetchState → received status code: 404
```
`createchaintx` and `bootstrap-chain` both open with `primary.MakeWallet`, which
begins at `FetchState`, so neither gets past its first network call. The live
surface is typed operations under `/v1/chain/P/ops` (OpenAPI 3.1 at
`/ops/.well-known/openapi.json`): `GET /blockchains`, `GET /utxos`, `POST /tx`
taking already-signed bytes. Reaching the P-chain from Go again means a client
that speaks that, not a newer path string.
What the primary network carries, read from `/v1/chain/P/ops/blockchains`. All
eleven sit on net `11111111111111111111111111111111LpoYY`; the P-chain itself is
`11111111111111111111111111111111P`. No T — it became F and M.
| chain | blockchain id |
|-------|---------------|
| C | `TZEa3jDMCY5iQWqm5brNhqdszHza3e2qvzSGCC63uQNbVA3z3` |
| X | `2fdnRbzs9sWj5cVqny2sdShXzZXgvm96DyzvzgB2Z7j3VKZukd` |
| A | `2NXHomv4gbu8i6JTqALHvcbdeb8gb8r7jzbxqXvqZRd1UzorhF` |
| B | `JNF8xWg2eMam5nAq9MQaE9LuXYo9Ccv2WcY8hEts7bDdmNGtJ` |
| D | `1AFS4GPsBYrzG3KLvjEfJfWAcs5AgTs2XfFoG4xBQed95p3tT` |
| F | `Ec9QkdmFnmhPSpuvXenwQ798mFH9gYCgJjy6V4Wfg336wFaX1` |
| G | `24C9zm36x43T7LqcaKF1ikHxSeuQeTXnstzi5Gwh2apo18rXNE` |
| K | `2sK7efGAyZJcfLMKPzHg39NPJnL4SwYmFUsPDHMYVLMVYqP4Fw` |
| M | `2erizn2pu4gbafsFzbyfqwzhkR2RT1qFdwr7kKKwn5T3BH3wW8` |
| Q | `2wiiMEaeLPnxQH3gs5GU1QWCBakE4axd9rJgAqwzkWfr5BwhyM` |
| Z | `ddz6d4PFUhuxzYdLDCiKyMfcxsuboT67KqQ7mwPt9baudAoKs` |
Only C is an EVM: `eth_chainId` `0x17871` = 96369, head `0x3b` = 59 on all five
validators. Aliases resolve, but only under `/ops` — `/v1/chain/P` alone is a
404 and `/v1/chain/P/ops/blockchains` is a 200. The P-chain's `/height` answers
204 with no body, which is why height reads look empty.
Nothing on this P-chain can pay a fee anyway. All 100 genesis allocations carry
`initialAmount: 0`; allocations 0–4 are `initialStakedFunds` and hold nothing
until their stake ends (~2026-12-12). Slots 5–98 each hold 3,500 LUX unlocked
against 46,500 stakeable-locked, and spending one needs the master mnemonic at
BIP-44 `m/44'/9000'/0'/0/<slot>`, which lives in KMS and was not on this machine.
### What Zoo mainnet needs here instead
`zood-mv` (ns `zoo-mainnet`) is declared and scheduled but has never started:
`zood-mv-0` has been `Init:0/1` since it was created, on three missing objects —
ConfigMaps `zood-mv-genesis` and `zood-mv-startup`, and Secret `zood-mv-staking`.
The startup script is already committed at `k8s/zoo-mainnet/zood-mv-startup.yaml`
(`--network-id=200200`, `/genesis/genesis.json` + `/genesis/upgrade.json`); the
other two are not.
The genesis is the one to be careful about.
`zoo/universe/configs/genesis/mainnet/genesis.json` is an EVM genesis (chainId
200200) with a `networkID` field added, which is not the shape `--genesis-file`
wants — compare `hanzod-mv-genesis`, which is a primary genesis carrying its EVM
under `cChainGenesis`. Zoo needs the same: a primary genesis for network 200200
with five stakers, that EVM blob verbatim as `cChainGenesis`, and the existing
`upgrade.json`. Anything else changes the genesis hash and orphans the history.
Two facts to carry into that work. Zoo's canonical genesis hash is
`0x7c548af47de27560779ccc67dda32a540944accc71dac3343da3b9cd18f14933`; a genesis
that does not reproduce it is a different chain. And `zoo/universe` LLM.md
records that `admin_importChain` of the RLP diverges at block 800 on both
v1.34.9 and v1.36.2 — the state moves by direct zapdb copy of the coreth C-db,
not by RLP import. `~/work/lux/state/rlp/zoo-mainnet/zoo-mainnet-200200-0-13347.rlp`
(14.7 MB, blocks 0–13347, sentinel hashes matching the canonical tip) is the
only copy of that history on this machine; the `data-zood-0` PVC and its
snapshot were on the DigitalOcean cluster.