32 Commits
Author SHA1 Message Date
zeekay 4e13893d5a chore: sync working tree
Commits 4 outstanding change(s) that were sitting uncommitted.
No build artifacts and no secrets in the changeset (both checked).
2026-07-26 10:13:27 -07:00
zeekayandHanzo Dev 2466a1a1fc genesis: header said KMS_WORKSPACE_ID, code reads KMS_ORG
The KMS fetch was migrated to the canonical /v1/kms/orgs/{org}/secrets path, but
the file header and the usage example were left describing the Infisical v3 raw
API and telling operators to export KMS_WORKSPACE_ID — a variable this program
does not read. Following the header got you a tool that could not resolve the
org and failed with no obvious reason.

Both now match resolveMnemonic: KMS_ENDPOINT + KMS_TOKEN + KMS_ORG, fetching
GET ${KMS_ENDPOINT}/v1/kms/orgs/<org>/secrets/lux/<env>/staking/mnemonic.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-26 08:13:48 -07:00
zeekay 0cf30f0164 fix(deps): get off the deleted luxfi/geth v1.16.98 tag
`go build ./...` failed outright — the v1.16.x line was DELETED from
github.com/luxfi/geth (newest is v1.20.1) while proxy.golang.org still serves
it, and GOPRIVATE forces a direct fetch for luxfi/*, so resolution fails with
"unknown revision v1.16.98".

Not fixable by tidying here: the requirement is baked into PUBLISHED modules,
which pin the dead tag and in some cases explicitly `exclude` the alternative.
The first versions that moved off it:

    luxfi/crypto     v1.20.2   (every version through v1.20.0 pins the dead tag)
    luxfi/constants  v1.6.2
    luxfi/warp       v1.24.1

Requiring those is what escapes it; geth then resolves to v1.20.1. Companion
luxfi modules moved with them at minor level within v1.x / v0.x — no major jumps.

Verified: go build ./... goes from exit 1 to exit 0. go test ./... is 1 ok / 3 fail. Those tests were NOT reachable before —
the packages could not compile — so this exposes pre-existing failures rather
than causing them.
2026-07-26 04:38:04 -07:00
zeekayandHanzo Dev 81209d2fda createchaintx: read the mnemonic from luxfi/kms, not Infisical
fetchKMSMnemonic called Infisical v3 raw secrets:

  GET ${KMS_ENDPOINT}/api/v3/secrets/raw?workspaceId=..&environment=prod&secretPath=..

That endpoint is not served by kms.lux.network or kms.hanzo.ai. Both answer it
with the console SPA HTML, so the JSON decode failed and no mnemonic was ever
retrievable this way — while the function, its env vars and its log line all
called it KMS.

Now it speaks the one documented HTTP surface, which luxfi/kms describes as the
only way to read a secret:

  GET ${KMS_ENDPOINT}/v1/kms/orgs/<org>/secrets/lux/<env>/staking/mnemonic
  Authorization: Bearer ${KMS_TOKEN}   (IAM-signed, resolved to <org>)
  -> {"secret": {"value": "..."}}

The server splits the path at its last slash into (path, name), so the secret
path still disambiguates the luxd env. ?env= is the KMS environment slug and
defaults to "default", matching the luxfi/kms client KMS_ENV.

KMS_WORKSPACE_ID is gone — an Infisical concept with no meaning here. Scope is
the org in the path: KMS_ORG, defaulting to lux. No compat shim; the old call
never worked.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-25 16:38:38 -07:00
zeekayandHanzo Dev 6895bcb2ff configs: size each M-Chain policy to the validator set that must satisfy it
mainnet's mchain.json asked for 7-of-10 while mainnet genesis declares
five validators, and localnet asked for 3-of-5 with three. Nothing read
those fields before, so the mismatch was inert; now that the policy is
authoritative it would fail closed forever — RunKeygen refuses a policy
needing more parties than the committee has, so no custody key could ever
be generated.

Policies now match the validator set each network actually has: 3-of-5 on
mainnet/testnet/devnet, 2-of-3 on localnet. Both keep 2K > N, so neither
admits two disjoint quorums.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-25 14:57:42 -07:00
zeekayandHanzo Dev e9d5c14f37 configs: state M-Chain's quorum in a form that cannot be misread
mchain.json carried "mpcThreshold": 7 alongside "mpcParties": 10. A bare
threshold number is exactly the ambiguity that produced degree-0 (1-of-n)
custody keys elsewhere in this stack: an operator reads it as the number
of signers, every threshold library reads it as the polynomial degree,
and the two differ by one. Nothing in the VM read these fields, so the
genesis blob stated a quorum that had no effect and could not be trusted
if it ever did.

Replaced by a single "policy" field in operator form — "7-of-10" on
mainnet, "3-of-5" on testnet/devnet/localnet, sized so each network's
validator count can actually satisfy it. M-Chain decodes it through
quorum.Policy and derives the protocol degree from it at one place, so
genesis is now the authority on how many custodians must cooperate to
move bridged funds.

Also renames the vm field from the retired "ThresholdVM" to "mpcvm".

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-25 14:49:18 -07:00
zeekayandHanzo Dev 060d74eedf fix(mainnet): DEFUSE C-Chain brick landmine — remove retroactive Multicall3 stateUpgrade[1]
stateUpgrades[1]@1784415311 (Multicall3 at 0xcA11...CA11, added in b6f6170) is a
latent brick for C-Chain 96369. The C-Chain EVM is github.com/luxfi/evm, whose
config load is strict:

  - plugin/evm/vm.go:962  dec.DisallowUnknownFields()
  - params/extras/state_upgrade.go checkStateUpgradesCompatible():
      len(newUpgrades) > len(activeUpgrades) => "cannot retroactively enable
      StateUpgrade[N]" => ConfigCompatError => VM init refused

Timestamp 1784415311 (2026-07-19) is already in the past. The live 5/5 run the
proven-canonical config (c3a1763) which has exactly ONE applied stateUpgrade,
[0]@1766708400 (23-account Path-A). The moment any luxfi/evm node rolls this
config with head past 1784415311, it computes 2 activated stateUpgrades vs the
1 in applied history -> retroactive error -> C-Chain bricks (warpConfig class).

Fix: remove stateUpgrades[1] entirely. Eliminates the retroactive-state-upgrade
brick class. File is now content-identical to proven-canonical c3a1763
(stateUpgrades=[0] only). Repo-config change ONLY — not rolled to live nodes.

Mainnet Multicall3 predeploy must instead use a FUTURE-dated monotonic
stateUpgrade or a deterministic factory (see deploy plan) — never a retroactive
one. Devnet got Multicall3 via CreateX factory with ZERO stateUpgrades.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-20 15:02:45 -07:00
zeekayandHanzo Dev b6f6170d77 predeploy(mainnet): Multicall3 at 0xcA11...CA11 via C-Chain stateUpgrade (96369)
Canonical upstream mirror of the universe luxd-startup change. Adds a stateUpgrade at
blockTimestamp 1784415311 deploying the canonical Multicall3 runtime (3808 bytes, verified
byte-identical to Ethereum's live 0xcA11). Purely additive; strictly-increasing timestamps.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-18 18:59:50 -07:00
zeekayandHanzo Dev c3a17633fe configs(mainnet): C-Chain upgrade.json = proven canonical (49 upgrades + 23-acct Path-A stateUpgrade); source-of-truth sync for the flag-day ConfigMap
Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-17 12:13:46 -07:00
zeekayandHanzo Dev 60902d86d1 fix(configs): Pars mainnet canonical EVMChainID 7070 -> 494949 (LP-018 map)
The LP-018 (family,env)->EVMChainID source-of-truth map carried the stale
7070 for Pars mainnet, but the live chain reports 494949 (api.pars.network
eth_chainId=0x78d65 / net_version=494949), and the map's own Pars testnet/devnet
(494950/494951) are already on the 4949xx base. Align mainnet to 494949 so the
map, its reverse lookup, and the tests agree with reality and with the rest of
the map. brand-genesis-homes.md updated to match. Dated l2-*.json inventory
snapshots left as historical records.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-14 10:12:26 -07:00
zeekayandHanzo Dev 6a3e80d0e7 deps: require luxfi/constants v1.6.1 (MPCVMID/FHEVMID)
Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-03 19:06:00 -07:00
zeekayandHanzo Dev abd8d365dd test: decomplect lp134 split test — one table, one loop, exact alias sets
Was 242 lines / 4 near-identical funcs with per-chain include-lists AND
banned-lists — the redundancy bred two self-contradiction bugs (F and M each
listed a required alias in their own banned list; 'mpcvm' twice on F).

Rob Pike: data dominates. One spec table + one loop. Exact alias-set equality
IS the whole invariant — it subsumes must-include, must-not-claim-the-other's,
and no-collision in a single assertion, and makes contradictory lists
impossible by construction. Exact-match also surfaced K-Chain's real alias set
{k,key,keyvm,kms} that the lenient old test never pinned.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-03 01:24:27 -07:00
zeekayandHanzo Dev 0a66629314 builder: flip F/M off shared ThresholdVMID → FHEVMID/MPCVMID (LP-134 decomplect)
The last thresholdvm braid: F-Chain and M-Chain shared constants.ThresholdVMID
and were disambiguated by BlockchainName string-match (mode dispatch). Flip to
distinct VMs per LP-134/LP-7050:
  - builder.go:604 F-Chain VMID ThresholdVMID -> FHEVMID
  - builder.go:608 M-Chain VMID ThresholdVMID -> MPCVMID
  - alias map + Aliases() now dispatch directly on FHEVMID/MPCVMID (no
    BlockchainName string-match, no shared-VM path)
  - zero ThresholdVMID remains in live genesis wiring
Shard JSON 'vm' fields left as-is to preserve per-chain GenesisData byte-stability
(routing is by builder VMID). Fixed a pre-existing self-contradictory test
(TestLP134_MChainIsMPCOnly required AND banned alias 'mpcvm').

Gate: configs + builder suites green (chainID locks + LP-134 split tests pass).
Prod unaffected — node pins genesis v1.13.16 (T-model); this is un-adopted branch
state pending a coordinated node release.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-03 01:21:33 -07:00
zeekayandHanzo Dev 8f637b68d4 builder: reconcile luxfi/pq@v1.0.3 checksum to fleet-canonical hash
The genesis/builder submodule go.sum pinned the pre-retag h1 hash
(pFlQm1...) for luxfi/pq v1.0.3, which no longer matches the module the
proxy and the rest of the fleet resolve. Every active repo that depends on
pq v1.0.3 (api, chains, cli, consensus, dex, evm, node, ...) records the
current hash ksw1dmf...; only a few stale/archived trees still carry the
old one. This submodule was one of the stale ones, which broke
`go build`/`go test` in the builder module with a checksum-mismatch
SECURITY ERROR. Reconcile to the fleet-canonical hash (verified against the
already-extracted local module cache). Dependency-hygiene only; no genesis
content, chain ID, or code changes.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-03 00:43:08 -07:00
zeekayandHanzo Dev 6a1f34e6e1 infra: s3.lux.network → s3.lux.cloud (correct snapshot endpoint for RLP re-import)
Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-02 12:45:29 -07:00
zeekayandHanzo Dev 8a8c3ac010 config: one canonical activation schedule — align devnet to Dec 25 2025 4:20pm PST gating
Devnet had all precompiles at genesis-0 while mainnet/testnet gate the new-feature
wave at 1766708400. One and one way only: all three networks now share the single
canonical fork-activation schedule. This is also what makes RLP re-import clean
(pre-activation blocks re-execute with new precompiles inactive).

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-02 12:27:02 -07:00
zeekayandHanzo Dev 13cf8b0d21 chore: migrate luxd HTTP routes /ext -> /v1
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>
2026-07-01 11:40:25 -07:00
zeekayandHanzo Dev fdc2e24299 createchaintx: --brands subset filter (process a named subset of brand L2s)
--brands=hanzo,zoo issues CreateChainTx only for the named brands, in
canonical list order (deterministic chain ordering). Unknown brand names
are a hard error (a typo must not silently create a different chain set).
Pure stdlib; zero new deps. Default (empty) = all five brands as before.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-06-30 16:06:42 -07:00
zeekay 0ec41b95b2 Merge branch 'fix/retire-brand-l2-in-luxd-bootstrap' 2026-06-30 13:36:09 -07:00
zeekay 464d35f07d genesis: retire brand-L2-in-luxd default in bootstrap-chain
bootstrap-chain defaulted --track-chain-ids=hanzo,zoo,pars,spc — it created
brand L2 EVMs INSIDE luxd, the dead WAY-1 that produced the phantom brand
chains which decayed into dangling chain-aliases. Per brand_sovereign_node_one_way
luxd runs the LUX primary network ONLY; brands run their own sovereign node.

- default --track-chain-ids is now empty
- hard-refuse brand names (hanzo/zoo/pars/spc/osage) before any P-chain spend
- doc updated; retires alongside cmd/createchaintx (deleted on
  decomplect/retire-brand-l2-in-luxd)
2026-06-28 17:27:04 -07:00
zeekay b81715a57a genesis: split T-Chain into F-Chain (FHE) + M-Chain (MPC) per LP-134
The legacy T-Chain conflated two orthogonal threshold primitives on one
ThresholdVM substrate. LP-134 decomplects them into two distinct
primary-network chains, both served by the shared ThresholdVM library:

  F-Chain (F/fhe/fhevm)  — threshold FHE, confidential compute / off-EVM
                            threshold DECRYPT. ThresholdVM in FHE mode.
  M-Chain (M/mpc/mpcvm)  — threshold MPC, CGGMP21/FROST bridge-custody
                            SIGNING. ThresholdVM in MPC mode. EVM verify
                            surface = 0x0800..02 (FROST) + 0x0800..03
                            (CGGMP21), verify-only, ceremony off-EVM.

Forward-only: tchain.json is retired on all 4 nets (T was never bootstrapped
with live state — a clean 404 forward-split, no state migration). F-Chain
occupies T's vacated shard slot (same VM, keeps Z/G/K byte-stable); M-Chain
is appended. Fresh non-colliding chainIds at the next free indices 9/10
(F: 97269/97268/97270/32327, M: 97369/97368/97370/32437); T's 96869-series
is not recycled.

K-Chain decomplect ("K stays keyvm" per LP-134): the M/mpc/mpcvm aliases and
MPC params were erroneously carried on the KeyVM shard (the "mpc->K backwards"
wiring). Moved them to M-Chain; kchain.json is now pure KMS key management.

Chain-level wiring (one way, data-driven by shard presence):
  - pkg/genesis: ConfigOutput/Config gain FChainGenesis (T's slot) +
    MChainGenesis; TChainGenesis removed.
  - configs.go chainSet/primaryChainShardFiles/slots + config.go
    optionalChainShards: tchain.json -> fchain.json, append mchain.json.
  - builder: F and M both map to constants.ThresholdVMID (shared substrate)
    and are disambiguated in Aliases() by CreateChainTx.BlockchainName.
  - chain_mapping role taxonomy: RoleThreshold("T") retired -> RoleFHE("F")
    + RoleMPC("M"); RoleKMS unchanged. (Canonical native FChainID/MChainID
    await a luxfi/ids change; the closed P/C/X/Q/A/B/T/Z/G/I/K/D set is
    out of scope here. Active path pins EVM chainIds in the shards.)

Tests: chain_shards_test updated to 11 chains + new F/M chainIds; builder
emits 11 chains; new lp134_split_test asserts the decomplect invariants
(F is FHE-only, M is MPC-only, K is KMS-only, no alias collision across
{F,M,K}, tchain.json retired). go build/vet/test green (GOWORK=off).
2026-06-28 07:40:05 -07:00
zeekay 3aef5af704 go.sum: ratify constants/crypto tag-move (refresh content hashes)
github.com/luxfi/constants@v1.5.7 and github.com/luxfi/crypto@v1.19.15 had
their git tags re-cut upstream (same go.mod, new module-zip content), so the
pinned h1: content hashes no longer matched what GOPROXY=direct serves and
GOWORK=off builds failed the checksum gate. Refresh the two content hashes to
the current tag state (versions unchanged). Pre-existing environmental drift,
independent of the LP-134 split that follows.
2026-06-28 07:39:40 -07:00
zeekay 43294cc7ba configs: scrub strictPQTimestamp from all upgrade.json
The strictPQTimestamp networkUpgradeOverride drove the EVM strict-PQ
precompile-refusal gate, which is removed (luxfi/evm enable-everything:
the field no longer exists on extras.NetworkUpgrades, so it is silently
ignored). Drop it from every env's upgrade.json so the canonical config
matches the new policy — builder precompile surface enables everything;
Lux PQ security is at consensus, not by refusing EVM verifiers.
2026-06-27 21:24:09 -07:00
zeekay fcb7acd636 decomplect: retire pqcrypto bundle (0x9003) — standalone mldsa/mlkem/slhdsa is the one way
Network reboot, no backward compat: delete the AI-slop pqcrypto bundle + every
gate pinning it (pqcryptoConfig genesis activation, relaunch-safety test pin).
ML-KEM stays via standalone mlkem (0x012201). pqcryptoConfig removed from all
upgrade.json/yaml; 0x9003 retired, never reuse.
2026-06-27 16:08:48 -07:00
zeekay f88c987025 chore: kill UPGRADE_NOTES.md (AI-generated upgrade-note slop; upgrade.json is canonical) 2026-06-26 22:32:06 -07:00
zeekay 71d5afb016 fix(devnet): canonical EVM chainID 96370 -> 96367 2026-06-23 14:00:16 -07:00
zeekay 8fef3692f6 configs(mainnet): activate all precompiles as of Dec 25 2025 (1766708400) — no future dates
20 precompiles (p3qVerify, pulsar/magnetar/corona/hqc, curve25519/x25519/sr25519,
babyjubjub/pedersen/poseidon/pasta/xwing, computeMarket/bridgeRegistrar/stableSwap/
vrf/attestation/anchor/fixedPointMath) were forward-dated to 2026-07-01; realigned to
the canonical Dec-25-2025 activation (1766708400) that testnet already uses. All
networks now activate the full surface as of Dec 25 2025 — zero future-dated upgrades.
2026-06-23 10:10:27 -07:00
zeekay 06f0807de6 configs: pin 17 live-at-genesis precompiles to blockTimestamp 0 (relaunch-safe)
The mainnet/testnet C-Chain upgrade.json scheduled 17 already-live
precompiles (aiMiningConfig, blake3Config, cggmp21Verify, deadZeroConfig,
deadConfig, deadFullConfig, routerConfig, fheConfig, frostVerify,
graphConfig, hpkeConfig, mldsaVerify, mlkemConfig, pqcryptoConfig,
ringConfig, slhdsaVerify, zkConfig) at blockTimestamp 1766708400 — a
future (2025-12-26) timestamp. On the running mainnet these precompiles
are active at BLOCK 0 (the deployed luxd UPGRADE_JSON in luxfi/universe
k8s/lux-mainnet/luxd-startup.yaml has always carried them at 0).

Leaving the canonical genesis file at 1766708400 is a relaunch fork /
boot-refusal hazard: a relaunch from the canonical genesis would treat
each as INACTIVE before that timestamp and diverge from the canonical
chain where it is active at block 0 — or checkPrecompileCompatible would
refuse boot ("missing PrecompileUpgrade"). Pin all 17 to blockTimestamp 0
so IsForkTransition(0, nil, genesisTime) = (0 <= genesisTime) activates
them idempotently at block 0 on any relaunch, matching the deployed set.

warpConfig is unchanged in intent: it lives in the genesis chainConfig
(cchain.json config.warpConfig @ genesis time 1730446786,
requirePrimaryNetworkSigners=false). The upgrade schedule keeps its
genuine FUTURE strict-PQ toggle (disable@1766708399, re-enable@1766708400
with quorumNumerator=67, requirePrimaryNetworkSigners=true). The array is
reordered so all blockTimestamp:0 entries lead, preserving the
non-decreasing monotonicity rule in verifyPrecompileUpgrades. Every
non-zero timestamp is strictly greater than the genesis time, so a
relaunch re-fires no already-applied activation.

UPGRADE_NOTES.md documents the live-at-0 / strict-PQ-toggle / BLS /
Quasar-Edition tiers and the relaunch-safety contract.
2026-06-21 22:22:20 -07:00
zeekay 62bf39d883 fix(configs): remove dead dexConfig precompile key from all upgrade configs
node v1.30.27/28 dropped the 0x9010 DEX precompile; its config key
`dexConfig` is no longer registered, so any C-Chain upgrade/genesis
config carrying it is rejected at boot with "unknown precompile config:
dexConfig" -> C-Chain VM init fails. Remove the dead dexConfig entry from
every per-env upgrade.json and the devnet cchain.json. 0x9999 (live DEX
settlement) is config-free, so no key is added; routerConfig and all
other registered keys are preserved. Verified each file remains valid
JSON with dexConfig absent.

Files:
- configs/{mainnet,testnet,devnet,local,localnet}/upgrade.json
- configs/devnet/cchain.json
2026-06-21 19:03:46 -07:00
zeekay 10d6203817 genesis/cmd: derivekey + derive-scan (LightMnemonic→funded localnet account, non-ewoq) 2026-06-17 19:29:32 -07:00
zeekay 4b9b66c14e scrub branding + corona→corona (OSS brand hygiene) 2026-06-10 23:36:12 -07:00
zeekay 7f4f3318f5 ci: route to canonical native arcd labels [self-hosted, linux, <arch>]
Replaces non-canonical scale-set / org-prefixed labels with the
existing labels every arcd host registers with. Matches evo for
amd64 and spark for arm64. No new labels added.
2026-06-10 20:22:05 -07:00