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.
106 lines
5.1 KiB
Solidity
106 lines
5.1 KiB
Solidity
// Copyright 2025 RISC Zero, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
pragma solidity ^0.8.9;
|
|
|
|
import {Ownable, Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
|
|
|
|
import {IRiscZeroVerifier, Receipt} from "./IRiscZeroVerifier.sol";
|
|
|
|
/// @notice Router for IRiscZeroVerifier, allowing multiple implementations to be accessible behind a single address.
|
|
contract RiscZeroVerifierRouter is IRiscZeroVerifier, Ownable2Step {
|
|
/// @notice Mapping from 4-byte verifier selector to verifier contracts.
|
|
/// Used to route receipts to verifiers that are able to check the receipt.
|
|
mapping(bytes4 => IRiscZeroVerifier) public verifiers;
|
|
|
|
/// @notice Value of an entry that has never been set.
|
|
IRiscZeroVerifier internal constant UNSET = IRiscZeroVerifier(address(0));
|
|
/// @notice A "tombstone" value used to mark verifier entries that have been removed from the mapping.
|
|
IRiscZeroVerifier internal constant TOMBSTONE = IRiscZeroVerifier(address(1));
|
|
|
|
/// @notice Error raised when attempting to verify a receipt with a selector that is not
|
|
/// registered on this router. Generally, this indicates a version mismatch where the
|
|
/// prover generated a receipt with version of the zkVM that does not match any
|
|
/// registered version on this router contract.
|
|
error SelectorUnknown(bytes4 selector);
|
|
/// @notice Error raised when attempting to add a verifier for a selector that is already registered.
|
|
error SelectorInUse(bytes4 selector);
|
|
/// @notice Error raised when attempting to verify a receipt with a selector that has been
|
|
/// removed, or attempting to add a new verifier with a selector that was previously
|
|
/// registered and then removed.
|
|
error SelectorRemoved(bytes4 selector);
|
|
/// @notice Error raised when attempting to add a verifier with a zero address.
|
|
error VerifierAddressZero();
|
|
|
|
constructor(address admin) Ownable() { transferOwnership(admin); }
|
|
|
|
/// @notice Adds a verifier to the router, such that it can receive receipt verification calls.
|
|
function addVerifier(bytes4 selector, IRiscZeroVerifier verifier) external virtual onlyOwner {
|
|
if (verifiers[selector] == TOMBSTONE) {
|
|
revert SelectorRemoved({selector: selector});
|
|
}
|
|
if (verifiers[selector] != UNSET) {
|
|
revert SelectorInUse({selector: selector});
|
|
}
|
|
if (address(verifier) == address(0)) {
|
|
revert VerifierAddressZero();
|
|
}
|
|
verifiers[selector] = verifier;
|
|
}
|
|
|
|
/// @notice Removes verifier from the router, such that it can not receive verification calls.
|
|
/// Removing a selector sets it to the tombstone value. It can never be set to any
|
|
/// other value, and can never be reused for a new verifier, in order to enforce the
|
|
/// property that each selector maps to at most one implementation across time.
|
|
function removeVerifier(bytes4 selector) external virtual onlyOwner {
|
|
// Simple check to reduce the chance of accidents.
|
|
// NOTE: If there ever _is_ a reason to remove a selector that has never been set, the owner
|
|
// can call addVerifier with the tombstone address.
|
|
if (verifiers[selector] == UNSET) {
|
|
revert SelectorUnknown({selector: selector});
|
|
}
|
|
verifiers[selector] = TOMBSTONE;
|
|
}
|
|
|
|
/// @notice Get the associated verifier, reverting if the selector is unknown or removed.
|
|
function getVerifier(bytes4 selector) public view virtual returns (IRiscZeroVerifier) {
|
|
IRiscZeroVerifier verifier = verifiers[selector];
|
|
if (verifier == UNSET) {
|
|
revert SelectorUnknown({selector: selector});
|
|
}
|
|
if (verifier == TOMBSTONE) {
|
|
revert SelectorRemoved({selector: selector});
|
|
}
|
|
return verifier;
|
|
}
|
|
|
|
/// @notice Get the associated verifier, reverting if the selector is unknown or removed.
|
|
function getVerifier(bytes calldata seal) public view returns (IRiscZeroVerifier) {
|
|
// Use the first 4 bytes of the seal at the selector to look up in the mapping.
|
|
return getVerifier(bytes4(seal[0:4]));
|
|
}
|
|
|
|
/// @inheritdoc IRiscZeroVerifier
|
|
function verify(bytes calldata seal, bytes32 imageId, bytes32 journalDigest) external view virtual {
|
|
getVerifier(seal).verify(seal, imageId, journalDigest);
|
|
}
|
|
|
|
/// @inheritdoc IRiscZeroVerifier
|
|
function verifyIntegrity(Receipt calldata receipt) external view virtual {
|
|
getVerifier(receipt.seal).verifyIntegrity(receipt);
|
|
}
|
|
}
|