PoSQLVerifier

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/PoSQLVerifier.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import {IVerify} from "./query-router/interfaces/IVerify.sol";
import {IQueryRouter} from "./query-router/interfaces/IQueryRouter.sol";

import {Verifier} from "sxt-proof-of-sql/src/verifier/Verifier.post.sol";
import {ParamsBuilder} from "sxt-proof-of-sql/src/client/ParamsBuilder.post.sol";

contract PoSQLVerifier is IVerify {
    uint256 internal constant WORD_SIZE = 0x20; // aderyn-ignore unused-state-variable
    uint8 internal constant HYPER_KZG_COMMITMENT_SCHEME_VARIANT = 0;

    address public immutable PAYOUT_ADDRESS;
    address private immutable OWNER;

    error ZeroAddressNotAllowed();
    error OnlyOwnerAllowed();

    struct CommitmentProof {
        bytes32[] proof;
        bytes32[] r;
        bytes32[] s;
        uint8[] v;
        uint64 blockNumber;
        bool[] proofFlags;
    }

    struct ResultBody {
        bytes result;
        bytes proof;
        CommitmentProof commitmentProof;
        string[] tableNames; // should be in the same order as tableCommitments
        bytes[] tableCommitments;
    }

    function _onlyOwner() internal view {
        if (msg.sender != OWNER) revert OnlyOwnerAllowed();
    }

    constructor(address payoutAddress) {
        if (payoutAddress == address(0)) revert ZeroAddressNotAllowed();
        PAYOUT_ADDRESS = payoutAddress;
        OWNER = msg.sender;
    }

    receive() external payable {}

    /// @notice Returns the payout address and fee
    /// @return payoutAddress The payout address
    /// @return fee The fee (0.5 USD)
    function getPayoutAddressAndFee() external view returns (address payoutAddress, uint248 fee) {
        return (PAYOUT_ADDRESS, 0.5 ether);
    }

    struct TableCommitment {
        uint256 commitmentsPtr;
        uint64 tableLength;
        bytes32[] columnNameHashes;
    }

    // slither-disable-start dead-code
    function encodeTableCommitmentLeaf(string memory tableId, bytes memory tableCommitment) /// aderyn-ignore dead-code
        internal
        pure
        returns (bytes32)
    {
        bytes memory packedLeaf = abi.encodePacked( // aderyn-ignore abi-encode-packed-hash-collision
            uint8(bytes(tableId).length),
            tableId,
            HYPER_KZG_COMMITMENT_SCHEME_VARIANT,
            tableCommitment
        );
        bytes32 hashedLeaf;
        assembly {
            let len := mload(packedLeaf)
            packedLeaf := add(packedLeaf, WORD_SIZE)
            hashedLeaf := keccak256(packedLeaf, len)
        }
        return hashedLeaf;
    }

    // slither-disable-end dead-code

    /// @inheritdoc IVerify
    function verify(IQueryRouter.Query calldata queryData, bytes calldata proof)
        external
        view
        returns (bytes memory result)
    {
        ResultBody calldata queryResultStruct;
        assembly {
            queryResultStruct := add(proof.offset, WORD_SIZE)
        }

        uint256[] memory __placeholderParameters = ParamsBuilder.deserializeParamArray(queryData.parameters);

        Verifier.verify(
            queryResultStruct.result,
            queryData.innerQuery,
            __placeholderParameters,
            queryResultStruct.proof,
            queryResultStruct.tableCommitments
        );

        return queryResultStruct.result;
    }

    /// @notice Allows the contract owner to withdraw any ETH that might be sent to this contract
    /// @dev Added to address Slither warning about contracts locking ether
    // slither-disable-next-line low-level-calls
    function withdraw() external {
        _onlyOwner();
        payable(OWNER).transfer(address(this).balance); // aderyn-ignore dead-code unsafe-erc20-operation
    }
}
"
    },
    "src/query-router/interfaces/IVerify.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import {IQueryRouter} from "./IQueryRouter.sol";

/// @title IVerify
/// @author Placeholder
/// @notice Minimal verifier interface that exposes exactly the verify method
interface IVerify {
    /// @notice Verify a query result and return the extracted result bytes
    /// @param queryData The original query struct
    /// @param proof Encoded proof containing the query result and cryptographic proof
    /// @return result The query result data extracted from the proof
    function verify(IQueryRouter.Query calldata queryData, bytes calldata proof)
        external
        view
        returns (bytes memory result);
}
"
    },
    "src/query-router/interfaces/IQueryRouter.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

/// @title IQueryRouter
/// @author Placeholder
/// @notice Interface for querying external data sources with cryptographic proofs
interface IQueryRouter {
    /// @notice Query details
    /// @param version Query version identifier
    /// @param innerQuery Encoded, version-dependent query payload
    /// @param parameters Encoded parameters for the query
    /// @param metadata Encoded metadata for the query
    struct Query {
        bytes32 version;
        bytes innerQuery;
        bytes parameters;
        bytes metadata;
    }

    /// @notice Callback execution details
    /// @param maxGasPrice Max native gas price allowed for the callback
    /// @param gasLimit Gas limit forwarded to the callback contract
    /// @param callbackContract Address of the contract to call back
    /// @param selector Function selector to call on the callback contract
    /// @param callbackData Opaque callback-specific data passed to the callback
    struct Callback {
        uint256 maxGasPrice;
        uint64 gasLimit;
        address callbackContract;
        bytes4 selector;
        bytes callbackData;
    }

    /// @notice Emitted when a query is requested
    /// @param queryId Unique identifier for the query
    /// @param queryNonce Nonce used when the query was created
    /// @param requester Address that requested the query
    /// @param query Query details
    /// @param callback Callback details
    /// @param paymentAmount Amount of tokens held pending fulfillment
    /// @param timeout Timestamp after which cancellation is allowed
    event QueryRequested(
        bytes32 indexed queryId,
        uint64 indexed queryNonce,
        address indexed requester,
        Query query,
        Callback callback,
        uint256 paymentAmount,
        uint64 timeout
    );

    /// @notice Emitted when a query has been fulfilled (logical fulfillment/result)
    /// @param queryId Unique identifier for the query
    /// @param fulfiller Address that fulfilled the query
    /// @param result The query result data
    event QueryFulfilled(bytes32 indexed queryId, address indexed fulfiller, bytes result);

    /// @notice Emitted when a payout for a fulfilled query occurred (payments/refunds)
    /// @param queryId Unique identifier for the query
    /// @param fulfiller Address that fulfilled the query
    /// @param refundRecipient Address that received a refund (if any)
    /// @param fulfillerAmount Amount paid to the fulfiller for this fulfillment
    /// @param refundAmount Amount refunded to the refundRecipient (if any)
    event PayoutOccurred(
        bytes32 indexed queryId,
        address indexed fulfiller,
        address indexed refundRecipient,
        uint256 fulfillerAmount,
        uint256 refundAmount
    ); // solhint-disable-line gas-indexed-events

    /// @notice Emitted when a query is cancelled
    /// @param queryId Unique identifier for the query
    /// @param refundRecipient Address that received the refund
    /// @param refundAmount Amount refunded
    event QueryCancelled(bytes32 indexed queryId, address indexed refundRecipient, uint256 indexed refundAmount);

