mirror of
https://github.com/luxfi/precompile.git
synced 2026-09-24 00:26:21 +00:00
main
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ca0bf6b303 |
precompile: seven packages to 96-99%, from lanes killed before they could commit
slhdsa 97.9 · mlkem 97.4 · mldsa 96.8 · xwing 96.2 · bls12381 97.2 · kzg4844 97.8 · v3 98.7. All build, vet and gofmt clean, all green under -count=1, and preserved here rather than lost to a session limit. v3's lane did report before it died: 78.1% to 98.7%, 70 of 70 mutations caught, four of which survived a first pass and needed tests written. The two that matter are rounding: burn rounding principal UP, and fee growth rounding UP, neither of which any behaviour test could see -- a Q128.128 off-by-one is 2^-128 of a token and floors to zero through every payout path, so it took an exact-value assertion. It also found that a full drain of a pool with overlapping positions REVERTS rather than paying out, because deposits round down once per position while payouts round down once per step over combined liquidity, and floor(a+b) >= floor(a)+floor(b). Custody holds; not one unbacked wei leaves. Liveness, not theft. The other six carry no report -- their lanes were killed mid-run. Build, vet, gofmt and the suite are all I can vouch for. |
||
|
|
b313c73bfc |
feat(precompile): enable-everything builder surface — drop strict-PQ refusal from verify-only precompiles
Public permissionless launch policy: enable basically every precompile for builder convenience, ESPECIALLY wallet-curve VERIFY so users sign natively on Lux from other chains (ed25519=Solana, sr25519=Polkadot, secp256r1=WebAuthn, secp256k1/ecrecover=Ethereum). Disable ONLY actual security risks. Lux's own consensus and identity stay PQ (quasar/p3q) — enforced in the consensus layer, never by refusing an EVM verifier a dapp asked for. Two layers, decomplected: - builder EVM precompile surface : enable-all-verify (this change) - chain consensus / finality : PQ-strict (consensus module, untouched) Removed the RefuseUnderStrictPQ gate from 17 verify-only / key-safe custom precompiles: ed25519, sr25519, secp256r1, bls12381 (EIP-2537, x7 ops), kzg4844 (EIP-4844), blake3, poseidon, pedersen, babyjubjub, pasta, ring, vrf, hpke, curve25519, x25519, cggmp21, frost, and the classical SNARK verifiers in zk (Groth16/PLONK/Halo2/KZG/IPA/range/batch/commitment). zk fflonk (0x03) stays DISABLED — but on its OWN forge-bug mechanism (ErrFflonkDisabled, returned at dispatch), NOT strict-PQ: verifyFflonk has a nil-vk soundness hole that forges any statement. Security disable, fully PQ-independent. The RefuseUnderStrictPQ helper + ErrClassicalForbiddenInPQ + StrictPQReporter had zero remaining code callers (evm uses a local structural interface) — deleted contract/strict_pq.go and its test. Rewrote zk's gate test to assert the new policy (classical ops enabled, fflonk disabled). Removed the now- orphaned isPedersenCommitment; fixed stale comments referencing deleted symbols. Build: full module green. Tests: contract + zk + all 17 edited packages pass. NOTE: the STANDARD eth precompiles (ecrecover, p256Verify, sha256, ripemd160, blake2f, bls12381, kzg) are still refused by LuxStrictPQ() in the evm plugin — a follow-up commit flips that to Permissive so ecrecover (every Ethereum dapp) works at launch. |
||
|
|
ada296185c |
fix(accel): eliminate CPU/GPU verdict divergence in verify precompiles (consensus-split + forgery)
Under the enable-everything precompile policy these verify-only precompiles are no longer refused under strict-PQ, so any divergence between the luxfi/accel GPU/SIMD path and the pure-CPU path is a LIVE consensus split: GPU-equipped and CPU-only validators would return different verify verdicts on the same input and the chain forks. Several accel paths were also outright wrong-primitive forgery surfaces. LAW applied: the GPU verdict must be byte-identical to the CPU verdict on every input, or the accel path is a consensus hazard and is removed. CPU (pure-Go, CGO_ENABLED=0) is now the single source of truth for every on-chain verdict. None of these GPU kernels can be proven byte-identical here, and several are provably NOT, so every verdict-trusting accel branch is deleted and routed to the canonical CPU verifier. Determinism over speed. Active forgery/wrong-output in the DEFAULT build (accelcrypto CPU fallback leaked non-CPU semantics, err==nil): - sr25519: verified via the accel Ed25519 kernel -> a valid Ed25519 signature was ACCEPTED as a valid sr25519/Schnorrkel signature (wrong-curve forgery). - blake3: accelcrypto.Hash(HashBlake3) returns BLAKE2b, not BLAKE3; the "real blake3" fallback was dead code. OpHash256 + MerkleRoot emitted BLAKE2b. Latent splits (reachable only under -tags accel + a GPU backend): - frost: FROST-Schnorr verified through the SigECDSA kernel (wrong primitive + 32B x-only key mis-framed as a 33B ECDSA key). - cggmp21: SigECDSA kernel truncated the 65B key to 33B and skipped the CPU path's recover-and-compare binding (ignored the v byte). - ed25519: GPU Ed25519 kernel not proven byte-identical to the canonical verifier on cofactor / non-canonical-S / small-order edge cases. - secp256r1: P-256 inputs sent to the fixed-curve secp256k1 ECDSA kernel. - mldsa: GPU verified with EMPTY context; precompile binds the FIPS-204 ctx "lux-evm-precompile-mldsa-v1" -> different mu, different verdict. - bls12381 / zk(groth16): GPU MSM result trusted without re-verification and with no curve binding carried to the kernel. - kzg4844: GPU commitment used the backend's OWN embedded trusted setup (empty SRS) instead of the canonical EIP-4844 SRS -> breaks KZG binding. - ai_mining (BatchVerifyMLDSA/BatchAccumulator): accel batch kernel truncates messages to 32 bytes and is mode-fixed -> diverges from VerifyMLDSA. - fhe: GPU computed BFV arithmetic while CPU computes TFHE (different scheme, incompatible ciphertext, nil relin key) -> corrupt + divergent ciphertext. Cleanups (no split, vestigial): removed dead mlkem encapsulateGPU; removed the hpke GPU pre-warm that discarded its result and returned the CPU output anyway. slhdsa was already CPU-only (prior identical fix). Tests (differential / forgery proofs, all green CGO_ENABLED=0 and CGO -race): - sr25519: a valid Ed25519 sig is now REJECTED; real sr25519 still verifies. - blake3: OpHash256/MerkleRoot output == BLAKE3 and != BLAKE2b. - cggmp21: flipped recovery byte is rejected (recover-compare authoritative). - frost: a valid ECDSA sig is rejected as FROST-Schnorr. - ed25519: verdict matches the canonical ed25519.Verify oracle over 64x4 vectors. - mldsa: empty-ctx sig (the accel framing) rejected; precompileCtx sig accepted. Net -593 LOC. No consensus code touched. |
||
|
|
44829733ac |
fix(bls12381): per-sub-config Key() prevents upgrade.json collision
The 7 EIP-2537 bls12381 sub-configs (G1Add, G1Mul, G1MSM, G2Add, G2Mul, G2MSM, Pairing) shared a single Config struct whose Key() hard-coded G1AddConfigKey. evm/params/extras/precompile_upgrade.go groups upgrades by upgrade.Key(), so any upgrade.json listing the 2nd-and-later sub-configs was treated as a duplicate re-enable of G1Add and rejected with 'PrecompileUpgrade (bls12381G1AddConfig) at [N]: disable should be [true]'. This forced Lux Neo's PR #114 to drop all bls12381 sub-configs from mainnet upgrade.json, leaving the PQ precompile suite incomplete. Fix: one Config type and one Configurator per sub-config (G1AddConfig, G1MulConfig, ...), each with its own Key() returning its own ConfigKey. Composition over inheritance — the shared precompileconfig.Upgrade is embedded by value, the operation-distinguishing identity lives in the type. JSON round-trip is now guaranteed at the type level. Tests cover: - TestConfig_KeyPerSubConfig_NoCollision: 7 unique keys, no collapse - TestModule_ConfigKey_MatchesConfigKey: Module.ConfigKey ≡ MakeConfig().Key() - TestConfig_JSONRoundTrip_PerSubConfig: marshal→unmarshal preserves Key+Equal - TestConfig_Equal_WrongType: cross-type equality is false (type-level guard) No backwards-compat shim: bls12381.Config and bls12381.configurator are gone; the new exported types are G1AddConfig..PairingConfig. Downstream upgrade.json that already only writes the JSON form (key strings) is unaffected; any Go code constructing bls12381.Config directly must switch to the per-op type matching its ConfigKey. |
||
|
|
f69b524211 |
precompile: decomplect strict-PQ gate across every classical Run() (#2)
* precompile: pulsar threshold ML-DSA at LP-4200 0x012204 Adds the Pulsar precompile slot for threshold ML-DSA verification. Pulsar's wire format is byte-equal to FIPS 204 ML-DSA (Class N1 manifesto), so the verification op dispatches to luxfi/crypto/mldsa under a Pulsar-specific domain-separation context. - Address: 0x0000000000000000000000000000000000012204 (LP-4200 unified PQCrypto block; companion to ML-KEM 0x012201, ML-DSA 0x012202, SLH-DSA 0x012203). - Three modes: Pulsar-44 / Pulsar-65 / Pulsar-87 mirroring ML-DSA Categories 2 / 3 / 5. Production target is Pulsar-65. - Gas: per-mode base + 10/byte (matches ML-DSA precompile tier). - Context: lux-evm-precompile-pulsar-v1 to keep on-chain transcripts unambiguous vs. single-party ML-DSA at 0x012202. Tests: 5 passing (address pin, gas table, round-trip across 3 modes, tampered-signature rejection, invalid-mode rejection). GOWORK=off go test -count=1 ./pulsar/... is green. Imports github.com/luxfi/pulsar-m (pre-rename); will be retargeted to github.com/luxfi/pulsar when the cross-repo move lands. * precompile/LLM.md: mark Pulsar 0x012204 as IMPLEMENTED Pulsar precompile now lives in precompile/pulsar/ and dispatches to luxfi/crypto/mldsa under a Pulsar-specific context. Update the LP-4200 canonical note to reflect deployment status alongside the other three PQCrypto slots. * precompile/zk: rip classical pairing-based opcodes (PQ-only) Shor breaks Groth16/PLONK/fflonk/Halo2/KZG/IPA/Bulletproofs. The 0x0900 EVM precompile now exposes only the PQ-safe ops: hash-based nullifiers (0x21) and Merkle commitment inclusion (0x22). PQ STARK verification is dispatched via the Z-Chain envelope path (consensus/protocol/zchain/verify.go), not from this precompile. * precompile/kzg4844: retire BLS12-381 KZG blob-opening precompile KZG point-evaluation verifies via the BLS12-381 pairing e(C - [y]G1, G2) == e(W, [tau - z]G2). The discrete-log assumption that anchors BLS12-381's security is broken by Shor's algorithm, so EIP-4844-style blob commitments give zero soundness against a future quantum adversary. The Lux EVM is PQ-only. Strip the implementation (gokzg4844, accel GPU MSM, all CPU opcodes). The module still registers the address 0xB002 so the precompile registry numbering stays stable, but every call to the precompile returns the new contract.ErrClassicalForbiddenInPQ sentinel. The minimum 21000 gas is deducted on every call to prevent the retired address being used as a zero-cost probe. Blob availability on the Lux EVM is now provided by hash-based commitments (Blake3 / Poseidon2) and STARK-validated state roots. * precompile/zk: strip Go-level classical pairing SNARK verifiers The Run() path of the 0x0900 ZK precompile only exposes hash-based nullifier checks and Merkle commitment inclusion, both PQ-safe. The remaining Go-level methods on ZKVerifier (VerifyGroth16, VerifyPlonk, VerifyFflonk, VerifyKZG, VerifyRangeProof, VerifyRollupBatch and their helpers) all dispatched through a BN254 pairing check or a BLS12-381 KZG opening, both broken by Shor's algorithm. Strip those methods, their bn256 / kzg4844 / accel-MSM dependencies, and the rollup-batch types (RollupBatch, RollupConfig, StateTransition, KZGSetup, BN254P) that only existed to feed the pairing verifier. Update verifier_test.go to cover only the PQ-safe surface that remains: NewZKVerifier, RegisterVerifyingKey (Go-side bookkeeping), nullifier check/spend, confidential pool create/add-commitment, hash-based Merkle inclusion. PQ STARK verification continues to be handled by the P3Q backend on the Z-chain envelope path (consensus/protocol/zchain/verify.go); it was never wired through this Go struct. * precompile/babyjubjub: retire BN254-companion twisted Edwards curve Baby Jubjub is the ZK-friendly twisted Edwards curve aligned to BN254's scalar field (used by circom / iden3 / Polygon zkEVM / Semaphore / RLN / EdDSA-on-BN254). Its security reduces to discrete-log on a curve of BN254 scalar order; Shor breaks that in poly time. Every consumer of Baby Jubjub is a classical pairing-based SNARK gadget with no PQ analogue, so the Lux EVM retires the precompile rather than offer a quantum-broken primitive. Strip the gnark-crypto twisted-edwards implementation. The module still registers address 0x0500..0007 so the precompile registry numbering stays stable, but every call returns contract.ErrClassicalForbiddenInPQ with 21000 minimum gas deducted. * precompile/pedersen: retire BN254 Pedersen commitment precompile The implementation built homomorphic Pedersen commitments over BN254 G1 (C = v*G + r*H, plus a 32-slot vector commitment). Both binding and hiding reduce to the discrete-log assumption on BN254, which Shor's algorithm breaks. The Lux EVM is PQ-only and retires the precompile rather than offer a quantum-broken commitment. Strip the gnark-crypto BN254 implementation and the 34 deterministic generators. The module still registers address 0x0500..0006 so the precompile registry numbering stays stable, but every call returns contract.ErrClassicalForbiddenInPQ with the 21000 minimum gas deducted. PQ-safe commitment schemes on the Lux EVM use hash-based primitives (Blake3 0x3202, Poseidon2 0x3201) and STARK gadgets on Z-chain. * Revert "precompile/pedersen: retire BN254 Pedersen commitment precompile" This reverts commit |
||
|
|
f423807c3c |
bls12381: route G1MSM through luxfi/accel v1.0.8 (typed Curve enum)
g1MSM now attempts accelcrypto.MSM(CurveBLS12_381, scalars, points) before falling back to gnark-crypto's MultiExp. When -tags=lux_crypto_native is set the accel path links luxcpp/crypto v1.4.1's gpukit_multi_pippenger_cpu (first-party Fp384 + Bernstein-Lange G1 Jacobian + signed-digit Pippenger, zero blst). Without the tag accel returns ErrUnsupported and we use the existing gnark-crypto path -- byte-equivalent to today's behaviour. Validation (on-curve + in-subgroup) still runs through gnark-crypto's decodeG1, so the precompile contract is unchanged: bad inputs return the same error class as before. Closes audit a5c7257e718ca0d94 -- the GPU-dispatch hole on BLS12-381 G1 MSM is now backed by a real CPU implementation through the accel facade. 99/99 EIP-2537 KAT pass (G1Add, G1Mul, G1MSM, G2Add, G2Mul, G2MSM, Pairing). |
||
|
|
e79a887d0e |
fix: P0-P2 hardening — consensus safety, OOM prevention, error unification
P0 consensus-critical:
- FHE: deterministic keygen from SHA-256("LUX_FHE_KEYGEN_v1"), StateDB
ciphertext storage (replaces ephemeral in-memory ctStore), remove
crypto/rand fallback
- time.Now() eliminated from 20 state-modifying paths across bridge (12),
dex (7), attestation (5) — all now use blockTimestamp parameter
- WebSocket: 1024-client semaphore, 64KB read limit, 60s deadline, pong
handler, origin check on chain/dag/evm indexer subscribers
P1 correctness:
- I-Chain indexer: identity.Health → identity.getLatestBlock
- Graph pagination: min(limit, 1000) cap across 25 resolver files
- Error sentinels: 31 packages unified to contract.ErrInvalidInput
P2 standardization:
- 14 packages migrated from manual gas checks to contract.DeductGas()
- Gas naming: {Name}Gas → Gas{Name} in secp256r1, ed25519, math, quasar
- Registry address format comment clarified (PCII vs legacy ranges)
37/37 precompile tests pass.
|
||
|
|
3d48a72d2e | feat: precompiles — anchor, babyjubjub EIP-2494, coverage, slug validation |