Commit Graph
45 Commits
Author SHA1 Message Date
zeekayandHanzo Dev 8c06c66a86 registry: link the precompile suite by its own registry
This file named 41 suite packages one by one so their init() would run, because
luxd rejects an upgrade.json activation for a configKey it has never seen with
"unknown precompile config". That made it a second record of what the suite
contains, and it had drifted: aivmbridge, swap and v3 registered in the suite and
were absent here, so no Lux chain could activate them however its genesis was
written.

Importing the suite's registry instead cannot drift — that package derives its set
from the packages that actually register rather than from a list. One record, kept
in the repository that owns the thing recorded.

The list was also pinned to suite v0.19.8 while the suite had moved to v0.19.21,
so even the import alone left 14 of 56 modules linked. With the bump the surface
a luxd built from this module dispatches is 56, which is exactly what the suite
holds — measurable rather than asserted: cmd/surface prints it, and it is the
list an upgrade.json is allowed to name.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 17:59:23 -07:00
zeekayandHanzo Dev 6337b219aa style: gofmt the tracked EVM tree
Co-authored-by: Hanzo Dev <[email protected]>
2026-08-21 11:51:32 -07:00
zeekayandHanzo Dev c56386b415 stakeweight: make P-chain stake a usable on-chain vote weight
P-chain stake is not natively readable from the C-chain EVM, and the obvious
fix — a precompile that reads the validator set in Run() — is consensus-fatal.
The BlockContext handed to Run() (precompile/contract/interfaces.go:63) carries
Number, Timestamp and GetPredicateResults, and nothing else; a validator-set
read from there would have to use the node's own current P-chain height
(node vms/platformvm/validators/manager.go:214 getCurrentHeight ->
state.GetLastAccepted), so two honest nodes executing the same block a second
apart would compute different weights and fork the chain.

The one place a P-chain height IS agreed is predicate verification:
Block.VerifyWithContext passes ProposerVMBlockCtx.PChainHeight to
VerifyPredicate (plugin/evm/block.go:283), the pass/fail bitset is written into
the header (miner/worker.go:514) and re-checked on replay
(plugin/evm/block.go:366). A ballot verified there is a consensus-committed
fact, and historical sets stay reconstructible from P-chain weight diffs.

So the ballot CLAIMS a weight and the predicate refuses any overstatement:
  weight <= weightAt(ballot.pChainHeight)  - no flash-stake
  weight <= weightAt(block.pChainHeight)   - no exited or shrunken validator
  totalWeight == totalAt(snapshot)         - the denominator is exact
Under-claiming is always allowed, so a voter never has to predict which block
its transaction lands in.

The unit of weight is the validator, and it already includes delegations: the
P-chain keeps one weight per nodeID and folds each delegator into it
(node vms/platformvm/state/state_validators.go:570,582 — AddStaker(own stake)
then AddWeight(each delegator) under the same key). One map entry per nodeID is
what makes double-counting a delegation impossible. Delegators do not get a
separate ballot; their override is exit, which needs no code.

Authorisation reuses the BLS key the P-chain already binds to the nodeID, so
there is no registry to capture, no admin to hold it and no key ceremony. The
signature covers (domain, chainID, nodeID, voter, authEpoch) only — a standing
authorisation, reusable for every later proposal, rotated by signing a strictly
greater epoch.

Uptime is deliberately not a gate: it is absent from GetValidatorOutput and is
a per-node subjective measurement (all five mainnet validators report
uptime 0.0000 through the public API), so no deterministic rule can read it.

Proven against a read-only fork of mainnet 96369 — the real five-validator set,
real registered BLS keys, real 5e17/2.5e18 weights — including that no ballot
is accepted for any of them without the operator's key.

Address 0x0200...0006 is the next free slot after warp; eth_getCode on 96369
returns 0x for it and 0x01 for warp, so predicates are already live there.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 13:36:21 -07:00
zeekayandHanzo Dev d260656efc evm: gate DEX 0x9999 genesis injection on protocol ActivationTime (preserve pre-2025 genesis)
The AlwaysOn DEX settlement precompile (0x9999) had its EXTCODESIZE marker
baked into EVERY chain's genesis state unconditionally (parent==nil in
ApplyPrecompileActivations), mutating the genesis state root. This changed the
genesis hash of every chain genesised before the DEX activation, breaking RLP
re-import of the real archived Lux mainnet (0x3f4fa2a0), Lux testnet
(0x1c5fe377) and Zoo mainnet (0x7c548af4) — all re-genesised Nov 2024, before
the Dec-2025 activation.

Fix: an AlwaysOn system precompile carries a protocol ActivationTime (Dec 2025
for 0x9999, set by the registry bridge — a fork-like constant, not per-net
config). Its genesis marker is installed ONLY IF ActivationTime <= the genesis
timestamp; otherwise it activates later, on the block transition that crosses
ActivationTime during history replay. Dispatch (GetExtrasRules) is gated on the
same timestamp so a codeless address never dispatches. A chain born before
activation reproduces its ORIGINAL genesis byte-for-byte; a fresh chain born
at/after activation still gets 0x9999 at genesis.

Verified against the real RLP block-0 of all three chains (byte-identical
reproduction) plus a fresh post-activation chain. Corrects two pre-existing
tests that had hardcoded the buggy with-0x9999 hashes as "canonical".

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-02 16:50:11 -07:00
zeekay 5460f8370e feat(evm): enable standard precompiles — remove vestigial strict-PQ refusal layer
Enable-everything builder surface (public permissionless launch). The geth-layer
strict-PQ profile (LuxStrictPQ) refused ecrecover / p256Verify / sha256 /
ripemd160 / blake2f / bls12381 / kzg under vm.config.PQ — but ecrecover
(secp256k1) is THE Ethereum signature path every dapp depends on, and the rest
are verify-only / hash, key-safe. Refusing them breaks the builder surface.