    /// @notice Emitted when open fulfillment is toggled
    /// @param enabled Whether open fulfillment is now enabled
    event OpenFulfillmentToggled(bool indexed enabled);

    /// @notice Emitted when the base cost used by the router is updated
    /// @param newBaseCost The new base cost value
    event BaseCostUpdated(uint256 indexed newBaseCost);

    /// @notice Emitted when a version is set
    /// @param version The string version
    /// @param versionHash The keccak256 hash of the version
    /// @param verifier The verifier contract address associated with the version
    event VersionSet(string version, bytes32 indexed versionHash, address indexed verifier);

    /// @notice Thrown when a query is not found or unauthorized cancellation is attempted
    error QueryNotFound(); // aderyn-ignore unused-error

    /// @notice Thrown when a query cancellation is attempted before the timeout
    error QueryTimeoutNotReached(); // aderyn-ignore unused-error

    /// @notice Thrown when the query version is not supported by the router
    error UnsupportedQueryVersion(); // aderyn-ignore unused-error

    /// @notice Register a verifier contract address to a version string
    /// @param version The string version to hash
    /// @param verifier The contract address to associate with the version
    function registerVerifierToVersion(string calldata version, address verifier) external;

    /// @notice Set the base cost for queries
    /// @param newBaseCost The new base cost
    function setBaseCost(uint256 newBaseCost) external;

    /// @notice Cancel a pending query and refund the payment
    /// @param queryId Unique identifier for the query to cancel
    function cancelQuery(bytes32 queryId) external;

    /// @notice Request a query to be executed.
    /// @param query Query struct containing query string, parameters, and version.
    /// @param callback Callback struct containing callback details.
    /// @param paymentAmount Amount of tokens to hold pending fulfillment.
    /// @param timeout Timestamp after which cancellation is allowed
    /// @return queryId Unique ID for this query.
    function requestQuery(Query calldata query, Callback calldata callback, uint256 paymentAmount, uint64 timeout)
        external
        returns (bytes32 queryId);

    /// @notice Fulfill a query by providing its data and proof.
    /// @param query Query struct for the original request.
    /// @param callback Callback struct for the original request.
    /// @param queryNonce Nonce used when the query was created.
    /// @param proof Encoded proof containing the query result and cryptographic proof.
    function fulfillQuery(Query calldata query, Callback calldata callback, uint64 queryNonce, bytes calldata proof)
        external;

    /// @notice Toggle open fulfillment on or off
    /// @param enabled True to allow anyone to fulfill, false to restrict to FULFILLER_ROLE
    function setOpenFulfillment(bool enabled) external;

    /// @notice Verify a query result without executing its callback.
    /// @param query Query struct for the original request.
    /// @param proof Encoded proof containing the query result and cryptographic proof.
    /// @return result The query result data extracted from the proof.
    function verifyQuery(Query calldata query, bytes calldata proof) external view returns (bytes memory result);
}
"
    },
    "dependencies/sxt-proof-of-sql-0.123.10/src/verifier/Verifier.post.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
// This is licensed under the Cryptographic Open Software License 1.0
pragma solidity ^0.8.28;

import "../base/Constants.sol";
import "../base/Errors.sol";

