configs(mainnet): activate 30 safe-subset precompiles forward-dated 2026-07-01 UTC

Task #114 — extend the Lux primary C-Chain upgrade.json with the 30 missing
safe-subset precompiles, forward-dated to blockTimestamp=1782864000
(2026-07-01 00:00 UTC = 29 days from authorship 2026-06-02, exceeding the
14-day validator-buffer minimum). Brand L2s (hanzo/zoo/pars/spc) already
carry these in their block-0 genesis; this catches the primary network up.

Safe subset framing:
- Brand L2 genesis = 43 precompiles (~/work/lux/genesis/configs/hanzo-mainnet/genesis.json).
- Primary C-Chain = 42 (brand L2 minus eciesConfig) + 3 standard EIP
  precompiles brand L2s don't carry (kzg4844Config, secp256r1Config,
  ed25519Config) + 3 burn handlers (dead*Config) + warpConfig.

Total after patch: 49 entries:
- 1 warpConfig at blockTimestamp=0 (genesis pre-alloc at 0x0200…0005).
- 18 already-live precompiles at blockTimestamp=0 (aiMining, blake3,
  cggmp21Verify, dead*x3, dexConfig, routerConfig, fheConfig, frostVerify,
  graphConfig, hpkeConfig, mldsaVerify, mlkemConfig, pqcryptoConfig,
  ringConfig, slhdsaVerify, zkConfig — the set inlined in
  ~/work/lux/universe/k8s/lux-mainnet/luxd-startup.yaml UPGRADE_JSON).
  These MUST stay at blockTimestamp=0 — luxd's checkPrecompileCompatible
  refuses to boot if an already-live precompile is rescheduled.
- 30 safe-subset additions at blockTimestamp=1782864000 (2026-07-01 UTC):
  Pulsar + Magnetar + P3Q + Corona threshold; HQC; BLS12-381 G1/G2/MSM/
  Pairing x7; Curve25519, X25519, Sr25519, BabyJubJub, Pedersen, Poseidon,
  Pasta, X-Wing; Compute Market, Bridge Registrar, StableSwap, VRF,
  Attestation, Anchor, FixedPointMath, KZG-4844, secp256r1, Ed25519.

Exclusions:

- eciesConfig — deliberately excluded per the rationale in
  ~/work/lux/precompile/x25519/contract.go (lines 17-23). ECIES requires
  the recipient's private key in calldata; calldata is world-readable on
  a public chain, irrecoverably exposing the key. Symmetric (AES,
  ChaCha20) precompiles were removed for the same reason. X25519/ML-KEM/
  HQC/X-Wing are retained because they expose only ciphertexts and
  ephemeral public material, never secrets.

- contractDeployerAllowListConfig, contractNativeMinterConfig,
  txAllowListConfig, rewardManagerConfig — admin-gated allowlists. The
  primary C-Chain is permissionless by design; activating these would
  hand admin to an arbitrary address (trust hazard) or activate empty
  (dormant gate, strictly worse). They remain available for subnet/L2
  activation where an admin role is appropriate.

- feeManagerConfig — removed from canonical. Previously parked at
  blockTimestamp=900000000 (1998) as a registry-slot placeholder; that
  placement violates the monotonicity rule enforced by
  extras.ChainConfig.verifyPrecompileUpgrades. Activate via a separate
  forward-dated governance event with admin addresses explicitly assigned
  if needed; the chain-config feeConfig is already pinned directly.

Strict-PQ profile gate (NetworkUpgradeOverrides.strictPQTimestamp =
1766708400) activates contract.StrictPQReporter on the ChainConfig from
the Quasar Edition activation (2025-12-25 16:20 PST). All classical
pairing-based / discrete-log precompiles call
contract.RefuseUnderStrictPQ(state) at the top of Run() (verified across
bls12381 + secp256r1 module.go dispatchers + babyjubjub / pasta /
pedersen / poseidon / curve25519 / x25519 / sr25519 / ed25519 / frost /
cggmp21 / kzg4844 contract.go). The 30 forward-dated activations all
fall after strictPQTimestamp, so no window exists where a classical
primitive executes permissively on the primary network.

Tests (luxfi/evm params/extras):

- TestMainnetUpgradeJSON_IsForwardCompatibleWithLiveActivations PASS
  (every already-live precompile preserved at the same blockTimestamp).