The chain now installs NO forbidding pq.Profile: chainConfig.PQ stays nil,
which pq.RefuseUnder(nil) treats as permissive. The generic geth mechanism
(chainConfig.PQ + runPrecompile.RefuseUnder + legacypool nil-check) is kept for
any chain that wants it; Lux installs nothing.

This completes the decomplect started in luxfi/precompile: consensus PQ and the
EVM precompile profile were complected through config.PQ / StrictPQTimestamp.
After precompile dropped contract.RefuseUnderStrictPQ from every verify-only
precompile, the whole strict-PQ projection here was dead. Removed:
  - plugin/evm/pq_profile.go (LuxStrictPQ)
  - plugin/evm/vm.go: the `if vm.config.PQ { chainConfig.PQ = LuxStrictPQ() }`
    install + the unconditional StrictPQTimestamp=0 genesis pin
  - plugin/evm/config: the config.PQ bool field (no code writer; was JSON-opt-in)
  - params/extras/network_upgrades.go: StrictPQTimestamp field + apply + IsStrictPQ
  - precompile/registry/bridge.go + core/precompile_overrider.go: the dead
    IsStrictPQ adapters (only existed to feed the deleted StrictPQReporter)
  - tests: pq_test.go, strict_pq_activation_test.go, and the two StrictPQ
    assertions (+ orphaned helper) in precompile_upgrade_rollout_test.go

Lux's PQ security is enforced at consensus / identity (quasar/p3q), not by
refusing an EVM verifier a dapp asked for. The live lux-mainnet upgrade.json
never actually set strictPQTimestamp, so this matches production.

Build: full module green. Tests: params/extras, plugin/evm/config,
precompile/registry pass.
2026-06-27 21:14:05 -07:00
zeekay 06091588fc evm: precompile v0.15.0 (active-only DEX money path) + retire pqcrypto bundle (standalone mldsa/mlkem/slhdsa); no dormant AtomicStager, no backward compat 2026-06-27 18:48:21 -07:00
zeekay 8272580165 evm: thread real consensus identity + GetCodeSize into 0x9999 value path
The 0x9999 DEX precompile must see the true (networkID, cChainID) and prove
an ERC-20 has live code, on BOTH paths:

- block processing: ApplyTransactionWithResults now threads bc.ConsensusContext()
  onto blockContext.ConsensusContext when absent (nil-guarded; the miner's
  NewEVMBlockContext already sets it). The stale "StatefulPrecompileHook not
  exposed" note is removed — vm.NewEVM preserves ConsensusContext onto evm.Context.
- eth_call/estimateGas: ChainContext.ConsensusContext now returns the backend
  blockchain's consensus context (which embeds the chain Runtime via
  runtime.WithContext), not the RPC request context — the latter made every
  identity-reading precompile see networkID 0 / C-Chain Empty (fail-closed) on
  eth_call. EthAPIBackend.ConsensusContext exposes it.
- stateDBBridge.GetCodeSize forwards EXTCODESIZE to the internal StateDB so the
  OnChainAssetVerifier's C1 live-code proof works; returns -1 (not 0) when
  unavailable so the value path fails CLOSED rather than admit a fabricated zero.

Adds cmd/dexlive (real end-to-end 0x9999 value-path harness over a running
localnet C-Chain: deploy 2 ERC-20s, open market, seed maker, taker swap, read
DEXFill + balance deltas; synthetic/no-code negative control must revert) and
the consensus-identity unit tests for both paths.
2026-06-23 01:06:53 -07:00
zeekay b80a7d0ffd evm: wire the per-network DEX governance controller into the 0x9999 value path
HIGH-3 host side. The always-on 0x9999 settlement precompile resolves its halt +
pot-seeding authority from contract.AtomicState.GovernanceController(); this is the
production wiring that supplies it — a per-network governance CONTRACT, never a
hardcoded mnemonic-derivable EOA.

  - dex_value_wiring.go (installDEXValuePath): bind rt.GovernanceController =
    dexGovernanceFor(networkID) onto the chain runtime at boot (the ONE production
    site), alongside the asset resolver + native D client, and log it. dexGovernanceFor
    is the genesis-set per-network governance-contract seam: it returns ids.ShortEmpty
    for every network TODAY (no Governor/Timelock is deployed at a known address on any
    Lux network yet), so every network runs FAIL-CLOSED (no halt authority — provably no
    single key can DoS the DEX) until its real governance CONTRACT address is wired in,
    per net. The directive is explicit: each entry MUST be a governance contract, NEVER a
    dev-mnemonic EOA, and NEVER the retired 0x9011…94714. The boot log makes an unset
    authority loud ("<unset: halt/seed FAIL-CLOSED — deploy + wire a governance contract>").
  - core/precompile_overrider.go + precompile/registry/bridge.go: accessibleStateAdapter
    and accessibleStateBridge implement GovernanceController() (ids.ShortID→common.Address,
    exact 20-byte conversion); the internal twin interface gains the method. Returns the
    zero address (fail-closed) when the runtime/atomic capability is absent.
  - precompile/contract/atomic.go (evm-internal twin): AtomicState gains GovernanceController().

Builds clean (CGO off) across plugin/evm, core, precompile/registry; the dexsettle_guard
parity test passes. Normal trading is unaffected (halt switches are emergency controls,
off by default); only the ability to halt is gated — which previously only a mnemonic-EOA
holder had (a vuln), so no legitimate capability is lost and a censorship/DoS vector is removed.
2026-06-22 22:50:19 -07:00
zeekay 06c4d8916c precompile env: gate the Call surface to the DEX settlement family (0x9999/0x9996)
GetPrecompileEnv() is on the SHARED external contract.AccessibleState interface,
so the live Call surface (whose sub-call msg.sender is the asserting precompile's
OWN address) is reachable by every external precompile that type-asserts the
optional callableEnv capability. Bound that blast radius with defense-in-depth:

