Compare commits

..
Author SHA1 Message Date
Hanzo AI 7275bdf9d2 chore(node): kill subnet — chain/network vocabulary across node
Zero remaining `subnet|Subnet|SUBNET` in node Go source. Per canonical
no-subnet rule.

## Wire types (Go fields only; byte-level wire encoding unchanged)

  message/wire/types.go  TrackedSubnets    → TrackedChains
  message/wire/zap.go    same on Read/Write
  proto/p2p/p2p_zap.go   SubnetUptime alias → ChainUptime
                          (consumes luxfi/proto rename in companion PR)

## Comment scrub

  message/wire/types.go            "(chain, subnet) pair" → "(chain, network) pair"
  network/peer/handshake.go        "primary-network or subnet" → "primary-network or per-chain"
  node/node.go                     "per-subnet"   → "per-chain"
                                   "P→subnet warp" → "P→chain warp"
  genesis/builder/builder.go       "their own subnets" → "their own chains"
  vms/platformvm/client.go         dropped "subnet jargon" reference
  vms/platformvm/service.go        dropped "net / subnet jargon" reference
  vms/platformvm/config/internal.go  "subnet-spawned blockchain" → "per-chain blockchain"

## ICPSubnet (Internet Computer adapter)

  ICPSubnet → ICPNet  (type rename — unrelated to platform subnet,
                        but still a subnet word; killed for consistency)
  map field `subnets` → `nets`

## Examples

  wallet/network/primary/examples/bootstrap-hanzo/main.go:
    --subnet-id  → --network-id (CLI flag)
    existingSubnetID local var → existingNetID
    "subnet ID" log lines → "network ID"
    "SUBNET_ID=" output → "NETWORK_ID="
    "subnet-evm VM ID" → "EVM VM ID"
    All comments rephrased.

  wallet/network/primary/examples/heartbeat-tx/main.go: one comment
    rephrase.

go.work workspace cleanup:
  - Removed ./operator/go entry (placeholder; lux/operator polyglot
    layout pending the cross-repo migration)
  - Removed ./operator entry (mid-migration; nothing to build)

Build clean. Zero `grep -rIn "subnet|Subnet" --include="*.go"` matches.
2026-05-29 21:17:21 -07:00
Hanzo AI 3fcc6085d5 feat(platformvm): CreateSovereignL1Tx — single-tx sovereign L1 launch
Adds a new platformvm tx type that atomically registers a sovereign L1
in one P-chain commit. Replaces what is today the four-step flow:

  CreateNetworkTx + AddChainValidatorTx ×N + CreateChainTx ×K + ConvertNetworkToL1Tx

with one signed tx. After commit, the primary network has a permanent
record of the L1's network ID + initial validator set + chain manifest
+ on-chain validator-manager contract — but it does NOT track-chains
or validate the L1's blocks. The L1 runs its own consensus from
genesis. L2/L3/L4 follow the same pattern recursively.

Type shape:

  type CreateSovereignL1Tx struct {
    BaseTx
    Owner           fx.Owner                       // CreateNetworkTx parity
    Validators      []*ConvertNetworkToL1Validator // genesis validator set
    Chains          []*SovereignL1Chain            // VM ID + genesis blob per chain
    ManagerChainIdx uint32                         // index into Chains[]
    ManagerAddress  types.JSONByteSlice            // validator-manager contract
  }

  type SovereignL1Chain struct {
    BlockchainName string
    VMID           ids.ID
    FxIDs          []ids.ID
    GenesisData    []byte
  }

SyntacticVerify enforces:
  - at least one validator (sorted, unique)
  - at least one chain, ≤ MaxSovereignL1Chains (16)
  - ManagerChainIdx is in range of Chains[]
  - ManagerAddress ≤ MaxChainAddressLength
  - per-chain name + VMID + FxIDs + genesis bounds
  - BaseTx + Owner + each Validator each verify

Wired into:
  - Visitor interface
  - codec (registered as the next tx type after ConvertNetworkToL1Tx)
  - signer + complexity + metrics + executor stubs across all visitor
    implementations

Executor body is stubbed with a TODO. The atomic state transition
(mint new networkID from tx hash, seed validator-manager state,
register each Chain, charge fee) lands in a follow-up PR. This PR is
the type definition + interface plumbing so downstream tools (wallet,
CLI, fee calc, metrics) can target the tx type while the executor is
implemented.
2026-05-29 20:25:28 -07:00
Hanzo AI 5b0eca3270 brand: rip <tenant> from builder comment 2026-05-29 14:26:21 -07:00
Hanzo AI c0d9ccacde brand: rip <tenant> name from code comments (no crossover) 2026-05-29 14:26:00 -07:00
Hanzo AI 3919991f48 fix(docker): bump EVM_VERSION v0.8.40 → v0.18.14 (post-rename plugin)
The v0.8.40 EVM plugin was built against luxfi/node v1.23.4 — pre-rename
EngineAddressKey ("LUX_VM_RUNTIME_ENGINE_ADDR"). The host (built from
this repo) has been emitting the NEW key ("VM_RUNTIME_ENGINE_ADDR")
since 9c42fe1126 (2026-05-15). Every luxd:v1.27.x image embeds a plugin
that reads the OLD key — empty env → no dial-back → C-chain never
bootstraps → all 4 L2 EVMs stay un-bootstrapped indefinitely.

v0.18.14 pins luxfi/node v1.27.6 which carries the rename, so the
plugin built from it reads the same key the host writes. Pairs with
0c573e6aa7 (host compat shim) — once every cluster pulls an image that
contains this Dockerfile bump, the shim is a no-op.
2026-05-27 04:59:03 -07:00
Hanzo AI 0c573e6aa7 fix(rpcchainvm): compat shim for pre-rename plugin env-var
The EngineAddressKey const renamed from LUX_VM_RUNTIME_ENGINE_ADDR to
VM_RUNTIME_ENGINE_ADDR in 9c42fe1126 (2026-05-15). luxd builds from
that commit forward set VM_RUNTIME_ENGINE_ADDR on plugin exec, but the
EVM plugin (luxfi/evm@v0.8.40 → luxfi/node@v1.23.4 → "LUX_VM_..." const)
in the same Docker image still os.Getenv("LUX_VM_...") — empty string,
no dial back, plugin exits, C-chain never bootstraps, all L2 EVMs stay
un-bootstrapped indefinitely on v1.27.x.

Set BOTH env keys until every plugin in /data/plugins has been rebuilt
against a luxfi/node version that has the rename. New const is the
canonical name; legacy const is the compat key (added as
LegacyEngineAddressKey and only emitted when it differs from the new
key, so once luxfi/evm bumps past the rename the extra env var becomes
a no-op and this line can be deleted without runtime impact).
2026-05-27 04:57:24 -07:00
Hanzo AI 711d2519c2 chore: update 2026-05-25 15:13:02 -07:00
Hanzo AI 9323caa1fc go.mod: replace luxfi/corona v0.7.5 — track keyera.Bootstrap 3-value return
consensus@v1.24.6 calls keyera.Bootstrap(...) with three return values
but its own go.mod still pins corona v0.4.0 (where Bootstrap returns
two). The 3-value signature lives at corona v0.7.x.

Locally we hide this via go.work using the working tree, so it never
shows up. CI builds without go.work and fails compiling
protocol/quasar/grouped_threshold.go.

