Constant EVM_HALO2_VERIFIER_TEMPLATE

Source
pub const EVM_HALO2_VERIFIER_TEMPLATE: &str = "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport { Halo2Verifier } from \"./Halo2Verifier.sol\";\nimport { IOpenVmHalo2Verifier } from \"./interfaces/IOpenVmHalo2Verifier.sol\";\n\ntype MemoryPointer is uint256;\n\n/// @notice This contract provides a thin wrapper around the Halo2 verifier\n/// outputted by `snark-verifier`, exposing a more user-friendly interface.\ncontract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier {\n    /// @dev Invalid public values length\n    error InvalidPublicValuesLength(uint256 expected, uint256 actual);\n\n    /// @dev Invalid proof data length\n    error InvalidProofDataLength(uint256 expected, uint256 actual);\n\n    /// @dev Proof verification failed\n    error ProofVerificationFailed();\n\n    /// @dev The length of the proof data, in bytes.\n    uint256 private constant PROOF_DATA_LENGTH = (12 + 43) * 32;\n\n    /// @dev The length of the public values, in bytes. This value is set by\n    /// OpenVM and is guaranteed to be no larger than 8192.\n    uint256 private constant PUBLIC_VALUES_LENGTH = {PUBLIC_VALUES_LENGTH};\n\n    /// @dev The length of the full proof, in bytes\n    uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + PUBLIC_VALUES_LENGTH + 43) * 32;\n\n    /// @dev The version of OpenVM that generated this verifier.\n    string public constant OPENVM_VERSION = \"{OPENVM_VERSION}\";\n\n    /// @notice A wrapper that constructs the proof into the right format for\n    /// use with the `snark-verifier` verification.\n    ///\n    /// @dev The verifier expected proof format is:\n    /// proof[..12 * 32]: KZG accumulator\n    /// proof[12 * 32..13 * 32]: app exe commit\n    /// proof[13 * 32..14 * 32]: app vm commit\n    /// proof[14 * 32..(14 + PUBLIC_VALUES_LENGTH) * 32]: publicValues[0..PUBLIC_VALUES_LENGTH]\n    /// proof[(14 + PUBLIC_VALUES_LENGTH) * 32..]: Proof Suffix\n    ///\n    /// @param publicValues The PVs revealed by the OpenVM guest program.\n    /// @param proofData All components of the proof except the public values and\n    /// app exe and vm commits. The expected format is:\n    /// `abi.encodePacked(kzgAccumulator, proofSuffix)`\n    /// @param appExeCommit The commitment to the OpenVM application executable whose execution\n    /// is being verified.\n    /// @param appVmCommit The commitment to the VM configuration.\n    function verify(bytes calldata publicValues, bytes calldata proofData, bytes32 appExeCommit, bytes32 appVmCommit) external view {\n        if (publicValues.length != PUBLIC_VALUES_LENGTH) revert InvalidPublicValuesLength(PUBLIC_VALUES_LENGTH, publicValues.length);\n        if (proofData.length != PROOF_DATA_LENGTH) revert InvalidProofDataLength(PROOF_DATA_LENGTH, proofData.length);\n\n        // We will format the public values and construct the full proof payload\n        // below.\n\n        MemoryPointer proofPtr = _constructProof(publicValues, proofData, appExeCommit, appVmCommit);\n\n        uint256 fullProofLength = FULL_PROOF_LENGTH;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Self-call using the proof as calldata\n            if iszero(staticcall(gas(), address(), proofPtr, fullProofLength, 0, 0)) {\n                mstore(0x00, 0xd611c318) // ProofVerificationFailed()\n                revert(0x1c, 0x04)\n            }\n        }\n    }\n\n    /// @dev The assembly code should perform the same function as the following\n    /// solidity code:\n    //\n    /// ```solidity\n    /// bytes memory proof =\n    ///     abi.encodePacked(proofData[0:0x180], appExeCommit, appVmCommit, publicValuesPayload, proofData[0x180:]);\n    /// ```\n    //\n    /// where `publicValuesPayload` is a memory payload with each byte in\n    /// `publicValues` separated into its own `bytes32` word.\n    ///\n    /// This function does not clean the memory it allocates. Since it is the\n    /// only memory write that occurs in the call frame, we know that\n    /// the memory region cannot have been dirtied.\n    ///\n    /// @return proofPtr Memory pointer to the beginning of the constructed\n    /// proof. This pointer does not follow `bytes memory` semantics.\n    function _constructProof(bytes calldata publicValues, bytes calldata proofData, bytes32 appExeCommit, bytes32 appVmCommit)\n        internal\n        pure\n        returns (MemoryPointer proofPtr)\n    {\n        uint256 fullProofLength = FULL_PROOF_LENGTH;\n\n        // The expected proof format using hex offsets:\n        //\n        // proof[..0x180]: KZG accumulator\n        // proof[0x180..0x1a0]: app exe commit\n        // proof[0x1a0..0x1c0]: app vm commit\n        // proof[0x1c0..(0x1c0 + PUBLIC_VALUES_LENGTH * 32)]: publicValues[0..PUBLIC_VALUES_LENGTH]\n        // proof[(0x1c0 + PUBLIC_VALUES_LENGTH * 32)..]: Proof Suffix\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            proofPtr := mload(0x40)\n            // Allocate the memory as a safety measure.\n            mstore(0x40, add(proofPtr, fullProofLength))\n\n            // Copy the KZG accumulator (length 0x180) into the beginning of\n            // the memory buffer\n            calldatacopy(proofPtr, proofData.offset, 0x180)\n\n            // Copy the App Exe Commit and App Vm Commit into the memory buffer\n            mstore(add(proofPtr, 0x180), appExeCommit)\n            mstore(add(proofPtr, 0x1a0), appVmCommit)\n\n            // Copy the Proof Suffix (length 43 * 32 = 0x560) into the\n            // end of the memory buffer, leaving PUBLIC_VALUES_LENGTH words in\n            // between for the publicValuesPayload.\n            //\n            // Begin copying from the end of the KZG accumulator in the\n            // calldata buffer (0x180)\n            let proofSuffixOffset := add(0x1c0, shl(5, PUBLIC_VALUES_LENGTH))\n            calldatacopy(add(proofPtr, proofSuffixOffset), add(proofData.offset, 0x180), 0x560)\n\n            // Copy each byte of the public values into the proof. It copies the\n            // most significant bytes of public values first.\n            let publicValuesMemOffset := add(add(proofPtr, 0x1c0), 0x1f)\n            for { let i := 0 } iszero(eq(i, PUBLIC_VALUES_LENGTH)) { i := add(i, 1) } {\n                calldatacopy(add(publicValuesMemOffset, shl(5, i)), add(publicValues.offset, i), 0x01)\n            }\n        }\n    }\n}\n";