1778 Commits
Author SHA1 Message Date
zeekay e41e0fa066 k8s: strip {brand}fix-suffix from chain aliases and references
The fix-suffix workaround (hanzofix/zoofix/spcfix/parsfix) is dead.
luxfi/genesis bootstrap-chain now derives the P-chain CreateChainTx
name from canonical genesis content (commit 3a072e7 there), so
re-bootstraps are idempotent and never collide on P-chain. The
user-facing brand identifier ("hanzo", "zoo", "spc", "pars") lives
exclusively at this chain-aliases ConfigMap layer.

Per-cluster changes:
- lux-testnet + lux-devnet chain-aliases.yaml: alias map now has
  only brand names; legacy "fix" suffix removed. BIDs point at the
  current live backing chains (live cluster CMs already updated via
  kubectl apply 2026-06-02).
- testnet explorer.yaml: stale "re-bootstrapped as zoofix" comment
  removed (the comment leaked a workaround name into config).
- testnet ingress-chains.yaml: "backed by zoofix chain" → "backed
  by blockchain ID LXuiihy…WeQ".
- testnet network.yaml, api-gateway-gateway-config.yaml,
  dead-chains-cm.yaml, lux-indexer.yaml: comments updated to refer
  to live BIDs/aliases instead of stale fix-suffix names.
- lux-mainnet/lux-indexer.yaml: stale "parsv4/spcv4/zoofix" example
  list removed.
- lux-k8s/api-gateway/ingresses.yaml: "LXuiihy... zoofix dormant"
  note rewritten to reflect promotion to live zoo backing chain.
- lux-k8s/validators/crd-resources.yaml: indexer-zoo CR no longer
  sets chainAlias: zoofix or routes /ext/bc/zoofix/rpc; routes
  /ext/bc/LXuiihy…WeQ/rpc + relies on alias resolution for /zoo/rpc.

No BID changes here — only naming hygiene. Live cluster CM updates
were applied imperatively on 2026-06-02 (chain-aliases + explorer-
chains in lux-testnet and lux-devnet namespaces).
2026-06-02 20:53:37 -07:00
Hanzo AI 19ebe35c43 k8s: strip {brand}fix-suffix from chain aliases and references
The fix-suffix workaround (hanzofix/zoofix/spcfix/parsfix) is dead.
luxfi/genesis bootstrap-chain now derives the P-chain CreateChainTx
name from canonical genesis content (commit 3a072e7 there), so
re-bootstraps are idempotent and never collide on P-chain. The
user-facing brand identifier ("hanzo", "zoo", "spc", "pars") lives
exclusively at this chain-aliases ConfigMap layer.

Per-cluster changes:
- lux-testnet + lux-devnet chain-aliases.yaml: alias map now has
  only brand names; legacy "fix" suffix removed. BIDs point at the
  current live backing chains (live cluster CMs already updated via
  kubectl apply 2026-06-02).
- testnet explorer.yaml: stale "re-bootstrapped as zoofix" comment
  removed (the comment leaked a workaround name into config).
- testnet ingress-chains.yaml: "backed by zoofix chain" → "backed
  by blockchain ID LXuiihy…WeQ".
- testnet network.yaml, api-gateway-gateway-config.yaml,
  dead-chains-cm.yaml, lux-indexer.yaml: comments updated to refer
  to live BIDs/aliases instead of stale fix-suffix names.
- lux-mainnet/lux-indexer.yaml: stale "parsv4/spcv4/zoofix" example
  list removed.
- lux-k8s/api-gateway/ingresses.yaml: "LXuiihy... zoofix dormant"
  note rewritten to reflect promotion to live zoo backing chain.
- lux-k8s/validators/crd-resources.yaml: indexer-zoo CR no longer
  sets chainAlias: zoofix or routes /ext/bc/zoofix/rpc; routes
  /ext/bc/LXuiihy…WeQ/rpc + relies on alias resolution for /zoo/rpc.

No BID changes here — only naming hygiene. Live cluster CM updates
were applied imperatively on 2026-06-02 (chain-aliases + explorer-
chains in lux-testnet and lux-devnet namespaces).
2026-06-02 20:53:37 -07:00
zeekay 1a0e70be4d k8s/lux-{mainnet,testnet,devnet}: bump luxd v1.28.19 → v1.28.20
v1.28.19 was tagged from 9df3e16f30 (LP-023 ZAP-native activation
cutover) BEFORE Blue's v3.x safety net commits landed. v1.28.20 is
rebuilt from main HEAD 2e7012af0e which includes:

  - Blue v3.0 (15b25a2f16) — R6V4 CRITICAL: CreateSovereignL1Tx
    zero-validator / zero-chain gate (must reject in Verify())
  - Blue v3.5 (d51942d18d) — RESERVED bytes zero-gate + AddressList
    CI audit gate + cross-blob aliasing contract
  - Blue v3.6 (30c9608255) — R7V5 mempool admission gate for
    zap_native + R7V7 Verify() for RegisterL1ValidatorTx and
    ConvertNetworkToL1Tx + R7V8 MustVerify rename + CI gate
  - bench fix (2e7012af0e) — disable_legacy_test underflow on
    ZAPActivationUnix=0

Without R7V5 the mempool would accept zap_native L1 txs that the
current executor cannot process under always-on activation — this
bump closes that consensus risk before the per-env rollout.
2026-06-02 19:59:53 -07:00
Hanzo AI ee04c5bfda k8s/lux-{mainnet,testnet,devnet}: bump luxd v1.28.19 → v1.28.20
v1.28.19 was tagged from 9df3e16f30 (LP-023 ZAP-native activation
cutover) BEFORE Blue's v3.x safety net commits landed. v1.28.20 is
rebuilt from main HEAD 2e7012af0e which includes:

  - Blue v3.0 (15b25a2f16) — R6V4 CRITICAL: CreateSovereignL1Tx
    zero-validator / zero-chain gate (must reject in Verify())
  - Blue v3.5 (d51942d18d) — RESERVED bytes zero-gate + AddressList
    CI audit gate + cross-blob aliasing contract
  - Blue v3.6 (30c9608255) — R7V5 mempool admission gate for
    zap_native + R7V7 Verify() for RegisterL1ValidatorTx and
    ConvertNetworkToL1Tx + R7V8 MustVerify rename + CI gate
  - bench fix (2e7012af0e) — disable_legacy_test underflow on
    ZAPActivationUnix=0

Without R7V5 the mempool would accept zap_native L1 txs that the
current executor cannot process under always-on activation — this
bump closes that consensus risk before the per-env rollout.
2026-06-02 19:59:53 -07:00
zeekay b5f4d17e03 infra/k8s/arc: lux-build amd64 runner pool values
Pins the gha-runner-scale-set values for the lux-build pool on
do-sfo3-lux-k8s. The pool was missing 2026-06-02 (helm release gone,
unclear when removed) — v1.28.19 build sat queued 28+ minutes until
reinstalled. Committing the values file so reinstall is reproducible.

