aere-contracts/contracts/zkverify/AereHalo2ProofAnchor.sol
Aere Network a13a649b77
Some checks are pending
contracts-ci / Install (lockfile) → compile → full test suite (push) Waiting to run
contracts-ci / PQC known-answer tests (NIST vectors) (push) Waiting to run
contracts-ci / Coverage (scoped, with artifacts) (push) Waiting to run
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:02:37 +03:00

104 lines
3.7 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
/// @dev Generated Halo2 (bn254/KZG) verifier ABI: verifyProof returns a
/// 32-byte true on success and REVERTS (empty data) on any failure.
interface IHalo2Verifier {
function verifyProof(bytes calldata proof, uint256[] calldata instances)
external
returns (bool);
}
/**
* @title AereHalo2ProofAnchor — on-chain record of verified Halo2 proofs
* @notice Thin, admin-less anchor over a generated Halo2 Solidity verifier
* (privacy-scaling-explorations/halo2-solidity-verifier, bn254/KZG,
* Bdfg21/SHPLONK batch opening). The bound verifier for this
* deployment is AereHalo2CubicVerifier: a real 4-row standard-PLONK
* circuit proving knowledge of a private x with x^3 + x + 5 == out,
* where out is the single public instance.
*
* verifyAndRecord() forwards (proof, instances) to the verifier;
* the verifier reverts on an invalid proof, so reaching the record
* line means the proof is genuinely valid. Records are append-only:
* (sender, keccak256(proof), keccak256(instances), block, time).
*
* IMMUTABILITY: the verifier address is fixed at deploy; no owner,
* no admin, no pause.
*/
contract AereHalo2ProofAnchor {
/// @notice The generated Halo2 verifier this anchor is bound to.
address public immutable VERIFIER;
struct Record {
address sender;
bytes32 proofHash; // keccak256 of the raw proof bytes
bytes32 instancesHash; // keccak256(abi.encodePacked(instances))
uint64 blockNumber;
uint64 timestamp;
}
Record[] private _records;
/// @notice Number of successful verifications per proof hash.
mapping(bytes32 => uint256) public verificationCountByProofHash;
event Halo2ProofVerified(
address indexed sender,
bytes32 indexed proofHash,
bytes32 instancesHash,
uint256 index
);
error ZeroVerifier();
error ProofRejected();
constructor(address verifier) {
if (verifier == address(0)) revert ZeroVerifier();
VERIFIER = verifier;
}
/**
* @notice Verify a Halo2 proof through the bound verifier and record it.
* @param proof Raw proof bytes as produced by the halo2 prover
* (Keccak256Transcript, ProverSHPLONK).
* @param instances Public instances (for AereHalo2CubicVerifier: [out]).
* @return index Index of the stored record.
*/
function verifyAndRecord(bytes calldata proof, uint256[] calldata instances)
external
returns (uint256 index)
{
// The generated verifier reverts on an invalid proof; bubble that up
// as a clean custom error if it somehow returns false instead.
bool ok = IHalo2Verifier(VERIFIER).verifyProof(proof, instances);
if (!ok) revert ProofRejected();
bytes32 proofHash = keccak256(proof);
bytes32 instancesHash = keccak256(abi.encodePacked(instances));
index = _records.length;
_records.push(Record({
sender: msg.sender,
proofHash: proofHash,
instancesHash: instancesHash,
blockNumber: uint64(block.number),
timestamp: uint64(block.timestamp)
}));
verificationCountByProofHash[proofHash] += 1;
emit Halo2ProofVerified(msg.sender, proofHash, instancesHash, index);
}
/// @notice Total number of recorded verifications.
function recordCount() external view returns (uint256) {
return _records.length;
}
/// @notice Full record at `index` (reverts if out of range).
function getRecord(uint256 index) external view returns (Record memory) {
return _records[index];
}
}