Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
PoSQLVerifier
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 4294967295 runs
Other Settings:
prague EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
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;
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;
}
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;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
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);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
/// @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 Payment info for queries
/// @param paymentAmount Funds held when pending fulfillment
/// @param refundTo Recipient of refunds or excess payment returns
/// @param timeout Timestamp after which cancellation is allowed
struct Payment {
uint256 paymentAmount;
address refundTo;
uint64 timeout;
}
/// @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 payment Payment details
event QueryRequested(
bytes32 indexed queryId,
uint64 indexed queryNonce,
address indexed requester,
Query query,
Callback callback,
Payment payment
);
/// @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();
/// @notice Thrown when a query cancellation is attempted before the timeout
error QueryTimeoutNotReached();
/// @notice Thrown when the query version is not supported by the router
error UnsupportedQueryVersion();
/// @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
/// @param payment Payment struct for the original request.
function cancelQuery(bytes32 queryId, Payment calldata payment) 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 payment Payment struct containing payment details.
/// @return queryId Unique ID for this query.
function requestQuery(Query calldata query, Callback calldata callback, Payment calldata payment)
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 payment Payment 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,
Payment calldata payment,
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);
}// 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_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_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 := 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_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_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_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_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_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_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_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_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_run_transcript() {} // solhint-disable-line no-empty-blocks
function run_transcript(com_ptr, v_ptr, w_ptr, transcript_ptr, ell) -> r, q, d {
append_calldata(transcript_ptr, com_ptr, mul(WORDX2_SIZE, sub(ell, 1)))
r := draw_challenge(transcript_ptr)
append_calldata(transcript_ptr, v_ptr, mul(WORDX3_SIZE, ell))
q := draw_challenge(transcript_ptr)
append_calldata(transcript_ptr, w_ptr, WORDX6_SIZE)
d := draw_challenge(transcript_ptr)
}
function exclude_coverage_stop_run_transcript() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_check_v_consistency() {} // solhint-disable-line no-empty-blocks
function check_v_consistency(v_ptr, r, x, y) {
let ell := mload(x)
let v_stack := add(v_ptr, mul(WORDX3_SIZE, ell))
x := add(x, mul(WORD_SIZE, add(ell, 1)))
let last_v2 := y
for {} ell { ell := sub(ell, 1) } {
v_stack := sub(v_stack, WORD_SIZE)
let v2i := calldataload(v_stack)
v_stack := sub(v_stack, WORD_SIZE)
let v1i := calldataload(v_stack)
v_stack := sub(v_stack, WORD_SIZE)
let v0i := calldataload(v_stack)
x := sub(x, WORD_SIZE)
let xi := mload(x)
// r * (2 * y + (xi - 1) * (v1i + v0i)) + xi * (v1i - v0i)
if addmod_bn254(
mulmod_bn254(
r,
addmod_bn254(
addmod_bn254(last_v2, last_v2),
mulmod_bn254(submod_bn254(xi, 1), addmod_bn254(v1i, v0i))
)
),
mulmod_bn254(xi, submod_bn254(v1i, v0i))
) { err(ERR_HYPER_KZG_INCONSISTENT_V) }
last_v2 := v2i
}
}
function exclude_coverage_stop_check_v_consistency() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_submod_bn254() {} // solhint-disable-line no-empty-blocks
function submod_bn254(lhs, rhs) -> difference {
difference := addmod(lhs, mulmod(rhs, MODULUS_MINUS_ONE, MODULUS), MODULUS)
}
function exclude_coverage_stop_submod_bn254() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_gl_msm() {} // solhint-disable-line no-empty-blocks
function compute_gl_msm(com_ptr, length, w_ptr, commitment_ptr, r, q, d, b, scratch) {
univariate_group_evaluation(com_ptr, q, length, scratch)
// g_l *= q
ec_mul_assign(scratch, q)
// g_l += commitment
ec_add_assign(scratch, commitment_ptr)
// g_l *= d * (d + 1) + 1
ec_mul_assign(scratch, addmod_bn254(mulmod_bn254(d, addmod_bn254(d, 1)), 1))
// g_l += -G * b
constant_ec_mul_add_assign(scratch, G1_NEG_GEN_X, G1_NEG_GEN_Y, b)
let dr := mulmod_bn254(d, r)
// g_l += w[0] * r
calldata_ec_mul_add_assign(scratch, w_ptr, r)
// g_l += w[1] * -d * r
calldata_ec_mul_add_assign(scratch, add(w_ptr, WORDX2_SIZE), sub(MODULUS, dr))
// g_l += w[2] * (d * r)^2
calldata_ec_mul_add_assign(scratch, add(w_ptr, WORDX4_SIZE), mulmod_bn254(dr, dr))
}
function exclude_coverage_stop_compute_gl_msm() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_ec_add_assign() {} // solhint-disable-line no-empty-blocks
function ec_add_assign(args_ptr, c_ptr) {
mcopy(add(args_ptr, WORDX2_SIZE), c_ptr, WORDX2_SIZE)
ec_add(args_ptr)
}
function exclude_coverage_stop_ec_add_assign() {} // 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_ptr, c_ptr) {
calldatacopy(add(args_ptr, WORDX2_SIZE), c_ptr, WORDX2_SIZE)
ec_add(args_ptr)
}
function exclude_coverage_stop_calldata_ec_add_assign() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_calldata_ec_mul_add_assign() {} // solhint-disable-line no-empty-blocks
function calldata_ec_mul_add_assign(args_ptr, c_ptr, scalar) {
calldatacopy(add(args_ptr, WORDX2_SIZE), c_ptr, WORDX2_SIZE)
ec_mul_assign(add(args_ptr, WORDX2_SIZE), scalar)
ec_add(args_ptr)
}
function exclude_coverage_stop_calldata_ec_mul_add_assign() {} // 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_ec_pairing_x2() {} // solhint-disable-line no-empty-blocks
function ec_pairing_x2(args_ptr) -> success {
if iszero(staticcall(ECPAIRINGX2_GAS, ECPAIRING_ADDRESS, args_ptr, WORDX12_SIZE, args_ptr, WORD_SIZE)) {
err(ERR_INVALID_EC_PAIRING_INPUTS)
}
success := mload(args_ptr)
}
function exclude_coverage_stop_ec_pairing_x2() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_verify_sumcheck_proof() {} // solhint-disable-line no-empty-blocks
function verify_sumcheck_proof(transcript_ptr, proof_ptr, num_vars) ->
proof_ptr_out,
evaluation_point_ptr,
expected_evaluation,
degree
{
append_calldata(transcript_ptr, proof_ptr, UINT64_SIZE)
let sumcheck_length := shr(UINT64_PADDING_BITS, calldataload(proof_ptr))
proof_ptr := add(proof_ptr, UINT64_SIZE)
if or(or(iszero(num_vars), iszero(sumcheck_length)), mod(sumcheck_length, num_vars)) {
err(ERR_INVALID_SUMCHECK_PROOF_SIZE)
}
degree := sub(div(sumcheck_length, num_vars), 1)
expected_evaluation := 0
evaluation_point_ptr := mload(FREE_PTR)
mstore(FREE_PTR, add(evaluation_point_ptr, mul(WORD_SIZE, add(num_vars, 1))))
let evaluation_ptr := evaluation_point_ptr
mstore(evaluation_ptr, num_vars)
evaluation_ptr := add(evaluation_ptr, WORD_SIZE)
for {} num_vars { num_vars := sub(num_vars, 1) } {
append_calldata(transcript_ptr, proof_ptr, mul(WORD_SIZE, add(degree, 1)))
let challenge := and(mload(transcript_ptr), MODULUS_MASK)
mstore(evaluation_ptr, challenge)
evaluation_ptr := add(evaluation_ptr, WORD_SIZE)
let round_evaluation, actual_sum
proof_ptr, round_evaluation, actual_sum := process_round(proof_ptr, degree, challenge)
if sub(expected_evaluation, actual_sum) { err(ERR_ROUND_EVALUATION_MISMATCH) }
expected_evaluation := round_evaluation
}
proof_ptr_out := proof_ptr
}
function exclude_coverage_stop_verify_sumcheck_proof() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_process_round() {} // solhint-disable-line no-empty-blocks
function process_round(proof_ptr, degree, challenge) -> proof_ptr_out, round_evaluation, actual_sum {
let coefficient := mod(calldataload(proof_ptr), MODULUS)
proof_ptr := add(proof_ptr, WORD_SIZE)
round_evaluation := coefficient
actual_sum := coefficient
for {} degree { degree := sub(degree, 1) } {
coefficient := calldataload(proof_ptr)
proof_ptr := add(proof_ptr, WORD_SIZE)
round_evaluation := mulmod_bn254(round_evaluation, challenge)
round_evaluation := addmod_bn254(round_evaluation, coefficient)
actual_sum := addmod_bn254(actual_sum, coefficient)
}
actual_sum := addmod_bn254(actual_sum, coefficient)
proof_ptr_out := proof_ptr
}
function exclude_coverage_stop_process_round() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_get_and_verify_slice_length() {} // solhint-disable-line no-empty-blocks
function get_and_verify_slice_length(plan_ptr, builder_ptr, input_length) ->
plan_ptr_out,
output_length,
output_chi_eval,
selection_eval
{
let expected_skip := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
let expected_max_length
{
let is_fetch_populated := shr(BOOLEAN_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, BOOLEAN_SIZE)
switch is_fetch_populated
case 0 { expected_max_length := input_length }
default {
let fetch := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
expected_max_length := min(add(expected_skip, fetch), input_length)
}
}
output_length, output_chi_eval := builder_consume_chi_evaluation_with_length(builder_ptr)
let actual_skip
actual_skip, selection_eval := builder_consume_chi_evaluation_with_length(builder_ptr)
let max_length, max_eval := builder_consume_chi_evaluation_with_length(builder_ptr)
selection_eval := submod_bn254(max_eval, selection_eval)
if sub(max_length, add(actual_skip, output_length)) { err(ERR_SLICE_OFFSET_SELECTION_SIZE_MISMATCH) }
if sub(min(expected_skip, input_length), actual_skip) { err(ERR_SLICE_OFFSET_PLAN_VALUE_MISMATCH) }
if sub(max_length, expected_max_length) { err(ERR_SLICE_MAX_LENGTH_MISMATCH) }
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_get_and_verify_slice_length() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_slice_folds() {} // solhint-disable-line no-empty-blocks
function compute_slice_folds(builder_ptr, input_evaluations_ptr) -> c_fold, d_fold, evaluations_ptr {
let alpha := builder_consume_challenge(builder_ptr)
let beta := builder_consume_challenge(builder_ptr)
c_fold := mulmod_bn254(alpha, compute_fold(beta, input_evaluations_ptr))
d_fold, evaluations_ptr := fold_first_round_mles(builder_ptr, beta, mload(input_evaluations_ptr))
d_fold := mulmod_bn254(alpha, d_fold)
}
function exclude_coverage_stop_compute_slice_folds() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_slice_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function slice_exec_evaluate(plan_ptr, builder_ptr) ->
plan_ptr_out,
evaluations_ptr,
output_length,
output_chi_eval
{
let c_fold, d_fold, input_chi_eval, selection_eval
{
let input_length, input_evaluations_ptr
plan_ptr, input_evaluations_ptr, input_length, input_chi_eval :=
proof_plan_evaluate(plan_ptr, builder_ptr)
plan_ptr_out, output_length, output_chi_eval, selection_eval :=
get_and_verify_slice_length(plan_ptr, builder_ptr, input_length)
c_fold, d_fold, evaluations_ptr := compute_slice_folds(builder_ptr, input_evaluations_ptr)
}
verify_filter(builder_ptr, c_fold, d_fold, input_chi_eval, output_chi_eval, selection_eval)
}
function exclude_coverage_stop_slice_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_g_in_star_eval_for_aggregate() {} // solhint-disable-line no-empty-blocks
function compute_g_in_star_eval_for_aggregate(plan_ptr, builder_ptr, alpha, beta) ->
plan_ptr_out,
g_in_star_eval_times_selection_eval,
num_group_by_columns,
input_chi_eval,
input_evaluations
{
let input_length
plan_ptr, input_evaluations, input_length, input_chi_eval := proof_plan_evaluate(plan_ptr, builder_ptr)
num_group_by_columns := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
// We can not prove uniqueness for multiple columns yet
if gt(num_group_by_columns, 1) { err(ERR_UNPROVABLE_GROUP_BY) }
plan_ptr := add(plan_ptr, UINT64_SIZE)
// Process group by columns
let g_in_star_eval
plan_ptr, g_in_star_eval :=
fold_log_star_evaluate_from_expr_evals(
plan_ptr, builder_ptr, input_chi_eval, alpha, beta, num_group_by_columns, input_evaluations
)
let selection_eval
plan_ptr, selection_eval :=
proof_expr_evaluate(plan_ptr, builder_ptr, input_chi_eval, input_evaluations)
g_in_star_eval_times_selection_eval := mulmod_bn254(g_in_star_eval, selection_eval)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_compute_g_in_star_eval_for_aggregate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_sum_in_fold_eval_for_aggregate() {} // solhint-disable-line no-empty-blocks
function compute_sum_in_fold_eval_for_aggregate(
plan_ptr, builder_ptr, alpha, beta, input_chi_eval, accessor
) -> plan_ptr_out, sum_in_fold_eval, num_sum_columns {
num_sum_columns := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
plan_ptr, sum_in_fold_eval :=
fold_expr_evals(plan_ptr, builder_ptr, input_chi_eval, beta, num_sum_columns, accessor)
sum_in_fold_eval := addmod_bn254(mulmod_bn254(sum_in_fold_eval, beta), input_chi_eval)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_compute_sum_in_fold_eval_for_aggregate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_g_out_star_eval() {} // solhint-disable-line no-empty-blocks
function compute_g_out_star_eval(
builder_ptr, alpha, beta, output_chi_eval, evaluations_ptr, num_group_by_columns
) -> g_out_star_eval {
let mles
g_out_star_eval, mles :=
fold_log_star_evaluate_from_mles(builder_ptr, alpha, beta, num_group_by_columns, output_chi_eval)
if num_group_by_columns {
let mle := mload(add(mles, WORD_SIZE))
mstore(evaluations_ptr, mle)
evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
monotonic_verify(builder_ptr, alpha, beta, mle, output_chi_eval, 1, 1)
}
}
function exclude_coverage_stop_compute_g_out_star_eval() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_sum_out_fold_eval_for_aggregate() {} // solhint-disable-line no-empty-blocks
function compute_sum_out_fold_eval_for_aggregate(
builder_ptr, alpha, beta, output_chi_eval, num_sum_columns, evaluations_ptr
) -> sum_out_fold_eval {
sum_out_fold_eval := 0
for {} num_sum_columns { num_sum_columns := sub(num_sum_columns, 1) } {
// We increment evaluations_ptr first to avoid an unneceesary addition,
// Which means the value we pass in for evaluations_ptr should be adjusted accordingly
evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
let mle := builder_consume_first_round_mle(builder_ptr)
sum_out_fold_eval := addmod_bn254(mulmod_bn254(sum_out_fold_eval, beta), mle)
mstore(evaluations_ptr, mle)
}
}
function exclude_coverage_stop_compute_sum_out_fold_eval_for_aggregate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_aggregate_input_evals() {} // solhint-disable-line no-empty-blocks
function read_aggregate_input_evals(plan_ptr, builder_ptr, alpha, beta) ->
plan_ptr_out,
partial_dlog_zero_sum_constraint_eval,
num_sum_columns,
num_group_by_columns
{
// Read/eval aggregate inputs, selection inputs, and fold and dlog them
let g_in_star_eval_times_selection_eval, input_chi_eval, input_evaluations
plan_ptr,
g_in_star_eval_times_selection_eval,
num_group_by_columns,
input_chi_eval,
input_evaluations := compute_g_in_star_eval_for_aggregate(plan_ptr, builder_ptr, alpha, beta)
// Read/eval sum inputs and fold them
let sum_in_fold_eval
plan_ptr, sum_in_fold_eval, num_sum_columns :=
compute_sum_in_fold_eval_for_aggregate(
plan_ptr, builder_ptr, alpha, beta, input_chi_eval, input_evaluations
)
partial_dlog_zero_sum_constraint_eval :=
mulmod_bn254(g_in_star_eval_times_selection_eval, sum_in_fold_eval)
// Read count alias
{
let count_alias
plan_ptr, count_alias := read_binary(plan_ptr)
}
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_read_aggregate_input_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_aggregate_output_evals() {} // solhint-disable-line no-empty-blocks
function read_aggregate_output_evals(
builder_ptr, alpha, beta, partial_dlog_zero_sum_constraint_eval, num_group_by_columns, num_sum_columns
) -> evaluations_ptr, output_length, output_chi_eval {
num_sum_columns := add(num_sum_columns, 1)
// Allocate memory for evaluations
{
let free_ptr := mload(FREE_PTR)
evaluations_ptr := free_ptr
let num_evals := add(num_group_by_columns, num_sum_columns)
mstore(free_ptr, num_evals)
free_ptr := add(free_ptr, WORD_SIZE)
free_ptr := add(free_ptr, mul(num_evals, WORD_SIZE))
mstore(FREE_PTR, free_ptr)
}
output_length, output_chi_eval := builder_consume_chi_evaluation_with_length(builder_ptr)
let g_out_star_eval
g_out_star_eval :=
compute_g_out_star_eval(
builder_ptr, alpha, beta, output_chi_eval, add(evaluations_ptr, WORD_SIZE), num_group_by_columns
)
let sum_out_fold_eval :=
compute_sum_out_fold_eval_for_aggregate(
builder_ptr,
alpha,
beta,
output_chi_eval,
num_sum_columns,
add(evaluations_ptr, mul(num_group_by_columns, WORD_SIZE))
)
builder_produce_zerosum_constraint(
builder_ptr,
submod_bn254(
partial_dlog_zero_sum_constraint_eval, mulmod_bn254(g_out_star_eval, sum_out_fold_eval)
),
3
)
}
function exclude_coverage_stop_read_aggregate_output_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_aggregate_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function aggregate_exec_evaluate(plan_ptr, builder_ptr) ->
plan_ptr_out,
evaluations_ptr,
output_length,
output_chi_eval
{
let alpha := builder_consume_challenge(builder_ptr)
let beta := builder_consume_challenge(builder_ptr)
let partial_dlog_zero_sum_constraint_eval, num_sum_columns
{
let num_group_by_columns
plan_ptr_out, partial_dlog_zero_sum_constraint_eval, num_sum_columns, num_group_by_columns :=
read_aggregate_input_evals(plan_ptr, builder_ptr, alpha, beta)
// We reuse plan_ptr to save on variable space
plan_ptr := num_group_by_columns
}
// Read output
// For now, we can assume the number of group by columns is 1,
// because the function would have errored by this point otherwise
evaluations_ptr, output_length, output_chi_eval :=
read_aggregate_output_evals(
builder_ptr,
alpha,
beta,
partial_dlog_zero_sum_constraint_eval,
// Recall that plan_ptr is really num_group_by_columns here
plan_ptr,
num_sum_columns
)
}
function exclude_coverage_stop_aggregate_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_evaluate_input_plans() {} // solhint-disable-line no-empty-blocks
function evaluate_input_plans(plan_ptr, builder_ptr, evaluations) -> plan_ptr_out, hat_evals, join_evals {
// Determine total number of evaluations
let num_columns := mload(evaluations)
evaluations := add(evaluations, WORD_SIZE)
// Determine number of columns to join on
let num_join_columns := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
if sub(num_join_columns, 1) { err(ERR_NUMBER_OF_JOIN_COLUMNS_NOT_ONE) }
// We need a collection to record which indices are not join indices (1 means it is not a joining column).
// The total number of evaluations from the input should be the number of entries in this collection.
// No need to store the length.
let other_indices := mload(FREE_PTR)
hat_evals := add(other_indices, mul(num_columns, WORD_SIZE))
// There should be an extra entry in the hat collection for rho
mstore(hat_evals, add(num_columns, 1))
let target_hat_evals := add(hat_evals, WORD_SIZE)
join_evals := add(target_hat_evals, mul(add(num_columns, 1), WORD_SIZE))
// The join evals should have the same number as the length of the join index collection
mstore(join_evals, num_join_columns)
let target_join_evals := add(join_evals, WORD_SIZE)
mstore(FREE_PTR, add(target_join_evals, mul(num_join_columns, WORD_SIZE)))
// Populate the non join index collection with 1s.
for { let i := num_columns } i {} {
i := sub(i, 1)
// TODO: We probably don't need to be skipping by WORDS for what is effectively a bit collection
mstore(add(other_indices, mul(i, WORD_SIZE)), 1)
}
// We need to update each of our collections for each join column
for { let i := num_join_columns } i { i := sub(i, 1) } {
// Get the index of the join column from the plan
let join_column_index := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
// We set to 0 any indices that are covered by the join columns
mstore(add(other_indices, mul(join_column_index, WORD_SIZE)), 0)
// Get the evaluation of the column from the input evaluations
let join_column_eval := mload(add(evaluations, mul(join_column_index, WORD_SIZE)))
// Both hat and join evaluations should store the join column evaluation
mstore(target_hat_evals, join_column_eval)
target_hat_evals := add(target_hat_evals, WORD_SIZE)
mstore(target_join_evals, join_column_eval)
target_join_evals := add(target_join_evals, WORD_SIZE)
}
// We need to iterate through each index to determine which were not covered by join columns
for { let i := 0 } lt(i, num_columns) { i := add(i, 1) } {
// We only need to worry about the indices that were not join indices
if mload(add(other_indices, mul(i, WORD_SIZE))) {
// We store each column evaluation in the hat collection
mstore(target_hat_evals, mload(add(evaluations, mul(i, WORD_SIZE))))
target_hat_evals := add(target_hat_evals, WORD_SIZE)
}
}
// The last entry in the hat collection is the rho evaluation
mstore(target_hat_evals, builder_consume_rho_evaluation(builder_ptr))
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_evaluate_input_plans() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_evaluate_u_column_with_monotony_check() {} // solhint-disable-line no-empty-blocks
function evaluate_u_column_with_monotony_check(builder_ptr, alpha_and_beta) ->
u_column_eval_array,
u_chi_eval
{
// The length of the u eval collection is 1, until we support joining on multiple columns
u_column_eval_array := mload(FREE_PTR)
mstore(FREE_PTR, add(u_column_eval_array, WORDX2_SIZE))
mstore(u_column_eval_array, 1)
// We run our monotony check on u eval, before wrapping it in the collection
u_chi_eval := builder_consume_chi_evaluation(builder_ptr)
let u_column_eval := builder_consume_first_round_mle(builder_ptr)
monotonic_verify(
builder_ptr,
mload(alpha_and_beta),
mload(add(alpha_and_beta, WORD_SIZE)),
u_column_eval,
u_chi_eval,
1,
1
)
// Store the u eval in the collection
mstore(add(u_column_eval_array, WORD_SIZE), u_column_eval)
}
function exclude_coverage_stop_evaluate_u_column_with_monotony_check() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_consume_and_membership_check_left_column_evals() {} // solhint-disable-line no-empty-blocks
function consume_and_membership_check_left_column_evals(
builder_ptr, alpha_and_beta, hat_evals, res_chi_eval, chi_eval
) -> res_column_evals {
// Initially we set the length of res_column_evals to include the rho eval
// This will allow us to check the left evals against the hat evals without needing to load a second,
// almost identical collection
let num_hat_columns := mload(hat_evals)
res_column_evals := mload(FREE_PTR)
mstore(res_column_evals, num_hat_columns)
mstore(FREE_PTR, add(res_column_evals, mul(add(num_hat_columns, 1), WORD_SIZE)))
let target_ptr := add(res_column_evals, WORD_SIZE)
for { let i := num_hat_columns } i { i := sub(i, 1) } {
let eval := builder_consume_first_round_mle(builder_ptr)
mstore(target_ptr, eval)
target_ptr := add(target_ptr, WORD_SIZE)
}
pop(
membership_check_evaluate(
builder_ptr,
mload(alpha_and_beta),
mload(add(alpha_and_beta, WORD_SIZE)),
chi_eval,
res_chi_eval,
hat_evals,
res_column_evals
)
)
}
function exclude_coverage_stop_consume_and_membership_check_left_column_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_populate_right_evals_for_join() {} // solhint-disable-line no-empty-blocks
function populate_right_evals_for_join(eval, right_column_evals, res_column_evals_out) {
// We store the output in two collections. One output collection and one to compare with the hat evals
mstore(right_column_evals, eval)
mstore(res_column_evals_out, eval)
}
function exclude_coverage_stop_populate_right_evals_for_join() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_consume_right_evals_for_join() {} // solhint-disable-line no-empty-blocks
function consume_right_evals_for_join(
builder_ptr, num_join_columns, hat_evals, left_right_and_output_evaluations
) -> i_eval, right_output_column_evals {
// The length of hat_evals is the length of the collection which will be used in the membership check
let num_hat_columns := mload(hat_evals)
right_output_column_evals := mload(FREE_PTR)
mstore(right_output_column_evals, num_hat_columns)
let res_column_evals := mload(add(left_right_and_output_evaluations, WORDX2_SIZE))
let res_column_evals_out := add(right_output_column_evals, mul(add(num_hat_columns, 1), WORD_SIZE))
mstore(add(left_right_and_output_evaluations, WORDX2_SIZE), res_column_evals_out)
// Load length of incoming res_column_evals
let num_left_output_columns := sub(mload(res_column_evals), 1)
// The length of the outgoing collection should be
// the incoming length plus the number of right hat evals less the common columns
mstore(
FREE_PTR,
add(
res_column_evals_out,
mul(add(num_left_output_columns, sub(add(num_hat_columns, 1), num_join_columns)), WORD_SIZE)
)
)
mstore(
res_column_evals_out, add(num_left_output_columns, sub(sub(num_hat_columns, 1), num_join_columns))
)
// The first num_join_columns entries in the res_column_evals collection are the common evals.
// Both res_column_evals_out and right_output_column_evals need them.
for { let i := num_join_columns } i { i := sub(i, 1) } {
// We increment before reading and writing because we did not increment after handling the lenghts.
res_column_evals := add(res_column_evals, WORD_SIZE)
res_column_evals_out := add(res_column_evals_out, WORD_SIZE)
right_output_column_evals := add(right_output_column_evals, WORD_SIZE)
populate_right_evals_for_join(
mload(res_column_evals), right_output_column_evals, res_column_evals_out
)
}
// We copy over the remaining res_column_evals to res_column_evals_out
for { let i := sub(num_left_output_columns, num_join_columns) } i { i := sub(i, 1) } {
res_column_evals := add(res_column_evals, WORD_SIZE)
res_column_evals_out := add(res_column_evals_out, WORD_SIZE)
mstore(res_column_evals_out, mload(res_column_evals))
}
// We consume non common right evals and populate right_output_column_evals and res_column_evals_out
for { let i := sub(num_hat_columns, num_join_columns) } i { i := sub(i, 1) } {
right_output_column_evals := add(right_output_column_evals, WORD_SIZE)
res_column_evals_out := add(res_column_evals_out, WORD_SIZE)
populate_right_evals_for_join(
builder_consume_first_round_mle(builder_ptr), right_output_column_evals, res_column_evals_out
)
}
// The last entry in right_output_column_evals is rho_bar_right_eval
// We saved rho_bar_left_eval from earlier, so that we could calculate i_eval now. Note that this value
// does not get recorded in res_column_evals_out.
i_eval :=
addmod_bn254(
mload(right_output_column_evals), mulmod_bn254(shl(64, 1), mload(add(res_column_evals, WORD_SIZE)))
)
// We drop the pointers back to their starting places
right_output_column_evals := sub(right_output_column_evals, mul(num_hat_columns, WORD_SIZE))
}
function exclude_coverage_stop_consume_right_evals_for_join() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_consume_and_membership_check_right_column_evals() {} // solhint-disable-line no-empty-blocks
function consume_and_membership_check_right_column_evals(
builder_ptr,
alpha_and_beta,
num_join_columns,
hat_evals,
right_and_output_chi_evals,
left_right_and_output_evaluations
) -> i_eval {
let right_column_evals
i_eval, right_column_evals :=
consume_right_evals_for_join(
builder_ptr, num_join_columns, hat_evals, left_right_and_output_evaluations
)
// Finally, we can do our membership check
pop(
membership_check_evaluate(
builder_ptr,
mload(alpha_and_beta),
mload(add(alpha_and_beta, WORD_SIZE)),
mload(right_and_output_chi_evals),
mload(add(right_and_output_chi_evals, WORD_SIZE)),
hat_evals,
right_column_evals
)
)
}
function exclude_coverage_stop_consume_and_membership_check_right_column_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_evaluate_consume_and_check_left_column_evals() {} // solhint-disable-line no-empty-blocks
function evaluate_consume_and_check_left_column_evals(
plan_ptr, builder_ptr, alpha_and_beta, res_chi_eval, left_right_and_output_evaluations, chi_eval
) -> plan_ptr_out {
// We only need the hat evals for a membership check on the output columns
let hat_evals, join_evals
plan_ptr_out, hat_evals, join_evals :=
evaluate_input_plans(plan_ptr, builder_ptr, mload(left_right_and_output_evaluations))
mstore(left_right_and_output_evaluations, join_evals)
let res_column_evals :=
consume_and_membership_check_left_column_evals(
builder_ptr, alpha_and_beta, hat_evals, res_chi_eval, chi_eval
)
mstore(add(left_right_and_output_evaluations, WORDX2_SIZE), res_column_evals)
}
function exclude_coverage_stop_evaluate_consume_and_check_left_column_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_evaluate_consume_and_check_right_join_evals() {} // solhint-disable-line no-empty-blocks
function evaluate_consume_and_check_right_join_evals(
plan_ptr, builder_ptr, alpha_and_beta, left_right_and_output_evaluations, right_and_output_chi_evals
) -> plan_ptr_out {
let hat_evals, i_eval, join_evals
plan_ptr, hat_evals, join_evals :=
evaluate_input_plans(plan_ptr, builder_ptr, mload(add(left_right_and_output_evaluations, WORD_SIZE)))
i_eval :=
consume_and_membership_check_right_column_evals(
builder_ptr,
alpha_and_beta,
mload(join_evals),
hat_evals,
right_and_output_chi_evals,
left_right_and_output_evaluations
)
mstore(add(left_right_and_output_evaluations, WORD_SIZE), join_evals)
monotonic_verify(
builder_ptr,
mload(alpha_and_beta),
mload(add(alpha_and_beta, WORD_SIZE)),
i_eval,
mload(add(right_and_output_chi_evals, WORD_SIZE)),
1,
1
)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_evaluate_consume_and_check_right_join_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_evaluate_remaining_check_on_both_left_and_right_sides() {} // solhint-disable-line no-empty-blocks
function evaluate_remaining_check_on_both_left_and_right_sides(
plan_ptr, builder_ptr, alpha_and_beta, left_right_and_output_evaluations, left_chi_eval, right_chi_eval
) -> plan_ptr_out, w_eval {
let u_column_eval_array, u_chi_eval :=
evaluate_u_column_with_monotony_check(builder_ptr, alpha_and_beta)
w_eval :=
membership_check_evaluate(
builder_ptr,
mload(alpha_and_beta),
mload(add(alpha_and_beta, WORD_SIZE)),
u_chi_eval,
left_chi_eval,
u_column_eval_array,
mload(left_right_and_output_evaluations)
)
// We want to capture w_l_eval and w_r_eval
w_eval :=
mulmod_bn254(
w_eval,
membership_check_evaluate(
builder_ptr,
mload(alpha_and_beta),
mload(add(alpha_and_beta, WORD_SIZE)),
u_chi_eval,
right_chi_eval,
u_column_eval_array,
mload(add(left_right_and_output_evaluations, WORD_SIZE))
)
)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_evaluate_remaining_check_on_both_left_and_right_sides() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_evaluate_sort_merge_join_outputs() {} // solhint-disable-line no-empty-blocks
function evaluate_sort_merge_join_outputs(
plan_ptr, builder_ptr, left_right_and_output_evaluations, left_chi_eval, right_and_output_chi_evals
) -> plan_ptr_out {
// In order to save on local variables, we save alpha and beta in one location in memory
let alpha_and_beta := mload(FREE_PTR)
let output_chi_eval := mload(add(right_and_output_chi_evals, WORD_SIZE))
mstore(FREE_PTR, add(alpha_and_beta, WORDX2_SIZE))
mstore(alpha_and_beta, builder_consume_challenge(builder_ptr))
mstore(add(alpha_and_beta, WORD_SIZE), builder_consume_challenge(builder_ptr))
plan_ptr :=
evaluate_consume_and_check_left_column_evals(
plan_ptr,
builder_ptr,
alpha_and_beta,
output_chi_eval,
left_right_and_output_evaluations,
left_chi_eval
)
plan_ptr :=
evaluate_consume_and_check_right_join_evals(
plan_ptr, builder_ptr, alpha_and_beta, left_right_and_output_evaluations, right_and_output_chi_evals
)
let w_eval
plan_ptr, w_eval :=
evaluate_remaining_check_on_both_left_and_right_sides(
plan_ptr,
builder_ptr,
alpha_and_beta,
left_right_and_output_evaluations,
left_chi_eval,
mload(right_and_output_chi_evals)
)
// sum w_eval - output_chi_eval = 0
builder_produce_zerosum_constraint(builder_ptr, submod_bn254(w_eval, output_chi_eval), 2)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_evaluate_sort_merge_join_outputs() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_skip_sort_merge_join_aliases() {} // solhint-disable-line no-empty-blocks
function skip_sort_merge_join_aliases(plan_ptr) -> plan_ptr_out {
let num_aliases := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
for {} num_aliases { num_aliases := sub(num_aliases, 1) } {
let entry
plan_ptr, entry := read_binary(plan_ptr)
}
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_skip_sort_merge_join_aliases() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_sort_merge_join_evaluate() {} // solhint-disable-line no-empty-blocks
function sort_merge_join_evaluate(plan_ptr, builder_ptr) ->
plan_ptr_out,
evaluations_ptr,
output_length,
output_chi_eval
{
// In order to save on local variables, we save the left, right, and output evaluations
// in one location in memory
let left_right_and_output_evaluations := mload(FREE_PTR)
mstore(FREE_PTR, add(left_right_and_output_evaluations, WORDX3_SIZE))
let left_chi_eval
{
let left_evaluations, left_output_length
plan_ptr, left_evaluations, left_output_length, left_chi_eval :=
proof_plan_evaluate(plan_ptr, builder_ptr)
mstore(left_right_and_output_evaluations, left_evaluations)
}
let right_and_output_chi_evals := mload(FREE_PTR)
mstore(FREE_PTR, add(right_and_output_chi_evals, WORDX2_SIZE))
{
let right_evaluations, right_output_length, right_chi_eval
plan_ptr, right_evaluations, right_output_length, right_chi_eval :=
proof_plan_evaluate(plan_ptr, builder_ptr)
mstore(right_and_output_chi_evals, right_chi_eval)
mstore(add(left_right_and_output_evaluations, WORD_SIZE), right_evaluations)
}
output_length, output_chi_eval := builder_consume_chi_evaluation_with_length(builder_ptr)
mstore(add(right_and_output_chi_evals, WORD_SIZE), output_chi_eval)
plan_ptr :=
evaluate_sort_merge_join_outputs(
plan_ptr, builder_ptr, left_right_and_output_evaluations, left_chi_eval, right_and_output_chi_evals
)
evaluations_ptr := mload(add(left_right_and_output_evaluations, WORDX2_SIZE))
plan_ptr_out := skip_sort_merge_join_aliases(plan_ptr)
}
function exclude_coverage_stop_sort_merge_join_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_union_input_evaluate() {} // solhint-disable-line no-empty-blocks
function union_input_evaluate(plan_ptr, builder_ptr, gamma, beta) ->
plan_ptr_out,
output_length,
num_columns,
zerosum_constraint
{
let input_count := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
if lt(input_count, 2) {
// Not enough input plans for union
err(ERR_UNION_NOT_ENOUGH_INPUT_PLANS)
}
// Process each input plan
for {} input_count { input_count := sub(input_count, 1) } {
// Recursively evaluate the input plan
let input_evaluations_ptr
let input_length
let input_chi_eval
plan_ptr, input_evaluations_ptr, input_length, input_chi_eval :=
proof_plan_evaluate(plan_ptr, builder_ptr)
output_length := add(output_length, input_length)
switch num_columns
case 0 {
// If this is the first input, initialize num_columns
num_columns := mload(input_evaluations_ptr)
if iszero(num_columns) {
// No columns in input evaluations
err(ERR_UNION_INVALID_COLUMN_COUNTS)
}
}
default {
// Ensure all inputs have the same number of columns
if iszero(eq(num_columns, mload(input_evaluations_ptr))) {
// Mismatched column counts
err(ERR_UNION_INVALID_COLUMN_COUNTS)
}
}
// Apply FoldLogExpr to get c_star for this input
let c_star :=
fold_log_star_evaluate(builder_ptr, gamma, beta, input_evaluations_ptr, input_chi_eval)
// Add to zero-sum constraint
zerosum_constraint := addmod_bn254(zerosum_constraint, c_star)
}
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_union_input_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_union_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function union_exec_evaluate(plan_ptr, builder_ptr) ->
plan_ptr_out,
evaluations_ptr,
output_length,
output_chi_eval
{
// Consume gamma and beta challenges for FoldLogExpr
let gamma := builder_consume_challenge(builder_ptr)
let beta := builder_consume_challenge(builder_ptr)
{
let num_columns, zerosum_constraint
plan_ptr, output_length, num_columns, zerosum_constraint :=
union_input_evaluate(plan_ptr, builder_ptr, gamma, beta)
// Consume first-round MLEs for output columns
{
let d_fold
d_fold, evaluations_ptr := fold_first_round_mles(builder_ptr, beta, num_columns)
d_fold := mulmod_bn254(gamma, d_fold)
// Consume chi evaluation for output
output_chi_eval := builder_consume_chi_evaluation(builder_ptr)
let d_star := builder_consume_final_round_mle(builder_ptr)
// d_star + d_fold * d_star - output_chi = 0
builder_produce_identity_constraint(
builder_ptr,
submod_bn254(addmod_bn254(d_star, mulmod_bn254(d_fold, d_star)), output_chi_eval),
2
)
// Generate zero-sum constraint: sum(c_stars) - d_star = 0
zerosum_constraint := submod_bn254(zerosum_constraint, d_star)
builder_produce_zerosum_constraint(builder_ptr, zerosum_constraint, 1)
}
}
// Return output evaluations
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_union_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_legacy_filter_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function legacy_filter_exec_evaluate(plan_ptr, builder_ptr) ->
plan_ptr_out,
evaluations_ptr,
output_length,
output_chi_eval
{
let input_chi_eval, selection_eval, c_fold, d_fold
{
let alpha := builder_consume_challenge(builder_ptr)
let beta := builder_consume_challenge(builder_ptr)
input_chi_eval :=
builder_get_table_chi_evaluation(builder_ptr, shr(UINT64_PADDING_BITS, calldataload(plan_ptr)))
plan_ptr := add(plan_ptr, UINT64_SIZE)
plan_ptr, selection_eval :=
proof_expr_evaluate(
plan_ptr, builder_ptr, input_chi_eval, builder_get_column_evaluations(builder_ptr)
)
plan_ptr, c_fold, d_fold, evaluations_ptr :=
compute_filter_folds(
plan_ptr, builder_ptr, input_chi_eval, beta, builder_get_column_evaluations(builder_ptr)
)
c_fold := mulmod_bn254(alpha, c_fold)
d_fold := mulmod_bn254(alpha, d_fold)
}
output_length, output_chi_eval := builder_consume_chi_evaluation_with_length(builder_ptr)
verify_filter(builder_ptr, c_fold, d_fold, input_chi_eval, output_chi_eval, selection_eval)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_legacy_filter_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_proof_plan_evaluate() {} // solhint-disable-line no-empty-blocks
function proof_plan_evaluate(plan_ptr, builder_ptr) ->
plan_ptr_out,
evaluations_ptr,
output_length,
output_chi_eval
{
let proof_plan_variant := shr(UINT32_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT32_SIZE)
switch proof_plan_variant
case 0 {
case_const(0, LEGACY_FILTER_EXEC_VARIANT)
plan_ptr_out, evaluations_ptr, output_length, output_chi_eval :=
legacy_filter_exec_evaluate(plan_ptr, builder_ptr)
}
case 1 {
case_const(1, EMPTY_EXEC_VARIANT)
evaluations_ptr, output_length, output_chi_eval := empty_exec_evaluate(builder_ptr)
plan_ptr_out := plan_ptr
}
case 2 {
case_const(2, TABLE_EXEC_VARIANT)
plan_ptr_out, evaluations_ptr, output_length, output_chi_eval :=
table_exec_evaluate(plan_ptr, builder_ptr)
}
case 3 {
case_const(3, PROJECTION_EXEC_VARIANT)
plan_ptr_out, evaluations_ptr, output_length, output_chi_eval :=
projection_exec_evaluate(plan_ptr, builder_ptr)
}
case 4 {
case_const(4, SLICE_EXEC_VARIANT)
plan_ptr_out, evaluations_ptr, output_length, output_chi_eval :=
slice_exec_evaluate(plan_ptr, builder_ptr)
}
case 5 {
case_const(5, GROUP_BY_EXEC_VARIANT)
plan_ptr_out, evaluations_ptr, output_length, output_chi_eval :=
group_by_exec_evaluate(plan_ptr, builder_ptr)
}
case 6 {
case_const(6, UNION_EXEC_VARIANT)
plan_ptr_out, evaluations_ptr, output_length, output_chi_eval :=
union_exec_evaluate(plan_ptr, builder_ptr)
}
case 7 {
case_const(7, SORT_MERGE_JOIN_EXEC_VARIANT)
plan_ptr_out, evaluations_ptr, output_length, output_chi_eval :=
sort_merge_join_evaluate(plan_ptr, builder_ptr)
}
case 8 {
case_const(8, FILTER_EXEC_VARIANT)
plan_ptr_out, evaluations_ptr, output_length, output_chi_eval :=
filter_exec_evaluate(plan_ptr, builder_ptr)
}
case 9 {
case_const(9, AGGREGATE_EXEC_VARIANT)
plan_ptr_out, evaluations_ptr, output_length, output_chi_eval :=
aggregate_exec_evaluate(plan_ptr, builder_ptr)
}
default { err(ERR_UNSUPPORTED_PROOF_PLAN_VARIANT) }
}
function exclude_coverage_stop_proof_plan_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_projection_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function projection_exec_evaluate(plan_ptr, builder_ptr) ->
plan_ptr_out,
evaluations_ptr,
output_length,
output_chi_eval
{
let input_evaluations_ptr
plan_ptr, input_evaluations_ptr, output_length, output_chi_eval :=
proof_plan_evaluate(plan_ptr, builder_ptr)
let column_count := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
evaluations_ptr := mload(FREE_PTR)
mstore(FREE_PTR, add(evaluations_ptr, add(WORD_SIZE, mul(column_count, WORD_SIZE))))
let target_ptr := evaluations_ptr
mstore(target_ptr, column_count)
for {} column_count { column_count := sub(column_count, 1) } {
target_ptr := add(target_ptr, WORD_SIZE)
let evaluation
plan_ptr, evaluation :=
proof_expr_evaluate(plan_ptr, builder_ptr, output_chi_eval, input_evaluations_ptr)
mstore(target_ptr, evaluation)
}
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_projection_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_filter_folds() {} // solhint-disable-line no-empty-blocks
function compute_filter_folds(plan_ptr, builder_ptr, input_chi_eval, beta, accessor) ->
plan_ptr_out,
c_fold,
d_fold,
evaluations_ptr
{
let column_count := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
plan_ptr, c_fold := fold_expr_evals(plan_ptr, builder_ptr, input_chi_eval, beta, column_count, accessor)
d_fold, evaluations_ptr := fold_first_round_mles(builder_ptr, beta, column_count)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_compute_filter_folds() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_evaluate_input_plan_and_dependent_exprs() {} // solhint-disable-line no-empty-blocks
function evaluate_input_plan_and_dependent_exprs(plan_ptr, builder_ptr) ->
plan_ptr_out,
c_fold,
d_fold,
evaluations_ptr,
input_chi_eval,
selection_eval
{
let beta := builder_consume_challenge(builder_ptr)
let input_evaluations_ptr
{
let input_length
plan_ptr, input_evaluations_ptr, input_length, input_chi_eval :=
proof_plan_evaluate(plan_ptr, builder_ptr)
}
plan_ptr, selection_eval :=
proof_expr_evaluate(plan_ptr, builder_ptr, input_chi_eval, input_evaluations_ptr)
plan_ptr_out, c_fold, d_fold, evaluations_ptr :=
compute_filter_folds(plan_ptr, builder_ptr, input_chi_eval, beta, input_evaluations_ptr)
}
function exclude_coverage_stop_evaluate_input_plan_and_dependent_exprs() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_filter_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function filter_exec_evaluate(plan_ptr, builder_ptr) ->
plan_ptr_out,
evaluations_ptr,
output_length,
output_chi_eval
{
let input_chi_eval, selection_eval, c_fold, d_fold
{
let alpha := builder_consume_challenge(builder_ptr)
plan_ptr, c_fold, d_fold, evaluations_ptr, input_chi_eval, selection_eval :=
evaluate_input_plan_and_dependent_exprs(plan_ptr, builder_ptr)
c_fold := mulmod_bn254(alpha, c_fold)
d_fold := mulmod_bn254(alpha, d_fold)
}
output_length, output_chi_eval := builder_consume_chi_evaluation_with_length(builder_ptr)
verify_filter(builder_ptr, c_fold, d_fold, input_chi_eval, output_chi_eval, selection_eval)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_filter_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_min() {} // solhint-disable-line no-empty-blocks
function min(a, b) -> minimum {
minimum := a
if lt(b, a) { minimum := b }
}
function exclude_coverage_stop_min() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_fold() {} // solhint-disable-line no-empty-blocks
function compute_fold(beta, evals) -> fold {
let num_columns := mload(evals)
fold := 0
for { let i := 0 } lt(i, num_columns) { i := add(i, 1) } {
evals := add(evals, WORD_SIZE)
fold := addmod_bn254(mulmod_bn254(fold, beta), mload(evals))
}
}
function exclude_coverage_stop_compute_fold() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_consume_challenge() {} // solhint-disable-line no-empty-blocks
function builder_consume_challenge(builder_ptr) -> challenge {
challenge := dequeue(add(builder_ptr, BUILDER_CHALLENGES_OFFSET))
}
function exclude_coverage_stop_builder_consume_challenge() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_dequeue() {} // solhint-disable-line no-empty-blocks
function dequeue(queue_ptr) -> value {
let queue := mload(queue_ptr)
let length := mload(queue)
if iszero(length) { err(ERR_EMPTY_QUEUE) }
queue := add(queue, WORD_SIZE)
value := mload(queue)
mstore(queue, sub(length, 1))
mstore(queue_ptr, queue)
}
function exclude_coverage_stop_dequeue() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_consume_chi_evaluation_with_length() {} // solhint-disable-line no-empty-blocks
function builder_consume_chi_evaluation_with_length(builder_ptr) -> length, chi_eval {
length, chi_eval := dequeue_uint512(add(builder_ptr, BUILDER_CHI_EVALUATIONS_OFFSET))
}
function exclude_coverage_stop_builder_consume_chi_evaluation_with_length() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_dequeue_uint512() {} // solhint-disable-line no-empty-blocks
function dequeue_uint512(queue_ptr) -> upper, lower {
let queue := mload(queue_ptr)
let length := mload(queue)
if iszero(length) { err(ERR_EMPTY_QUEUE) }
queue := add(queue, WORD_SIZE)
upper := mload(queue)
queue := add(queue, WORD_SIZE)
lower := mload(queue)
mstore(queue, sub(length, 1))
mstore(queue_ptr, queue)
}
function exclude_coverage_stop_dequeue_uint512() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_fold_first_round_mles() {} // solhint-disable-line no-empty-blocks
function fold_first_round_mles(builder_ptr, beta, column_count) -> fold, evaluations_ptr {
evaluations_ptr := mload(FREE_PTR)
mstore(evaluations_ptr, column_count)
evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
fold := 0
for { let i := column_count } i { i := sub(i, 1) } {
let mle := builder_consume_first_round_mle(builder_ptr)
fold := addmod_bn254(mulmod_bn254(fold, beta), mle)
mstore(evaluations_ptr, mle)
evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
}
evaluations_ptr := mload(FREE_PTR)
mstore(FREE_PTR, add(evaluations_ptr, add(WORD_SIZE, mul(column_count, WORD_SIZE))))
}
function exclude_coverage_stop_fold_first_round_mles() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_consume_first_round_mle() {} // solhint-disable-line no-empty-blocks
function builder_consume_first_round_mle(builder_ptr) -> value {
value := dequeue(add(builder_ptr, BUILDER_FIRST_ROUND_MLES_OFFSET))
}
function exclude_coverage_stop_builder_consume_first_round_mle() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_verify_filter() {} // solhint-disable-line no-empty-blocks
function verify_filter(builder_ptr, c_fold, d_fold, input_chi_eval, output_chi_eval, selection_eval) {
let c_star := builder_consume_final_round_mle(builder_ptr)
let d_star := builder_consume_final_round_mle(builder_ptr)
builder_produce_identity_constraint(
builder_ptr, submod_bn254(mulmod_bn254(addmod_bn254(1, c_fold), c_star), input_chi_eval), 2
)
builder_produce_identity_constraint(
builder_ptr, submod_bn254(mulmod_bn254(addmod_bn254(1, d_fold), d_star), output_chi_eval), 2
)
builder_produce_zerosum_constraint(
builder_ptr, submod_bn254(mulmod_bn254(c_star, selection_eval), d_star), 2
)
builder_produce_identity_constraint(
builder_ptr, mulmod_bn254(d_fold, submod_bn254(output_chi_eval, 1)), 2
)
}
function exclude_coverage_stop_verify_filter() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_consume_final_round_mle() {} // solhint-disable-line no-empty-blocks
function builder_consume_final_round_mle(builder_ptr) -> value {
value := dequeue(add(builder_ptr, BUILDER_FINAL_ROUND_MLES_OFFSET))
}
function exclude_coverage_stop_builder_consume_final_round_mle() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_produce_identity_constraint() {} // solhint-disable-line no-empty-blocks
function builder_produce_identity_constraint(builder_ptr, evaluation, degree) {
if gt(add(degree, 1), mload(add(builder_ptr, BUILDER_MAX_DEGREE_OFFSET))) {
err(ERR_CONSTRAINT_DEGREE_TOO_HIGH)
}
// builder.aggregateEvaluation +=
// evaluation * dequeue(builder.constraintMultipliers) * builder.rowMultipliersEvaluation;
mstore(
add(builder_ptr, BUILDER_AGGREGATE_EVALUATION_OFFSET),
addmod(
mload(add(builder_ptr, BUILDER_AGGREGATE_EVALUATION_OFFSET)),
mulmod(
evaluation,
mulmod(
dequeue(add(builder_ptr, BUILDER_CONSTRAINT_MULTIPLIERS_OFFSET)),
mload(add(builder_ptr, BUILDER_ROW_MULTIPLIERS_EVALUATION_OFFSET)),
MODULUS
),
MODULUS
),
MODULUS
)
)
}
function exclude_coverage_stop_builder_produce_identity_constraint() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_produce_zerosum_constraint() {} // solhint-disable-line no-empty-blocks
function builder_produce_zerosum_constraint(builder_ptr, evaluation, degree) {
if gt(degree, mload(add(builder_ptr, BUILDER_MAX_DEGREE_OFFSET))) {
err(ERR_CONSTRAINT_DEGREE_TOO_HIGH)
}
// builder.aggregateEvaluation += evaluation * dequeue(builder.constraintMultipliers)
mstore(
add(builder_ptr, BUILDER_AGGREGATE_EVALUATION_OFFSET),
addmod(
mload(add(builder_ptr, BUILDER_AGGREGATE_EVALUATION_OFFSET)),
mulmod(evaluation, dequeue(add(builder_ptr, BUILDER_CONSTRAINT_MULTIPLIERS_OFFSET)), MODULUS),
MODULUS
)
)
}
function exclude_coverage_stop_builder_produce_zerosum_constraint() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_binary() {} // solhint-disable-line no-empty-blocks
function read_binary(result_ptr) -> result_ptr_out, entry {
let free_ptr := mload(FREE_PTR)
let len := shr(UINT64_PADDING_BITS, calldataload(result_ptr))
result_ptr := add(result_ptr, UINT64_SIZE)
// temps with their empty‐slice defaults
entry := 0
// only run this when len != 0
if len {
calldatacopy(free_ptr, result_ptr, len)
let hash_val := keccak256(free_ptr, len)
// endian-swap steps
hash_val :=
or(
shr(128, and(hash_val, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000)),
shl(128, and(hash_val, 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
)
hash_val :=
or(
shr(64, and(hash_val, 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000)),
shl(64, and(hash_val, 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF))
)
hash_val :=
or(
shr(32, and(hash_val, 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000)),
shl(32, and(hash_val, 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF))
)
hash_val :=
or(
shr(16, and(hash_val, 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000)),
shl(16, and(hash_val, 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF))
)
hash_val :=
or(
shr(8, and(hash_val, 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00)),
shl(8, and(hash_val, 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF))
)
entry := and(hash_val, MODULUS_MASK)
}
// single assign to named returns
result_ptr_out := add(result_ptr, len)
}
function exclude_coverage_stop_read_binary() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_equals_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function equals_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, result_eval {
let lhs_eval
expr_ptr, lhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
let rhs_eval
expr_ptr, rhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
let diff_eval := submod_bn254(lhs_eval, rhs_eval)
let diff_star_eval := builder_consume_final_round_mle(builder_ptr)
result_eval := mod(builder_consume_final_round_mle(builder_ptr), MODULUS)
builder_produce_identity_constraint(builder_ptr, mulmod_bn254(result_eval, diff_eval), 2)
builder_produce_identity_constraint(
builder_ptr,
submod_bn254(chi_eval, addmod_bn254(mulmod_bn254(diff_eval, diff_star_eval), result_eval)),
2
)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_equals_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_and_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function and_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, result_eval {
let lhs_eval
expr_ptr, lhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
let rhs_eval
expr_ptr, rhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
result_eval := mod(builder_consume_final_round_mle(builder_ptr), MODULUS)
builder_produce_identity_constraint(
builder_ptr, submod_bn254(result_eval, mulmod_bn254(lhs_eval, rhs_eval)), 2
)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_and_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_not_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function not_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, result_eval {
let input_eval
expr_ptr, input_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
result_eval := submod_bn254(chi_eval, input_eval)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_not_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_proof_expr_evaluate() {} // solhint-disable-line no-empty-blocks
// slither-disable-start cyclomatic-complexity
function proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, eval {
let proof_expr_variant := shr(UINT32_PADDING_BITS, calldataload(expr_ptr))
expr_ptr := add(expr_ptr, UINT32_SIZE)
switch proof_expr_variant
case 0 {
case_const(0, COLUMN_EXPR_VARIANT)
expr_ptr_out, eval := column_expr_evaluate(expr_ptr, accessor)
}
case 1 {
case_const(1, LITERAL_EXPR_VARIANT)
expr_ptr_out, eval := literal_expr_evaluate(expr_ptr, chi_eval)
}
case 2 {
case_const(2, EQUALS_EXPR_VARIANT)
expr_ptr_out, eval := equals_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
case 3 {
case_const(3, ADD_EXPR_VARIANT)
expr_ptr_out, eval := add_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
case 4 {
case_const(4, SUBTRACT_EXPR_VARIANT)
expr_ptr_out, eval := subtract_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
case 5 {
case_const(5, MULTIPLY_EXPR_VARIANT)
expr_ptr_out, eval := multiply_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
case 6 {
case_const(6, AND_EXPR_VARIANT)
expr_ptr_out, eval := and_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
case 7 {
case_const(7, OR_EXPR_VARIANT)
expr_ptr_out, eval := or_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
case 8 {
case_const(8, NOT_EXPR_VARIANT)
expr_ptr_out, eval := not_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
case 9 {
case_const(9, CAST_EXPR_VARIANT)
expr_ptr_out, eval := cast_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
case 10 {
case_const(10, INEQUALITY_EXPR_VARIANT)
expr_ptr_out, eval := inequality_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
case 11 {
case_const(11, PLACEHOLDER_EXPR_VARIANT)
expr_ptr_out, eval := placeholder_expr_evaluate(expr_ptr, builder_ptr, chi_eval)
}
case 12 {
case_const(12, SCALING_CAST_EXPR_VARIANT)
expr_ptr_out, eval := scaling_cast_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
default { err(ERR_UNSUPPORTED_PROOF_EXPR_VARIANT) }
}
// slither-disable-end cyclomatic-complexity
function exclude_coverage_stop_proof_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_subtract_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function subtract_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, result_eval {
let lhs_eval
expr_ptr, lhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
let rhs_eval
expr_ptr, rhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
result_eval := submod_bn254(lhs_eval, rhs_eval)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_subtract_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_or_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function or_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, result_eval {
let lhs_eval
expr_ptr, lhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
let rhs_eval
expr_ptr, rhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
let lhs_times_rhs_eval := builder_consume_final_round_mle(builder_ptr)
result_eval := submod_bn254(addmod_bn254(lhs_eval, rhs_eval), lhs_times_rhs_eval)
builder_produce_identity_constraint(
builder_ptr, submod_bn254(lhs_times_rhs_eval, mulmod_bn254(lhs_eval, rhs_eval)), 2
)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_or_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_multiply_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function multiply_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, result_eval {
let lhs_eval
expr_ptr, lhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
let rhs_eval
expr_ptr, rhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
result_eval := mod(builder_consume_final_round_mle(builder_ptr), MODULUS)
builder_produce_identity_constraint(
builder_ptr, submod_bn254(result_eval, mulmod_bn254(lhs_eval, rhs_eval)), 2
)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_multiply_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_cast_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function cast_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, result_eval {
let data_type
expr_ptr, data_type := read_data_type(expr_ptr)
expr_ptr_out, result_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
}
function exclude_coverage_stop_cast_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_add_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function add_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, result_eval {
let lhs_eval
expr_ptr, lhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
let rhs_eval
expr_ptr, rhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
result_eval := addmod_bn254(lhs_eval, rhs_eval)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_add_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_scaling_cast_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function scaling_cast_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, result_eval
{
let data_type
expr_ptr, data_type := read_data_type(expr_ptr)
// Evaluate the input expression
expr_ptr, result_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
// Read the scaling factor (256 bits)
let scaling_factor := calldataload(expr_ptr)
expr_ptr := add(expr_ptr, WORD_SIZE)
// Apply scaling by multiplying with the scaling factor
result_eval := mulmod_bn254(result_eval, scaling_factor)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_scaling_cast_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_inequality_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function inequality_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor) -> expr_ptr_out, result_eval {
let lhs_eval
expr_ptr, lhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
let rhs_eval
expr_ptr, rhs_eval := proof_expr_evaluate(expr_ptr, builder_ptr, chi_eval, accessor)
let is_lt := shr(BOOLEAN_PADDING_BITS, calldataload(expr_ptr))
expr_ptr := add(expr_ptr, BOOLEAN_SIZE)
let diff_eval
switch is_lt
case 0 { diff_eval := submod_bn254(rhs_eval, lhs_eval) }
default { diff_eval := submod_bn254(lhs_eval, rhs_eval) }
result_eval := sign_expr_evaluate(diff_eval, builder_ptr, chi_eval)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_inequality_expr_evaluate() {} // 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_column_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function column_expr_evaluate(expr_ptr, accessor) -> expr_ptr_out, eval {
let column_num := shr(UINT64_PADDING_BITS, calldataload(expr_ptr))
expr_ptr := add(expr_ptr, UINT64_SIZE)
eval := get_array_element(accessor, column_num)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_column_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_get_array_element() {} // solhint-disable-line no-empty-blocks
function get_array_element(arr, index) -> value {
let length := mload(arr)
if iszero(lt(index, length)) { err(ERR_INVALID_INDEX) }
value := mload(add(add(arr, WORD_SIZE), mul(index, WORD_SIZE)))
}
function exclude_coverage_stop_get_array_element() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_literal_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function literal_expr_evaluate(expr_ptr, chi_eval) -> expr_ptr_out, eval {
let literal_variant
expr_ptr, literal_variant := read_data_type(expr_ptr)
expr_ptr, eval := read_entry(expr_ptr, literal_variant)
eval := mulmod_bn254(eval, chi_eval)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_literal_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_entry() {} // solhint-disable-line no-empty-blocks
// slither-disable-start cyclomatic-complexity
function read_entry(result_ptr, data_type_variant) -> result_ptr_out, entry {
result_ptr_out := result_ptr
switch data_type_variant
case 0 {
case_const(0, DATA_TYPE_BOOLEAN_VARIANT)
entry := shr(BOOLEAN_PADDING_BITS, calldataload(result_ptr))
if shr(1, entry) { err(ERR_INVALID_BOOLEAN) }
result_ptr_out := add(result_ptr, BOOLEAN_SIZE)
entry := mod(entry, MODULUS)
}
case 2 {
case_const(2, DATA_TYPE_TINYINT_VARIANT)
entry :=
add(MODULUS, signextend(INT8_SIZE_MINUS_ONE, shr(INT8_PADDING_BITS, calldataload(result_ptr))))
result_ptr_out := add(result_ptr, INT8_SIZE)
entry := mod(entry, MODULUS)
}
case 3 {
case_const(3, DATA_TYPE_SMALLINT_VARIANT)
entry :=
add(MODULUS, signextend(INT16_SIZE_MINUS_ONE, shr(INT16_PADDING_BITS, calldataload(result_ptr))))
result_ptr_out := add(result_ptr, INT16_SIZE)
entry := mod(entry, MODULUS)
}
case 4 {
case_const(4, DATA_TYPE_INT_VARIANT)
entry :=
add(MODULUS, signextend(INT32_SIZE_MINUS_ONE, shr(INT32_PADDING_BITS, calldataload(result_ptr))))
result_ptr_out := add(result_ptr, INT32_SIZE)
entry := mod(entry, MODULUS)
}
case 5 {
case_const(5, DATA_TYPE_BIGINT_VARIANT)
entry :=
add(MODULUS, signextend(INT64_SIZE_MINUS_ONE, shr(INT64_PADDING_BITS, calldataload(result_ptr))))
result_ptr_out := add(result_ptr, INT64_SIZE)
entry := mod(entry, MODULUS)
}
case 7 {
case_const(7, DATA_TYPE_VARCHAR_VARIANT)
result_ptr_out, entry := read_binary(result_ptr)
}
case 8 {
case_const(8, DATA_TYPE_DECIMAL75_VARIANT)
entry := calldataload(result_ptr)
result_ptr_out := add(result_ptr, WORD_SIZE)
entry := mod(entry, MODULUS)
}
case 9 {
case_const(9, DATA_TYPE_TIMESTAMP_VARIANT)
entry :=
add(MODULUS, signextend(INT64_SIZE_MINUS_ONE, shr(INT64_PADDING_BITS, calldataload(result_ptr))))
result_ptr_out := add(result_ptr, INT64_SIZE)
entry := mod(entry, MODULUS)
}
case 10 {
case_const(10, DATA_TYPE_SCALAR_VARIANT)
entry := calldataload(result_ptr)
result_ptr_out := add(result_ptr, WORD_SIZE)
entry := mod(entry, MODULUS)
}
case 11 {
case_const(11, DATA_TYPE_VARBINARY_VARIANT)
result_ptr_out, entry := read_binary(result_ptr)
}
default { err(ERR_UNSUPPORTED_DATA_TYPE_VARIANT) }
}
// slither-disable-end cyclomatic-complexity
function exclude_coverage_stop_read_entry() {} // 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_placeholder_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function placeholder_expr_evaluate(expr_ptr, builder_ptr, chi_eval) -> expr_ptr_out, eval {
let placeholder_index := shr(UINT64_PADDING_BITS, calldataload(expr_ptr))
expr_ptr := add(expr_ptr, UINT64_SIZE)
// Read column type using read_data_type
let column_type
expr_ptr, column_type := read_data_type(expr_ptr)
// Get the placeholder parameter value from the builder
let parameter_value := builder_get_placeholder_parameter(builder_ptr, placeholder_index)
// Multiply by chi_eval (similar to how literals work)
eval := mulmod_bn254(parameter_value, chi_eval)
expr_ptr_out := expr_ptr
}
function exclude_coverage_stop_placeholder_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_placeholder_parameter() {} // solhint-disable-line no-empty-blocks
function builder_get_placeholder_parameter(builder_ptr, index) -> value {
value := get_array_element_from_ptr(add(builder_ptr, BUILDER_PLACEHOLDER_PARAMETERS_OFFSET), index)
}
function exclude_coverage_stop_builder_get_placeholder_parameter() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_get_array_element_from_ptr() {} // solhint-disable-line no-empty-blocks
function get_array_element_from_ptr(arr_ptr, index) -> value {
let arr := mload(arr_ptr)
value := get_array_element(arr, index)
}
function exclude_coverage_stop_get_array_element_from_ptr() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_sign_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function sign_expr_evaluate(expr_eval, builder_ptr, chi_eval) -> result_eval {
let vary_mask
let leading_bit_mask
vary_mask, leading_bit_mask := builder_consume_bit_distribution(builder_ptr)
// Other than the lead bit, no bit should vary past some max bit position, depending on the field
if and(vary_mask, MODULUS_INVALID_VARY_MASK) { err(ERR_INVALID_VARYING_BITS) }
// The lead bit of the leading_bit_mask dictates the sign, if it's constant sign.
// So this will be the value if sign is constant. Otherwise, it will be overwritten
let sign_eval := mulmod_bn254(shr(255, leading_bit_mask), chi_eval)
// For future computations, leading_bit_mask should have a 1 in the lead bit
leading_bit_mask := or(leading_bit_mask, shl(255, 1))
// leading_bit_inverse_mask identifies columns that match the inverse of the lead bit column
// So !vary_mask ^ leading_bit_mask, with a lead bit of zero.
let leading_bit_inverse_mask := shr(1, shl(1, xor(not(vary_mask), leading_bit_mask)))
// sum_eval should ultimately add up to the original column of data
// It will effectively be a recomposition of the bit decomposition
let sum_eval := 0
for { let i := 0 } vary_mask {
i := add(i, 1)
vary_mask := shr(1, vary_mask)
} {
if and(vary_mask, 1) {
// For any varying bits...
let bit_eval := builder_consume_final_round_mle(builder_ptr)
// Verify that every eval is a bit
// bit_eval - bit_eval * bit_eval = 0
builder_produce_identity_constraint(
builder_ptr, submod_bn254(bit_eval, mulmod_bn254(bit_eval, bit_eval)), 2
)
switch i
// If the lead bit varies, that we get the sign from the mles.
case 255 { sign_eval := bit_eval }
// For varying non lead bits,
// we add bit_eval * 2ⁱ to the sum in order to recompose the original value of the column
default { sum_eval := addmod_bn254(sum_eval, mulmod_bn254(bit_eval, shl(i, 1))) }
}
}
result_eval := submod_bn254(chi_eval, sign_eval)
// For constant and lead bits...
// sum += sign_eval * leading_bit_mask + (sign_eval - chi_eval) * leading_bit_inverse_mask - chi_eval * (1 << 255)
sum_eval :=
submod_bn254(
addmod_bn254(
addmod_bn254(sum_eval, mulmod_bn254(sign_eval, leading_bit_mask)),
mulmod_bn254(result_eval, leading_bit_inverse_mask)
),
mulmod_bn254(chi_eval, shl(255, 1))
)
// Verify the bit recomposition matches the original column evaluation
if sub(sum_eval, expr_eval) { err(ERR_BIT_DECOMPOSITION_INVALID) }
}
function exclude_coverage_stop_sign_expr_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_consume_bit_distribution() {} // solhint-disable-line no-empty-blocks
function builder_consume_bit_distribution(builder_ptr) -> vary_mask, leading_bit_mask {
let values_ptr := add(builder_ptr, BUILDER_FINAL_ROUND_BIT_DISTRIBUTIONS_OFFSET)
vary_mask, leading_bit_mask := dequeue_uint512(values_ptr)
}
function exclude_coverage_stop_builder_consume_bit_distribution() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_fold_expr_evals() {} // solhint-disable-line no-empty-blocks
function fold_expr_evals(plan_ptr, builder_ptr, input_chi_eval, beta, column_count, accessor) ->
plan_ptr_out,
fold
{
fold := 0
for {} column_count { column_count := sub(column_count, 1) } {
let expr_eval
plan_ptr, expr_eval := proof_expr_evaluate(plan_ptr, builder_ptr, input_chi_eval, accessor)
fold := addmod_bn254(mulmod_bn254(fold, beta), expr_eval)
}
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_fold_expr_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_fold_log_star_evaluate_from_expr_evals() {} // solhint-disable-line no-empty-blocks
function fold_log_star_evaluate_from_expr_evals(
plan_ptr, builder_ptr, input_chi_eval, alpha, beta, column_count, accessor
) -> plan_ptr_out, star {
let fold
plan_ptr, fold := fold_expr_evals(plan_ptr, builder_ptr, input_chi_eval, beta, column_count, accessor)
fold := mulmod_bn254(fold, alpha)
star := fold_log_star_evaluate_from_fold(builder_ptr, fold, input_chi_eval)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_fold_log_star_evaluate_from_expr_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_fold_log_star_evaluate_from_fold() {} // solhint-disable-line no-empty-blocks
function fold_log_star_evaluate_from_fold(builder_ptr, fold, chi_eval) -> star {
star := builder_consume_final_round_mle(builder_ptr)
// star + fold * star - chi = 0
builder_produce_identity_constraint(
builder_ptr, submod_bn254(addmod_bn254(star, mulmod_bn254(fold, star)), chi_eval), 2
)
}
function exclude_coverage_stop_fold_log_star_evaluate_from_fold() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_fold_log_star_evaluate_from_mles() {} // solhint-disable-line no-empty-blocks
function fold_log_star_evaluate_from_mles(builder_ptr, alpha, beta, column_count, chi_eval) ->
star,
evaluations_ptr
{
let fold
fold, star, evaluations_ptr :=
fold_log_evaluate_from_mles(builder_ptr, alpha, beta, column_count, chi_eval)
}
function exclude_coverage_stop_fold_log_star_evaluate_from_mles() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_fold_log_evaluate_from_mles() {} // solhint-disable-line no-empty-blocks
function fold_log_evaluate_from_mles(builder_ptr, alpha, beta, column_count, chi_eval) ->
fold,
star,
evaluations_ptr
{
fold, evaluations_ptr := fold_first_round_mles(builder_ptr, beta, column_count)
fold := mulmod_bn254(alpha, fold)
star := fold_log_star_evaluate_from_fold(builder_ptr, fold, chi_eval)
}
function exclude_coverage_stop_fold_log_evaluate_from_mles() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_monotonic_verify() {} // solhint-disable-line no-empty-blocks
function monotonic_verify(builder_ptr, alpha, beta, column_eval, chi_eval, strict, asc) {
// 1. Verify that `shifted_column` is a shift of `column`
let shifted_column_eval, shifted_chi_eval :=
shift_evaluate(builder_ptr, alpha, beta, column_eval, chi_eval)
// 2. Compute indicator evaluation based on strictness and direction
let ind_eval
switch eq(strict, asc)
case 1 {
// (strict && asc) || (!strict && !asc): ind = shifted_column - column
ind_eval := submod_bn254(shifted_column_eval, column_eval)
}
default {
// (!strict && asc) || (strict && !asc): ind = column - shifted_column
ind_eval := submod_bn254(column_eval, shifted_column_eval)
}
// 3. Verify the sign of `ind`
let sign_eval := sign_expr_evaluate(ind_eval, builder_ptr, shifted_chi_eval)
let singleton_chi_eval := builder_get_singleton_chi_evaluation(builder_ptr)
// 4. Check if sign_eval is in allowed evaluations
let is_valid := 0
switch strict
case 1 {
// Strict monotonicity: sign(ind) == 1 for all but first and last element
// Allowed evaluations: chi_eval, shifted_chi_eval - singleton_chi_eval, chi_eval - singleton_chi_eval
is_valid :=
or(
or(eq(sign_eval, chi_eval), eq(sign_eval, submod_bn254(shifted_chi_eval, singleton_chi_eval))),
eq(sign_eval, submod_bn254(chi_eval, singleton_chi_eval))
)
}
default {
// Non-strict monotonicity: sign(ind) == 0 for all but first and last element
// Allowed evaluations: singleton_chi_eval, shifted_chi_eval - chi_eval,
// singleton_chi_eval + shifted_chi_eval - chi_eval, 0
is_valid :=
or(
or(eq(sign_eval, singleton_chi_eval), eq(sign_eval, submod_bn254(shifted_chi_eval, chi_eval))),
or(
eq(sign_eval, submod_bn254(addmod_bn254(singleton_chi_eval, shifted_chi_eval), chi_eval)),
iszero(sign_eval)
)
)
}
if iszero(is_valid) { err(ERR_MONOTONY_CHECK_FAILED) }
}
function exclude_coverage_stop_monotonic_verify() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_singleton_chi_evaluation() {} // solhint-disable-line no-empty-blocks
function builder_get_singleton_chi_evaluation(builder_ptr) -> value {
value := mload(add(builder_ptr, BUILDER_SINGLETON_CHI_EVALUATION_OFFSET))
}
function exclude_coverage_stop_builder_get_singleton_chi_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_shift_evaluate() {} // solhint-disable-line no-empty-blocks
function shift_evaluate(builder_ptr, alpha, beta, expr_eval, chi_eval) ->
shifted_expr_eval,
chi_plus_one_eval
{
chi_plus_one_eval := builder_consume_chi_evaluation(builder_ptr)
shifted_expr_eval := builder_consume_first_round_mle(builder_ptr)
let rho_eval := builder_consume_rho_evaluation(builder_ptr)
let rho_plus_one_eval := builder_consume_rho_evaluation(builder_ptr)
let c_star_eval := builder_consume_final_round_mle(builder_ptr)
let d_star_eval := builder_consume_final_round_mle(builder_ptr)
// sum c_star - d_star = 0
builder_produce_zerosum_constraint(builder_ptr, submod_bn254(c_star_eval, d_star_eval), 1)
// c_star + c_fold * c_star - chi_n_plus_1 = 0
{
let c_fold := compute_shift_fold(alpha, beta, expr_eval, addmod_bn254(rho_eval, chi_eval))
builder_produce_identity_constraint(
builder_ptr, compute_shift_identity_constraint(c_star_eval, chi_plus_one_eval, c_fold), 2
)
}
// d_star + d_fold * d_star - chi_n_plus_1 = 0
{
let d_fold := compute_shift_fold(alpha, beta, shifted_expr_eval, rho_plus_one_eval)
builder_produce_identity_constraint(
builder_ptr, compute_shift_identity_constraint(d_star_eval, chi_plus_one_eval, d_fold), 2
)
}
}
function exclude_coverage_stop_shift_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_shift_identity_constraint() {} // solhint-disable-line no-empty-blocks
function compute_shift_identity_constraint(star, chi_plus_one, fold) -> constraint {
constraint := addmod_bn254(submod_bn254(star, chi_plus_one), mulmod_bn254(fold, star))
}
function exclude_coverage_stop_compute_shift_identity_constraint() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_consume_chi_evaluation() {} // solhint-disable-line no-empty-blocks
function builder_consume_chi_evaluation(builder_ptr) -> value {
let length
length, value := dequeue_uint512(add(builder_ptr, BUILDER_CHI_EVALUATIONS_OFFSET))
}
function exclude_coverage_stop_builder_consume_chi_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_consume_rho_evaluation() {} // solhint-disable-line no-empty-blocks
function builder_consume_rho_evaluation(builder_ptr) -> value {
value := dequeue(add(builder_ptr, BUILDER_RHO_EVALUATIONS_OFFSET))
}
function exclude_coverage_stop_builder_consume_rho_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_shift_fold() {} // solhint-disable-line no-empty-blocks
function compute_shift_fold(alpha, beta, eval, rho) -> fold {
fold := mulmod_bn254(alpha, addmod_bn254(mulmod_bn254(beta, rho), eval))
}
function exclude_coverage_stop_compute_shift_fold() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_table_chi_evaluation() {} // solhint-disable-line no-empty-blocks
function builder_get_table_chi_evaluation(builder_ptr, table_num) -> value {
let length
length, value :=
get_uint512_array_element(add(builder_ptr, BUILDER_TABLE_CHI_EVALUATIONS_OFFSET), table_num)
}
function exclude_coverage_stop_builder_get_table_chi_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_get_uint512_array_element() {} // solhint-disable-line no-empty-blocks
function get_uint512_array_element(arr_ptr, index) -> upper, lower {
let arr := mload(arr_ptr)
let length := mload(arr)
if iszero(lt(index, length)) { err(ERR_INVALID_INDEX) }
let element_ptr := add(add(arr, WORD_SIZE), mul(index, WORDX2_SIZE))
upper := mload(element_ptr)
lower := mload(add(element_ptr, WORD_SIZE))
}
function exclude_coverage_stop_get_uint512_array_element() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_membership_check_evaluate() {} // solhint-disable-line no-empty-blocks
function membership_check_evaluate(
builder_ptr, alpha, beta, chi_n_eval, chi_m_eval, column_evals, candidate_evals
) -> multiplicity_eval {
let num_columns := mload(column_evals)
let num_candidate_columns := mload(candidate_evals)
if sub(num_columns, num_candidate_columns) { err(ERR_INTERNAL) }
multiplicity_eval := builder_consume_first_round_mle(builder_ptr)
let c_star_eval := fold_log_star_evaluate(builder_ptr, alpha, beta, column_evals, chi_n_eval)
let d_star_eval := fold_log_star_evaluate(builder_ptr, alpha, beta, candidate_evals, chi_m_eval)
// sum c_star * multiplicity_eval - d_star = 0
builder_produce_zerosum_constraint(
builder_ptr, submod_bn254(mulmod_bn254(c_star_eval, multiplicity_eval), d_star_eval), 2
)
}
function exclude_coverage_stop_membership_check_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_fold_log_star_evaluate() {} // solhint-disable-line no-empty-blocks
function fold_log_star_evaluate(builder_ptr, alpha, beta, column_evals, chi_eval) -> star {
let fold := mulmod_bn254(alpha, compute_fold(beta, column_evals))
star := fold_log_star_evaluate_from_fold(builder_ptr, fold, chi_eval)
}
function exclude_coverage_stop_fold_log_star_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_empty_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function empty_exec_evaluate(builder_ptr) -> evaluations_ptr, output_length, output_chi_eval {
evaluations_ptr := mload(FREE_PTR)
mstore(evaluations_ptr, 0)
mstore(FREE_PTR, add(evaluations_ptr, WORD_SIZE))
output_chi_eval := builder_get_singleton_chi_evaluation(builder_ptr)
output_length := 1
}
function exclude_coverage_stop_empty_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_table_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function table_exec_evaluate(plan_ptr, builder_ptr) ->
plan_ptr_out,
evaluations_ptr,
output_length,
output_chi_eval
{
let table_number := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
output_length, output_chi_eval :=
builder_get_table_chi_evaluation_with_length(builder_ptr, table_number)
// Get the number of columns in the schema
let column_count := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
let copy_size := add(WORD_SIZE, mul(column_count, WORD_SIZE))
plan_ptr := add(plan_ptr, UINT64_SIZE)
// Initialize evaluations array to store column evaluations
evaluations_ptr := mload(FREE_PTR)
mstore(evaluations_ptr, column_count)
// Read column evaluations for each field in the schema
for {} column_count { column_count := sub(column_count, 1) } {
evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
// For each column in schema, get its column number/index
let column_num := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
// Get the column evaluation from the builder
let column_eval := builder_get_column_evaluation(builder_ptr, column_num)
// Store the column evaluation in the result
mstore(evaluations_ptr, column_eval)
}
// Reset evaluations_ptr to the beginning of the array
evaluations_ptr := mload(FREE_PTR)
// Update free memory pointer
mstore(FREE_PTR, add(evaluations_ptr, copy_size))
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_table_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_column_evaluation() {} // solhint-disable-line no-empty-blocks
function builder_get_column_evaluation(builder_ptr, column_num) -> value {
value := get_array_element_from_ptr(add(builder_ptr, BUILDER_COLUMN_EVALUATIONS_OFFSET), column_num)
}
function exclude_coverage_stop_builder_get_column_evaluation() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_builder_get_table_chi_evaluation_with_length() {} // solhint-disable-line no-empty-blocks
function builder_get_table_chi_evaluation_with_length(builder_ptr, table_num) -> length, chi_eval {
length, chi_eval :=
get_uint512_array_element(add(builder_ptr, BUILDER_TABLE_CHI_EVALUATIONS_OFFSET), table_num)
}
function exclude_coverage_stop_builder_get_table_chi_evaluation_with_length() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_group_by_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function group_by_exec_evaluate(plan_ptr, builder_ptr) ->
plan_ptr_out,
evaluations_ptr,
output_length,
output_chi_eval
{
let alpha := builder_consume_challenge(builder_ptr)
let beta := builder_consume_challenge(builder_ptr)
let partial_dlog_zero_sum_constraint_eval, num_sum_columns
{
let num_group_by_columns
plan_ptr_out, partial_dlog_zero_sum_constraint_eval, num_sum_columns, num_group_by_columns :=
read_input_evals(plan_ptr, builder_ptr, alpha, beta)
// We reuse plan_ptr to save on variable space
plan_ptr := num_group_by_columns
}
// Read output
// For now, we can assume the number of group by columns is 1,
// because the function would have errored by this point otherwise
evaluations_ptr, output_length, output_chi_eval :=
read_output_evals(
builder_ptr,
alpha,
beta,
partial_dlog_zero_sum_constraint_eval,
// Recall that plan_ptr is really num_group_by_columns here
plan_ptr,
num_sum_columns
)
}
function exclude_coverage_stop_group_by_exec_evaluate() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_input_evals() {} // solhint-disable-line no-empty-blocks
function read_input_evals(plan_ptr, builder_ptr, alpha, beta) ->
plan_ptr_out,
partial_dlog_zero_sum_constraint_eval,
num_sum_columns,
num_group_by_columns
{
// Read input chi evaluation
let input_chi_eval
{
let table_num := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
input_chi_eval := builder_get_table_chi_evaluation(builder_ptr, table_num)
plan_ptr := add(plan_ptr, UINT64_SIZE)
}
// Read/eval group by inputs, selection inputs, and fold and dlog them
let g_in_star_eval_times_selection_eval
plan_ptr, g_in_star_eval_times_selection_eval, num_group_by_columns :=
compute_g_in_star_eval(plan_ptr, builder_ptr, alpha, beta, input_chi_eval)
// Read/eval sum inputs and fold them
let sum_in_fold_eval
plan_ptr, sum_in_fold_eval, num_sum_columns :=
compute_sum_in_fold_eval(plan_ptr, builder_ptr, alpha, beta, input_chi_eval)
partial_dlog_zero_sum_constraint_eval :=
mulmod_bn254(g_in_star_eval_times_selection_eval, sum_in_fold_eval)
// Read count alias
{
let count_alias
plan_ptr, count_alias := read_binary(plan_ptr)
}
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_read_input_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_sum_in_fold_eval() {} // solhint-disable-line no-empty-blocks
function compute_sum_in_fold_eval(plan_ptr, builder_ptr, alpha, beta, input_chi_eval) ->
plan_ptr_out,
sum_in_fold_eval,
num_sum_columns
{
num_sum_columns := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
plan_ptr, sum_in_fold_eval :=
fold_expr_evals(
plan_ptr,
builder_ptr,
input_chi_eval,
beta,
num_sum_columns,
builder_get_column_evaluations(builder_ptr)
)
sum_in_fold_eval := addmod_bn254(mulmod_bn254(sum_in_fold_eval, beta), input_chi_eval)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_compute_sum_in_fold_eval() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_g_in_star_eval() {} // solhint-disable-line no-empty-blocks
function compute_g_in_star_eval(plan_ptr, builder_ptr, alpha, beta, input_chi_eval) ->
plan_ptr_out,
g_in_star_eval_times_selection_eval,
num_group_by_columns
{
num_group_by_columns := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
// We can not prove uniqueness for multiple columns yet
if gt(num_group_by_columns, 1) { err(ERR_UNPROVABLE_GROUP_BY) }
plan_ptr := add(plan_ptr, UINT64_SIZE)
// Process group by columns
let g_in_star_eval
plan_ptr, g_in_star_eval :=
fold_log_star_evaluate_from_column_exprs(
plan_ptr,
builder_ptr,
alpha,
beta,
num_group_by_columns,
input_chi_eval,
builder_get_column_evaluations(builder_ptr)
)
let selection_eval
plan_ptr, selection_eval :=
proof_expr_evaluate(plan_ptr, builder_ptr, input_chi_eval, builder_get_column_evaluations(builder_ptr))
g_in_star_eval_times_selection_eval := mulmod_bn254(g_in_star_eval, selection_eval)
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_compute_g_in_star_eval() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_fold_log_star_evaluate_from_column_exprs() {} // solhint-disable-line no-empty-blocks
function fold_log_star_evaluate_from_column_exprs(
plan_ptr, builder_ptr, alpha, beta, column_count, chi_eval, accessor
) -> plan_ptr_out, star {
let fold
plan_ptr_out, fold := fold_column_expr_evals(plan_ptr, accessor, beta, column_count)
fold := mulmod_bn254(alpha, fold)
star := fold_log_star_evaluate_from_fold(builder_ptr, fold, chi_eval)
}
function exclude_coverage_stop_fold_log_star_evaluate_from_column_exprs() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_fold_column_expr_evals() {} // solhint-disable-line no-empty-blocks
function fold_column_expr_evals(plan_ptr, accessor, beta, column_count) -> plan_ptr_out, fold {
fold := 0
for {} column_count { column_count := sub(column_count, 1) } {
let expr_eval
plan_ptr, expr_eval := column_expr_evaluate(plan_ptr, accessor)
fold := addmod_bn254(mulmod_bn254(fold, beta), expr_eval)
}
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_fold_column_expr_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_output_evals() {} // solhint-disable-line no-empty-blocks
function read_output_evals(
builder_ptr, alpha, beta, partial_dlog_zero_sum_constraint_eval, num_group_by_columns, num_sum_columns
) -> evaluations_ptr, output_length, output_chi_eval {
num_sum_columns := add(num_sum_columns, 1)
// Allocate memory for evaluations
{
let free_ptr := mload(FREE_PTR)
evaluations_ptr := free_ptr
let num_evals := add(num_group_by_columns, num_sum_columns)
mstore(free_ptr, num_evals)
free_ptr := add(free_ptr, WORD_SIZE)
free_ptr := add(free_ptr, mul(num_evals, WORD_SIZE))
mstore(FREE_PTR, free_ptr)
}
output_length, output_chi_eval := builder_consume_chi_evaluation_with_length(builder_ptr)
let g_out_star_eval
g_out_star_eval :=
compute_g_out_star_eval(
builder_ptr, alpha, beta, output_chi_eval, add(evaluations_ptr, WORD_SIZE), num_group_by_columns
)
let sum_out_fold_eval :=
compute_sum_out_fold_eval(
builder_ptr,
alpha,
beta,
output_chi_eval,
num_sum_columns,
add(evaluations_ptr, mul(num_group_by_columns, WORD_SIZE))
)
builder_produce_zerosum_constraint(
builder_ptr,
submod_bn254(
partial_dlog_zero_sum_constraint_eval, mulmod_bn254(g_out_star_eval, sum_out_fold_eval)
),
3
)
}
function exclude_coverage_stop_read_output_evals() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_compute_sum_out_fold_eval() {} // solhint-disable-line no-empty-blocks
function compute_sum_out_fold_eval(
builder_ptr, alpha, beta, output_chi_eval, num_sum_columns, evaluations_ptr
) -> sum_out_fold_eval {
sum_out_fold_eval := 0
for {} num_sum_columns { num_sum_columns := sub(num_sum_columns, 1) } {
// We increment evaluations_ptr first to avoid an unneceesary addition,
// Which means the value we pass in for evaluations_ptr should be adjusted accordingly
evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
let mle := builder_consume_first_round_mle(builder_ptr)
sum_out_fold_eval := addmod_bn254(mulmod_bn254(sum_out_fold_eval, beta), mle)
mstore(evaluations_ptr, mle)
}
}
function exclude_coverage_stop_compute_sum_out_fold_eval() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_skip_plan_names() {} // solhint-disable-line no-empty-blocks
function skip_plan_names(plan_ptr) -> plan_ptr_out {
// skip over the table names
let num_tables := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
for {} num_tables { num_tables := sub(num_tables, 1) } {
let name_len := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, add(UINT64_SIZE, name_len))
}
// skip over the column names
let num_columns := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
for {} num_columns { num_columns := sub(num_columns, 1) } {
plan_ptr := add(plan_ptr, UINT64_SIZE)
let name_len := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, add(UINT64_SIZE, name_len))
let data_type
plan_ptr, data_type := read_data_type(plan_ptr)
}
// skip over the output column names
let num_outputs := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, UINT64_SIZE)
for {} num_outputs { num_outputs := sub(num_outputs, 1) } {
let name_len := shr(UINT64_PADDING_BITS, calldataload(plan_ptr))
plan_ptr := add(plan_ptr, add(UINT64_SIZE, name_len))
}
plan_ptr_out := plan_ptr
}
function exclude_coverage_stop_skip_plan_names() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_verify_result_evaluations() {} // solhint-disable-line no-empty-blocks
function verify_result_evaluations(result_ptr, evaluation_point_ptr, evaluations_ptr) {
let num_columns := shr(UINT64_PADDING_BITS, calldataload(result_ptr))
result_ptr := add(result_ptr, UINT64_SIZE)
if sub(num_columns, mload(evaluations_ptr)) { err(ERR_RESULT_COLUMN_COUNT_MISMATCH) }
evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
let first := 1
let table_len
let eval_vec
for {} num_columns { num_columns := sub(num_columns, 1) } {
let name_length := shr(UINT64_PADDING_BITS, calldataload(result_ptr))
result_ptr := add(result_ptr, add(UINT64_SIZE, name_length))
if byte(0, calldataload(result_ptr)) { err(ERR_INVALID_RESULT_COLUMN_NAME) }
result_ptr := add(result_ptr, 1)
let value := mload(evaluations_ptr)
evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
let data_type_variant
result_ptr, data_type_variant := read_data_type(result_ptr)
let column_length := shr(UINT64_PADDING_BITS, calldataload(result_ptr))
result_ptr := add(result_ptr, UINT64_SIZE)
if first {
first := 0
table_len := column_length
eval_vec := compute_evaluation_vec(table_len, evaluation_point_ptr)
}
if sub(table_len, column_length) { err(ERR_INCONSISTENT_RESULT_COLUMN_LENGTHS) }
value := mulmod(MODULUS_MINUS_ONE, value, MODULUS)
let temp_eval_vec := eval_vec
for { let i := table_len } i { i := sub(i, 1) } {
let entry
result_ptr, entry := read_entry(result_ptr, data_type_variant)
value := addmod_bn254(value, mulmod_bn254(entry, mload(temp_eval_vec)))
temp_eval_vec := add(temp_eval_vec, WORD_SIZE)
}
if value { err(ERR_INCORRECT_RESULT) }
}
}
function exclude_coverage_stop_verify_result_evaluations() {} // solhint-disable-line no-empty-blocks
function read_first_round_message(proof_ptr_init, transcript_ptr, builder_ptr) ->
proof_ptr,
range_length,
num_challenges
{
proof_ptr := proof_ptr_init
range_length := shr(UINT64_PADDING_BITS, calldataload(proof_ptr))
proof_ptr := add(proof_ptr, UINT64_SIZE)
num_challenges := shr(UINT64_PADDING_BITS, calldataload(proof_ptr))
proof_ptr := add(proof_ptr, UINT64_SIZE)
let array_ptr
proof_ptr, array_ptr := read_uint64_array_as_uint512_array(proof_ptr)
builder_set_chi_evaluations(builder_ptr, array_ptr)
proof_ptr, array_ptr := read_uint64_array(proof_ptr)
builder_set_rho_evaluations(builder_ptr, array_ptr)
proof_ptr, array_ptr := read_wordx2_array(proof_ptr)
builder_set_first_round_commitments(builder_ptr, array_ptr)
append_calldata(transcript_ptr, proof_ptr_init, sub(proof_ptr, proof_ptr_init))
}
function read_final_round_message(proof_ptr_init, transcript_ptr, builder_ptr) -> proof_ptr, num_constraints
{
proof_ptr := proof_ptr_init
num_constraints := shr(UINT64_PADDING_BITS, calldataload(proof_ptr))
proof_ptr := add(proof_ptr, UINT64_SIZE)
let array_ptr
proof_ptr, array_ptr := read_wordx2_array(proof_ptr)
builder_set_final_round_commitments(builder_ptr, array_ptr)
proof_ptr, array_ptr := read_wordx2_array(proof_ptr)
builder_set_bit_distributions(builder_ptr, array_ptr)
append_calldata(transcript_ptr, proof_ptr_init, sub(proof_ptr, proof_ptr_init))
}
function read_and_verify_sumcheck_proof(proof_ptr_init, transcript_ptr, builder_ptr, num_vars) ->
proof_ptr,
evaluation_point_ptr
{
let expected_evaluation, sumcheck_degree
proof_ptr, evaluation_point_ptr, expected_evaluation, sumcheck_degree :=
verify_sumcheck_proof(transcript_ptr, proof_ptr_init, num_vars)
builder_set_aggregate_evaluation(builder_ptr, mulmod_bn254(MODULUS_MINUS_ONE, expected_evaluation))
builder_set_max_degree(builder_ptr, sumcheck_degree)
}
function read_pcs_evaluations(proof_ptr_init, transcript_ptr, builder_ptr) -> proof_ptr {
proof_ptr := proof_ptr_init
let array_ptr
proof_ptr, array_ptr := read_word_array(proof_ptr)
builder_set_first_round_mles(builder_ptr, array_ptr)
proof_ptr, array_ptr := read_word_array(proof_ptr)
builder_set_column_evaluations(builder_ptr, array_ptr)
proof_ptr, array_ptr := read_word_array(proof_ptr)
builder_set_final_round_mles(builder_ptr, array_ptr)
append_calldata(transcript_ptr, proof_ptr_init, sub(proof_ptr, proof_ptr_init))
}
// TODO: possibly move this to another file and add unit tests
function verify_pcs_evaluations(
proof_ptr, commitments_ptr, transcript_ptr, builder_ptr, evaluation_point_ptr
) {
let batch_commitment_ptr := mload(FREE_PTR)
mstore(FREE_PTR, add(batch_commitment_ptr, WORDX5_SIZE))
mstore(batch_commitment_ptr, 0)
mstore(add(batch_commitment_ptr, WORD_SIZE), 0)
let batch_eval := 0
batch_eval :=
batch_pcs(
batch_commitment_ptr,
transcript_ptr,
builder_get_first_round_commitments(builder_ptr),
builder_get_first_round_mles(builder_ptr),
batch_eval
)
batch_eval :=
batch_pcs(
batch_commitment_ptr,
transcript_ptr,
commitments_ptr,
builder_get_column_evaluations(builder_ptr),
batch_eval
)
batch_eval :=
batch_pcs(
batch_commitment_ptr,
transcript_ptr,
builder_get_final_round_commitments(builder_ptr),
builder_get_final_round_mles(builder_ptr),
batch_eval
)
verify_hyperkzg(proof_ptr, transcript_ptr, batch_commitment_ptr, evaluation_point_ptr, batch_eval)
}
function make_transcript(result_ptr, plan_ptr, table_lengths_ptr, commitments_ptr) -> transcript_ptr {
transcript_ptr := mload(FREE_PTR)
mstore(FREE_PTR, add(transcript_ptr, WORD_SIZE))
mstore(transcript_ptr, INITIAL_TRANSCRIPT_STATE)
append_calldata(transcript_ptr, plan_ptr, calldataload(sub(plan_ptr, WORD_SIZE)))
append_calldata(transcript_ptr, result_ptr, calldataload(sub(result_ptr, WORD_SIZE)))
append_array(transcript_ptr, table_lengths_ptr)
let commitment_len := mload(commitments_ptr)
mstore(commitments_ptr, mul(commitment_len, 2))
append_array(transcript_ptr, commitments_ptr)
mstore(commitments_ptr, commitment_len)
mstore(mload(FREE_PTR), mload(transcript_ptr))
mstore(add(mload(FREE_PTR), WORD_SIZE), 0)
mstore(transcript_ptr, keccak256(mload(FREE_PTR), add(UINT64_SIZE, WORD_SIZE)))
}
function verify_proof(
result_ptr, plan_ptr, proof_ptr, table_lengths_ptr, commitments_ptr, placeholder_params_ptr
) -> evaluation_point_ptr, evaluations_ptr {
let transcript_ptr := make_transcript(result_ptr, plan_ptr, table_lengths_ptr, commitments_ptr)
let builder_ptr := builder_new()
builder_set_table_chi_evaluations(builder_ptr, table_lengths_ptr)
builder_set_placeholder_parameters(builder_ptr, placeholder_params_ptr)
let range_length
{
let num_challenges
proof_ptr, range_length, num_challenges :=
read_first_round_message(proof_ptr, transcript_ptr, builder_ptr)
builder_set_challenges(builder_ptr, draw_challenges(transcript_ptr, num_challenges))
}
{
let num_constraints
proof_ptr, num_constraints := read_final_round_message(proof_ptr, transcript_ptr, builder_ptr)
builder_set_constraint_multipliers(builder_ptr, draw_challenges(transcript_ptr, num_constraints))
}
let num_vars := log2_up(range_length)
let row_multipliers_challenges := draw_challenges(transcript_ptr, num_vars)
proof_ptr, evaluation_point_ptr :=
read_and_verify_sumcheck_proof(proof_ptr, transcript_ptr, builder_ptr, num_vars)
proof_ptr := read_pcs_evaluations(proof_ptr, transcript_ptr, builder_ptr)
verify_pcs_evaluations(proof_ptr, commitments_ptr, transcript_ptr, builder_ptr, evaluation_point_ptr)
table_lengths_ptr := read_word_array_as_uint512_array(table_lengths_ptr)
builder_set_table_chi_evaluations(builder_ptr, table_lengths_ptr)
compute_evaluations_with_length(evaluation_point_ptr, table_lengths_ptr)
compute_evaluations_with_length(evaluation_point_ptr, builder_get_chi_evaluations(builder_ptr))
builder_set_singleton_chi_evaluation(
builder_ptr, compute_truncated_lagrange_basis_sum(1, add(evaluation_point_ptr, WORD_SIZE), num_vars)
)
compute_rho_evaluations(evaluation_point_ptr, builder_get_rho_evaluations(builder_ptr))
builder_set_row_multipliers_evaluation(
builder_ptr,
compute_truncated_lagrange_basis_inner_product(
range_length,
add(row_multipliers_challenges, WORD_SIZE),
add(evaluation_point_ptr, WORD_SIZE),
num_vars
)
)
plan_ptr := skip_plan_names(plan_ptr)
{
let output_length, output_chi_eval
plan_ptr, evaluations_ptr, output_length, output_chi_eval :=
proof_plan_evaluate(plan_ptr, builder_ptr)
}
builder_check_aggregate_evaluation(builder_ptr)
}
function verify_query(
result_ptr, plan_ptr, placeholder_params_ptr, proof_ptr, table_lengths_ptr, commitments_ptr
) {
let evaluation_point_ptr, evaluations_ptr :=
verify_proof(
result_ptr, plan_ptr, proof_ptr, table_lengths_ptr, commitments_ptr, placeholder_params_ptr
)
verify_result_evaluations(result_ptr, evaluation_point_ptr, evaluations_ptr)
}
// Revert if the commitments array has an odd length
let commitments_len := mload(__commitments)
if mod(commitments_len, 2) { err(ERR_COMMITMENT_ARRAY_ODD_LENGTH) }
mstore(__commitments, div(commitments_len, 2))
verify_query(
__result.offset, __plan.offset, __placeholderParameters, __proof.offset, __tableLengths, __commitments
)
}
}
}// 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";
/// @title ParamsBuilder
/// @dev Library for constructing an array of sql params
library ParamsBuilder {
/// @dev Returns a serialized array of parameters
/// @param arrayOfSerializedParamElements An array of serialized parameters
/// @return serializedParams The serialized array of parameters
function serializeParamArray(bytes[] memory arrayOfSerializedParamElements)
internal
pure
returns (bytes memory serializedParams)
{
uint256 uncastLength = arrayOfSerializedParamElements.length;
if (uncastLength > MAX_UINT64) {
revert Errors.TooManyParameters();
} else {
uint64 length = uint64(uncastLength);
serializedParams = abi.encodePacked(length);
for (uint64 i = 0; i < length; ++i) {
serializedParams = abi.encodePacked(serializedParams, arrayOfSerializedParamElements[i]);
}
}
}
/// @dev Returns an array of parameters
/// @param serializedParams The serialized parameters
/// @return params The parameters as scalars
function deserializeParamArray(bytes calldata serializedParams) internal pure returns (uint256[] memory params) {
uint64 length;
assembly {
length := shr(UINT64_PADDING_BITS, calldataload(serializedParams.offset))
}
params = new uint256[](length);
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_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_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_read_entry() {} // solhint-disable-line no-empty-blocks
// slither-disable-start cyclomatic-complexity
function read_entry(result_ptr, data_type_variant) -> result_ptr_out, entry {
result_ptr_out := result_ptr
switch data_type_variant
case 0 {
case_const(0, DATA_TYPE_BOOLEAN_VARIANT)
entry := shr(BOOLEAN_PADDING_BITS, calldataload(result_ptr))
if shr(1, entry) { err(ERR_INVALID_BOOLEAN) }
result_ptr_out := add(result_ptr, BOOLEAN_SIZE)
entry := mod(entry, MODULUS)
}
case 2 {
case_const(2, DATA_TYPE_TINYINT_VARIANT)
entry :=
add(MODULUS, signextend(INT8_SIZE_MINUS_ONE, shr(INT8_PADDING_BITS, calldataload(result_ptr))))
result_ptr_out := add(result_ptr, INT8_SIZE)
entry := mod(entry, MODULUS)
}
case 3 {
case_const(3, DATA_TYPE_SMALLINT_VARIANT)
entry :=
add(MODULUS, signextend(INT16_SIZE_MINUS_ONE, shr(INT16_PADDING_BITS, calldataload(result_ptr))))
result_ptr_out := add(result_ptr, INT16_SIZE)
entry := mod(entry, MODULUS)
}
case 4 {
case_const(4, DATA_TYPE_INT_VARIANT)
entry :=
add(MODULUS, signextend(INT32_SIZE_MINUS_ONE, shr(INT32_PADDING_BITS, calldataload(result_ptr))))
result_ptr_out := add(result_ptr, INT32_SIZE)
entry := mod(entry, MODULUS)
}
case 5 {
case_const(5, DATA_TYPE_BIGINT_VARIANT)
entry :=
add(MODULUS, signextend(INT64_SIZE_MINUS_ONE, shr(INT64_PADDING_BITS, calldataload(result_ptr))))
result_ptr_out := add(result_ptr, INT64_SIZE)
entry := mod(entry, MODULUS)
}
case 7 {
case_const(7, DATA_TYPE_VARCHAR_VARIANT)
result_ptr_out, entry := read_binary(result_ptr)
}
case 8 {
case_const(8, DATA_TYPE_DECIMAL75_VARIANT)
entry := calldataload(result_ptr)
result_ptr_out := add(result_ptr, WORD_SIZE)
entry := mod(entry, MODULUS)
}
case 9 {
case_const(9, DATA_TYPE_TIMESTAMP_VARIANT)
entry :=
add(MODULUS, signextend(INT64_SIZE_MINUS_ONE, shr(INT64_PADDING_BITS, calldataload(result_ptr))))
result_ptr_out := add(result_ptr, INT64_SIZE)
entry := mod(entry, MODULUS)
}
case 10 {
case_const(10, DATA_TYPE_SCALAR_VARIANT)
entry := calldataload(result_ptr)
result_ptr_out := add(result_ptr, WORD_SIZE)
entry := mod(entry, MODULUS)
}
case 11 {
case_const(11, DATA_TYPE_VARBINARY_VARIANT)
result_ptr_out, entry := read_binary(result_ptr)
}
default { err(ERR_UNSUPPORTED_DATA_TYPE_VARIANT) }
}
// slither-disable-end cyclomatic-complexity
function exclude_coverage_stop_read_entry() {} // solhint-disable-line no-empty-blocks
function exclude_coverage_start_read_binary() {} // solhint-disable-line no-empty-blocks
function read_binary(result_ptr) -> result_ptr_out, entry {
let free_ptr := mload(FREE_PTR)
let len := shr(UINT64_PADDING_BITS, calldataload(result_ptr))
result_ptr := add(result_ptr, UINT64_SIZE)
// temps with their empty‐slice defaults
entry := 0
// only run this when len != 0
if len {
calldatacopy(free_ptr, result_ptr, len)
let hash_val := keccak256(free_ptr, len)
// endian-swap steps
hash_val :=
or(
shr(128, and(hash_val, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000)),
shl(128, and(hash_val, 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
)
hash_val :=
or(
shr(64, and(hash_val, 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000)),
shl(64, and(hash_val, 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF))
)
hash_val :=
or(
shr(32, and(hash_val, 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000)),
shl(32, and(hash_val, 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF))
)
hash_val :=
or(
shr(16, and(hash_val, 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000)),
shl(16, and(hash_val, 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF))
)
hash_val :=
or(
shr(8, and(hash_val, 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00)),
shl(8, and(hash_val, 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF))
)
entry := and(hash_val, MODULUS_MASK)
}
// single assign to named returns
result_ptr_out := add(result_ptr, len)
}
function exclude_coverage_stop_read_binary() {} // solhint-disable-line no-empty-blocks
let paramsOffset := add(serializedParams.offset, UINT64_SIZE)
let paramsArray := add(params, WORD_SIZE)
for {} length { length := sub(length, 1) } {
let data_type
paramsOffset, data_type := read_data_type(paramsOffset)
let entry
paramsOffset, entry := read_entry(paramsOffset, data_type)
mstore(paramsArray, entry)
paramsArray := add(paramsArray, WORD_SIZE)
}
}
}
/// @dev Serializes a bool parameter
/// @param param The parameter
/// @return serializedParam The serialized parameter
function boolParam(bool param) internal pure returns (bytes memory serializedParam) {
serializedParam = abi.encodePacked(DATA_TYPE_BOOLEAN_VARIANT, param);
}
/// @dev Serializes a tinyint parameter
/// @param param The parameter
/// @return serializedParam The serialized parameter
function tinyIntParam(int8 param) internal pure returns (bytes memory serializedParam) {
serializedParam = abi.encodePacked(DATA_TYPE_TINYINT_VARIANT, param);
}
/// @dev Serializes a smallint parameter
/// @param param The parameter
/// @return serializedParam The serialized parameter
function smallIntParam(int16 param) internal pure returns (bytes memory serializedParam) {
serializedParam = abi.encodePacked(DATA_TYPE_SMALLINT_VARIANT, param);
}
/// @dev Serializes an int32 parameter
/// @param param The parameter
/// @return serializedParam The serialized parameter
function intParam(int32 param) internal pure returns (bytes memory serializedParam) {
serializedParam = abi.encodePacked(DATA_TYPE_INT_VARIANT, param);
}
/// @dev Serializes a bigint parameter
/// @param param The parameter
/// @return serializedParam The serialized parameter
function bigIntParam(int64 param) internal pure returns (bytes memory serializedParam) {
serializedParam = abi.encodePacked(DATA_TYPE_BIGINT_VARIANT, param);
}
/// @dev Serializes a string parameter
/// @param param The parameter
/// @return serializedParam The serialized parameter
function varCharParam(string memory param) internal pure returns (bytes memory serializedParam) {
uint64 length = uint64(bytes(param).length);
serializedParam = abi.encodePacked(DATA_TYPE_VARCHAR_VARIANT, length, param);
}
/// @dev Serializes a decimal parameter
/// @param param The parameter
/// @param precision The precision of the decimal
/// @param scale The scale of the decimal
/// @return serializedParam The serialized parameter
function decimal75Param(uint256 param, uint8 precision, int8 scale)
internal
pure
returns (bytes memory serializedParam)
{
serializedParam = abi.encodePacked(DATA_TYPE_DECIMAL75_VARIANT, precision, scale, param);
}
/// @dev Serializes a timestamp parameter
/// @param param The parameter
/// @return serializedParam The serialized parameter
function unixTimestampMillisParam(int64 param) internal pure returns (bytes memory serializedParam) {
serializedParam =
abi.encodePacked(DATA_TYPE_TIMESTAMP_VARIANT, TIMEUNIT_MILLISECOND_VARIANT, TIMEZONE_UTC, param);
}
/// @dev Serializes a varbinary parameter
/// @param param The parameter
/// @return serializedParam The serialized parameter
function varBinaryParam(bytes memory param) internal pure returns (bytes memory serializedParam) {
uint64 length = uint64(param.length);
serializedParam = abi.encodePacked(DATA_TYPE_VARBINARY_VARIANT, length, param);
}
}// SPDX-License-Identifier: UNLICENSED // This is licensed under the Cryptographic Open Software License 1.0 pragma solidity ^0.8.28; /// @dev The modulus of the bn254 scalar field. uint256 constant MODULUS = 0x30644e72_e131a029_b85045b6_8181585d_2833e848_79b97091_43e1f593_f0000001; /// @dev The largest mask that can be applied to a 256-bit number in order to enforce that it is less than the modulus. uint256 constant MODULUS_MASK = 0x1FFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF; /// @dev A mask that can be applied to a bit distributions vary mask to see if it is valid, given the modulus. uint256 constant MODULUS_INVALID_VARY_MASK = 0x60000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000; /// @dev MODULUS + 1. Needs to be explicit for Yul usage. uint256 constant MODULUS_PLUS_ONE = 0x30644e72_e131a029_b85045b6_8181585d_2833e848_79b97091_43e1f593_f0000002; /// @dev MODULUS - 1. Needs to be explicit for Yul usage. uint256 constant MODULUS_MINUS_ONE = 0x30644e72_e131a029_b85045b6_8181585d_2833e848_79b97091_43e1f593_f0000000; /// @dev Size of a word in bytes: 32. uint256 constant WORD_SIZE = 0x20; /// @dev Size of two words in bytes. uint256 constant WORDX2_SIZE = 0x20 * 2; /// @dev Size of three words in bytes. uint256 constant WORDX3_SIZE = 0x20 * 3; /// @dev Size of four words in bytes. uint256 constant WORDX4_SIZE = 0x20 * 4; /// @dev Size of five words in bytes. uint256 constant WORDX5_SIZE = 0x20 * 5; /// @dev Size of six words in bytes. uint256 constant WORDX6_SIZE = 0x20 * 6; /// @dev Size of eight words in bytes. uint256 constant WORDX8_SIZE = 0x20 * 8; /// @dev Size of nine words in bytes. uint256 constant WORDX9_SIZE = 0x20 * 9; /// @dev Size of ten words in bytes. uint256 constant WORDX10_SIZE = 0x20 * 10; /// @dev Size of eleven words in bytes. uint256 constant WORDX11_SIZE = 0x20 * 11; /// @dev Size of twelve words in bytes. uint256 constant WORDX12_SIZE = 0x20 * 12; /// @dev Size of boolean in bytes. In bincode encoding, booleans are one byte. uint256 constant BOOLEAN_SIZE = 0x01; /// @dev Number of bits needed to pad boolean to 256 bits /// @dev This is useful for shifting a uint256 to the right to extract a boolean uint256 constant BOOLEAN_PADDING_BITS = 0xF8; /// @dev Size of boolean minus one byte uint256 constant BOOLEAN_SIZE_MINUS_ONE = 0x00; /// @dev Size of int8 in bytes uint256 constant INT8_SIZE = 0x01; /// @dev Number of bits needed to pad int8 to 256 bits /// @dev This is useful for shifting a uint256 to the right to extract a int8 uint256 constant INT8_PADDING_BITS = 0xF8; /// @dev Size of int8 minus one byte uint256 constant INT8_SIZE_MINUS_ONE = 0x00; /// @dev Size of uint8 in bytes uint256 constant UINT8_SIZE = 0x01; /// @dev Number of bits needed to pad uint8 to 256 bits /// @dev This is useful for shifting a uint256 to the right to extract a uint8 uint256 constant UINT8_PADDING_BITS = 0xF8; /// @dev Size of int16 in bytes uint256 constant INT16_SIZE = 0x02; /// @dev Number of bits needed to pad int16 to 256 bits /// @dev This is useful for shifting a uint256 to the right to extract a int16 uint256 constant INT16_PADDING_BITS = 0xF0; /// @dev Size of int16 minus one byte uint256 constant INT16_SIZE_MINUS_ONE = 0x01; /// @dev Size of uint16 in bytes uint256 constant UINT16_SIZE = 0x02; /// @dev Size of uint32 in bytes uint256 constant UINT32_SIZE = 0x04; /// @dev Number of bits needed to pad uint32 to 256 bits /// @dev This is useful for shifting a uint256 to the right to extract a uint32 uint256 constant UINT32_PADDING_BITS = 0xE0; /// @dev Size of int32 in bytes uint256 constant INT32_SIZE = 0x04; /// @dev Number of bits needed to pad int32 to 256 bits /// @dev This is useful for shifting a uint256 to the right to extract a int32 uint256 constant INT32_PADDING_BITS = 0xE0; /// @dev Size of int32 minus one byte uint256 constant INT32_SIZE_MINUS_ONE = 0x03; /// @dev Size of uint64 in bytes uint256 constant UINT64_SIZE = 0x08; /// @dev Number of bits needed to pad uint64 to 256 bits /// @dev This is useful for shifting a uint256 to the right to extract a uint64 uint256 constant UINT64_PADDING_BITS = 0xC0; /// @dev Size of int64 in bytes uint256 constant INT64_SIZE = 0x08; /// @dev Number of bits needed to pad int64 to 256 bits /// @dev This is useful for shifting a uint256 to the right to extract a int64 uint256 constant INT64_PADDING_BITS = 0xC0; /// @dev Size of int64 minus one byte uint256 constant INT64_SIZE_MINUS_ONE = 0x07; /// @dev Size of uint128 in bytes uint256 constant UINT128_SIZE = 0x10; /// @dev Max value for a uint64 uint256 constant MAX_UINT64 = 0xFFFFFFFFFFFFFFFF; /// @dev Column variant constant for proof expressions uint32 constant COLUMN_EXPR_VARIANT = 0; /// @dev Literal variant constant for proof expressions uint32 constant LITERAL_EXPR_VARIANT = 1; /// @dev Equals variant constant for proof expressions uint32 constant EQUALS_EXPR_VARIANT = 2; /// @dev Add variant constant for proof expressions uint32 constant ADD_EXPR_VARIANT = 3; /// @dev Subtract variant constant for proof expressions uint32 constant SUBTRACT_EXPR_VARIANT = 4; /// @dev Multiply variant constant for proof expressions uint32 constant MULTIPLY_EXPR_VARIANT = 5; /// @dev And variant constant for proof expressions uint32 constant AND_EXPR_VARIANT = 6; /// @dev Or variant constant for proof expressions uint32 constant OR_EXPR_VARIANT = 7; /// @dev Not variant constant for proof expressions uint32 constant NOT_EXPR_VARIANT = 8; /// @dev Cast variant constant for proof expressions uint32 constant CAST_EXPR_VARIANT = 9; /// @dev Inequality variant constant for proof expressions uint32 constant INEQUALITY_EXPR_VARIANT = 10; /// @dev Placeholder variant constant for proof expressions uint32 constant PLACEHOLDER_EXPR_VARIANT = 11; /// @dev Scaling cast variant constant for proof expressions uint32 constant SCALING_CAST_EXPR_VARIANT = 12; /// @dev Legacy Filter variant constant for proof plans uint32 constant LEGACY_FILTER_EXEC_VARIANT = 0; /// @dev Empty variant constant for proof plans uint32 constant EMPTY_EXEC_VARIANT = 1; /// @dev Table variant constant for proof plans uint32 constant TABLE_EXEC_VARIANT = 2; /// @dev Projection variant constant for proof plans uint32 constant PROJECTION_EXEC_VARIANT = 3; /// @dev Slice variant constant for proof plans uint32 constant SLICE_EXEC_VARIANT = 4; /// @dev Group By variant constant for proof plans uint32 constant GROUP_BY_EXEC_VARIANT = 5; /// @dev Union variant constant for proof plans uint32 constant UNION_EXEC_VARIANT = 6; /// @dev Sort Merge Join variant constant for proof plans uint32 constant SORT_MERGE_JOIN_EXEC_VARIANT = 7; /// @dev Filter variant constant for proof plans uint32 constant FILTER_EXEC_VARIANT = 8; /// @dev Aggregate variant constant for proof plans uint32 constant AGGREGATE_EXEC_VARIANT = 9; /// @dev Boolean variant constant for column types uint32 constant DATA_TYPE_BOOLEAN_VARIANT = 0; /// @dev TinyInt variant constant for column types uint32 constant DATA_TYPE_TINYINT_VARIANT = 2; /// @dev SmallInt variant constant for column types uint32 constant DATA_TYPE_SMALLINT_VARIANT = 3; /// @dev Int variant constant for column types uint32 constant DATA_TYPE_INT_VARIANT = 4; /// @dev BigInt variant constant for column types uint32 constant DATA_TYPE_BIGINT_VARIANT = 5; /// @dev Varchar variant constant for column types uint32 constant DATA_TYPE_VARCHAR_VARIANT = 7; /// @dev Decimal75 variant constant for column types uint32 constant DATA_TYPE_DECIMAL75_VARIANT = 8; /// @dev Timestamp variant constant for column types uint32 constant DATA_TYPE_TIMESTAMP_VARIANT = 9; /// @dev Scalar variant constant for column types uint32 constant DATA_TYPE_SCALAR_VARIANT = 10; /// @dev Varbinary variant constant for column types uint32 constant DATA_TYPE_VARBINARY_VARIANT = 11; /// @dev Timestamp variant constant for column types uint32 constant TIMEUNIT_MILLISECOND_VARIANT = 1; /// @dev Timestamp variant constant for column types int32 constant TIMEZONE_UTC = 0; /// @dev Position of the free memory pointer in the context of the EVM memory. uint256 constant FREE_PTR = 0x40; /// @dev Address of the ECADD precompile. uint256 constant ECADD_ADDRESS = 0x06; /// @dev Address of the ECMUL precompile. uint256 constant ECMUL_ADDRESS = 0x07; /// @dev Address of the ECPAIRING precompile. uint256 constant ECPAIRING_ADDRESS = 0x08; /// @dev Gas cost for the ECADD precompile. uint256 constant ECADD_GAS = 150; /// @dev Gas cost for the ECMUL precompile. uint256 constant ECMUL_GAS = 6000; /// @dev Gas cost for the ECPAIRING precompile with two pairings. uint256 constant ECPAIRINGX2_GAS = 45000 + 2 * 34000; /// @dev The X coordinate of the G1 generator point. uint256 constant G1_GEN_X = 1; /// @dev The Y coordinate of the G1 generator point. uint256 constant G1_GEN_Y = 2; /// @dev The G2 generator point's x-coordinate real component. uint256 constant G2_GEN_X_REAL = 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed; /// @dev The G2 generator point's x-coordinate imaginary component. uint256 constant G2_GEN_X_IMAG = 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2; /// @dev The G2 generator point's y-coordinate real component. uint256 constant G2_GEN_Y_REAL = 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa; /// @dev The G2 generator point's y-coordinate imaginary component. uint256 constant G2_GEN_Y_IMAG = 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b; /// @dev The X coordinate of the negated G1 generator point. uint256 constant G1_NEG_GEN_X = 1; /// @dev The Y coordinate of the negated G1 generator point. uint256 constant G1_NEG_GEN_Y = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45; /// @dev The G2 negated generator point's x-coordinate real component. uint256 constant G2_NEG_GEN_X_REAL = 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed; /// @dev The G2 negated generator point's x-coordinate imaginary component. uint256 constant G2_NEG_GEN_X_IMAG = 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2; /// @dev The G2 negated generator point's y-coordinate real component. uint256 constant G2_NEG_GEN_Y_REAL = 0x1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d; /// @dev The G2 negated generator point's y-coordinate imaginary component. uint256 constant G2_NEG_GEN_Y_IMAG = 0x275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec; uint256 constant VK_TAU_HX_REAL = 0x285b1f14edd7e6632340a37dfae9005ff762edcfecfe1c732a7474c0708bef80; uint256 constant VK_TAU_HX_IMAG = 0x17cc93077f56f654da727c1def86010339c2b4131094547285adb083e48c197b; uint256 constant VK_TAU_HY_REAL = 0x2bad9a374aec49d329ec66e8f530f68509313450580c4c17c6db5ddb9bde7fd0; uint256 constant VK_TAU_HY_IMAG = 0x219edfceee1723de674f5b2f6fdb69d9e32dd53b15844956a630d3c7cdaa6ed9; /// @dev Size of the verification builder in bytes. uint256 constant VERIFICATION_BUILDER_SIZE = 0x20 * 16; /// @dev Offset of the pointer to the challenge queue in the verification builder. uint256 constant BUILDER_CHALLENGES_OFFSET = 0x20 * 0; /// @dev Offset of the pointer to the first round MLEs in the verification builder. uint256 constant BUILDER_FIRST_ROUND_MLES_OFFSET = 0x20 * 1; /// @dev Offset of the pointer to the final round MLEs in the verification builder. uint256 constant BUILDER_FINAL_ROUND_MLES_OFFSET = 0x20 * 2; /// @dev Offset of the pointer to the chi evaluations in the verification builder. uint256 constant BUILDER_CHI_EVALUATIONS_OFFSET = 0x20 * 3; /// @dev Offset of the pointer to the rho evaluations in the verification builder. uint256 constant BUILDER_RHO_EVALUATIONS_OFFSET = 0x20 * 4; /// @dev Offset of the pointer to the constraint multipliers in the verification builder. uint256 constant BUILDER_CONSTRAINT_MULTIPLIERS_OFFSET = 0x20 * 5; /// @dev Offset of the max degree in the verification builder. uint256 constant BUILDER_MAX_DEGREE_OFFSET = 0x20 * 6; /// @dev Offset of the aggregate evaluation in the verification builder. uint256 constant BUILDER_AGGREGATE_EVALUATION_OFFSET = 0x20 * 7; /// @dev Offset of the row multipliers evaluation in the verification builder. uint256 constant BUILDER_ROW_MULTIPLIERS_EVALUATION_OFFSET = 0x20 * 8; /// @dev Offset of the pointer to the column evaluations in the verification builder. uint256 constant BUILDER_COLUMN_EVALUATIONS_OFFSET = 0x20 * 9; /// @dev Offset of the pointer to the table chi evaluations in the verification builder. uint256 constant BUILDER_TABLE_CHI_EVALUATIONS_OFFSET = 0x20 * 10; /// @dev Offset of the placeholder parameters in the verification builder. uint256 constant BUILDER_PLACEHOLDER_PARAMETERS_OFFSET = 0x20 * 11; /// @dev Offset of the pointer to the first round commitments in the verification builder. uint256 constant BUILDER_FIRST_ROUND_COMMITMENTS_OFFSET = 0x20 * 12; /// @dev Offset of the pointer to the final round commitments in the verification builder. uint256 constant BUILDER_FINAL_ROUND_COMMITMENTS_OFFSET = 0x20 * 13; /// @dev Offset of the singleton chi evaluation in the verification builder. uint256 constant BUILDER_SINGLETON_CHI_EVALUATION_OFFSET = 0x20 * 14; /// @dev Offset of the pointer to the final round bit distributions in the verification builder. uint256 constant BUILDER_FINAL_ROUND_BIT_DISTRIBUTIONS_OFFSET = 0x20 * 15; /// @dev The initial transcript state. This is the hash of the empty string. uint256 constant INITIAL_TRANSCRIPT_STATE = 0x7c26f909f37b2c61df0bb3b19f76296469cb4d07b582a215c4e2b1f7a05527c3;
// SPDX-License-Identifier: UNLICENSED
// This is licensed under the Cryptographic Open Software License 1.0
pragma solidity ^0.8.28;
/// @dev Error code for when ECADD inputs are invalid.
uint32 constant ERR_INVALID_EC_ADD_INPUTS = 0x765bcba0;
/// @dev Error code for when ECMUL inputs are invalid.
uint32 constant ERR_INVALID_EC_MUL_INPUTS = 0xe32c7472;
/// @dev Error code for when ECPAIRING inputs are invalid.
uint32 constant ERR_INVALID_EC_PAIRING_INPUTS = 0x4385b511;
/// @dev Error code for when a boolean literal is invalid.
uint32 constant ERR_INVALID_BOOLEAN = 0xaf979eb5;
/// @dev Error code for commitment array having odd length which is impossible
/// since each commitment is 2 elements.
uint32 constant ERR_COMMITMENT_ARRAY_ODD_LENGTH = 0x88acadef;
/// @dev Error code for when the size of a sumcheck proof is incorrect.
uint32 constant ERR_INVALID_SUMCHECK_PROOF_SIZE = 0x3f889a17;
/// @dev Error code for when the evaluation of a round in a sumcheck proof does not match the expected value.
uint32 constant ERR_ROUND_EVALUATION_MISMATCH = 0x741f5c3f;
/// @dev Error code for when a dequeue attempt was made on an empty queue.
uint32 constant ERR_EMPTY_QUEUE = 0x31dcf2b5;
/// @dev Error code for when the HyperKZG proof has an inconsistent v.
uint32 constant ERR_HYPER_KZG_INCONSISTENT_V = 0x6a5ae827;
/// @dev Error code for when the HyperKZG proof has an empty x point.
uint32 constant ERR_HYPER_KZG_EMPTY_POINT = 0xf1c6069e;
/// @dev Error code for when the HyperKZG proof fails the pairing check.
uint32 constant ERR_HYPER_KZG_PAIRING_CHECK_FAILED = 0xa41148a3;
/// @dev Error code for when the produced constraint degree is higher than the provided proof.
uint32 constant ERR_CONSTRAINT_DEGREE_TOO_HIGH = 0x8568ae69;
/// @dev Error code for when the case literal in a switch statement is incorrect.
uint32 constant ERR_INCORRECT_CASE_CONST = 0x9324fb03;
/// @dev Error code for when an index is invalid.
uint32 constant ERR_INVALID_INDEX = 0x63df8171;
/// @dev Error code for when a proof expression variant is unsupported.
uint32 constant ERR_UNSUPPORTED_PROOF_EXPR_VARIANT = 0xb8a26620;
/// @dev Error code for when PCS batch lengths don't match.
uint32 constant ERR_PCS_BATCH_LENGTH_MISMATCH = 0x5a64ac85;
/// @dev Error code for when result column counts don't match.
uint32 constant ERR_RESULT_COLUMN_COUNT_MISMATCH = 0x4b08a100;
/// @dev Error code for when a result column name is invalid.
uint32 constant ERR_INVALID_RESULT_COLUMN_NAME = 0xc5a456b6;
/// @dev Error code for when result column lengths are inconsistent.
uint32 constant ERR_INCONSISTENT_RESULT_COLUMN_LENGTHS = 0x68c99843;
/// @dev Error code for when the result is incorrect.
uint32 constant ERR_INCORRECT_RESULT = 0x3ad072a3;
/// @dev Error code for when HyperKZG proof size doesn't match.
uint32 constant ERR_HYPER_KZG_PROOF_SIZE_MISMATCH = 0xbe285ccd;
/// @dev Error code for when aggregate evaluation doesn't match.
uint32 constant ERR_AGGREGATE_EVALUATION_MISMATCH = 0xf5c6cb38;
/// @dev Error code for when proof type is unsupported.
uint32 constant ERR_UNSUPPORTED_PROOF = 0x6f1c50d9;
/// @dev Error code for when a proof plan variant is unsupported.
uint32 constant ERR_UNSUPPORTED_PROOF_PLAN_VARIANT = 0xe5503cfa;
/// @dev Error code for when a data type variant is unsupported.
uint32 constant ERR_UNSUPPORTED_DATA_TYPE_VARIANT = 0xbd12560e;
/// @dev Error code for when the evaluation length is too large.
uint32 constant ERR_EVALUATION_LENGTH_TOO_LARGE = 0xb65e7142;
/// @dev Error code for when a bit decomposition is invalid.
uint32 constant ERR_BIT_DECOMPOSITION_INVALID = 0xda443b2b;
/// @dev Error code for when bits that shouldn't vary do vary.
uint32 constant ERR_INVALID_VARYING_BITS = 0x76d56a3d;
/// @dev Error code for when monotony check fails.
uint32 constant ERR_MONOTONY_CHECK_FAILED = 0x976f97b8;
/// @dev Error code for when offset and plan value mismatch in slice.
uint32 constant ERR_SLICE_OFFSET_PLAN_VALUE_MISMATCH = 0x86052984;
/// @dev Error code for when offset and selection size mismatch in slice.
uint32 constant ERR_SLICE_OFFSET_SELECTION_SIZE_MISMATCH = 0xd66498ee;
/// @dev Error code for when the max length is incorrect in slice.
uint32 constant ERR_SLICE_MAX_LENGTH_MISMATCH = 0xd2e2f4a8;
/// @dev Error code for when there are not enough input plans in a union.
uint32 constant ERR_UNION_NOT_ENOUGH_INPUT_PLANS = 0x22d85efe;
/// @dev Error thrown when the number of column counts in a union is invalid (e.g. zero or inconsistent).
uint32 constant ERR_UNION_INVALID_COLUMN_COUNTS = 0x2b150620;
/// @dev Error thrown when there is an internal error.
uint32 constant ERR_INTERNAL = 0xfe835e35;
/// @dev Error code for unprovable group by error.
uint32 constant ERR_UNPROVABLE_GROUP_BY = 0x6bd33da2;
/// @dev Error code for unsupported table commitments.
uint32 constant ERR_TABLE_COMMITMENT_UNSUPPORTED = 0x4b35c9c3;
/// @dev Error code for when a plan has a number of join columns other than one.
uint32 constant ERR_NUMBER_OF_JOIN_COLUMNS_NOT_ONE = 0xf81ffd2a;
library Errors {
/// @notice Error thrown when the inputs to the ECADD precompile are invalid.
error InvalidECAddInputs();
/// @notice Error thrown when the inputs to the ECMUL precompile are invalid.
error InvalidECMulInputs();
/// @notice Error thrown when the inputs to the ECPAIRING precompile are invalid.
error InvalidECPairingInputs();
/// @notice Error thrown when a boolean literal is invalid.
error InvalidBoolean();
/// @notice Error code for commitment array having odd length which is impossible
/// since each commitment is 2 elements.
error CommitmentArrayOddLength();
/// @notice Error thrown when the size of a sumcheck proof is incorrect.
error InvalidSumcheckProofSize();
/// @notice Error thrown when the evaluation of a round in a sumcheck proof does not match the expected value.
error RoundEvaluationMismatch();
/// @notice Error thrown when a dequeue attempt was made on an empty queue.
error EmptyQueue();
/// @notice Error thrown when the HyperKZG proof has an inconsistent v.
error HyperKZGInconsistentV();
/// @notice Error thrown when the HyperKZG proof has an empty x point.
error HyperKZGEmptyPoint();
/// @notice Error thrown when the HyperKZG proof fails the pairing check.
error HyperKZGPairingCheckFailed();
/// @notice Error thrown when the produced constraint degree is higher than the provided proof.
error ConstraintDegreeTooHigh();
/// @notice Error thrown when the case literal in a switch statement is incorrect.
error IncorrectCaseConst();
/// @notice Error thrown when an index is invalid.
error InvalidIndex();
/// @notice Error thrown when a proof expression variant is unsupported.
error UnsupportedProofExprVariant();
/// @notice Error thrown when PCS batch lengths don't match.
error PCSBatchLengthMismatch();
/// @notice Error thrown when result column counts don't match.
error ResultColumnCountMismatch();
/// @notice Error thrown when a result column name is invalid.
error InvalidResultColumnName();
/// @notice Error thrown when result column lengths are inconsistent.
error InconsistentResultColumnLengths();
/// @notice Error thrown when the result is incorrect.
error IncorrectResult();
/// @notice Error thrown when HyperKZG proof size doesn't match.
error HyperKZGProofSizeMismatch();
/// @notice Error thrown when aggregate evaluation doesn't match.
error AggregateEvaluationMismatch();
/// @notice Error thrown when proof type is unsupported.
error UnsupportedProof();
/// @notice Error thrown when a proof plan variant is unsupported.
error UnsupportedProofPlanVariant();
/// @notice Error thrown when a data type variant is unsupported.
error UnsupportedDataTypeVariant();
/// @notice Error thrown when the evaluation length is too large.
error EvaluationLengthTooLarge();
/// @notice Error thrown when a bit decomposition is invalid.
error BitDecompositionInvalid();
/// @notice Error thrown when bits that shouldn't vary do vary.
error InvalidVaryingBits();
/// @notice Error thrown when monotony check fails.
error MonotonyCheckFailed();
/// @notice Error code for when offset and plan value mismatch in slice.
error SliceOffsetPlanValueMismatch();
/// @notice Error thrown when offset and selection size mismatch in slice.
error SliceOffsetSelectionSizeMismatch();
/// @notice Error thrown when the max length is incorrect in slice.
error SliceMaxLengthMismatch();
/// @notice Error thrown when there are not enough input plans in a union.
error UnionNotEnoughInputPlans();
/// @notice Error thrown when the number of column counts in a union is invalid (e.g. zero or inconsistent).
error UnionInvalidColumnCounts();
/// @notice Error thrown when there is an internal error.
error InternalError();
/// @notice Error thrown for unprovable group by error.
error UnprovableGroupBy();
/// @notice Error thrown for commitments that are not found.
error CommitmentsNotFound();
/// @notice Error thrown for unsupported table commitments.
error TableCommitmentUnsupported();
/// @notice Error thrown for having too many parameters.
error TooManyParameters();
/// @notice Error thrown when a plan has a number of join columns other than one.
error NumberOfJoinColumnsNotOne();
function __err(uint32 __code) internal pure {
assembly {
function err(code) {
mstore(0, code)
revert(28, 4)
}
err(__code)
}
}
}{
"remappings": [
"@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.2.0/",
"forge-std/=dependencies/forge-std-1.9.7/",
"smartcontractkit-chainlink-evm-1.5.0/=dependencies/smartcontractkit-chainlink-evm-1.5.0/",
"sxt-proof-of-sql/=dependencies/sxt-proof-of-sql-0.127.30/",
"@openzeppelin-contracts-5.2.0/=dependencies/@openzeppelin-contracts-5.2.0/",
"forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/",
"sxt-proof-of-sql-0.127.30/=dependencies/sxt-proof-of-sql-0.127.30/src/"
],
"optimizer": {
"enabled": true,
"runs": 4294967295
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "prague",
"viaIR": true,
"libraries": {
"src/PoSQLVerifier.sol": {
"Verifier": "0x2f94e3f04dbaa42840fa825c4302fec3a70673f8"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"components":[{"internalType":"bytes32","name":"version","type":"bytes32"},{"internalType":"bytes","name":"innerQuery","type":"bytes"},{"internalType":"bytes","name":"parameters","type":"bytes"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct IQueryRouter.Query","name":"queryData","type":"tuple"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"verify","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60808060405234601557610a7d908161001a8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c63dd71257c14610024575f80fd5b346100f25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100f25760043567ffffffffffffffff81116100f25760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126100f25760243567ffffffffffffffff81116100f257366023820112156100f257806004013567ffffffffffffffff81116100f25760243691830101116100f2576100ee9160246100e292019060040161045c565b604051918291826100f6565b0390f35b5f80fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100f2570180359067ffffffffffffffff82116100f2576020019181360383136100f257565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100f2570180359067ffffffffffffffff82116100f257602001918160051b360383136100f257565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761025157604052565b6101e3565b5f9103126100f257565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b90602083828152019060208160051b85010193835f915b8383106102c55750505050505090565b9091929394957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820301865286357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112156100f2578301906020823592019167ffffffffffffffff81116100f25780360383136100f2576103526020928392600195610260565b9801960194930191906102b5565b979593906103809061038e94939b9a98969b60a08b5260a08b0191610260565b9188830360208a0152610260565b8581036040870152602080895192838152019801905f5b8181106103d757505050956103c6916103d496978683036060880152610260565b92608081850391015261029e565b90565b82518a526020998a0199909201916001016103a5565b6040513d5f823e3d90fd5b92919267ffffffffffffffff8211610251576040519161044060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184610210565b8294818452818301116100f2578281602093845f960137010152565b90602081019061046f604084018461013e565b50803560c01c8061047f81610700565b9261048d6040519485610210565b818452600861049b83610700565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020870193013684370190925b6105a857505050732f94e3f04dbaa42840fa825c4302fec3a70673f86105006104f3858061013e565b919096602081019061013e565b96909360a061051f610515604089018a61013e565b929098018961018f565b91863b156100f2575f98610563946040519c8d9a8b998a997fc0d7f5df000000000000000000000000000000000000000000000000000000008b5260048b01610360565b03915af49081156105a3576103d49261058292610589575b508061013e565b36916103f8565b806105975f61059d93610210565b80610256565b5f61057b565b6103ed565b803560e01c60048201918190815f146106d157816002146106d157816003146106d157816004146106d157816005146106d157816007146106d1578160081461069d57508060091461066c5780600a1461063e57600b03610725576106306020917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93610732565b8552930192910190816104ca565b506106306020917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93610732565b5061063060209160087fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9401610732565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9350610630915091600660209301610732565b50506106306020917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93610732565b67ffffffffffffffff81116102515760051b60200190565b63af979eb55f526004601cfd5b63bd12560e5f526004601cfd5b90801561088c578060021461085a578060031461082857806004146107f657806005146107ba57806007146107ec578060081461078d57806009146107ba5780600a1461078d57600b0361072557610789906108cb565b9091565b50907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016020830192350690565b50907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160088301923560c01d81010690565b50610789906108cb565b50907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160048301923560e01d81010690565b50907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028301923560f01d81010690565b50907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160018301923560f81d81010690565b50908135918260f91c6108c65760017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000191019260f81c0690565b610718565b604051813560c01c80915f926108e6575b5060089192010191565b600892508190818486018237207fffffffffffffffffffffffffffffffff000000000000000000000000000000008160801b169060801c1777ffffffffffffffff0000000000000000ffffffffffffffff7fffffffffffffffff0000000000000000ffffffffffffffff00000000000000008260401b169160401c16177bffffffff00000000ffffffff00000000ffffffff00000000ffffffff7fffffffff00000000ffffffff00000000ffffffff00000000ffffffff000000008260201b169160201c16177dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff7fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff00008260101b169160101c16177eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff7f1f00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff0082851b1691841c1617916108dc56fea26469706673582212206107a4c0bd12eef724f18445a4239a1c935b4b10c1fe5abccb68bdeceb8994a264736f6c634300081e0033
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c63dd71257c14610024575f80fd5b346100f25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100f25760043567ffffffffffffffff81116100f25760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126100f25760243567ffffffffffffffff81116100f257366023820112156100f257806004013567ffffffffffffffff81116100f25760243691830101116100f2576100ee9160246100e292019060040161045c565b604051918291826100f6565b0390f35b5f80fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100f2570180359067ffffffffffffffff82116100f2576020019181360383136100f257565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100f2570180359067ffffffffffffffff82116100f257602001918160051b360383136100f257565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761025157604052565b6101e3565b5f9103126100f257565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b90602083828152019060208160051b85010193835f915b8383106102c55750505050505090565b9091929394957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820301865286357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112156100f2578301906020823592019167ffffffffffffffff81116100f25780360383136100f2576103526020928392600195610260565b9801960194930191906102b5565b979593906103809061038e94939b9a98969b60a08b5260a08b0191610260565b9188830360208a0152610260565b8581036040870152602080895192838152019801905f5b8181106103d757505050956103c6916103d496978683036060880152610260565b92608081850391015261029e565b90565b82518a526020998a0199909201916001016103a5565b6040513d5f823e3d90fd5b92919267ffffffffffffffff8211610251576040519161044060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184610210565b8294818452818301116100f2578281602093845f960137010152565b90602081019061046f604084018461013e565b50803560c01c8061047f81610700565b9261048d6040519485610210565b818452600861049b83610700565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020870193013684370190925b6105a857505050732f94e3f04dbaa42840fa825c4302fec3a70673f86105006104f3858061013e565b919096602081019061013e565b96909360a061051f610515604089018a61013e565b929098018961018f565b91863b156100f2575f98610563946040519c8d9a8b998a997fc0d7f5df000000000000000000000000000000000000000000000000000000008b5260048b01610360565b03915af49081156105a3576103d49261058292610589575b508061013e565b36916103f8565b806105975f61059d93610210565b80610256565b5f61057b565b6103ed565b803560e01c60048201918190815f146106d157816002146106d157816003146106d157816004146106d157816005146106d157816007146106d1578160081461069d57508060091461066c5780600a1461063e57600b03610725576106306020917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93610732565b8552930192910190816104ca565b506106306020917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93610732565b5061063060209160087fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9401610732565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9350610630915091600660209301610732565b50506106306020917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93610732565b67ffffffffffffffff81116102515760051b60200190565b63af979eb55f526004601cfd5b63bd12560e5f526004601cfd5b90801561088c578060021461085a578060031461082857806004146107f657806005146107ba57806007146107ec578060081461078d57806009146107ba5780600a1461078d57600b0361072557610789906108cb565b9091565b50907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016020830192350690565b50907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160088301923560c01d81010690565b50610789906108cb565b50907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160048301923560e01d81010690565b50907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028301923560f01d81010690565b50907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160018301923560f81d81010690565b50908135918260f91c6108c65760017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000191019260f81c0690565b610718565b604051813560c01c80915f926108e6575b5060089192010191565b600892508190818486018237207fffffffffffffffffffffffffffffffff000000000000000000000000000000008160801b169060801c1777ffffffffffffffff0000000000000000ffffffffffffffff7fffffffffffffffff0000000000000000ffffffffffffffff00000000000000008260401b169160401c16177bffffffff00000000ffffffff00000000ffffffff00000000ffffffff7fffffffff00000000ffffffff00000000ffffffff00000000ffffffff000000008260201b169160201c16177dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff7fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff00008260101b169160101c16177eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff7f1f00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff0082851b1691841c1617916108dc56fea26469706673582212206107a4c0bd12eef724f18445a4239a1c935b4b10c1fe5abccb68bdeceb8994a264736f6c634300081e0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.