aere-docs/AERE-STARK-POSEIDON2-SUMMARY.md
Aere Network e4cead319d Initial public release
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.
2026-07-20 01:01:36 +03:00

6.4 KiB

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^2735); 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.