library Verifier {
    function verify(
        bytes calldata __result,
        bytes calldata __plan,
        uint256[] memory __placeholderParameters,
        bytes calldata __proof,
        bytes[] calldata __tableCommitments
    ) public view {
        (uint256[] memory tableLengths, uint256[] memory commitments) =
            getCommitmentsAndLength(__plan, __tableCommitments);
        __internalVerify({
            __result: __result,
            __plan: __plan,
            __placeholderParameters: __placeholderParameters,
            __proof: __proof,
            __tableLengths: tableLengths,
            __commitments: commitments
        });
    }

    struct TableCommitment {
        uint256 commitmentsPtr;
        uint64 tableLength;
        bytes32[] columnNameHashes;
    }

    // slither-disable-next-line cyclomatic-complexity
    function deserializeTableCommitment(bytes calldata tableCommitment)
        internal
        pure
        returns (TableCommitment memory result)
    {
        uint256 commitmentsPtr;
        uint64 tableLength;
        // columnNameHashes[columnId] = columnNameHash
        bytes32[] memory columnNameHashes;
        assembly {
            function exclude_coverage_start_err() {} // solhint-disable-line no-empty-blocks
            function err(code) {
                mstore(0, code)
                revert(28, 4)
            }
            function exclude_coverage_stop_err() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_read_data_type() {} // solhint-disable-line no-empty-blocks
            function read_data_type(ptr) -> ptr_out, data_type {
                data_type := shr(UINT32_PADDING_BITS, calldataload(ptr))
                ptr_out := add(ptr, UINT32_SIZE)
                switch data_type
                case 0 { case_const(0, DATA_TYPE_BOOLEAN_VARIANT) }
                case 2 { case_const(2, DATA_TYPE_TINYINT_VARIANT) }
                case 3 { case_const(3, DATA_TYPE_SMALLINT_VARIANT) }
                case 4 { case_const(4, DATA_TYPE_INT_VARIANT) }
                case 5 { case_const(5, DATA_TYPE_BIGINT_VARIANT) }
                case 7 { case_const(7, DATA_TYPE_VARCHAR_VARIANT) }
                case 8 {
                    case_const(8, DATA_TYPE_DECIMAL75_VARIANT)
                    ptr_out := add(ptr_out, UINT8_SIZE) // Skip precision
                    ptr_out := add(ptr_out, INT8_SIZE) // Skip scale
                }
                case 9 {
                    case_const(9, DATA_TYPE_TIMESTAMP_VARIANT)
                    ptr_out := add(ptr_out, UINT32_SIZE) // Skip timeunit
                    ptr_out := add(ptr_out, INT32_SIZE) // Skip timezone
                }
                case 10 { case_const(10, DATA_TYPE_SCALAR_VARIANT) }
                case 11 { case_const(11, DATA_TYPE_VARBINARY_VARIANT) }
                default { err(ERR_UNSUPPORTED_DATA_TYPE_VARIANT) }
            }
            function exclude_coverage_stop_read_data_type() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_case_const() {} // solhint-disable-line no-empty-blocks
            function case_const(lhs, rhs) {
                if sub(lhs, rhs) { err(ERR_INCORRECT_CASE_CONST) }
            }
            function exclude_coverage_stop_case_const() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_hash_string() {} // solhint-disable-line no-empty-blocks
            function hash_string(ptr, free_ptr) -> ptr_out, free_ptr_out {
                let name_len := shr(UINT64_PADDING_BITS, calldataload(ptr))
                ptr := add(ptr, UINT64_SIZE)

                // TODO: This line should probably be using the FREE_PTR directly, instead of having it passed in the function.
                // This is a little dangerous as it is.
                calldatacopy(free_ptr, ptr, name_len)
                mstore(free_ptr, keccak256(free_ptr, name_len))
                ptr_out := add(ptr, name_len)
                free_ptr_out := add(free_ptr, WORD_SIZE)
            }
            function exclude_coverage_stop_hash_string() {} // solhint-disable-line no-empty-blocks

            let ptr := tableCommitment.offset

            // range.start (usize) must be 0
            if shr(UINT64_PADDING_BITS, calldataload(ptr)) { err(ERR_TABLE_COMMITMENT_UNSUPPORTED) }
            ptr := add(ptr, UINT64_SIZE)

            // range.end *usize) is the table length
            tableLength := shr(UINT64_PADDING_BITS, calldataload(ptr))
            ptr := add(ptr, UINT64_SIZE)

            // commitments.len() (usize) is the number of columns
            let num_columns := shr(UINT64_PADDING_BITS, calldataload(ptr))
            ptr := add(ptr, UINT64_SIZE)

            // each commitment is a 2-word commitment
            commitmentsPtr := ptr
            ptr := add(ptr, mul(num_columns, WORDX2_SIZE))

            // column_metadata.len() (usize) must match the number of columns
            if sub(num_columns, shr(UINT64_PADDING_BITS, calldataload(ptr))) { err(ERR_TABLE_COMMITMENT_UNSUPPORTED) }
            ptr := add(ptr, UINT64_SIZE)

            // allocating space for column namess
            let free_ptr := mload(FREE_PTR)
            columnNameHashes := free_ptr

            // initializing length of column names
            mstore(free_ptr, num_columns)
            free_ptr := add(free_ptr, WORD_SIZE)

            // for each entry in column_metadata
            for {} num_columns { num_columns := sub(num_columns, 1) } {
                ptr, free_ptr := hash_string(ptr, free_ptr)

                // column_metadata[i].Ident.quote_style (Option<char>) must be None, i.e. 0
                if shr(UINT8_PADDING_BITS, calldataload(ptr)) { err(ERR_TABLE_COMMITMENT_UNSUPPORTED) }
                ptr := add(ptr, UINT8_SIZE)

                let data_type
                ptr, data_type := read_data_type(ptr)

                // column_metadata[i].ColumnCommitmentMetadata.bounds (ColumnBounds)
                let variant := shr(UINT32_PADDING_BITS, calldataload(ptr))
                ptr := add(ptr, UINT32_SIZE)
                function skip_bounds(data_size, ptr_in) -> ptr_out {
                    let bounds_variant := shr(UINT32_PADDING_BITS, calldataload(ptr_in))
                    ptr_out := add(ptr_in, UINT32_SIZE)
                    if bounds_variant { ptr_out := add(ptr_out, mul(data_size, 2)) }
                }
                switch variant
                // ColumnBounds::NoOrder
                case 0 {}
                // ColumnBounds::Uint8
                case 1 { ptr := skip_bounds(UINT8_SIZE, ptr) }
                // ColumnBounds::TinyInt
                case 2 { ptr := skip_bounds(UINT8_SIZE, ptr) }
                // ColumnBounds::SmallInt
                case 3 { ptr := skip_bounds(UINT16_SIZE, ptr) }
                // ColumnBounds::Int
                case 4 { ptr := skip_bounds(UINT32_SIZE, ptr) }
                // ColumnBounds::BigInt
                case 5 { ptr := skip_bounds(UINT64_SIZE, ptr) }
                // ColumnBounds::Int128
                case 6 { ptr := skip_bounds(UINT128_SIZE, ptr) }
                // ColumnBounds::TimestampTZ
                case 7 { ptr := skip_bounds(UINT64_SIZE, ptr) }
                default { err(ERR_TABLE_COMMITMENT_UNSUPPORTED) }
            }

            // done allocating space for column names
            mstore(FREE_PTR, free_ptr)
        }
        result = TableCommitment(commitmentsPtr, tableLength, columnNameHashes);
    }

    function deserializeTableCommitments(bytes[] calldata tableCommitments)
        internal
        pure
        returns (
            // tableCommitments[tableId] = TableCommitment
            TableCommitment[] memory result
        )
    {
        uint256 numTableCommitments = tableCommitments.length;
        result = new TableCommitment[](numTableCommitments);
        for (uint256 i = 0; i < numTableCommitments; ++i) {
            result[i] = deserializeTableCommitment(tableCommitments[i]);
        }
    }

    function deserializeProofPlanPrefix(bytes calldata plan)
        internal
        pure
        returns (
            // tableNameHashes[tableId] = tableNameHash
            bytes32[] memory tableNameHashes,
            // columnTableIndexes[columnId] = tableId
            uint64[] memory columnTableIndexes,
            // columnNameHashes[columnId] = columnNameHash
            bytes32[] memory columnNameHashes
        )
    {
        assembly {
            function exclude_coverage_start_read_data_type() {} // solhint-disable-line no-empty-blocks
            function read_data_type(ptr) -> ptr_out, data_type {
                data_type := shr(UINT32_PADDING_BITS, calldataload(ptr))
                ptr_out := add(ptr, UINT32_SIZE)
                switch data_type
                case 0 { case_const(0, DATA_TYPE_BOOLEAN_VARIANT) }
                case 2 { case_const(2, DATA_TYPE_TINYINT_VARIANT) }
                case 3 { case_const(3, DATA_TYPE_SMALLINT_VARIANT) }
                case 4 { case_const(4, DATA_TYPE_INT_VARIANT) }
                case 5 { case_const(5, DATA_TYPE_BIGINT_VARIANT) }
                case 7 { case_const(7, DATA_TYPE_VARCHAR_VARIANT) }
                case 8 {
                    case_const(8, DATA_TYPE_DECIMAL75_VARIANT)
                    ptr_out := add(ptr_out, UINT8_SIZE) // Skip precision
                    ptr_out := add(ptr_out, INT8_SIZE) // Skip scale
                }
                case 9 {
                    case_const(9, DATA_TYPE_TIMESTAMP_VARIANT)
                    ptr_out := add(ptr_out, UINT32_SIZE) // Skip timeunit
                    ptr_out := add(ptr_out, INT32_SIZE) // Skip timezone
                }
                case 10 { case_const(10, DATA_TYPE_SCALAR_VARIANT) }
                case 11 { case_const(11, DATA_TYPE_VARBINARY_VARIANT) }
                default { err(ERR_UNSUPPORTED_DATA_TYPE_VARIANT) }
            }
            function exclude_coverage_stop_read_data_type() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_case_const() {} // solhint-disable-line no-empty-blocks
            function case_const(lhs, rhs) {
                if sub(lhs, rhs) { err(ERR_INCORRECT_CASE_CONST) }
            }
            function exclude_coverage_stop_case_const() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_err() {} // solhint-disable-line no-empty-blocks
            function err(code) {
                mstore(0, code)
                revert(28, 4)
            }
            function exclude_coverage_stop_err() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_hash_string() {} // solhint-disable-line no-empty-blocks
            function hash_string(ptr, free_ptr) -> ptr_out, free_ptr_out {
                let name_len := shr(UINT64_PADDING_BITS, calldataload(ptr))
                ptr := add(ptr, UINT64_SIZE)

                // TODO: This line should probably be using the FREE_PTR directly, instead of having it passed in the function.
                // This is a little dangerous as it is.
                calldatacopy(free_ptr, ptr, name_len)
                mstore(free_ptr, keccak256(free_ptr, name_len))
                ptr_out := add(ptr, name_len)
                free_ptr_out := add(free_ptr, WORD_SIZE)
            }
            function exclude_coverage_stop_hash_string() {} // solhint-disable-line no-empty-blocks

            let ptr := plan.offset

            let free_ptr := mload(FREE_PTR)

            // tables.len() (usize) is the number of tables
            let num_tables := shr(UINT64_PADDING_BITS, calldataload(ptr))
            ptr := add(ptr, UINT64_SIZE)

            // allocating space for table names
            tableNameHashes := free_ptr
            mstore(free_ptr, num_tables)
            free_ptr := add(free_ptr, WORD_SIZE)

            // for each table
            for {} num_tables { num_tables := sub(num_tables, 1) } { ptr, free_ptr := hash_string(ptr, free_ptr) }
            // done allocating space for table names

            // columns.len() (usize) is the number of columns
            let num_columns := shr(UINT64_PADDING_BITS, calldataload(ptr))
            ptr := add(ptr, UINT64_SIZE)

            // allocating space for column table indexes
            columnTableIndexes := free_ptr
            let index_ptr := free_ptr

            // initializing length of column table indexes
            mstore(index_ptr, num_columns)
            index_ptr := add(index_ptr, WORD_SIZE)

            free_ptr := add(index_ptr, mul(num_columns, WORD_SIZE))
            // done allocating space for column table indexes

            // allocating space for column names
            columnNameHashes := free_ptr

            // initializing length of column names
            mstore(free_ptr, num_columns)
            free_ptr := add(free_ptr, WORD_SIZE)

            // for each column
            for {} num_columns { num_columns := sub(num_columns, 1) } {
                // column[i].0 (usize) is the table id. We store it in the columnTableIndexes array
                mstore(index_ptr, shr(UINT64_PADDING_BITS, calldataload(ptr)))
                ptr := add(ptr, UINT64_SIZE)
                index_ptr := add(index_ptr, WORD_SIZE)

                ptr, free_ptr := hash_string(ptr, free_ptr)

                let data_type
                ptr, data_type := read_data_type(ptr)
            }

            // done allocating space for column names
            mstore(FREE_PTR, free_ptr)
        }
    }

    /// @notice Internal function to get the relevant commitments
    /// @dev validates that all commitments are found
    /// @return commitments the commitments in the order of the columns
    function getRelevantCommitments(
        uint64[] memory columnTableIndexes,
        bytes32[] memory columnNameHashes,
        TableCommitment[] memory tableCommitments
    ) internal pure returns (uint256[] memory commitments) {
        uint256 numColumns = columnTableIndexes.length;
        commitments = new uint256[](numColumns * 2);
        uint256 commitmentsFreePtr;
        assembly {
            commitmentsFreePtr := add(commitments, 0x20)
        }

        for (uint256 i = 0; i < numColumns; ++i) {
            uint64 columnTableIndex = columnTableIndexes[i];
            bytes32 columnNameHash = columnNameHashes[i];

            if (!(columnTableIndex < tableCommitments.length)) {
                revert Errors.CommitmentsNotFound();
            }
            TableCommitment memory tableCommitment = tableCommitments[columnTableIndex];
            uint256 commitmentsPtr = tableCommitment.commitmentsPtr;
            bool found = false;
            uint256 columnNameHashesLength = tableCommitment.columnNameHashes.length;
            for (uint256 j = 0; j < columnNameHashesLength; ++j) {
                if (tableCommitment.columnNameHashes[j] == columnNameHash) {
                    assembly {
                        calldatacopy(commitmentsFreePtr, add(commitmentsPtr, mul(j, WORDX2_SIZE)), WORDX2_SIZE)
                        commitmentsFreePtr := add(commitmentsFreePtr, WORDX2_SIZE)
                    }
                    found = true;
                    break;
                }
            }
            if (!found) {
                revert Errors.CommitmentsNotFound();
            }
        }
    }

    function getTableLengths(TableCommitment[] memory tableCommitments)
        private
        pure
        returns (uint256[] memory tableLengths)
    {
        uint256 numTables = tableCommitments.length;
        tableLengths = new uint256[](numTables);
        for (uint256 i = 0; i < numTables; ++i) {
            tableLengths[i] = tableCommitments[i].tableLength;
        }
    }

    function getCommitmentsAndLength(bytes calldata queryPlan, bytes[] calldata tableCommitmentsAsBytes)
        internal
        pure
        returns (uint256[] memory __tableLengths, uint256[] memory __commitments)
    {
        TableCommitment[] memory tableCommitments = deserializeTableCommitments(tableCommitmentsAsBytes);
        (, uint64[] memory columnTableIndexes, bytes32[] memory columnNameHashes) =
            deserializeProofPlanPrefix(queryPlan);

        // construct `uint256[] memory commitments` and validate that all commitments are found
        uint256[] memory commitments = getRelevantCommitments(columnTableIndexes, columnNameHashes, tableCommitments);

        // construct `uint256[] memory tableLengths`
        uint256[] memory tableLengths = getTableLengths(tableCommitments);
        __tableLengths = tableLengths;
        __commitments = commitments;
    }

    function __internalVerify(
        bytes calldata __result,
        bytes calldata __plan,
        uint256[] memory __placeholderParameters,
        bytes calldata __proof,
        uint256[] memory __tableLengths,
        uint256[] memory __commitments
    ) public view {
        assembly {
            function exclude_coverage_start_err() {} // solhint-disable-line no-empty-blocks
            function err(code) {
                mstore(0, code)
                revert(28, 4)
            }
            function exclude_coverage_stop_err() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_mulmod_bn254() {} // solhint-disable-line no-empty-blocks
            function mulmod_bn254(lhs, rhs) -> product {
                product := mulmod(lhs, rhs, MODULUS)
            }
            function exclude_coverage_stop_mulmod_bn254() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_log2_up() {} // solhint-disable-line no-empty-blocks
            function log2_up(value) -> exponent {
                if value { value := sub(value, 1) }
                exponent := 1
                if gt(value, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {
                    exponent := add(exponent, 128)
                    value := shr(128, value)
                }
                if gt(value, 0xFFFFFFFFFFFFFFFF) {
                    exponent := add(exponent, 64)
                    value := shr(64, value)
                }
                if gt(value, 0xFFFFFFFF) {
                    exponent := add(exponent, 32)
                    value := shr(32, value)
                }
                if gt(value, 0xFFFF) {
                    exponent := add(exponent, 16)
                    value := shr(16, value)
                }
                if gt(value, 0xFF) {
                    exponent := add(exponent, 8)
                    value := shr(8, value)
                }
                if gt(value, 0xF) {
                    exponent := add(exponent, 4)
                    value := shr(4, value)
                }
                if gt(value, 0x3) {
                    exponent := add(exponent, 2)
                    value := shr(2, value)
                }
                if gt(value, 0x1) {
                    exponent := add(exponent, 1)
                    value := shr(1, value)
                }
            }
            function exclude_coverage_stop_log2_up() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_read_uint64_array() {} // solhint-disable-line no-empty-blocks
            function read_uint64_array(source_ptr) -> source_ptr_out, array_ptr {
                array_ptr := mload(FREE_PTR)

                let length := shr(UINT64_PADDING_BITS, calldataload(source_ptr))
                mstore(array_ptr, length)
                source_ptr := add(source_ptr, UINT64_SIZE)

                let tmp_ptr := add(array_ptr, WORD_SIZE)
                for {} length { length := sub(length, 1) } {
                    mstore(tmp_ptr, shr(UINT64_PADDING_BITS, calldataload(source_ptr)))
                    source_ptr := add(source_ptr, UINT64_SIZE)
                    tmp_ptr := add(tmp_ptr, WORD_SIZE)
                }

                mstore(FREE_PTR, tmp_ptr)

                source_ptr_out := source_ptr
            }
            function exclude_coverage_stop_read_uint64_array() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_read_uint64_array_as_uint512_array() {} // solhint-disable-line no-empty-blocks
            function read_uint64_array_as_uint512_array(source_ptr) -> source_ptr_out, array_ptr {
                array_ptr := mload(FREE_PTR)

                let length := shr(UINT64_PADDING_BITS, calldataload(source_ptr))
                mstore(array_ptr, length)
                source_ptr := add(source_ptr, UINT64_SIZE)
                let target_ptr := add(array_ptr, WORD_SIZE)

                for {} length { length := sub(length, 1) } {
                    mstore(target_ptr, shr(UINT64_PADDING_BITS, calldataload(source_ptr)))
                    mstore(add(target_ptr, WORD_SIZE), 0)
                    source_ptr := add(source_ptr, UINT64_SIZE)
                    target_ptr := add(target_ptr, WORDX2_SIZE)
                }

                mstore(FREE_PTR, target_ptr)

                source_ptr_out := source_ptr
            }
            function exclude_coverage_stop_read_uint64_array_as_uint512_array() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_read_word_array() {} // solhint-disable-line no-empty-blocks
            function read_word_array(source_ptr) -> source_ptr_out, array_ptr {
                array_ptr := mload(FREE_PTR)

                let length := shr(UINT64_PADDING_BITS, calldataload(source_ptr))
                mstore(array_ptr, length)
                source_ptr := add(source_ptr, UINT64_SIZE)

                let target_ptr := add(array_ptr, WORD_SIZE)
                let copy_size := mul(length, WORD_SIZE)
                calldatacopy(target_ptr, source_ptr, copy_size)

                mstore(FREE_PTR, add(target_ptr, copy_size))

                source_ptr_out := add(source_ptr, copy_size)
            }
            function exclude_coverage_stop_read_word_array() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_read_word_array_as_uint512_array() {} // solhint-disable-line no-empty-blocks
            function read_word_array_as_uint512_array(input_array_ptr) -> array_ptr {
                array_ptr := mload(FREE_PTR)

                let length := mload(input_array_ptr)
                mstore(array_ptr, length)
                input_array_ptr := add(input_array_ptr, WORD_SIZE)
                let target_ptr := add(array_ptr, WORD_SIZE)

                for {} length { length := sub(length, 1) } {
                    mstore(target_ptr, mload(input_array_ptr))
                    mstore(add(target_ptr, WORD_SIZE), 0)
                    input_array_ptr := add(input_array_ptr, WORD_SIZE)
                    target_ptr := add(target_ptr, WORDX2_SIZE)
                }

                mstore(FREE_PTR, target_ptr)
            }
            function exclude_coverage_stop_read_word_array_as_uint512_array() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_read_wordx2_array() {} // solhint-disable-line no-empty-blocks
            function read_wordx2_array(source_ptr) -> source_ptr_out, array_ptr {
                // Allocate space for array length
                array_ptr := mload(FREE_PTR)

                let length := shr(UINT64_PADDING_BITS, calldataload(source_ptr))
                mstore(array_ptr, length)
                source_ptr := add(source_ptr, UINT64_SIZE)

                let target_ptr := add(array_ptr, WORD_SIZE)
                let copy_size := mul(length, WORDX2_SIZE)
                calldatacopy(target_ptr, source_ptr, copy_size)

                mstore(FREE_PTR, add(target_ptr, copy_size))

                source_ptr_out := add(source_ptr, copy_size)
            }
            function exclude_coverage_stop_read_wordx2_array() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_compute_evaluations_with_length() {} // solhint-disable-line no-empty-blocks
            function compute_evaluations_with_length(evaluation_point_ptr, array_ptr) {
                let num_vars := mload(evaluation_point_ptr)
                let x := add(evaluation_point_ptr, WORD_SIZE)
                let array_len := mload(array_ptr)
                array_ptr := add(array_ptr, WORD_SIZE)
                for {} array_len { array_len := sub(array_len, 1) } {
                    mstore(
                        add(array_ptr, WORD_SIZE), compute_truncated_lagrange_basis_sum(mload(array_ptr), x, num_vars)
                    )
                    array_ptr := add(array_ptr, WORDX2_SIZE)
                }
            }
            function exclude_coverage_stop_compute_evaluations_with_length() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_compute_truncated_lagrange_basis_sum() {} // solhint-disable-line no-empty-blocks
            function compute_truncated_lagrange_basis_sum(length, x_ptr, num_vars) -> result {
                result := 0

                // Invariant that holds within the for loop:
                // 0 <= result <= modulus + 1
                // This invariant reduces modulus operations.
                for {} num_vars {} {
                    switch and(length, 1)
                    case 0 { result := mulmod(result, sub(MODULUS_PLUS_ONE, mod(mload(x_ptr), MODULUS)), MODULUS) }
                    default {
                        result := sub(MODULUS_PLUS_ONE, mulmod(sub(MODULUS_PLUS_ONE, result), mload(x_ptr), MODULUS))
                    }
                    num_vars := sub(num_vars, 1)
                    length := shr(1, length)
                    x_ptr := add(x_ptr, WORD_SIZE)
                }
                switch length
                case 0 { result := mod(result, MODULUS) }
                default { result := 1 }
            }
            function exclude_coverage_stop_compute_truncated_lagrange_basis_sum() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_compute_rho_evaluations() {} // solhint-disable-line no-empty-blocks
            function compute_rho_evaluations(evaluation_point_ptr, array_ptr) {
                let array_len := mload(array_ptr)
                for {} array_len { array_len := sub(array_len, 1) } {
                    array_ptr := add(array_ptr, WORD_SIZE)
                    let length := mload(array_ptr)
                    let evaluation_vec := compute_evaluation_vec(length, evaluation_point_ptr)
                    let product := 0
                    for {} length {} {
                        let i := sub(length, 1)
                        product := addmod_bn254(product, mulmod_bn254(i, mload(add(evaluation_vec, mul(i, WORD_SIZE)))))
                        length := i
                    }
                    mstore(array_ptr, product)
                }
            }
            function exclude_coverage_stop_compute_rho_evaluations() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_compute_evaluation_vec() {} // solhint-disable-line no-empty-blocks
            function compute_evaluation_vec(length, evaluation_point_ptr) -> evaluations_ptr {
                evaluations_ptr := mload(FREE_PTR)
                mstore(FREE_PTR, add(evaluations_ptr, mul(length, WORD_SIZE)))
                mstore(evaluations_ptr, 1)
                let num_vars := mload(evaluation_point_ptr)
                if gt(length, shl(num_vars, 1)) { err(ERR_EVALUATION_LENGTH_TOO_LARGE) }
                for { let len := 1 } num_vars { num_vars := sub(num_vars, 1) } {
                    let x := mod(mload(add(evaluation_point_ptr, mul(num_vars, WORD_SIZE))), MODULUS)
                    let one_minus_x := sub(MODULUS_PLUS_ONE, x)
                    len := mul(len, 2)
                    if gt(len, length) { len := length }
                    for { let l := len } l {} {
                        l := sub(l, 1)
                        let to_ptr := add(evaluations_ptr, mul(l, WORD_SIZE))
                        let from_ptr := add(evaluations_ptr, mul(shr(1, l), WORD_SIZE))
                        switch mod(l, 2)
                        case 0 { mstore(to_ptr, mulmod(mload(from_ptr), one_minus_x, MODULUS)) }
                        case 1 { mstore(to_ptr, mulmod(mload(from_ptr), x, MODULUS)) }
                    }
                }
            }
            function exclude_coverage_stop_compute_evaluation_vec() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_addmod_bn254() {} // solhint-disable-line no-empty-blocks
            function addmod_bn254(lhs, rhs) -> sum {
                sum := addmod(lhs, rhs, MODULUS)
            }
            function exclude_coverage_stop_addmod_bn254() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_compute_truncated_lagrange_basis_inner_product() {} // solhint-disable-line no-empty-blocks
            function compute_truncated_lagrange_basis_inner_product(length, x_ptr, y_ptr, num_vars) -> result {
                let part := 0 // This is g in the formulas
                result := 1 // This is h in the formulas
                for {} num_vars {} {
                    let x := mload(x_ptr)
                    let y := mload(y_ptr)
                    let xy := mulmod(x, y, MODULUS)
                    // let c := 1 - x
                    // let d := 1 - y
                    let cd := sub(add(MODULUS_PLUS_ONE, xy), addmod(x, y, MODULUS))
                    switch and(length, 1)
                    case 0 { part := mulmod(part, cd, MODULUS) }
                    default { part := add(mulmod(result, cd, MODULUS), mulmod(part, xy, MODULUS)) }
                    result := mulmod(result, add(cd, xy), MODULUS)
                    num_vars := sub(num_vars, 1)
                    length := shr(1, length)
                    x_ptr := add(x_ptr, WORD_SIZE)
                    y_ptr := add(y_ptr, WORD_SIZE)
                }
                if iszero(length) { result := mod(part, MODULUS) } // we return g in "short" cases
            }
            function exclude_coverage_stop_compute_truncated_lagrange_basis_inner_product() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_append_array() {} // solhint-disable-line no-empty-blocks
            function append_array(transcript_ptr, array_ptr) {
                let array_len := mload(array_ptr)
                mstore(array_ptr, mload(transcript_ptr))
                mstore(transcript_ptr, keccak256(array_ptr, mul(add(array_len, 1), WORD_SIZE)))
                mstore(array_ptr, array_len)
            }
            function exclude_coverage_stop_append_array() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_append_calldata() {} // solhint-disable-line no-empty-blocks
            function append_calldata(transcript_ptr, offset, size) {
                let free_ptr := mload(FREE_PTR)
                mstore(free_ptr, mload(transcript_ptr))
                calldatacopy(add(free_ptr, WORD_SIZE), offset, size)
                mstore(transcript_ptr, keccak256(free_ptr, add(size, WORD_SIZE)))
            }
            function exclude_coverage_stop_append_calldata() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_draw_challenges() {} // solhint-disable-line no-empty-blocks
            function draw_challenges(transcript_ptr, count) -> result_ptr {
                // allocate `count` words
                let free_ptr := mload(FREE_PTR)
                mstore(FREE_PTR, add(free_ptr, mul(add(count, 1), WORD_SIZE)))
                // result is the pointer to the first word
                result_ptr := free_ptr
                // store count in the first word
                mstore(result_ptr, count)
                // increment to next word
                free_ptr := add(free_ptr, WORD_SIZE)
                // first challenge is the current transcript state
                let challenge := mload(transcript_ptr)
                for {} count {} {
                    mstore(transcript_ptr, challenge)

                    // store challenge in next word
                    mstore(free_ptr, and(challenge, MODULUS_MASK))
                    // hash challenge to get next challenge
                    challenge := keccak256(transcript_ptr, WORD_SIZE)
                    // increment to next word
                    free_ptr := add(free_ptr, WORD_SIZE)
                    // decrement count
                    count := sub(count, 1)
                }
                // The last (unused) challenge is the current state of the transcript
                mstore(transcript_ptr, challenge)
            }
            function exclude_coverage_stop_draw_challenges() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_check_aggregate_evaluation() {} // solhint-disable-line no-empty-blocks
            function builder_check_aggregate_evaluation(builder_ptr) {
                if mload(add(builder_ptr, BUILDER_AGGREGATE_EVALUATION_OFFSET)) {
                    err(ERR_AGGREGATE_EVALUATION_MISMATCH)
                }
            }
            function exclude_coverage_stop_builder_check_aggregate_evaluation() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_get_chi_evaluations() {} // solhint-disable-line no-empty-blocks
            function builder_get_chi_evaluations(builder_ptr) -> values_ptr {
                values_ptr := mload(add(builder_ptr, BUILDER_CHI_EVALUATIONS_OFFSET))
            }
            function exclude_coverage_stop_builder_get_chi_evaluations() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_get_column_evaluations() {} // solhint-disable-line no-empty-blocks
            function builder_get_column_evaluations(builder_ptr) -> values_ptr {
                values_ptr := mload(add(builder_ptr, BUILDER_COLUMN_EVALUATIONS_OFFSET))
            }
            function exclude_coverage_stop_builder_get_column_evaluations() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_get_final_round_commitments() {} // solhint-disable-line no-empty-blocks
            function builder_get_final_round_commitments(builder_ptr) -> values_ptr {
                values_ptr := mload(add(builder_ptr, BUILDER_FINAL_ROUND_COMMITMENTS_OFFSET))
            }
            function exclude_coverage_stop_builder_get_final_round_commitments() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_get_final_round_mles() {} // solhint-disable-line no-empty-blocks
            function builder_get_final_round_mles(builder_ptr) -> values_ptr {
                values_ptr := mload(add(builder_ptr, BUILDER_FINAL_ROUND_MLES_OFFSET))
            }
            function exclude_coverage_stop_builder_get_final_round_mles() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_get_first_round_commitments() {} // solhint-disable-line no-empty-blocks
            function builder_get_first_round_commitments(builder_ptr) -> values_ptr {
                values_ptr := mload(add(builder_ptr, BUILDER_FIRST_ROUND_COMMITMENTS_OFFSET))
            }
            function exclude_coverage_stop_builder_get_first_round_commitments() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_get_first_round_mles() {} // solhint-disable-line no-empty-blocks
            function builder_get_first_round_mles(builder_ptr) -> values_ptr {
                values_ptr := mload(add(builder_ptr, BUILDER_FIRST_ROUND_MLES_OFFSET))
            }
            function exclude_coverage_stop_builder_get_first_round_mles() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_get_rho_evaluations() {} // solhint-disable-line no-empty-blocks
            function builder_get_rho_evaluations(builder_ptr) -> values_ptr {
                values_ptr := mload(add(builder_ptr, BUILDER_RHO_EVALUATIONS_OFFSET))
            }
            function exclude_coverage_stop_builder_get_rho_evaluations() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_new() {} // solhint-disable-line no-empty-blocks
            function builder_new() -> builder_ptr {
                builder_ptr := mload(FREE_PTR)
                mstore(FREE_PTR, add(builder_ptr, VERIFICATION_BUILDER_SIZE))
            }
            function exclude_coverage_stop_builder_new() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_aggregate_evaluation() {} // solhint-disable-line no-empty-blocks
            function builder_set_aggregate_evaluation(builder_ptr, value) {
                mstore(add(builder_ptr, BUILDER_AGGREGATE_EVALUATION_OFFSET), value)
            }
            function exclude_coverage_stop_builder_set_aggregate_evaluation() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_bit_distributions() {} // solhint-disable-line no-empty-blocks
            function builder_set_bit_distributions(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_FINAL_ROUND_BIT_DISTRIBUTIONS_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_bit_distributions() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_challenges() {} // solhint-disable-line no-empty-blocks
            function builder_set_challenges(builder_ptr, challenges_ptr) {
                mstore(add(builder_ptr, BUILDER_CHALLENGES_OFFSET), challenges_ptr)
            }
            function exclude_coverage_stop_builder_set_challenges() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_chi_evaluations() {} // solhint-disable-line no-empty-blocks
            function builder_set_chi_evaluations(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_CHI_EVALUATIONS_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_chi_evaluations() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_column_evaluations() {} // solhint-disable-line no-empty-blocks
            function builder_set_column_evaluations(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_COLUMN_EVALUATIONS_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_column_evaluations() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_constraint_multipliers() {} // solhint-disable-line no-empty-blocks
            function builder_set_constraint_multipliers(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_CONSTRAINT_MULTIPLIERS_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_constraint_multipliers() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_final_round_commitments() {} // solhint-disable-line no-empty-blocks
            function builder_set_final_round_commitments(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_FINAL_ROUND_COMMITMENTS_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_final_round_commitments() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_final_round_mles() {} // solhint-disable-line no-empty-blocks
            function builder_set_final_round_mles(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_FINAL_ROUND_MLES_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_final_round_mles() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_first_round_commitments() {} // solhint-disable-line no-empty-blocks
            function builder_set_first_round_commitments(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_FIRST_ROUND_COMMITMENTS_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_first_round_commitments() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_first_round_mles() {} // solhint-disable-line no-empty-blocks
            function builder_set_first_round_mles(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_FIRST_ROUND_MLES_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_first_round_mles() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_max_degree() {} // solhint-disable-line no-empty-blocks
            function builder_set_max_degree(builder_ptr, value) {
                mstore(add(builder_ptr, BUILDER_MAX_DEGREE_OFFSET), value)
            }
            function exclude_coverage_stop_builder_set_max_degree() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_placeholder_parameters() {} // solhint-disable-line no-empty-blocks
            function builder_set_placeholder_parameters(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_PLACEHOLDER_PARAMETERS_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_placeholder_parameters() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_rho_evaluations() {} // solhint-disable-line no-empty-blocks
            function builder_set_rho_evaluations(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_RHO_EVALUATIONS_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_rho_evaluations() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_row_multipliers_evaluation() {} // solhint-disable-line no-empty-blocks
            function builder_set_row_multipliers_evaluation(builder_ptr, value) {
                mstore(add(builder_ptr, BUILDER_ROW_MULTIPLIERS_EVALUATION_OFFSET), value)
            }
            function exclude_coverage_stop_builder_set_row_multipliers_evaluation() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_singleton_chi_evaluation() {} // solhint-disable-line no-empty-blocks
            function builder_set_singleton_chi_evaluation(builder_ptr, value) {
                mstore(add(builder_ptr, BUILDER_SINGLETON_CHI_EVALUATION_OFFSET), value)
            }
            function exclude_coverage_stop_builder_set_singleton_chi_evaluation() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_builder_set_table_chi_evaluations() {} // solhint-disable-line no-empty-blocks
            function builder_set_table_chi_evaluations(builder_ptr, values_ptr) {
                mstore(add(builder_ptr, BUILDER_TABLE_CHI_EVALUATIONS_OFFSET), values_ptr)
            }
            function exclude_coverage_stop_builder_set_table_chi_evaluations() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_batch_pcs() {} // solhint-disable-line no-empty-blocks
            function batch_pcs(args_ptr, transcript_ptr, commitments_ptr, evaluations_ptr, batch_eval) -> batch_eval_out
            {
                let num_commitments := mload(commitments_ptr)
                commitments_ptr := add(commitments_ptr, WORD_SIZE)
                let num_evaluations := mload(evaluations_ptr)
                evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
                if sub(num_commitments, num_evaluations) { err(ERR_PCS_BATCH_LENGTH_MISMATCH) }
                for {} num_commitments { num_commitments := sub(num_commitments, 1) } {
                    let challenge := draw_challenge(transcript_ptr)
                    constant_ec_mul_add_assign(
                        args_ptr, mload(commitments_ptr), mload(add(commitments_ptr, WORD_SIZE)), challenge
                    )
                    commitments_ptr := add(commitments_ptr, WORDX2_SIZE)
                    batch_eval := addmod_bn254(batch_eval, mulmod_bn254(mload(evaluations_ptr), challenge))
                    evaluations_ptr := add(evaluations_ptr, WORD_SIZE)
                }
                batch_eval_out := mod(batch_eval, MODULUS)
            }
            function exclude_coverage_stop_batch_pcs() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_draw_challenge() {} // solhint-disable-line no-empty-blocks
            function draw_challenge(transcript_ptr) -> result {
                result := and(mload(transcript_ptr), MODULUS_MASK)
                mstore(transcript_ptr, keccak256(transcript_ptr, WORD_SIZE))
            }
            function exclude_coverage_stop_draw_challenge() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_constant_ec_mul_add_assign() {} // solhint-disable-line no-empty-blocks
            function constant_ec_mul_add_assign(args_ptr, c_x, c_y, scalar) {
                mstore(add(args_ptr, WORDX2_SIZE), c_x)
                mstore(add(args_ptr, WORDX3_SIZE), c_y)
                ec_mul_assign(add(args_ptr, WORDX2_SIZE), scalar)
                ec_add(args_ptr)
            }
            function exclude_coverage_stop_constant_ec_mul_add_assign() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_ec_add() {} // solhint-disable-line no-empty-blocks
            function ec_add(args_ptr) {
                if iszero(staticcall(ECADD_GAS, ECADD_ADDRESS, args_ptr, WORDX4_SIZE, args_ptr, WORDX2_SIZE)) {
                    err(ERR_INVALID_EC_ADD_INPUTS)
                }
            }
            function exclude_coverage_stop_ec_add() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_ec_mul_assign() {} // solhint-disable-line no-empty-blocks
            function ec_mul_assign(args_ptr, scalar) {
                mstore(add(args_ptr, WORDX2_SIZE), scalar)
                ec_mul(args_ptr)
            }
            function exclude_coverage_stop_ec_mul_assign() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_ec_mul() {} // solhint-disable-line no-empty-blocks
            function ec_mul(args_ptr) {
                if iszero(staticcall(ECMUL_GAS, ECMUL_ADDRESS, args_ptr, WORDX3_SIZE, args_ptr, WORDX2_SIZE)) {
                    err(ERR_INVALID_EC_MUL_INPUTS)
                }
            }
            function exclude_coverage_stop_ec_mul() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_verify_hyperkzg() {} // solhint-disable-line no-empty-blocks
            function verify_hyperkzg(proof_ptr, transcript_ptr, commitment_ptr, x, y) {
                function v_ptr(ptr, l) -> result {
                    result := add(ptr, add(UINT64_SIZE, sub(mul(WORDX2_SIZE, l), WORDX2_SIZE)))
                }
                function w_ptr(ptr, l) -> result {
                    result := add(ptr, add(UINT64_SIZE, sub(mul(WORDX5_SIZE, l), WORDX2_SIZE)))
                }

                let ell := mload(x)

                // if ell == 0, then error
                if iszero(ell) { err(ERR_HYPER_KZG_EMPTY_POINT) }
                {
                    let com_len := shr(UINT64_PADDING_BITS, calldataload(proof_ptr))
                    if sub(com_len, sub(ell, 1)) { err(ERR_HYPER_KZG_PROOF_SIZE_MISMATCH) }
                    proof_ptr := add(proof_ptr, UINT64_SIZE)
                    let v_len := shr(UINT64_PADDING_BITS, calldataload(add(proof_ptr, mul(WORDX2_SIZE, sub(ell, 1)))))
                    if sub(v_len, ell) { err(ERR_HYPER_KZG_PROOF_SIZE_MISMATCH) }
                }

                // Step 1: Run the transcript
                // WARNING: The public inputs (x, y, the commitments, digest of the KZG SRS, degree bound, etc) are
                // NOT included in the transcript and need to be added, either explicitly or implicitly,
                // before calling this function
                let r, q, d :=
                    run_transcript(proof_ptr, v_ptr(proof_ptr, ell), w_ptr(proof_ptr, ell), transcript_ptr, ell)

                // Step 2: Compute bivariate evaluation
                let b := bivariate_evaluation(v_ptr(proof_ptr, ell), q, d, ell)

                // Step 3: Check v consistency
                check_v_consistency(v_ptr(proof_ptr, ell), r, x, y)

                // Allocate scratch space for L, R, and the pairing check
                let scratch := mload(FREE_PTR)

                // Step 4: Compute L
                compute_gl_msm(proof_ptr, sub(ell, 1), w_ptr(proof_ptr, ell), commitment_ptr, r, q, d, b, scratch)

                // Step 5: Compute R
                univariate_group_evaluation(w_ptr(proof_ptr, ell), d, 3, add(scratch, WORDX6_SIZE))

                // Step 6: Verify the pairing equation
                mstore(add(scratch, WORDX2_SIZE), G2_NEG_GEN_X_IMAG)
                mstore(add(scratch, WORDX3_SIZE), G2_NEG_GEN_X_REAL)
                mstore(add(scratch, WORDX4_SIZE), G2_NEG_GEN_Y_IMAG)
                mstore(add(scratch, WORDX5_SIZE), G2_NEG_GEN_Y_REAL)
                mstore(add(scratch, WORDX8_SIZE), VK_TAU_HX_IMAG)
                mstore(add(scratch, WORDX9_SIZE), VK_TAU_HX_REAL)
                mstore(add(scratch, WORDX10_SIZE), VK_TAU_HY_IMAG)
                mstore(add(scratch, WORDX11_SIZE), VK_TAU_HY_REAL)
                if iszero(ec_pairing_x2(scratch)) { err(ERR_HYPER_KZG_PAIRING_CHECK_FAILED) }
            }
            function exclude_coverage_stop_verify_hyperkzg() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_bivariate_evaluation() {} // solhint-disable-line no-empty-blocks
            function bivariate_evaluation(v_ptr, q, d, ell) -> b {
                b := 0
                let v_stack := add(v_ptr, mul(WORDX3_SIZE, ell))
                for {} ell { ell := sub(ell, 1) } {
                    // tmp = v2i
                    v_stack := sub(v_stack, WORD_SIZE)
                    let tmp := calldataload(v_stack)
                    // tmp = v2i * d
                    tmp := mulmod_bn254(tmp, d)
                    // tmp += v1i
                    v_stack := sub(v_stack, WORD_SIZE)
                    tmp := addmod_bn254(tmp, calldataload(v_stack))
                    // tmp *= d
                    tmp := mulmod_bn254(tmp, d)
                    // tmp += v0i
                    v_stack := sub(v_stack, WORD_SIZE)
                    tmp := addmod_bn254(tmp, calldataload(v_stack))

                    // b *= q
                    b := mulmod_bn254(b, q)
                    // b += tmp
                    b := addmod_bn254(b, tmp)
                }
            }
            function exclude_coverage_stop_bivariate_evaluation() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_univariate_group_evaluation() {} // solhint-disable-line no-empty-blocks
            function univariate_group_evaluation(g_ptr, e, length, scratch) {
                switch length
                case 0 {
                    mstore(scratch, 0)
                    mstore(add(scratch, WORD_SIZE), 0)
                }
                default {
                    length := sub(length, 1)
                    g_ptr := add(g_ptr, mul(length, WORDX2_SIZE))
                    // result = g.pop()
                    calldatacopy(scratch, g_ptr, WORDX2_SIZE)
                    for {} length { length := sub(length, 1) } {
                        // g_l *= e
                        ec_mul_assign(scratch, e)
                        // g_l += com.pop()
                        g_ptr := sub(g_ptr, WORDX2_SIZE)
                        calldata_ec_add_assign(scratch, g_ptr)
                    }
                }
            }
            function exclude_coverage_stop_univariate_group_evaluation() {} // solhint-disable-line no-empty-blocks
            function exclude_coverage_start_calldata_ec_add_assign() {} // solhint-disable-line no-empty-blocks
            function calldata_ec_add_assign(args_p

Tags:
Proxy, Swap, Upgradeable, Factory, Oracle|addr:0x74f710114a9a226fe70741a7fa10c6f3689538ef|verified:true|block:23723216|tx:0x55fc11d7c4c67bfc956c17e0b853d7f6ae4d4334a34b954f33acbe0845a45c40|first_check:1762251036

Submitted on: 2025-11-04 11:10:13

Comments

Log in to comment.

No comments yet.