- precompile/registry/bridge.go: callableEnvAllowlist keyed on the geth env's
  self-address (env.Addresses().Self), populated from the canonical
  dex.LXSettleAddress (0x9999) + dex.DEXPositionManagerAddress (0x9996) constants
  (one source of truth). Every other external precompile (PQ/ZK verifiers at
  0x0122xx, future ones) gets a nil callable env and falls back to fail-secure
  refusal. No live behaviour change today (none assert callableEnv yet) — it
  prevents a FUTURE precompile silently acquiring sub-call power. Sits on top of
  each settlement Run's CALL-only guard.
- core/precompile_overrider.go: GetPrecompileEnv comment corrected — the accessor
  is off the EVM-INTERNAL interface but IS on the shared external one; reach is
  bounded by the bridge gate + the settle CALL-only guard.
- precompile/registry/bridge_precompileenv_test.go: recordingEnv carries a self;
  TestBridge_GetPrecompileEnv_NonSettlementSelf_Gated (0x012204 verifier -> nil,
  no Call) + _PositionManagerSelf_Allowed (0x9996 -> non-nil); WiredForwardsCall
  now models the 0x9999 self.
2026-06-22 14:37:01 -07:00
zeekay 1e41171291 precompile env: wire 0x9999 ERC-20 Call surface to the DEX precompile
ROOT CAUSE: the external DEX 0x9999 settlement precompile's ERC-20 leg (transferFrom/
transfer/balanceOf on the token contract) needs the EVM Call surface, but the adapter
chain that delivers its AccessibleState narrowed Call away:

  geth evmPrecompileEnv{Call}
   -> evm/core accessibleStateAdapter{env}        (env captured, not exposed)
   -> evm/registry accessibleStateBridge          (GetPrecompileEnv() => nil)
   -> luxfi/precompile contract.PrecompileEnvironment (no Call)

so poolStateAdapter.callable() got nil and every ERC-20 deposit/withdraw refused with
ErrERC20VaultUnavailable (fail-secure — never minted). Native LUX settlement was
unaffected because it uses GetBalance/SubBalance, already plumbed through the bridges.

FIX (minimal, off the shared many-implementer interfaces):
- evm/core accessibleStateAdapter.GetPrecompileEnv() exposes the geth env it already
  holds (concrete accessor, NOT a widening of the internal contract.AccessibleState).
- evm/registry accessibleStateBridge.GetPrecompileEnv() type-asserts that accessor and
  returns precompileEnvBridge, which adds the callableEnv-shaped Call the precompile
  type-asserts; nil (fail-secure) when no geth env is present.
- Call forwards with NO caller proxying: the token's msg.sender is the precompile self
  (0x9999), matching the depositor's approve(0x9999) allowance. Proxying would check
  the wrong allowance and break the pull.

geth is UNTOUCHED: vm.PrecompileEnvironment already declares Call; the DEX never runs
through geth's own accessibleStateAdapter (that path serves only the PQ precompiles).

Regression guards: core pins *accessibleStateAdapter satisfies the envProvider accessor
and returns its env; registry pins the bridge returns a non-nil callable env that
forwards Call (value passed, ZERO options) when wired, and untyped-nil otherwise
(no-env + typed-nil traps).
2026-06-22 14:37:01 -07:00
zeekay 8e04c4e23f evm: fix 0x9999 dispatch consensus-divergence on replay path + harden value/genesis edges (v1.99.34)
Red review of the 0x9999 dated-fork activation (v1.99.33) found ONE HIGH that
blocked the production deploy, plus a money-path footgun and two guards. The
money path (V4 swap ABI, EXTCODESIZE marker, two-phase atomic settle) is
byte-for-byte unchanged — only the dispatch-path timestamp source, the SubBalance
fail-mode, the genesis-builder guard, and stale comments change. Bumps
precompile v0.5.53 -> v0.5.54 (Red L1 comment scrub).

H1 (HIGH, blocked deploy) — consensus-divergence on the relaunch/replay path:
  core.LuxPrecompileOverrider.PrecompileOverride read the PROCESS-GLOBAL
  params.lastRulesContext via GetRulesExtra(Rules{}). That global is rewritten
  last-writer-wins by SetRulesContext on every Rules()/RulesAt() — including
  concurrent eth_call/estimateGas/miner goroutines. The geth EVM invokes
  PrecompileOverride LAZILY during opcode execution, a different instant than when
  precompileHook set the global. On a live, RPC-serving post-fork node replaying a
  PRE-fork RLP block (admin.importChain), a concurrent post-fork eth_call could
  overwrite the global timestamp between the verify goroutine's NewEVM(pre-fork
  block) and its tx dispatch -> the pre-fork block sees 0x9999 ENABLED and
  dispatches SettleContract.Run during plain-account execution -> STATE DIVERGENCE.
  Fix: the dispatch gate now decides from the overrider's OWN per-EVM fields
  (o.chainConfig + o.timestamp) via the pure params.GetExtrasRules — which performs
  the SAME dated-fork (extras.IsDexSettleActive) computation GetRulesExtra did,
  minus the racy global read. Audited every GetRulesExtra reader: only the overrider
  was on the precompile-dispatch path; no other dispatch/consensus-replay call site
  consults the 0x9999 gate. Every replay of a given block now yields the same
  enabled set on every validator, independent of concurrent activity.

L2 (money-path footgun) — registry stateDBBridge.SubBalance fail-open silent mint:
  when the subBalancer type-assertion failed it logged + returned a zero 'previous
  balance' WITHOUT subtracting, while the caller treats the debit as successful ->
  native value minted. Now FAILS CLOSED: it panics, which the EVM recovers into a
  reverted call, so the enclosing value move rolls back rather than committing
  half-done. Structurally unreachable in prod (the concrete adapter implements
  SubBalance) but no longer mints if a future StateDB omits it.

