Description:
Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/PoSQLVerifier.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IVerify} from "./query-router/interfaces/IVerify.sol";
import {IQueryRouter} from "./query-router/interfaces/IQueryRouter.sol";
import {Verifier} from "sxt-proof-of-sql/src/verifier/Verifier.post.sol";
import {ParamsBuilder} from "sxt-proof-of-sql/src/client/ParamsBuilder.post.sol";
contract PoSQLVerifier is IVerify {
uint256 internal constant WORD_SIZE = 0x20; // aderyn-ignore unused-state-variable
uint8 internal constant HYPER_KZG_COMMITMENT_SCHEME_VARIANT = 0;
address public immutable PAYOUT_ADDRESS;
address private immutable OWNER;
error ZeroAddressNotAllowed();
error OnlyOwnerAllowed();
struct CommitmentProof {
bytes32[] proof;
bytes32[] r;
bytes32[] s;
uint8[] v;
uint64 blockNumber;
bool[] proofFlags;
}
struct ResultBody {
bytes result;
bytes proof;
CommitmentProof commitmentProof;
string[] tableNames; // should be in the same order as tableCommitments
bytes[] tableCommitments;
}
function _onlyOwner() internal view {
if (msg.sender != OWNER) revert OnlyOwnerAllowed();
}
constructor(address payoutAddress) {
if (payoutAddress == address(0)) revert ZeroAddressNotAllowed();
PAYOUT_ADDRESS = payoutAddress;
OWNER = msg.sender;
}
receive() external payable {}
/// @notice Returns the payout address and fee
/// @return payoutAddress The payout address
/// @return fee The fee (0.5 USD)
function getPayoutAddressAndFee() external view returns (address payoutAddress, uint248 fee) {
return (PAYOUT_ADDRESS, 0.5 ether);
}
struct TableCommitment {
uint256 commitmentsPtr;
uint64 tableLength;
bytes32[] columnNameHashes;
}
// slither-disable-start dead-code
function encodeTableCommitmentLeaf(string memory tableId, bytes memory tableCommitment) /// aderyn-ignore dead-code
internal
pure
returns (bytes32)
{
bytes memory packedLeaf = abi.encodePacked( // aderyn-ignore abi-encode-packed-hash-collision
uint8(bytes(tableId).length),
tableId,
HYPER_KZG_COMMITMENT_SCHEME_VARIANT,
tableCommitment
);
bytes32 hashedLeaf;
assembly {
let len := mload(packedLeaf)
packedLeaf := add(packedLeaf, WORD_SIZE)
hashedLeaf := keccak256(packedLeaf, len)
}
return hashedLeaf;
}
// slither-disable-end dead-code
/// @inheritdoc IVerify
function verify(IQueryRouter.Query calldata queryData, bytes calldata proof)
external
view
returns (bytes memory result)
{
ResultBody calldata queryResultStruct;
assembly {
queryResultStruct := add(proof.offset, WORD_SIZE)
}
uint256[] memory __placeholderParameters = ParamsBuilder.deserializeParamArray(queryData.parameters);
Verifier.verify(
queryResultStruct.result,
queryData.innerQuery,
__placeholderParameters,
queryResultStruct.proof,
queryResultStruct.tableCommitments
);
return queryResultStruct.result;
}
/// @notice Allows the contract owner to withdraw any ETH that might be sent to this contract
/// @dev Added to address Slither warning about contracts locking ether
// slither-disable-next-line low-level-calls
function withdraw() external {
_onlyOwner();
payable(OWNER).transfer(address(this).balance); // aderyn-ignore dead-code unsafe-erc20-operation
}
}
"
},
"src/query-router/interfaces/IVerify.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IQueryRouter} from "./IQueryRouter.sol";
/// @title IVerify
/// @author Placeholder
/// @notice Minimal verifier interface that exposes exactly the verify method
interface IVerify {
/// @notice Verify a query result and return the extracted result bytes
/// @param queryData The original query struct
/// @param proof Encoded proof containing the query result and cryptographic proof
/// @return result The query result data extracted from the proof
function verify(IQueryRouter.Query calldata queryData, bytes calldata proof)
external
view
returns (bytes memory result);
}
"
},
"src/query-router/interfaces/IQueryRouter.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
/// @title IQueryRouter
/// @author Placeholder
/// @notice Interface for querying external data sources with cryptographic proofs
interface IQueryRouter {
/// @notice Query details
/// @param version Query version identifier
/// @param innerQuery Encoded, version-dependent query payload
/// @param parameters Encoded parameters for the query
/// @param metadata Encoded metadata for the query
struct Query {
bytes32 version;
bytes innerQuery;
bytes parameters;
bytes metadata;
}
/// @notice Callback execution details
/// @param maxGasPrice Max native gas price allowed for the callback
/// @param gasLimit Gas limit forwarded to the callback contract
/// @param callbackContract Address of the contract to call back
/// @param selector Function selector to call on the callback contract
/// @param callbackData Opaque callback-specific data passed to the callback
struct Callback {
uint256 maxGasPrice;
uint64 gasLimit;
address callbackContract;
bytes4 selector;
bytes callbackData;
}
/// @notice Emitted when a query is requested
/// @param queryId Unique identifier for the query
/// @param queryNonce Nonce used when the query was created
/// @param requester Address that requested the query
/// @param query Query details
/// @param callback Callback details
/// @param paymentAmount Amount of tokens held pending fulfillment
/// @param timeout Timestamp after which cancellation is allowed
event QueryRequested(
bytes32 indexed queryId,
uint64 indexed queryNonce,
address indexed requester,
Query query,
Callback callback,
uint256 paymentAmount,
uint64 timeout
);
/// @notice Emitted when a query has been fulfilled (logical fulfillment/result)
/// @param queryId Unique identifier for the query
/// @param fulfiller Address that fulfilled the query
/// @param result The query result data
event QueryFulfilled(bytes32 indexed queryId, address indexed fulfiller, bytes result);
/// @notice Emitted when a payout for a fulfilled query occurred (payments/refunds)
/// @param queryId Unique identifier for the query
/// @param fulfiller Address that fulfilled the query
/// @param refundRecipient Address that received a refund (if any)
/// @param fulfillerAmount Amount paid to the fulfiller for this fulfillment
/// @param refundAmount Amount refunded to the refundRecipient (if any)
event PayoutOccurred(
bytes32 indexed queryId,
address indexed fulfiller,
address indexed refundRecipient,
uint256 fulfillerAmount,
uint256 refundAmount
); // solhint-disable-line gas-indexed-events
/// @notice Emitted when a query is cancelled
/// @param queryId Unique identifier for the query
/// @param refundRecipient Address that received the refund
/// @param refundAmount Amount refunded
event QueryCancelled(bytes32 indexed queryId, address indexed refundRecipient, uint256 indexed refundAmount);
/// @notice Emitted when open fulfillment is toggled
/// @param enabled Whether open fulfillment is now enabled
event OpenFulfillmentToggled(bool indexed enabled);
/// @notice Emitted when the base cost used by the router is updated
/// @param newBaseCost The new base cost value
event BaseCostUpdated(uint256 indexed newBaseCost);
/// @notice Emitted when a version is set
/// @param version The string version
/// @param versionHash The keccak256 hash of the version
/// @param verifier The verifier contract address associated with the version
event VersionSet(string version, bytes32 indexed versionHash, address indexed verifier);
/// @notice Thrown when a query is not found or unauthorized cancellation is attempted
error QueryNotFound(); // aderyn-ignore unused-error
/// @notice Thrown when a query cancellation is attempted before the timeout
error QueryTimeoutNotReached(); // aderyn-ignore unused-error
/// @notice Thrown when the query version is not supported by the router
error UnsupportedQueryVersion(); // aderyn-ignore unused-error
/// @notice Register a verifier contract address to a version string
/// @param version The string version to hash
/// @param verifier The contract address to associate with the version
function registerVerifierToVersion(string calldata version, address verifier) external;
/// @notice Set the base cost for queries
/// @param newBaseCost The new base cost
function setBaseCost(uint256 newBaseCost) external;
/// @notice Cancel a pending query and refund the payment
/// @param queryId Unique identifier for the query to cancel
function cancelQuery(bytes32 queryId) external;
/// @notice Request a query to be executed.
/// @param query Query struct containing query string, parameters, and version.
/// @param callback Callback struct containing callback details.
/// @param paymentAmount Amount of tokens to hold pending fulfillment.
/// @param timeout Timestamp after which cancellation is allowed
/// @return queryId Unique ID for this query.
function requestQuery(Query calldata query, Callback calldata callback, uint256 paymentAmount, uint64 timeout)
external
returns (bytes32 queryId);
/// @notice Fulfill a query by providing its data and proof.
/// @param query Query struct for the original request.
/// @param callback Callback struct for the original request.
/// @param queryNonce Nonce used when the query was created.
/// @param proof Encoded proof containing the query result and cryptographic proof.
function fulfillQuery(Query calldata query, Callback calldata callback, uint64 queryNonce, bytes calldata proof)
external;
/// @notice Toggle open fulfillment on or off
/// @param enabled True to allow anyone to fulfill, false to restrict to FULFILLER_ROLE
function setOpenFulfillment(bool enabled) external;
/// @notice Verify a query result without executing its callback.
/// @param query Query struct for the original request.
/// @param proof Encoded proof containing the query result and cryptographic proof.
/// @return result The query result data extracted from the proof.
function verifyQuery(Query calldata query, bytes calldata proof) external view returns (bytes memory result);
}
"
},
"dependencies/sxt-proof-of-sql-0.123.10/src/verifier/Verifier.post.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// This is licensed under the Cryptographic Open Software License 1.0
pragma solidity ^0.8.28;
import "../base/Constants.sol";
import "../base/Errors.sol";
library Verifier {
function verify(
bytes calldata __result,
bytes calldata __plan,
uint256[] memory __placeholderParameters,
bytes calldata __proof,
bytes[] calldata __tableCommitments
) public view {
(uint256[] memory tableLengths, uint256[] memory commitments) =
getCommitmentsAndLength(__plan, __tableCommitments);
__internalVerify({
__result: __result,
__plan: __plan,
__placeholderParameters: __placeholderParameters,
__proof: __proof,
__tableLengths: tableLengths,
__commitments: commitments
});
}
struct TableCommitment {
uint256 commitmentsPtr;
uint64 tableLength;
bytes32[] columnNameHashes;
}
// slither-disable-next-line cyclomatic-complexity
function deserializeTableCommitment(bytes calldata tableCommitment)
internal
pure
returns (TableCommitment memory result)
{
uint256 commitmentsPtr;
uint64 tableLength;
// columnNameHashes[columnId] = columnNameHash
bytes32[] memory columnNameHashes;
assembly {
function exclude_coverage_start_err() {} // solhint-disable-line no-empty-blocks
function err(code) {
mstore(0, code)
revert(28, 4)
}
function exclude_coverage_stop_err() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_data_type() {} // solhint-disable-line no-empty-blocks
function read_data_type(ptr) -> ptr_out, data_type {
data_type := shr(UINT32_PADDING_BITS, calldataload(ptr))
ptr_out := add(ptr, UINT32_SIZE)
switch data_type
case 0 { case_const(0, DATA_TYPE_BOOLEAN_VARIANT) }
case 2 { case_const(2, DATA_TYPE_TINYINT_VARIANT) }
case 3 { case_const(3, DATA_TYPE_SMALLINT_VARIANT) }
case 4 { case_const(4, DATA_TYPE_INT_VARIANT) }
case 5 { case_const(5, DATA_TYPE_BIGINT_VARIANT) }
case 7 { case_const(7, DATA_TYPE_VARCHAR_VARIANT) }
case 8 {
case_const(8, DATA_TYPE_DECIMAL75_VARIANT)
ptr_out := add(ptr_out, UINT8_SIZE) // Skip precision
ptr_out := add(ptr_out, INT8_SIZE) // Skip scale
}
case 9 {
case_const(9, DATA_TYPE_TIMESTAMP_VARIANT)
ptr_out := add(ptr_out, UINT32_SIZE) // Skip timeunit
ptr_out := add(ptr_out, INT32_SIZE) // Skip timezone
}
case 10 { case_const(10, DATA_TYPE_SCALAR_VARIANT) }
case 11 { case_const(11, DATA_TYPE_VARBINARY_VARIANT) }
default { err(ERR_UNSUPPORTED_DATA_TYPE_VARIANT) }
}
function exclude_coverage_stop_read_data_type() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_case_const() {} // solhint-disable-line no-empty-blocks
function case_const(lhs, rhs) {
if sub(lhs, rhs) { err(ERR_INCORRECT_CASE_CONST) }
}
function exclude_coverage_stop_case_const() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_hash_string() {} // solhint-disable-line no-empty-blocks
function hash_string(ptr, free_ptr) -> ptr_out, free_ptr_out {
let name_len := shr(UINT64_PADDING_BITS, calldataload(ptr))
ptr := add(ptr, UINT64_SIZE)
// TODO: This line should probably be using the FREE_PTR directly, instead of having it passed in the function.
// This is a little dangerous as it is.
calldatacopy(free_ptr, ptr, name_len)
mstore(free_ptr, keccak256(free_ptr, name_len))
ptr_out := add(ptr, name_len)
free_ptr_out := add(free_ptr, WORD_SIZE)
}
function exclude_coverage_stop_hash_string() {} // solhint-disable-line no-empty-blocks
let ptr := tableCommitment.offset
// range.start (usize) must be 0
if shr(UINT64_PADDING_BITS, calldataload(ptr)) { err(ERR_TABLE_COMMITMENT_UNSUPPORTED) }
ptr := add(ptr, UINT64_SIZE)
// range.end *usize) is the table length
tableLength := shr(UINT64_PADDING_BITS, calldataload(ptr))
ptr := add(ptr, UINT64_SIZE)
// commitments.len() (usize) is the number of columns
let num_columns := shr(UINT64_PADDING_BITS, calldataload(ptr))
ptr := add(ptr, UINT64_SIZE)
// each commitment is a 2-word commitment
commitmentsPtr := ptr
ptr := add(ptr, mul(num_columns, WORDX2_SIZE))
// column_metadata.len() (usize) must match the number of columns
if sub(num_columns, shr(UINT64_PADDING_BITS, calldataload(ptr))) { err(ERR_TABLE_COMMITMENT_UNSUPPORTED) }
ptr := add(ptr, UINT64_SIZE)
// allocating space for column namess
let free_ptr := mload(FREE_PTR)
columnNameHashes := free_ptr
// initializing length of column names
mstore(free_ptr, num_columns)
free_ptr := add(free_ptr, WORD_SIZE)
// for each entry in column_metadata
for {} num_columns { num_columns := sub(num_columns, 1) } {
ptr, free_ptr := hash_string(ptr, free_ptr)
// column_metadata[i].Ident.quote_style (Option<char>) must be None, i.e. 0
if shr(UINT8_PADDING_BITS, calldataload(ptr)) { err(ERR_TABLE_COMMITMENT_UNSUPPORTED) }
ptr := add(ptr, UINT8_SIZE)
let data_type
ptr, data_type := read_data_type(ptr)
// column_metadata[i].ColumnCommitmentMetadata.bounds (ColumnBounds)
let variant := shr(UINT32_PADDING_BITS, calldataload(ptr))
ptr := add(ptr, UINT32_SIZE)
function skip_bounds(data_size, ptr_in) -> ptr_out {
let bounds_variant := shr(UINT32_PADDING_BITS, calldataload(ptr_in))
ptr_out := add(ptr_in, UINT32_SIZE)
if bounds_variant { ptr_out := add(ptr_out, mul(data_size, 2)) }
}
switch variant
// ColumnBounds::NoOrder
case 0 {}
// ColumnBounds::Uint8
case 1 { ptr := skip_bounds(UINT8_SIZE, ptr) }
// ColumnBounds::TinyInt
case 2 { ptr := skip_bounds(UINT8_SIZE, ptr) }
// ColumnBounds::SmallInt
case 3 { ptr := skip_bounds(UINT16_SIZE, ptr) }
// ColumnBounds::Int
case 4 { ptr := skip_bounds(UINT32_SIZE, ptr) }
// ColumnBounds::BigInt
case 5 { ptr := skip_bounds(UINT64_SIZE, ptr) }
// ColumnBounds::Int128
case 6 { ptr := skip_bounds(UINT128_SIZE, ptr) }
// ColumnBounds::TimestampTZ
case 7 { ptr := skip_bounds(UINT64_SIZE, ptr) }
default { err(ERR_TABLE_COMMITMENT_UNSUPPORTED) }
}
// done allocating space for column names
mstore(FREE_PTR, free_ptr)
}
result = TableCommitment(commitmentsPtr, tableLength, columnNameHashes);
}
function deserializeTableCommitments(bytes[] calldata tableCommitments)
internal
pure
returns (
// tableCommitments[tableId] = TableCommitment
TableCommitment[] memory result
)
{
uint256 numTableCommitments = tableCommitments.length;
result = new TableCommitment[](numTableCommitments);
for (uint256 i = 0; i < numTableCommitments; ++i) {
result[i] = deserializeTableCommitment(tableCommitments[i]);
}
}
function deserializeProofPlanPrefix(bytes calldata plan)
internal
pure
returns (
// tableNameHashes[tableId] = tableNameHash
bytes32[] memory tableNameHashes,
// columnTableIndexes[columnId] = tableId
uint64[] memory columnTableIndexes,
// columnNameHashes[columnId] = columnNameHash
bytes32[] memory columnNameHashes
)
{
assembly {
function exclude_coverage_start_read_data_type() {} // solhint-disable-line no-empty-blocks
function read_data_type(ptr) -> ptr_out, data_type {
data_type := shr(UINT32_PADDING_BITS, calldataload(ptr))
ptr_out := add(ptr, UINT32_SIZE)
switch data_type
case 0 { case_const(0, DATA_TYPE_BOOLEAN_VARIANT) }
case 2 { case_const(2, DATA_TYPE_TINYINT_VARIANT) }
case 3 { case_const(3, DATA_TYPE_SMALLINT_VARIANT) }
case 4 { case_const(4, DATA_TYPE_INT_VARIANT) }
case 5 { case_const(5, DATA_TYPE_BIGINT_VARIANT) }
case 7 { case_const(7, DATA_TYPE_VARCHAR_VARIANT) }
case 8 {
case_const(8, DATA_TYPE_DECIMAL75_VARIANT)
ptr_out := add(ptr_out, UINT8_SIZE) // Skip precision
ptr_out := add(ptr_out, INT8_SIZE) // Skip scale
}
case 9 {
case_const(9, DATA_TYPE_TIMESTAMP_VARIANT)
ptr_out := add(ptr_out, UINT32_SIZE) // Skip timeunit
ptr_out := add(ptr_out, INT32_SIZE) // Skip timezone
}
case 10 { case_const(10, DATA_TYPE_SCALAR_VARIANT) }
case 11 { case_const(11, DATA_TYPE_VARBINARY_VARIANT) }
default { err(ERR_UNSUPPORTED_DATA_TYPE_VARIANT) }
}
function exclude_coverage_stop_read_data_type() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_case_const() {} // solhint-disable-line no-empty-blocks
function case_const(lhs, rhs) {
if sub(lhs, rhs) { err(ERR_INCORRECT_CASE_CONST) }
}
function exclude_coverage_stop_case_const() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_err() {} // solhint-disable-line no-empty-blocks
function err(code) {
mstore(0, code)
revert(28, 4)
}
function exclude_coverage_stop_err() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_hash_string() {} // solhint-disable-line no-empty-blocks
function hash_string(ptr, free_ptr) -> ptr_out, free_ptr_out {
let name_len := shr(UINT64_PADDING_BITS, calldataload(ptr))
ptr := add(ptr, UINT64_SIZE)
// TODO: This line should probably be using the FREE_PTR directly, instead of having it passed in the function.
// This is a little dangerous as it is.
calldatacopy(free_ptr, ptr, name_len)
mstore(free_ptr, keccak256(free_ptr, name_len))
ptr_out := add(ptr, name_len)
free_ptr_out := add(free_ptr, WORD_SIZE)
}
function exclude_coverage_stop_hash_string() {} // solhint-disable-line no-empty-blocks
let ptr := plan.offset
let free_ptr := mload(FREE_PTR)
// tables.len() (usize) is the number of tables
let num_tables := shr(UINT64_PADDING_BITS, calldataload(ptr))
ptr := add(ptr, UINT64_SIZE)
// allocating space for table names
tableNameHashes := free_ptr
mstore(free_ptr, num_tables)
free_ptr := add(free_ptr, WORD_SIZE)
// for each table
for {} num_tables { num_tables := sub(num_tables, 1) } { ptr, free_ptr := hash_string(ptr, free_ptr) }
// done allocating space for table names
// columns.len() (usize) is the number of columns
let num_columns := shr(UINT64_PADDING_BITS, calldataload(ptr))
ptr := add(ptr, UINT64_SIZE)
// allocating space for column table indexes
columnTableIndexes := free_ptr
let index_ptr := free_ptr
// initializing length of column table indexes
mstore(index_ptr, num_columns)
index_ptr := add(index_ptr, WORD_SIZE)
free_ptr := add(index_ptr, mul(num_columns, WORD_SIZE))
// done allocating space for column table indexes
// allocating space for column names
columnNameHashes := free_ptr
// initializing length of column names
mstore(free_ptr, num_columns)
free_ptr := add(free_ptr, WORD_SIZE)
// for each column
for {} num_columns { num_columns := sub(num_columns, 1) } {
// column[i].0 (usize) is the table id. We store it in the columnTableIndexes array
mstore(index_ptr, shr(UINT64_PADDING_BITS, calldataload(ptr)))
ptr := add(ptr, UINT64_SIZE)
index_ptr := add(index_ptr, WORD_SIZE)
ptr, free_ptr := hash_string(ptr, free_ptr)
let data_type
ptr, data_type := read_data_type(ptr)
}
// done allocating space for column names
mstore(FREE_PTR, free_ptr)
}
}
/// @notice Internal function to get the relevant commitments
/// @dev validates that all commitments are found
/// @return commitments the commitments in the order of the columns
function getRelevantCommitments(
uint64[] memory columnTableIndexes,
bytes32[] memory columnNameHashes,
TableCommitment[] memory tableCommitments
) internal pure returns (uint256[] memory commitments) {
uint256 numColumns = columnTableIndexes.length;
commitments = new uint256[](numColumns * 2);
uint256 commitmentsFreePtr;
assembly {
commitmentsFreePtr := add(commitments, 0x20)
}
for (uint256 i = 0; i < numColumns; ++i) {
uint64 columnTableIndex = columnTableIndexes[i];
bytes32 columnNameHash = columnNameHashes[i];
if (!(columnTableIndex < tableCommitments.length)) {
revert Errors.CommitmentsNotFound();
}
TableCommitment memory tableCommitment = tableCommitments[columnTableIndex];
uint256 commitmentsPtr = tableCommitment.commitmentsPtr;
bool found = false;
uint256 columnNameHashesLength = tableCommitment.columnNameHashes.length;
for (uint256 j = 0; j < columnNameHashesLength; ++j) {
if (tableCommitment.columnNameHashes[j] == columnNameHash) {
assembly {
calldatacopy(commitmentsFreePtr, add(commitmentsPtr, mul(j, WORDX2_SIZE)), WORDX2_SIZE)
commitmentsFreePtr := add(commitmentsFreePtr, WORDX2_SIZE)
}
found = true;
break;
}
}
if (!found) {
revert Errors.CommitmentsNotFound();
}
}
}
function getTableLengths(TableCommitment[] memory tableCommitments)
private
pure
returns (uint256[] memory tableLengths)
{
uint256 numTables = tableCommitments.length;
tableLengths = new uint256[](numTables);
for (uint256 i = 0; i < numTables; ++i) {
tableLengths[i] = tableCommitments[i].tableLength;
}
}
function getCommitmentsAndLength(bytes calldata queryPlan, bytes[] calldata tableCommitmentsAsBytes)
internal
pure
returns (uint256[] memory __tableLengths, uint256[] memory __commitments)
{
TableCommitment[] memory tableCommitments = deserializeTableCommitments(tableCommitmentsAsBytes);
(, uint64[] memory columnTableIndexes, bytes32[] memory columnNameHashes) =
deserializeProofPlanPrefix(queryPlan);
// construct `uint256[] memory commitments` and validate that all commitments are found
uint256[] memory commitments = getRelevantCommitments(columnTableIndexes, columnNameHashes, tableCommitments);
// construct `uint256[] memory tableLengths`
uint256[] memory tableLengths = getTableLengths(tableCommitments);
__tableLengths = tableLengths;
__commitments = commitments;
}
function __internalVerify(
bytes calldata __result,
bytes calldata __plan,
uint256[] memory __placeholderParameters,
bytes calldata __proof,
uint256[] memory __tableLengths,
uint256[] memory __commitments
) public view {
assembly {
function exclude_coverage_start_err() {} // solhint-disable-line no-empty-blocks
function err(code) {
mstore(0, code)
revert(28, 4)
}
function exclude_coverage_stop_err() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_mulmod_bn254() {} // solhint-disable-line no-empty-blocks
function mulmod_bn254(lhs, rhs) -> product {
product := mulmod(lhs, rhs, MODULUS)
}
function exclude_coverage_stop_mulmod_bn254() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_log2_up() {} // solhint-disable-line no-empty-blocks
function log2_up(value) -> exponent {
if value { value := sub(value, 1) }
exponent := 1
if gt(value, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {
exponent := add(exponent, 128)
value := shr(128, value)
}
if gt(value, 0xFFFFFFFFFFFFFFFF) {
exponent := add(exponent, 64)
value := shr(64, value)
}
if gt(value, 0xFFFFFFFF) {
exponent := add(exponent, 32)
value := shr(32, value)
}
if gt(value, 0xFFFF) {
exponent := add(exponent, 16)
value := shr(16, value)
}
if gt(value, 0xFF) {
exponent := add(exponent, 8)
value := shr(8, value)
}
if gt(value, 0xF) {
exponent := add(exponent, 4)
value := shr(4, value)
}
if gt(value, 0x3) {
exponent := add(exponent, 2)
value := shr(2, value)
}
if gt(value, 0x1) {
exponent := add(exponent, 1)
value := shr(1, value)
}
}
function exclude_coverage_stop_log2_up() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_uint64_array() {} // solhint-disable-line no-empty-blocks
function read_uint64_array(source_ptr) -> source_ptr_out, array_ptr {
array_ptr := mload(FREE_PTR)
let length := shr(UINT64_PADDING_BITS, calldataload(source_ptr))
mstore(array_ptr, length)
source_ptr := add(source_ptr, UINT64_SIZE)
let tmp_ptr := add(array_ptr, WORD_SIZE)
for {} length { length := sub(length, 1) } {
mstore(tmp_ptr, shr(UINT64_PADDING_BITS, calldataload(source_ptr)))
source_ptr := add(source_ptr, UINT64_SIZE)
tmp_ptr := add(tmp_ptr, WORD_SIZE)
}
mstore(FREE_PTR, tmp_ptr)
source_ptr_out := source_ptr
}
function exclude_coverage_stop_read_uint64_array() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_uint64_array_as_uint512_array() {} // solhint-disable-line no-empty-blocks
function read_uint64_array_as_uint512_array(source_ptr) -> source_ptr_out, array_ptr {
array_ptr := mload(FREE_PTR)
let length := shr(UINT64_PADDING_BITS, calldataload(source_ptr))
mstore(array_ptr, length)
source_ptr := add(source_ptr, UINT64_SIZE)
let target_ptr := add(array_ptr, WORD_SIZE)
for {} length { length := sub(length, 1) } {
mstore(target_ptr, shr(UINT64_PADDING_BITS, calldataload(source_ptr)))
mstore(add(target_ptr, WORD_SIZE), 0)
source_ptr := add(source_ptr, UINT64_SIZE)
target_ptr := add(target_ptr, WORDX2_SIZE)
}
mstore(FREE_PTR, target_ptr)
source_ptr_out := source_ptr
}
function exclude_coverage_stop_read_uint64_array_as_uint512_array() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_word_array() {} // solhint-disable-line no-empty-blocks
function read_word_array(source_ptr) -> source_ptr_out, array_ptr {
array_ptr := mload(FREE_PTR)
let length := shr(UINT64_PADDING_BITS, calldataload(source_ptr))
mstore(array_ptr, length)
source_ptr := add(source_ptr, UINT64_SIZE)
let target_ptr := add(array_ptr, WORD_SIZE)
let copy_size := mul(length, WORD_SIZE)
calldatacopy(target_ptr, source_ptr, copy_size)
mstore(FREE_PTR, add(target_ptr, copy_size))
source_ptr_out := add(source_ptr, copy_size)
}
function exclude_coverage_stop_read_word_array() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_word_array_as_uint512_array() {} // solhint-disable-line no-empty-blocks
function read_word_array_as_uint512_array(input_array_ptr) -> array_ptr {
array_ptr := mload(FREE_PTR)
let length := mload(input_array_ptr)
mstore(array_ptr, length)
input_array_ptr := add(input_array_ptr, WORD_SIZE)
let target_ptr := add(array_ptr, WORD_SIZE)
for {} length { length := sub(length, 1) } {
mstore(target_ptr, mload(input_array_ptr))
mstore(add(target_ptr, WORD_SIZE), 0)
input_array_ptr := add(input_array_ptr, WORD_SIZE)
target_ptr := add(target_ptr, WORDX2_SIZE)
}
mstore(FREE_PTR, target_ptr)
}
function exclude_coverage_stop_read_word_array_as_uint512_array() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_wordx2_array() {} // solhint-disable-line no-empty-blocks
function read_wordx2_array(source_ptr) -> source_ptr_out, array_ptr {
// Allocate space for array length
array_ptr := mload(FREE_PTR)
let length := shr(UINT64_PADDING_BITS, calldataload(source_ptr))
mstore(array_ptr, length)
source_ptr := add(source_ptr, UINT64_SIZE)
let target_ptr := add(array_ptr, WORD_SIZE)
let copy_size := mul(length, WORDX2_SIZE)
calldatacopy(target_ptr, source_ptr, copy_size)
mstore(FREE_PTR, add(target_ptr, copy_size))
source_ptr_out := add(source_ptr, copy_size)
}
function exclude_coverage_stop_read_wordx2_array() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_evaluations_with_length() {} // solhint-disable-line no-empty-blocks
function compute_evaluations_with_length(evaluation_point_ptr, array_ptr) {
let num_vars := mload(evaluation_point_ptr)
let x := add(evaluation_point_ptr, WORD_SIZE)
let array_len := mload(array_ptr)
array_ptr := add(array_ptr, WORD_SIZE)
for {} array_len { array_len := sub(array_len, 1) } {
mstore(
add(array_ptr, WORD_SIZE), compute_truncated_lagrange_basis_sum(mload(array_ptr), x, num_vars)
)
array_ptr := add(array_ptr, WORDX2_SIZE)
}
}
function exclude_coverage_stop_compute_evaluations_with_length() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_truncated_lagrange_basis_sum() {} // solhint-disable-line no-empty-blocks
function compute_truncated_lagrange_basis_sum(length, x_ptr, num_vars) -> result {
result := 0
// Invariant that holds within the for loop:
// 0 <= result <= modulus + 1
// This invariant reduces modulus operations.
for {} num_vars {} {
switch and(length, 1)
case 0 { result := mulmod(result, sub(MODULUS_PLUS_ONE, mod(mload(x_ptr), MODULUS)), MODULUS) }
default {
result := sub(MODULUS_PLUS_ONE, mulmod(sub(MODULUS_PLUS_ONE, result), mload(x_ptr), MODULUS))
}
num_vars := sub(num_vars, 1)
length := shr(1, length)
x_ptr := add(x_ptr, WORD_SIZE)
}
switch length
case 0 { result := mod(result, MODULUS) }
default { result := 1 }
}
function exclude_coverage_stop_compute_truncated_lagrange_basis_sum() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_rho_evaluations() {} // solhint-disable-line no-empty-blocks
function compute_rho_evaluations(evaluation_point_ptr, array_ptr) {
let array_len := mload(array_ptr)
for {} array_len { array_len := sub(array_len, 1) } {
array_ptr := add(array_ptr, WORD_SIZE)
let length := mload(array_ptr)
let evaluation_vec := compute_evaluation_vec(length, evaluation_point_ptr)
let product := 0
for {} length {} {
let i := sub(length, 1)
product := addmod_bn254(product, mulmod_bn254(i, mload(add(evaluation_vec, mul(i, WORD_SIZE)))))
length := i
}
mstore(array_ptr, product)
}
}
function exclude_coverage_stop_compute_rho_evaluations() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_evaluation_vec() {} // solhint-disable-line no-empty-blocks
function compute_evaluation_vec(length, evaluation_point_ptr) -> evaluations_ptr {
evaluations_ptr := mload(FREE_PTR)
mstore(FREE_PTR, add(evaluations_ptr, mul(length, WORD_SIZE)))
mstore(evaluations_ptr, 1)
let num_vars := mload(evaluation_point_ptr)
if gt(length, shl(num_vars, 1)) { err(ERR_EVALUATION_LENGTH_TOO_LARGE) }
for { let len := 1 } num_vars { num_vars := sub(num_vars, 1) } {
let x := mod(mload(add(evaluation_point_ptr, mul(num_vars, WORD_SIZE))), MODULUS)
let one_minus_x := sub(MODULUS_PLUS_ONE, x)
len := mul(len, 2)
if gt(len, length) { len := length }
for { let l := len } l {} {
l := sub(l, 1)
let to_ptr := add(evaluations_ptr, mul(l, WORD_SIZE))
let from_ptr := add(evaluations_ptr, mul(shr(1, l), WORD_SIZE))
switch mod(l, 2)
case 0 { mstore(to_ptr, mulmod(mload(from_ptr), one_minus_x, MODULUS)) }
case 1 { mstore(to_ptr, mulmod(mload(from_ptr), x, MODULUS)) }
}
}
}
function exclude_coverage_stop_compute_evaluation_vec() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_addmod_bn254() {} // solhint-disable-line no-empty-blocks
function addmod_bn254(lhs, rhs) -> sum {
sum := addmod(lhs, rhs, MODULUS)
}
function exclude_coverage_stop_addmod_bn254() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_truncated_lagrange_basis_inner_product() {} // solhint-disable-line no-empty-blocks
function compute_truncated_lagrange_basis_inner_product(length, x_ptr, y_ptr, num_vars) -> result {
let part := 0 // This is g in the formulas
result := 1 // This is h in the formulas
for {} num_vars {} {
let x := mload(x_ptr)
let y := mload(y_ptr)
let xy := mulmod(x, y, MODULUS)
// let c := 1 - x
// let d := 1 - y
let cd := sub(add(MODULUS_PLUS_ONE, xy), addmod(x, y, MODULUS))
switch and(length, 1)
case 0 { part := mulmod(part, cd, MODULUS) }
default { part := add(mulmod(result, cd, MODULUS), mulmod(part, xy, MODULUS)) }
result := mulmod(result, add(cd, xy), MODULUS)
num_vars := sub(num_vars, 1)
length := shr(1, length)
x_ptr := add(x_ptr, WORD_SIZE)
y_ptr := add(y_ptr, WORD_SIZE)
}
if iszero(length) { result := mod(part, MODULUS) } // we return g in "short" cases
}
function exclude_coverage_stop_compute_truncated_lagrange_basis_inner_product() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_append_array() {} // solhint-disable-line no-empty-blocks
function append_array(transcript_ptr, array_ptr) {
let array_len := mload(array_ptr)
mstore(array_ptr, mload(transcript_ptr))
mstore(transcript_ptr, keccak256(array_ptr, mul(add(array_len, 1), WORD_SIZE)))
mstore(array_ptr, array_len)
}
function exclude_coverage_stop_append_array() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_append_calldata() {} // solhint-disable-line no-empty-blocks
function append_calldata(transcript_ptr, offset, size) {
let free_ptr := mload(FREE_PTR)
mstore(free_ptr, mload(transcript_ptr))
calldatacopy(add(free_ptr, WORD_SIZE), offset, size)
mstore(transcript_ptr, keccak256(free_ptr, add(size, WORD_SIZE)))
}
function exclude_coverage_stop_append_calldata() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_draw_challenges() {} // solhint-disable-line no-empty-blocks
function draw_challenges(transcript_ptr, count) -> result_ptr {
// allocate `count` words
let free_ptr := mload(FREE_PTR)
mstore(FREE_PTR, add(free_ptr, mul(add(count, 1), WORD_SIZE)))
// result is the pointer to the first word
result_ptr := free_ptr
// store count in the first word
mstore(result_ptr, count)
// increment to next word
free_ptr := add(free_ptr, WORD_SIZE)
// first challenge is the current transcript state
let challenge := mload(transcript_ptr)
for {} count {} {
mstore(transcript_ptr, challenge)
// store challenge in next word
mstore(free_ptr, and(challenge, MODULUS_MASK))
// hash challenge to get next challenge
challenge := keccak256(transcript_ptr, WORD_SIZE)
// increment to next word
free_ptr := add(free_ptr, WORD_SIZE)
// decrement count
count := sub(count, 1)
}
// The last (unused) challenge is the current state of the transcript
mstore(transcript_ptr, challenge)
}
function exclude_coverage_stop_draw_challenges() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_check_aggregate_evaluation() {} // solhint-disable-line no-empty-blocks
function builder_check_aggregate_evaluation(builder_ptr) {
if mload(add(builder_ptr, BUILDER_AGGREGATE_EVALUATION_OFFSET)) {
err(ERR_AGGREGATE_EVALUATION_MISMATCH)
}
}
function exclude_coverage_stop_builder_check_aggregate_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_chi_evaluations() {} // solhint-disable-line no-empty-blocks
function builder_get_chi_evaluations(builder_ptr) -> values_ptr {
values_ptr := mload(add(builder_ptr, BUILDER_CHI_EVALUATIONS_OFFSET))
}
function exclude_coverage_stop_builder_get_chi_evaluations() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_column_evaluations() {} // solhint-disable-line no-empty-blocks
function builder_get_column_evaluations(builder_ptr) -> values_ptr {
values_ptr := mload(add(builder_ptr, BUILDER_COLUMN_EVALUATIONS_OFFSET))
}
function exclude_coverage_stop_builder_get_column_evaluations() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_final_round_commitments() {} // solhint-disable-line no-empty-blocks
function builder_get_final_round_commitments(builder_ptr) -> values_ptr {
values_ptr := mload(add(builder_ptr, BUILDER_FINAL_ROUND_COMMITMENTS_OFFSET))
}
function exclude_coverage_stop_builder_get_final_round_commitments() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_final_round_mles() {} // solhint-disable-line no-empty-blocks
function builder_get_final_round_mles(builder_ptr) -> values_ptr {
values_ptr := mload(add(builder_ptr, BUILDER_FINAL_ROUND_MLES_OFFSET))
}
function exclude_coverage_stop_builder_get_final_round_mles() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_first_round_commitments() {} // solhint-disable-line no-empty-blocks
function builder_get_first_round_commitments(builder_ptr) -> values_ptr {
values_ptr := mload(add(builder_ptr, BUILDER_FIRST_ROUND_COMMITMENTS_OFFSET))
}
function exclude_coverage_stop_builder_get_first_round_commitments() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_first_round_mles() {} // solhint-disable-line no-empty-blocks
function builder_get_first_round_mles(builder_ptr) -> values_ptr {
values_ptr := mload(add(builder_ptr, BUILDER_FIRST_ROUND_MLES_OFFSET))
}
function exclude_coverage_stop_builder_get_first_round_mles() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_rho_evaluations() {} // solhint-disable-line no-empty-blocks
function builder_get_rho_evaluations(builder_ptr) -> values_ptr {
values_ptr := mload(add(builder_ptr, BUILDER_RHO_EVALUATIONS_OFFSET))
}
function exclude_coverage_stop_builder_get_rho_evaluations() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_new() {} // solhint-disable-line no-empty-blocks
function builder_new() -> builder_ptr {
builder_ptr := mload(FREE_PTR)
mstore(FREE_PTR, add(builder_ptr, VERIFICATION_BUILDER_SIZE))
}
function exclude_coverage_stop_builder_new() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_aggregate_evaluation() {} // solhint-disable-line no-empty-blocks
function builder_set_aggregate_evaluation(builder_ptr, value) {
mstore(add(builder_ptr, BUILDER_AGGREGATE_EVALUATION_OFFSET), value)
}
function exclude_coverage_stop_builder_set_aggregate_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_bit_distributions() {} // solhint-disable-line no-empty-blocks
function builder_set_bit_distributions(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_FINAL_ROUND_BIT_DISTRIBUTIONS_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_bit_distributions() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_challenges() {} // solhint-disable-line no-empty-blocks
function builder_set_challenges(builder_ptr, challenges_ptr) {
mstore(add(builder_ptr, BUILDER_CHALLENGES_OFFSET), challenges_ptr)
}
function exclude_coverage_stop_builder_set_challenges() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_chi_evaluations() {} // solhint-disable-line no-empty-blocks
function builder_set_chi_evaluations(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_CHI_EVALUATIONS_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_chi_evaluations() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_column_evaluations() {} // solhint-disable-line no-empty-blocks
function builder_set_column_evaluations(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_COLUMN_EVALUATIONS_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_column_evaluations() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_constraint_multipliers() {} // solhint-disable-line no-empty-blocks
function builder_set_constraint_multipliers(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_CONSTRAINT_MULTIPLIERS_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_constraint_multipliers() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_final_round_commitments() {} // solhint-disable-line no-empty-blocks
function builder_set_final_round_commitments(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_FINAL_ROUND_COMMITMENTS_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_final_round_commitments() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_final_round_mles() {} // solhint-disable-line no-empty-blocks
function builder_set_final_round_mles(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_FINAL_ROUND_MLES_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_final_round_mles() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_first_round_commitments() {} // solhint-disable-line no-empty-blocks
function builder_set_first_round_commitments(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_FIRST_ROUND_COMMITMENTS_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_first_round_commitments() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_first_round_mles() {} // solhint-disable-line no-empty-blocks
function builder_set_first_round_mles(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_FIRST_ROUND_MLES_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_first_round_mles() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_max_degree() {} // solhint-disable-line no-empty-blocks
function builder_set_max_degree(builder_ptr, value) {
mstore(add(builder_ptr, BUILDER_MAX_DEGREE_OFFSET), value)
}
function exclude_coverage_stop_builder_set_max_degree() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_placeholder_parameters() {} // solhint-disable-line no-empty-blocks
function builder_set_placeholder_parameters(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_PLACEHOLDER_PARAMETERS_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_placeholder_parameters() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_rho_evaluations() {} // solhint-disable-line no-empty-blocks
function builder_set_rho_evaluations(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_RHO_EVALUATIONS_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_rho_evaluations() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_row_multipliers_evaluation() {} // solhint-disable-line no-empty-blocks
function builder_set_row_multipliers_evaluation(builder_ptr, value) {
mstore(add(builder_ptr, BUILDER_ROW_MULTIPLIERS_EVALUATION_OFFSET), value)
}
function exclude_coverage_stop_builder_set_row_multipliers_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_singleton_chi_evaluation() {} // solhint-disable-line no-empty-blocks
function builder_set_singleton_chi_evaluation(builder_ptr, value) {
mstore(add(builder_ptr, BUILDER_SINGLETON_CHI_EVALUATION_OFFSET), value)
}
function exclude_coverage_stop_builder_set_singleton_chi_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_set_table_chi_evaluations() {} // solhint-disable-line no-empty-blocks
function builder_set_table_chi_evaluations(builder_ptr, values_ptr) {
mstore(add(builder_ptr, BUILDER_TABLE_CHI_EVALUATIONS_OFFSET), values_ptr)
}
function exclude_coverage_stop_builder_set_table_chi_evaluations() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_batch_pcs() {} // solhint-disable-line no-empty-blocks
function batch_pcs(args_ptr, transcript_ptr, commitments_ptr, evaluations_ptr, batch_eval) -> batch_eval_out
{
let num_commitments := mload(commitments_ptr)
commitments_ptr := add(commitments_ptr, WORD_SIZE)
let num_evaluations := mload(evaluations_ptr)
evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
if sub(num_commitments, num_evaluations) { err(ERR_PCS_BATCH_LENGTH_MISMATCH) }
for {} num_commitments { num_commitments := sub(num_commitments, 1) } {
let challenge := draw_challenge(transcript_ptr)
constant_ec_mul_add_assign(
args_ptr, mload(commitments_ptr), mload(add(commitments_ptr, WORD_SIZE)), challenge
)
commitments_ptr := add(commitments_ptr, WORDX2_SIZE)
batch_eval := addmod_bn254(batch_eval, mulmod_bn254(mload(evaluations_ptr), challenge))
evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
}
batch_eval_out := mod(batch_eval, MODULUS)
}
function exclude_coverage_stop_batch_pcs() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_draw_challenge() {} // solhint-disable-line no-empty-blocks
function draw_challenge(transcript_ptr) -> result {
result := and(mload(transcript_ptr), MODULUS_MASK)
mstore(transcript_ptr, keccak256(transcript_ptr, WORD_SIZE))
}
function exclude_coverage_stop_draw_challenge() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_constant_ec_mul_add_assign() {} // solhint-disable-line no-empty-blocks
function constant_ec_mul_add_assign(args_ptr, c_x, c_y, scalar) {
mstore(add(args_ptr, WORDX2_SIZE), c_x)
mstore(add(args_ptr, WORDX3_SIZE), c_y)
ec_mul_assign(add(args_ptr, WORDX2_SIZE), scalar)
ec_add(args_ptr)
}
function exclude_coverage_stop_constant_ec_mul_add_assign() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_ec_add() {} // solhint-disable-line no-empty-blocks
function ec_add(args_ptr) {
if iszero(staticcall(ECADD_GAS, ECADD_ADDRESS, args_ptr, WORDX4_SIZE, args_ptr, WORDX2_SIZE)) {
err(ERR_INVALID_EC_ADD_INPUTS)
}
}
function exclude_coverage_stop_ec_add() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_ec_mul_assign() {} // solhint-disable-line no-empty-blocks
function ec_mul_assign(args_ptr, scalar) {
mstore(add(args_ptr, WORDX2_SIZE), scalar)
ec_mul(args_ptr)
}
function exclude_coverage_stop_ec_mul_assign() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_ec_mul() {} // solhint-disable-line no-empty-blocks
function ec_mul(args_ptr) {
if iszero(staticcall(ECMUL_GAS, ECMUL_ADDRESS, args_ptr, WORDX3_SIZE, args_ptr, WORDX2_SIZE)) {
err(ERR_INVALID_EC_MUL_INPUTS)
}
}
function exclude_coverage_stop_ec_mul() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_verify_hyperkzg() {} // solhint-disable-line no-empty-blocks
function verify_hyperkzg(proof_ptr, transcript_ptr, commitment_ptr, x, y) {
function v_ptr(ptr, l) -> result {
result := add(ptr, add(UINT64_SIZE, sub(mul(WORDX2_SIZE, l), WORDX2_SIZE)))
}
function w_ptr(ptr, l) -> result {
result := add(ptr, add(UINT64_SIZE, sub(mul(WORDX5_SIZE, l), WORDX2_SIZE)))
}
let ell := mload(x)
// if ell == 0, then error
if iszero(ell) { err(ERR_HYPER_KZG_EMPTY_POINT) }
{
let com_len := shr(UINT64_PADDING_BITS, calldataload(proof_ptr))
if sub(com_len, sub(ell, 1)) { err(ERR_HYPER_KZG_PROOF_SIZE_MISMATCH) }
proof_ptr := add(proof_ptr, UINT64_SIZE)
let v_len := shr(UINT64_PADDING_BITS, calldataload(add(proof_ptr, mul(WORDX2_SIZE, sub(ell, 1)))))
if sub(v_len, ell) { err(ERR_HYPER_KZG_PROOF_SIZE_MISMATCH) }
}
// Step 1: Run the transcript
// WARNING: The public inputs (x, y, the commitments, digest of the KZG SRS, degree bound, etc) are
// NOT included in the transcript and need to be added, either explicitly or implicitly,
// before calling this function
let r, q, d :=
run_transcript(proof_ptr, v_ptr(proof_ptr, ell), w_ptr(proof_ptr, ell), transcript_ptr, ell)
// Step 2: Compute bivariate evaluation
let b := bivariate_evaluation(v_ptr(proof_ptr, ell), q, d, ell)
// Step 3: Check v consistency
check_v_consistency(v_ptr(proof_ptr, ell), r, x, y)
// Allocate scratch space for L, R, and the pairing check
let scratch := mload(FREE_PTR)
// Step 4: Compute L
compute_gl_msm(proof_ptr, sub(ell, 1), w_ptr(proof_ptr, ell), commitment_ptr, r, q, d, b, scratch)
// Step 5: Compute R
univariate_group_evaluation(w_ptr(proof_ptr, ell), d, 3, add(scratch, WORDX6_SIZE))
// Step 6: Verify the pairing equation
mstore(add(scratch, WORDX2_SIZE), G2_NEG_GEN_X_IMAG)
mstore(add(scratch, WORDX3_SIZE), G2_NEG_GEN_X_REAL)
mstore(add(scratch, WORDX4_SIZE), G2_NEG_GEN_Y_IMAG)
mstore(add(scratch, WORDX5_SIZE), G2_NEG_GEN_Y_REAL)
mstore(add(scratch, WORDX8_SIZE), VK_TAU_HX_IMAG)
mstore(add(scratch, WORDX9_SIZE), VK_TAU_HX_REAL)
mstore(add(scratch, WORDX10_SIZE), VK_TAU_HY_IMAG)
mstore(add(scratch, WORDX11_SIZE), VK_TAU_HY_REAL)
if iszero(ec_pairing_x2(scratch)) { err(ERR_HYPER_KZG_PAIRING_CHECK_FAILED) }
}
function exclude_coverage_stop_verify_hyperkzg() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_bivariate_evaluation() {} // solhint-disable-line no-empty-blocks
function bivariate_evaluation(v_ptr, q, d, ell) -> b {
b := 0
let v_stack := add(v_ptr, mul(WORDX3_SIZE, ell))
for {} ell { ell := sub(ell, 1) } {
// tmp = v2i
v_stack := sub(v_stack, WORD_SIZE)
let tmp := calldataload(v_stack)
// tmp = v2i * d
tmp := mulmod_bn254(tmp, d)
// tmp += v1i
v_stack := sub(v_stack, WORD_SIZE)
tmp := addmod_bn254(tmp, calldataload(v_stack))
// tmp *= d
tmp := mulmod_bn254(tmp, d)
// tmp += v0i
v_stack := sub(v_stack, WORD_SIZE)
tmp := addmod_bn254(tmp, calldataload(v_stack))
// b *= q
b := mulmod_bn254(b, q)
// b += tmp
b := addmod_bn254(b, tmp)
}
}
function exclude_coverage_stop_bivariate_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_univariate_group_evaluation() {} // solhint-disable-line no-empty-blocks
function univariate_group_evaluation(g_ptr, e, length, scratch) {
switch length
case 0 {
mstore(scratch, 0)
mstore(add(scratch, WORD_SIZE), 0)
}
default {
length := sub(length, 1)
g_ptr := add(g_ptr, mul(length, WORDX2_SIZE))
// result = g.pop()
calldatacopy(scratch, g_ptr, WORDX2_SIZE)
for {} length { length := sub(length, 1) } {
// g_l *= e
ec_mul_assign(scratch, e)
// g_l += com.pop()
g_ptr := sub(g_ptr, WORDX2_SIZE)
calldata_ec_add_assign(scratch, g_ptr)
}
}
}
function exclude_coverage_stop_univariate_group_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_calldata_ec_add_assign() {} // solhint-disable-line no-empty-blocks
function calldata_ec_add_assign(args_p
Submitted on: 2025-11-04 11:10:47
Comments
Log in to comment.
No comments yet.