mirror of
https://github.com/luxfi/genesis.git
synced 2026-07-27 05:54:08 +00:00
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:
@@ -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.
|
||||
@@ -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": []
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user