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.
78 lines
4.8 KiB
Markdown
78 lines
4.8 KiB
Markdown
# Poseidon2-BabyBear width-16 constants: confirmation + conformance (task summary)
|
|
|
|
> **Scope caveat (2026-07-19 finding).** These constants are 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 over the **KoalaBear** field, so these BabyBear Poseidon2 constants are not
|
|
> SP1 6.1.0's constants, FRI and DEEP-ALI do not apply to SP1 6.1.0, and this work does not verify SP1
|
|
> 6.1.0 proofs. 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. Component (b) of the PQ STARK-verify precompile 0x0AE8.
|
|
|
|
## Outcome (headline)
|
|
|
|
- Constants: **CONFIRMED-FROM-SOURCE.**
|
|
- Conformance KAT: **PASSED** (3/3 real known-answer vectors reproduced byte-for-byte).
|
|
- Top-level 0x0AE8: **still fail-closed** (returns EMPTY for every input). DO NOT ACTIVATE banner kept.
|
|
|
|
## What the prior pass had wrong, and what was confirmed
|
|
|
|
The prior pass implemented the permutation STRUCTURE but used SHA-256 PLACEHOLDER round constants
|
|
(`AERE-PLACEHOLDER-NOT-PLONKY3`) and a textbook internal layer. Two things were confirmed/fixed:
|
|
|
|
1. The 141 round constants are now the real Plonky3 values (128 external + 13 internal), generated by
|
|
`Xoroshiro128Plus::seed_from_u64(1)` via `new_from_rng_128` and extracted from the pinned crates.
|
|
2. The internal linear layer was WRONG (a genuine bug, the "two wrong copies agree" trap). The pinned
|
|
`DiffusionMatrixBabyBear`, as a canonical map, is `M_I = R^{-1} * (J + diag(D))` with
|
|
R^{-1} = 943718400 = (2^32)^{-1} mod p, i.e. `out[i] = R_INV*(sum + D[i]*state[i])`. The prior pass
|
|
used `state[i]*D[i] + sum` (no R^{-1}), which is self-consistent but disagrees with the prover.
|
|
This is the Montgomery-form subtlety the task flagged. Verified by recovering the exact 16x16
|
|
canonical matrix from the library (off-diagonal = R^{-1}, diagonal = R^{-1}*(1+D[i])).
|
|
|
|
Also confirmed: ROUNDS_F=8, ROUNDS_P=13 (`poseidon2_round_numbers_128(16,7)`); M4 =
|
|
[[2,3,1,1],[1,2,3,1],[1,1,2,3],[3,1,1,2]] (recovered from `Poseidon2ExternalMatrixGeneral`); the
|
|
internal diagonal D = [p-2,1,2,4,...,8192,32768] (canonical). The x^7 S-box was already solid.
|
|
|
|
## Source (exact) and method
|
|
|
|
Pinned target: `p3-baby-bear` / `p3-poseidon2` crates.io `0.4.3-succinct` (checksums
|
|
`d69e6e9a...` / `52298637...`, matching `aerenew/.../Cargo.lock`). The numbers are authoritative
|
|
because the pinned crates were compiled and executed (cargo 1.97.0; the fresh build resolved the same
|
|
two checksums, byte-identical to the AERE pin). Corroborating source pages:
|
|
- https://docs.rs/crate/p3-baby-bear/0.4.3-succinct/source/src/poseidon2.rs (diagonal, RNG comment)
|
|
- https://docs.rs/crate/p3-monty-31/0.4.3-succinct/source/src/monty_31.rs (Standard sampling, new_monty)
|
|
- https://docs.rs/crate/p3-poseidon2/0.4.3-succinct/source/src/lib.rs (new_from_rng_128 order)
|
|
- https://github.com/Plonky3/Plonky3 poseidon2/src/{round_numbers.rs, external.rs}
|
|
- https://github.com/rust-random/rngs rand_xoshiro (SplitMix64 seed, next_u32 = next_u64>>32)
|
|
|
|
Full provenance + the KAT vectors: `aere-research/pq-stark/spec-poseidon2-constants.md`.
|
|
|
|
## Conformance KAT (executed from the pinned library, reproduced by all references)
|
|
|
|
- zeros [0;16] -> [1787823396, 953829438, 89382455, ...]
|
|
- iota [0..15] -> [157639285, 1851003038, 1852457045, ...]
|
|
- testvec (p3 test) -> [512585766, 975869435, 1921378527, ...]
|
|
|
|
Results: `python test_poseidon2_babybear.py` -> PASS=47017 FAIL=0 (Python/Node/Java byte-identical,
|
|
3/3 conformance KATs); `java Poseidon2BabyBearSelfTest` -> PASS=13536 FAIL=0.
|
|
|
|
## Files changed
|
|
|
|
- `aere-research/pq-stark/poseidon2_babybear_reference.py` / `.mjs`, real constants, R_INV
|
|
internal layer, conformance KATs.
|
|
- `aere-research/pq-stark/Poseidon2BabyBearSelfTest.java`, same; self-test PASS=13536.
|
|
- `aere-research/pq-stark/test_poseidon2_babybear.py`, added conformance stage; honest status.
|
|
- `aere-research/precompiles/Sp1StarkVerifierPrecompiledContract.java`, real constants, R_INV
|
|
internal layer, `Poseidon2Bb.available = true`; decoupled challenger gate
|
|
(`Challenger.spongePorted = false`) so the top level stays fail-closed.
|
|
- `aere-research/pq-stark/README.md`, `aerenew/docs/AERE-STARK-VERIFIER-PORT-SPEC.md`, real status.
|
|
- New: `aere-research/pq-stark/spec-poseidon2-constants.md` (provenance/citation doc).
|
|
|
|
## Fail-closed confirmation
|
|
|
|
`Poseidon2Bb.available = true` (permutation confirmed), but the duplex sponge is a separate un-ported
|
|
component: `Challenger.spongePorted = false` -> `checkProofOfWork` returns false and
|
|
`sampleQueryIndices` returns empty; `StarkConstraints.evaluateAtZeta` and `Fri.checkQuery` return
|
|
UNAVAILABLE. So `verify(...)` never reaches `return ACCEPT`; the precompile returns EMPTY for every
|
|
input. The DO NOT ACTIVATE banner is intact.
|