INFO1 (latent footgun) — genesis-config builders bypassed the dated fork:
  SetAllGenesisPrecompiles/AllGenesisPrecompiles iterated ALL RegisteredModules()
  incl the AlwaysOn 0x9999 and wrote timestamp-0 genesis configs, which would enable
  0x9999 from block 0 on a fresh chain — bypassing the dated fork and re-introducing
  the genesis-marker mutation. Both builders now skip AlwaysOn modules.

INFO2 (tests):
  - core: -race regression TestDexSettle_PrecompileOverride_NoGlobalRace reproduces
    the exact relaunch race (pre-fork verify vs concurrent post-fork eth_call
    clobbering the global) and asserts the pre-fork side ALWAYS sees 0x9999 ABSENT,
    post-fork ALWAYS PRESENT. PerEVMTimestamp pins the gate reads o.timestamp not the
    global. Replay e2e asserts a pre-fork value transfer to 0x9999 credits a PLAIN
    account WITHOUT invoking the precompile. All proven to FAIL under the old
    global-read code and PASS under the fix; -race clean.
  - extras + core: TestGenesisPrecompileBuilders_SkipAlwaysOn / _Skip9999 pin INFO1.
  - subbalance test comment refreshed to 0x9999 + fail-closed semantics.
2026-06-21 12:42:42 -07:00
zeekay d6a6584ad1 dex(0x9999): timestamp-gated dated-fork activation + marker install (v1.99.33)
Replace the v1.99.32 "always-on, dispatch-only, no marker" activation of the
0x9999 DEX settlement money path with the CTO's exact model: a SINGLE canonical
dated fork that both enables dispatch AND installs the EXTCODESIZE marker —
forward, at the fork boundary, never in historical genesis.

The fork: extras.DexSettleActivationTime = 1766704800 (Dec 25 2025 00:00:00 UTC),
defined ONCE in params/extras/network_upgrades.go alongside the Durango/Quasar/
Fortuna/Granite built-in upgrades. NOT per-net config (no per-net upgrade.json
precompileUpgrades entry, no genesisPrecompiles entry) — one dated fork, identical
on every Lux network, DRY. This is the proper canonical fork mechanism for a
system precompile that takes no per-net parameters (0x9999 resolves protocolFee-
Controller=DefaultDAOTreasury and dChainID at runtime from the consensus context).

Two coupled effects, both gated on that one timestamp:

  1. DISPATCH (params/config_extra.go GetExtrasRules): the AlwaysOnModules() inject
     into the enabled precompile set is now wrapped in extras.IsDexSettleActive(ts)
     — present at/after Dec 25, ABSENT before. This is REQUIRED for canonical
     history: replaying a pre-Dec-25 block (the ~/work/lux/state RLP snapshot, e.g.
     lux-mainnet 96369 = 1,082,780 blocks via admin.importChain) must see 0x9999 as
     a PLAIN ACCOUNT so a historical value transfer to that address behaves as it
     did originally, not as a precompile dispatch. The prior unconditional inject
     would have diverged replay from canonical state.

  2. MARKER (core/state_processor_ext.go ApplyPrecompileActivations): on the block
     transition that CROSSES the fork (params.IsDexSettleForkTransition →
     extras.IsForkTransition), write the STANDARD precompile-activation marker
     (SetNonce=1 + SetCode{0x1}) into 0x9999 — identical to the config-driven path.
     This is the forward state upgrade: EXTCODESIZE(0x9999)>0, eth_getCode!=0x, and
     Solidity's contract-existence guard passes for a typed IPoolManager(0x9999)
     .swap(...). The prior change DROPPED this marker to avoid mutating genesis;
     installing it forward at the fork preserves the genesis hash (pre-activation
     blocks get NO marker) while making typed calls work post-activation. Reverts
     the v1.99.32 "writes NO genesis state for always-on modules" skip.

IsForkTransition fires exactly once (!parentForked && currentForked). For a fresh
net whose genesis timestamp is already >= the fork (parent==nil), it fires at
genesis — so fresh/local/new nets carry the marker from block 0 via the SAME
mechanism, no separate genesisPrecompiles entry (CTO step 4). For an existing net
(genesis ts < fork) it does NOT fire at genesis — genesis hash immutable — and
fires forward at the Dec 25 block.

KEPT byte-for-byte: runtime DChainID via BCLookup.Lookup("D"), DefaultDAOTreasury
protocolFeeController, networkID/cChainID from runtime context, AlwaysOn module
tagging + AlwaysOnModules(), all settlement/money-path logic.

0x9010: with precompile v0.5.53 the 0x9010 module is no longer registered, so the
EVM never dispatches it and eth_getCode(0x9010)=0x. registry comment updated to
LP-9999. No EVM-side 0x9010 dispatch reference existed.

deps: precompile v0.5.52 -> v0.5.53.

Tests (core/precompile_alwayson_test.go, rewritten — DRY, replaces the prior
unconditional/no-marker assertions):
  - TestDexSettle_DispatchGate_TimestampGated: 0x9999 absent pre-fork, present
    at/after (replay safety + post-activation dispatch).
  - TestDexSettle_NoGenesisMarker_ExistingNet: genesis (ts<fork) writes no marker
    (genesis hash immutable).
  - TestDexSettle_MarkerInstalledAtForkTransition: marker (nonce=1 + code, EXTCODESIZE>0)
    installed at the boundary block.
  - TestDexSettle_ForkTransitionFiresOnce: fires once; fresh-net genesis>=fork at
    block 0; existing-net genesis<fork not at genesis.
  - TestAlwaysOn_9999_Registered: 0x9999 bridged AlwaysOn.
  core + params/extras green incl. the real-mainnet genesis-hash guards. (Two
  pre-existing unrelated failures on pristine main: params/config_test.go references
  a removed DurangoTimestamp field; params/extras mainnet upgrade.json ringConfig/
  warpConfig timestamp guards — both fail identically with these changes stashed.)
