Aere Network public source. Everything here can be checked against the live chain (chain id 2800, https://rpc.aere.network). Scope note, stated up front rather than buried: consensus on chain 2800 is classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at the signature, precompile, account and transport layers. Nothing here makes the consensus post-quantum, and no document in it should be read as claiming so.
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):
|
|
- `aerenew/pqc-fork/precompiles/Sp1StarkVerifierPrecompiledContract.java` - `Poseidon2Bb.permute`
|
|
implemented; `Poseidon2Bb.available` STAYS false (gates everything above it).
|
|
- `aerenew/pqc-fork/pq-stark/poseidon2_babybear_reference.py` (Python reference).
|
|
- `aerenew/pqc-fork/pq-stark/poseidon2_babybear_reference.mjs` (Node reference).
|
|
- `aerenew/pqc-fork/pq-stark/Poseidon2BabyBearSelfTest.java` (standalone Java, no Besu classpath).
|
|
- `aerenew/pqc-fork/pq-stark/test_poseidon2_babybear.py` (harness).
|
|
- `aerenew/pqc-fork/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 `aerenew/pqc-fork/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.
|