|
| 1 | +Status: PASS |
| 2 | +Reviewed-Commit: a79db380f848eccb1edf62f1d712b74685910d5d |
| 3 | +Tester: External pentest and maintainer retest |
| 4 | +Scope: eth v0.50.9 BN254 projective post-loop line carrier, optimal-ate Miller-loop scalar table, Q1/-Q2 post-loop line multiplication, fail-closed EIP-197 pairing boundary, fuzz reachability, documentation, and package metadata. |
| 5 | +Date: 2026-07-09 |
| 6 | + |
| 7 | +# eth v0.50.9 Pentest Report |
| 8 | + |
| 9 | +## Summary |
| 10 | + |
| 11 | +The v0.50.9 release was reviewed after adding the first-party BN254 projective |
| 12 | +post-loop line carrier required before non-empty EIP-197 pairing results can be |
| 13 | +admitted. The review covered the projective line-function path, sparse Fp12 |
| 14 | +line multiplication, Q1 and -Q2 post-loop line additions, the fail-closed |
| 15 | +pairing boundary, regression coverage, documentation, release metadata, and |
| 16 | +package boundaries. |
| 17 | + |
| 18 | +The initial review found one Critical correctness issue: the hard-coded BN254 |
| 19 | +`6u+2` non-adjacent-form table encoded the wrong scalar. This did not affect |
| 20 | +public execution in v0.50.9 because non-empty pairing inputs still return |
| 21 | +`PrecompileBackendUnavailable`, but it would have made the planned |
| 22 | +result-admission release unsafe. The review also identified the related test |
| 23 | +design gap: the new Miller-loop tests were self-consistency checks and could |
| 24 | +not catch a wrong scalar table. |
| 25 | + |
| 26 | +Both issues were fixed before this report was committed. Retest passed. |
| 27 | + |
| 28 | +Non-empty BN254 pairing execution remains fail-closed with |
| 29 | +`PrecompileBackendUnavailable`; this release does not claim public non-empty |
| 30 | +EIP-197 pairing success or failure words. |
| 31 | + |
| 32 | +## Findings |
| 33 | + |
| 34 | +### F-01 - Wrong BN254 loop constant breaks pairing bilinearity |
| 35 | + |
| 36 | +Severity: Critical |
| 37 | + |
| 38 | +Result: Fixed. |
| 39 | + |
| 40 | +`BN254_SIX_U_PLUS_2_NAF` was intended to encode `6u+2` for the BN254 |
| 41 | +optimal-ate parameter `u = 4965661367192848881`, but the table reconstructed to |
| 42 | +a different scalar. The pentest demonstrated the failure with the bilinearity |
| 43 | +identity `e([2]P, Q) == e(P, Q)^2`, using the existing BN254 add precompile |
| 44 | +path to construct `[2]P`. |
| 45 | + |
| 46 | +The remediation replaced the table with an independently derived NAF for: |
| 47 | + |
| 48 | +```text |
| 49 | +6 * 4965661367192848881 + 2 = 29793968203157093288 |
| 50 | +``` |
| 51 | + |
| 52 | +Two permanent regressions now cover this failure class: |
| 53 | + |
| 54 | +- `miller_loop_naf_reconstructs_six_u_plus_two` reconstructs the scalar from |
| 55 | + the hard-coded NAF table. |
| 56 | +- `miller_loop_is_bilinear_over_g1_double` checks |
| 57 | + `e([2]P, Q) == e(P, Q)^2` after final exponentiation. |
| 58 | + |
| 59 | +### F-02 - Regression suite relied on self-consistency only |
| 60 | + |
| 61 | +Severity: Process |
| 62 | + |
| 63 | +Result: Fixed. |
| 64 | + |
| 65 | +The original v0.50.9 tests checked determinism, repeated tuple multiplication, |
| 66 | +and generator-plus-negated-generator neutrality. Those properties can hold even |
| 67 | +when a Miller loop uses the wrong scalar, so they were insufficient for |
| 68 | +admitting more pairing algebra. |
| 69 | + |
| 70 | +The bilinearity regression now checks the accumulator against an independently |
| 71 | +constructed group element. The release notes and BN254 economics document also |
| 72 | +record that future result-admission work must include official EIP-197 |
| 73 | +positive/negative vectors and independent differential vectors before any |
| 74 | +non-empty public result is admitted. |
| 75 | + |
| 76 | +## Verified Clean |
| 77 | + |
| 78 | +- The corrected NAF table reconstructs exactly to `6u+2`. |
| 79 | +- The G1-doubling bilinearity regression passes. |
| 80 | +- The generator tuple still does not map to one after final exponentiation. |
| 81 | +- The generator plus negated-generator batch still maps to one after final |
| 82 | + exponentiation. |
| 83 | +- The projective line carrier, Q1/-Q2 post-loop additions, and sparse Fp12 |
| 84 | + multiplication remain internal behind the fail-closed EIP-197 boundary. |
| 85 | +- Non-empty pairing execution still returns `PrecompileBackendUnavailable`. |
| 86 | +- No default crypto, allocator, bigint, or pairing backend dependency was |
| 87 | + added. |
| 88 | +- README files, release notes, crate version matrix, release plan, release |
| 89 | + gate, and package metadata are aligned for v0.50.9. |
| 90 | +- The temporary root `PENTEST.md` file was removed before release |
| 91 | + finalization. |
| 92 | + |
| 93 | +## Verification |
| 94 | + |
| 95 | +- `cargo test -p eth-valkyoth-evm-core bn254` |
| 96 | +- `cargo clippy -p eth-valkyoth-evm-core --all-targets --all-features -- -D warnings` |
| 97 | +- `cargo clippy --manifest-path fuzz/Cargo.toml --bin bn254_pairing_frame -- -D warnings` |
| 98 | +- `cargo fmt --all --check` |
| 99 | +- `scripts/validate-release-metadata.sh` |
| 100 | +- `python3 scripts/test-release-metadata.py` |
| 101 | +- `scripts/release_crates.py --check` |
| 102 | +- `scripts/checks.sh` |
| 103 | + |
| 104 | +## Decision |
| 105 | + |
| 106 | +The v0.50.9 release candidate is accepted. Tagging must wait for GitHub CI and |
| 107 | +CodeQL to pass on the final report commit. |
0 commit comments