2026-06-21 12:09:46 -07:00
zeekay 570308a113 dex(0x9999): always-on settlement activation + runtime DChainID (v1.99.32)
Wire the EVM side of the always-on DEX settlement money path 0x9999. It is ACTIVE
on every chain from genesis with NO config entry — neither a genesis-inlined
precompile nor a precompileUpgrades timestamp. Zero per-net config, one way.

Activation is DISPATCH-only (genesis state is consensus-critical and immutable):
  - params.GetExtrasRules injects every modules.AlwaysOnModules() entry into the
    enabled precompile set unconditionally (every chain, every timestamp). This is
    what PrecompileOverride.IsPrecompileEnabled consults, so 0x9999 runs for a
    tx-to-0x9999, a low-level CALL/STATICCALL, and the 0x9010 V4 forward.
  - ApplyPrecompileActivations writes NO genesis state for always-on modules. An
    EXTCODESIZE marker at genesis would change the genesis hash and FORK existing
    networks (a fresh-syncing node would disagree with the committed genesis). The
    real lux-mainnet genesis hash is preserved (TestSkipPostMergeFieldsGenesisHash).
  - The always-on module's Configurator is never invoked (no activating config).

DChainID runtime resolution (THE crux): contract.AtomicState gains DChainID(); the
EVM adapter (accessibleStateAdapter) resolves it from the consensus context via
runtime.GetBCLookup().Lookup("D") — the dexvm "D"/"dex"/"dexvm" alias the node
registers in initChainAliases before any chain bootstraps. Identical on every
validator and re-execution; ids.Empty on a network with no dexvm (seam stays closed,
fail-secure). The registry bridge forwards DChainID across the internal/external
AtomicState surfaces. modules.Module gains AlwaysOn (+ AlwaysOnModules()), bridged
from github.com/luxfi/precompile.

deps: precompile v0.5.51 -> v0.5.52 (DChainID + AlwaysOn + always-on settle module).

Tests: core suite green incl. the real-mainnet genesis-hash guards. New
core/precompile_alwayson_test.go: 0x9999 registers AlwaysOn, is dispatch-enabled with
NO config at genesis + far-future ts, and writes NO genesis state (genesis-hash
immutability). (Two pre-existing unrelated failures: params/config_test.go references
a removed DurangoTimestamp field; mainnet upgrade.json aiMining/warp timestamp guards
— both fail identically on pristine main.)
2026-06-21 09:21:06 -07:00
zeekay 8f942b3943 plugin/evm: one-batch-atomic DEX native seam flush (FIX 2 chain-halt)
The host side of the 0x9999 native C<->D atomic seam, and the consensus-liveness
fix Red found.

THE BUG: Block.Accept applied the staged atomic ops to shared memory FIRST
(sm.Apply, no batch -> committed immediately) and advanced the node-local seq
marker LATER, in a separate versiondb.Commit(). atomic.SharedMemory.Apply is NOT
idempotent (duplicate Put errors). A crash BETWEEN them left shared memory
mutated but the marker unadvanced; on restart the same parent->current window
re-collected, sm.Apply re-applied the present Put, errored, and Accept returned
fatal -> the chain HALTED.

THE FIX (mirrors chains/dexvm commitAtomic): flushDexAtomic -> stageDexAtomic
stages the advanced dexAtomicSeqKey marker INTO the versiondb in-memory layer and
returns (reqs, sm). Block.Accept snapshots the versiondb (marker + lastAccepted)
via CommitBatch() and passes it to sm.Apply(reqs, batch) — its WriteAll commits
the shared-memory mutation AND the batch in ONE database write. The marker advance
and the SM mutation are now all-or-nothing: a crash applies-and-marks both or
neither, and a re-accept of an applied window sees an advanced marker -> empty
window -> no duplicate Put -> no halt. With no atomic ops the plain
versiondb.Commit() path is unchanged.

Also: core/precompile_overrider.go wires CallIndex() through the EVM accessible-
state adapter; precompile/registry/bridge.go + precompile/contract/atomic.go
forward the optional contract.AtomicState capability to luxfi/precompile.

Regression for the closed halt window lives in precompile
native_haltwindow_test.go (unit). The live-path test (real versiondb + crash
injection) is CI-only (CGO + luxfi/accel LUXCPP). Local symbol-resolution proof:
CGO_ENABLED=0 go build ./plugin/evm/ compiles clean.
2026-06-21 00:19:47 -07:00
zooqueenandHanzo Dev d125bb74f3 feat(registry): activate AI inference + model-registry precompiles (precompile v0.5.38)
Bump luxfi/precompile v0.5.37 -> v0.5.38 and register the two new AI-family precompiles:
- inference     (0x0300..0003): deterministic on-chain int8 transformer (byte-exact across
                                Go/Rust/Metal/CUDA/HIP; the trustless on-chain 'thinking' path)
- modelregistry (0x0300..0002): governance-adopted versioned model-commitment registry
v0.5.38 also carries the ai (0x0300) atomic cross-chain mining methods (verifyAndMintWork/Data).

Additive + DORMANT: registering != activating. No chain runs these until its genesis/upgrade
config enables the ConfigKey (aiInferenceConfig / modelRegistryConfig). Mainnet C-Chain + zoo
do not; the Zoo L3 Beluga genesis does. Full registry init() verified clean — all precompiles
register with no address collision.

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-10 08:15:23 -07:00
zeekay edce485ac1 evm: codec rip — message.Manager + validators state hand-rolled binary
Salvages an in-flight Wave 1C cascade on evm/ (the EVM fork separate
from coreth and evmgpu). 17 files touched. Mirrors the coreth
migration patterns:

- plugin/evm/message/codec.go: defines local Manager interface with
  hand-rolled wrappers.Packer; drops codec.Manager polymorphic registry.
