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.
98 lines
6.3 KiB
Markdown
98 lines
6.3 KiB
Markdown
# STARK-verify port 0x0AE8, component (c): MMCS (FieldMerkleTreeMmcs) - IMPLEMENTED + CONFORMANCE-CONFIRMED
|
|
|
|
> **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. 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: real known-answer test PASSES. Top-level precompile stays fail-closed.
|
|
|
|
## What was done
|
|
|
|
Implemented and conformance-confirmed component (c) of the SP1/Plonky3 inner STARK-verify port: the
|
|
Mixed Matrix Commitment Scheme (MMCS), i.e. Plonky3's `FieldMerkleTreeMmcs`, the Merkle-tree vector
|
|
commitment that FRI (d) and the trace commitment are built on. Same rigorous ground-truth method that
|
|
worked for Poseidon2: compiled and executed the exact pinned Plonky3 crates to emit authoritative
|
|
reference vectors, then reproduced them byte-for-byte.
|
|
|
|
### 1. Confirmed the exact construction from the pinned crates
|
|
|
|
Read the source of the pinned `0.4.3-succinct` crates (checksums matched the repo Cargo.lock):
|
|
`p3-merkle-tree` (d5703d92...), `p3-symmetric` (9047ce85...), `p3-commit` (50acacc7...),
|
|
`p3-matrix` (75c3f150...). The SP1 inner config is pinned VERBATIM in `p3-merkle-tree`'s own
|
|
`mmcs.rs` tests:
|
|
- leaf hasher = `PaddingFreeSponge<Perm, WIDTH=16, RATE=8, OUT=8>` (overwrite-mode, padding-free)
|
|
- 2-to-1 compr. = `TruncatedPermutation<Perm, N=2, CHUNK=8, WIDTH=16>` (permute(l||r)[0..8])
|
|
- MMCS = `FieldMerkleTreeMmcs<Packing, Packing, MyHash, MyCompress, DIGEST_ELEMS=8>`
|
|
So a digest = 8 BabyBear elements (32 bytes). Leaf hash / node compression run on the CONFIRMED
|
|
Poseidon2-BabyBear permutation (component (b)). Traced the tree build (`first_digest_layer` /
|
|
`compress_and_inject`), `open_batch`, and `verify_batch` from source; documented the mixed-height rule
|
|
(tallest-first, power-of-two padding with the zero digest, injection at the matching padded layer,
|
|
index reduced by `index >> (log_max_height - log2_ceil(height))`) and the height property that makes
|
|
the tree-build and verify grouping select the same set.
|
|
|
|
### 2. Ground-truth extractor (Rust, scratch dir only)
|
|
|
|
Wrote `mmcs-extractor` depending on the pinned crates, built the exact `MyMmcs`, and used the SAME
|
|
deterministic permutation as the Poseidon2 confirmation (`new_from_rng_128(seed_from_u64(1))`). It
|
|
commits to six known matrix batches and emits the root + an `open_batch` opening (opened rows + sibling
|
|
path) for each, printing every field element as canonical u32, and asserts the library's OWN
|
|
`verify_batch` accepts each. Its `permute([0;16])` equals the confirmed Poseidon2 "zeros" vector, so
|
|
the extractor's permutation is byte-identical to the reference's (guards the "two wrong copies" trap).
|
|
Ran on this box; all six library `verify_batch` calls returned Ok.
|
|
|
|
The six cases exercise: single power-of-two height (8x2), single non-power-of-two height (6x2, padded,
|
|
zero-digest padding), a column vector (8x1), and three mixed-height batches (8x2+4x3, 8x1+4x2+2x2,
|
|
5x2+3x1). One case (mixed_5x2_3x1) has a default (all-zero) sibling digest in its proof.
|
|
|
|
### 3. References + precompile wiring (matching the existing convention)
|
|
|
|
- `pqc-fork/pq-stark/mmcs_babybear_reference.py` (Python), `.mjs` (Node), `MmcsBabyBearSelfTest.java`
|
|
(standalone Java): hash_iter (PaddingFreeSponge), compress2to1 (TruncatedPermutation), full
|
|
mixed-height tree build + commit + open_batch + verify_batch, over the confirmed Poseidon2.
|
|
- `pqc-fork/precompiles/Sp1StarkVerifierPrecompiledContract.java`: new `Mmcs` static class
|
|
(`hashIter`, `compress2to1`, mixed-height `verifyBatch`) wired behind the still-fail-closed top level;
|
|
`Mmcs.available = true`. Referenced from `Fri.checkQuery` (still returns UNAVAILABLE). Compiles clean.
|
|
- `pqc-fork/pq-stark/test_mmcs_babybear.py` harness + `../results/kat-results-mmcs-babybear.json`.
|
|
- `pqc-fork/pq-stark/spec-mmcs-babybear.md` provenance doc.
|
|
- Updated `docs/AERE-STARK-VERIFIER-PORT-SPEC.md` (section 4 -> CONFIRMED, status table, intro, files)
|
|
and `pqc-fork/pq-stark/README.md` (new (c) section, layout, reproduce).
|
|
|
|
### 4. CONFORMANCE KAT: PASSED
|
|
|
|
`python test_mmcs_babybear.py` -> **PASS=300 FAIL=0**. CONFORMANCE 37/37 (perm sanity + 6 primitive
|
|
hash/compress KATs + 6 MMCS cases: root + openings + proof + verify-accept + tamper-reject) reproduced
|
|
EXACTLY from the pinned crates. Cross-language byte-identical across Python + Node + Java. Standalone
|
|
`java MmcsBabyBearSelfTest` -> PASS=80 FAIL=0 (includes open-every-valid-leaf self-consistency).
|
|
Poseidon2 regression (`test_poseidon2_babybear.py`) still PASS. No em-dashes / `--` in prose docs.
|
|
|
|
### Multi-matrix generalization
|
|
|
|
Handled beyond the single-matrix case: three genuine mixed-height batches (2 and 3 matrices) are in the
|
|
KAT and pass, so the tallest-first grouping, power-of-two padding, and injection logic are exercised,
|
|
not just documented.
|
|
|
|
## Fail-closed confirmation (unchanged)
|
|
|
|
The top-level 0x0AE8 still verifies NOTHING and returns EMPTY for every input:
|
|
- `StarkConstraints.evaluateAtZeta` returns UNAVAILABLE (stage 4 -> UNAVAILABLE -> EMPTY).
|
|
- `Challenger.spongePorted = false` (absorb no-op; `checkProofOfWork` false; `sampleQueryIndices` empty).
|
|
- `Fri.checkQuery` returns UNAVAILABLE.
|
|
- `computePrecompile` returns `VERIFIED` only if `verify(...) == ACCEPT`; the single `return ACCEPT`
|
|
line is unreachable. `Mmcs.available = true` flips NO top-level gate.
|
|
- DO NOT ACTIVATE banner intact.
|
|
|
|
## Honesty caveat ([MEASURE] remaining)
|
|
|
|
Conformance is against the pinned crate library (KAT reproduced byte-for-byte). Matching a REAL exported
|
|
SP1 v6.1.0 proof's actual commitment root (its specific trace / FRI matrices and heights) is a further
|
|
[MEASURE] step needing an exported proof + the challenger; flagged honestly, not faked.
|
|
|
|
## Scope boundary (unchanged)
|
|
|
|
On-chain ZK verifiers on Aere remain the classical BN254 Groth16 gateway until the whole STARK verifier
|
|
is real, audited, and founder-activated. This is one more component of a multi-week port. Consensus on
|
|
chain 2800 is unaffected (classical secp256k1 ECDSA QBFT).
|