13 KiB
AIP-23: AERE Proof Protocol (a portable, verifiable statement + on-chain finality envelope)
Preamble
| Field | Value |
|---|---|
| AIP | 23 |
| Title | AERE Proof Protocol (portable verifiable-statement envelope with optional post-quantum on-chain finality) |
| Author | Aere Network Foundation |
| Type | Standards Track |
| Category | Interface |
| Status | Draft (describes the envelope AERE tools already emit; the reference verifier is published with this AIP) |
| Created | 2026-09-26 |
| Requires | AIP-15 (anchor certificate under the block hash), AIP-21 (per-block PQ seal record) |
| Supersedes | None |
| Superseded-By | None |
| Ratification | Not ratified; open standard, reference verifier aere-node/tools/verify-proof.mjs, conformance vectors in aere-node/tools/proof-vectors/ |
Abstract
AERE already emits proofs from several surfaces (Proof of Software attestations, Cloud audit-log notarization, the anchor certificate) and they share one shape without ever having been named: a structured statement, a statementHash (the SHA-256 of the statement's canonical text), an optional producer signature, and an optional on-chain notarization whose finality becomes post-quantum once an AERE anchor with a post-quantum validator certificate (AIP-15) covers the state that records it. This AIP names that shape the AERE Proof Protocol, fixes it so anyone can produce and verify it without trusting the producer, and publishes a reference verifier and conformance vectors. The claim it makes checkable is narrow and concrete: a stranger can verify what a system stated, and when the chain first saw it, against a chain state certified post-quantum, without trusting the producer or the RPC endpoint they read through.
Motivation
Today the same envelope is re-described in each tool (Proof of Software's attestation.json, the gateway's /v1/proof, the audit
export). A third party who wants to verify an AERE proof has to read the source each time. Fixing one envelope and one open verifier
turns "AERE can verify post-quantum" into "anyone can verify against AERE", which is the only version of the claim that survives a
hostile reading.
Non-goals: this AIP does not define new cryptography, a new chain rule, or a new contract. It fixes the interface of proofs
that already exist. Signature schemes are referenced (hybrid ECDSA + ML-DSA via @aere/pq-sign), not redefined.
Specification
1. The envelope
A proof is a JSON object:
{
"v": 1,
"kind": "aere-proof-of-<type>-attestation",
"statement": { "v": 1, "kind": "aere-proof-of-<type>", ...type-specific fields..., "createdAt": "<RFC3339>" },
"statementHash": "0x<64 hex>",
"signature": { "scheme": "ml-dsa-65", "publicKey": "<spki der base64 | pem>", "signature": "<base64|hex>" } | null,
"notarization": { "txHash": "0x..", "block": <n>, "firstSeenAt": <unix seconds>, "contract": "0x..", "chainId": 2800 } | null
}
statementis the payload: what happened. Itskindnames the proof type (aere-proof-of-software,aere-proof-of-data,aere-proof-of-ai,aere-proof-of-execution,aere-proof-of-identity,aere-proof-of-compliance, ...). The type-specific fields are that type's business; the protocol constrains only the envelope.statementHashbinds the statement.signature(optional) is the producer's signature over the canonical statement text.notarization(optional) records thatstatementHashwas written to the on-chain notary. It is a claim of the producer; a verifier does not take it on trust (section 4).
2. Canonical text and statementHash
The canonical text of a statement is JSON.stringify(statement) with keys in insertion order, exactly as written into the
envelope (this is what Proof of Software already does; do not re-sort keys, do not reformat). statementHash is
statementHash = "0x" + hex( SHA-256( utf8( JSON.stringify(statement) ) ) )
A verifier recomputes the SHA-256 over the exact statement sub-object as serialized and requires equality. (SHA-256 rather than
keccak: it is the digest Proof of Software has emitted since 1.0.0 and the one software-attestation tooling speaks; the on-chain
notary stores whatever 32-byte value it is handed.)
3. Signature (optional)
If present, the signature is over the canonical statement text (section 2), not over the envelope. The reference verifier
checks an ml-dsa-{44,65,87} signature with node:crypto (OpenSSL 3.5) when the public key is present; the full hybrid
ECDSA + ML-DSA form is verified by @aere/pq-sign. A signature the reference verifier cannot check is reported UNMEASURED,
never silently passed.
4. On-chain finality (optional)
statementHash is notarized by calling notarize(bytes32) on the AERE notary contract (chain 2800,
0x4aB392c4Aca7D9D4C16c0b60a9514c5025bd58c7; permissionless, no owner). The contract records, once, the time of the block in
which the hash was first seen: firstSeen[h] = block.timestamp (unix seconds, proofOf(bytes32) -> uint64). It does not record
a block number; the block that holds the first sighting is found from the contract's Notarized event.
A verifier establishes finality from a certified state, not from what an endpoint says:
- the chain's most recent anchor is verified: every post-quantum seal of its certificate is checked against the published key
manifests, and the certificate is bound under the anchor's hash (AIP-15; this is what
aere-node/tools/verify-anchor.mjsdoes); - the header of the anchor's parent is re-encoded in its on-chain form and must hash to the parent hash those seals signed;
- that header's state root anchors a Merkle-Patricia proof (
eth_getProof) of the notary's account, whose code hash must be the notary's runtime code hash (0x8eaa924081e9718fcee05ae64fadaa1815437ebbbcef5b87317c5879050452ce), and of the storage slotfirstSeen[statementHash](slotkeccak256(statementHash || uint256(0))); - the slot's value is the first-seen time. An empty slot, proven absent, means not notarized as of that certified state.
The endpoint only carries data: a header, a proof node or a value it altered would not match the hash the certificate signed. The first-seen block, located through the endpoint's logs, is reported as such and is not part of what is certified. Levels:
| level | meaning |
|---|---|
not-notarized |
the certified state holds no entry for the hash (proven absent) |
pending |
the endpoint reports a notarization after the certified state; the next anchor will cover it |
post-quantum |
the certified state records the hash with its first-seen time; changing that record would require forging the certificate of an anchor at or above it |
The most recent anchor is used, not the anchor right after the first sighting, because the record never changes once written (a
second notarize of the same hash leaves it as it is) and the endpoint's state window may not reach an old block.
5. Verification levels and verdict
A verifier reports each level that is present in the envelope, and a verdict:
- form: the envelope has
statement(object) andstatementHash(0x+ 64 hex). - integrity: section 2 holds.
- signature: present ? verified or
UNMEASURED: absent. - finality: (the envelope claims a notarization, or an endpoint is given) ? the section-4 levels : absent. A claimed notarization that the certified state does not hold is a failure.
VALID iff every present level passed; PARTIAL if a present level is UNMEASURED or pending; INVALID if any present level
failed. A verifier that cannot go INVALID cannot be trusted: the conformance suite plants failures and requires each to be caught.
Rationale
- One envelope, many kinds. The protocol constrains only what every proof needs (a statement, its hash, an optional signature, an optional notarization); each kind keeps its own fields. A verifier that knows no kind can still check levels 1, 2 and 4.
- SHA-256 over the canonical text. It is what Proof of Software already emits, and it keeps the envelope checkable with the standard library of any language; the notary is agnostic to the digest.
- Finality from a certified state, not from an endpoint. Reading
proofOfthrough an RPC endpoint and calling the result post-quantum because the covering anchor carries a certificate would make the endpoint the trust anchor. Binding a storage proof to a header whose hash the verified certificate signed moves the trust to the certificate, which is what the anchor is for. - The most recent anchor. The notary's record is write-once, so the most recent certified state is as good as the one right after the first sighting, and it is the one an endpoint can still prove (state windows are finite).
Backwards Compatibility
Envelopes that Proof of Software and the Cloud gateway already emit are valid envelopes under this AIP; nothing they produce changes. A draft of the reference verifier (2026-09-26, not published) read the notary's value as a block number and reported the covering anchor post-quantum from the presence of a certificate; it is replaced by the verifier described here.
Security Considerations
- What is certified. That the statementHash was recorded by the notary, with its first-seen time, in a state covered by a post-quantum validator certificate. Not certified: the truth of the statement (that is the producer's word, or its signature's); the first-seen block number (located through logs); anything about the producer's identity unless the signature level passed.
- Notarization is permissionless. Anyone can notarize any hash; a first-seen time proves that the statement existed at that time, not who wrote it. Authorship is the signature level's job.
- The certificate's trust is the validator set's and the published key manifests': a verifier that trusts the manifests it
downloads trusts their publisher, and
aere-node/tools/verify-anchor.mjschecks the manifests' self-consistency and the validators' own bindings to their keys. - An endpoint can refuse to answer or answer late (reported
UNMEASURED), but it cannot make an altered header, proof node or value pass: each is bound by hash to what the certificate signed. - Signatures a verifier cannot check are
UNMEASURED, neverPASSED.
Reference Implementation and On-Chain Deployment
-
AERE notary: chain 2800
0x4aB392c4Aca7D9D4C16c0b60a9514c5025bd58c7; public testnet 280010x70099E62735500AA2F85B60C518551a57B202d54(the same runtime code, code hash in section 4). -
aere-node/tools/verify-proof.mjs: the verifier (Node,node:cryptoand@noble/hashes); for the finality level it runsaere-node/tools/verify-anchor.mjs, published beside it, and reads the anchor it verified from itsANCHOR_REPORToutput, so the certificate check exists in one place.node verify-proof.mjs <envelope.json> [--rpc <url>] [--chain 2800|28001] [--json]. -
aere-node/tools/proof-vectors/: envelopes with their expected verdicts, a real Proof-of-Software attestation among them, and one notarized on the public testnet 28001.
Measured status (2026-09-27)
- Levels 1 to 3: the verifier reproduces the statementHash of a real attestation; a changed statement, a changed statementHash
and a missing statementHash each give
INVALID. - Finality, end to end on the public testnet 28001, where a notary with the same runtime code was deployed for this purpose
(
0x70099E62735500AA2F85B60C518551a57B202d54): a statement about the published AIP-22 conformance corpus was notarized at block 3,618,722, and the verifier reports itpost-quantumfrom the state of the parent of the most recent anchor, with its first-seen time. Through an endpoint that alters the parent header's state root, a node of the storage proof, or the valueproofOfreturns, and with a certificate altered on the way to the anchor check, the verdict isINVALIDin the first, second and fourth cases and unaffected by the third (the value is read from the proof, not from the call); an address that holds another contract is refused by its code hash. With a check removed in a copy of the verifier (the header binding, the code hash, the node hash, the anchor verdict), the corresponding case no longer gives the expected verdict, four of four. - On chain 2800 nothing is notarized yet; there the verifier proves the absence of a hash from the certified state.
Adoption path
The value is in external implementations: once other tools emit this envelope and other verifiers check it, AERE becomes a common
verification layer rather than one more product. Concretely: the verifier and vectors are published with this AIP, the SDKs gain a
verify command that wraps the verifier, and the conformance vectors are the compatibility contract.
Errata
None.
Post-Acceptance Outcome Record
Not accepted; nothing to record.
Copyright
Copyright and related rights waived via CC0.