aere-research/pq-stark/test_poseidon2_babybear.py
Aere Network 6cb0140fae Republished from a clean root: the compiled artifact is gone from history, and the local line of work joins the sanitized public line
The public history carried kat/__pycache__/mlkem768_reference.cpython-314.pyc,
a compiled Python artifact embedding the operator's absolute local path. Text
secret scanners do not read compiled binaries, which is exactly how it slipped
through, and removing it from the tip would have left it reachable through the
old root commits. So this repository is republished from a single clean root.

This root also carries, from the previously unpublished line of work:
- corrected LICENSE year, LICENSING.md, VERIFY-POLICY.md, and
  CITATIONS-UNRESOLVED.md remeasured 2026-08-11 (101 paths, README aligned)
- O-018: run_consensus_verification.py ran 19 of 29 models and reported PASS;
  it now runs all 29, and computemarket_smt.py gains resolveByTimeout /
  reclaimUnsettled cases plus a negative control
- O-006: the word 'audited' removed from next to Bouncy Castle, twice, after a
  concurrent edit resurrected it
- O-014: prior art named and dated - Algorand's native falcon_verify shipped
  about ten months before AERE's precompiles; the primacy claim is withdrawn
  where it was implied
- bench/ scripts parametrized so they actually run for an outsider (the
  earlier textual sanitization left $STAGING unexpanded inside Python strings)
- AIP-2/AIP-3 errata with measured figures, spec remeasurements at 2026-08-01,
  and the spec-zk-stack retractions (owner is an operational key, not the
  Foundation; 'maximally sound' withdrawn; aggregator V1 deprecated)
The redacted bench-host environment files from the sanitized line are kept
exactly as published; the unredacted local variants are not carried.
2026-08-15 13:52:14 +03:00

313 lines
15 KiB
Python