Org separation: luxfi/* workflows MUST runs-on: lux-build (this pool);
hanzoai/* workflows MUST runs-on: hanzo-build-linux-amd64. Cross-org
runs-on queues silently and times out at 24h.

Install:
  helm pull oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set --version 0.14.0 --destination /tmp
  helm --kube-context=do-sfo3-lux-k8s -n arc-system install lux-build \\
    /tmp/gha-runner-scale-set-0.14.0.tgz \\
    -f infra/k8s/arc/values-build-amd64.yaml
2026-06-02 19:30:04 -07:00
Hanzo AI 88fe314415 infra/k8s/arc: lux-build amd64 runner pool values
Pins the gha-runner-scale-set values for the lux-build pool on
do-sfo3-lux-k8s. The pool was missing 2026-06-02 (helm release gone,
unclear when removed) — v1.28.19 build sat queued 28+ minutes until
reinstalled. Committing the values file so reinstall is reproducible.

Org separation: luxfi/* workflows MUST runs-on: lux-build (this pool);
hanzoai/* workflows MUST runs-on: hanzo-build-linux-amd64. Cross-org
runs-on queues silently and times out at 24h.

Install:
  helm pull oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set --version 0.14.0 --destination /tmp
  helm --kube-context=do-sfo3-lux-k8s -n arc-system install lux-build \\
    /tmp/gha-runner-scale-set-0.14.0.tgz \\
    -f infra/k8s/arc/values-build-amd64.yaml
2026-06-02 19:30:04 -07:00
zeekay 22ffa32706 k8s/lux-{mainnet,testnet,devnet}: bump luxd image to v1.28.19
LP-023 ZAP-native activation cutover. ZAPActivationUnix=0 (always-on)
— the forward-dated 2026-07-01 activation is dead. ZAP wire is
mandatory from genesis; legacy linearcodec is reachable only via
LUXD_ENABLE_LEGACY_CODEC=1 for read-path back-compat.

Also includes EVM v0.18.18 HashScheme default fix for the fresh L2
chain-create wedge (hanzo/zoo/spc/pars) — same fix as v1.28.18.

Operator v0.3.12 / v0.6.2 does not reconcile image tag on adoptExisting
StatefulSets — explicit pod-by-pod restart required after this sync
(kubectl delete pod luxd-N, wait for 1/1, repeat).

Authorized by 2026-06-02 destructive recovery sweep.
2026-06-02 19:04:53 -07:00
Hanzo AI 1f1a61abce k8s/lux-{mainnet,testnet,devnet}: bump luxd image to v1.28.19
LP-023 ZAP-native activation cutover. ZAPActivationUnix=0 (always-on)
— the forward-dated 2026-07-01 activation is dead. ZAP wire is
mandatory from genesis; legacy linearcodec is reachable only via
LUXD_ENABLE_LEGACY_CODEC=1 for read-path back-compat.

Also includes EVM v0.18.18 HashScheme default fix for the fresh L2
chain-create wedge (hanzo/zoo/spc/pars) — same fix as v1.28.18.

Operator v0.3.12 / v0.6.2 does not reconcile image tag on adoptExisting
StatefulSets — explicit pod-by-pod restart required after this sync
(kubectl delete pod luxd-N, wait for 1/1, repeat).

Authorized by 2026-06-02 destructive recovery sweep.
2026-06-02 19:04:53 -07:00
zeekay a0905a4597 dns(lux.network): add 16 brand explorer hosts for testnet+devnet
Adds A records pointing to 134.199.138.27 (lux-k8s hanzoai/ingress LB)
for the 8 brand explorer SPA hosts and 8 backend API hosts that were
declared in k8s/lux-{testnet,devnet}/ingress-chains.yaml but had no
DNS records to back them.

Added (16 total):
  explore-{hanzo,zoo,spc,pars}-{test,dev}.lux.network          (8 SPA)
  api-explore-{hanzo,zoo,spc,pars}-{test,dev}.lux.network      (8 API)

IngressRoutes + explorer Service+Deployment already existed in
lux-testnet and lux-devnet namespaces (mainnet cluster, 84d old).
The unified Go explorer (ghcr.io/luxfi/explorer:1.2.11) was already
indexing all 5 chains per env into per-slug SQLite. The only blocker
was DNS.

Records pushed to Cloudflare zone 287bdfd07cf016bd102f6394892e4759
via global API key (script bash scripts/dns-sync.sh cannot create
new records under the existing API token; used the cloudflare-api-
credentials k8s Secret from lux-system ns).

Verified live (curl --resolve to bypass local resolver lag):
  All 8 SPA hosts: HTTP 200
  All 8 API hosts: HTTP 200 on /stats with real per-chain data
    hanzo-test:  696 blocks, 679 txs
    spc-test:    398 blocks, 394 txs
    pars-test:   381 blocks, 353 txs
    zoo-test:      1 block,    0 txs (chain bootstrapped, no traffic)
    hanzo-dev:     6 blocks,   5 txs
    spc-dev:     165 blocks, 164 txs
    pars-dev:     89 blocks,  86 txs
    zoo-dev:       0 blocks,   0 txs (chain bootstrapped, no traffic)

Sister commit: 18863e19 (mainnet api-explore-* routing).
2026-06-02 18:42:11 -07:00
Hanzo AI 54079a52d8 dns(lux.network): add 16 brand explorer hosts for testnet+devnet
Adds A records pointing to 134.199.138.27 (lux-k8s hanzoai/ingress LB)
for the 8 brand explorer SPA hosts and 8 backend API hosts that were
declared in k8s/lux-{testnet,devnet}/ingress-chains.yaml but had no
DNS records to back them.

Added (16 total):
  explore-{hanzo,zoo,spc,pars}-{test,dev}.lux.network          (8 SPA)
  api-explore-{hanzo,zoo,spc,pars}-{test,dev}.lux.network      (8 API)

IngressRoutes + explorer Service+Deployment already existed in
lux-testnet and lux-devnet namespaces (mainnet cluster, 84d old).
The unified Go explorer (ghcr.io/luxfi/explorer:1.2.11) was already
indexing all 5 chains per env into per-slug SQLite. The only blocker
was DNS.

Records pushed to Cloudflare zone 287bdfd07cf016bd102f6394892e4759
via global API key (script bash scripts/dns-sync.sh cannot create
new records under the existing API token; used the cloudflare-api-
credentials k8s Secret from lux-system ns).

Verified live (curl --resolve to bypass local resolver lag):
  All 8 SPA hosts: HTTP 200
  All 8 API hosts: HTTP 200 on /stats with real per-chain data
    hanzo-test:  696 blocks, 679 txs
    spc-test:    398 blocks, 394 txs
    pars-test:   381 blocks, 353 txs
    zoo-test:      1 block,    0 txs (chain bootstrapped, no traffic)
    hanzo-dev:     6 blocks,   5 txs
    spc-dev:     165 blocks, 164 txs
    pars-dev:     89 blocks,  86 txs
    zoo-dev:       0 blocks,   0 txs (chain bootstrapped, no traffic)

Sister commit: 18863e19 (mainnet api-explore-* routing).
2026-06-02 18:42:11 -07:00
zeekay ebe0012505 #114: scope mainnet luxd-startup upgrade.json to C-Chain only via ConfigMap mount
Split the inline UPGRADE_JSON shell heredoc out of startup.sh into a
dedicated `cchain-upgrade.json` data key in the luxd-startup ConfigMap.
The startup script now cp's /scripts/cchain-upgrade.json to the
C-Chain alias dir only (CHAIN_CONFIG_DIR/C/upgrade.json), removing
the prior loop that overwrote EVERY EVM chain's upgrade.json (incl.
brand L2s like hanzo/zoo/pars/spc which carry their own activations
baked at block 0).

Per Red round-2 review vector 5 (HIGH): overwriting brand L2
upgrade.json with the C-Chain schedule would either be a redundant
no-op or — worse — re-schedule an already-live precompile to a
forward timestamp and brick the chain via
extras.ChainConfig.checkPrecompileCompatible. C-Chain ONLY scope
eliminates the foot-gun.

The embedded cchain-upgrade.json data block is byte-identical
(semantically, modulo whitespace) to luxfi/genesis
configs/mainnet/upgrade.json — sync rule documented in-line.
2026-06-02 18:37:12 -07:00
Hanzo AI c5bbf9f51a #114: scope mainnet luxd-startup upgrade.json to C-Chain only via ConfigMap mount
Split the inline UPGRADE_JSON shell heredoc out of startup.sh into a
dedicated `cchain-upgrade.json` data key in the luxd-startup ConfigMap.
The startup script now cp's /scripts/cchain-upgrade.json to the
C-Chain alias dir only (CHAIN_CONFIG_DIR/C/upgrade.json), removing
the prior loop that overwrote EVERY EVM chain's upgrade.json (incl.
brand L2s like hanzo/zoo/pars/spc which carry their own activations
baked at block 0).

Per Red round-2 review vector 5 (HIGH): overwriting brand L2
upgrade.json with the C-Chain schedule would either be a redundant
no-op or — worse — re-schedule an already-live precompile to a
forward timestamp and brick the chain via
extras.ChainConfig.checkPrecompileCompatible. C-Chain ONLY scope
eliminates the foot-gun.

The embedded cchain-upgrade.json data block is byte-identical
(semantically, modulo whitespace) to luxfi/genesis
configs/mainnet/upgrade.json — sync rule documented in-line.
2026-06-02 18:37:12 -07:00
zeekay 997c8a46a3 lux-devnet: version-control luxd-startup CM, document chain-aliases + L2-config gotchas
The luxd-startup ConfigMap was previously hand-applied to the lux-devnet
namespace (do-sfo3-lux-k8s); pin it here so future reconciles converge.

Two runtime limitations now documented inline:

1. info.isBootstrapped(chain="hanzo"|"zoo"|"pars"|"spc") returns
   "there is no chain with alias/ID 'hanzo'" because the canonical
   chain-aliases.json file trips a json.Unmarshal failure on the
   production luxd v1.28.16 binary (errMissingQuotes from
   ids.ID.UnmarshalJSON). The same 262-byte JSON parses fine in
   local unit tests; production fails. Workaround: omit
   --chain-aliases-file*; chains are reachable via blockchain.name
   so /ext/bc/<brand>/rpc keeps working — only the info.* alias
   lookup is degraded (cosmetic). Tracked in luxfi/ids.

2. Writing bootstrap-l2-chain-configs blobs as ongoing per-chain
   /data/configs/chains/<blockchainID>/config.json triggers
   PANIC in eth.New: triedb parent [...] layer missing. Those
   configs are CreateChainTx-time only. Startup now aggressively
   removes any stale L2 config dirs from previous reconciler runs.

L2 mapping (consistent with chain-aliases CM in this overlay and
luxfi/genesis@06dc203 configs/<brand>-devnet/genesis.json):

  blockchainID                                       brand   chainID
  i3AxuEfLAqzAvabgpYvXC7QCvqXnJAHr3AYiVzfK2FDauyJSa  hanzo   36964
  5YP3iV6ytRjtscF8dcXWQTqd8dwjAaoZnW6oNVfDM3d2mwwvS  zoo     200202
  JxDPdhGde9PSrZ3nLwe7shwZaXEFBoAJ8V9rGqbcKXy9FEQEm  pars    494951
  LHU4rNBLr1Zi2pNJXL47djkCmmyDSgTXmaB4oNQBYyGfqPtg9  spc     36912

Verified end-to-end via luxd-0..3 LBs: eth_chainId returns the
correct chainID per brand and matches luxfi/genesis@06dc203.

Refs #168.
2026-06-02 14:34:59 -07:00
Hanzo AI 39ab41f363 lux-devnet: version-control luxd-startup CM, document chain-aliases + L2-config gotchas
The luxd-startup ConfigMap was previously hand-applied to the lux-devnet
namespace (do-sfo3-lux-k8s); pin it here so future reconciles converge.

Two runtime limitations now documented inline:

1. info.isBootstrapped(chain="hanzo"|"zoo"|"pars"|"spc") returns
   "there is no chain with alias/ID 'hanzo'" because the canonical
   chain-aliases.json file trips a json.Unmarshal failure on the
   production luxd v1.28.16 binary (errMissingQuotes from
   ids.ID.UnmarshalJSON). The same 262-byte JSON parses fine in
   local unit tests; production fails. Workaround: omit
   --chain-aliases-file*; chains are reachable via blockchain.name
   so /ext/bc/<brand>/rpc keeps working — only the info.* alias
   lookup is degraded (cosmetic). Tracked in luxfi/ids.

2. Writing bootstrap-l2-chain-configs blobs as ongoing per-chain
   /data/configs/chains/<blockchainID>/config.json triggers
   PANIC in eth.New: triedb parent [...] layer missing. Those
   configs are CreateChainTx-time only. Startup now aggressively
   removes any stale L2 config dirs from previous reconciler runs.

L2 mapping (consistent with chain-aliases CM in this overlay and
luxfi/genesis@06dc203 configs/<brand>-devnet/genesis.json):

  blockchainID                                       brand   chainID
  i3AxuEfLAqzAvabgpYvXC7QCvqXnJAHr3AYiVzfK2FDauyJSa  hanzo   36964
  5YP3iV6ytRjtscF8dcXWQTqd8dwjAaoZnW6oNVfDM3d2mwwvS  zoo     200202
  JxDPdhGde9PSrZ3nLwe7shwZaXEFBoAJ8V9rGqbcKXy9FEQEm  pars    494951
  LHU4rNBLr1Zi2pNJXL47djkCmmyDSgTXmaB4oNQBYyGfqPtg9  spc     36912

Verified end-to-end via luxd-0..3 LBs: eth_chainId returns the
correct chainID per brand and matches luxfi/genesis@06dc203.

Refs #168.
2026-06-02 14:34:59 -07:00
zeekay 6155179077 explorer: route api-explore-{hanzo,zoo,spc,pars}.lux.network → explorer-unified:8090
Brand explorer API hosts were targeting dead per-brand services
(explorer-{brand}:4000) replaced by unified Go indexer at
explorer-mainnet-v2:8090 (lux-explorer ns). Cross-ns via existing
explorer-unified ExternalName Service in lux-mainnet ns.

Adds brand-prefix middleware chain (mainpage-rewrite +
blockscout-prefix-{brand} + cors-allow-all) so unified backend
dispatches to per-slug SQLite via /v1/indexer/{brand} prefix —
same pattern as lux-explorer/lux-explorer-mainnet-chains for X/P/D.

Verified: api-explore-hanzo.lux.network now hits unified backend
(content-security-policy header present); 404 on /v1/indexer/hanzo
expected until per-brand indexer pods come up (chain-layer work).
2026-06-02 14:25:51 -07:00
Hanzo Dev 18863e1976 explorer: route api-explore-{hanzo,zoo,spc,pars}.lux.network → explorer-unified:8090
Brand explorer API hosts were targeting dead per-brand services
(explorer-{brand}:4000) replaced by unified Go indexer at
explorer-mainnet-v2:8090 (lux-explorer ns). Cross-ns via existing
explorer-unified ExternalName Service in lux-mainnet ns.

Adds brand-prefix middleware chain (mainpage-rewrite +
blockscout-prefix-{brand} + cors-allow-all) so unified backend
dispatches to per-slug SQLite via /v1/indexer/{brand} prefix —
same pattern as lux-explorer/lux-explorer-mainnet-chains for X/P/D.

Verified: api-explore-hanzo.lux.network now hits unified backend
(content-security-policy header present); 404 on /v1/indexer/hanzo
expected until per-brand indexer pods come up (chain-layer work).
2026-06-02 14:25:51 -07:00
zeekay a98cd782f0 explorer: fix pars frontend-config — chainId 494949→7070, RPC → live blockchainID
Aligns frontend-config-pars with canonical pars-mainnet values:
- NETWORK_ID: 494949 → 7070 (LP-182, matches lux-mainnet/explorer.yaml)
- RPC_URL blockchainID: 2pUsk… → 2wYWj… (live, per lux-mainnet/chain-aliases CM)

Cross-referenced lux-mainnet/chain-aliases ConfigMap (live in cluster):
  '2wYWjBHziTjfMJmUPZwsDdWhm96cWHo4vov1HPBmCYLXdbAZfM': ['pars']
2026-06-02 14:25:36 -07:00
Hanzo Dev 215e679148 explorer: fix pars frontend-config — chainId 494949→7070, RPC → live blockchainID
Aligns frontend-config-pars with canonical pars-mainnet values:
- NETWORK_ID: 494949 → 7070 (LP-182, matches lux-mainnet/explorer.yaml)
- RPC_URL blockchainID: 2pUsk… → 2wYWj… (live, per lux-mainnet/chain-aliases CM)

Cross-referenced lux-mainnet/chain-aliases ConfigMap (live in cluster):
  '2wYWjBHziTjfMJmUPZwsDdWhm96cWHo4vov1HPBmCYLXdbAZfM': ['pars']
2026-06-02 14:25:36 -07:00
zeekay afbc3facab explorer: delete stale lux-explorer/explorer-chains CM
Duplicates lux-mainnet/explorer-chains with wrong pars chainId 494949
(canonical: 7070) and stale blockchainID. Unmounted — lux-explorer ns
has no pods, only routing layer. Single source of truth now
lux-mainnet/explorer-chains (consumed by explorer Deployment in
lux-mainnet).
2026-06-02 14:25:23 -07:00
Hanzo Dev c1a711d903 explorer: delete stale lux-explorer/explorer-chains CM
Duplicates lux-mainnet/explorer-chains with wrong pars chainId 494949
(canonical: 7070) and stale blockchainID. Unmounted — lux-explorer ns
has no pods, only routing layer. Single source of truth now
lux-mainnet/explorer-chains (consumed by explorer Deployment in
lux-mainnet).
2026-06-02 14:25:23 -07:00
zeekay b8f26df495 universe(test+dev): register 4 brand L2 chains on fresh primaries (closes #168)
CreateChainTx fired on testnet + devnet P-chains for all 4 brand L2 EVMs
(hanzo / zoo / spc / pars) — 8 chains total, all isBootstrapped=true on
all 3 pods per env (24/24 verified). Each chain uses the canonical EVM
plugin (vmID mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6) and its
own per-chain validator-network (CreateNetworkTx ID, L2-anchor pattern).
All 5 primary validators added as chain validators via
IssueAddChainValidatorTx.

EVM chain IDs match the LP-182 canonical map per (brand, env):
  hanzo: test=36962 dev=36964
  zoo  : test=200201 dev=200202
  spc  : test=36910 dev=36912
  pars : test=494950 dev=494951

Required a second wipe-and-rebootstrap of both primaries because #186's
fresh genesis funded all 50T LUX into the validator stake (zero spendable
P-chain balance for the deployer). Added a 6th allocation per genesis (a
deterministic SHA-256 deployer key — 100K LUX spendable, NOT in
initialStakedFunds). Reapplied lux-{testnet,devnet}-genesis ConfigMap,
scaled luxd StatefulSet 3→0→3, P + C re-bootstrapped in ~75s on all pods.
Snapshots from #186 retained (data-luxd-{0..2}-20260602).

Inventory committed at
k8s/lux-{test,dev}-k8s/{testnet,devnet}/chains-inventory.json (8 chains:
blockchainID + per-chain networkID + evmChainID + bootstrap timestamps).
chain-aliases ConfigMap committed for each env mapping
brand-name → blockchainID for operator + gateway convenience.

Tool used: ~/work/lux/genesis/cmd/bootstrap-chain (lux/genesis@HEAD —
adds --key-file flag) against ~/work/lux/node/wallet/network/primary
(lux/node@HEAD — fail-soft FetchState when X-Chain disabled).

Followups:
- Roll block 1 on each L2 (eth_blockNumber > 0) via heartbeat tx when
  downstream contract deploys land.
- Update lux-gateway/gateway.yaml routing for /testnet/* and /devnet/*
  paths to point at the new lux-{test,dev}-k8s namespaces (currently
  still routes to legacy lux-testnet/lux-devnet namespaces).
- Migrate ~/work/lux/keys/deployer-test-dev/private.key to KMS once
  kms-operator is deployed in test+dev clusters.
2026-06-02 13:49:37 -07:00
Hanzo AI fb366acf1a universe(test+dev): register 4 brand L2 chains on fresh primaries (closes #168)
CreateChainTx fired on testnet + devnet P-chains for all 4 brand L2 EVMs
(hanzo / zoo / spc / pars) — 8 chains total, all isBootstrapped=true on
all 3 pods per env (24/24 verified). Each chain uses the canonical EVM
plugin (vmID mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6) and its
own per-chain validator-network (CreateNetworkTx ID, L2-anchor pattern).
All 5 primary validators added as chain validators via
IssueAddChainValidatorTx.

EVM chain IDs match the LP-182 canonical map per (brand, env):
  hanzo: test=36962 dev=36964
  zoo  : test=200201 dev=200202
  spc  : test=36910 dev=36912
  pars : test=494950 dev=494951

Required a second wipe-and-rebootstrap of both primaries because #186's
fresh genesis funded all 50T LUX into the validator stake (zero spendable
P-chain balance for the deployer). Added a 6th allocation per genesis (a
deterministic SHA-256 deployer key — 100K LUX spendable, NOT in
initialStakedFunds). Reapplied lux-{testnet,devnet}-genesis ConfigMap,
scaled luxd StatefulSet 3→0→3, P + C re-bootstrapped in ~75s on all pods.
Snapshots from #186 retained (data-luxd-{0..2}-20260602).

Inventory committed at
k8s/lux-{test,dev}-k8s/{testnet,devnet}/chains-inventory.json (8 chains:
blockchainID + per-chain networkID + evmChainID + bootstrap timestamps).
chain-aliases ConfigMap committed for each env mapping
brand-name → blockchainID for operator + gateway convenience.

Tool used: ~/work/lux/genesis/cmd/bootstrap-chain (lux/genesis@HEAD —
adds --key-file flag) against ~/work/lux/node/wallet/network/primary
(lux/node@HEAD — fail-soft FetchState when X-Chain disabled).

Followups:
- Roll block 1 on each L2 (eth_blockNumber > 0) via heartbeat tx when
  downstream contract deploys land.
- Update lux-gateway/gateway.yaml routing for /testnet/* and /devnet/*
  paths to point at the new lux-{test,dev}-k8s namespaces (currently
  still routes to legacy lux-testnet/lux-devnet namespaces).
- Migrate ~/work/lux/keys/deployer-test-dev/private.key to KMS once
  kms-operator is deployed in test+dev clusters.
2026-06-02 13:49:37 -07:00
zeekay 2fadd4fb18 runners: mark DOKS ARC retired, pointer to canonical arcd fleet
luxfi now served by host-level arcd daemons (dbc Mac + evo WSL +
evo Windows) alongside hanzoai, zooai, parsdao, zenlm. See
hanzoai/universe/infra/runners/README.md for the fleet topology.
2026-06-02 13:46:28 -07:00
Hanzo AI b15bdea806 runners: mark DOKS ARC retired, pointer to canonical arcd fleet
luxfi now served by host-level arcd daemons (dbc Mac + evo WSL +
evo Windows) alongside hanzoai, zooai, parsdao, zenlm. See
hanzoai/universe/infra/runners/README.md for the fleet topology.
2026-06-02 13:46:28 -07:00
zeekay 3710b6408e universe(test+dev): fresh-bootstrap lux primary via new BLS keys + matching genesis (closes #186)
2026-06-02 — Both test+dev primaries were wedged for 10 days (BLS key in Secret
didn't match validator-set BLS pubkey on chain → 0 peers, P-chain unreachable).

Fix:
- Generated 5 fresh validator keypairs (staker cert + BLS signer.key) via canonical
  local 5-validator pattern. luxd-0..2 are active (replicas=3); 3+4 staged for grow.
- Built matching primary network genesis with these validators in initialStakers
  (with BLS pubkey + PoP) and seeded treasury.
- Replaced cluster Secret luxd-staking + ConfigMap lux-{testnet,devnet}-genesis.
- Wiped 3× 200Gi PVCs per env (snapshots taken 2026-06-02 first as safety net).
- Restarted StatefulSets → fresh consensus quorum, P-chain bootstrapped block 0,
  C-Chain followed via canonical chain config from configs/{net}/cchain.json.
- Devnet startup script previously had hardcoded --track-chains=<old-L2-id>;
  patched cluster CM to --track-all-chains=true (track everything registered on
  the L1, no manual chain-id pin).

Live verification:
  do-sfo3-lux-k8s     /lux-mainnet :9630  P=True C=True  (preserved untouched)
  do-sfo3-lux-test-k8s/testnet     :9650  P=True C=True  (fresh)
  do-sfo3-lux-dev-k8s /devnet      :9650  P=True C=True  (fresh)

Snapshot path: PVC VolumeSnapshots `data-luxd-{0..2}-20260602` per env retain
the wedged state forensically for the next 7 days.

Followups (separate tasks):
- Brand L2 chain CreateChainTx on test+dev primaries (hanzo/zoo/spc/pars per
  chainID map) — driving next.
- kms-operator deployment in test+dev clusters → migrate file-on-disk
  node{0..2}/ keys to KMS-stored per-env validator mnemonics.

Gotchas documented in LLM.md "Fresh-bootstrap primary (testnet + devnet) — 2026-06-02".
2026-06-02 12:00:28 -07:00
Hanzo AI f80953f05c universe(test+dev): fresh-bootstrap lux primary via new BLS keys + matching genesis (closes #186)
2026-06-02 — Both test+dev primaries were wedged for 10 days (BLS key in Secret
didn't match validator-set BLS pubkey on chain → 0 peers, P-chain unreachable).

Fix:
- Generated 5 fresh validator keypairs (staker cert + BLS signer.key) via canonical
  local 5-validator pattern. luxd-0..2 are active (replicas=3); 3+4 staged for grow.
- Built matching primary network genesis with these validators in initialStakers
  (with BLS pubkey + PoP) and seeded treasury.
- Replaced cluster Secret luxd-staking + ConfigMap lux-{testnet,devnet}-genesis.
- Wiped 3× 200Gi PVCs per env (snapshots taken 2026-06-02 first as safety net).
- Restarted StatefulSets → fresh consensus quorum, P-chain bootstrapped block 0,
  C-Chain followed via canonical chain config from configs/{net}/cchain.json.
- Devnet startup script previously had hardcoded --track-chains=<old-L2-id>;
  patched cluster CM to --track-all-chains=true (track everything registered on
  the L1, no manual chain-id pin).

Live verification:
  do-sfo3-lux-k8s     /lux-mainnet :9630  P=True C=True  (preserved untouched)
  do-sfo3-lux-test-k8s/testnet     :9650  P=True C=True  (fresh)
  do-sfo3-lux-dev-k8s /devnet      :9650  P=True C=True  (fresh)

Snapshot path: PVC VolumeSnapshots `data-luxd-{0..2}-20260602` per env retain
the wedged state forensically for the next 7 days.

Followups (separate tasks):
- Brand L2 chain CreateChainTx on test+dev primaries (hanzo/zoo/spc/pars per
  chainID map) — driving next.
- kms-operator deployment in test+dev clusters → migrate file-on-disk
  node{0..2}/ keys to KMS-stored per-env validator mnemonics.

Gotchas documented in LLM.md "Fresh-bootstrap primary (testnet + devnet) — 2026-06-02".
2026-06-02 12:00:28 -07:00
zeekay 404d86e54c k8s/lux-mainnet: bump luxd v1.28.16 → v1.28.18 (fresh-L2 chain-create fix)
v1.28.18 ships EVM plugin v0.18.18, which fixes the
"panic in eth.New: triedb parent [<EmptyRootHash>] layer missing" wedge
on freshly-provisioned L2 EVM chains (hanzo, zoo, spc, pars). Root cause
is plugin/evm/vm.go letting eth/backend.go inherit geth's path-by-default
on empty DBs while simultaneously hard-refusing path mode upfront —
detail in evm@1dea806f8 (v0.18.18). The fix locks the operator-empty
StateScheme to HashScheme before backend.go can pick "path".
2026-06-02 11:57:35 -07:00
Hanzo AI a85aacac0c k8s/lux-mainnet: bump luxd v1.28.16 → v1.28.18 (fresh-L2 chain-create fix)
v1.28.18 ships EVM plugin v0.18.18, which fixes the
"panic in eth.New: triedb parent [<EmptyRootHash>] layer missing" wedge
on freshly-provisioned L2 EVM chains (hanzo, zoo, spc, pars). Root cause
is plugin/evm/vm.go letting eth/backend.go inherit geth's path-by-default
on empty DBs while simultaneously hard-refusing path mode upfront —
detail in evm@1dea806f8 (v0.18.18). The fix locks the operator-empty
StateScheme to HashScheme before backend.go can pick "path".
2026-06-02 11:57:35 -07:00
zeekay 60c05f9ce7 fix: gofmt -s across repo (CI format check) 2026-06-02 11:40:01 -07:00
Hanzo AI 2a7401179b fix: gofmt -s across repo (CI format check) 2026-06-02 11:40:01 -07:00
zeekay 2cdb82c840 compose+docs: replace deprecated --track-subnets with --track-chains
luxd v1.24+ removed --track-subnets in favor of --track-chains (the
flag accepts both chain and blockchain IDs). compose.local.yml was
still passing the dead flag; switching to --track-chains=all preserves
behavior.

docs/PRODUCTION.md: rewrite stale ./wallet/network/primary/examples/
deploy-subnets/ paths to deploy-chains/ which is the actual example
directory in luxfi/node.
2026-06-02 11:23:28 -07:00
Hanzo AI cbfc4b71b5 compose+docs: replace deprecated --track-subnets with --track-chains
luxd v1.24+ removed --track-subnets in favor of --track-chains (the
flag accepts both chain and blockchain IDs). compose.local.yml was
still passing the dead flag; switching to --track-chains=all preserves
behavior.

docs/PRODUCTION.md: rewrite stale ./wallet/network/primary/examples/
deploy-subnets/ paths to deploy-chains/ which is the actual example
directory in luxfi/node.
2026-06-02 11:23:28 -07:00
zeekay c7f64a18b3 phase-a: lux.network/v1alpha1 → lux.cloud/v1 migration scaffolding
Phase A status: BLOCKED on luxfi/operator v0.6.3 + v0.7.0 binaries
(see luxfi/operator d2ecca5 — duplicate Network reconciler
registration makes both crashloop at startup). Cluster rolled back
to v0.3.12 on lux.network/v1alpha1 reconcile, all 3 chains 5/5
healthy.

What this commit lays down for the next attempt (once a v0.6.4 or
v0.7.1 image ships with the operator fix):

- `scripts/migrate-luxnetwork-crds.sh <ctx>` — race-clean CR
  migration script. Walks lux.network/v1alpha1 LuxNetwork,
  LuxChain, LuxGateway, LuxIndexer, LuxExplorer, LuxMPC CRs,
  apiVersion-swaps each to lux.cloud/v1 (dropping the Lux
  prefix on every Kind except LuxNetwork which v0.6.x also
  calls LuxNetwork in the canonical group). Spec/status pass
  through opaque — both CRDs use
  x-kubernetes-preserve-unknown-fields: true. Strips server-side
  metadata. Idempotent.
- `k8s/backups/pre-phase-a-20260602-020926/` — full live state
  snapshot for the 3 DOKS lux clusters, captured BEFORE any
  in-cluster mutation. Used to verify migration and as the rollback
  source if the next attempt needs to re-restore CRs.
- `k8s/PHASE_A_ROLLBACK.md` — step-by-step rollback procedure.

Inventory (lux-k8s only — test-k8s / dev-k8s have zero lux CRs):
- 3 LuxNetworks (luxnetworks.lux.network) — mainnet/testnet/devnet luxd
- 11 LuxChains (luxchains.lux.network) — mainnet a/b/d/g/i/k/m/o/q/r/z
- 3 LuxGateways (luxgateways.lux.network) — */api-gateway
- 1 LuxMPC (luxmpcs.lux.network) — mainnet/lux-mpc
- 0 LuxIndexers, 0 LuxExplorers