- plugin/evm/message/request.go: typed Marshaler boundary.
- sync/{client,handlers}/*.go: codec.Manager → message.Manager swap.
- plugin/evm/customrawdb/*: explicit big-endian for state sync schema.
- plugin/evm/validators/state/{codec,state,state_test}.go: hand-rolled.
- plugin/evm/upgrade/feewindow/window.go + plugin/evm/vm.go +
  network/network.go + plugin/evm/network_handler.go: call-site fixups.
- precompile/registry/registry.go: codec-free registration path.

Builds clean: go build ./...
2026-06-05 15:31:59 -07:00
zeekay 3a570ec52b params/extras: rollout regression tests + register 16 missing precompiles
Two changes for the Quasar Edition rollout:

1. precompile/registry/registry.go side-effect imports the 16 modules
   that ship in the canonical upgrade.json but were not yet wired into
   the registry: attestation, babyjubjub, bls12381, bridge, compute,
   curve25519, ed25519, math, pasta, pedersen, poseidon, sr25519,
   stableswap, vrf, x25519, xwing. Without these imports each module's
   init() never runs, so modules.RegisteredModules omits them and
   UpgradeConfig.UnmarshalJSON rejects the activation with
   "unknown precompile config: <key>", bricking luxd boot.

2. params/extras/precompile_upgrade_rollout_test.go (NEW) is the
   forward-compat regression gate against the live lux-mainnet config.
   Five subtests:
   - IsForwardCompatibleWithLiveActivations: every precompile
     activation currently in the lux-mainnet StatefulSet inline
     upgrade.json (18 entries at blockTimestamp:0 including the
     dead* family) MUST be preserved at the same blockTimestamp in
     the canonical upgrade.json, else checkPrecompileCompatible
     refuses boot.
   - PrecompileTimestampsAreMonotonic: verifyPrecompileUpgrades
     rejects non-monotonic timestamps; we verify the canonical
     config respects this.
   - WarpRequiresPrimaryNetworkSigners: warpConfig MUST pin
     requirePrimaryNetworkSigners=true (red-review finding #8).
   - HasStrictPQActivation: networkUpgradeOverrides MUST set
     strictPQTimestamp=1766708400 (Quasar timestamp) so
     contract.RefuseUnderStrictPQ fires.
   - HasStrictPQTrue: ~/work/lux/state/chain-configs/lux-mainnet/
     config.json MUST set "pq": true so the EVM plugin boots into
     strict-PQ posture.

The test uses raw JSON parsing (not typed UpgradeConfig.Unmarshal) so
it does not depend on the registry side-effect imports being loaded
in the test binary — avoiding cgo linker conflicts between sr25519's
NaCl-compat randombytes and the HQC PQClean randombytes shim.

Red review findings #2, #7, #8.
2026-06-01 21:12:21 -07:00
zeekay cad4a25469 feat: register all 8 LP-4200 PQ precompiles (magnetar 0x012207 + hqc 0x012208 + p3q 0x012205 added to init imports); bump luxfi/precompile v0.5.17→v0.5.23; force luxfi/lens v0.1.3 to break transitive lens-rc1 cascade 2026-05-19 11:42:17 -07:00
zeekay 8b4fc26000 precompile/registry: swap corona (old) for LP-4200 corona+pulsar threshold precompiles
The published v0.5.17 precompile pkg moved the Ring-LWE threshold scheme to
slot 0x012206 under the name 'corona' (its canonical upstream name) and
added the Module-LWE threshold (Pulsar) at 0x012204. Corona is gone —
its package was renamed corona during the LP-4200 unification pass.

Also bumps luxfi/precompile to v0.5.17 to pull in the corona/pulsar/p3q
module registrations and the bridge ErrChainNameTooLong sentinel.
2026-05-13 15:51:29 -07:00
zeekay 47d4a4aa94 params/extras: StrictPQTimestamp + per-chain PQ posture wiring (CR-2)
Closes CR-2 from the cross-stack adversarial audit: PQ posture on
multi-chain hosts moves from a process-global to a per-chain
ChainConfig setting. A strict-PQ subnet and a permissive L1 in the
same node process now refuse / admit classical primitives correctly,
independent of which subnet last initialised.

Surface:
  - NetworkUpgrades.StrictPQTimestamp *uint64 (json:"strictPQTimestamp")
    nil = chain is classical-permissive (default for non-Lux integrators)
    0   = strict-PQ from genesis (set by plugin/evm when config.PQ=true)
  - NetworkUpgrades.IsStrictPQ(time uint64) bool — fork rule
  - chainConfigAdapter.IsStrictPQ — bridges params/extras into the
    contract.StrictPQReporter contract that stateful precompiles call.
  - extChainConfigBridge.IsStrictPQ — type-asserts via a local
    interface so non-Lux chains integrating Lux precompiles remain
    classical-permissive (no contract widening forced on them).
  - plugin/evm: when config.PQ=true, vm.chainConfig.PQ is installed
    (covers 0x01..0x0a standard precompiles via runPrecompile gate) AND
    extras.StrictPQTimestamp is set to genesis (covers Lux stateful
    precompiles — KZG, Groth16, PLONK, fflonk, Halo2, BN254-Pedersen,
    BabyJubJub, Pallas/Vesta — via contract.RefuseUnderStrictPQ).

Module bumps:
  - github.com/luxfi/geth v1.16.91
    (bundles MLDSATxType (0x42) + per-chain PQ profile gate)
  - github.com/luxfi/pq v1.0.1-0.20260512064747-3d4c9414e15e
    (RefuseUnder promoted to method on *Profile)

No semantic change for chains that do not opt into PQ:
StrictPQTimestamp is nil, IsStrictPQ returns false, every classical
primitive admits, gas accounting unchanged.
2026-05-11 23:54:35 -07:00
zeekay 988e4f97ee feat: Lux EVM — GPU auto-detect, anchor precompile, nogpu build tag 2026-03-02 18:00:00 -08:00
zeekay 3da82f7eb2 feat: add bridge precompile registry module
Register bridge precompile in the modules registerer and add
bridge.go registry implementation.
2026-03-12 16:13:54 -07:00
zeekay 736fa4e15c feat: register zk, blake3, and dead address precompiles
Add ZK proof verification (Groth16, PLONK, Halo2), Blake3 hash
function, and dead/burn address routing precompiles to the registry.
2026-03-11 13:32:45 -07:00
zeekay d32e075809 refactor: update to vm v1.0.18, migrate log and metrics packages
- Update vm dependency to v1.0.18
- Remove internal log package in favor of luxfi/log
- Migrate prometheus to gatherer package
2026-01-11 21:38:34 -08:00
zeekay e440ade25e refactor: update imports to github.com/luxfi/constants 2026-01-08 19:36:51 -08:00
zeekay 4234da3b48 Update admin api, precompiles 2026-01-06 11:51:58 -08:00
zeekay 4b7da04687 Use luxfi/math/math instead of geth/common/math 2026-01-03 17:37:03 -08:00
Fuma Nama 569b09a1c7 chore(deps): update to latest luxfi packages, remove local replaces
- Remove local replace directives for node and geth
- Update to latest published versions:
  - geth v1.16.67
  - crypto v1.17.32
  - database v1.2.18
  - ids v1.2.6
  - p2p v1.18.3
2025-12-31 18:02:38 -08:00
zeekay df05c46ab3 Update precompile imports to singular module name
Changed import paths from github.com/luxfi/precompiles to
github.com/luxfi/precompile v0.2.0. Updated go.mod to require
the new singular module and exclude old plural versions.
2025-12-30 22:58:32 -08:00
zeekay 4692930eff feat(precompiles): enable FHE and rename precompileHook
- Enable FHE precompile from standalone precompiles package
- Rename luxRulesHook to precompileHook for clarity
- DEX precompiles to be imported from standalone precompiles package
- Clean up debug logging from vm.go

The FHE precompile uses pure Go TFHE implementation from
github.com/luxfi/fhe for on-chain homomorphic encryption.
2025-12-29 23:05:42 -08:00
zeekay 1c7d8d23ab chore: update module from luxfi/constants to luxfi/const v1.4.0
Update all imports to use renamed module path.
2025-12-29 14:25:24 -08:00
zeekay f5a46918fb refactor: consolidate crypto precompiles to standalone package
- Remove duplicate fhe, mldsa, pqcrypto, quasar from evm
- Update registry to import from github.com/luxfi/precompiles
- Remove local node replace directive
- Upgrade node to v1.22.69, precompiles to v0.1.8
- Keep EVM-specific precompiles: deployerallowlist, feemanager,
  nativeminter, rewardmanager, txallowlist, warp
2025-12-28 16:29:13 -08:00
zeekay 2df37edcf1 fix: upgrade geth to v1.16.62 and configure PQ crypto precompiles
- Upgrade geth to v1.16.62 (fixes circl import path in precompiles)
- Add proper config.go and module.go for mldsa precompile
- Add proper module.go for pqcrypto precompile
- Register both precompiles in registry.go
- Update LLM.md with PQ crypto documentation

All tests pass including previously failing accounts/abi/bind tests.
2025-12-24 23:56:48 -08:00
zeekay b1979b4a02 Update EVM 2025-08-01 01:23:42 +00:00
zeekay 7d8b52af3f Update copyrights properly 2025-07-21 21:10:03 -05:00
zeekay 8da155c1b1 Update imports 2025-07-18 01:55:16 +00:00
zeekay 9cb77af539 fix: remove ALL ava-labs/libevm imports
- Remove all references to github.com/ava-labs/libevm
- Clean up imports in state, triedb, and test files
2025-07-17 17:06:20 -05:00
zeekay 5bde5ae476 fix: resolve merge conflicts in test files
- Fixed merge conflicts in precompile_config_test.go
- Fixed merge conflicts in block_test.go
- Fixed merge conflicts in test_statedb.go
2025-07-17 16:44:45 -05:00
zeekay 4ac513dba4 Merge upstream subnet-evm v0.7.5
Merged latest upstream changes from ava-labs/subnet-evm v0.7.5 while preserving Lux customizations:
- Updated copyright headers to Lux Industries Inc 2025
- Kept Lux branding and network references
- Preserved custom Lux configurations
- Updated dependencies to latest versions
- Removed deprecated files (trie/, core/vm/, etc)
- Updated import paths to use go-ethereum libraries where applicable
2025-07-03 23:56:17 -04:00
zeekay 1d04d6d04f Update copyright headers to Lux Industries Inc 2025
Updated all copyright headers from "Lux Partners Limited" to "Lux Industries Inc" and updated the year to 2025 to reflect the new holding company structure.
2025-07-03 23:49:31 -04:00
a394a37a79 move warp to precompiles package (#1034)
* move warp to precompiles package

* move warp params to warp package

* use log gas cost from contract package

---------

Co-authored-by: Darioush Jalali <[email protected]>
2024-01-04 22:08:03 +00:00
zeekay d561b4d550 Sync upstream 2024-01-03 09:52:28 +01:00
zeekay f8dd36a8be Update SubnetEVM 2024-01-03 09:44:09 +01:00
aaronbuchwaldandGitHub 246815e95d Add warp contract implementation (#718)
* Add warp contract implementation

* Cleanup predicate test

* Fix new function signature

* Replace invalid fuzz test with unit test

* Add chain config to enable warp API for warp e2e test

* remove unused var

* Add experimental warning and move warp precompile to x/ package

* fix warning label

* Fix warning

* vm test nits

* Improve sendWarpMessenger sol comment

* more vm warp test nits

* Move warp params into params package

* More vm warp test nits

* Address more PR comments

* Remove triggerTx2

* Add check for expected topics from sendWarpMessage log

* Fix config test

* Fix incorrect replace

* remove unnecessary echo

* Address comments

* Address comments

* Address PR comments

* Improve comments

* Convert [32]byte type to common.Hash

* Add base cost for getVerifiedWarpMessage

* fix require equal type check

* Fix updated awm message format

* Update warp message format

* Move IWarpMessenger.sol to interfaces/

* Add newline to warp genesis

* uncomment assertion

* Fix broken links in README
2023-07-31 10:56:25 -04:00
Ceyhun OnurandGitHub d8a3e64378 Stateful Precompile Improvements (#389)
* move inline string ABIs to separate files and embed them (#383)

* move inline string ABIs to separate files and embed them

* fix tests

* fix tests

* unexport function

* Update accounts/abi/bind/bind.go

Co-authored-by: Darioush Jalali <[email protected]>

* fix func name

Co-authored-by: Darioush Jalali <[email protected]>

* replace getByKey with getByAddress (#395)

* rework on panics in precompiles (#418)

* rework on panics in precompiles

* Update precompile/allow_list.go

Co-authored-by: aaronbuchwald <[email protected]>

* Update precompile/fee_config_manager.go

Co-authored-by: aaronbuchwald <[email protected]>

* Update precompile/fee_config_manager.go

Co-authored-by: aaronbuchwald <[email protected]>

* fix reviews

* wrap errors in ConfigurePrecompiles

* cleaner errors

* Update utils.go

* Update miner/worker.go

Co-authored-by: aaronbuchwald <[email protected]>

* Update core/state_processor.go

Co-authored-by: aaronbuchwald <[email protected]>

Co-authored-by: aaronbuchwald <[email protected]>

* Precompile Specific Packages (#420)

* rework on panics in precompiles

* Update precompile/allow_list.go

Co-authored-by: aaronbuchwald <[email protected]>

* Update precompile/fee_config_manager.go

Co-authored-by: aaronbuchwald <[email protected]>

* Update precompile/fee_config_manager.go

Co-authored-by: aaronbuchwald <[email protected]>

* fix reviews

* wrap errors in ConfigurePrecompiles

* cleaner errors

* move reward manager precompile to package (WIP)

* rename files

* fix abi path

* move typecheck

* move precompiles to their own packages

* refactor precompile template

* remove test file

* upate comments

* rm test files

* new allowlist package

* Update precompile/utils.go

Co-authored-by: Darioush Jalali <[email protected]>

* Update precompile/nativeminter/contract_native_minter.go

Co-authored-by: Darioush Jalali <[email protected]>

* Update precompile/nativeminter/contract_native_minter.go

Co-authored-by: Darioush Jalali <[email protected]>

* Update precompile/utils.go

Co-authored-by: Darioush Jalali <[email protected]>

* Update precompile/nativeminter/contract_native_minter.go

Co-authored-by: Darioush Jalali <[email protected]>

* fix nits

Co-authored-by: aaronbuchwald <[email protected]>
Co-authored-by: Darioush Jalali <[email protected]>

* rename fee manager config struct (#427)

* rename struct

* rename fee config managers to fee managers

* fix comments

* Generalized upgrades rb (#434)

* introduce precompiles as registrable modules

* add precompile specific contract tests

* remove print debug

* add unmarshal tests

* remove unnecessary func

* fix initial disabled value

* register all modules in core/evm/contract_stateful

* more refactor & test fix

* sync template

* fix more tests

* rename file

* add comment

* rename

* fix linter

* use require error contains

* remove whitespace

* trim mock interface

* sort steps

* reviews

* Update precompile/stateful_precompile_module.go

* Update params/precompile_config.go

* Update params/precompile_config.go

* fix reviews

* add new module to configs and group module functions

* generalized-upgrades-rb review (#474)

* keep genesis disabled fix

* nits

* nits

* nit

* review fixes

* Update precompile/allowlist/allowlist.go

* use address in map

* fix linter for embedded keys

* update err messages

* more err update

* remove unnecessary function (#478)

* Start work on breaking cyclic dependency (#496)

* Update core/state_processor.go

* fix reviews

* Update precompile/contracts/txallowlist/contract_test.go

* Generalized upgrades rb nits0 (#512)

* Minor improvements

* restore readOnly

* more updates

* Add back readOnly to allow list tests

* Precompile improvements merge (#513)

Co-authored-by: aaronbuchwald <[email protected]>
Co-authored-by: Ceyhun Onur <[email protected]>
Co-authored-by: Darioush Jalali <[email protected]>
Co-authored-by: cam-schultz <[email protected]>
Co-authored-by: Matthew Lam <[email protected]>
Co-authored-by: cam-schultz <[email protected]>
Co-authored-by: omahs <[email protected]>
Co-authored-by: Anusha <[email protected]>
Co-authored-by: Hagen Hübel <[email protected]>
Co-authored-by: minghinmatthewlam <[email protected]>
Fix: typos (#428)
fix allow list comments (#469)
fix CGO flags issue (#489)
fix lint job (#499)

* review fixes

* minor nits

* fix precompile generator

* fix fee manager config test

* remove debug files

* Update core/state_processor.go

Co-authored-by: aaronbuchwald <[email protected]>

* fix comments

* restore statedb ordering

* fix configure in reward manager

* precompiles: adds a regression test for the IsDisabled case in AvalancheRules (#515)

* Rename configs: alternative (#520)

* alternative renaming for precompile configs

* fixes

* update naming

* rename to AllowListConfig

* simplify

* move blackhole check to module registerer (#523)

* move blackhole check to module registerer

* check blackhole first

* add unit test

* Add test case for registering module outside of reserved range

---------

Co-authored-by: Aaron Buchwald <[email protected]>

* precompile: improve test structure (#517)

* refactor precompile tests

* minor improvements

* nit

* fix merge

* rename package

* pr comments

* rm file

* merge AllowListTests

* pr comments

* explicit BeforeHook

* wspace

* Mark TestTransactionIndices flaky

---------

Co-authored-by: Aaron Buchwald <[email protected]>

* nit improvements (#529)

* nit improvements

* move comments to README

* Update cmd/precompilegen/template-readme.md

* Rename new config (#528)

* rename configurator's new config to make config

* use new built-in to create new config instance

* precompile: just nits (#534)
2023-02-22 12:27:48 -08:00