- TestMainnetUpgradeJSON_PrecompileTimestampsAreMonotonic PASS
  (0 → 0 → ... → 0 → 1782864000 → ... → 1782864000, monotonic).
- TestMainnetUpgradeJSON_WarpRequiresPrimaryNetworkSigners PASS
  (warpConfig.requirePrimaryNetworkSigners=true).
- TestMainnetUpgradeJSON_HasStrictPQActivation PASS
  (strictPQTimestamp=1766708400).
- TestMainnetChainConfig_HasStrictPQTrue PASS (chain-configs side).

UPGRADE_NOTES.md sidecar documents the exclusion rationale, the activation
tier table, the strict-PQ posture, and a red-review checklist.

RED REVIEW REQUIRED — do not push to origin without sign-off. Mainnet
primary network upgrade is consequential.

Follow-up (separate PRs, out of scope):
- ~/work/lux/universe/k8s/lux-mainnet/luxd-startup.yaml currently writes
  the same UPGRADE_JSON to all 5 EVM chain config dirs (C + brand L2s);
  brand L2s already carry these precompiles in their block-0 genesis, so
  the override is at best a no-op and at worst a wedge. Patch to scope
  the inline upgrade.json to the primary C-Chain only and refresh its
  contents from this canonical file.
This commit is contained in:
Hanzo AI
2026-06-02 14:03:06 -07:00
parent d712fad7f9
commit 3354940651
2 changed files with 199 additions and 63 deletions
+149
View File
@@ -0,0 +1,149 @@
# Lux Primary C-Chain — `upgrade.json` Activation Notes
Source-of-truth for the Lux primary network C-Chain (chainId `96369`) precompile
activation schedule. This file lives next to `upgrade.json` to explain why each
activation is dated where it is, and which precompiles are deliberately
excluded from the primary-network safe subset.
## Safe-subset framing
- **Brand L2s** (hanzo, zoo, pars, spc) carry **43 precompiles** baked into
their genesis at block 0. See `~/work/lux/genesis/configs/hanzo-mainnet/genesis.json`
for the canonical L2 set; the precompile keys are identical across the four
brand L2 genesis files.
- **Primary C-Chain safe subset = 42** (brand L2 `43` minus `eciesConfig`),
plus three additional standard EIP precompiles that brand L2s do not need
but the primary network does (`kzg4844Config`, `secp256r1Config`,
`ed25519Config`), plus three burn-handler precompiles
(`deadConfig`, `deadFullConfig`, `deadZeroConfig`) that exist only on the
primary network, plus `warpConfig` and the AI-Mining / DEX / Router stack
already activated at genesis (`blockTimestamp: 0`).
## Exclusions
### `eciesConfig` — deliberately excluded
ECIES requires the caller to pass the recipient's *private key* in calldata
so the precompile can perform the discrete-log unwrap. Calldata on a public
chain is permanently world-readable; placing a private key there
irrecoverably exposes it. The same reasoning applies to the symmetric-key
precompiles (AES, ChaCha20), which were removed for the same reason — see
`~/work/lux/precompile/x25519/contract.go` lines 17-23 (the live comment
block carrying the rationale).
X25519 key exchange is retained because the shared secret is *not* in
calldata — only ephemeral public points are. ML-KEM-768 / HQC / X-Wing are
retained for the same reason: they expose only ciphertexts and encapsulated
keys, never secrets.
### `contractDeployerAllowListConfig`, `contractNativeMinterConfig`, `txAllowListConfig`, `rewardManagerConfig` — deliberately excluded
These are admin-gated allow-list precompiles whose activation requires the
operator to provide a stable `adminAddresses` list. The primary C-Chain is
permissionless by design — there is no admin address to assign — so
activating these would either (a) hand admin to an arbitrary address and
create a trust hazard, or (b) activate them empty and leave the gate
dormant, which is strictly worse than not activating them at all. They
remain available for brand L2 / subnet activation where an admin role makes
sense.
### `feeManagerConfig` — removed from canonical
Previously parked at `blockTimestamp: 900000000` (1998-07-09 UTC) as a
registry-slot reservation, but that placement violates the monotonicity
rule enforced by `extras.ChainConfig.verifyPrecompileUpgrades` (timestamps
must be non-decreasing across the upgrade list). The entry is removed from
canonical; if the FeeManager precompile is ever needed, it can be activated
via a separate forward-dated governance event with admin addresses
explicitly assigned. The current `chain-configs/lux-mainnet/config.json`
already pins `feeConfig` directly, so no behavioural change.
## Activation tiers
| Tier | Timestamp (Unix) | Timestamp (UTC) | Count | Notes |
|------|------------------|-----------------|-------|-------|
| Genesis | `0` | block 0 | 19 | `warpConfig` + 18 already-live precompiles (the set inlined in `~/work/lux/universe/k8s/lux-mainnet/luxd-startup.yaml` `UPGRADE_JSON`). DO NOT RESCHEDULE — luxd's `checkPrecompileCompatible` refuses to boot if any already-live precompile is moved to a different timestamp. The `IsForwardCompatibleWithLiveActivations` rollout test pins this contract. |
| Safe-subset extension (this patch) | `1782864000` | 2026-07-01 00:00 UTC | 30 | Forward-dated 29 days from patch authorship date (2026-06-02) to give validators upgrade buffer. Brand L2s already carry these at their own block-0 genesis. |
Total entries: **49** (1 warp + 18 live + 30 forward-dated).
## Strict-PQ profile gate
`strictPQTimestamp = 1766708400` (2025-12-25 16:20 PST / 2025-12-26 00:20
UTC) activates `contract.StrictPQReporter` on the ChainConfig. All
classical pairing-based / discrete-log precompiles (BLS12-381 G1/G2/Pairing,
BabyJubJub, Pasta) call `contract.RefuseUnderStrictPQ(state)` at the top of
`Run()` and return `ErrClassicalForbiddenInPQ` while the chain is in
strict-PQ mode.
The forward-dated activations at `1782864000` fall *after* the strict-PQ
activation, so every classical precompile in tier 2 is registered behind
the gate from its first block of activation. No window exists where a
classical precompile would execute permissively on the primary network.
## Forward-date rationale
Today's date when this patch was authored: **2026-06-02**.
Chosen activation: **`1782864000` (2026-07-01 00:00 UTC)** = **29 days of
buffer**.
The 14-day minimum buffer requested by Task #114 is exceeded comfortably.
A clean calendar boundary (Q3 start) was chosen so validators have an
unambiguous, easy-to-remember mark. UTC midnight has no DST drift.
## Deployment surfaces
This canonical file is the source-of-truth. The runtime distribution
surfaces that consume it:
1. `~/work/lux/genesis/configs/mainnet/upgrade.json` — canonical (this
file).
2. `~/work/lux/universe/k8s/lux-mainnet/luxd-startup.yaml` — k8s
StatefulSet startup script. Currently carries a hand-coded inline
`UPGRADE_JSON` shell variable with 17 of the 18 already-live activations
(the `aiMiningConfig` plus the 16 deterministic crypto/dex precompiles
activated at block 0). The same shell variable is written to all 5 EVM
chains (C + 4 brand L2s), which is a separate latent issue — brand L2s
already carry these precompiles in their genesis at block 0 and
overwriting their per-chain `upgrade.json` with the primary set is at
best a no-op and at worst a wedge. The k8s ConfigMap rewrite is the
operator-side follow-up; this canonical file change is the
source-of-truth side.
## Verification
After luxd reads this file at boot, validators on Lux mainnet should see:
- Existing primary-C-Chain RPC behaviour preserved (no boot regression);
`IsForwardCompatibleWithLiveActivations` is the gate.
- After `2026-07-01 00:00 UTC`: `eth_call` to BLS12-381 precompile
addresses succeed for honest inputs and return
`ErrClassicalForbiddenInPQ` (chain reports strict-PQ from `1766708400`).
- ML-DSA, SLH-DSA, ML-KEM, HQC, X-Wing precompiles available after
forward-date.
- Pulsar / Magnetar / Corona / P3Q threshold + PQ-STARK precompiles
available after forward-date.
## Red review checklist
- [ ] Every classical precompile in tier 2 (BLS12-381 family, BabyJubJub,
Pasta, Pedersen, Poseidon) is verified to call
`contract.RefuseUnderStrictPQ` at the top of its `Run()` method. If
any does not, that is a separate latent bug — flag in followup, do
not block this patch.
- [ ] The 30 new activations at `1782864000` do not introduce any
precompile whose source has not been audited or which has been
deprecated.
- [ ] Activation date `1782864000` (2026-07-01 00:00 UTC) is no earlier
than 14 days from merge time.
- [ ] No `eciesConfig`, `contract*AllowListConfig`, `*NativeMinterConfig`,
`rewardManagerConfig`, or `*MinterConfig` in the activation list.
- [ ] All 18 already-live precompiles stay at `blockTimestamp: 0` so
`checkPrecompileCompatible` does not refuse boot.
- [ ] Monotonicity test passes (no entry has a smaller blockTimestamp than
its predecessor in the list).
- [ ] k8s StatefulSet startup script is patched in a separate PR to (a)
inline the new canonical `UPGRADE_JSON` for the primary C-Chain only
and (b) stop writing `upgrade.json` to the brand L2 EVM chain
directories. The brand L2s already have precompiles in their genesis
at block 0.
+50 -63
View File
@@ -9,81 +9,68 @@
},
"precompileUpgrades": [
{"warpConfig": {"blockTimestamp": 0, "quorumNumerator": 67, "requirePrimaryNetworkSigners": true}},
{"aiMiningConfig": {"blockTimestamp": 1766708400}},
{"blake3Config": {"blockTimestamp": 1766708400}},
{"cggmp21Verify": {"blockTimestamp": 1766708400}},
{"deadZeroConfig": {"blockTimestamp": 1766708400}},
{"deadConfig": {"blockTimestamp": 1766708400}},
{"deadFullConfig": {"blockTimestamp": 1766708400}},
{"aiMiningConfig": {"blockTimestamp": 0}},
{"blake3Config": {"blockTimestamp": 0}},
{"cggmp21Verify": {"blockTimestamp": 0}},
{"deadZeroConfig": {"blockTimestamp": 0}},
{"deadConfig": {"blockTimestamp": 0}},
{"deadFullConfig": {"blockTimestamp": 0}},
{"dexConfig": {
"blockTimestamp": 1766708400,
"blockTimestamp": 0,
"protocolFeeController": "0x9011E888251AB053B7bD1cdB598Db4f9DEd94714",
"maxPools": 10000,
"enableFlashLoans": true,
"enableHooks": true
}},
{"routerConfig": {
"blockTimestamp": 1766708400,
"blockTimestamp": 0,
"v3QuoterAddress": "0x0000000000000000000000000000000000000000",
"v3FactoryAddress": "0x0000000000000000000000000000000000000000",
"v2RouterAddress": "0x0000000000000000000000000000000000000000",
"v2FactoryAddress": "0x0000000000000000000000000000000000000000"
}},
{"fheConfig": {"blockTimestamp": 1766708400}},
{"frostVerify": {"blockTimestamp": 1766708400}},
{"graphConfig": {"blockTimestamp": 1766708400}},
{"hpkeConfig": {"blockTimestamp": 1766708400}},
{"mldsaVerify": {"blockTimestamp": 1766708400}},
{"mlkemConfig": {"blockTimestamp": 1766708400}},
{"pqcryptoConfig": {"blockTimestamp": 1766708400}},
{"ringConfig": {"blockTimestamp": 1766708400}},
{"slhdsaVerify": {"blockTimestamp": 1766708400}},
{"zkConfig": {"blockTimestamp": 1766708400}},
{"feeManagerConfig": {
"blockTimestamp": 900000000,
"adminAddresses": ["0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"],
"enabledAddresses": [],
"initialFeeConfig": {
"gasLimit": 20000000,
"minBaseFee": 25000000000,
"targetGas": 15000000,
"baseFeeChangeDenominator": 36,
"minBlockGasCost": 0,
"maxBlockGasCost": 10000000,
"targetBlockRate": 2,
"blockGasCostStep": 500000
}
}},
{"pulsarVerify": {"blockTimestamp": 1766708400}},
{"magnetarVerify": {"blockTimestamp": 1766708400}},
{"p3qVerify": {"blockTimestamp": 1766708400}},
{"coronaThreshold": {"blockTimestamp": 1766708400}},
{"hqcEncapsulate": {"blockTimestamp": 1766708400}},
{"bls12381G1AddConfig": {"blockTimestamp": 1766708400}},
{"bls12381G1MulConfig": {"blockTimestamp": 1766708400}},
{"bls12381G1MSMConfig": {"blockTimestamp": 1766708400}},
{"bls12381G2AddConfig": {"blockTimestamp": 1766708400}},
{"bls12381G2MulConfig": {"blockTimestamp": 1766708400}},
{"bls12381G2MSMConfig": {"blockTimestamp": 1766708400}},
{"bls12381PairingConfig": {"blockTimestamp": 1766708400}},
{"curve25519Config": {"blockTimestamp": 1766708400}},
{"x25519Config": {"blockTimestamp": 1766708400}},
{"sr25519Verify": {"blockTimestamp": 1766708400}},
{"babyjubjubConfig": {"blockTimestamp": 1766708400}},
{"pedersenConfig": {"blockTimestamp": 1766708400}},
{"poseidonConfig": {"blockTimestamp": 1766708400}},
{"pastaConfig": {"blockTimestamp": 1766708400}},
{"xwingConfig": {"blockTimestamp": 1766708400}},
{"computeMarketConfig": {"blockTimestamp": 1766708400}},
{"bridgeRegistrarConfig": {"blockTimestamp": 1766708400}},
{"stableSwapConfig": {"blockTimestamp": 1766708400}},
{"vrfConfig": {"blockTimestamp": 1766708400}},
{"attestationConfig": {"blockTimestamp": 1766708400}},
{"anchorConfig": {"blockTimestamp": 1766708400}},
{"fixedPointMathConfig": {"blockTimestamp": 1766708400}},
{"kzg4844Config": {"blockTimestamp": 1766708400}},
{"secp256r1Config": {"blockTimestamp": 1766708400}},
{"ed25519Config": {"blockTimestamp": 1766708400}}
{"fheConfig": {"blockTimestamp": 0}},
{"frostVerify": {"blockTimestamp": 0}},
{"graphConfig": {"blockTimestamp": 0}},
{"hpkeConfig": {"blockTimestamp": 0}},
{"mldsaVerify": {"blockTimestamp": 0}},
{"mlkemConfig": {"blockTimestamp": 0}},
{"pqcryptoConfig": {"blockTimestamp": 0}},
{"ringConfig": {"blockTimestamp": 0}},
{"slhdsaVerify": {"blockTimestamp": 0}},
{"zkConfig": {"blockTimestamp": 0}},
{"pulsarVerify": {"blockTimestamp": 1782864000}},
{"magnetarVerify": {"blockTimestamp": 1782864000}},
{"p3qVerify": {"blockTimestamp": 1782864000}},
{"coronaThreshold": {"blockTimestamp": 1782864000}},
{"hqcEncapsulate": {"blockTimestamp": 1782864000}},
{"bls12381G1AddConfig": {"blockTimestamp": 1782864000}},
{"bls12381G1MulConfig": {"blockTimestamp": 1782864000}},
{"bls12381G1MSMConfig": {"blockTimestamp": 1782864000}},
{"bls12381G2AddConfig": {"blockTimestamp": 1782864000}},
{"bls12381G2MulConfig": {"blockTimestamp": 1782864000}},
{"bls12381G2MSMConfig": {"blockTimestamp": 1782864000}},
{"bls12381PairingConfig": {"blockTimestamp": 1782864000}},
{"curve25519Config": {"blockTimestamp": 1782864000}},
{"x25519Config": {"blockTimestamp": 1782864000}},
{"sr25519Verify": {"blockTimestamp": 1782864000}},
{"babyjubjubConfig": {"blockTimestamp": 1782864000}},
{"pedersenConfig": {"blockTimestamp": 1782864000}},
{"poseidonConfig": {"blockTimestamp": 1782864000}},
{"pastaConfig": {"blockTimestamp": 1782864000}},
{"xwingConfig": {"blockTimestamp": 1782864000}},
{"computeMarketConfig": {"blockTimestamp": 1782864000}},
{"bridgeRegistrarConfig": {"blockTimestamp": 1782864000}},
{"stableSwapConfig": {"blockTimestamp": 1782864000}},
{"vrfConfig": {"blockTimestamp": 1782864000}},
{"attestationConfig": {"blockTimestamp": 1782864000}},
{"anchorConfig": {"blockTimestamp": 1782864000}},
{"fixedPointMathConfig": {"blockTimestamp": 1782864000}},
{"kzg4844Config": {"blockTimestamp": 1782864000}},
{"secp256r1Config": {"blockTimestamp": 1782864000}},
{"ed25519Config": {"blockTimestamp": 1782864000}}
],
"stateUpgrades": []
}