In-cluster prep that survived rollback:
- lux.cloud/v1 CRDs installed alongside lux.network/v1alpha1 (idempotent
  apply of `~/work/lux/operator/spec/crd/bases/lux.cloud/`).
- Migrated lux.cloud/v1 CRs already created (apply succeeded, no
  controller bound — inert until v0.6.4+ operator ships).

Next attempt blocked on:
1. CI build of v0.6.4 or v0.7.1 operator image with luxfi/operator
   d2ecca5 fix (push triggers via `hanzo-build-linux-amd64` ARC pool).
2. Bump `k8s/lux-k8s/operator/deployment.yaml` image tag.
3. Re-run scale-down → image-bump → scale-up cycle.

Forward-only, no AI slop, no API breakage, current chains stay alive
during entire procedure.
2026-06-02 02:22:54 -07:00
Hanzo AI 108e47bc38 phase-a: lux.network/v1alpha1 → lux.cloud/v1 migration scaffolding
Phase A status: BLOCKED on luxfi/operator v0.6.3 + v0.7.0 binaries
(see luxfi/operator d2ecca5 — duplicate Network reconciler
registration makes both crashloop at startup). Cluster rolled back
to v0.3.12 on lux.network/v1alpha1 reconcile, all 3 chains 5/5
healthy.