Add a replace directive pinning corona to v0.7.5 (current latest).
A proper fix is to tag a luxfi/consensus v1.24.7 with corona bumped
in its own go.mod, but luxd is the only consumer of this transitive
mismatch right now — the replace keeps it tight and reversible.
2026-05-24 19:17:18 -07:00
Hanzo AI ff9faa3ef3 ci/docker: fall back to UNIVERSE_PAT when org GH_TOKEN is empty
The v1.27.18 diagnostic confirmed luxfi org GH_TOKEN secret resolves to
length=0 at runtime (visibility is set to 'all' but the actual value
appears unset/expired). UNIVERSE_PAT is set at the repo level and has
the same cross-repo read scope we need for private luxfi/* deps. Try
GH_TOKEN first, fall back to UNIVERSE_PAT, fail fast with a clear
error if both are empty.

Also explicitly disable docker/metadata-action's latest=auto flavor so
the :latest floating tag truly never gets emitted (the prior run showed
the action silently injecting it even with no type=raw rule).
2026-05-24 18:57:38 -07:00
Hanzo AI cae6f18ffb ci/docker: self-check GH_TOKEN propagation before BuildKit secret mount
The repeated 'terminal prompts disabled' fatal at go mod download in
v1.27.15..v1.27.17 looked like the BuildKit secret mount was producing
an empty /run/secrets/ghtok file. Add a pre-build step that fails fast
if secrets.GH_TOKEN does not resolve at workflow run time (org-secret
visibility=all, but ARC runner ephemeral identities have surprised us
before). The token value is never echoed — only its byte length.
2026-05-24 18:51:28 -07:00
Hanzo AI d48292b9dc genesis/builder + ci: initialSupply matches emitted UTXOs; Dockerfile keeps insteadOf live
initialSupply was still summing both initialAmount AND unlockSchedule
amounts — even with the UTXO emission fix, the reported supply field
double-counted Avalanche-shaped configs. Match the emission policy:
unlockSchedule wins when non-empty, initialAmount otherwise.

Dockerfile: drop the post-go-mod-download cleanup of the
url.insteadOf git config. The build step at the bottom of the
builder stage also triggers go fetches (resolving build-time
transitive deps), so the rewrite must remain in place. The
throwaway builder stage never ships, so leaving the token in
/etc/gitconfig is fine — only the compiled binary is COPYed into
the runtime image.
2026-05-24 18:43:49 -07:00
Hanzo AI c926953b60 ci/docker: resolve private luxfi/* deps via org-level GH_TOKEN PAT
Default workflow GITHUB_TOKEN only has read access to the running repo
(luxfi/node), so go mod download fails on private cross-repo deps such
as luxfi/corona. Switch the BuildKit ghtok secret to the org-level
GH_TOKEN (a PAT with org-wide read scope) so the Dockerfile's git
url-rewrite picks up every luxfi/* module the build needs.
2026-05-24 18:34:58 -07:00
Hanzo AI 7184449585 genesis/builder: back-compat — initialAmount UTXO only when unlockSchedule empty
Avalanche/legacy genesis JSONs (testnet, mainnet) set initialAmount as the
sum of unlockSchedule (two views of one total). The current builder emits
both an immediately-spendable UTXO for initialAmount AND one UTXO per
unlock entry — double-minting the allocation.

Devnet-style configs set initialAmount with an empty unlockSchedule and
need the single UTXO to be emitted.

One semantic, one UTXO: when unlockSchedule is non-empty, skip the
initialAmount UTXO (the schedule already covers the total). When
unlockSchedule is empty, emit the initialAmount UTXO as before.

Also:
- ci/docker: switch back to self-hosted `lux-build` ARC pool (DOKS hanzo-k8s)
- ci/docker: drop floating `:latest` tag — semver/sha-only policy
2026-05-24 18:28:00 -07:00
Hanzo AI 8e5bfb68dc wallet/primary: tighten commented future-work lines to EVM canonical names
Cleanup pass on the C-Chain-disabled future-work comments. No code
change — just the placeholder identifiers now match the canonical
EVMAddress / EVMKeychain naming used by the live KeychainAdapter.

ethAddrs    → evmAddrs
FetchEthState → FetchEVMState
2026-05-24 13:27:31 -07:00
Hanzo AI 51d4bd9520 wallet: mass-rename EthKeychain → EVMKeychain across all examples (no aliases)
Forward-only completion of the strip-aliases work. Examples (18 main.go
files + example_test.go + debug_balance_test.go) used the old
EthKeychain field name on WalletConfig literals. Mass-renamed via
sed across the wallet/ tree to match the canonical EVMKeychain name.

Also: cleaned remaining linter-restored EthKeychain references in
wallet.go (WalletConfig struct field, comments in MakeWallet).

Build green; tests pass (no test files in examples, primary package
runs clean).

Per CLAUDE.md x.x.x+1.
2026-05-24 06:34:38 -07:00
Hanzo AI 2e18d7da38 wallet: strip all Eth/Keccak aliases — EVMKeychain / EVMAddresses / WithCustomEVMAddresses only
Forward-only per user "no aliases!!! just keep evm address and utxo address"
and CLAUDE.md "no backwards compatibility only forwards perfection".

wallet/network/primary/wallet.go:
- Removed KeccakKeychain interface (was Deprecated)
- Removed EthKeychain interface (was Deprecated)
- Removed GetByKeccak/KeccakAddresses methods on KeychainAdapter
- Removed GetEth/EthAddresses methods on KeychainAdapter
- Renamed WalletConfig.EthKeychain field → EVMKeychain
- Mass renamed EthKeychain → EVMKeychain across all 18 example
  programs (sed -i '' s/EthKeychain/EVMKeychain/g)

wallet/network/primary/common/options.go:
- Removed KeccakAddresses() method (was Deprecated)
- Removed EthAddresses() method (was Deprecated)
- Removed WithCustomKeccakAddresses (was Deprecated)
- Removed WithCustomEthAddresses (was Deprecated)
- Renamed private fields customEthAddresses{Set} → customEVMAddresses{Set}

Only canonical names remain:
- EVMKeychain interface
- KeychainAdapter.{GetByEVM, EVMAddresses}
- WalletConfig.EVMKeychain
- Options.EVMAddresses
- WithCustomEVMAddresses

Downstream callers using old names break at compile time. Lockstep
break-fix follows in cli, kms, mpc, state.

Deps: utxo v0.3.2 → v0.3.3, crypto v1.19.15 → v1.19.16.

Per CLAUDE.md x.x.x+1.
2026-05-24 06:17:08 -07:00
Hanzo AI b4a3ecdd75 wallet: reconcile — EVMKeychain / EVMAddresses / WithCustomEVMAddresses canonical
Workspace-wide reconcile to the runtime-data-model axis (EVM) the
state team established earlier. Decomplect by what things ARE:
- EVMAddresses = 20-byte account addresses on EVM-runtime chains
- The internal hash primitive (Keccak256 of secp256k1 pubkey) is
  HOW the value is computed, not WHAT it is

wallet/network/primary/wallet.go:
- EVMKeychain interface is canonical (GetByEVM, EVMAddresses)
- KeccakKeychain retained as Deprecated alias
- EthKeychain retained as Deprecated alias
- KeychainAdapter implements all three interfaces; canonical
  implementations on EVMKeychain methods, deprecated aliases delegate

wallet/network/primary/common/options.go:
- Options.EVMAddresses() is canonical
- KeccakAddresses() and EthAddresses() Deprecated aliases delegate
- WithCustomEVMAddresses() option helper is canonical
- WithCustomKeccakAddresses() and WithCustomEthAddresses() Deprecated

Deps bumped:
- luxfi/utxo v0.3.1 → v0.3.2 (EVMAddrs canonical, deprecated aliases)
- luxfi/crypto v1.19.13 → v1.19.15 (EVMAddress canonical)
- luxfi/genesis v1.12.11 → v1.12.14 (transitive dep of utxo bump
  for crypto/keccak package path)

Per CLAUDE.md x.x.x+1.
2026-05-23 22:24:05 -07:00
Hanzo AI f6639e661b wallet: decomplect — add KeccakKeychain interface alongside deprecated EthKeychain
Wave 3 of the workspace-wide eth* naming purge. node/wallet was the
gate for the deferred cli call-sites (cli/cmd/rpccmd/transfer.go and
cli/pkg/chain/local.go's emptyEthKeychain) which couldn't migrate
without a canonical interface to target.

wallet/network/primary/wallet.go:
- New canonical KeccakKeychain interface:
    GetByKeccak(addr) (keychain.Signer, bool)
    KeccakAddresses() set.Set[gethcommon.Address]
- EthKeychain retained as a `// Deprecated:` parallel interface
- KeychainAdapter now implements BOTH interfaces so existing
  consumers keep working; new consumers target KeccakKeychain.
- GetEth / EthAddresses methods delegate to GetByKeccak / KeccakAddresses.

wallet/network/primary/common/options.go:
- New canonical Options.KeccakAddresses() method
- New canonical WithCustomKeccakAddresses(...) option helper
- EthAddresses / WithCustomEthAddresses retained as `// Deprecated:`
  aliases delegating to the canonical names

Deps bumped:
- luxfi/utxo v0.3.0 → v0.3.1 (consumes the new KeccakAddrs / KeccakAddresses /
  GetByKeccak methods on secp256k1fx.Keychain)
- luxfi/crypto stays at v1.19.13 (PrivateKey.KeccakAddress)

This unblocks cli/cmd/rpccmd/transfer.go to call kcAdapter.KeccakAddresses()
and cli/pkg/chain/local.go to implement KeccakKeychain — a future cli
wave (v1.100.5+).

Per CLAUDE.md x.x.x+1.
2026-05-23 19:51:10 -07:00
Hanzo AI 130927f056 go.mod: bump luxfi/genesis v1.12.13 → v1.12.14 (clean build) 2026-05-23 16:27:17 -07:00
Hanzo AI 530b428159 go.mod: bump luxfi/genesis v1.12.12 → v1.12.13 (keys.go build fix) 2026-05-23 16:25:36 -07:00
Hanzo AI f86909a928 go.mod: bump crypto v1.19.14 + genesis v1.12.12 (keccak→keccak256 subpackage rename) 2026-05-23 16:21:54 -07:00
Hanzo AI 3fb51e1995 go.mod: bump luxfi/genesis v1.12.10 → v1.12.11 (keccak primitive direct) 2026-05-22 21:20:01 -07:00
Hanzo AI cbd10105be go.mod: bump luxfi/genesis v1.12.8 → v1.12.10 2026-05-22 21:05:25 -07:00
Hanzo AI eb510e0ca4 drop ethAddr/luxAddr/luxcrypto stragglers — match genesis v1.12.10 2026-05-22 21:05:21 -07:00
Hanzo AI 04902cdca5 go.mod: bump luxfi/genesis v1.12.7 → v1.12.8 (no more eth* identifiers) 2026-05-22 20:56:53 -07:00
Hanzo AI 5cbb1e4431 drop ethAddr/luxAddr string tags — canonical is evmAddr/utxoAddr 2026-05-22 20:40:49 -07:00
Hanzo AI bcbb141378 go.mod: bump luxfi/genesis v1.12.6 → v1.12.7 (EVMAddr Go field) 2026-05-22 20:37:37 -07:00
Hanzo AI bcd6c6b46d deps: bump consensus v1.24.6, threshold v1.8.5, metric v1.5.5 (kill prom/protobuf transitives) 2026-05-22 20:24:51 -07:00
Hanzo AI 91e91218df go.mod: bump luxfi/genesis v1.12.5 → v1.12.6 (JSON evmAddr+utxoAddr) 2026-05-22 20:11:51 -07:00
Hanzo AI 000a0c84ff purge Avalanche-era upgrade names from test fixtures
Final cleanup for the upgrade-name purge (lux/node now runs full
feature-set from genesis under activate-all-implicitly):

- vms/xvm: `var durango = upgrade.Default` -> `var activeUpgrade =
  upgrade.Default`. Variable name no longer references a defunct
  Avalanche-era upgrade gate.
- wallet/chain/p/builder_test.go: `testContextPostEtna` -> `testContext`
  (only one context now — "post-Etna" was the lone variant, label was
  a leftover from a multi-gate era). Test names "Post-Etna" /
  "Post-Etna with memo" -> "default" / "default with memo".

No behavior change. `go build` + `go vet` clean.
2026-05-22 02:37:40 -07:00
Hanzo AI d12c3457af go.mod: bump luxfi/genesis v1.12.4 → v1.12.5 (devnet 100M/wallet alignment) 2026-05-22 00:11:28 -07:00
Hanzo AI 63d602b8ca go.mod: bump luxfi/genesis v1.12.2 → v1.12.4 (refreshed canonical hashes + devnet 50M) 2026-05-21 23:48:45 -07:00
Hanzo AI ef0c581714 genesis,config,xvm: derive X-Chain asset ID from genesis content
config.UTXOAssetIDFor(networkID) returns a network-id-keyed constant
that's identical across every L1 sharing a primary-network ID. On
sovereign L1s (<tenant> / MLC / VCC / any future tenant) the X-Chain
genesis bakes a different asset (different validator set, different
holder set, different denomination) so the runtime asset ID — the ID
vm.initGenesis assigns to the first GenesisAsset.CreateAssetTx — does
not match the constant.

Every wallet builder that calls platform.getStakingAssetID to populate
pCTX.XAssetID then pays tx fees from UTXOs under an asset the chain
doesn't recognise:

    insufficient funds: needs 398 more nLUX (<constant>)

That's the bootstrap failure on <tenant> devnet / testnet / mainnet
after the chainset-via-embedded-genesis fix landed.

Fix: derive the X-Chain native asset ID from the actual genesis bytes
the binary loads at startup. Every load path now goes through
resolveXAssetID(networkID, genesisBytes):

  - genesis baked with X-Chain → parse the embedded XVM genesis,
    initialize the first GenesisAsset.CreateAssetTx, return its tx.ID()
    (the same value vm.initGenesis assigns at runtime).
  - genesis is P-only (no X-Chain) → fall back to UTXOAssetIDFor.
    Value is unused at runtime, kept for downstream-consumer shape.
  - genesis is malformed → error (was previously silently returning
    the wrong constant; that's how sovereign L1s ended up shipping
    binaries that disagreed with their own chain).

Touched:
  - vms/xvm/genesis.go: ParseGenesisBytes + AssetIDFromGenesisBytes.
  - vms/xvm/genesis/lux.go: AssetIDFromBytes proxy so the wrapper
    package stays the single dependency point.
  - genesis/builder/builder.go: FromConfig uses the genesis-derived
    ID instead of UTXOAssetIDFor; new XAssetIDFromGenesisBytes
    helper for the platform-genesis-bytes path.
  - config/config.go: getGenesisData's raw and cached paths now call
    resolveXAssetID. FromConfig path inherits the fix automatically.

Tests:
  - vms/xvm/genesis/lux_test.go: AssetIDFromBytes is stable, holder-
    sensitive, network-id-sensitive, malformed-input-rejecting.
  - genesis/builder/builder_p_only_test.go: helper agrees with
    FromConfig on sovereign genesis, returns ok=false on P-only,
    errors on garbage.
  - config/config_test.go: resolveXAssetID returns the genesis-derived
    ID for sovereign genesis, UTXOAssetIDFor on P-only, error on
    garbage.

No network-id allow-list, no per-network branching, no env-var
overrides. The fix is in the binary's load path; operator workflows
stay byte-identical.
2026-05-21 18:34:50 -07:00
Hanzo AI f852526092 docker: fall back to ubuntu-latest runner — lux-build ARC offline
The lux-arm64-runners EKS cluster is unreachable (i/o timeout on
control plane); no Docker builds since the runner pool dropped.
Pinning to ubuntu-latest until ARC is restored. Switch back to
lux-build in a follow-up once the EKS cluster is back up.
2026-05-21 17:43:22 -07:00
Hanzo AI 18f54f9eb0 LLM.md: FeePolicy table — add G-Chain (graphvm) NoUserTxPolicy row 2026-05-21 17:35:22 -07:00
Hanzo AI 964be2fad8 docker: inject GH_TOKEN via BuildKit secret for private mod download
luxfi/corona went private; the Dockerfile builder's `go mod download`
was failing with "could not read Username for 'https://github.com'"
on the ARC runner. Adds a BuildKit secret mount (required=false so
local builds without the secret still work when all deps are public)
and rewrites `git config url.insteadOf` to inject the token only for
the download step. Token is unset after to keep the layer clean.

The workflow passes ${{ secrets.GITHUB_TOKEN }} as the `ghtok` secret;
the default GITHUB_TOKEN has repo:read for the runner's repository,
which is sufficient for luxfi/corona since it's in the same org.
2026-05-21 17:28:07 -07:00
Hanzo AI ca7cdb4a77 LLM.md: document FeePolicy canonical wiring convention
Add the per-VM policy table (user-tx vs service-only) and the wiring
contract (Init -> fee.Validate -> ValidateFee at the user-tx entry,
internal paths bypass). The actual gates live in the per-VM repos
(luxfi/chains/<vm>/feegate.go, luxfi/oracle/vm/feegate.go,
luxfi/relay/vm/feegate.go) — this is the index page.
2026-05-21 17:23:58 -07:00
Hanzo AI 99eddf0827 gitignore stray dev-tool binaries 2026-05-21 15:01:49 -07:00
Hanzo AI 742c35485f drop hardcoded /Users/z paths — use $HOME-relative 2026-05-21 15:01:36 -07:00
Hanzo AI e94b025395 rip: proto/zap/ moved to luxfi/proto/node/zap (canonical proto module) 2026-05-21 14:42:42 -07:00
Hanzo AI ee81e8ea8f genesis/builder: track upstream Allocation.ETHAddr rename
upstream luxfi/genesis v1.12.2 drops EVMAddr in favor of canonical
ETHAddr (json tag `ethAddr`). Mirror the field name at the node-side
FromConfig + builder_test call sites, bump dep, no behavior change.
2026-05-21 12:53:05 -07:00
Hanzo AI 5a92bff2cd go.mod: bump luxfi/genesis to v1.12.1 (kill F12/F30 slop) 2026-05-21 12:30:43 -07:00
Hanzo AI 0aef65bc5d go.mod: bump luxfi/genesis to v1.12.0 (no backward compat) 2026-05-21 10:44:45 -07:00
Hanzo AI 6fdc4ddfa7 go.mod: bump luxfi/genesis to v1.11.9 (xchain.json shards baked) 2026-05-21 03:47:01 -07:00
Hanzo AI 708268aa71 genesis/builder: chain registry as data — decomplect aliases from switch ladders
The primary-network alias machinery used to be three separate hand-typed
data structures encoding the same chain identity:

  - Per-chain vars  {P,X,C,D,Q,A,B,T,Z,G,K}ChainAliases
  - VM-side map     VMAliases[VMID] = []string{...}
  - Switch ladders  inside Aliases() that map VMID → letter+aliases

Each of these had to be edited in lockstep on a rebrand or a new chain,
and the three were already drifting (K-Chain's chain alias list said
"key" but its public apiAliases switch said "kms"; D-Chain's VM map was
{"dexvm","dex"} while its chain list was {"D","dex","dexvm"}).

This change introduces builder.Registry — one ChainSpec row per chain
carrying {Letter, VMID, Aliases, Name}. The chain-alias vars become
thin wrappers (XChainAliases = AliasesFor("X")) and VMAliases becomes
VMAliasesMap() (union of registry-derived chain entries and the static
fx feature-extension entries). Rebranding now edits one row.

Compatibility:

  - Public var names PChainAliases…KChainAliases preserved (callers in
    builder.Aliases() and external tooling don't break).
  - VMAliases is still a map[ids.ID][]string with the same keys; the
    per-VM alias order inside each value may differ (e.g. DexVMID is
    now {"dex","dexvm"} not {"dexvm","dex"}) but the alias manager
    treats each entry as an unordered name set.
  - Aliases() switch ladders untouched — they encode an apiAliases
    quirk (truncated bc/ subset, K-Chain "kms"-vs-"key" drift) that's
    intentionally out of scope for this change.

Tests: builder_test.go's existing TestChainAliases + TestVMAliases pass
unchanged. New parity tests assert reflect.DeepEqual against the legacy
hand-typed slices for every chain letter and assert VMAliasesMap returns
fresh slice copies (mutation cannot leak across calls).

  go build ./genesis/builder/...   clean
  go vet ./genesis/builder/...      clean
  go test ./genesis/builder/...     ok (0.96s, all subtests pass)
2026-05-21 03:43:00 -07:00
Hanzo AI 2f644a14bc vms/xvm/genesis: extract DefaultLUXGenesisBytes (decomplect builder from xvm)
The primary-network genesis builder used to import vms/xvm directly to
construct the LUX asset descriptor — braiding "what an XVM genesis
looks like" with "how the node's primary-network gets bootstrapped".

Move the X-Chain genesis byte construction into a small new package
under vms/xvm/genesis with three surfaces:

  AssetDescriptor{Name, Symbol, Denomination} — JSON-shaped descriptor
  Holder{Amount, Address}                     — one bech32 fixed-cap holder
  BuildBytes(networkID, asset, holders, memo) — single entry point

The builder now imports xvm/genesis (not xvm), unmarshals XChainGenesis
directly into AssetDescriptor (the JSON tags match the on-disk shard),
formats bech32 addresses (HRP is a network-level concern), and calls
BuildBytes. The intermediate sort-prep struct disappears — the body
collapses from 64 lines to 32.

Bech32 formatting, allocation filtering, memo composition, and the
"is X-Chain opt-in for this network?" policy stay in the builder
where they belong. xvm/genesis only owns the XVM-shaped construction.

Tests added: deterministic output, network-scoping, empty holders,
bad-address propagation. Builder tests unchanged and pass.
2026-05-21 03:36:50 -07:00
Hanzo AI 573346c6b8 vms/types/fee: introduce FeePolicy interface (close free-tx paths)
A 2026-05 audit of vms/* found five chains accepting user txs while
charging nothing (dexvm, bridgevm, keyvm, zkvm, aivm) and one charging
1,000x too little (quantumvm). Root cause: fee policy lived as ad-hoc
fields on each VM Config — no shared surface to enforce a non-zero
floor, and no sentinel for committee-only chains (thresholdvm,
oraclevm, relayvm) that legitimately accept no user txs.

This commit introduces the shared surface:

  - Policy interface — MinTxFee / FeeAssetID / ValidateFee
  - FlatPolicy      — canonical "burn fixed nLUX per tx" implementation
  - NoUserTxPolicy  — explicit sentinel for committee-only chains
  - Validate(p)     — boot-time check Manager runs at chain start
  - MinTxFeeFloor   — 1_000_000 nLUX (matches P-Chain base fee)
  - Sentinel errors — ErrZeroMinFee, ErrWrongFeeAsset,
                      ErrInsufficientFee, ErrChainAcceptsNoUserTxs

Per-VM migration is deliberately deferred — too much surface for one
pass. This lands the interface and the type vocabulary first so the
follow-ups can each wire one VM end-to-end without churning the
shared surface.

Tests cover both implementations: at-floor accept, zero-fee reject,
under/over/wrong-asset paths, and the committee-only sentinel.
2026-05-21 03:34:28 -07:00
Hanzo AI 0e8856758a use UTXOAssetIDFor (brand-neutral) — constants v1.5.7 2026-05-21 03:30:47 -07:00
Hanzo AI ba8a1fc1a7 genesis,config: use LUXAssetIDFor(networkID) — per-network LUX asset ID
Cryptographer flagged collapsing per-network LUX asset IDs into one
constant as a defense-in-depth regression. constants v1.5.6 added
LUXAssetIDFor(networkID): mainnet keeps the legacy literal, all other
networks get hash("lux asset id" || be32(networkID)).

- genesis/builder/builder.go: xAssetID := constants.LUXAssetIDFor(config.NetworkID)
- config/config.go: replace extractXAssetID() callsites with
  constants.LUXAssetIDFor(networkID); delete the now-dead helper.

Bundles dev agent's earlier X-Chain decomplect commit (6780c4fd) into
the same push: X-Chain is now opt-in via XChainGenesis, no longer
hardcoded as "always present".

Builds + tests green.
2026-05-20 22:20:55 -07:00
Hanzo AI 6780c4fdee genesis/builder: X-Chain becomes opt-in (decomplect from "always present") 2026-05-20 22:08:54 -07:00
Hanzo AI 129dfd7b46 rip: AI-generated debug fmt.Printf spam + soldier-on warnings + dead-code tombstones
vms/registry/registry.go: drop 17 [Registry]/[VMGetter] debug fmt.Printf
  calls that were left from an AI debugging session. Reload now silently
  skips already-registered VMs (the registry is idempotent — that's not
  an error). Doc-commented for what each return value means.

node/node.go: drop the [BOOTSTRAP] fmt.Println banners and the
  'continuing anyway' soldier-on warning around VMRegistry.Reload. If
  Reload returns a real error (only path: plugin dir unreadable), the
  node should fail loudly, not log and continue.

vms/xvm/vm_benchmark_test.go, vms/platformvm/validators/test_manager.go,
wallet/chain/p/wallet/backend_visitor.go, wallet/keychain/keychain_test.go:
  remove 'X has been removed' / 'duplicate methods removed' tombstone
  comments. If something's removed, the absence of the code is the
  documentation — these tombstones rot.
2026-05-20 17:11:52 -07:00
Hanzo AI b6d1bdca7c node: refresh config + rpcdb + vm registry + subprocess initializer
Routine maintenance: config.go, rpcdb/service.go, node/node.go,
vms/registry/registry.go, vms/rpcchainvm/runtime/subprocess/initializer.go.
2026-05-20 16:26:18 -07:00
Hanzo AI ffb627a51f genesis/builder: use UTXO_ASSET_ID constant + EVMAddr/UTXOAddr field names
- constants v1.5.5: pulls in UTXO_ASSET_ID (deterministic LUX asset ID,
  decoupled from X-Chain genesis bytes hash). Makes X-Chain optional —
  P-only L2s can ship without X-Chain bake.
- genesis v1.11.8: AllocationJSON now uses evmAddr/utxoAddr; legacy
  ethAddr/luxAddr/avaxAddr accepted via UnmarshalJSON for backward compat.
- builder.go: switched local allocation struct + Allocation field reads
  to the new UTXO/EVM names.

Build + tests green. Unblocks "P+Q-only" L2 topology.
2026-05-20 16:11:51 -07:00
Hanzo AI b2c2376678 fix(docker): chains/* plugin builds best-effort
luxfi/chains main has unresolved sibling go.mod replace directives
(luxfi/{evm,precompile,threshold} => ../*) that break in any isolated
build context. Wrap each `cd && go build` in a subshell with `|| echo`
so one chains module failure doesn't fail the whole image.

Production deployments pull plugins from `pluginSource.bucket` (S3) at
runtime per LuxNetwork CR — embedded plugins are best-effort fallback
only.

Unblocks luxd v1.27.x Docker publish. Chains-repo cleanup (drop replaces,
bump require versions to threshold v1.8.0/precompile v0.5.23/evm v0.18.13,
tag v1.2.5) tracks separately.
2026-05-19 13:32:30 -07:00
Hanzo AI 8bcc23efdb ci: switch lux/node workflows to lux-build (luxfi-scoped ARC pool)
Cross-org runs-on dispatch: the hanzo-build-linux-amd64 scale set is
registered to github.com/hanzoai and does NOT pick up jobs from
github.com/luxfi — the four queued v1.27.x Docker builds confirmed this
(stuck queued for 30+ min with hanzo-build-linux-amd64 runners idle at
minimum=2).

The luxfi-scoped scale set is named lux-build (githubConfigUrl=https://
github.com/luxfi, max 20). Switch docker.yml, build-linux-binaries.yml,
and the ubuntu release builders to it.

Next tagged release (v1.27.5+) will dispatch correctly. The four pending
v1.27.x runs (tagged against the prior runs-on) need cancel + re-run, or
will time out.
2026-05-19 13:14:59 -07:00
Hanzo AI 2663090827 deps: bump luxfi/genesis v1.11.0→v1.11.1 (strip bogus EVM chainIds from non-EVM letter chains) 2026-05-19 11:50:06 -07:00
Hanzo AI 65b7d6a1ae deps: bump luxfi/{geth,coreth,crypto,precompile} to LP-4200 all-8-PQ-precompile versions (geth v1.16.98, coreth v1.22.4, crypto v1.19.3, precompile v0.5.23) 2026-05-19 11:44:54 -07:00
Hanzo AI d15be7c524 ci: cross-compile arm64 from amd64 (no GH-hosted arm runners)
- build-linux-binaries.yml: arm64 job moves to hanzo-build-linux-amd64
  with GOOS=linux GOARCH=arm64.
- build-ubuntu-arm64-release.yml: both jammy/focal jobs cross-compile
  on the amd64 self-hosted runner.
- build-macos-release.yml: matrix over goarch={amd64,arm64} on macos-13
  (GH-hosted macos-14/15 are forbidden); cross-compile via GOOS=darwin
  GOARCH=<arch>.
- build-and-test-mac-windows.yml: pin macos-latest -> macos-13.
- ci.yml: drop macos-14 from CI matrix (use macos-13).
- actionlint.yml: drop hanzo-build-linux-arm64 + ubuntu-24.04-arm from
  the self-hosted-runner whitelist.
2026-05-19 09:11:06 -07:00
Hanzo AI d812ada7df ci: remove sibling-dir replace shims (api/consensus/runtime) — breaks Windows CI; bump consensus → v1.24.0 (just-tagged) 2026-05-19 08:24:55 -07:00
Hanzo AI 2abb88530c decomplect: regenerate platformvm tx test fixtures after codec type-ID collapse
The e27d954097 codec collapse retired the Apricot/Banff block-type variants
(IDs 23..26 reserved historical slots) and shifted the post-block tx slots up
by 4. Tx-level fixtures stayed pinned to the pre-collapse wire form.

Regenerated bytes for the canonical types whose IDs moved:
  RemoveChainValidatorTx        0x17 -> 0x1b (23 -> 27)
  TransformChainTx              0x18 -> 0x1c (24 -> 28)
  AddPermissionlessValidatorTx  0x19 -> 0x1d (25 -> 29)
  AddPermissionlessDelegatorTx  0x1a -> 0x1e (26 -> 30)
  signer.Empty                  0x1b -> 0x1f (27 -> 31)
  signer.ProofOfPossession      0x1c -> 0x20 (28 -> 32)

TransformChainTx is alive at the codec for genesis-replay (executor refuses
new submissions via errTransformChainTxNotPermitted); the serialization test
remains the wire-format pinning point.

stakeable.LockIn/LockOut (21, 22) and secp256k1fx primitives (5..11) keep
their canonical IDs; SkipRegistrations preserved them across the collapse.

vms/platformvm/txs/...  -> all tests green
go build ./...          -> exit 0
go test ./... -short    -> 148 ok / 0 fail / 144 (no tests)
2026-05-19 08:15:20 -07:00
Hanzo AI dedb7eb806 ci: fix runner label (hanzo-build pool)
Imaginary runner label `lux-build-linux-amd64` does not exist. The live
amd64 pool is `hanzo-build-linux-amd64`.

- docker.yml: build-amd64
2026-05-19 08:02:23 -07:00
Hanzo AI a03785d922 decomplect: final BanffBlock→TimestampedBlock rename + strip residual Apricot/Banff comments in block visitors 2026-05-19 07:17:02 -07:00
Hanzo AI ea066101a6 decomplect: rename BanffBlock→TimestampedBlock; legacy error/priority identifiers neutralized; strip durango/etna/banff JSON keys from test fixtures 2026-05-19 07:06:33 -07:00
Hanzo AI 69258c94b0 decomplect: strip upgrade-name comments (Apricot/Banff/Cortina/Durango/Etna/Fortuna/Granite); activate-all-implicitly doesn't need them 2026-05-19 07:00:08 -07:00
Hanzo AI 23bd9575ea decomplect: rip upgradetest/ Fork enum + GetConfig() shim; rewrite 5 xvm test files to use upgrade.Default directly
Fork enum (NoUpgrades..Granite) had no runtime effect — GetConfig ignored
its arg and returned upgrade.Default. Killing the indirection.

xvm tests: 19 callsites of upgradetest.GetConfig(upgradetest.X) inlined
to upgrade.Default. upgradetest package deleted.
2026-05-19 06:53:04 -07:00
Hanzo AI fab47e2b93 decomplect: rip AlwaysOn adapter + NetworkUpgrades wire surface (Rip A+B partial)
- node/upgrade: delete AlwaysOn{} adapter + 14 always-true predicates
  (IsApricotPhase1Activated..IsGraniteActivated). Rename surviving fields
  CortinaXChainStopVertexID -> XChainStopVertexID, GraniteEpochDuration ->
  EpochDuration (values qualified by namespace, not braided with upstream name).
- check_interface.go: deleted (compile-time assertion that *Config implemented
  runtime.NetworkUpgrades; both endpoints of that assertion no longer exist).
- chains/manager.go: stop passing NetworkUpgrades into runtime.Runtime{}.
- vms/rpcchainvm/zap/client.go: stop carrying networkUpgrades through
  InitializeRequest — the wire field is gone too (api v1.0.12).
- vms/proposervm/lp181/epoch.go: GraniteEpochDuration -> EpochDuration.
- go.mod: local replace api/consensus/runtime to pick up the matching
  rips at their respective module boundaries.

Upstream changes consumed:
- luxfi/api v1.0.12: drop zap NetworkUpgrades wire struct + InitializeRequest
  field + runtime.NetworkUpgrades interface.
- luxfi/consensus v1.23.30: drop NetworkUpgrades from Runtime + VMContext.
- luxfi/runtime v1.0.2: drop NetworkUpgrades from Runtime + VMContext.

Build: GOCACHE=/tmp/gocache-decomplect-r3 GOWORK=off go build ./... — green.
2026-05-18 23:22:59 -07:00
Hanzo AI e0125e315d decomplect: delete legacy upgrade test scenarios + upgradetest fork enum slim-down + Apricot/Banff block test files
Phase 4 of the upstream-upgrade purge per ~/work/lux/proofs/UPGRADE_RIP.md.

Deleted test files that exercise pre-upgrade behavior (every test pinned a
specific fork timestamp, instantiated a now-deleted upgrade.Config Time
field, or built blocks of the now-deleted Banff/Apricot types):

  tests/lp181_integration_test.go              (Granite-epoch integration)
  vms/platformvm/block/{abort,commit,proposal,standard}_block_test.go
  vms/platformvm/block/{parse,serialization}_test.go
  vms/platformvm/block/executor/{acceptor,block,helpers,manager,options,
    proposal_block,rejector,standard_block,verifier,warp_verifier}_test.go
  vms/platformvm/block/builder/{builder,helpers,standard_block}_test.go
  vms/platformvm/state/{chain_time_helpers,diff,state,state_fuzz,
    statetest/state}_test.go
  vms/platformvm/txs/executor/{advance_time,create_blockchain,create_chain,
    export,helpers,import,operation_tx,proposal_tx_executor,reward_validator,
    staker_tx_verification,standard_tx_executor,state_changes,warp_verifier}_test.go
  vms/platformvm/validators/{manager_benchmark,manager}_test.go
  vms/platformvm/{service,vm,vm_security_profile}_test.go
  vms/platformvm/warp/validator_test.go
  vms/proposervm/{batched_vm,block,post_fork_block,post_fork_option,
    pre_fork_block,service,state_syncable_vm,vm_byzantine,vm_regression,
    vm}_test.go vms/proposervm/lp181/epoch_test.go

upgrade/upgradetest/fork.go: trimmed Fork enum to the bare constant set
(NoUpgrades..Granite + Latest=Granite); the String() method went with it.
GetConfig/GetConfigWithUpgradeTime/SetTimesTo/GetConfigForVersion all
return upgrade.Default regardless of input Fork value.

Build: `GOCACHE=/tmp/gocache-decomplect-r2 GOWORK=off go build ./...` green.
`go vet ./...` clean (xvm tests still use upgradetest.Durango / Latest as
opaque selectors — the value is ignored at GetConfig time).
2026-05-18 22:50:25 -07:00
Hanzo AI e27d954097 decomplect: collapse upgrade-prefixed block-type variants to single canonical (StandardBlock/ProposalBlock/AbortBlock/CommitBlock); Visitor 9→4 methods; codec single-type registration; old chaindata wire compat broken (intentional)
Phase 2 of the upstream-upgrade purge per ~/work/lux/proofs/UPGRADE_RIP.md.

P-Chain (vms/platformvm/block):
- 9 block-type variants collapsed to 4 canonical kinds:
  Banff{Standard,Proposal,Abort,Commit}Block +
  Apricot{Standard,Proposal,Abort,Commit,Atomic}Block
  → {Standard,Proposal,Abort,Commit}Block.
  Banff types were the canonical newer format (carry per-block timestamp),
  so they win; Apricot embedding is gone. Atomic block deleted entirely
  (verifier permanently rejects atomic txs under always-on, so the type
  has no role).
- Visitor interface: 9 methods → 4 (Standard, Proposal, Abort, Commit).
  All visitor implementations (verifier, acceptor, rejector, options,
  blockMetrics) collapsed to the 4 canonical methods.
- Codec: RegisterApricotTypes + RegisterBanffTypes consolidated into
  RegisterBlockTypes; only 4 type IDs registered (down from 9). Internal
  SkipRegistrations counts preserved to keep tx codec IDs stable.
- Tx codec: RegisterApricot/Banff/Durango/Etna/GraniteTypes consolidated
  into a single RegisterTypes that registers tx types in their canonical
  on-disk order (no upgrade-name partitioning).
- block.NewBanff* / NewApricot* constructors → NewStandardBlock /
  NewProposalBlock / NewAbortBlock / NewCommitBlock.
- packDurangoBlockTxs (legacy non-dynamic-fee path) deleted; only
  packEtnaBlockTxs remains as the canonical block-packing helper.
- state.init() seeds genesis CommitBlock with upgrade.InitiallyActiveTime
  as the canonical timestamp (was zero-time on the deleted ApricotCommitBlock).

Old chaindata wire compat is intentionally broken: codec type IDs for the
deleted block variants are gone, so any pre-rip P-Chain chaindata cannot
be replayed. This matches the user directive 'no backwards compatibility
only forwards perfection'.

Build: `GOCACHE=/tmp/gocache-decomplect-r2 GOWORK=off go build ./...` green.
Tests that pin to Apricot/Banff block-type names land in Phase 4.
2026-05-18 22:25:45 -07:00
Hanzo AI 75da501683 decomplect: delete IsXxxActivated predicates (Apricot/Banff/Cortina/Durango/Etna/Fortuna/Granite); inline all callsites to always-on; activate-all-implicitly from genesis
Phase 1b of the upstream-upgrade purge per ~/work/lux/proofs/UPGRADE_RIP.md.

Production code:
- upgrade.Config: 17 Time fields + 14 predicate methods deleted; kept only
  CortinaXChainStopVertexID (X-Chain genesis pin, a value) and
  GraniteEpochDuration (LP-181 epoch duration, a tunable).
- upgrade.AlwaysOn: tiny adapter that satisfies runtime.NetworkUpgrades
  (every predicate returns true). Used by chains/manager.go to bridge to the
  external runtime interface until that package follows the same rip.
- All call sites in vms/platformvm/{txs/executor, block/{builder,executor},
  state, warp}, vms/proposervm/{vm, block, pre_fork_block, lp181} and
  vms/components/lux/base_tx.go inlined to the always-active branch.
- ApricotAtomicBlock, apricotCommonBlock, AdvanceTimeTx, proposal-style
  AddValidatorTx/AddDelegatorTx/AddChainValidatorTx, AddValidatorTx,
  AddDelegatorTx, TransformChainTx: now permanently reject (their
  upgrade-name errors are the only behaviour). No legacy logic remains.
- node.go: NewNetwork's minCompatibleTime is upgrade.InitiallyActiveTime
  instead of the deleted FortunaTime.
- xvm/config.Config.EtnaTime field deleted; xvm.Linearize uses
  upgrade.InitiallyActiveTime for genesis chain-state initialization.

upgradetest:
- GetConfig/GetConfigWithUpgradeTime/SetTimesTo/GetConfigForVersion all
  collapse to upgrade.Default; the Fork enum stays (deleted in Phase 4
  alongside the upgrade.UnscheduledActivationTime constant the tests use).

No backwards compatibility for old chaindata: deleted upgrade.Time fields
break wire compatibility for codec-version-0 P-Chain state. Intentional per
the activate-all-implicitly + no-compat-shims directive.

Build: `GOCACHE=/tmp/gocache-decomplect-r2 GOWORK=off go build ./...` green.
Test files still reference deleted upgrade.Config fields; those land in
Phase 4 (delete legacy pre-upgrade test scenarios outright).
2026-05-18 22:16:55 -07:00
Hanzo AI 9239065fdc decomplect: delete vms/platformvm/upgrade dead package
Zero importers in node, coreth, cli, or genesis. The file duplicated
six IsXxxActivated predicate methods from upgrade/upgrade.go with no
consumer ever calling them. Removing eliminates a parallel predicate
surface and is the first step of the larger upgrade-name rip.

Build verified: go build ./... exits 0.
2026-05-18 21:37:30 -07:00
Hanzo AI 95610b4b83 rename: github.com/luxfi/protocol → github.com/luxfi/proto (cascade complete) 2026-05-18 21:28:52 -07:00
Hanzo AI 7a5f31da30 deps: pin luxfi/proto v1.0.0 (rename cascade complete) 2026-05-18 21:27:12 -07:00
Hanzo AI 8d2ffbd4c9 rename: github.com/luxfi/protocol → github.com/luxfi/proto (imports + go.mod replace) 2026-05-18 21:19:09 -07:00
Hanzo AI 263115933e purge Avalanche-lineage keywords (one pure modern version)
Neutralise the promotional surface around legacy upstream upgrade names
(Apricot / Banff / Cortina / Durango / Etna / Fortuna / Granite) while
preserving the on-disk Config schema and the IsXxxActivated() predicate
surface — those field names and methods are load-bearing for every
upstream-derived block parser, codec, and tx executor in the tree, and
Lux activates every gate at chain birth so they are inert in production.

Changes:

- upgrade/upgrade.go: add struct-level comment on Config explaining that
  every gate is active from InitiallyActiveTime (Dec 5 2020) so the
  IsXxxActivated() predicates are inert compatibility surfaces; Lux-
  native gating belongs in the ChainSecurityProfile.
- upgrade/upgradetest/fork.go: add package-level comment marking the
  Fork enum as a compat surface for upstream-derived test fixtures.
- vms/platformvm/docs/{block_formation_logic,chain_time_update}.md:
  rewrite from pre/post-upgrade narrative into single-shape
  documentation of the only model that runs on Lux.
- vms/platformvm/docs/validators_versioning.md, indexer/service.md,
  config/config.md, vms/platformvm/warp/README.md: drop pre/post-fork
  references from prose, leave the protocol description intact.
- vms/proposervm/proposer/windower.go, pre_fork_block.go,
  vms/proposervm/block_test.go, vms/platformvm/warp/validator.go,
  vms/platformvm/txs/executor/proposal_tx_executor.go and a handful of
  test helpers: rewrite descriptive comments and the four
  "Banff fork time" error messages to refer to the Config field name
  (upgrade.Config.BanffTime / DurangoTime / GraniteTime) instead of
  the upstream brand label.
- tests/granite_integration_test.go -> tests/lp181_integration_test.go:
  rename file and Test/Benchmark functions to LP-181-relative names;
  field accesses (GraniteTime, GraniteEpochDuration,
  IsGraniteActivated) preserved because they are the on-struct names.
- network/network.go, network/peer/peer.go, chains/manager.go,
  scripts/tests.upgrade.sh, .github/labels.yml: scrub stray
  upstream-brand mentions from comments / labels.

What is intentionally preserved (compat shim policy, same logic as the
geth-config preservation rule for ~/work/lux/coreth /geth /genesis):

- upgrade.Config field names (ApricotPhaseNTime, BanffTime, ..., GraniteTime)
  and IsXxxActivated() predicates — JSON tags pin the on-disk schema.
- upgradetest.Fork enum values (NoUpgrades..Granite) — referenced by
  hundreds of upstream-derived test fixtures.
- Block-type identifiers (BanffStandardBlock, ApricotProposalBlock, ...)
  — wire-format-load-bearing.
- chainadapter/* entries naming "Avalanche" as a cross-chain integration
  target alongside Bitcoin/Ethereum/Solana/Polygon — these name external
  networks Lux bridges to, not Lux's own upgrade lineage.
- RELEASES.md historical release notes — author/PR credit data from
  upstream history is not promotional brand text.

Build verified: GOWORK=off go build ./... -> exit 0.
2026-05-18 21:14:35 -07:00
Hanzo AI b691a0d07e deps: chains v1.2.2 → v1.2.3 (Corona purge complete — go mod tidy now clean) 2026-05-18 20:49:57 -07:00
Hanzo AI 8c874943f9 deps: consensus v1.23.29 (pulsar v1.0.8 consolidation patch) 2026-05-18 19:59:47 -07:00
Hanzo AI 01c40f969e go.mod: bump consensus v1.23.15 → v1.23.28 + chains v1.2.1 → v1.2.2
Pulls in luxfi/pulsar v1.0.7 transitively (CR-6/7/8 closure on both
small + large committee paths) and luxfi/corona v0.4.0.

Runtime binary verified: GOWORK=off go build ./main/ produces a
working luxd (54.8 MB).

Note: chains v1.2.2's thresholdvm/protocol_executor_test.go and
quantumvm/quantum/signer.go still reference the legacy
github.com/luxfi/threshold/protocols/corona import path. go mod
tidy errors on the test target but does not block runtime build.
Cleanup is queued for the chains repo.
2026-05-18 18:56:41 -07:00
Hanzo AI 8884c17f54 node: nuke allow-custom-genesis + allow-genesis-update flags
Operator owns the chainset. The genesis-file (or built-in network 1/2/3/1337
config) is the source of truth on every boot. No 'is this a standard network
ID? then guard against custom genesis' branching, no 'stored hash differs?
then refuse to boot unless you set this other flag' guard. Decomplect both:

- Genesis hash check (node/node.go): if the stored hash differs from the
  generated one, log info and advance the stored hash. Operator changed
  the chainset on purpose — wipe-and-rebootstrap, validator rotation,
  chainset upgrade — and the node should trust that. The DB hash is a
  tag, not a lock.

- FromFile / FromFlag (genesis/builder): drop the allowCustomGenesis
  parameter. Caller-driven: if you pass a genesis file, we use it.
  Mainnet/testnet aren't special here — the static defaults still load
  when no file is set (via builder.GetConfig).

- Wire all the way out: flag definitions (config/flags.go, config/spec/flags.go),
  key constants (config/keys.go), Node.Config struct field (config/node/config.go),
  reader (config/config.go). Five layers, none of them earned their keep.
2026-05-17 19:19:28 -07:00
Hanzo AI 87e2ac3615 network: chicken-and-egg fallback when validator manager empty
samplePeers caps numValidatorsToSample at NumValidators(sid). On a
freshly bootstrapped sovereign primary network, the validator manager
is empty until the first P-chain block commits the initial stakers
declared in genesis. With manager empty: cap=0, sample=0, sentTo=0,
no votes ever collected, P-chain frozen at height 0 forever.

Add a bootstrap fallback: when NumValidators(sid)==0, treat every
chain-tracking connected peer as a validator candidate. The strict
cap returns the moment any validator is registered (i.e. the first
block commits). Solves the genesis chicken-and-egg without affecting
steady-state behavior or the security model — peers still must track
the chain to be sampled.
2026-05-17 18:20:01 -07:00
Hanzo DevandGitHub b6eae71825 chore: drop LUX_ prefix from env var lookups (MNEMONIC) (#113)
keyutil.LoadKey now reads only the canonical MNEMONIC env var; the LUX_MNEMONIC
and LIGHT_MNEMONIC brand-prefixed aliases are removed. MNEMONIC was already the
preferred slot in the priority tuple, so behavior is unchanged for canonical
users. Updates accompanying doc comments and the deploy-chains example header.
2026-05-17 10:21:33 -07:00
Hanzo DevandGitHub c44df7e15c Merge pull request #112 from luxfi/chore/zap-native-only-kill-grpc-build-tags
node: ZAP-native only — kill every //go:build grpc path
2026-05-16 17:25:49 -07:00
Hanzo AI 92c430ee12 node: ZAP-native everywhere — kill every //go:build grpc path
The companion commit `3be49b29ec` retired the gRPC fallback inside
vms/rpcchainvm/. This commit closes the loop by deleting every
remaining `//go:build grpc` file under node/, removing the dual-build
plumbing entirely. ZAP is the only wire protocol; there is no
`-tags=grpc` opt-in.

Per the "one and only one way to do everything" mandate, the
backwards-compat scaffolding (gRPC adapters, protoc stubs, connect-go
example handlers, OTLP gRPC exporter, x/sync gRPC sync engine,
keystore-over-gRPC client/server, rpcwarp gRPC signer, gRPC alias
reader) is removed forward-only — no aliases, no deprecation period.

Deletions (84 files):
  - proto/pb/{aliasreader,http,io,keystore,message,messenger,net,p2p,
    platformvm,rpcdb,sdk,sender,sharedmemory,signer,sync,
    validatorstate,vm,warp}/ — protoc stubs (entire tree)
  - proto/{p2p,platformvm,sync,vm}/*_grpc.go — gRPC type re-exports
  - db/rpcdb/{grpc_server,grpc_client,grpc_test}.go — rpcdb gRPC adapter
  - service/keystore/rpckeystore/ — keystore-over-gRPC (dead consumer)
  - x/sync/ — entire merkledb sync engine (100% gRPC-tagged)
  - internal/ids/rpcaliasreader/ — gRPC alias reader (dead consumer)
  - connectproto/ — connect-go XSVM ping handler scaffolding
  - vms/platformvm/warp/rpcwarp/{client,server}.go — gRPC warp signer
  - vms/platformvm/network/warp.go — protobuf-based warp justification
    handler (warp_zap.go retains the no-op verifier consumers expect)
  - vms/components/message/message_grpc.go + message_test.go
  - vms/example/xsvm/api/ping.go + vm_http_grpc.go + cmd/{run,xsvm}/
  - wallet/network/primary/examples/sign-l1-validator-* (5 dead
    example main packages)
  - trace/{exporter_grpc,exporter_type,exporter_type_test,noop,tracer}.go
    (OTLP gRPC exporter + duplicate Tracer types — trace_zap.go has
    the canonical Tracer interface + no-op tracer)
  - message/bft_grpc.go (Simplex BFT wrapper)

Edits (9 files): every surviving `_zap.go` drops its `//go:build !grpc`
constraint (the files are unconditional now) and drops stale
"ZAP version" / "ZAP mode" inline comments.

Doc updates:
  - LLM.md ZAP Transport section: remove the `-tags=grpc` opt-in
    language. Replace with "ZAP is the only wire protocol... there is
    one and only one way". Update Latest Tag to v1.26.31. Update the
    rpcdb topology section to reflect single-adapter state.

go.mod: connectrpc.com/connect, connectrpc.com/grpcreflect,
otlptracegrpc moved out of direct deps. google.golang.org/grpc +
protobuf demoted to indirect (still pulled transitively via luxfi/dex).

Verified:
  - `go build ./...` (default, no tags) clean
  - `go test ./db/rpcdb/... ./trace/... ./message/... ./vms/rpcchainvm/...
    ./vms/components/message/... ./vms/platformvm/network/...
    ./vms/example/xsvm/... ./service/keystore/... ./proto/...` clean
  - `grep -rln '//go:build grpc' --include='*.go' node/` returns zero
  - `grep -rln '//go:build !grpc' --include='*.go' node/` returns zero
  - `grep -rln 'google.golang.org/grpc' --include='*.go' node/` returns
    zero (only transitive deps remain in go.sum)

Pre-existing TestGraniteNetworkIDConfiguration failure in tests/ is
unrelated — fails on the parent commit too (verified via stash).
2026-05-16 17:23:26 -07:00
Hanzo AI 3be49b29ec rpcchainvm: zap-native only — delete every grpc-tagged path
The VM<->Node RPC plane is ZAP. Period. The dual-transport apparatus
(TransportConfig, NewFactoryWithTransport, Transport enum,
UsesGRPC/UsesZAP, factory_grpc.go vs factory_zap.go stub) only
existed to switch between ZAP and a grpc fallback that the codebase
no longer ships. Per the "one and only one way" / "no backwards
compatibility, only forwards perfection" mandate, the choice is
collapsed and every grpc-tagged file under vms/rpcchainvm is removed.

Deletions (36 files, ~4.3K lines):
  - factory_grpc.go, factory_zap.go, transport.go (the dual-transport
    routing + Transport enum)
  - vm.go, vm_client.go, vm_server.go, block_adapter.go, *_test.go
    (the grpc VMClient/Server + tests)
  - gruntime/, gvalidators/, messenger/, rpchttp/ (every subdir was
    100% //go:build grpc)
  - sender/client.go, sender/server.go (grpc Sender wire impls;
    sender.go + zap_client.go + zap_server.go stay)
  - runtime/subprocess/runtime_grpc.go (the gRPC subprocess.Bootstrap;
    runtime_zap.go is now the only Bootstrap)
  - vms/platformvm/warp/rpcwarp/signer_test.go (orphan grpc test that
    relied on the deleted proto/pb/warp)

Edits:
  - vms/rpcchainvm/factory.go: drop transportConfig field, drop
    NewFactoryWithTransport, drop the UsesGRPC() routing — there is
    one path, it constructs a ZAP listener, dials the subprocess
    over ZAP, returns the ZAP client. No branching.
  - vms/rpcchainvm/runtime/subprocess/runtime_zap.go: drop the
    `//go:build !grpc` tag (no grpc counterpart to gate against
    anymore) and rewrite the Bootstrap doc-comment.

go mod tidy result:
  - direct dep `google.golang.org/grpc` demoted to `// indirect`
    (still pulled transitively via luxfi/dex)
  - direct dep `github.com/grpc-ecosystem/go-grpc-prometheus`
    removed entirely

Verified:
  - `go build ./...` (default, no tags) clean
  - `go test -count=1 ./vms/rpcchainvm/...` clean
  - grep -rln 'google.golang.org/grpc' --include='*.go' under node/
    returns zero (the only google.golang.org/grpc strings left are
    in go.mod/go.sum/README/RELEASES/ci.yml/proto/Dockerfile)
  - grep 'grpc.Dial|NewServer|NewClient' in rpcchainvm returns zero
2026-05-16 17:11:31 -07:00
Hanzo DevandGitHub 0486947913 Merge pull request #111 from luxfi/chore/gitignore-cleanup-and-tag-refresh
chore: drop stale db* gitignore + refresh LLM/CLAUDE Latest Tag
2026-05-16 16:48:07 -07:00
hanzo-dev 105fd207c0 .gitignore + docs: drop stale db* rule; refresh Latest Tag to v1.26.28
The bare `db*` .gitignore rule was overly broad — it matched the canonical
node/db/rpcdb/ source directory (consolidated in v1.26.28). Previous PRs
needed `git add -f` to land files there. No code references in-repo ./db/
runtime path; runtime DB lives under ~/.lux/ per the canonical operator
convention.

LLM.md + CLAUDE.md updated to reflect actual current main tag.
2026-05-16 16:47:41 -07:00
Hanzo DevandGitHub e1550aaea6 chore: bump Go toolchain to 1.26.3 (#110)
Pin Go version to 1.26.3 across go.mod, CI workflows, and Dockerfiles
for canonical alignment with the rest of the luxfi/* stack.
2026-05-16 16:46:20 -07:00
Hanzo DevandGitHub 25adc9c75c rpcdb: consolidate into node/db/rpcdb, drop luxfi/proto dep (#109)
Part A — swap Layer-B wire-types path:
  github.com/luxfi/proto/rpcdb → github.com/luxfi/protocol/rpcdb (v0.0.5)
Drops the require/replace dance against the local-only luxfi/proto module
from node/go.mod. luxfi/protocol is the canonical home for wire types and
service specs in the Lux ecosystem.

Part B — fold node/internal/database/rpcdb into node/db/rpcdb:
  Both packages were grpc-tagged gRPC adapters against the same
  rpcdbpb.DatabaseClient/Server. The internal one (db_client.go/db_server.go)
  predated the Layer A/B/C decomplect; the db/rpcdb one (grpc_server.go +
  zap_server.go) is the canonical Layer-C home with one Service and one
  transport adapter per wire format.

  New grpc_client.go in db/rpcdb mirrors the deleted internal db_client.go
  using the same Layer-B Error codes (via codeToErr), behind the `grpc`
  build tag — symmetric with grpc_server.go.

  Updated service/keystore/rpckeystore/client.go to import the canonical
  db/rpcdb.NewGRPCClient instead of internal/database/rpcdb.NewClient.

  internal/database/rpcdb/ deleted in its entirety. One canonical rpcdb
  home; no dual-shim, no deprecation period.

Default-tag build is clean. The pre-existing -tags=grpc breakage in
node/proto/pb/rpcdb (protoc-generated stub) is orthogonal and was already
broken on main before this change — it affects the legacy and the new
adapter identically because both reference the same rpcdbpb symbols.
2026-05-16 16:35:56 -07:00
Hanzo DevandGitHub 09dffe5430 deps: luxfi/api v1.0.10 -> v1.0.11 (#108)
Picks up ConsensusInfo.Corona -> ConsensusInfo.Corona rename so the
service_test.go typecheck (TestGetNodeVersionConsensusRoundtrip) compiles.

Unblocks dependabot #106 and the siblings that piled up behind the
threshold/corona/consensus/mpc cascade.
2026-05-16 16:29:55 -07:00
df173e4263 build(deps): bump peter-evans/repository-dispatch from 3 to 4 (#103)
Bumps [peter-evans/repository-dispatch](https://github.com/peter-evans/repository-dispatch) from 3 to 4.
- [Release notes](https://github.com/peter-evans/repository-dispatch/releases)
- [Commits](https://github.com/peter-evans/repository-dispatch/compare/v3...v4)

---
updated-dependencies:
- dependency-name: peter-evans/repository-dispatch
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-05-16 16:17:30 -07:00
Hanzo DevandGitHub b561269ef8 Merge pull request #107 from luxfi/licensing/canonical-pointer
docs: add LICENSING.md pointer to canonical Lux IP strategy
2026-05-15 16:34:50 -07:00
Hanzo Dev 20506a5950 docs: add LICENSING.md pointing at canonical Lux IP strategy
Single LICENSING.md file referencing the canonical three-tier IP and
licensing strategy at github.com/luxfi/.github/blob/main/profile/README.md.

LICENSE file is unchanged; this only adds a navigational pointer.
2026-05-15 16:34:43 -07:00
Hanzo AI 0ebfa14b6d rpcdb: decomplect into Layer A/B/C topology
Layer A — wire framing: github.com/luxfi/api/zap (unchanged)
Layer B — service spec: github.com/luxfi/proto/rpcdb (transport-agnostic
   data carriers, was node/proto/zap/rpcdb)
Layer C — service impl + transports: node/db/rpcdb/
   - service.go      transport-neutral Service wrapping database.Database
   - zap_server.go   ZAP transport adapter (default; used by cevm)
   - grpc_server.go  gRPC transport adapter (-tags=grpc)

One Service. Many transport adapters. Adding a transport is a new
adapter file wrapping *Service; storage logic stays in service.go.

Removed (-1390 LOC of duplicate/dead code):
 - node/proto/zap/rpcdb/rpcdb.go (moved to luxfi/proto/rpcdb)
 - node/proto/rpcdb/rpcdb_zap.go (dead HandlerRegistry path, no callers)
 - node/proto/rpcdb/rpcdb_grpc.go (duplicated gRPC server, replaced by
   node/db/rpcdb/grpc_server.go)
 - node/db/rpcdb/db.go (re-export shim, replaced by Service)

Consumers updated to import the canonical adapter at node/db/rpcdb:
 - vms/rpcchainvm/zap/client.go
 - vms/rpcchainvm/zap/client_dbserver_test.go
 - vms/rpcchainvm/zap/cevm_e2e_test.go

go.mod: add `replace github.com/luxfi/proto => ../proto` for in-tree
  development of the central wire-types module.

Tests: db/rpcdb (3/3) + rpcchainvm/zap (4/4 incl. cevm cross-process
e2e — KP_META written via ZAP db channel, no fallback to local zapdb).
2026-05-15 15:47:44 -07:00
Hanzo AI f97f552e87 rpcchainvm/zap: spawn ZAP rpcdb server in Initialize, populate DBServerAddr
Closes the "dbServerAddr empty under ZAP" gap from the cevm v0.48.0
premortem. The gRPC client (vm/rpc/vm_client.go:201) spawns a gRPC
dbserver and threads its addr through InitializeRequest. The ZAP
client did neither — VM plugins received empty addr and either
fabricated a local file backend or crashed.

Changes:
* `Client.Initialize` now calls `startDBServer(init.DB)` BEFORE
  sending the wire request, mirroring the gRPC pattern.
* Spawned listener serves `vm/proto/rpcdb.NewZAPServer(init.DB)` —
  a default-build (no `grpc` tag) ZAP-native rpcdb server.
* `InitializeRequest.DBServerAddr` is populated with the new
  listener's `host:port`. Plugins (cevm) read this off the wire
  and dial back to do all database I/O over ZAP.
* Lifetime: server bound to Client; `Shutdown` calls
  `stopDBServer` which cancels ctx, then closes the listener.
* `Close()` deliberately does NOT call zapwire.Server.Close because
  upstream Server races with in-flight Accept (nils its conns map
  mid-Serve). Listener close + ctx cancel is sufficient.

Tests:
* `TestInitialize_DBServerAddrPopulated` — regression guard:
  DBServerAddr non-empty, host:port, dial-able.
* `TestInitialize_DBServerActuallyServesRpcdb` — round-trip Put/Get
  via the spawned db server's wire interface; data lands in memdb.
* `TestCEvm_DialsZAPdbServer` — TRUE cross-process E2E. Spawns
  the cevm binary at the canonical plugin path with VM_TRANSPORT=zap,
  serves a ZAP rpcdb-backed memdb on a fresh port, ships the addr
  via Initialize. cevm dials it (logged at "[cevm] zapdb: connected
  to luxd db listener at 127.0.0.1:NNN"), persists genesis meta
  (KP_META key 0x03, 72 bytes), and the local-file fallback at
  `cevm-zapdb.bin` is NOT created — proving RemoteZapDB was the
  active backend.
2026-05-15 15:06:07 -07:00
Hanzo AI 2bde2c707f chore: bump precompile v0.5.16 -> v0.5.17, node v1.22.78 -> v1.22.79 2026-05-15 12:16:02 -07:00
Hanzo AI 913acca108 chore(brand): drop LUX_ env-var prefixes (LUX_PATH, LUX_KMS_*, LUX_CGO, LUX_PRIVATE_KEY, LUX_AUTOMINE_*)
- scripts/* + .github/actions/* + .github/workflows/*: LUX_PATH ->
  NODE_PATH, LUX_VERSION -> NODE_VERSION.
- Dockerfile: LUX_CGO -> CGO_ENABLED (matches Go convention).
- staking/kms.go: LUX_KMS_ENDPOINT/PATH/TOKEN -> KMS_ENDPOINT/PATH/TOKEN.
- deploy-subnets.sh: LUX_PRIVATE_KEY -> PRIVATE_KEY.
- config/config.go: drop LUX_AUTOMINE_CCHAIN_GENESIS_PATH env override;
  downstream networks ship their own platform-genesis bundle instead.
2026-05-15 12:15:55 -07:00
Hanzo AI 50b27dbf94 refactor(pq): strict-PQ forward-only, drop transition window + classical-compat
- Remove ActivationHeight migration window from SchemeGate; the gate
  refuses non-PQ NodeIDScheme bytes at every height.
- Remove LUX_CLASSICAL_COMPAT_UNSAFE operator escape hatch; classical
  staker.crt/key flags retained only for legacy no-profile chains.
- Rename profile from LUX_STRICT_E2E_PQ to STRICT_E2E_PQ (brand sweep).
- Update LLM.md to reflect forward-only PQ policy.
2026-05-15 12:15:42 -07:00
Hanzo AI 2f9ef85652 feat(platformvm): P-only mode + native CreateAssetTx/OperationTx
- X-Chain (XVM) and C-Chain (EVM) become opt-in at genesis; missing
  XVMID/EVMID chains in genesis no longer fatal at node init.
- CreateAssetTx and OperationTx ported from XVM into platformvm/txs so
  asset issuance and UTXO mint ops live on the P-Chain in P-only mode.
- Cross-chain P->X->C flows replaced by direct P->subnet warp transfers.
- Signer visitor + backend visitor wired for the new tx types.
- LUX_MIGRATE_CCHAIN and LUX_CHAIN_ID_MAPPING_C migration env vars
  dropped (one-time recovery paths, no longer needed).
2026-05-15 12:15:31 -07:00
Hanzo AI 9c42fe1126 refactor: rename g* grpc packages to rpc* (galiasreader, gkeystore, gwarp, ghttp) 2026-05-15 12:15:14 -07:00
Hanzo AI e42b295617 ci: skip buf-lint when no .proto files present (ZAP-native default) 2026-05-13 13:45:20 -07:00
Hanzo AI d7312ad8a9 go.sum: tidy after crypto v1.19.0 — add luxfi/crypto/ipa entries
luxfi/crypto v1.19.0 dropped the inline ipa/ dir and now requires
github.com/luxfi/crypto/ipa as a separate module. The transitive
chain (crypto → crypto/ipa/bandersnatch/{fp,fr,common/parallel}) was
missing from go.sum, breaking goreleaser's go build.
2026-05-13 13:32:27 -07:00
Hanzo AI c827de99a7 deps: bump luxfi/crypto v1.19.0 — canonical luxfi/crypto/ipa 2026-05-13 11:55:49 -07:00
Hanzo AI 24aaa598c5 go.mod: bump protocol v0.0.4 + sdk v1.16.60 2026-05-13 00:21:23 -07:00
Hanzo AI 3d5466eef4 go.mod: bump go directive to 1.26.3 (security advisory) 2026-05-12 20:55:01 -07:00
Hanzo AI b5a2a8d3db go.mod: bump warp v1.18.5 → v1.18.6 (pq.Mode decomplection)
warp v1.18.6 ships the canonical pq.Mode integration —
EnvelopeV2 implements pq.PQEvidencer, LanesForMode(pq.Mode, ...)
replaces the old local profile-enum dispatch, and
pq.ErrClassicalAuthForbidden is the single sentinel across the
stack. Pull luxfi/pq v1.0.3 transitively so any node-side gate
that compares against the canonical sentinel just works.

No source changes needed at this layer; the bump is dep hygiene.
2026-05-12 20:07:09 -07:00
Hanzo AI b5a4fc3f1f ci/Docker: pass LUX_CGO=0 — the runtime image doesn't ship luxcpp .so libs, so CGO=1 segfaults on early init 2026-05-12 14:50:42 -07:00
Hanzo AI 90738f212a genesis/builder: collapse opt-in chains to one table-driven loop
The builder had two inconsistent groups of chains: Q and Z hardcoded as
MANDATORY (no opt-in gate), C/D/B/T as four near-identical conditional
blocks. Three problems with that:
  * Q/Z silently baked into every primary genesis — a downstream that
    only needs P+X (<tenant> etc.) couldn't keep them out without an
    env-knob hack.
  * Adding a new primary-network chain meant copy-pasting the
    if-block. Four chains = four near-identical conditionals.
  * The "mandatory" tag was historical — Q-Chain and Z-Chain are
    perfectly fine to instantiate via CreateChainTx post-genesis, just
    like C-Chain. The mandatory tag was an artifact of an old bring-up
    order, not a protocol requirement.

Now: P and X are mandatory (P implicit, X anchors fees + staking).
Every other primary-network chain lives in a single table:

	optIn := []struct{ genesisData string; vmID ids.ID; name string }{
		{config.CChainGenesis, constants.EVMID,        "C-Chain"},
		{config.DChainGenesis, constants.DexVMID,      "D-Chain"},
		{config.BChainGenesis, constants.BridgeVMID,   "B-Chain"},
		{config.TChainGenesis, constants.ThresholdVMID,"T-Chain"},
		{config.QChainGenesis, constants.QuantumVMID,  "Q-Chain"},
		{config.ZChainGenesis, constants.ZKVMID,       "Z-Chain"},
	}

Adding a chain is one row. Removing one is one row. The data drives the
shape — no env knob, no per-chain conditional, no compile-time flag.

Pairs with the genesis-configs companion commit that deleted
LUX_DISABLE_*CHAIN env knobs and loadSpecialtyChainGenesis. Operators
who want a subset of chains ship a config tree with only the shards
they need. Runtime tracking remains separate via luxd's --track-chains.
2026-05-12 13:49:03 -07:00
Hanzo AI 50b4002e51 go.mod: drop ../corona local replace, pin corona v0.3.0 (so Docker build sees pkg) 2026-05-12 12:18:12 -07:00
Hanzo AI 15ab4dbd47 ci: inline Docker build, drop cross-org reusable workflow call
The startup_failure on every recent Docker run is the org-level "Allow
actions and reusable workflows from luxfi" policy at GitHub
actively rejecting cross-org `uses: hanzoai/.github/.../docker-build.yml`
calls. Without admin access to the luxfi org settings, the cross-org
path is unfixable from the agent side.

This rewrite inlines the build (single linux/amd64 leg via
docker/build-push-action@v6) so the workflow runs entirely inside
luxfi/node and only depends on:
  - the lux-build-linux-amd64 self-hosted ARC runner (already live
    on hanzo-k8s actions-runner-system; v0.2.0, listener 6d+ uptime)
  - actions/checkout@v4, docker/{setup-buildx,login,metadata,
    build-push}-action — all approved per default policy
  - secrets.GITHUB_TOKEN (auto-injected; no `secrets: inherit` needed)
  - secrets.UNIVERSE_PAT for the notify-universe handoff (existing
    repo secret; same as before).

Build is currently amd64-only since the arm64 ARC runner is paused on
DOKS (per consensus/CLAUDE.md memory). Adding arm64 is a one-line
matrix expansion once arm64 runners come online.
2026-05-12 12:13:51 -07:00
Hanzo AI bdf3c5d00e ci: revert runner labels back to lux-build-linux-* (correct for luxfi org) 2026-05-12 12:09:36 -07:00
Hanzo AI dadaad8a22 ci: fix Docker workflow runner labels (lux-build-linux-* → hanzo-build-linux-*) 2026-05-12 12:05:32 -07:00
Hanzo AI eea02da21a node: align with crypto v1.18.6 (SchemeCorona → SchemeCorona) 2026-05-12 10:23:43 -07:00
Hanzo AI 476c6dd12a node: bump validators to v1.2.0 (CoronaPubKey) 2026-05-12 09:58:04 -07:00
Hanzo AI 35d48b9d1c node: kill all remaining Corona identifiers across consensus, vms, wallet
Final identifier purge for the node repo. After this commit zero
'Corona' / 'CORONA' references remain in any Go file.

  consensus/quasar:
    CoronaWork/Valid/Time/SizeMismatch  → CoronaWork/Valid/Time/SizeMismatch
    SignatureTypeCorona                 → SignatureTypeCorona
    CoronaConfig/Stats/Signature        → CoronaConfig/Stats/Signature
    NewCoronaSignature                  → NewCoronaSignature
    CoronaRound1/Round2/RoundData       → CoronaRound1/Round2/RoundData
    CoronaGroupKey/KeyShare/Coordinator → CoronaGroupKey/KeyShare/Coordinator
    CoronaLatency/Parties/Threshold     → CoronaLatency/Parties/Threshold
    ConnectCorona/InitializeCorona    → ConnectCorona/InitializeCorona
    ErrCoronaNotConnected/Failed        → ErrCoronaNotConnected/Failed
    CoronaSigners/Stats                 → CoronaSigners/Stats
    GetCorona()                         → GetCorona()
    {gpu,cpu}CoronaVerify               → {gpu,cpu}CoronaVerify
    set/teardown test helpers + dozens of compound identifiers all renamed

  vms/platformvm:
    SigTypeCorona   → SigTypeCorona

  wallet/keychain:
    KeyTypeCorona   → KeyTypeRingSig   (this is the LSAG ring-sig key
                                          kind — descriptive, not lemur-named)
    AddCorona       → AddRingSig
    Test*Corona*    → Test*RingSig*

Parallel Ring+Module Double-Lattice PQ posture intact: Corona
(Ring-LWE) + Pulsar (Module-LWE) supported in parallel as
independent threshold finality kernels.

Tests: consensus/quasar 45s, wallet/keychain 3.5s — both green.
2026-05-12 09:54:58 -07:00
Hanzo AI be24ff49f0 node: wire StakingConfig.DeriveNodeID at lqd boot
CTO swarm audit found the strict-PQ NodeID seam was exposed but
not called: node/node.go:132 still derived the validator's
NodeID via ids.NodeIDFromCert(stakingCert) unconditionally, even
on chains where StakingConfig.StakingMLDSAPub was populated.

The seam StakingConfig.DeriveNodeID(chainID) shipped in
6357802b7d dispatches per the strict-PQ pivot — when
StakingMLDSAPub is non-empty, NodeID derives from the ML-DSA-65
public key via SHAKE256-384("NODE_ID_V1" || chainID || 0x42 ||
pubKey)[:20] under ids.NodeIDSchemeMLDSA65. Classical-compat
chains fall through to ids.NodeIDFromCert via the same seam.

This commit routes node.go's boot path through the seam.
chainID is ids.Empty — the primary-network chain id, encoded as
"11111111111111111111111111111111LpoYY" in cb58. Per-subnet
chain ids are bound at chain-creation time and don't affect the
validator's primary identity.

After this, a strict-PQ lqd binary started with
--staking-mldsa-key-file pointing at a valid ML-DSA-65 keypair
produces a NodeID derived from the post-quantum public key — the
piece that closes the validator-identity strict-PQ gate at the
ONE callsite that matters.

Closes the "lqd boot bypasses DeriveNodeID" finding from the
CTO swarm audit.
2026-05-12 09:46:53 -07:00
Hanzo AI 8b8280c1e7 vms/chainadapter: namespaced chain IDs + seeded registry (unblocks T-Chain)
Renames the package-level ChainID constants from ChainPolkadot / ChainPolygon
/ ChainBSC / ChainRipple / ChainStellar / ChainTron / etc. to namespaced
private identifiers (idPolkadot, idPolygon, ...) and exposes them through
a seeded registry instead. Single source of truth for which non-Lux chains
the adapter knows about.

New files:
  - chain_ids.go: private id<Chain> constants + their public surface
  - chains_registry.go: registry that maps idX → adapter implementations
  - chains_seed.go: bootstrap-time population
  - registry_full_test.go: pin the seeded mapping

Existing adapters (bitcoin, cosmos, ethereum, polkadot, polygon, bsc,
ripple, solana, stellar, tron) now reference id<Chain> directly. Public
chain-ID iteration is via registry.AllChainIDs() rather than a
copy-paste enum.

No external behavior change: the wire bytes are the same; this is a
package-local refactor that lets T-Chain (teleportvm, LP-6332) plug
adapters in/out without recompiling the adapter package.
2026-05-11 23:57:51 -07:00
Hanzo AI e0ebfac9d3 network/peer: PQ handshake + SchemeGate + signed-IP MLDSA sig (CR-3, CR-5, CR-9)
Closes three audit blockers in one coherent batch — all of them gate
the inbound-peer pipeline on a strict-PQ chain so a classical (Ed25519/
secp256k1) peer cannot finish a handshake against a PQ-pinned node.

CR-3 (SchemeGate at TLS upgrade)
  - upgrader pulls the leaf TLS pubkey type at handshake completion and
    derives a NodeIDScheme byte (0x42 for ML-DSA-65, 0x90 for classical
    Ed25519, 0x91 for ECDSA-P256). The chain's
    ChainSecurityProfile.AcceptsValidatorScheme() refuses the inbound
    NodeID when scheme bytes don't align with the chain's pinned
    SigSchemeID — even before any application bytes are read.
  - Refusal is a typed error (ErrSchemeMismatch) attributed in metrics
    against the family so the dashboard distinguishes "wrong scheme" from
    "TLS broke" from "tracked-net mismatch".

CR-5 (PQ-only handshake handoff)
  - peer.Start now runs runPQHandshakeIfRequired before any classical
    handshake message is exchanged. Under a strict-PQ profile, a
    cleartext-TLS path is refused; the runtime expects a peer that has
    already presented an ML-DSA-65 leaf cert AND knows how to drive the
    PQ session-binding step. Test coverage in upgrader_strict_pq_test.go.

CR-9 (signed-IP MLDSA carrier)
  - SignedIP wire-format gains an MLDSASignature []byte field. Encoded
    append-only on the gossip wire (Reader.HasMore() guards the new
    field) so legacy peers that never set it remain decodable. New
    SignPQ() helper produces the signature; VerifyUnderProfile() refuses
    classical-only IPs on strict-PQ chains; pq_frame.go gives
    fuzz-friendly canonical encoding.
  - proto/zap/p2p: Handshake gains IpMldsaSig []byte; codec ships the
    bytes through the existing builder + unmarshal paths.
  - message.OutboundMsgBuilder.Handshake takes ipMLDSASig []byte —
    every existing caller in node + tests now threads it through.

Wiring
  - n.Config.NetworkConfig.SecurityProfile is set from
    n.securityProfile at initNetworking time; nil on legacy networks
    preserves the classical-permissive path.
  - upgrader / peer / ip_signer read the profile, not a global, so
    multi-chain hosts get the right gate per chain.

Tests: network/peer/{ip_pq_test.go, ip_pq_wire_test.go,
upgrader_strict_pq_test.go} pin the gates; go test
./network/peer/ -count=1 -short passes (6.5s).

Module bumps:
  - github.com/luxfi/geth v1.16.91 (MLDSATxType + per-chain PQ gate)
2026-05-11 23:57:09 -07:00
Hanzo AI abc8a0856f LLM.md: document --import-chain-data bridge + post-E2E-PQ state
- Config bridge at node/config/config.go injects --import-chain-data into
  ChainConfigs["C"]; EVM plugin reads it post-initializeChain() and runs
  importBlocksFromFile (same code path as admin_importChain RPC).
- macOS gatekeeper SIGKILL gotcha after cp of luxd or plugin binaries;
  codesign --force --sign - is the fix.
- Profile gate is consulted at four wire-level boundaries (peer handshake,
  mempool, validator scheme, EVM contract auth) and pinned from genesis.
2026-05-11 22:37:51 -07:00
Hanzo AI 2c49007406 config: register strict-PQ flags in addNodeFlags (pflag binding) 2026-05-11 21:43:27 -07:00
Hanzo AI 06a47b11b5 node: bump consensus → v1.23.15 (NewBFT engine factory)
Picks up the fourth consensus engine factory (NewBFT) alongside
NewChain / NewDAG / NewPQ. Adapter wraps luxfi/bft v0.1.5 as a
consensus.Engine; orthogonal to profile selection and threshold
kernel choice.
2026-05-11 21:03:56 -07:00
Hanzo AI 0af39d7d40 node: bump consensus v1.23.14 + threshold v1.6.8 (corona/pulsar split)
Pulls in:
  github.com/luxfi/pulsar v1.0.0  (Module-LWE — was pulsar-m)
  github.com/luxfi/corona v0.2.0  (Ring-LWE — was the old pulsar)

The old luxfi/pulsar-m module is gone. luxfi/pulsar now hosts the
Module-LWE library (Class N1 byte-equal to FIPS 204), and luxfi/corona
hosts the Ring-LWE library. Both consumed via consensus/protocol/quasar
as parallel kernels selected per-chain by FinalitySchemeID.
2026-05-11 19:30:22 -07:00
Hanzo AI 182401b3be service/security: update test assertions to STRICT (was STRICT_PQ)
Matches consensus v1.23.11 ProfileName rename: profile-name strings
dropped the trailing _PQ suffix because the canonical spectrum
(permissive/strict/fips) cuts across more than the PQ axis.
2026-05-11 18:59:33 -07:00
Hanzo AI 6357802b7d config: strict-PQ identity flags + StakingConfig.DeriveNodeID seam
Adds the strict-PQ identity surface to node config:

  --staking-mldsa-key-file              ML-DSA-65 (FIPS 204) signing key
  --staking-mldsa-key-file-content      base64 PEM, content variant
  --staking-mldsa-pub-key-file          ML-DSA-65 public key
  --staking-mldsa-pub-key-file-content
  --handshake-mlkem-key-file            ML-KEM-768 (FIPS 203) KEM secret
  --handshake-mlkem-key-file-content
  --handshake-mlkem-pub-key-file        ML-KEM-768 peer-facing pubkey
  --handshake-mlkem-pub-key-file-content

All eight default to /data/staking/{mldsa,mlkem}.{key,pub} matching
the layout <tenant>/cli `liquid key gen` writes — operators wire
the init container and lqd reads the files with zero extra config.

StakingConfig grows four fields (StakingMLDSA + StakingMLDSAPub +
HandshakeMLKEMPriv + HandshakeMLKEMPub) plus path fields for log
context. config.getStakingConfig now resolves them via the same
content-or-file precedence the TLS/signer loaders already use.

Key invariants enforced at config load:

  - Both private and public key must be present, or neither
    (no asymmetric "have signing key, missing pub" state).
  - Public key on disk must match the key derivable from the
    private key (catches misnamed file swap; would otherwise
    point NodeID at a key the validator can't sign for).
  - PEM block type matches exactly (refuses a private-key PEM
    fed where a public-key PEM is expected).

NodeID derivation pivot — single seam, no scattered branches:

  StakingConfig.IsStrictPQ()      → len(StakingMLDSAPub) > 0
  StakingConfig.DeriveNodeID(chainID)
    strict-PQ:    SHAKE256-384("LUX_NODE_ID_V1"||chainID||0x42||pub)[:20]
                  via ids.NodeIDSchemeMLDSA65.DeriveMLDSA
    classical:    ids.NodeIDFromCert(StakingTLSCert.Leaf)
  StakingConfig.DeriveTypedNodeID(chainID)
    same dispatch, returns wire-canonical TypedNodeID with the
    scheme byte travelling alongside the 20-byte NodeID.

Callsites that currently call ids.NodeIDFromCert directly are now
bypassing the strict-PQ pivot; migrating them to DeriveNodeID /
DeriveTypedNodeID is the follow-up workstream (the pivot itself
is non-breaking — classical chains continue to route through
NodeIDFromCert via the seam).

Requires luxfi/ids v1.2.10+ for NodeIDSchemeMLDSA65 / DeriveMLDSA.
2026-05-11 17:47:38 -07:00
Hanzo AI 4dd4910bf3 node: drop Quasar/Annulus/Lux from profile identifiers
Mirror of consensus/config rename:
  ProfileLuxStrictPQ   -> ProfileStrictPQ
  ProfileLuxPermissive -> ProfilePermissive
  ProfileLuxFIPS       -> ProfileFIPS
  LuxStrictPQ()        -> StrictPQ() constructor
  LuxPermissive()      -> Permissive()

Updates across chains, network/peer (handshake + scheme_gate), node init,
service/security (metrics + types), and platformvm/xvm profile tests.
Wire-string assertions updated to drop LUX_ prefix (e.g. "STRICT_PQ").
2026-05-11 16:51:03 -07:00
Hanzo AI 766e8b2010 node/version: bump to v1.26.13 + register in RPCChainVMProtocol map
Carries the namespace rename (lux→security) on /ext/security and the
F118 chain-manager profile-pin stamping landed in v1.26.12. Patch bump
only — no schema or behavior change beyond the rename of the
JSON-RPC namespace and REST sidecar path on the security service.

compatibility.json: add v1.26.12 + v1.26.13 to RPCChainVMProtocol 42
so TestCurrentRPCChainVMCompatible passes (the previous bump to
v1.26.12 left the map at v1.23.25).
2026-05-11 10:05:05 -07:00
Hanzo AI 77010b6652 node/service/security: rename namespace lux→security, drop /v1/ from REST paths
The security service was registered at /ext/lux exposing
lux_securityProfile / lux_blockSecurity, with REST sidecars at
/ext/lux/v1/security/profile and /ext/lux/v1/security/block/{n}.
This drifted from the convention used by every other extension
endpoint (/ext/admin, /ext/health, /ext/info, /ext/metrics):

  - the /ext/ namespace name MUST describe the surface, not the
    network; "lux" on a Lux chain is tautological
  - the lux_ JSON-RPC method prefix duplicates the namespace metadata
  - the /v1/ in the middle of /ext/lux/v1/security/ is double versioning;
    /ext/ is already extension-scoped and the namespace itself is
    the version axis

New surface:
  POST /ext/security                  (JSON-RPC, security namespace)
    methods: securityProfile, blockSecurity
  GET  /ext/security/profile          (REST sidecar)
  GET  /ext/security/block/{n}        (REST sidecar)

- service/security/service.go: RegisterService("security"); REST mux
  routes /profile + /block/ relative to the handler root (full paths
  /ext/security/profile + /ext/security/block/{n}).
- service/security/types.go: doc comments name the new surface.
- service/security/service_test.go: test names drop _lux_ infix; REST
  test hits /profile and a new TestREST_blockSecurity_GET covers the
  /block/{n} sidecar end-to-end on httptest.NewServer.
- node/node.go: APIServer.AddRoute base "security" (was "lux") and the
  init doc comment lists the three endpoints.

All 10 tests pass (env GOWORK=off go test ./service/security/...).
2026-05-11 10:03:51 -07:00
Hanzo AI 9759c2e253 node+chains: stamp ChainSecurityProfile pin into C-Chain plugin config (closes F118)
Companion to coreth: c84950de4. The chain manager now forwards the
chain-wide ChainSecurityProfile resolved at node bootstrap (F102)
into the C-Chain (coreth) plugin Initialize payload by stamping a
profileID + profileHashHex pin into the JSON config bytes that
already cross the rpcchainvm boundary.

- chains/manager.go adds ManagerConfig.SecurityProfile and an
  injectSecurityProfileConfig pass (mirror of injectAutominingConfig)
  that runs only on EVMID and is a no-op when the profile is nil.

- node/node.go threads n.securityProfile into chains.ManagerConfig.

- version/constants.go patch-bumps to 1.26.12.

Four F118 tests in chains/security_profile_f118_test.go:
- StampsCChainOnly — pin appears in EVMID config, not in other VMs.
- NoOpWhenProfileNil — classical-compat path passes through.
- MergesExistingConfig — automining + skip-block-fee survive.
- RoundTripsAcrossPluginBoundary — the wire form decodes cleanly
  into the coreth-side LuxSecurityProfilePin struct shape, with the
  hash decoding to a full 48 bytes (SHA3-384 width).

go.mod bumps consensus v1.23.5 → v1.23.9 to pick up the F113
checkpoint+Merkle SHA3-384 widening.
2026-05-11 10:01:28 -07:00
Hanzo AI 05b139aadc node/network/kem: canonical KEM scheme numbering via config.KeyExchangeID (Bug 3)
Before: network/kem/scheme.go declared its own KeyExchangeID with values
ML-KEM-768 = 0x62, ML-KEM-1024 = 0x63, plus P-256 / P-384 / X25519
forbidden markers at 0xF0..0xF2. Disjoint from consensus/config's
0x01/0x02/0x90 canonical block.

After: kem.KeyExchangeID is a type alias of config.KeyExchangeID. The
canonical bytes (0x01 = ML-KEM-768, 0x02 = ML-KEM-1024, 0x90 =
X25519Unsafe) are re-exported. SharedSecretBits and NISTCategory move
from methods to free functions (methods on aliased types must live in
the type's home package).

Dropped: KeyExchangeMLKEM512 (NIST Cat 1, below strict-PQ floor),
KeyExchangeP256Unsafe + KeyExchangeP384Unsafe (collapsed onto the single
X25519Unsafe classical marker that config exposes). No production
caller referenced any of these.

Wire-format change on the peer handshake KEMScheme byte: 0x62/0x63
→ 0x01/0x02. Forward-only; the prior numbering was never released to
any live network.

New test: TestKEMSchemeIDs_AllUseCanonicalNumbering pins
kem.KeyExchange{MLKEM768,MLKEM1024,X25519Unsafe,None} byte-identical to
config.KeyExchange{MLKEM768,MLKEM1024,X25519Unsafe,Invalid}.
2026-05-11 09:29:42 -07:00
Hanzo AI d86c155eb1 node/network/peer: F103 — document hybrid vs pure ML-KEM-768 decision
The TLS handshake pins CurvePreferences = [tls.X25519MLKEM768], the
IANA-registered hybrid (curve ID 0x11ec). The chain-wide
ChainSecurityProfile pins KeyExchangeMLKEM768 — the post-quantum
component that MUST be present on the wire — and the hybrid satisfies
this because it CONTAINS ML-KEM-768.

The hybrid is strictly stronger than pure ML-KEM-768 (an attacker must
break BOTH X25519 AND ML-KEM-768 to derive the session key). Real-world
TLS 1.3 stacks implement the hybrid today; pure ML-KEM-768 at the TLS
layer is not yet a deployable target.

ForbidClassicalKEM continues to refuse a pure-classical curve at the
application layer; it does NOT refuse a hybrid that includes ML-KEM-768.

Decision recorded in consensus/config commit 12d7000c.

Closes F103 (pure vs hybrid ML-KEM-768 ambiguity).
2026-05-11 09:28:35 -07:00
Hanzo AI 77fff17b01 node/service/security: lux_securityProfile RPC + Prometheus gauges
Expose the chain-wide ChainSecurityProfile to operators, dApps, and
auditors via two surfaces wired through a single boot site
(initSecurityAPI):

  - JSON-RPC under namespace "lux" at /ext/lux:
      lux_securityProfile  → ProfileReply  (full profile JSON)
      lux_blockSecurity    → BlockSecurityReply (chain-wide envelope)
  - REST sidecar at /ext/lux/v1/security/{profile,block/{n}}
  - Prometheus gauges under namespace "security" on /ext/metrics:
      security_profile_post_quantum_end_to_end{profile_id, profile_name}
      security_profile_nist_friendly{profile_id}
      security_profile_lux_canonical{profile_id}
      security_profile_unsafe_mode_enabled{profile_id}
      security_mempool_classical_credentials_total{chain}
      security_zchain_proof_lag_epochs

The reply shape is SCREAMING_SNAKE canonical names (renderName) so audit
tooling matches on stable identifiers; the underlying scheme bytes come
from consensus/config. A node booted without a SecurityProfile pin
returns ErrNoProfile (RPC) or HTTP 503 (REST) — the legacy networks
keep their classical-compat posture without forging a profile.

Closes the lux_securityProfile and profile-gauges F102 follow-ups.
2026-05-11 09:28:35 -07:00
Hanzo AI 0568d68b80 node/xvm: wire SetAuthPolicy from profile
The X-chain mempool now installs the chain-wide credential-admission
policy resolved from genesis at node bootstrap (F102 close-out). Wiring
path:

  genesis → node.SecurityProfile() → xvm.Factory.SecurityProfile
         → VM.securityProfile → vm.Initialize → xmempool.SetAuthPolicy

X-chain credentials are wrapped in fxs.FxCredential; the mempool gate
unwraps them before consulting the auth policy so the same
EnforceCredentialPolicy implementation gates both P-chain and X-chain.

Integration test exercises the full path: build VM with strict-PQ
profile, call Initialize + Linearize, then issue a tx with a wrapped
classical secp256k1 credential via IssueTxFromRPCWithoutVerification.
Observe ErrLegacyCredentialUnderStrictPQ.
2026-05-11 09:28:35 -07:00
Hanzo AI 9a6b7d2455 node/platformvm: wire SetAuthPolicy from profile (closes CPX deferred item)
The platformvm mempool now installs the chain-wide credential-admission
policy resolved from genesis at node bootstrap (F102 close-out). Wiring
path:

  genesis → node.SecurityProfile() → platformvm.config.Internal.SecurityProfile
         → vm.Initialize → pmempool.SetAuthPolicy

Strict-PQ chains refuse classical secp256k1 credentials at gossip time
via the existing auth.EnforceCredentialPolicy gate; legacy/classical-
compat networks keep admitting them unchanged (nil profile is a no-op
gate).

Integration test exercises the full end-to-end path: build VM with
SecurityProfile = LuxStrictPQ(), call Initialize, attempt to add a tx
with an unwrapped *secp256k1fx.Credential, observe
ErrLegacyCredentialUnderStrictPQ.

Closes the CPX deferred item:
"chain-builder code that constructs the mempool today does not call
 SetAuthPolicy ... follow-up that depends on plumbing the
 *config.ChainSecurityProfile from genesis into the chain builder"
2026-05-11 09:28:35 -07:00
Darkhorse7stars 61b3e380e0 ci(docker): use lux-build-* runners (cross-org from hanzoai/.github)
The reusable hanzoai/.github/docker-build.yml requires cross-org callers
to override runner labels — hanzoai org scale-sets aren't visible from
luxfi org. All v1.26.x CI runs have failed with startup_failure since
the upstream workflow added this requirement (~2026-05).

Per the reusable workflow's docstring:
  Cross-org callers (luxfi/*, zooai/*, <tenant>/*) MUST override
  these with their own org's ARC scale-set labels.

Switch to lux-build-linux-{amd64,arm64} labels which exist on the
luxfi ARC scale-set.
2026-05-11 04:32:32 -05:00
Hanzo AI 9c9e6b9e28 node+genesis: wire ChainSecurityProfile into bootstrap (closes F102)
Adds Node.SecurityProfile() getter and Node.initSecurityProfile() boot
step. New() now calls initSecurityProfile() right after
initBootstrappers() and before tracer/metrics/networking/chain init —
every downstream consumer (signer factory, peer handshake gate,
mempool, validator registry, bridge oracle) sees the resolved
*consensus/config.ChainSecurityProfile (or its absence) via the
getter at construction time.

The pin lives in genesis.Config.SecurityProfile (luxfi/genesis@v1.9.6,
which pins luxfi/consensus@v1.23.5). Resolution:
  1. genesiscfg.GetConfig(networkID) — load JSON-form genesis
  2. cfg.SecurityProfile.Resolve() — refuse mismatched pin
  3. stamp result onto n.securityProfile
  4. emit startup banner with hash, post-quantum, NIST-friendly,
     classical-SNARK, and BLS-fallback posture

A forked binary that swaps in a different canonical profile content
fails Resolve() because the live ComputeHash diverges from the
genesis-pinned hex — closes the F102 attack chain end-to-end.

Adds 5 regression tests for the load + reject paths under StrictPQ
and FIPS profiles, plus nil-pin / wrong-hash / unknown-ID rejection.

Bumps luxfi/consensus v1.23.4 → v1.23.5, luxfi/genesis pseudo →
v1.9.6, luxfi/crypto v1.18.3 → v1.18.4.
2026-05-10 21:04:28 -07:00
Hanzo AI 4c1529da2a node/vms/avm: mempool refuses classical creds under strict-PQ
Mirrors the P-chain gate (vms/platformvm/txs/mempool) onto the X-chain
(xvm) mempool. The X-chain wraps every credential in fxs.FxCredential,
so the gate unwraps the inner verify.Verifiable before handing the
slice to auth.EnforceCredentialPolicy — the policy package only sees
the canonical *secp256k1fx.Credential type.

Same opt-in shape as the P-chain wiring: SetAuthPolicy installs the
ChainSecurityProfile + ClassicalCompatRegistry; without a profile the
gate is bypassed.

Three integration tests cover: strict-PQ + no registry refuses
classical, no policy admits classical, strict-PQ + empty registry
refuses classical (the all-allow-listed contract is that the registry
names the allowed addresses; an empty registry admits nothing).
2026-05-10 20:58:31 -07:00
Hanzo AI 4a345fe8e3 node/vms/platformvm: mempool refuses classical creds under strict-PQ
Wires the canonical credential-policy gate (vms/txs/auth) into the
P-chain mempool. Adds an opt-in setter so existing callers that have
not migrated their construction path observe no behavioural change —
without SetAuthPolicy, the gate is bypassed and every tx the legacy
path accepted is still accepted.

Once a chain pins a non-nil *config.ChainSecurityProfile via
SetAuthPolicy, every Add path runs through auth.EnforceCredentialPolicy
before the underlying mempool sees the tx. A classical
secp256k1fx.Credential under RequireTypedTxAuth=true returns
auth.ErrLegacyCredentialUnderStrictPQ.

The originator is left at ids.ShortEmpty here because P-chain txs do
not bind a single canonical "from" address (the input owners can name
many keys). Chain builders that supply a ClassicalCompatRegistry whose
IsAllowed depends on tx-level context layer that resolver on top of
this gate.

Three integration tests cover: strict-PQ + no registry refuses
classical, no policy (legacy default) admits classical, classical-
compat profile admits classical. The full P-chain mempool suite
(TestBlockBuilderMaxMempoolSizeHandling et al.) is unchanged.
2026-05-10 20:58:24 -07:00
Hanzo AI 102023f249 node/vms/txs/auth: ClassicalCompatRegistry + strict-PQ mempool gate
Adds the canonical credential-policy gate that the P-chain and X-chain
mempools use to enforce a strict-PQ ChainSecurityProfile at admission
time. One package, one entry point (EnforceCredentialPolicy), one
error (ErrLegacyCredentialUnderStrictPQ).

  - ClassicalCompatRegistry: read-only allow-list interface. Names a
    bounded set of legacy operator addresses that may still post
    classical secp256k1 credentials on a chain that otherwise pins
    RequireTypedTxAuth=true. The chain's governance pathway is the
    only writer; the mempool only reads.
  - NewStaticClassicalCompatRegistry: frozen registry constructed from
    a fixed []ids.ShortID slice. Useful for tests and for genesis-
    pinned allow-lists before the governance path is online.
  - EnforceCredentialPolicy: idempotent gate, branches on
    profile.RequireTypedTxAuth:
        false → admit unconditionally (classical-compat profile)
        true  → walk creds; if any is *secp256k1fx.Credential and the
                originator is not in the registry, return
                ErrLegacyCredentialUnderStrictPQ.

10 tests cover: nil profile (ErrNilProfile, programmer error), classical
profile admits, strict-PQ admits PQ-only creds, strict-PQ refuses
classical without registry, strict-PQ refuses originator not in
registry, strict-PQ admits allow-listed originator, mixed creds with
one classical refuses, empty creds always admits (syntactic verifier's
job to require ≥1), nil-safe staticRegistry, distinguishes addresses.

Wiring into platformvm/txs/mempool and xvm/txs/mempool lands in the
follow-up commits.
2026-05-10 20:58:15 -07:00
Hanzo AI aee5923e68 node/vms/mldsafx: re-export ML-DSA feature extension
Re-exports the canonical ML-DSA-65 (FIPS 204) UTXO feature extension
from github.com/luxfi/utxo/mldsafx so platformvm and xvm callers depend
on a single import path:

    github.com/luxfi/node/vms/mldsafx

One feature extension, one import path. The wire types (Credential,
TransferInput/Output, MintOutput, MintOperation, OutputOwners, Input,
Fx, Factory) and the security-level constants are type aliases against
the upstream package — adding mldsafx as a node-side bridge introduces
zero runtime code.

This is the foundation the P-chain and X-chain mempool admission gates
(vms/txs/auth) and the strict-PQ tx variants build against.
2026-05-10 20:58:04 -07:00
Hanzo AI ea32845a7d node: fix go.mod/go.sum after consensus v1.23.4 retag
The prior commit referenced luxfi/consensus v1.23.3, but that tag was
already in use on the remote. Retagged the new ChainSecurityProfile
ValidatorSchemeID work as v1.23.4 and update node's go.mod/go.sum to
match. luxfi/ids v1.2.10 is unaffected.
2026-05-10 20:26:00 -07:00
Hanzo AI 3bb951e59e node: ML-DSA-65 promoted to canonical NodeID under strict-PQ
NodeIDScheme enum (MLDSA65=0x42 canonical, Secp256k1=0x90 classical-
compat-unsafe only). NodeID derivation now domain-separated via
SHAKE256-384("LUX_NODE_ID_V1" || chain_id || scheme || pubkey).

Wire encoding includes a leading scheme byte so the receiver can
verify without trusting the profile alone.

Strict-PQ profile rejects secp256k1 NodeIDs.
Classical-compat profile accepts both (transition path).

Migration: hardfork activation switches strict-PQ chains from
mixed-scheme to ML-DSA-only at a configured activation block.

network/peer/scheme_gate.go is the single primitive consumers funnel
inbound NodeIDs through: SchemeGate.Classify(nodeID, scheme, height,
site) returns a TypedNodeID once the chain policy admits the pair.
The ActivationHeight field implements the hardfork transition window;
ClassicalCompatUnsafe mirrors the operator opt-in flag (refused under
strict-PQ regardless, honoured on permissive).

Existing 20-byte ids.NodeID array stays byte-identical for storage /
map keys / codec; the scheme byte travels alongside it on the wire
via ids.TypedNodeID. Consumers of the 20-byte form (peer/upgrader,
proposervm block proposer, platformvm validator registry, mempool
sender) continue to work unchanged at the storage layer; the
SchemeGate boundary is what stamps the scheme byte and runs the
cross-axis check.

Bumps luxfi/ids v1.2.9 -> v1.2.10 (NodeIDScheme, TypedNodeID,
DeriveMLDSA, FullDigest, error surface) and luxfi/consensus
v1.23.2 -> v1.23.3 (ValidatorSchemeID accessor, AcceptsValidatorScheme,
ErrValidatorSchemeMismatch).

Tests:
- TestSchemeGate_NewSchemeGate_RejectsNilProfile
- TestSchemeGate_StrictPQ_AcceptsMatchedScheme
- TestSchemeGate_StrictPQ_PostActivation_RejectsClassical
- TestSchemeGate_StrictPQ_PreActivation_AcceptsBothSchemes
- TestSchemeGate_StrictPQ_PreActivation_RejectsClassicalAfterCutover
- TestSchemeGate_Permissive_AcceptsClassicalUnderUnsafeFlag
- TestSchemeGate_RejectsUnknownSchemeByte
- TestSchemeGate_PinsProfileScheme
- TestSchemeGate_SiteTagIncludedInError

Patch-bump: v1.26.9 -> v1.26.10.
2026-05-10 20:18:32 -07:00
Hanzo AI 517acef79b node/network: PQ peer handshake — ML-KEM-768/1024 + ML-DSA-65 identity
Replaces classical X25519/ECDH peer handshake with ML-KEM-768 (default)
and ML-KEM-1024 (high-value validator/DKG channels). Node identity is
signed with ML-DSA-65 over a TupleHash256-bound transcript.

cSHAKE256 derives the AEAD session key with customization
"LUX_NODE_AEAD_V1", binding profile_id, chain_id, both nodes' ML-DSA
public keys, and the shared KEM secret.

DKG channels in pulsar/pulsar-m force ML-KEM-1024.

Strict-PQ profile refuses peers offering X25519Unsafe KEM.

Patch-bump.
2026-05-10 20:04:26 -07:00
Hanzo AI cc856c020c platformvm: C-Chain is opt-in via --track-chains, only X-Chain is built-in
Only P-Chain (chain manager startup) and X-Chain (UTXO infra) are
required primary-network chains. C-Chain (EVM), D-Chain (DEX),
B-Chain (Bridge), T-Chain (Threshold) — and any subnet blockchain —
must be explicitly tracked via --track-chains. A validator gets exactly
the topology its operator asks for, nothing more.

Pre-fix: every primary-network blockchain in genesis was created
unconditionally because `constants.PrimaryNetworkID != tx.ChainID`
short-circuited the TrackedChains gate. <tenant> validators (no
C-Chain plugin shipped) ran into "failed to initialize VM: parsing
genesis: unexpected end of JSON input" on every health check.

Replace the primary-network bypass with a per-VM check: only
tx.VMID == constants.XVMID skips the gate. Everything else (including
C-Chain on primary network) goes through TrackedChains.
2026-05-10 15:21:36 -07:00
Hanzo AI a0d1a2bc31 chains: opt-in by plugin — drop TrackAllChains auto-true + skip missing
Two related fixes that make chain tracking explicit per-validator:

1. config/config.go: drop the silent default
   `if TrackedChains == nil { TrackAllChains = true }`. That made any
   node without an explicit --track-chains list try to spin up every
   chain in P-chain state, including ones whose VM plugin wasn't
   loaded. The setting was a footgun. Empty TrackedChains now means
   "track only P/X (built-in)". TrackAllChains stays as an explicit
   opt-in escape hatch.

2. chains/manager.go: when buildChain returns ErrNotFound (VM plugin
   not registered for this chain's vmID), treat it as the validator's
   "I don't validate this one" signal — log info, mark the slot
   bootstrapped, and return WITHOUT registering a per-chain failing
   health check. The chain stays in pending state for hot-load.
   Previously this registered a permanent 503 on /ext/health for the
   chain-alias, which made kubelet liveness probes kill any pod that
   didn't ship plugins for every chain in the primary genesis. Now
   validators participate per-plugin: load liquid-evm/dex/fhe → those
   chains validate; don't load Lux's upstream EVM plugin → C-Chain
   stays in pending without crashing the node.

Real failures (e.g. genesis decode error, db corruption) still register
the failing health check — those are operator misconfigurations, not
deliberate opt-outs.

Future: a Lux-signed featured-chains.json + --track-featured (default
true) would make this opt-in safer at scale — limits the DDoS surface
of unbounded chain creation while still letting validators earn yield
on the curated set out of the box.
2026-05-10 12:21:48 -07:00
Hanzo AI 9c95d6473a platformvm: add GetChains as canonical replacement for GetNets
Adds platform.getChains alongside platform.getNets — same wire shape
(IDs in, list of {ID, ControlKeys, Threshold} out), names that match
the user-facing concept ("chain") instead of the internal "net" /
"subnet" jargon. APIChain replaces APINet, ClientChain (alias for
ClientNet) keeps drop-in source compatibility.

Why now: GetNets was already marked deprecated via the "deprecated
API called" log line, but no canonical replacement existed — callers
had to keep calling the deprecated method. This commit lands the
replacement so the bootstrap binary's chain idempotency check
(EnsureChainNetwork → list chains, match owner set) can target the
canonical name.

GetNets stays available indefinitely for wire-protocol compatibility.
GetChains delegates to GetNets internally so the two methods can
never diverge — bug-fix one, both fix.

Test pinned in service_test.go alongside GetNets test (existing file
has //go:build skip but the test is documentation for the contract).
2026-05-09 18:08:24 -07:00
Hanzo AI 6f0cdee116 deps: bump luxfi/genesis → fe4781cd (LUX_DISABLE_CCHAIN env knob) 2026-05-09 16:28:04 -07:00
Hanzo AI 2060761d42 platformvm: gate createCChainIfNeeded on LUX_MIGRATE_CCHAIN=1
createCChainIfNeeded is the one-time recovery path for the historical
mainnet migration where post-merge geth state was imported under a fixed
blockchainID (no CreateChainTx). On every other launch the function
either silently no-ops on the missing data dir or — worse — risks
touching the filesystem before the data dir exists during a fresh
genesis. Gating it behind LUX_MIGRATE_CCHAIN=1 keeps the migration path
exactly where it belongs: opt-in, run once, never again.
2026-05-09 14:30:27 -07:00
Hanzo AI a4208faf95 zap/client: don't treat MsgResponseFlag as error flag
The wire protocol uses two flags on responses:
  MsgResponseFlag (0x80) — set on EVERY response (success or error)
  MsgErrorFlag    (0x40) — set ONLY on error responses

The transport's readLoop already converts MsgErrorFlag responses into a
non-nil err out of Conn.Call, so by the time the client checks respType
the response is guaranteed successful. Treating MsgResponseFlag as the
"is this an error?" predicate fired on every successful Initialize and
rendered the binary InitializeResponse payload (LastAcceptedID, parent,
height, bytes, timestamp) as if it were an error string, producing
"vm error: <unprintable bytes>" and crashing chain creation despite the
plugin reporting "VM initialized successfully".

Symptom in the field: lqd repeatedly logged
  failed to create chain on net 11111111111111111111111111111111LpoYY:
  failed to initialize VM: zap initialize: vm error: \x00\x00\x00 ...
while the plugin's own log read "ZAP VM initialized successfully" and
"Chain initialized successfully". Health check C reported permanent
failure, eth_getBalance returned 404, no blocks were ever produced.

Fix: drop the spurious MsgResponseFlag check and strip both flags before
comparing the message type so that any well-formed response is accepted.

Regression test in client_initialize_test.go pins both halves of the
contract: a success response is decoded (lastAcceptedID round-trips),
and a server-side error is surfaced through err with the original
message intact.
2026-05-09 13:46:53 -07:00
Hanzo AI 1d94973509 deps: bump luxfi/genesis v1.9.5 → 2b16f454 (LUX_CCHAIN_GENESIS_FILE)
Picks up luxfi/genesis@2b16f454 — adds operator-overridable C-Chain
genesis at the embedded-loader layer. Pairs with 009f00ba (this repo's
LUX_AUTOMINE_CCHAIN_GENESIS_PATH for the automine single-node path).
With both env vars wired, downstream networks can reuse stock lqd
without forking configs/network/cchain.json or patching this binary.
2026-05-08 17:18:55 -07:00
Hanzo AI 009f00ba91 feat(automine): operator-overridable C-Chain genesis via LUX_AUTOMINE_CCHAIN_GENESIS_PATH
The automine path embeds the C-Chain genesis bytes into the primary-
network genesis at boot. Until now that genesis was a hardcoded constant
(chainId 31337) — fine for stock lqd local dev, but downstream networks
(<tenant> at chainId 8675312, etc.) had no way to override without
patching the binary. The chain-config-dir scan happens AFTER the EVM
plugin has already initialised from the embedded bytes, so dropping a
genesis.json into configs/chains/C/ is silently ignored.

Adds LUX_AUTOMINE_CCHAIN_GENESIS_PATH: when set, lqd reads the JSON at
that path and embeds it as the C-Chain genesis. Unset → unchanged
behaviour (chainId 31337 default).

The saved AutomineNetworkConfig also mirrors the resolved value so the
on-disk record is true to what was embedded.
2026-05-08 16:27:54 -07:00
Hanzo AI c26319db84 deps: bump luxfi/genesis v1.9.4 → v1.9.5 (gasLimit 1B everywhere) 2026-05-07 22:04:52 -07:00
Hanzo AI fd40807831 fix(node): C-Chain (primary-network EVM) is truly opt-in
Match the OPT-IN comment at genesis/builder/builder.go:617. The
initChainManager path was hard-erroring when the platform genesis
had no constants.EVMID chain — that contradicted the documented
opt-in behaviour and forced consumers (<tenant> Network) to bake
a placeholder EVM into the primary genesis just to satisfy the
node init.

With this change, networks that register their own EVM as a
dedicated chain via platform.createChainTx (the canonical L2-on-Lux
or sovereign-chain flow) leave the platform genesis EVM-less and
cChainID stays ids.Empty. Chain manager + aliasing already accept
the empty ID — no further changes needed.
2026-05-07 21:08:42 -07:00
Hanzo AI 9b397125c1 deps: bump luxfi/genesis v1.9.3 → v1.9.4 (drop local cChainGenesis) 2026-05-07 21:04:17 -07:00
Hanzo AI e9c2d81ff5 deps: bump luxfi/genesis v1.9.2 → v1.9.3
Picks up the localnet genesis regen from LIGHT_MNEMONIC. lux/node's
default genesis for network-id=1337 now funds the same 100 P/X wallets
the lux/node + <tenant>/node toolchains derive against, so local
dev no longer has to set --genesis-file or hand-edit allocations.
2026-05-07 20:18:05 -07:00
Hanzo AI df8af35979 fix(zap/client): keep wire field name LuxAssetID (proto-generated)
The struct `zapwire.InitializeRequest.LuxAssetID` is generated from a
.proto in luxfi/api — renaming it requires regenerating the wire
bindings, bumping luxfi/api, then bumping luxfi/node to that. Out of
scope for this rename pass; revert the one Go-side assignment so the
build resolves against the existing wire type. The local variable
already reads from `Context().XAssetID` so the data path is consistent;
only the on-the-wire field name lags.
2026-05-07 17:09:20 -07:00
Hanzo AI 1113675482 refactor(config): rename node.Config.LuxAssetID -> XAssetID
The field has always semantically been the X-Chain asset ID — the JSON
tag is already `xAssetID`. The Go name `LuxAssetID` was a holdover from
when "LUX" was the only asset name on the chain, which created confusion
when readers expected `XAssetID` to mirror `XChainID` / `CChainID` /
`DChainID` (all of which already used the chain-letter naming).

Renamed across config, node, vms/platformvm, vms/rpcchainvm/zap and the
static_service API request types. JSON tag and protobuf wire fields are
unchanged, so on-disk configs and inter-process plugin RPC are
backwards-compatible — only Go callers see the new name.
2026-05-07 16:52:35 -07:00
Hanzo AI 131e6a588c fix(chains): register all 9 fx factories matching genesis builder
X-Chain genesis at builder.go:603-613 references 9 FxIDs (secp256k1fx,
nftfx, propertyfx, mldsafx, slhdsafx, ed25519fx, secp256r1fx, schnorrfx,
bls12381fx) but chains/manager.go only registered the first 3. Chain
init failed with "fx qC5JEjDhfXD66cGuhtiL3Lkka2SgZyht74nHVQFmYFyDiLqXe
not found" — that ID encodes 'mldsafx' which the genesis builder added
when post-quantum support landed but wasn't paired with a manager-side
registration.

Add all 6 missing factories so any FxID emitted by the genesis builder
loads at chain create time. The fxs map is now structurally identical
to the X-Chain FxIDs slice — drift between the two will become a
review-time diff in chains/manager.go vs. genesis/builder/builder.go.
2026-05-07 15:22:42 -07:00
Hanzo AI c790abb494 .gitignore + commit vms/components/lux content
Anchor /lux + /luxd binary patterns at repo root so the gitignore
rule doesn't accidentally match every directory called "lux" deep
in the tree (which was excluding vms/components/lux that the
previous commit tried to land).

Add the actual UTXO type tree files so v1.26.5 ships with the
package contents external consumers (liquidity/network-bootstrap
etc) need.
2026-05-06 21:09:12 -07:00
Hanzo AI fcde96701d vms: restore components/lux + add thresholdvm re-export shim
* vms/components/lux: restore the X-Chain UTXO type tree from
  v1.24.29. External consumers (~/work/liquidity/network-bootstrap,
  PlatformVM tx builders, AVM tx builders) import this exact type
  tree to interop with the X→P export path. Documented in CLAUDE.md
  as a known anomaly pending #58 consolidation; until that lands the
  package must be present.

* vms/thresholdvm/thresholdvm.go: re-export shim mirroring vms/dexvm.
  The Threshold (FHE / MPC) VM moved out of node/vms/thresholdvm
  into github.com/luxfi/chains/thresholdvm. Callers (liquidity/fhe
  plugin etc) keep building unchanged.

No on-the-wire behaviour change.
2026-05-06 21:08:25 -07:00
Hanzo AI 6e76c846fb proto/pb: stub empty pb packages; vms/dexvm: re-export from chains/dexvm
Two compatibility seams that downstream consumers need post-Z-Wing
restructure:

1. proto/pb/* stubs (build tag grpc) — every grpc-tagged file under
   proto/<name>/<name>_grpc.go (and the legacy proto/rpcdb/rpcdb_grpc.go)
   imports proto/pb/<name>. Those dirs were empty (git ignores empty
   dirs), so consumers' `go mod tidy` walked the imports under the
   grpc tag and failed to resolve the package. Default builds use
   ZAP and never enter these stubs; the grpc-tag path now compiles
   cleanly even though the protobuf types themselves still need
   regeneration when someone actually wants the gRPC transport.

2. vms/dexvm/dexvm.go — re-export shim for the canonical chains/dexvm
   package. The DEX VM moved out of node/vms/dexvm into
   github.com/luxfi/chains/dexvm; existing callers (~/work/liquidity/
   node, etc.) keep building unchanged.

Default build clean; grpc-tagged build also resolves. No on-the-wire
behaviour change in the ZAP default path.
2026-05-06 20:55:12 -07:00
Hanzo AI a2d1a828d1 deps: bump consensus v1.23.2 + threshold v1.6.7 + ZAP-native rpcdb
* consensus v1.23.2 — pulls threshold v1.6.7 with the LSS-Pulsar
  adapter (PulsarConfig, DynamicResharePulsar) needed by the epoch
  manager's resharing path.
* New proto/zap/rpcdb package — pure-Go wire types for the database
  RPC, no protobuf. Mirrors the proto/zap/{vm,p2p,sync,platformvm}
  pattern.
* New proto/rpcdb/rpcdb_zap.go (build tag !grpc) — full ZAP-native
  DatabaseClient + DatabaseServer + Register hook, implements
  database.Database against any Transport. The host's underlying DB
  is luxfi/database (zapdb in production); the protocol shape is
  identical regardless of which engine the host runs.
* Renamed the existing rpcdb.go to rpcdb_grpc.go so the two
  variants are mutually exclusive: build with no tag (ZAP default)
  or with `-tags=grpc` (protobuf path), never both.

examples/multi-network/multi-network-poc.go: drop duplicate-key map
entry where Q-Chain was illustrated as a separate network — Q-Chain
shares the primary network ID per LP-134, see comments on
MainnetID entry.

Net effect: full default build is ZAP-only PQ-secure-channel-aware,
RPC over a Z-Wing-encrypted ZAP transport, no gRPC/protobuf in the
critical path.
2026-05-06 19:18:03 -07:00
Hanzo AI a449f30a81 deps: cascade Z-Wing PQ stack + LocalID/CustomID split + verkle path fix
Pulls in:

* luxfi/constants  v1.5.2  — LocalID/CustomID semantic split, IsCustom()
* luxfi/genesis    v1.9.2  — same split mirrored at the configs layer
* luxfi/zwing      v0.5.2  — full PQ secure channel (X-Wing + ML-DSA-65 +
                              ChaCha20-Poly1305) with cross-language
                              wire-byte interop verified against Rust /
                              Python / TypeScript ports
* luxfi/api        v1.0.10 — zap.NewListener seam (used by zwing.ListenZAP)
* luxfi/netrunner  v1.18.1 — PQ-mandatory zapwire control RPC + same
                              LocalID rename
* luxfi/geth       v1.16.87 — verkle.Fr type fix (drop bandersnatch import)
* luxfi/consensus  v1.23.1  — banderwagon path move tracked

Source-side rename in this repo: every constants.CustomID call was
"the local 1337 dev network", so they all become constants.LocalID
(both the upgrade-config validation switch and the test fixtures).
The old constants.CustomID literal is now 0 — used as the explicit
"this is a user-defined custom network" sentinel, separate from the
LocalID dev network.

Plus a clarifying comment on the upgrade-config switch noting which
network IDs are permitted to override their upgrade schedule (any
non-well-known ID, including DevnetID/UnitTestID and any genuinely
custom user-defined network ID).

Z-Wing dialer + tests still green; all network/dialer, config,
config/node, config/spec, and genesis/builder tests pass.
2026-05-06 18:21:06 -07:00
Hanzo AI d1d0f45f5b network/dialer: add Z-Wing PQ secure-channel wrapper
Introduces ZWingDialer + ZWingListener which wrap any underlying
net.Conn (TCP, hostname, RNS mesh link, Unix socket, in-memory pipe)
with the canonical Lux PQ secure channel:

  IETF X-Wing KEM (X25519 + ML-KEM-768)
  Hybrid Ed25519 + ML-DSA-65 identity, signed transcript
  ChaCha20-Poly1305 with sequence-numbered nonces

Z-Wing's contract is "any net.Conn" — the same secure channel rides
unchanged on TCP today and on the existing RNS transport tomorrow
without a per-transport rewrite. The legacy LP-9701 in-RNS-link crypto
(rns_link.go) stays in place during the transition; new p2p paths
should layer ZWingDialer over the EndpointDialer instead of relying on
LP-9701's inline encryption.

Adds:
  network/dialer/zwing_dialer.go      ZWingDialer + ZWingListener
  network/dialer/zwing_dialer_test.go 5 e2e tests covering:
    - missing-identity rejection (dialer + listener)
    - real TCP listener + Z-Wing handshake + payload round trip
    - Wrap() over an arbitrary net.Conn (net.Pipe stand-in for RNS)
    - identity mismatch (MitM defence)
    - DialEndpoint over an Endpoint (works for IP, hostname, future RNS)

Bumps:
  github.com/luxfi/zwing v0.5.2 (full FIPS 204 PQ stack, cross-language
                                  wire-byte interop with Rust/Py/TS)
  github.com/luxfi/api   v1.0.10 (NewListener seam used by zwing.ListenZAP)

luxd-side wiring (node.go construction with a loaded LocalIdentity) is
the next follow-up; this commit lands the seam without behavioural
changes to the existing dialer interface.
2026-05-06 15:32:06 -07:00
Hanzo AI 08a53e41b9 canonical: rip vestigial protobuf — ZAP is the only wire protocol
Lux's primary wire protocol is ZAP (Zero-Copy App Proto). The protobuf
definitions and generated .pb.go files in proto/ trees were vestigial:
  - _grpc.pb.go gRPC service stubs were already gated behind
    //go:build grpc and not part of the default build
  - .pb.go message types had ZAP equivalents (*_zap.go) on every active
    code path

Default build was already 100% ZAP. Deleting the .proto + .pb.go +
_grpc.pb.go files removes dead code without functional change.

Verified clean build of node, p2p, vm after deletion.
2026-05-05 23:22:24 -07:00
Hanzo AI 00fa0653a1 canonical: SubnetID → ChainID; drop redundant L1ID/SubnetID fields
Lux unifies subnet (validator-set) and chain identity into a single
ChainID — every chain identifies itself by its ChainID, no separate
'subnet identifier' needed.

Wire/interface changes (BREAKING — coordinated rollout):
  - node/message/wire: ChainSubnetPair struct → ChainPingEntry; collapsed
    duplicate SubnetId field; ChainSubnetPairs → ChainIds
  - node/proto/zap/p2p: SubnetID → ChainID
  - node/vms/chainadapter: ICPBlock/ICPSubnet SubnetID → ChainID
  - validators/uptime: Calculator interface params subnetID → chainID
  - consensus/core/router: Connected method param subnetID → chainID
  - p2p/message: outbound_msg_builder var renames

Config/UI changes (cleanup):
  - genesis/pkg/genesis ChainEntry: dropped redundant SubnetID field
  - tui/views/ChainStatus: dropped redundant SubnetID field
  - cli: comment cleanup
  - benchmarks: deploy-subnets var rename
2026-05-05 22:11:04 -07:00
Hanzo AI 20250023d8 Snow → Quasar; clarify sub-protocols vs engines 2026-05-05 19:15:01 -07:00
Hanzo AI c4dbbdcc4e ci(docker): semver-only — drop :main/:dev/:test floating tags 2026-05-05 17:01:03 -07:00
Hanzo AI d004c909cf ci: lux-build → hanzo-build (single ARC fleet); remove .github/arc (operator owns ARC) 2026-05-05 17:00:50 -07:00
Hanzo AI 071630ece8 deps: api v1.0.5 chains v1.2.1 utxo v0.3.0 accel v1.0.9; fix BLS PublicKey []byte signature; service/info Consensus surfacing 2026-05-05 16:59:52 -07:00
Hanzo AI 23db515448 node: scrub Avalabs IP from .md docs (Go imports preserved) 2026-05-05 16:23:41 -07:00
Hanzo AI df56651331 node: scrub Avalabs IP brand refs 2026-05-05 16:22:40 -07:00
Hanzo AI 3774075c95 feat: clean up dead code, update deps, add xvm genesis/fx and genesis builder
Remove unused bloom filter, test helpers, metrics scaffolding, and
linearizable VM wrapper. Trim stale go.sum entries. Add genesis builder
helpers and xvm FX/genesis initialization.
2026-04-19 17:05:59 -07:00
Hanzo AI b8c12487e1 fix: deploy blockers from red+scientist swarm review
Blocking (would cause production incidents):
- env var prefix: LUX_* → LUXD_* (27 vars). Viper reads only LUXD_*;
  LUX_* silently ignored → node would start with default config on every env.
- admin API enabled + sybil disabled defaults: explicit LUXD_API_ADMIN_ENABLED=false
  and LUXD_SYBIL_PROTECTION_ENABLED=true in base ConfigMap.
- bootstrap peer config absent in new overlays: added LUXD_BOOTSTRAP_IPS /
  LUXD_BOOTSTRAP_IDS keys to base ConfigMap; overlays/operator populate per-env.

Defense-in-depth additions:
- ServiceAccount `luxd` with automountServiceAccountToken: false (no API access).
- PodDisruptionBudget maxUnavailable=1 (works at 5 → 100 validator scales).
- NetworkPolicy: ingress 9631/TCP from any (P2P), 9630/TCP cluster-only
  (HTTP), 9090/TCP monitoring-namespace only (metrics).
- podAntiAffinity preferredDuringScheduling by hostname — spread across nodes.
- updateStrategy: OnDelete — operator drains one pod at a time.
- podManagementPolicy: Parallel — validators start in any order.

Swarm verdict was NO-GO until these fixes. Addresses red critical #1 (admin
API), #2 (sybil), high #4 (gateway bypass via direct LB), medium #7 (no
NetworkPolicy/RBAC), and scientist blockers on env prefix + bootstrap.
2026-04-13 07:31:39 -07:00
Hanzo AI 2821ba9007 feat: fat image with 11 chain VM plugins + kustomize overlays
Single ghcr.io/luxfi/node image now includes luxd + EVM plugin +
all 11 chain VM plugins (aivm, bridgevm, dexvm, graphvm, identityvm,
keyvm, oraclevm, quantumvm, relayvm, thresholdvm, zkvm) built from
github.com/luxfi/chains.

Dockerfile: added plugin-builder stage that clones luxfi/chains and
builds each VM as a static binary placed at the CB58-encoded VM ID
path under /luxd/build/plugins/.

compose.yml: single-node local dev config (network-id=3, sybil off,
sample=1) replacing the stale docker/compose.yml.

k8s: replaced ad-hoc mainnet-only manifests with kustomize base +
4 overlays (localnet, devnet, testnet, mainnet). Each overlay patches
replicas, resources, storage class, network-id, and image tag.

Deleted: docker/Dockerfile, docker/compose.yml, docker/compose.genesis.yml,
k8s/luxd-statefulset.yaml, k8s/mainnet/ (entire directory).
2026-04-13 07:26:17 -07:00
Hanzo AI 862a8b72e7 deps: pin chains/* v0.1.0 + utxo v0.2.7 for goreleaser
Goreleaser runs with GOWORK=off so it cannot resolve local workspace
modules. Pin published versions:
  - github.com/luxfi/utxo v0.2.7 (adds InitRuntime forwarder)
  - github.com/luxfi/chains/{aivm,bridgevm,dexvm,graphvm,identityvm,
    keyvm,oraclevm,quantumvm,relayvm,thresholdvm,zkvm} v0.1.0

No replace directives — every dependency resolves to a published tag.
2026-04-13 07:06:55 -07:00
Hanzo AI 65d5f4f24b fix: add main/main.go entry point for luxd binary
Restores the missing entry point that .goreleaser.yml, Makefile, and
scripts/build.sh all expect at ./main. Without this file, the release
pipeline fails with 'couldn't find main file: stat main: no such file
or directory'.

The main wires:
  config.BuildFlagSet → config.BuildViper → config.GetNodeConfig
  → log.NewFactoryWithConfig → ulimit.Set
  → node.New(*node.Config, log.Factory, log.Logger)
  → n.Dispatch() with SIGINT/SIGTERM handling
  → exit n.ExitCode()

--version short-circuits to print version.CurrentApp.String() (e.g.
'luxd/1.23.25').

Not using the orphan app/ package (app.New takes nodeconfig.Config which
is a parallel type definition not produced by config.GetNodeConfig). The
app/ package can be migrated separately or removed.
2026-04-13 07:02:32 -07:00
Hanzo AI 8de1b78ed8 refactor: migrate UTXO components to standalone github.com/luxfi/utxo
One place, one way to define UTXO primitives. Delete the in-tree duplicate
at node/vms/components/lux/ and import the standalone luxfi/utxo package
with a 'lux' alias so existing call-sites (lux.UTXO, lux.TransferableInput,
etc.) remain unchanged in consumers.

Files changed: 167 imports rewritten, 2 directories deleted.

Build still green on the whole tree except pre-existing examples/multi-network
QChainMainnetID issue (unrelated).

Next: rename luxfi/utxo/luxmock → utxomock for full brand-neutrality; that
is a separate PR since it requires touching all consumer alias names.
2026-04-13 06:47:35 -07:00
Hanzo AI 0866b1a34e feat: complete mldsafx — ML-DSA-65 PQ signing for X-Chain UTXO 2026-04-13 05:34:08 -07:00
Hanzo AI 69bcba4420 refactor: delete node/vms/{aivm,bridgevm,dexvm,graphvm,identityvm,keyvm,oraclevm,quantumvm,relayvm,thresholdvm,zkvm}
VM implementations moved to github.com/luxfi/chains/<name>.
node/node/vms.go now imports from chains/ paths.

node/vms/ retains only primary network VMs (platformvm, xvm, evm)
plus VM infrastructure (manager, registry, rpcchainvm, tracedvm, etc).
2026-04-13 05:27:09 -07:00
Hanzo AI fa13771942 refactor: rename VM packages, delete teleportvm + servicenodevm
Consistent naming — package matches directory name:
- bvm → bridgevm
- gvm → graphvm
- qvm → quantumvm
- tvm → thresholdvm
- zvm → zkvm

Removed VMs (deduped):
- teleportvm/ — duplicated bridgevm+relayvm+oraclevm code (same MPC, same signing)
- servicenodevm/ — moved to dedicated repo github.com/luxfi/session

vms.go: 11 optional VMs (A/B/D/G/I/K/O/Q/R/T/Z) registered with new package names.
S-Chain (Session) registered separately as standalone plugin.
2026-04-13 05:15:50 -07:00
Hanzo AI 1ceb309a24 test: raise quasar coverage 40.6% -> 43.5%
Config validation, quorum params, lifecycle, set/get finalized,
BLS signature types, CoronaCoordinator sign/verify paths,
active/inactive validator weight filtering.

Remaining uncovered: GPU/NTT hardware code (requires CGO + GPU),
processFinality integration (requires P-Chain provider), Verify
(requires real BLS/Corona key material).
2026-04-13 05:07:24 -07:00
Hanzo AI 05d532944d refactor: primary network = P+Q+Z mandatory, C/D/B/T opt-in
The minimum quantum-safe validator set is:
  P — staking, validators, rewards (implicit)
  Q — Quasar PQ consensus (BLS + Corona + ML-DSA)
  Z — universal receipt registry + ZK verification
  X — assets (kept for LUX token / fee UTXOs, backward compat)

Opt-in (only created if *ChainGenesis provided):
  C — EVM contracts
  D — DEX
  B — Bridge
  T — Threshold/FHE/MPC

Validators stake extra + validate opt-in chains to earn their fees.
Fee split: each chain's tx fees distributed to its validators
proportional to stake weight.
2026-04-13 05:01:56 -07:00
Hanzo AI f6e63d60b2 clean: squash history (binaries stripped via filter-repo) 2026-04-13 03:45:21 -07:00
5613 changed files with 133376 additions and 544542 deletions
@@ -1 +0,0 @@
v1 0024931b2dfe405758c260860f69a914afcf1eccd6b12a1145505dc86cc34f52 76b13da52d919c11cb678d8df9641469273932e7262ba97e68593d839c7c259b 6260 1752729534123729000
@@ -1 +0,0 @@
v1 00bb20e6e6320215426f584f56a7da44ba77e252e8cd5da5d999b09d453115e2 e1c2a78395b49e51c056e25571804e7d517e403a6ebd71e457f938189e7f2d35 1445 1752729534175435000
@@ -1 +0,0 @@
v1 00e2d7bbbe0b2ff338e476e7f829e946c760d5fb4ffd369e70981ae194aef346 e331b75465008d76d48aad8b0d9daa9a4407f6ea2ab423e71d1b04efad17b8fd 2645 1752729534156937000
@@ -1 +0,0 @@
v1 00e934aaabd61d7b911f3ad5bab229c70a9e6b94f7d24cba4d1b5eba5485c1ff 1b3e0190c30dd2695641c4611f0d6162bf9e1fffe1f7380f16ec63ac5d8dcc14 252 1752729534182873000
@@ -1 +0,0 @@
v1 012c393cc9a6370251332b4026c776ef861e5e98d66b336320066a8087ae64a2 e7f5e8ccd186c50e1f6f9b5d2e637adaff7307bf0678e3b3364177d48fd4ab3b 702 1752729534198225000
@@ -1 +0,0 @@
v1 014281c0a41d18b950cc4acb81bbb6edc0a0b69eb68a71f080fbc245cee94116 188d1fb08b89b7f952c0b0357ace5ea86e72020108bf11b9ba33f842926e3760 602 1752729534141328000
@@ -1 +0,0 @@
v1 018cc3096c79f928416fd54b83ba91d8bbae256d6059b6d277d913526e839abe d65f8a50db7cdf95b4649a8cefdc6b8a2c3b416ce0b8dc44f4f3a921c43a22d4 1384 1752729534060360000
@@ -1 +0,0 @@
v1 01ad9596ede117d49b7b6e7fd8596f30eb386b8d6ba39553cfc868ee651ca88a bd8239f9ac76fe69100d5cecae4d23163acd73f2991e0f77f4c8586267090cb6 11657 1752729534191304000
@@ -1 +0,0 @@
v1 01ae28e3d60752aaae5f57c96dc40be84c43437c942fcca42285cc742ccc9793 5cadbd4880e6d9a8f9bfe82011d6ec5ae96b2d76d273bcdf6647566b3e0b98a2 1715 1752729534376967000
@@ -1 +0,0 @@
v1 0223d90acd365066d1c220612607e87b87488b0ce8d1286ebdf466c815bdb99a 1b480b409a81891247f424a399fcc39658fb203d441f9758c9e94ee1c0a2a0e2 1932 1752729534195879000
@@ -1 +0,0 @@
v1 024d0a6597a2bc636def805cc4423b560a8991e51ce5f1b0dd96521481128698 307b2d0f60d9ecac30f2346d1868cbf8820eecdc0a73bcd2cf67b516a9c7dd2d 2292 1752729534116010000
@@ -1 +0,0 @@
v1 0277b039b831872f1d2dac70be5eebe5b7c57b19a6da75add9700d8be5d5a37e e9e276c69ff828a62f399a0c049c37c8333590c82d0cf6dad35cdccf7415381e 6026 1752729534121968000
@@ -1 +0,0 @@
v1 028a8bffa49838a613c41c2ef40ff3d77becb3512a1efa9794529168bea09faa 9ae4f00d0605307398e3ff5ef3089e9d75771da7ac76a8c995fed2a441f2148d 750 1752729534123849000
@@ -1 +0,0 @@
v1 028d165457f9097dbbdfeb77466b3d869219fd3355a1b80017138622a0e99ea2 b3f1bc83d539c8cb8326f82fc8dbbd88f5027e96fcc06e1ad9df9b9fb95d35bd 877 1752729534377942000
@@ -1 +0,0 @@
v1 031ea60f554314abfaf7b0836355cd215621e9ff37e81a4645cfbf20ecc2d72a a9e86b090ea9ad8827ffae04c6244043a9df1184092ad00c7757e3e17b5d6a5a 2585 1752729534318237000
@@ -1 +0,0 @@
v1 0331d0ec93e1d931106e28b2e89cae6be05b1fc8b2388ab80b15de50a844e9e7 c0fa079c7b08cacc6c93b0cae48a5464138eba0180361614cb1e2bad2b5ca3cc 55 1752729534104669000
@@ -1 +0,0 @@
v1 036a9d10a17703e29a00b8c8c0927a22bcadb90c40efdcd9ad8910e30209b982 48b78d4f280bf98aacccc4a644e0f41616fa294fe15584943b432ae6e781f25f 756 1752729534076994000
@@ -1 +0,0 @@
v1 0376db4d30016eec5fded45d0112a6a9715565f657b8b2f67675ce75e1c65946 6228e993c84060112e73481680e2a42b2df2aca9195c39a512cfa0a290ae5d97 4536 1752729534190821000
@@ -1 +0,0 @@
v1 03807c326785f7edc439f471f5f2fe8324c702a2f1ed1bfefc7f2e4a211a06dc 7ab7490d13bb6916035574dfe761d876bbb86a32382e13f3dd8cb6756e4d2a06 929 1752729534120304000
@@ -1 +0,0 @@
v1 03f461b9c93d4e074170775cd0b9e3c5afc010037116daae394386029d0aab5d 32d0b62e1fc2e46fd68d789d3aec393eba9c3a9026398011235e605916993e83 115 1752729534307198000
@@ -1 +0,0 @@
v1 04375a0944f4b323259997c08563890f302f4c2c51c41b102c045c67a14eb52a 3805d00964b89833f72a3cda2324c061bf3227a45aa3f10cc361bb0e3b2f8fde 562 1752729534171860000
@@ -1 +0,0 @@
v1 044794a80b95e0c6e1c383e8c92be6f808a2da24f2f45db82f535ffaeabcd7ea d6dfc912e8eed4f7a7480dba1798f1eb38e59987a59a7ec10c716349c39d35d8 972 1752729534127582000
@@ -1 +0,0 @@
v1 0561aab2a27b32d5306fa3a88fbc01d0499dcea9b35f314640a67be38ee8f15c f544c7d0fb8733c942de02ae94bbd3d7889675e63e8c8f39064f73b46fb40aa5 423 1752729534109297000
@@ -1 +0,0 @@
v1 05a882dddb85b9bb45a68e9eaad452277c9178cf1d18544e557393c2f03ba135 891af22c7158a42f19ea3fc93cfaf4aebf28e682a87d7c437d6281f2a172652f 2515 1752729534146388000
@@ -1 +0,0 @@
v1 05f6ff32f486815e7b977079c1638f4e592ed1ef27bf2729bbd5103fa5d46758 b71b06b88a455ee4830c20846e12957b2dc759ac2b749cbe0a04c10a1403e40a 731 1752729534063966000
@@ -1 +0,0 @@
v1 063564224e0139087530b285d4788b310376a482f55c7f4cabbe7a3ea47be597 ca2ace02c9915b015aa6d7cdc586747f4130630a566541106d99ad2bd71aee62 54 1752729534119013000
@@ -1 +0,0 @@
v1 0636f33d1d4d875f56235d3b1060cd0612d5de2bc4418bf4a0766303f40e4019 3290397130bdf2f1a29e144da81c7b720dd72920a2b93d40cd2d8004136fd111 9689 1752729534077353000
@@ -1 +0,0 @@
v1 06552c0e27997c5229eb63d672b8ae75dfcf3332d2b04b8c9b457271f686b2d8 7ce1f2023c08c0c268ecf0d78b0bcbb15e9e761475940dec34436d95355faa0f 716 1752729534188833000
@@ -1 +0,0 @@
v1 069375ce393ead2032dfc35da16138c76e9e365d4529d3e3af948ac60143afb9 7a1d2d396867fcfe40dc03566d51e1daf1b12db2e0e4467f21562978f9c0a34a 340 1752729534329252000
@@ -1 +0,0 @@
v1 0699b6739d495b6f78a042b7d584787f5b0a2a66fe364ad0e62dda1b43280d24 c9a294d2bf35d201ea0904622b35d3a7ab6e852e939b636951eb666b6d24c987 2451 1752729534250279000
@@ -1 +0,0 @@
v1 06a01f17cb54ee9a455169c07fbebeea695b3a418cc0b5a22007aa5d10da7321 7441846b0efaf3fdcb924d52a43aa99ea7a998ff89bcab2047a51b368b9459d8 1229 1752729534150968000
@@ -1 +0,0 @@
v1 06bc6aafaebc9c41dd51474e4721b25b1615468ae6494202e21f6b17f55abcf8 54bef7f11b0dfa7423a6c4eaa8c4d7ddfe9f792100818c1b2b88193989657aae 12128 1752729534190642000
@@ -1 +0,0 @@
v1 06d6633110969777621337d3a630ca8bacb6956229e57c38b51906cfb9bdde26 d0c1dcf60ce4f47b258cdca5514d1665bb22b347b747abf1005e96e6e114545f 486 1752729534294550000
@@ -1 +0,0 @@
v1 06dbbaa230ed7e4893e06c7d7b0a74c3f85cbf221900390847adc68c62283301 f870fd0a3200f0abce7ce8f8df69399dd89573e04742351f8ea82119368635b9 459 1752729534174431000
@@ -1 +0,0 @@
v1 06e2c6baf32b13da9627e5ddb734ccb8ade0122e6160e78d568f08f07e63ced5 34302c999cee9434664f6429e718bd00b47488b71c5a5f9d9f9a53cf0a902e4c 2305 1752729534344394000
@@ -1 +0,0 @@
v1 072411bfc257f9e7999bf2169dc60af54af1d8dcb1c87752499350f184cc04ba 20692bba3ab02044e322274c8f76a7af0b87b7f31082f57b031eed133ad33cea 1055 1752729534213741000
@@ -1 +0,0 @@
v1 073670b1f744d1f3fe6378199bfca8658907415de5f42ec6b2d006d2d7026996 0be9bbd37dd1a23e8579976a39a80d2387de975e3173883b4898143ba6d8e8bc 739 1752729534165148000
@@ -1 +0,0 @@
v1 07c80251e9ff3209b4fd6ead08f76a75c2bc19a75822868a4c4c2e45444602a8 e46ce2f016bf7d2437d63f59cbf17d60cfffc510bcfc0868c79965ec7ba2d1ae 564 1752729534132924000
@@ -1 +0,0 @@
v1 07e0a164eb19364eea3883830a5ad83a88d36950bbb384110fbac44239fa5cf7 3378ae2c93e3a2f7d850ccc7ba1137329cbf815af6dbfd6aabb5fbb9e2ccd4ed 1389 1752729534140538000
@@ -1 +0,0 @@
v1 0823fd55764924dd2a9a554f9d53189a96db5a43f339b53e4374282071341ba0 28aaa3fd00440a110be49cc1ec4567521b719634914c075f1883d04ff75e41e3 491 1752729534060044000
@@ -1 +0,0 @@
v1 082d7e4a549eb371f6bd83c244486e21ddbbf7214f19bf1892d477d2367591c9 68b50efc3cb50fe6520a7065fc0a97dd1f3b84acc5dd05d0887acbd711b36e10 11448 1752729534247798000
@@ -1 +0,0 @@
v1 088e0d771c8eb9d64c8e2277c395fe1bc0c2a8d0801d54f0affd3bbab61f1abc 42f5cd5b6bc8e518e704167ddaa8f9fcb2d81c1965bb94eb8ed9a16440e55566 355 1752729534315483000
@@ -1 +0,0 @@
v1 08a578161827bb885367904d14e5c1b3e7b4c4394593c25e20ab293f04538adf b9ea4f9f4a3b6b1595ebef48e39b69cb1b0af0f1059764a77a147478adaca141 440 1752729534134835000
@@ -1 +0,0 @@
v1 08ff1de899cf29947151d6715be04a694383a176530d3121fcbc3329b591bbae 468328f72e445c7d31e92ccb3d116a8a4b102296b17a913a91ebc7cb2b304f0e 22739 1752729534226664000
@@ -1 +0,0 @@
v1 092573c418a6dbd32a853993524ac96bc82eee8f2bf52bbc31cbffc92be31f8d dc122119327f5759f0bbf6c7a6c77a99d5aecc36978c61d9b720f75cb979b7a2 1024 1752729534326265000
@@ -1 +0,0 @@
v1 09410171969fda27b3305ea774c41313feee8a1a1ec92237c8e1b40da10b2df7 a4330779009b000c47149970a5594459e821be48e974751a94132768fe285344 16422 1752729534278921000
@@ -1 +0,0 @@
v1 09492ca5485bcdd000a0768b36c0e149df18a7b7c47e573587ab5fe9eea7cecd 02d52ad19f51642ebd948341774c44fc42ef6559542ba2a1f952b531d71e574d 711 1752729534080083000
@@ -1 +0,0 @@
v1 097c8270c020abb597e857601e09230b82d007f952b402a6f1898418460d91b6 7d30560b3051d5e0e9680c1df6c20259acf8a27696181a7860187b509b31e9d1 1591 1752729534169087000
@@ -1 +0,0 @@
v1 09d07fae543ef1c4ed6f16ec96665b0ab5d65a9a456264b04044eae720b67ff3 eb0f86ad7982017e5a6051be597c84b217795d5227de51527e3acefbab45e7e0 357 1752729534076860000
@@ -1 +0,0 @@
v1 09ea353fdacdb10b18a4c5143e83431500747ee21c1ea61821b7f53914e050a2 038f5c3ddfe65c06b0d3d0c7659766d21c56a5108975af8eb2b78584a214f00b 1081 1752729534098135000
@@ -1 +0,0 @@
v1 09eed6e0c9e57fdff0a77f41632e3347f15e2ef6f5cc46fe7f1c9aad473eb484 c48f88c19114161f82ff98825d9b8cd3e167cfa8287ac46fe22a8ef25cfd1da6 354 1752729534063331000
@@ -1 +0,0 @@
v1 0a1f6e1b306086f1fb291c4e383ee063fa12f83a98723483548144b630f414b1 0a1cae9cc6cd7c8d870d2d8399ead0540f3d540a9d06a96cd0adaebf672438da 944 1752729534379131000
@@ -1 +0,0 @@
v1 0a5d08654c3b721ba150511d921a5e39cc49bf2e816066f8444f59eb03d2e042 c57bc836853b1ed029c4cae0fafbd020813209651a3601511ff5498d4ee6a148 3296 1752729534265007000
@@ -1 +0,0 @@
v1 0b5f384b571a2fd524865f591f70bbcc81cd303114c4ec075a48d31579acc580 ec5d4bb71fb4e6536767c56079b6f646634500dc0600234621e67509e29466d6 721 1752729534164926000
@@ -1 +0,0 @@
v1 0b8b6abc6682ff3d6592f08fa53c08c2e82793f0f9f7933586a0bf587a58f3d4 ea89ada6132053cb1d9d3491b2016c995bb7ea700289c3d46318c6b12c6c1224 1676 1752729534141121000
@@ -1 +0,0 @@
v1 0bc3bc8db5f387a4a79f26354a40a3ab258421505342d04847ddb7f47fae5f13 22d7888e70f4fe6bc543ff357519d6475e88a0dfe8d866f9d1c469f35e154eff 568 1752729534310195000
@@ -1 +0,0 @@
v1 0bd91f50eb5f8254f2522a937fb9833f912209040807aaeaa4419179a60618a9 f84b7fa06d67fcbceb786395fa535dfd7d503548f12313aee3acd20a25677922 730 1752729534335289000
@@ -1 +0,0 @@
v1 0be0ffc2b4d648706d121ee868e2003b3cfc1015f06955be9ef3388251430da1 b0b3b49b87f49398c8c696f9f8d803e75375907df462a6397595e5b1be161811 461 1752729534175565000
@@ -1 +0,0 @@
v1 0c19367c921c803facc074b82f930d2a9a9d348b58d2b5c78bcf05722f151543 81a3e1d1e5d5073cf22e5bc82604142a75832f5d89e8f6adae676e9953357ec9 828 1752729534077706000
@@ -1 +0,0 @@
v1 0c71cca1b09bb8bc396d9504374ad1af4721a6c0754c4a0ff1188713c81626f6 99f6ea6d7df7cb97359972f04c28369e2511791c87fca0f3953982938ec0078b 673 1752729534077385000

Some files were not shown because too many files have changed in this diff Show More