The published line and the local line of this repository had no common ancestor: the public one carried the hygiene pass (no host names, no internal paths), the local one carried a month of corrections that never shipped. This commit ports the local work onto the public line, keeping the public hygiene wording wherever the two touched the same sentence, and keeping the public version of AERE-CROSS-CLIENT-DETERMINISM.md entirely. Carried: LICENSE/LICENSING corrections, VERIFY-POLICY.md, CITATIONS-UNRESOLVED.md remeasured 2026-08-11, the 'audited' adjective removed from next to Bouncy Castle, citation paths rewritten to published form, AIP-8, the QA consolidation report, the second EIP validation pass, fork-height corrections, the AereSink / threshold-factory correction, the forge test floor, and the architecture-map updates.
95 lines
6.4 KiB
Markdown
95 lines
6.4 KiB
Markdown
# Poseidon2-over-BabyBear (width 16) - component (b) of the 0x0AE8 STARK-verify port
|
|
|
|
> **Scope caveat (2026-07-19 finding).** This component is conformance-confirmed against Plonky3
|
|
> `0.4.3-succinct` (Aere's OWN BabyBear + FRI STARK stack), NOT against SP1 6.1.0. SP1 6.1.0 is a
|
|
> **Hypercube** release (KoalaBear multilinear: BaseFold + Jagged + sumcheck-zerocheck + LogUp-GKR),
|
|
> so FRI and DEEP-ALI do not apply to it and this skeleton does not verify SP1 6.1.0 proofs. (Only the
|
|
> Poseidon2 sponge SHAPE carries over to SP1's Hypercube stack, and even that needs the KoalaBear
|
|
> field and KoalaBear Poseidon2 constants.) Replacing the SP1 BN254 Groth16 wrap is a separate
|
|
> ~22 to 32 person-week retarget. See `AERE-STARK-SP1-RECURSION-AIR-PORT-SPEC-SUMMARY.md`.
|
|
|
|
Date: 2026-07-19. Status: STRUCTURE implemented + self-consistency TESTED; CONFORMANCE to Plonky3 is
|
|
[VERIFY] (no KAT run). Top-level 0x0AE8 verifier UNCHANGED and still fail-closed.
|
|
|
|
## What was implemented
|
|
|
|
The Poseidon2 permutation over BabyBear (p = 2^31 - 2^27 + 1) at the standard SP1/Plonky3 width 16:
|
|
|
|
- S-box x^7 (BabyBear: 7 is the smallest d>1 with gcd(d, p-1)=1, so it is a bijection on F_p).
|
|
- 8 external (full) rounds: 4 initial + 4 terminal, S-box on all 16 lanes, then the MDS-light
|
|
external layer M_E built from M4 = [[2,3,1,1],[1,2,3,1],[1,1,2,3],[3,1,1,2]] (block matrix with
|
|
diagonal blocks 2*M4, off-diagonal blocks M4; the two-step "apply M4 per block, add col sums" form).
|
|
- 13 internal (partial) rounds: S-box on lane 0 only, then M_I = J + diag(D) applied as
|
|
state[i] = state[i]*D[i] + sum(state), D = INTERNAL_DIAG_M1_16.
|
|
- Round-constant schedule: 128 external (add to all 16 lanes) + 13 internal (add to lane 0) = 141.
|
|
- A `compress2to1` truncated-permutation 2-to-1 compression for the Merkle layer (shape [VERIFY]).
|
|
|
|
Files (mirrors the field sub-component's Python + Node + standalone-Java + precompile convention):
|
|
- `aere-research/precompiles/Sp1StarkVerifierPrecompiledContract.java` - `Poseidon2Bb.permute`
|
|
implemented; `Poseidon2Bb.available` STAYS false (gates everything above it).
|
|
- `aere-research/pq-stark/poseidon2_babybear_reference.py` (Python reference).
|
|
- `aere-research/pq-stark/poseidon2_babybear_reference.mjs` (Node reference).
|
|
- `aere-research/pq-stark/Poseidon2BabyBearSelfTest.java` (standalone Java, no Besu classpath).
|
|
- `aere-research/pq-stark/test_poseidon2_babybear.py` (harness).
|
|
- `aere-research/results/kat-results-poseidon2-babybear.json` (machine-readable result).
|
|
- Docs updated: `aerenew/docs/AERE-STARK-VERIFIER-PORT-SPEC.md` (intro, section 3, section 9 table,
|
|
section 10 files) and `aere-research/pq-stark/README.md`.
|
|
|
|
## Self-consistency result (REAL, ran 2026-07-19)
|
|
|
|
`python test_poseidon2_babybear.py` -> PASS=47014 FAIL=0. Standalone `java Poseidon2BabyBearSelfTest`
|
|
-> PASS=13533 FAIL=0. Additionally the precompile's exact `Poseidon2Bb.permute` bytes were compiled
|
|
in a throwaway and matched the references on all 13 shared states.
|
|
|
|
Proven offline (genuine, and it IS self-consistency, not conformance):
|
|
- x^7 bijection: 7 CONFIRMED as the minimal coprime degree (p-1 = 2^27*3*5); monomial inverse
|
|
round-trips on 20k random x; S-box equals an independent bignum pow(x,7,p).
|
|
- Determinism + genuine BIJECTION: an explicit inverse permutation round-trips on the fixed set +
|
|
3000 random states; 0 output collisions on the sample.
|
|
- MDS / invertibility: M4 is MDS (all 69 square submatrices nonsingular); external and internal
|
|
layers equal their explicit 16x16 matrices; both matrices are invertible over F_p.
|
|
- Cross-language: Python, Node, and standalone Java produce BYTE-IDENTICAL permutation outputs on a
|
|
shared 13-state input set (all-zero, [0..15], all-(p-1), structured, and LCG-random states).
|
|
|
|
## Conformance = [VERIFY] (NOT tested; no KAT claimed)
|
|
|
|
This is the whole risk of Poseidon2 (the "two wrong copies agree" trap): a structurally-correct
|
|
permutation with the WRONG constants is self-consistent and cross-language identical yet silently
|
|
disagrees with the real prover. The constants here are NOT confirmed to be Plonky3's:
|
|
|
|
- The 141 round constants are DETERMINISTIC PLACEHOLDERS (SHA-256 of a labelled counter,
|
|
"AERE-PLACEHOLDER-NOT-PLONKY3|..."), cross-language reproducible but NOT Plonky3's. Plonky3
|
|
generates them from Xoroshiro128Plus::seed_from_u64(1) via new_from_rng_128.
|
|
- INTERNAL_DIAG_M1_16 = [p-2, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 32768]
|
|
is a CANDIDATE observed via a lossy docs.rs summary of p3-baby-bear's
|
|
POSEIDON2_INTERNAL_MATRIX_DIAG_16_BABYBEAR_MONTY. May be Montgomery-form; transcription unconfirmed;
|
|
not checksum-verified.
|
|
- ROUNDS_F=8, ROUNDS_P=13 are the commonly-cited counts; ROUNDS_P is [VERIFY]
|
|
(Plonky3 poseidon2_round_numbers_128(16, 7)).
|
|
- M4 and the MDS-light M_E construction are the Poseidon2-paper standard; byte identity vs
|
|
p3-poseidon2 is [VERIFY].
|
|
|
|
Pinned conformance target (found in the repo's Cargo.lock, not vendored as source): Plonky3
|
|
`p3-poseidon2` and `p3-baby-bear` at crates.io `0.4.3-succinct` (checksums
|
|
522986377b2164c5f94f2dae88e0e0a3d169cc6239202ef4aeb4322d60feffd0 and
|
|
d69e6e9af4eaaaa60f7bb9f0e0f73ebcbaefe7e00974d97ad0fa542d6a4f0890).
|
|
|
|
[VERIFY: confirm the p3-poseidon2 BabyBear width-16 round constants + internal diagonal + round
|
|
counts against SP1 v6.1.0 (Plonky3 0.4.3-succinct), regenerate the round constants from the pinned
|
|
RNG, replace the placeholders, then run the real KAT (all-zero state, [0,1,...,15]) against
|
|
p3-baby-bear's test_poseidon2_babybear output and report PASS/FAIL.]
|
|
|
|
## Top-level stays fail-closed
|
|
|
|
`Poseidon2Bb.available = false` (constants are [VERIFY], so it is NOT flipped). With it false, the
|
|
Challenger PoW check returns false, sampleQueryIndices returns empty, StarkConstraints.evaluateAtZeta
|
|
returns UNAVAILABLE, and Fri.checkQuery returns UNAVAILABLE. `Sp1StarkVerifierPrecompiledContract.verify`
|
|
therefore returns UNAVAILABLE and `computePrecompile` returns EMPTY (0x) for every input. The single
|
|
`return VerifyResult.ACCEPT` line is unreachable. The "DO NOT ACTIVATE ON MAINNET / verifies nothing"
|
|
banner is unchanged. On-chain ZK verifiers remain the classical BN254 Groth16 gateway. The multi-week
|
|
port continues: components (c) Merkle/MMCS, the rest of (d) FRI, (e) AIR, (f) transcript are un-ported,
|
|
and Poseidon2's own conformance is the flagged open item.
|
|
|
|
Sub-component tally: 3 of 6 components now have implemented+tested pieces (a field COMPLETE, b
|
|
Poseidon2 structure with [VERIFY] conformance, one constant-free slice of d). None makes 0x0AE8 accept.
|