What this commit lays down for the next attempt (once a v0.6.4 or
v0.7.1 image ships with the operator fix):

- `scripts/migrate-luxnetwork-crds.sh <ctx>` — race-clean CR
  migration script. Walks lux.network/v1alpha1 LuxNetwork,
  LuxChain, LuxGateway, LuxIndexer, LuxExplorer, LuxMPC CRs,
  apiVersion-swaps each to lux.cloud/v1 (dropping the Lux
  prefix on every Kind except LuxNetwork which v0.6.x also
  calls LuxNetwork in the canonical group). Spec/status pass
  through opaque — both CRDs use
  x-kubernetes-preserve-unknown-fields: true. Strips server-side
  metadata. Idempotent.
- `k8s/backups/pre-phase-a-20260602-020926/` — full live state
  snapshot for the 3 DOKS lux clusters, captured BEFORE any
  in-cluster mutation. Used to verify migration and as the rollback
  source if the next attempt needs to re-restore CRs.
- `k8s/PHASE_A_ROLLBACK.md` — step-by-step rollback procedure.

Inventory (lux-k8s only — test-k8s / dev-k8s have zero lux CRs):
- 3 LuxNetworks (luxnetworks.lux.network) — mainnet/testnet/devnet luxd
- 11 LuxChains (luxchains.lux.network) — mainnet a/b/d/g/i/k/m/o/q/r/z
- 3 LuxGateways (luxgateways.lux.network) — */api-gateway
- 1 LuxMPC (luxmpcs.lux.network) — mainnet/lux-mpc
- 0 LuxIndexers, 0 LuxExplorers