#!/usr/bin/env python3
# Test harness for the Poseidon2-over-BabyBear width-16 permutation sub-component (port spec section
# 3, component (b)). Runs:
# 1. S-box structure: 7 is the smallest d>1 with gcd(d, p-1)=1 (so x^7 is a bijection on F_p); the
# monomial inverse round-trips over many random cases,
# 2. determinism: permute(s) == permute(s),
# 3. bijection: permute_inverse(permute(s)) == s over the fixed set + many random states (a genuine
# permutation on F_p^16), and no output collisions on a large sampled input set,
# 4. linear-layer / MDS structure: the external layer equals its explicit 16x16 matrix and that
# matrix is invertible; M4 is MDS (every square submatrix nonsingular); the internal layer equals
# R^{-1}*(J + diag(D)) and is invertible,
# 5. cross-language agreement: Python vs Node vs Java produce byte-identical permutation outputs on a
# shared input set (three independent implementations of the SAME permutation),
# 6. CONFORMANCE: the permutation reproduces real known-answer vectors (zeros / iota / testvec)
# emitted by executing the pinned p3-baby-bear / p3-poseidon2 0.4.3-succinct crates.
# Writes ../results/kat-results-poseidon2-babybear.json and exits non-zero on any failure.
#
# ============================ HONEST SCOPE (CONFIRMED 2026-07-19) ============================
# This validates the permutation LOGIC/arithmetic AND conformance to Plonky3. The port spec warned of
# the "two wrong copies agree" trap (a structurally-correct permutation with wrong constants is
# self-consistent yet disagrees with the prover). That trap is now closed: the constants + structure
# reproduce real known-answer vectors extracted from the exact pinned crates (checksums matched).
# - The 141 round constants are CONFIRMED (Xoroshiro128Plus::seed_from_u64(1) via new_from_rng_128).
# - The internal layer is CONFIRMED as R^{-1}*(J + diag(D)), R^{-1} = 943718400 (the Montgomery-form
# artifact recovered from the pinned library's exact 16x16 canonical matrix; the prior textbook
# state[i]*D[i] + sum was self-consistent but WRONG, exactly the two-wrong-copies trap).
# - ROUNDS_F=8, ROUNDS_P=13, M4, and the S-box degree are CONFIRMED.
# What is still NOT validated: the FULL STARK verifier. The duplex-sponge challenger, FRI folding,
# MMCS/Merkle openings, and the SP1 recursion-AIR are un-ported, so the top-level 0x0AE8 precompile
# stays fail-closed (returns EMPTY for every input) regardless of this component being confirmed.
import json
import os
import random
import subprocess
import sys
from shutil import which
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import poseidon2_babybear_reference as R # noqa: E402
RESULTS = os.path.normpath(os.path.join(HERE, "..", "results", "kat-results-poseidon2-babybear.json"))
_pass = 0
_fail = 0
_notes = []
def check(name, cond):
global _pass, _fail
if cond:
_pass += 1
else:
_fail += 1
print(f"FAIL {name}")
# ---- 1. S-box structure -----------------------------------------------------------------------------
def sbox_structure():
p = R.P
from math import gcd
# 7 is the smallest d>1 with gcd(d, p-1)=1 (p-1 = 2^27*3*5, so 2,3,4,5,6 all share a factor)
check("sbox.deg.is7", R.SBOX_DEGREE == 7)
for d in range(2, 7):
check(f"sbox.deg.notcoprime.d{d}", gcd(d, p - 1) != 1)
check("sbox.deg7.coprime", gcd(7, p - 1) == 1)
_notes.append("S-box x^7 CONFIRMED: 7 is the smallest d>1 with gcd(d, p-1)=1 (p-1 = 2^27*3*5), "
"so x^7 is a bijection on F_p")
rnd = random.Random(0xC0FFEE)
for _ in range(20000):
x = rnd.randrange(p)
check("sbox.roundtrip", R.sbox_mono_inv(R.sbox_mono(x)) == x)
check("sbox.value", R.sbox_mono(x) == pow(x, 7, p)) # x^7 vs an independent bignum power
# ---- 2/3. determinism + bijection + collision-freeness ----------------------------------------------
def permutation_bijection():
rnd = random.Random(0xBEEF01)
seen = {}
collisions = 0
for _ in range(3000):
st = [rnd.randrange(R.P) for _ in range(R.WIDTH)]
out = R.permute(st)
check("permute.deterministic", R.permute(st) == out)
check("permute.bijection", R.permute_inverse(out) == [x % R.P for x in st])
key = tuple(out)
if key in seen and seen[key] != tuple(st):
collisions += 1
seen[key] = tuple(st)
check("permute.no.collisions", collisions == 0)
_notes.append(f"permutation is a bijection: inverse round-trips on 3000 random states + fixed set; "
f"{len(seen)} distinct outputs, {collisions} collisions")
# ---- 4. linear-layer / MDS structure ----------------------------------------------------------------
def _minor_det(m, rows, cols):
"""Determinant mod p of the submatrix on the given rows/cols, via Gaussian elimination."""
n = len(rows)
a = [[m[r][c] % R.P for c in cols] for r in rows]
det = 1
for col in range(n):
piv = next((r for r in range(col, n) if a[r][col] % R.P != 0), None)
if piv is None:
return 0
if piv != col:
a[col], a[piv] = a[piv], a[col]
det = (-det) % R.P
det = (det * a[col][col]) % R.P
invp = pow(a[col][col], -1, R.P)
a[col] = [(x * invp) % R.P for x in a[col]]
for r in range(col + 1, n):
if a[r][col] % R.P != 0:
f = a[r][col]
a[r] = [(a[r][k] - f * a[col][k]) % R.P for k in range(n)]
return det
def _is_mds(m, size):
"""A matrix is MDS iff every square submatrix is nonsingular. Feasible for the 4x4 M4."""
from itertools import combinations
for k in range(1, size + 1):
for rows in combinations(range(size), k):
for cols in combinations(range(size), k):
if _minor_det(m, rows, cols) == 0:
return False
return True
def linear_layers():
rnd = random.Random(0xD00D)
ext = R.external_matrix()
inte = R.internal_matrix()
# layers equal their explicit matrices
for _ in range(500):
v = [rnd.randrange(R.P) for _ in range(R.WIDTH)]
check("ext.layer.eq.matrix", R.external_layer(v) == R.mat_vec(ext, v))
check("int.layer.eq.matrix", R.internal_layer(v) == R.mat_vec(inte, v))
# invertibility (necessary for the permutation to be a bijection)
ext_inv = R.mat_inverse(ext)
int_inv = R.mat_inverse(inte)
ident = [[1 if i == j else 0 for j in range(R.WIDTH)] for i in range(R.WIDTH)]
prod_ext = [[sum(ext[i][k] * ext_inv[k][j] for k in range(R.WIDTH)) % R.P for j in range(R.WIDTH)]
for i in range(R.WIDTH)]
check("ext.matrix.invertible", prod_ext == ident)
prod_int = [[sum(inte[i][k] * int_inv[k][j] for k in range(R.WIDTH)) % R.P for j in range(R.WIDTH)]
for i in range(R.WIDTH)]
check("int.matrix.invertible", prod_int == ident)
# M4 is MDS (every square submatrix nonsingular); M_E MDS then follows from the Poseidon2 construction
m4 = R.M4
check("m4.is.mds", _is_mds(m4, 4))
_notes.append("M4 is MDS (all 69 square submatrices nonsingular); external layer M_E and internal "
"layer M_I = R^{-1}*(J + diag(D)) are invertible over F_p (both CONFIRMED vs p3)")
# ---- 6. CONFORMANCE: reproduce the pinned-library known-answer vectors ------------------------------
def conformance():
passed, total = R.conformance_kats()
for kat in R.CONFORMANCE_KATS:
check(f"conformance.{kat['name']}", R.permute(list(kat["in"])) == kat["out"])
_notes.append(f"CONFORMANCE: {passed}/{total} known-answer vectors from p3-baby-bear/p3-poseidon2 "
f"0.4.3-succinct reproduced exactly (zeros, iota [0..15], testvec)")
# ---- 5. cross-language agreement (Python vs Node vs Java) -------------------------------------------
def canonicalize(v):
def ia(x):
return [int(e) for e in x]
return {
"constants": {k: (ia(x) if isinstance(x, list) else int(x)) for k, x in v["constants"].items()},
"permute": [(ia(r["in"]), ia(r["out"]), bool(r["roundtrip"])) for r in v["permute"]],
"conformanceKats": [(k["name"], ia(k["in"]), ia(k["out"]), bool(k["match"]))
for k in v.get("conformanceKats", [])],
}
def cross_language():
py = canonicalize(R.shared_vectors())
# every Python-side round-trip must be true (self-check before comparing languages)
check("py.all.roundtrip", all(r[2] for r in py["permute"]))
langs = {"python": py}
node = which("node")
if node:
try:
out = subprocess.run(
[node, os.path.join(HERE, "poseidon2_babybear_reference.mjs")],
capture_output=True, text=True, timeout=180, check=True,
).stdout.strip()
langs["node"] = canonicalize(json.loads(out))
except Exception as e: # noqa: BLE001
_notes.append(f"node cross-check unavailable: {e}")
else:
_notes.append("node not found on PATH; node cross-check skipped")
javac = which("javac")
java = which("java")
if javac and java:
try:
subprocess.run(
[javac, "-d", os.path.join(HERE, "out"),
os.path.join(HERE, "Poseidon2BabyBearSelfTest.java")],
capture_output=True, text=True, timeout=180, check=True,
)
out = subprocess.run(
[java, "-cp", os.path.join(HERE, "out"), "Poseidon2BabyBearSelfTest", "--emit"],
capture_output=True, text=True, timeout=120, check=True,
).stdout.strip()
langs["java"] = canonicalize(json.loads(out))
except Exception as e: # noqa: BLE001
_notes.append(f"java cross-check unavailable: {e}")
else:
_notes.append("javac/java not found on PATH; java cross-check skipped")
for name, data in langs.items():
if name == "python":
continue
check(f"crosslang.{name}.agree", data == py)
_notes.append("cross-language implementations compared: " + ", ".join(sorted(langs)))
return sorted(langs)
def main():
sbox_structure()
permutation_bijection()
linear_layers()
conformance()
langs = cross_language()
report = {
"component": "Poseidon2 permutation over BabyBear, width 16 (port spec component (b))",
"precompile": "0x0000000000000000000000000000000000000ae8",
"scope": "port spec section 3; the hash Plonky3/SP1 uses for Merkle/MMCS compression and the "
"Fiat-Shamir duplex challenger",
"validates": "SELF-CONSISTENCY + CONFORMANCE: x^7 is a bijection (7 = smallest coprime degree, "
"proven); the permutation is deterministic and a genuine bijection (inverse "
"round-trip, no collisions); M4 is MDS and the external/internal linear layers "
"are invertible; Python/Node/Java produce byte-identical outputs; AND the "
"permutation reproduces real known-answer vectors from the pinned p3-baby-bear / "
"p3-poseidon2 0.4.3-succinct crates (the 'two wrong copies agree' trap is closed).",
"does_not_validate": "the FULL STARK verifier. Only component (b) (the Poseidon2 permutation) is "
"confirmed. The duplex-sponge challenger, FRI folding/consistency, "
"MMCS/Merkle openings, and the SP1 recursion-AIR are un-ported.",
"top_level_verifier": "unchanged, still fail-closed (returns EMPTY for every input). "
"Poseidon2Bb.available is now true (the permutation is confirmed), but the "
"challenger/FRI/AIR are still un-ported (Challenger.spongePorted=false, "
"StarkConstraints=UNAVAILABLE), so the top level still returns EMPTY.",
"constants": {
"P": R.P,
"r_inv": R.R_INV,
"width": R.WIDTH,
"sbox_degree": R.SBOX_DEGREE,
"rounds_f": R.ROUNDS_F,
"rounds_p": R.ROUNDS_P,
"internal_diag_m1_16": R.INTERNAL_DIAG_M1_16,
"internal_layer_form": "M_I = R_INV * (J + diag(D)), R_INV = 943718400 (Montgomery artifact)",
"m4": [R.M4[r][c] for r in range(4) for c in range(4)],
"round_constants": "141 CONFIRMED constants (128 external + 13 internal) from "
"Xoroshiro128Plus::seed_from_u64(1) via new_from_rng_128",
},
"cross_language": langs,
"conformance": {
"status": "CONFIRMED (real known-answer test PASSED)",
"method": "the exact pinned crates were executed via cargo (lockfile checksums matched) to "
"emit constants + 3 permutation vectors; this reference reproduces all 3 exactly",
"vectors": [k["name"] for k in R.CONFORMANCE_KATS],
},
"pinned_conformance_target": {
"revision": "Succinct Plonky3 fork, crates.io version 0.4.3-succinct",
"p3_poseidon2_checksum": "522986377b2164c5f94f2dae88e0e0a3d169cc6239202ef4aeb4322d60feffd0",
"p3_baby_bear_checksum": "d69e6e9af4eaaaa60f7bb9f0e0f73ebcbaefe7e00974d97ad0fa542d6a4f0890",
"found_in": "aerenew/zk-circuits/*/Cargo.lock and aerenew/rollup-evm-validity/*/Cargo.lock",
},
"confirmed": [
"CONFIRMED round constants: 128 external + 13 internal from seed_from_u64(1) / new_from_rng_128",
"CONFIRMED ROUNDS_F=8, ROUNDS_P=13 (poseidon2_round_numbers_128(16, 7))",
"CONFIRMED M4 = [[2,3,1,1],[1,2,3,1],[1,1,2,3],[3,1,1,2]] (recovered from Poseidon2ExternalMatrixGeneral)",
"CONFIRMED INTERNAL_DIAG_M1_16 (canonical) and the R^{-1}*(J+diag(D)) internal-layer form "
"(Montgomery artifact, recovered exactly from DiffusionMatrixBabyBear's 16x16 canonical matrix)",
"CONFORMANCE KAT PASSED against p3-baby-bear / p3-poseidon2 0.4.3-succinct (checksums matched)",
],
"flags": [
"[VERIFY] the SP1 v6.1.0 Merkle/MMCS compression convention (padding/rate, which 8 lanes) "
"for compress2to1 (component (c)) is not yet pinned",
],
"notes": _notes,
"passed": _pass,
"failed": _fail,
"total": _pass + _fail,
}
os.makedirs(os.path.dirname(RESULTS), exist_ok=True)
with open(RESULTS, "w") as f:
json.dump(report, f, indent=2)
print("\n=== Poseidon2-BabyBear (width 16) KAT ===")
print(f"cross-language: {', '.join(langs)}")
for nnote in _notes:
print(f"note: {nnote}")
print(f"PASS={_pass} FAIL={_fail} TOTAL={_pass + _fail}")
print(f"results -> {RESULTS}")
print("CONFORMANCE to Plonky3 constants: CONFIRMED (real KAT PASSED vs p3-* 0.4.3-succinct; "
"checksums matched)")
if _fail != 0:
print("POSEIDON2_BABYBEAR_KAT_FAILED")
sys.exit(1)
print("POSEIDON2_BABYBEAR_CONFORMANCE_OK")
if __name__ == "__main__":
main()