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.
396 lines
22 KiB
Markdown
396 lines
22 KiB
Markdown
# Aere Network Post-Quantum Finality: XMSS Aggregation Circuit Design
|
|
|
|
Research item #4, the off-chain half of the Aere Network Post-Quantum Finality Certificate.
|
|
|
|
Status header, read this first.
|
|
|
|
- IMPLEMENTED and TESTED: the per-validator VERIFICATION CORE. An RFC 8391
|
|
XMSS-SHA2_10_256 hash-based signature verifier (WOTS+ one-time signature plus the
|
|
XMSS Merkle authentication-path check that recovers the root public key), written
|
|
as a dependency-free, `no_std`, allocation-free, float-free, hash-only Rust crate
|
|
at `aerenew/pqc-fork/pq-finality-circuit/xmss-verify-core/`. It is validated
|
|
against the OFFICIAL github.com/XMSS/xmss-reference known-answer vector and passes
|
|
(see Section 7 for the real, run test result).
|
|
- NOT IMPLEMENTED, `[MEASURE]`, multi-week specialist work: the full zkVM
|
|
aggregation guest that runs this core over N validators, the SP1 proving pipeline,
|
|
and the end-to-end certificate. This document specifies that design. It does not
|
|
claim it works.
|
|
- UNCHANGED and fail-closed: the on-chain half
|
|
(`contracts/contracts/pqfinality/AereFinalityCertificateVerifier.sol` and
|
|
`AerePQAttestationKeyRegistry.sol`). Nothing in this work touches it. See Section 8.
|
|
|
|
Scope boundary, unchanged from the certificate design. This is the ADDITIVE
|
|
post-quantum finality-attestation READ path. Aere consensus is still classical ECDSA
|
|
QBFT. Validators keep signing ECDSA committed seals for block production and ALSO
|
|
sign a hash-based attestation over each finalized block. The certificate proves the
|
|
second, additive quorum. It does not replace, gate, or flip consensus, it needs no
|
|
re-genesis, and post-quantum finality is NOT live end to end. Aere consensus is not
|
|
post-quantum, and nothing here claims it is.
|
|
|
|
---
|
|
|
|
## 1. Where this sits
|
|
|
|
`AERE-PQ-FINALITY-CERTIFICATE.md` describes the whole feature. The on-chain verifier
|
|
consumes ONE succinct proof and binds its public values to the live attestation-key
|
|
registry. The proof is produced by an off-chain aggregation circuit that, inside a
|
|
zkVM, verifies that a quorum of validators hash-based-signed a finalized block.
|
|
|
|
That aggregation circuit has an inner obligation it discharges once PER VALIDATOR:
|
|
take a validator's committed hash-based public key and one signature, and confirm the
|
|
signature is a genuine hash-based signature under that key over the domain-bound block
|
|
message. For the XMSS-SHA2_10_256 scheme (RFC 8391, registry `SCHEME_XMSS`), that
|
|
inner obligation is exactly the code in `xmss-verify-core`: recover the XMSS root from
|
|
the signature and compare it to the validator's committed root.
|
|
|
|
This document specifies how the aggregation circuit wraps N instances of that inner
|
|
obligation into the single proof the on-chain verifier already accepts.
|
|
|
|
---
|
|
|
|
## 2. The inner obligation (IMPLEMENTED)
|
|
|
|
For one validator, XMSS-SHA2_10_256 verification (RFC 8391 sections 4.1.9 / 4.1.10,
|
|
single tree, height h = 10, n = 32, Winternitz w = 16, len = 67 chains, SHA-256):
|
|
|
|
1. `M' = H_msg( toByte(2,32) || R || root || toByte(idx,32) || M )`, the randomized,
|
|
root-bound message hash, where `M` is the domain-bound block message (Section 4.3).
|
|
2. `pk_ots = WOTS_PKFromSig(sig_ots, M', SEED, OTS-address(idx))`, completing each of
|
|
the 67 Winternitz chains from the signature value to its chain end.
|
|
3. `leaf = ltree(pk_ots, SEED, LTree-address(idx))`, the L-tree compression of the 67
|
|
WOTS+ public values to one n-byte leaf.
|
|
4. `node = compute_root(leaf, idx, auth, SEED, HashTree-address)`, folding the leaf
|
|
with the h = 10 authentication path.
|
|
5. The signature is VALID for `(root, SEED)` iff `node == root`.
|
|
|
|
All hashing uses the RFC 8391 keyed, address-domain-separated toolbox with
|
|
padding_len = n = 32: `F`, `H`, `H_msg`, and `PRF`, with per-address keys and bitmasks
|
|
derived by `PRF(SEED, ADRS)` over the 32-byte hash address. The reference crate is a
|
|
byte-for-byte model of the already-deployed on-chain `AereXmssVerifier.sol` and its
|
|
independent JS oracle, both validated against the same official vector.
|
|
|
|
Why XMSS verification is zkVM-tractable, honestly. It is hash-only: no floating point,
|
|
no FFT, no Gaussian sampling (the reason Falcon is hard in a circuit). Every step is a
|
|
SHA-256 call over fixed-size inputs, and SHA-256 is an SP1 precompile. The cost is a
|
|
LARGE but BOUNDED number of SHA-256 invocations (Section 6), not a novel arithmetic
|
|
gadget. That is what makes this the tractable first target.
|
|
|
|
Honest limits of the core. It verifies that a signature is valid for a given
|
|
`(root, SEED)`. It does NOT and cannot enforce the signer's one-time-per-leaf state:
|
|
XMSS is stateful, and reusing a leaf index breaks WOTS+ off-chain, not in the verifier.
|
|
The registry models rotation (Section 5); state discipline is the signer's duty.
|
|
|
|
---
|
|
|
|
## 3. The aggregation circuit (NOT implemented, `[MEASURE]`)
|
|
|
|
The guest program (SP1 zkVM in the reference design, matching the repo's existing
|
|
guests under `aerenew/zk-light-client/` and `aerenew/zk-circuits/`) takes a private
|
|
witness and commits public values.
|
|
|
|
### 3.1 Private witness
|
|
|
|
- `blockHash`, `blockHeight`: the finalized Aere block the certificate is about.
|
|
- `attestationDomain`: the 32-byte domain the on-chain verifier binds (Section 4.3).
|
|
- The ordered validator set: for each of the N enrolled validators (in the registry's
|
|
enrollment order, which fixes the root ordering): the validator address, its current
|
|
`keyEpoch`, and its current attestation public key bytes (for XMSS: `root || SEED`,
|
|
plus scheme id).
|
|
- For each validator that attested: its XMSS signature `(idx, R, wots[67], auth[10])`
|
|
over the domain-bound block message. Non-attesting validators carry a null marker.
|
|
|
|
### 3.2 What the circuit MUST enforce
|
|
|
|
1. RECOMPUTE the committee commitment. Rebuild `validatorSetRoot` from the witnessed
|
|
set exactly as `AerePQAttestationKeyRegistry.validatorSetRoot()` defines it
|
|
(Section 4.1), and ABORT unless it equals the committed root the circuit emits. This
|
|
is the membership check: a signature only counts if it is under a key the registry
|
|
committed. Because the flat commitment binds every validator's address, key-epoch,
|
|
and current key material, the circuit that reproduces it has proven each counted key
|
|
is a genuine member at the committed epoch.
|
|
2. VERIFY each counted attestation. For each attesting validator, run the Section 2
|
|
inner obligation against THAT validator's committed `(root, SEED)` over the message
|
|
of Section 4.3, and count it only if it recovers the committed root.
|
|
3. NEVER double-count. The circuit iterates the committed validator list in order and
|
|
admits at most one counted attestation per list position, so distinctness is
|
|
structural, not a runtime set-membership test.
|
|
4. COUNT and THRESHOLD. Let `quorumCount` be the number of DISTINCT valid attestations.
|
|
The circuit requires `quorumCount >= ceil(2N/3)` (the on-chain
|
|
`_quorumThreshold(n) = (2n + 2) / 3`), and ABORTS otherwise, so a proof cannot exist
|
|
below quorum.
|
|
5. EMIT the public values of Section 4.2.
|
|
|
|
The proof is succinct: its size and on-chain verification cost are fixed by the SP1
|
|
verifier, independent of N and of how many attestations were checked internally. That
|
|
independence lives entirely in the SP1 proof system, not in this circuit.
|
|
|
|
---
|
|
|
|
## 4. Binding to the on-chain verifier (the exact contract)
|
|
|
|
The circuit exists to satisfy the ALREADY-BUILT, UNCHANGED on-chain verifier. The
|
|
binding is exact and is the load-bearing honesty of the design.
|
|
|
|
### 4.1 The committee commitment (registry-defined)
|
|
|
|
`AerePQAttestationKeyRegistry.validatorSetRoot()` is a flat, ordered keccak commitment:
|
|
|
|
```
|
|
leaf_i = keccak256(abi.encode(validator_i, keyEpoch_i, keyHash_i))
|
|
root = keccak256(abi.encode(leaf_0, leaf_1, ..., leaf_{N-1}))
|
|
```
|
|
|
|
where `keyHash_i = keccak256(currentPubKey_i)`, or `bytes32(0)` if validator_i has no
|
|
key yet, and the ordering is enrollment order. The circuit MUST reproduce this
|
|
byte-for-byte, including the Solidity `abi.encode` framing.
|
|
|
|
`[VERIFY]` Two encoding details the guest implementation must match against the
|
|
deployed registry when built: (a) `abi.encode(validator_i, keyEpoch_i, keyHash_i)`
|
|
left-pads the 20-byte address and the `uint32` epoch to 32 bytes each, giving a 96-byte
|
|
pre-image; (b) `abi.encode(bytes32[] leaves)` prepends the ABI head for a single
|
|
dynamic array (a 32-byte offset word then a 32-byte length word) before the N leaves,
|
|
so `root = keccak256( 0x20-word || N-word || leaf_0 || ... || leaf_{N-1} )`. Both use
|
|
keccak-256, an SP1 precompile, distinct from the SHA-256 inside XMSS.
|
|
|
|
A Merkle tree is a drop-in alternative if per-leaf inclusion proofs are ever wanted
|
|
(the registry doc notes this). It is NOT needed here: because the circuit witnesses the
|
|
WHOLE set, recomputing the flat commitment is both sufficient and cheaper than N
|
|
logarithmic inclusion proofs. If N grows large enough that witnessing the whole set is
|
|
undesirable, switch the registry to a Merkle root and have the circuit check per-member
|
|
inclusion instead; the on-chain verifier is agnostic, it only compares roots.
|
|
|
|
### 4.2 The public values (fixed 192-byte layout)
|
|
|
|
The circuit MUST commit exactly the six-word layout
|
|
`AereFinalityCertificateVerifier._decode` expects:
|
|
|
|
```
|
|
abi.encode(
|
|
bytes32 blockHash, // the finalized Aere block hash
|
|
uint256 blockHeight, // its height
|
|
bytes32 validatorSetRoot, // recomputed IN the circuit per Section 4.1
|
|
uint256 validatorSetSize, // N committed under the root
|
|
uint256 quorumCount, // number of DISTINCT valid attestations, >= ceil(2N/3)
|
|
bytes32 attestationDomain // the domain tag of Section 4.3
|
|
)
|
|
```
|
|
|
|
The on-chain verifier then, in ONE call and independent of N, checks: the registry is
|
|
non-empty; `validatorSetRoot` equals the live registry root (a rotation invalidates old
|
|
certs); `validatorSetSize` equals the live N; `attestationDomain` equals its immutable
|
|
bound domain; `quorumCount >= ceil(2N/3)`; `blockHash != 0`; and the SP1 proof verifies
|
|
against the pinned circuit vkey. The circuit is trusted for the facts behind those six
|
|
words; the contract binds them to live state.
|
|
|
|
### 4.3 The attestation message (domain-bound)
|
|
|
|
Each validator signs `M`, the 32-byte value the on-chain verifier defines in
|
|
`attestationMessage`:
|
|
|
|
```
|
|
attestationDomain = keccak256(abi.encode(DOMAIN_PREFIX, chainId, registry))
|
|
M = keccak256(abi.encode(attestationDomain, blockHash, blockHeight))
|
|
```
|
|
|
|
`DOMAIN_PREFIX = keccak256("AerePQFinalityCertificate.v1")`. `M` is a keccak output;
|
|
the XMSS `H_msg` then hashes `M` (as its message bytes) with SHA-256 internally. Domain
|
|
binding blocks replay of a certificate to another chain, registry, or purpose. The
|
|
circuit computes `M` from the witnessed `attestationDomain`, `blockHash`, `blockHeight`
|
|
and checks every counted XMSS signature over it, then emits `attestationDomain` so the
|
|
contract can confirm it equals the domain it pinned at construction.
|
|
|
|
---
|
|
|
|
## 5. Choice of hash-based scheme, and the tradeoff
|
|
|
|
The registry already carries scheme labels: `SCHEME_XMSS` (RFC 8391 stateful few-time),
|
|
`SCHEME_WOTS` (Winternitz OTS+ one-time), `SCHEME_LEANSIG` (lean hash-based), and
|
|
`SCHEME_SLHDSA128S` (FIPS 205 stateless), plus `SCHEME_XMSSMT`. The circuit's inner
|
|
verifier is scheme-specific, so the scheme choice is a real design axis.
|
|
|
|
### 5.1 WOTS+ / XMSS (the implemented target)
|
|
|
|
- WOTS+ alone is ONE-TIME: a key signs exactly one message safely. XMSS layers a Merkle
|
|
tree of `2^h` WOTS+ keys under one long-term root, giving `2^h` safe signatures (here
|
|
`2^10 = 1024`) before the key is exhausted. Both are STATEFUL: the signer must never
|
|
reuse a leaf index. This is why attestation keys ROTATE, which
|
|
`AerePQAttestationKeyRegistry` already models with a monotonic per-validator
|
|
`keyEpoch` and an append-only key history. A validator that spends its `2^h` leaves
|
|
registers a successor key; the root changes; old certificates stop matching; new ones
|
|
bind to the new root. Rotation is expected, cheap, and fail-closed.
|
|
- Pro: standardized (RFC 8391, NIST SP 800-208), the most conservative post-quantum
|
|
assumption (security from SHA-256 collision and preimage resistance alone), and it
|
|
MATCHES the deployed on-chain `AereXmssVerifier.sol`, so the same bytes verify
|
|
on-chain and in-circuit.
|
|
- Con: SHA-256 is bit-oriented and comparatively EXPENSIVE to prove. The per-validator
|
|
cost is thousands of SHA-256 invocations (Section 6). With N small this is tractable;
|
|
it does not scale gracefully to thousands of validators.
|
|
|
|
`SCHEME_SLHDSA128S` (SLH-DSA, FIPS 205) is the STATELESS hash-based alternative: no
|
|
rotation discipline (a key signs many times safely), at the cost of larger signatures
|
|
and even more hashing per verify, so a heavier circuit. It is the right choice if
|
|
operators cannot be trusted to manage XMSS state; it trades circuit cost for removing
|
|
the stateful footgun.
|
|
|
|
### 5.2 leanSig / Poseidon2 (the field-native alternative)
|
|
|
|
leanSig is the hash-based signature line behind Ethereum's Lean Consensus / beam-chain
|
|
direction: a generalized-XMSS-style construction whose hash is Poseidon2 over a small
|
|
STARK-native field, chosen precisely for signature aggregation in a proof system.
|
|
|
|
- Pro: Poseidon2 is arithmetization-friendly. It is DRAMATICALLY cheaper inside a
|
|
FRI/STARK circuit than SHA-256 (which pays for bit operations the field does not model
|
|
natively). A leanSig aggregation circuit proves far faster per validator and scales to
|
|
much larger N, which is why Ethereum targets it for its very large validator set.
|
|
- Con: it is NEWER and less standardized than RFC 8391 XMSS, and it moves the hash off
|
|
SHA-256. To keep the on-chain binding exact, the registry key material and the
|
|
committee commitment would also need a consistent hashing story (either keep the
|
|
keccak commitment over Poseidon2-based public keys, or move the commitment to
|
|
Poseidon2 too); the on-chain `AereXmssVerifier.sol` SHA-256 path would not be the
|
|
in-circuit hash. It is the better ENDGAME for cost and scale; XMSS-SHA2 is the better
|
|
FIRST target for standards-alignment and for reusing the already-validated on-chain
|
|
verifier.
|
|
|
|
The tradeoff in one line: XMSS-SHA2 buys standardization, conservatism, and on-chain
|
|
reuse at a higher in-circuit hashing cost; leanSig/Poseidon2 buys a much cheaper,
|
|
more scalable circuit at the cost of novelty and a hashing story that diverges from the
|
|
deployed SHA-256 verifier. An ML-DSA-in-zkVM approach (FIPS 204, integer arithmetic) is
|
|
a further alternative with an easier circuit than SHA-256-XMSS, but it is LATTICE-based,
|
|
not hash-based, so it does NOT carry the hash-only quantum-safety argument and is out of
|
|
scope for the hash-based certificate.
|
|
|
|
Aere Network's live-first advantage is honest and specific: with a small validator set
|
|
(N = 7 today, N >= 9 planned) the XMSS-SHA2 aggregation verifies at most N hash-based
|
|
signatures per certificate, a tractable proving workload NOW, whereas Ethereum's
|
|
hundreds of thousands of validators force the leanSig research runway. The small set
|
|
that makes Aere's honest-quorum premise an operator assumption is the same property that
|
|
makes post-quantum finality aggregation buildable today.
|
|
|
|
---
|
|
|
|
## 6. Structural cost (derivable) and performance (`[MEASURE]`)
|
|
|
|
The following op counts are STRUCTURAL: they follow from the XMSS-SHA2_10_256 parameters
|
|
and the toolbox definitions, and are derivable without running anything. They are NOT a
|
|
performance measurement.
|
|
|
|
Per SHA-256-toolbox primitive: `PRF` and `F` hash 96-byte inputs; `H` hashes a 128-byte
|
|
input; each `F` step needs 2 `PRF` (key, mask) plus one `F` hash (3 SHA-256 calls); each
|
|
`H` node needs 3 `PRF` (key, two masks) plus one `H` hash (4 SHA-256 calls).
|
|
|
|
Per-validator XMSS-SHA2_10_256 verify (worst case, chains completed from the low end):
|
|
|
|
| Stage | Units | SHA-256 calls (worst case) |
|
|
| ----------------- | ------------------------------ | -------------------------- |
|
|
| `H_msg` | 1 hash over ~129 bytes | 1 |
|
|
| WOTS_PKFromSig | up to 67 chains x 15 `F` steps | up to ~3015 |
|
|
| L-tree | 66 `H` nodes | ~264 |
|
|
| Auth path (h=10) | 10 `H` nodes | ~40 |
|
|
| Per validator | | up to ~3320 SHA-256 calls |
|
|
|
|
For N = 7 that is on the order of ~23,000 SHA-256 invocations across the aggregation,
|
|
plus a handful of keccak-256 calls for the committee commitment and the message binding.
|
|
Typical (not worst) WOTS cost is roughly half, since the average completed chain length
|
|
is about w/2. These counts are exactly why SHA-256 is the cost driver and why
|
|
leanSig/Poseidon2 is the cheaper long-run hash.
|
|
|
|
`[MEASURE]` and NOT run here (each depends on the actual SP1 guest build, the sha256/
|
|
keccak precompile configuration, the prover hardware, and the proof mode):
|
|
|
|
- RISC-V cycle count per validator and per certificate inside the SP1 zkVM.
|
|
- Proving latency and memory for N = 7 and N = 9, on a given prover or the Succinct
|
|
prover network.
|
|
- On-chain `verifyProof` gas against the REAL Succinct gateway (the contract is
|
|
currently tested against a mock gateway).
|
|
- Native STARK vs Groth16-wrap tradeoff. A Groth16 wrap over BN254 shrinks the on-chain
|
|
proof but REINTRODUCES a Shor-breakable pairing leg, forfeiting the end-to-end
|
|
quantum-safety of Section 4 of the certificate doc. A native hash-based STARK proof
|
|
(verified by the `AerePQStarkVerifier` line) keeps the proof itself post-quantum. This
|
|
choice is a `[MEASURE]` cost-vs-quantum-safety decision, not settled here.
|
|
Scope caveat (2026-07-19 finding): the `AerePQStarkVerifier` skeleton (0x0AE8) built so
|
|
far is a BabyBear + FRI verifier that targets Aere's OWN Plonky3 STARKs. It does NOT
|
|
verify an SP1 6.1.0 proof, because the pinned SP1 6.1.0 is a Hypercube / BaseFold
|
|
(KoalaBear multilinear) system, not BabyBear FRI. So the native-STARK option here means
|
|
proving the aggregation as an Aere-native BabyBear/FRI STARK (or retargeting 0x0AE8 to
|
|
the SP1 Hypercube stack, a separate ~22 to 32 person-week effort), not verifying an SP1
|
|
zkVM proof directly. See `AERE-STARK-SP1-RECURSION-AIR-PORT-SPEC-SUMMARY.md`.
|
|
|
|
---
|
|
|
|
## 7. What was actually built and the REAL test result
|
|
|
|
Built at `aerenew/pqc-fork/pq-finality-circuit/xmss-verify-core/`:
|
|
|
|
- `src/sha256.rs`: a dependency-free `no_std` SHA-256 (self-checked against FIPS 180-4
|
|
`SHA256("abc")` and `SHA256("")`). A production SP1 guest swaps this for the
|
|
SP1-patched `sha2` precompile crate; the bytes are identical.
|
|
- `src/xmss.rs`: the RFC 8391 XMSS-SHA2_10_256 verification core (`chain_lengths`,
|
|
`wots_pk_from_sig`, `l_tree`, `compute_root`, `xmss_recover_root`, `xmss_verify`),
|
|
`no_std`, allocation-free, float-free, hash-only.
|
|
- `src/vectors.rs`: the official vector, GENERATED by `scripts/gen_vectors.mjs` from the
|
|
committed `contracts/test/fixtures/xmss-sha2_10_256-kat.json`
|
|
(github.com/XMSS/xmss-reference, oid=1, idx=512, msg=0x25), so the Rust vector is
|
|
provably derived from the official fixture with no hand transcription.
|
|
- `tests/kat.rs`: the known-answer validation.
|
|
|
|
Real result of `cargo test --offline` (run, not asserted from memory): 12 tests
|
|
passed, 0 failed. The genuine official signature recovers the official root
|
|
`0x9d898033e37af48e6a116f8b15651cc26773467007ad19375d38c23c690c3483` and verifies; and
|
|
every tamper (a WOTS+ value, the checksum chain, an authentication-path node, the
|
|
message, the leaf index, the claimed root, the R randomizer) fails to verify. The two
|
|
SHA-256 self-checks match FIPS 180-4.
|
|
|
|
This validates the INNER obligation of Section 2 only. It is not a proof, not a zkVM
|
|
run, and not an aggregation.
|
|
|
|
---
|
|
|
|
## 8. On-chain side is unchanged and fail-closed
|
|
|
|
This work adds an off-chain reference crate and this document. It does NOT modify
|
|
`AereFinalityCertificateVerifier.sol` or `AerePQAttestationKeyRegistry.sol`, and does
|
|
not touch their tests. The on-chain verifier remains fail-closed exactly as before: it
|
|
rejects unless the registry is non-empty, the proven root and size match the live
|
|
registry, the domain matches, `quorumCount >= ceil(2N/3)`, the block hash is non-zero,
|
|
AND the SP1 proof verifies against the pinned vkey through the immutable gateway. Until
|
|
a real aggregation guest and a real proof exist, no certificate can pass the real
|
|
gateway, which is the correct fail-closed behavior.
|
|
|
|
---
|
|
|
|
## 9. Effort estimate for the remaining `[MEASURE]` work
|
|
|
|
Honest, and a range, not a promise. The verification core (done) is the small part.
|
|
The remaining full zkVM guest plus proving pipeline is multi-week specialist work:
|
|
|
|
- Guest program: port `xmss-verify-core` into an SP1 guest, add the keccak committee
|
|
commitment and message binding, the N-validator loop, distinct-count, and the
|
|
threshold, and wire the six-word public-values output. Roughly 1 to 2 weeks including
|
|
matching the `abi.encode` framing of Section 4.1 against the deployed registry.
|
|
- Host and witness assembly: collect attestations, build the private witness, run the
|
|
prover. Roughly 1 week.
|
|
- Proving, tuning, and MEASURE: cycle counts, latency, memory, real-gateway gas, and the
|
|
native-STARK vs Groth16 decision. Roughly 1 to 3 weeks, hardware-dependent.
|
|
- Audit of the guest before any mainnet vkey is pinned. Separate, founder-gated.
|
|
|
|
Total on the order of several weeks of focused specialist work before an end-to-end
|
|
certificate could be produced, plus audit. Do NOT describe the certificate as working
|
|
end-to-end until that work is done and measured.
|
|
|
|
---
|
|
|
|
## 10. References
|
|
|
|
- On-chain half (unchanged): `contracts/contracts/pqfinality/AereFinalityCertificateVerifier.sol`,
|
|
`contracts/contracts/pqfinality/AerePQAttestationKeyRegistry.sol`, and
|
|
`contracts/test/AerePQFinalityCertificate.test.js`.
|
|
- Feature doc: `aerenew/docs/AERE-PQ-FINALITY-CERTIFICATE.md`.
|
|
- Deployed on-chain XMSS verifier and its official vector:
|
|
`contracts/contracts/pqc/AereXmssVerifier.sol`, `contracts/test/xmssVerifier.test.js`,
|
|
`contracts/test/fixtures/xmss-sha2_10_256-kat.json`.
|
|
- SP1 guest / core-crate pattern this crate mirrors: `aerenew/zk-light-client/guest/`,
|
|
`aerenew/zk-light-client/qbft-finality/`, `aerenew/zk-circuits/recursive-aggregation-scale/`.
|
|
- Standards: RFC 8391 (XMSS), NIST SP 800-208 (stateful hash-based signatures), FIPS 205
|
|
(SLH-DSA), FIPS 180-4 (SHA-256).
|
|
```
|