In-cluster prep that survived rollback:
- lux.cloud/v1 CRDs installed alongside lux.network/v1alpha1 (idempotent
  apply of `~/work/lux/operator/spec/crd/bases/lux.cloud/`).
- Migrated lux.cloud/v1 CRs already created (apply succeeded, no
  controller bound — inert until v0.6.4+ operator ships).

Next attempt blocked on:
1. CI build of v0.6.4 or v0.7.1 operator image with luxfi/operator
   d2ecca5 fix (push triggers via `hanzo-build-linux-amd64` ARC pool).
2. Bump `k8s/lux-k8s/operator/deployment.yaml` image tag.
3. Re-run scale-down → image-bump → scale-up cycle.

Forward-only, no AI slop, no API breakage, current chains stay alive
during entire procedure.
2026-06-02 02:22:54 -07:00
zeekay 78be703f9c k8s: bump all 3 lux nets to luxd v1.28.16 (EVM v0.18.16 PQ gate fix)
v1.28.16 = v1.28.15 + Dockerfile EVM_VERSION bump only. luxfi/evm v0.18.16
fixes the nil-chainConfig panic at the PQ gate: vm.chainConfig.PQ was set
BEFORE vm.chainConfig was assigned from g.Config, panic on dereference.
Repro path is fresh-PVC bootstrap with chain-config.json pq:true causing
"panic in eth.New: ... triedb parent ... layer missing" — exactly the
wedge currently blocking lux-mainnet C-Chain.

