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.
87 lines
3.3 KiB
Solidity
87 lines
3.3 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
import {ISP1Verifier, ISP1VerifierWithHash} from "../ISP1Verifier.sol";
|
|
import {PlonkVerifier} from "./PlonkVerifier.sol";
|
|
|
|
/// @title SP1 Verifier
|
|
/// @author Succinct Labs
|
|
/// @notice This contracts implements a solidity verifier for SP1.
|
|
contract SP1Verifier is PlonkVerifier, ISP1VerifierWithHash {
|
|
/// @notice Thrown when the verifier selector from this proof does not match the one in this
|
|
/// verifier. This indicates that this proof was sent to the wrong verifier.
|
|
/// @param received The verifier selector from the first 4 bytes of the proof.
|
|
/// @param expected The verifier selector from the first 4 bytes of the VERIFIER_HASH().
|
|
error WrongVerifierSelector(bytes4 received, bytes4 expected);
|
|
|
|
/// @notice Thrown when the exit code is invalid.
|
|
error InvalidExitCode();
|
|
|
|
/// @notice Thrown when the proof is invalid.
|
|
error InvalidProof();
|
|
|
|
/// @notice Thrown when the vkRoot is invalid.
|
|
error InvalidVkRoot();
|
|
|
|
/// @notice The version of the circuit.
|
|
function VERSION() external pure returns (string memory) {
|
|
return "v6.1.0";
|
|
}
|
|
|
|
/// @inheritdoc ISP1VerifierWithHash
|
|
function VERIFIER_HASH() public pure returns (bytes32) {
|
|
return 0x5a093a2fcb46394f5cadfe55c44d4d572fad9cec7aeb38026b0278322ef07fac;
|
|
}
|
|
|
|
/// @notice The recursion vk root.
|
|
function VK_ROOT() public pure returns (bytes32) {
|
|
return 0x002f850ee998974d6cc00e50cd0814b098c05bfade466d28573240d057f25352;
|
|
}
|
|
|
|
/// @notice Hashes the public values to a field elements inside Bn254.
|
|
/// @param publicValues The public values.
|
|
function hashPublicValues(bytes calldata publicValues) public pure returns (bytes32) {
|
|
return sha256(publicValues) & bytes32(uint256((1 << 253) - 1));
|
|
}
|
|
|
|
/// @notice Verifies a proof with given public values and vkey.
|
|
/// @param programVKey The verification key for the RISC-V program.
|
|
/// @param publicValues The public values encoded as bytes.
|
|
/// @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes.
|
|
function verifyProof(
|
|
bytes32 programVKey,
|
|
bytes calldata publicValues,
|
|
bytes calldata proofBytes
|
|
) external view {
|
|
bytes4 receivedSelector = bytes4(proofBytes[:4]);
|
|
bytes4 expectedSelector = bytes4(VERIFIER_HASH());
|
|
if (receivedSelector != expectedSelector) {
|
|
revert WrongVerifierSelector(receivedSelector, expectedSelector);
|
|
}
|
|
|
|
uint256 expectedVkRoot = uint256(VK_ROOT());
|
|
|
|
bytes32 publicValuesDigest = hashPublicValues(publicValues);
|
|
uint256 exitCode = uint256(bytes32(proofBytes[4:36]));
|
|
uint256 vkRoot = uint256(bytes32(proofBytes[36:68]));
|
|
uint256 nonce = uint256(bytes32(proofBytes[68:100]));
|
|
|
|
uint256[] memory inputs = new uint256[](5);
|
|
inputs[0] = uint256(programVKey);
|
|
inputs[1] = uint256(publicValuesDigest);
|
|
inputs[2] = exitCode;
|
|
inputs[3] = vkRoot;
|
|
inputs[4] = nonce;
|
|
if (exitCode != 0) {
|
|
revert InvalidExitCode();
|
|
}
|
|
if (vkRoot != expectedVkRoot) {
|
|
revert InvalidVkRoot();
|
|
}
|
|
bool success = this.Verify(proofBytes[100:], inputs);
|
|
if (!success) {
|
|
revert InvalidProof();
|
|
}
|
|
}
|
|
}
|