Files touched (one canonical pin per net):
  k8s/lux-mainnet/network.yaml          v1.28.15 -> v1.28.16
  k8s/lux-testnet/network.yaml          v1.23.31 -> v1.28.16 (manifest was
                                         stale; live pods on v1.28.7)
  k8s/lux-devnet/network.yaml           v1.28.15 -> v1.28.16
  k8s/lux-k8s/validators/statefulset.yaml  3x v1.28.7 -> v1.28.16
  k8s/lux-test-k8s/testnet/statefulset.yaml  2x v1.28.7 -> v1.28.16

Note: operator on lux-k8s is v0.3.12 (manifest pins v0.6.3 but cluster
has not been reconciled). v0.3.12 does NOT reconcile spec.image.tag on
LuxNetwork CRs, so a CR-only apply will not change running pods. Direct
StatefulSet patch or operator bump is needed to actually roll forward.
2026-06-02 02:05:35 -07:00
Hanzo AI 517e6b987c k8s: bump all 3 lux nets to luxd v1.28.16 (EVM v0.18.16 PQ gate fix)
v1.28.16 = v1.28.15 + Dockerfile EVM_VERSION bump only. luxfi/evm v0.18.16
fixes the nil-chainConfig panic at the PQ gate: vm.chainConfig.PQ was set
BEFORE vm.chainConfig was assigned from g.Config, panic on dereference.
Repro path is fresh-PVC bootstrap with chain-config.json pq:true causing
"panic in eth.New: ... triedb parent ... layer missing" — exactly the
wedge currently blocking lux-mainnet C-Chain.

Files touched (one canonical pin per net):
  k8s/lux-mainnet/network.yaml          v1.28.15 -> v1.28.16
  k8s/lux-testnet/network.yaml          v1.23.31 -> v1.28.16 (manifest was
                                         stale; live pods on v1.28.7)
  k8s/lux-devnet/network.yaml           v1.28.15 -> v1.28.16
  k8s/lux-k8s/validators/statefulset.yaml  3x v1.28.7 -> v1.28.16
  k8s/lux-test-k8s/testnet/statefulset.yaml  2x v1.28.7 -> v1.28.16

Note: operator on lux-k8s is v0.3.12 (manifest pins v0.6.3 but cluster
has not been reconciled). v0.3.12 does NOT reconcile spec.image.tag on
LuxNetwork CRs, so a CR-only apply will not change running pods. Direct
StatefulSet patch or operator bump is needed to actually roll forward.
2026-06-02 02:05:35 -07:00
zeekay 09a6765701 k8s: bump lux-mainnet + lux-devnet to luxd v1.28.15 (closure swarm)
Pins ghcr.io/luxfi/node:v1.28.15:
  - consensus v1.25.13 (gofmt + accel v1.1.8 + magnetar v1.2.0
    PVSS-DKG)
  - threshold v1.9.7 (slhdsa-tee + accel v1.1.8)
  - magnetar v1.2.0 (dealerless PVSS-DKG)
  - pulsar v1.1.2 (canonical wire codec + jasmin CI deps)
  - keys v1.1.0 (BBF hybrid secp256k1+ML-DSA-65 signature)
  - kms v1.11.2 (anti-replay nonce ledger + vendor-safe accel header)
  - accel v1.1.8 (//go:embed c_api.h — vendor-safe header)
  - corona v0.7.6

NO weird compat tag (dropped v1.28.7-corona-v0.7.6 + v1.25.5-corona-v0.7.6
upstream). Coordinated full-network restart per
~/work/lux/migration/LLM.md Step 5: STOP all 5 luxd pods, swap image
to v1.28.15, START all 5 simultaneously. Brief outage, clean upgrade.

Lux-testnet remains pinned at v1.23.31 per
~/.claude/projects/-Users-z-work-hanzo/memory/luxd_runtime_env_rename.md
— v1.27.x ships mid-rename of VM_RUNTIME_ENGINE_ADDR.
2026-06-02 02:05:35 -07:00
Hanzo AI 5fe08ef6fa k8s: bump lux-mainnet + lux-devnet to luxd v1.28.15 (closure swarm)
Pins ghcr.io/luxfi/node:v1.28.15:
  - consensus v1.25.13 (gofmt + accel v1.1.8 + magnetar v1.2.0
    PVSS-DKG)
  - threshold v1.9.7 (slhdsa-tee + accel v1.1.8)
  - magnetar v1.2.0 (dealerless PVSS-DKG)
  - pulsar v1.1.2 (canonical wire codec + jasmin CI deps)
  - keys v1.1.0 (BBF hybrid secp256k1+ML-DSA-65 signature)
  - kms v1.11.2 (anti-replay nonce ledger + vendor-safe accel header)
  - accel v1.1.8 (//go:embed c_api.h — vendor-safe header)
  - corona v0.7.6

NO weird compat tag (dropped v1.28.7-corona-v0.7.6 + v1.25.5-corona-v0.7.6
upstream). Coordinated full-network restart per
~/work/lux/migration/LLM.md Step 5: STOP all 5 luxd pods, swap image
to v1.28.15, START all 5 simultaneously. Brief outage, clean upgrade.

Lux-testnet remains pinned at v1.23.31 per
~/.claude/projects/-Users-z-work-hanzo/memory/luxd_runtime_env_rename.md
— v1.27.x ships mid-rename of VM_RUNTIME_ENGINE_ADDR.
2026-06-02 02:05:35 -07:00
zeekay 8436464e6a lux-mainnet: revive C-Chain + L1 EVMs via genesis field rename + track-chains
Three independent fixes wedged together unblock 5 of 7 mainnet chains:

1. genesis.json alloc field names ethAddr/luxAddr → evmAddr/utxoAddr.
   luxd v1.28.7 uses luxfi/genesis v1.12.19+ which requires the canonical
   names. The embedded base64 blob is the source of truth for amounts
   and addresses — a sed translates field names in-place post-decode.
   Idempotent.

2. track-chains adds C-Chain's content-derived blockchain ID
   (9SUt666By9zgBK2PUw6scnsW1xHCCEuFVNT6HkjTK6mHGeENG, computed by
   migrateNewGenesisChains from the cChainGenesis blob in P-Chain
   genesis). Without this the SybilProtection gate in
   platformvm/config/internal.go.CreateChain silently drops C-Chain
   even though it is in P-Chain state.

3. tenant-import loop sentinels only on curl success (rc=0). The prior
   unconditional touch/rm-marker consumed markers on transient failures
   (luxd not ready, plugin missing, chain not registered) and left the
   import un-applied with no retry. Now failed imports preserve the
   marker for the next reconcile.

State after deploy:
  P-Chain: bootstrapped (preserved h~260, sybil-protected, never wiped)
  C-Chain: live at h=0 (new genesis, RLP replay blocked by genesis
           hash mismatch with archival snapshot — separate task)
  Hanzo L1 EVM: alive at h=0 after per-chain DB wipe
  Zoo L1 EVM: preserved at h=799 (RLP-imported, untouched)
  Pars/SPC L1 EVMs: wedged on shared EVM triedb cache (orphan refs
                    persist after chainData wipe — separate task)
  X-Chain: P-only mode by design (XChainGenesis empty in mainnet genesis)
2026-06-01 18:29:50 -07:00
Hanzo AI 4cc4b26c05 lux-mainnet: revive C-Chain + L1 EVMs via genesis field rename + track-chains
Three independent fixes wedged together unblock 5 of 7 mainnet chains:

1. genesis.json alloc field names ethAddr/luxAddr → evmAddr/utxoAddr.
   luxd v1.28.7 uses luxfi/genesis v1.12.19+ which requires the canonical
   names. The embedded base64 blob is the source of truth for amounts
   and addresses — a sed translates field names in-place post-decode.
   Idempotent.

2. track-chains adds C-Chain's content-derived blockchain ID
   (9SUt666By9zgBK2PUw6scnsW1xHCCEuFVNT6HkjTK6mHGeENG, computed by
   migrateNewGenesisChains from the cChainGenesis blob in P-Chain
   genesis). Without this the SybilProtection gate in
   platformvm/config/internal.go.CreateChain silently drops C-Chain
   even though it is in P-Chain state.

3. tenant-import loop sentinels only on curl success (rc=0). The prior
   unconditional touch/rm-marker consumed markers on transient failures
   (luxd not ready, plugin missing, chain not registered) and left the
   import un-applied with no retry. Now failed imports preserve the
   marker for the next reconcile.

State after deploy:
  P-Chain: bootstrapped (preserved h~260, sybil-protected, never wiped)
  C-Chain: live at h=0 (new genesis, RLP replay blocked by genesis
           hash mismatch with archival snapshot — separate task)
  Hanzo L1 EVM: alive at h=0 after per-chain DB wipe
  Zoo L1 EVM: preserved at h=799 (RLP-imported, untouched)
  Pars/SPC L1 EVMs: wedged on shared EVM triedb cache (orphan refs
                    persist after chainData wipe — separate task)
  X-Chain: P-only mode by design (XChainGenesis empty in mainnet genesis)
2026-06-01 18:29:50 -07:00
zeekay dab9c748ea lux-mainnet: rip sentinel-v-suffix kludge, content-hash tenant-imports
luxd-startup.yaml drops the hardcoded c-chain (.cchain_rlp_imported_v4)
and zoo (.zoo_rlp_imported_v1) blocks. Replaced with a generic loop
over operator-written JSON request markers at
/data/db/.tenant-import-request-*.json. The loop parses chainAlias,
rlpPath, and sentinelPath out of each marker, calls admin_importChain,
touches the sentinel, removes the marker. Zero hardcoded tenant names.

network.yaml adds C-Chain to tenantImports[] alongside Zoo, with
chainAlias on each (required by luxfi/operator v0.7.0).

Pairs with luxfi/[email protected]: spec change → new content hash →
operator emits new request marker → loop re-fires → fresh sentinel.
Re-firing after a fix is automatic. No version-string bumping.
2026-06-01 16:59:42 -07:00
Hanzo AI e03cd81e19 lux-mainnet: rip sentinel-v-suffix kludge, content-hash tenant-imports
luxd-startup.yaml drops the hardcoded c-chain (.cchain_rlp_imported_v4)
and zoo (.zoo_rlp_imported_v1) blocks. Replaced with a generic loop
over operator-written JSON request markers at
/data/db/.tenant-import-request-*.json. The loop parses chainAlias,
rlpPath, and sentinelPath out of each marker, calls admin_importChain,
touches the sentinel, removes the marker. Zero hardcoded tenant names.

network.yaml adds C-Chain to tenantImports[] alongside Zoo, with
chainAlias on each (required by luxfi/operator v0.7.0).

Pairs with luxfi/[email protected]: spec change → new content hash →
operator emits new request marker → loop re-fires → fresh sentinel.
Re-firing after a fix is automatic. No version-string bumping.
2026-06-01 16:59:42 -07:00
zeekay 0d4db8216f bump: luxd 1.27.4/v1.27.27→v1.28.7 (all 3 networks), lux kms 1.9.9→1.9.11
luxd v1.28.7 (luxfi/node@6564bf2) consolidates the entire post-rename
plugin family at latest patch:
- consensus  v1.25.7 (race-clean, MAGS/MAGG wire, ZAP keys rehomed)
- threshold  v1.9.0
- pulsar     v1.0.23
- corona     v0.7.6
- magnetar   v1.0.0 (safety-floor — not bumped further; transient-seed gap)
- keys       v1.0.10
- multi-version platformvm codec (v1.28.0+) — both v0 (read) and v1
  (write) codecs registered; devnet/testnet/mainnet all on v1-wire from
  genesis.
- v1.28.7 stale-genesis-cache invalidation fix (PR #126) — config
  parse failures no longer leave a stale cached genesis behind that
  CrashLoops subsequent boots.

Manifests bumped:
- lux-mainnet/network.yaml: 1.27.4 → v1.28.7
- lux-k8s/validators/statefulset.yaml: mainnet+testnet 1.27.4 → v1.28.7,
  devnet v1.27.27 → v1.28.7
- lux-test-k8s/testnet/statefulset.yaml: 1.27.4 → v1.28.7
- lux-devnet/luxd-genesis.yaml annotation: v1.27.23 → v1.28.7
- lux-kms-go/deployment.yaml: ghcr.io/luxfi/kms:1.9.9 → 1.9.11

NOT bumped (per CLAUDE.md constraints):
- luxfi/operator (lux-k8s/operator/deployment.yaml): stays v0.3.12.
  v0.6.2 image build broken (#117); reconciler #119 incomplete.
- luxfi/magnetar: stays v1.0.0 (transient-seed safety floor).
- luxfi/node devnet chain-aliases annotation: stays v1.28.0
  (historical rebuild marker, not a current pin).
2026-06-01 16:54:28 -07:00
Hanzo AI db158cbb7b bump: luxd 1.27.4/v1.27.27→v1.28.7 (all 3 networks), lux kms 1.9.9→1.9.11
luxd v1.28.7 (luxfi/node@6564bf2) consolidates the entire post-rename
plugin family at latest patch:
- consensus  v1.25.7 (race-clean, MAGS/MAGG wire, ZAP keys rehomed)
- threshold  v1.9.0
- pulsar     v1.0.23
- corona     v0.7.6
- magnetar   v1.0.0 (safety-floor — not bumped further; transient-seed gap)
- keys       v1.0.10
- multi-version platformvm codec (v1.28.0+) — both v0 (read) and v1
  (write) codecs registered; devnet/testnet/mainnet all on v1-wire from
  genesis.
- v1.28.7 stale-genesis-cache invalidation fix (PR #126) — config
  parse failures no longer leave a stale cached genesis behind that
  CrashLoops subsequent boots.

Manifests bumped:
- lux-mainnet/network.yaml: 1.27.4 → v1.28.7
- lux-k8s/validators/statefulset.yaml: mainnet+testnet 1.27.4 → v1.28.7,
  devnet v1.27.27 → v1.28.7
- lux-test-k8s/testnet/statefulset.yaml: 1.27.4 → v1.28.7
- lux-devnet/luxd-genesis.yaml annotation: v1.27.23 → v1.28.7
- lux-kms-go/deployment.yaml: ghcr.io/luxfi/kms:1.9.9 → 1.9.11

NOT bumped (per CLAUDE.md constraints):
- luxfi/operator (lux-k8s/operator/deployment.yaml): stays v0.3.12.
  v0.6.2 image build broken (#117); reconciler #119 incomplete.
- luxfi/magnetar: stays v1.0.0 (transient-seed safety floor).
- luxfi/node devnet chain-aliases annotation: stays v1.28.0
  (historical rebuild marker, not a current pin).
2026-06-01 16:54:28 -07:00
zeekay 65b76dd424 lux-k8s/operator: align manifest with v0.6.3 reality (name + args + RBAC)
The previous commit bumped the image tag from v0.3.12 → v0.6.3 but
left three other surfaces stale, any of which would have crashlooped
the pod on `kubectl apply`:

1. Deployment name. YAML said `metadata.name: operator` but the
   cluster's actual deployment is `lux-operator`. `kubectl apply -f
   deployment.yaml` would have created a parallel `operator`
   Deployment alongside the running `lux-operator`, never updating
   the running one. Fixed: rename to `lux-operator` to match the
   cluster.

2. Flag surface. v0.6.3 (go/cmd/operator/main.go) takes
   --api-group / --namespace / --operator-namespace /
   --metrics-bind-address / --health-probe-bind-address /
   --leader-elect / --leader-election-id. v0.3.x took
   --log-level / --metrics-port / --health-port / --leader-election.
   None of the v0.3.x flags exist in v0.6.3 — pflag.Parse would
   error and the pod would crashloop. Args rewritten to the
   v0.6.3 surface.

3. ClusterRole. v0.3.x used `apiGroups: ["lux.network"]` with
   prefixed plurals (luxchains, luxindexers, luxexplorers,
   luxgateways). v0.6.3 canonical group is `lux.cloud` (see
   api/v1/groupversion_info.go DefaultGroup) with unprefixed
   plurals (chains, networks, validators, etc.). The CRD list
   matches the 20 canonical kinds + Network/LuxNetwork emitted
   by cmd/generate-crd-yaml at HEAD. Also added `leases` /
   `serviceaccounts` / Rbac for the controllers that need them.

Other deltas:
- Added `imagePullSecrets: [{name: ghcr-luxfi}]` (cluster already has
  the secret, age 96d; the previous YAML relied on the cluster
  having a node-level credential which works today but is brittle).
- `imagePullPolicy: IfNotPresent` (was implicit; explicit is better
  for semver-pinned tags — no need to re-pull when the same digest
  is already present).

Post-apply readiness probe:
  kubectl --context=do-sfo3-lux-k8s -n lux-system rollout status \
    deploy/lux-operator --timeout=180s
2026-06-01 16:46:11 -07:00
Hanzo AI 0dce847992 lux-k8s/operator: align manifest with v0.6.3 reality (name + args + RBAC)
The previous commit bumped the image tag from v0.3.12 → v0.6.3 but
left three other surfaces stale, any of which would have crashlooped
the pod on `kubectl apply`:

1. Deployment name. YAML said `metadata.name: operator` but the
   cluster's actual deployment is `lux-operator`. `kubectl apply -f
   deployment.yaml` would have created a parallel `operator`
   Deployment alongside the running `lux-operator`, never updating
   the running one. Fixed: rename to `lux-operator` to match the
   cluster.

2. Flag surface. v0.6.3 (go/cmd/operator/main.go) takes
   --api-group / --namespace / --operator-namespace /
   --metrics-bind-address / --health-probe-bind-address /
   --leader-elect / --leader-election-id. v0.3.x took
   --log-level / --metrics-port / --health-port / --leader-election.
   None of the v0.3.x flags exist in v0.6.3 — pflag.Parse would
   error and the pod would crashloop. Args rewritten to the
   v0.6.3 surface.

3. ClusterRole. v0.3.x used `apiGroups: ["lux.network"]` with
   prefixed plurals (luxchains, luxindexers, luxexplorers,
   luxgateways). v0.6.3 canonical group is `lux.cloud` (see
   api/v1/groupversion_info.go DefaultGroup) with unprefixed
   plurals (chains, networks, validators, etc.). The CRD list
   matches the 20 canonical kinds + Network/LuxNetwork emitted
   by cmd/generate-crd-yaml at HEAD. Also added `leases` /
   `serviceaccounts` / Rbac for the controllers that need them.

Other deltas:
- Added `imagePullSecrets: [{name: ghcr-luxfi}]` (cluster already has
  the secret, age 96d; the previous YAML relied on the cluster
  having a node-level credential which works today but is brittle).
- `imagePullPolicy: IfNotPresent` (was implicit; explicit is better
  for semver-pinned tags — no need to re-pull when the same digest
  is already present).

Post-apply readiness probe:
  kubectl --context=do-sfo3-lux-k8s -n lux-system rollout status \
    deploy/lux-operator --timeout=180s
2026-06-01 16:46:11 -07:00
zeekay 939ced5ada fix(lux-mainnet/luxd-startup): sentinel-write touches v4 not v3
Bug: wipe-check on .cchain_rlp_imported_v4 (correct since 57f0119d)
but the sentinel-write line still touched .cchain_rlp_imported_v3.
Result: import succeeds, writes v3 sentinel, next reconcile sees
v4 absent, wipes + re-imports — infinite loop.

This whole shell-script-sentinel approach is a kludge. Tracked for
removal in #122 (decomplect into operator-driven content-hash
addressed tenantImports[]).
2026-06-01 16:44:01 -07:00
Hanzo AI f21f7694f0 fix(lux-mainnet/luxd-startup): sentinel-write touches v4 not v3
Bug: wipe-check on .cchain_rlp_imported_v4 (correct since 57f0119d)
but the sentinel-write line still touched .cchain_rlp_imported_v3.
Result: import succeeds, writes v3 sentinel, next reconcile sees
v4 absent, wipes + re-imports — infinite loop.

This whole shell-script-sentinel approach is a kludge. Tracked for
removal in #122 (decomplect into operator-driven content-hash
addressed tenantImports[]).
2026-06-01 16:44:01 -07:00
zeekay d896018d9d lux-k8s/operator: bump to v0.6.3 (luxnetwork pluginSource + tenantImports + genesisConfigMap)
ghcr.io/luxfi/operator was stuck at v0.3.12 since 2026-04-26 because
every Docker build since the canonical-reusable migration produced a
startup_failure (zero artifacts published — verified GHCR empty for
v0.4.x, v0.5.x, v0.6.0, v0.6.1, v0.6.2).

luxfi/[email protected] ships:
- Declarative VM plugin fetch + chain-id symlinks (PluginSource).
  Replaces the hand-managed `cp -f /luxd/build/plugins/* + ln -sf` step
  from luxd-startup.yaml.
- Per-(tenant, version) TenantImports with sentinel + request-marker
  discipline for first-boot RLP imports (closes #50).
- GenesisConfigMap mount support — bake-in path for #91 (declarative
  canonical genesis CMs replace the embedded base64 blobs in the
  luxd-startup ConfigMap).
- CRD generator dedup (Network was listed twice, second overwrote
  first → 23 files instead of 24; CI count updated to 23).
- Regenerated CRD bases for all four universes (lux.cloud, hanzo.ai,
  zoo.cloud, osage.cloud); metadata.name now matches `<plural>.<group>`
  (previously stale `nets.<group>` from the Subnet→Net era would have
  been rejected by k8s).
- Inline Docker workflow (cross-org workflow_call to hanzoai/.github
  remains broken in practice; replicated luxfi/kms self-contained
  pattern → first successful Docker build in the repo's history).

Image verified pullable:
  $ docker manifest inspect ghcr.io/luxfi/operator:v0.6.3
  schemaVersion: 2, mediaType: application/vnd.docker.distribution.manifest.v2+json

Bring-up sequence (the swarm may fire these directly):
  kubectl --context=do-sfo3-lux-k8s -n lux-system apply -f k8s/lux-k8s/operator/deployment.yaml
  kubectl --context=do-sfo3-lux-k8s -n lux-system rollout restart deploy/operator
  kubectl --context=do-sfo3-lux-k8s -n lux-system rollout status deploy/operator --timeout=180s
2026-06-01 16:43:31 -07:00
Hanzo AI 080ac7d5d4 lux-k8s/operator: bump to v0.6.3 (luxnetwork pluginSource + tenantImports + genesisConfigMap)
ghcr.io/luxfi/operator was stuck at v0.3.12 since 2026-04-26 because
every Docker build since the canonical-reusable migration produced a
startup_failure (zero artifacts published — verified GHCR empty for
v0.4.x, v0.5.x, v0.6.0, v0.6.1, v0.6.2).

luxfi/[email protected] ships:
- Declarative VM plugin fetch + chain-id symlinks (PluginSource).
  Replaces the hand-managed `cp -f /luxd/build/plugins/* + ln -sf` step
  from luxd-startup.yaml.
- Per-(tenant, version) TenantImports with sentinel + request-marker
  discipline for first-boot RLP imports (closes #50).
- GenesisConfigMap mount support — bake-in path for #91 (declarative
  canonical genesis CMs replace the embedded base64 blobs in the
  luxd-startup ConfigMap).
- CRD generator dedup (Network was listed twice, second overwrote
  first → 23 files instead of 24; CI count updated to 23).
- Regenerated CRD bases for all four universes (lux.cloud, hanzo.ai,
  zoo.cloud, osage.cloud); metadata.name now matches `<plural>.<group>`
  (previously stale `nets.<group>` from the Subnet→Net era would have
  been rejected by k8s).
- Inline Docker workflow (cross-org workflow_call to hanzoai/.github
  remains broken in practice; replicated luxfi/kms self-contained
  pattern → first successful Docker build in the repo's history).

Image verified pullable:
  $ docker manifest inspect ghcr.io/luxfi/operator:v0.6.3
  schemaVersion: 2, mediaType: application/vnd.docker.distribution.manifest.v2+json

Bring-up sequence (the swarm may fire these directly):
  kubectl --context=do-sfo3-lux-k8s -n lux-system apply -f k8s/lux-k8s/operator/deployment.yaml
  kubectl --context=do-sfo3-lux-k8s -n lux-system rollout restart deploy/operator
  kubectl --context=do-sfo3-lux-k8s -n lux-system rollout status deploy/operator --timeout=180s
2026-06-01 16:43:31 -07:00