diff --git a/barretenberg/sol/src/honk/Transcript.sol b/barretenberg/sol/src/honk/Transcript.sol index 86f689aa81d0..c10d2c00654c 100644 --- a/barretenberg/sol/src/honk/Transcript.sol +++ b/barretenberg/sol/src/honk/Transcript.sol @@ -223,61 +223,6 @@ library TranscriptLib { // logFr("rho", rho); } - function generateGeminiRChallenge(Honk.Proof memory proof, Fr prevChallenge) - internal - pure - returns (Fr geminiR, Fr nextPreviousChallenge) - { - uint256[(CONST_PROOF_SIZE_LOG_N - 1) * 4 + 1] memory gR; - gR[0] = Fr.unwrap(prevChallenge); - - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { - gR[1 + i * 4] = proof.geminiFoldUnivariates[i].x_0; - gR[2 + i * 4] = proof.geminiFoldUnivariates[i].x_1; - gR[3 + i * 4] = proof.geminiFoldUnivariates[i].y_0; - gR[4 + i * 4] = proof.geminiFoldUnivariates[i].y_1; - } - - nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR))); - Fr unused; - (geminiR, unused) = splitChallenge(nextPreviousChallenge); - } - - function generateShplonkNuChallenge(Honk.Proof memory proof, Fr prevChallenge) - internal - pure - returns (Fr shplonkNu, Fr nextPreviousChallenge) - { - uint256[(CONST_PROOF_SIZE_LOG_N) + 1] memory shplonkNuChallengeElements; - shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge); - - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - shplonkNuChallengeElements[i + 1] = Fr.unwrap(proof.geminiAEvaluations[i]); - } - - nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements))); - Fr unused; - (shplonkNu, unused) = splitChallenge(nextPreviousChallenge); - } - - function generateShplonkZChallenge(Honk.Proof memory proof, Fr prevChallenge) - internal - pure - returns (Fr shplonkZ, Fr nextPreviousChallenge) - { - uint256[5] memory shplonkZChallengeElements; - shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge); - - shplonkZChallengeElements[1] = proof.shplonkQ.x_0; - shplonkZChallengeElements[2] = proof.shplonkQ.x_1; - shplonkZChallengeElements[3] = proof.shplonkQ.y_0; - shplonkZChallengeElements[4] = proof.shplonkQ.y_1; - - nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements))); - Fr unused; - (shplonkZ, unused) = splitChallenge(nextPreviousChallenge); - } - function generateGeminiRChallenge(Honk.Proof memory proof, Fr prevChallenge) internal pure diff --git a/barretenberg/sol/src/honk/instance/Add2Honk.sol b/barretenberg/sol/src/honk/instance/Add2Honk.sol index a56a3b256a01..f64a6016571d 100644 --- a/barretenberg/sol/src/honk/instance/Add2Honk.sol +++ b/barretenberg/sol/src/honk/instance/Add2Honk.sol @@ -435,7 +435,6 @@ contract Add2HonkVerifier is IVerifier { a_0_pos = batchedEvalAccumulator; } - // This implementation is the same as above with different constants function batchMul( Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory base, Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory scalars @@ -480,14 +479,14 @@ contract Add2HonkVerifier is IVerifier { bytes memory input = abi.encodePacked( rhs.x, rhs.y, - // Fixed G1 point + // G2 [1] uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), lhs.x, lhs.y, - // G1 point from VK + // G2 [x] uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), diff --git a/barretenberg/sol/src/honk/instance/BlakeHonk.sol b/barretenberg/sol/src/honk/instance/BlakeHonk.sol index 1085ed748ca8..da35a52bd501 100644 --- a/barretenberg/sol/src/honk/instance/BlakeHonk.sol +++ b/barretenberg/sol/src/honk/instance/BlakeHonk.sol @@ -17,7 +17,7 @@ import { CONST_PROOF_SIZE_LOG_N } from "../HonkTypes.sol"; -import {ecMul, ecAdd, ecSub, negateInplace, convertProofPoint, logFr, logG1} from "../utils.sol"; +import {ecMul, ecAdd, ecSub, negateInplace, convertProofPoint} from "../utils.sol"; // Field arithmetic libraries - prevent littering the code with modmul / addmul import {MODULUS as P, MINUS_ONE, Fr, FrLib} from "../Fr.sol"; @@ -37,7 +37,12 @@ error ShpleminiFailed(); contract BlakeHonkVerifier is IVerifier { using FrLib for Fr; - function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) { + function verify(bytes calldata proof, bytes32[] calldata publicInputs) + public + // view WORKTODO: bring back + override + returns (bool) + { Honk.VerificationKey memory vk = loadVerificationKey(); Honk.Proof memory p = TranscriptLib.loadProof(proof); @@ -55,8 +60,6 @@ contract BlakeHonkVerifier is IVerifier { // Sumcheck bool sumcheckVerified = verifySumcheck(p, t); if (!sumcheckVerified) revert SumcheckFailed(); - uint256 gasAfter = gasleft(); - console.log("Gas used until sumcheck: ", gasBefore - gasAfter); bool shpleminiVerified = verifyShplemini(p, vk, t); if (!shpleminiVerified) revert ShpleminiFailed(); @@ -200,6 +203,9 @@ contract BlakeHonkVerifier is IVerifier { struct ShpleminiIntermediates { Fr unshiftedScalar; Fr shiftedScalar; + // Negative versions of the values above - these are used in hot loops, so storing is preferred + Fr unshiftedScalarNeg; + Fr shiftedScalarNeg; // Scalar to be multiplied by [1]₁ Fr constantTermAccumulator; // Linear combination of multilinear (sumcheck) evaluations and powers of rho @@ -210,8 +216,10 @@ contract BlakeHonkVerifier is IVerifier { function verifyShplemini(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp) internal - view - returns (bool verified) + returns ( + // WORKTODO: reinstantiate view func + bool verified + ) { ShpleminiIntermediates memory mem; // stack @@ -262,14 +270,19 @@ contract BlakeHonkVerifier is IVerifier { mem.batchingChallenge = Fr.wrap(1); mem.batchedEvaluation = Fr.wrap(0); + // TODO: move into mem above - same with one below!!!! + // mem.unshiftedScalarNeg = mem.unshiftedScalar.neg(); for (uint256 i = 1; i <= NUMBER_UNSHIFTED; ++i) { scalars[i] = mem.unshiftedScalar.neg() * mem.batchingChallenge; + // scalars[i] = mem.unshiftedScalarNeg * mem.batchingChallenge; mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i - 1] * mem.batchingChallenge); mem.batchingChallenge = mem.batchingChallenge * tp.rho; } // g commitments are accumulated at r + // mem.shiftedScalarNeg = mem.unshiftedScalar.neg(); for (uint256 i = NUMBER_UNSHIFTED + 1; i <= NUMBER_OF_ENTITIES; ++i) { scalars[i] = mem.shiftedScalar.neg() * mem.batchingChallenge; + // scalars[i] = mem.shiftedScalarNeg * mem.batchingChallenge; mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i - 1] * mem.batchingChallenge); mem.batchingChallenge = mem.batchingChallenge * tp.rho; } @@ -401,11 +414,17 @@ contract BlakeHonkVerifier is IVerifier { Fr[CONST_PROOF_SIZE_LOG_N] memory eval_challenge_powers ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N + 1] memory inverse_vanishing_evals) { Fr eval_challenge = tp.shplonkZ; + inverse_vanishing_evals[0] = (eval_challenge - eval_challenge_powers[0]).invert(); + Fr temp = eval_challenge - eval_challenge_powers[0]; + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { Fr round_inverted_denominator = Fr.wrap(0); if (i <= LOG_N + 1) { + // TOOD(md): remove both lines + temp = (eval_challenge + eval_challenge_powers[i]); + round_inverted_denominator = (eval_challenge + eval_challenge_powers[i]).invert(); } inverse_vanishing_evals[i + 1] = round_inverted_denominator; @@ -418,22 +437,19 @@ contract BlakeHonkVerifier is IVerifier { Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers ) internal view returns (Fr a_0_pos) { - for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) { + // OTP: this does not need to iterate more than LOG_N times + // There is no benefit - the current code is CONST_PROOF_SIZE_LOG_N + for (uint256 i = LOG_N; i > 0; --i) { Fr challengePower = geminiEvalChallengePowers[i - 1]; Fr u = tp.sumCheckUChallenges[i - 1]; Fr evalNeg = geminiEvaluations[i - 1]; - Fr batchedEvalRoundAcc = ( + batchedEvalAccumulator = ( (challengePower * batchedEvalAccumulator * Fr.wrap(2)) - evalNeg * (challengePower * (Fr.wrap(1) - u) - u) ); // Divide by the denominator - batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (Fr.wrap(1) - u) + u).invert(); - - bool is_dummy_round = (i > LOG_N); - if (!is_dummy_round) { - batchedEvalAccumulator = batchedEvalRoundAcc; - } + batchedEvalAccumulator = batchedEvalAccumulator * (challengePower * (Fr.wrap(1) - u) + u).invert(); } a_0_pos = batchedEvalAccumulator; @@ -443,7 +459,7 @@ contract BlakeHonkVerifier is IVerifier { function batchMul( Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory base, Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory scalars - ) internal view returns (Honk.G1Point memory result) { + ) internal returns (Honk.G1Point memory result) { uint256 limit = NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2; assembly { let success := 0x01 @@ -456,8 +472,24 @@ contract BlakeHonkVerifier is IVerifier { mstore(add(free, 0x60), mload(add(0x20, mload(base)))) // Add scalar mstore(add(free, 0x80), mload(scalars)) + + // Inputs + log4( + 0x00, + 0x00, + 0x20, + // The point + mload(mload(base)), + mload(add(0x20, mload(base))), + // The scalar + mload(scalars) + ) + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40)) + // TEMPLOG: Initial accumualtor + log3(0x00, 0x00, 0x00, mload(free), mload(add(free, 0x20))) + let count := 0x01 for {} lt(count, limit) { count := add(count, 1) } { // Get loop offsets @@ -469,6 +501,17 @@ contract BlakeHonkVerifier is IVerifier { // Add scalar mstore(add(free, 0x80), mload(scalar_base)) + log4( + 0x00, + 0x00, + count, + // The point + mload(add(free, 0x40)), + mload(add(free, 0x60)), + // The scalar + mload(add(free, 0x80)) + ) + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) // accumulator = accumulator + accumulator_2 success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) @@ -484,14 +527,14 @@ contract BlakeHonkVerifier is IVerifier { bytes memory input = abi.encodePacked( rhs.x, rhs.y, - // Fixed G1 point + // G2 [1] uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), lhs.x, lhs.y, - // G1 point from VK + // G2 [x] uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), diff --git a/barretenberg/sol/src/honk/instance/EcdsaHonk.sol b/barretenberg/sol/src/honk/instance/EcdsaHonk.sol index 5e3c064defc1..d0dffade485d 100644 --- a/barretenberg/sol/src/honk/instance/EcdsaHonk.sol +++ b/barretenberg/sol/src/honk/instance/EcdsaHonk.sol @@ -483,14 +483,14 @@ contract EcdsaHonkVerifier is IVerifier { bytes memory input = abi.encodePacked( rhs.x, rhs.y, - // Fixed G1 point + // G2 [1] uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), lhs.x, lhs.y, - // G1 point from VK + // G2 [x] uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), diff --git a/barretenberg/sol/src/honk/optimised/blake-opt.sol b/barretenberg/sol/src/honk/optimised/blake-opt.sol index 2f12853fe55f..2dd59fafff9a 100644 --- a/barretenberg/sol/src/honk/optimised/blake-opt.sol +++ b/barretenberg/sol/src/honk/optimised/blake-opt.sol @@ -1,4 +1,8 @@ -pragma solidity ^0.8.26; +// TODO: CONVERT ALL LATEX INTO ASCII LATEX +pragma solidity ^0.8.27; + +// WORKTODO: could we have two versions of the verifier, one which has rolled loops and one which +// unrolls loops?? - analogous with aggressive inlining import {IVerifier} from "../../interfaces/IVerifier.sol"; import { @@ -18,6 +22,14 @@ import "forge-std/console.sol"; import {logAsmG1, logFr, bytes32ToString} from "../utils.sol"; + +error PUBLIC_INPUT_TOO_LARGE(); +error SUMCHECK_FAILED(); +error PAIRING_FAILED(); +error BATCH_ACCUMULATION_FAILED(); +error MODEXP_FAILED(); +error PROOF_POINT_NOT_ON_CURVE(); + // The plan // Write an optimised version of the add2 circuit contract BlakeOptHonkVerifier is IVerifier { @@ -120,6 +132,7 @@ contract BlakeOptHonkVerifier is IVerifier { uint256 internal constant z_perm_x1_loc = 0x1560; uint256 internal constant z_perm_y0_loc = 0x1580; uint256 internal constant z_perm_y1_loc = 0x15a0; + uint256 internal constant sumcheck_univariate_0_0 = 0x15c0; uint256 internal constant sumcheck_univariate_0_1 = 0x15e0; uint256 internal constant sumcheck_univariate_0_2 = 0x1600; @@ -344,6 +357,7 @@ contract BlakeOptHonkVerifier is IVerifier { uint256 internal constant sumcheck_univariate_7_25 = 0x3160; uint256 internal constant sumcheck_univariate_7_26 = 0x3180; uint256 internal constant sumcheck_univariate_7_27 = 0x31a0; + uint256 internal constant QM_EVAL_LOC = 0x31c0; uint256 internal constant QC_EVAL_LOC = 0x31e0; uint256 internal constant Q1_EVAL_LOC = 0x3200; @@ -389,297 +403,494 @@ contract BlakeOptHonkVerifier is IVerifier { uint256 internal constant W4_SHIFT_EVAL_LOC = 0x3700; uint256 internal constant Z_PERM_SHIFT_EVAL_LOC = 0x3720; - // Zermorph items - uint256 internal constant zm_cqs_0_x0_loc = 0x3740; - uint256 internal constant zm_cqs_0_x1_loc = 0x3760; - uint256 internal constant zm_cqs_0_y0_loc = 0x3780; - uint256 internal constant zm_cqs_0_y1_loc = 0x37a0; - uint256 internal constant zm_cqs_1_x0_loc = 0x37c0; - uint256 internal constant zm_cqs_1_x1_loc = 0x37e0; - uint256 internal constant zm_cqs_1_y0_loc = 0x3800; - uint256 internal constant zm_cqs_1_y1_loc = 0x3820; - uint256 internal constant zm_cqs_2_x0_loc = 0x3840; - uint256 internal constant zm_cqs_2_x1_loc = 0x3860; - uint256 internal constant zm_cqs_2_y0_loc = 0x3880; - uint256 internal constant zm_cqs_2_y1_loc = 0x38a0; - uint256 internal constant zm_cqs_3_x0_loc = 0x38c0; - uint256 internal constant zm_cqs_3_x1_loc = 0x38e0; - uint256 internal constant zm_cqs_3_y0_loc = 0x3900; - uint256 internal constant zm_cqs_3_y1_loc = 0x3920; - uint256 internal constant zm_cqs_4_x0_loc = 0x3940; - uint256 internal constant zm_cqs_4_x1_loc = 0x3960; - uint256 internal constant zm_cqs_4_y0_loc = 0x3980; - uint256 internal constant zm_cqs_4_y1_loc = 0x39a0; - uint256 internal constant zm_cqs_5_x0_loc = 0x39c0; - uint256 internal constant zm_cqs_5_x1_loc = 0x39e0; - uint256 internal constant zm_cqs_5_y0_loc = 0x3a00; - uint256 internal constant zm_cqs_5_y1_loc = 0x3a20; - uint256 internal constant zm_cqs_6_x0_loc = 0x3a40; - uint256 internal constant zm_cqs_6_x1_loc = 0x3a60; - uint256 internal constant zm_cqs_6_y0_loc = 0x3a80; - uint256 internal constant zm_cqs_6_y1_loc = 0x3aa0; - uint256 internal constant zm_cqs_7_x0_loc = 0x3ac0; - uint256 internal constant zm_cqs_7_x1_loc = 0x3ae0; - uint256 internal constant zm_cqs_7_y0_loc = 0x3b00; - uint256 internal constant zm_cqs_7_y1_loc = 0x3b20; - uint256 internal constant zm_cqs_8_x0_loc = 0x3b40; - uint256 internal constant zm_cqs_8_x1_loc = 0x3b60; - uint256 internal constant zm_cqs_8_y0_loc = 0x3b80; - uint256 internal constant zm_cqs_8_y1_loc = 0x3ba0; - uint256 internal constant zm_cqs_9_x0_loc = 0x3bc0; - uint256 internal constant zm_cqs_9_x1_loc = 0x3be0; - uint256 internal constant zm_cqs_9_y0_loc = 0x3c00; - uint256 internal constant zm_cqs_9_y1_loc = 0x3c20; - uint256 internal constant zm_cqs_10_x0_loc = 0x3c40; - uint256 internal constant zm_cqs_10_x1_loc = 0x3c60; - uint256 internal constant zm_cqs_10_y0_loc = 0x3c80; - uint256 internal constant zm_cqs_10_y1_loc = 0x3ca0; - uint256 internal constant zm_cqs_11_x0_loc = 0x3cc0; - uint256 internal constant zm_cqs_11_x1_loc = 0x3ce0; - uint256 internal constant zm_cqs_11_y0_loc = 0x3d00; - uint256 internal constant zm_cqs_11_y1_loc = 0x3d20; - uint256 internal constant zm_cqs_12_x0_loc = 0x3d40; - uint256 internal constant zm_cqs_12_x1_loc = 0x3d60; - uint256 internal constant zm_cqs_12_y0_loc = 0x3d80; - uint256 internal constant zm_cqs_12_y1_loc = 0x3da0; - uint256 internal constant zm_cqs_13_x0_loc = 0x3dc0; - uint256 internal constant zm_cqs_13_x1_loc = 0x3de0; - uint256 internal constant zm_cqs_13_y0_loc = 0x3e00; - uint256 internal constant zm_cqs_13_y1_loc = 0x3e20; - uint256 internal constant zm_cqs_14_x0_loc = 0x3e40; - uint256 internal constant zm_cqs_14_x1_loc = 0x3e60; - uint256 internal constant zm_cqs_14_y0_loc = 0x3e80; - uint256 internal constant zm_cqs_14_y1_loc = 0x3ea0; - uint256 internal constant zm_cqs_15_x0_loc = 0x3ec0; - uint256 internal constant zm_cqs_15_x1_loc = 0x3ee0; - uint256 internal constant zm_cqs_15_y0_loc = 0x3f00; - uint256 internal constant zm_cqs_15_y1_loc = 0x3f20; - uint256 internal constant zm_cqs_16_x0_loc = 0x3f40; - uint256 internal constant zm_cqs_16_x1_loc = 0x3f60; - uint256 internal constant zm_cqs_16_y0_loc = 0x3f80; - uint256 internal constant zm_cqs_16_y1_loc = 0x3fa0; - uint256 internal constant zm_cqs_17_x0_loc = 0x3fc0; - uint256 internal constant zm_cqs_17_x1_loc = 0x3fe0; - uint256 internal constant zm_cqs_17_y0_loc = 0x4000; - uint256 internal constant zm_cqs_17_y1_loc = 0x4020; - uint256 internal constant zm_cqs_18_x0_loc = 0x4040; - uint256 internal constant zm_cqs_18_x1_loc = 0x4060; - uint256 internal constant zm_cqs_18_y0_loc = 0x4080; - uint256 internal constant zm_cqs_18_y1_loc = 0x40a0; - uint256 internal constant zm_cqs_19_x0_loc = 0x40c0; - uint256 internal constant zm_cqs_19_x1_loc = 0x40e0; - uint256 internal constant zm_cqs_19_y0_loc = 0x4100; - uint256 internal constant zm_cqs_19_y1_loc = 0x4120; - uint256 internal constant zm_cqs_20_x0_loc = 0x4140; - uint256 internal constant zm_cqs_20_x1_loc = 0x4160; - uint256 internal constant zm_cqs_20_y0_loc = 0x4180; - uint256 internal constant zm_cqs_20_y1_loc = 0x41a0; - uint256 internal constant zm_cqs_21_x0_loc = 0x41c0; - uint256 internal constant zm_cqs_21_x1_loc = 0x41e0; - uint256 internal constant zm_cqs_21_y0_loc = 0x4200; - uint256 internal constant zm_cqs_21_y1_loc = 0x4220; - uint256 internal constant zm_cqs_22_x0_loc = 0x4240; - uint256 internal constant zm_cqs_22_x1_loc = 0x4260; - uint256 internal constant zm_cqs_22_y0_loc = 0x4280; - uint256 internal constant zm_cqs_22_y1_loc = 0x42a0; - uint256 internal constant zm_cqs_23_x0_loc = 0x42c0; - uint256 internal constant zm_cqs_23_x1_loc = 0x42e0; - uint256 internal constant zm_cqs_23_y0_loc = 0x4300; - uint256 internal constant zm_cqs_23_y1_loc = 0x4320; - uint256 internal constant zm_cqs_24_x0_loc = 0x4340; - uint256 internal constant zm_cqs_24_x1_loc = 0x4360; - uint256 internal constant zm_cqs_24_y0_loc = 0x4380; - uint256 internal constant zm_cqs_24_y1_loc = 0x43a0; - uint256 internal constant zm_cqs_25_x0_loc = 0x43c0; - uint256 internal constant zm_cqs_25_x1_loc = 0x43e0; - uint256 internal constant zm_cqs_25_y0_loc = 0x4400; - uint256 internal constant zm_cqs_25_y1_loc = 0x4420; - uint256 internal constant zm_cqs_26_x0_loc = 0x4440; - uint256 internal constant zm_cqs_26_x1_loc = 0x4460; - uint256 internal constant zm_cqs_26_y0_loc = 0x4480; - uint256 internal constant zm_cqs_26_y1_loc = 0x44a0; - uint256 internal constant zm_cqs_27_x0_loc = 0x44c0; - uint256 internal constant zm_cqs_27_x1_loc = 0x44e0; - uint256 internal constant zm_cqs_27_y0_loc = 0x4500; - uint256 internal constant zm_cqs_27_y1_loc = 0x4520; - uint256 internal constant zm_cq_x0_loc = 0x4540; - uint256 internal constant zm_cq_x1_loc = 0x4560; - uint256 internal constant zm_cq_y0_loc = 0x4580; - uint256 internal constant zm_cq_y1_loc = 0x45a0; - uint256 internal constant zm_pi_x0_loc = 0x45c0; - uint256 internal constant zm_pi_x1_loc = 0x45e0; - uint256 internal constant zm_pi_y0_loc = 0x4600; - uint256 internal constant zm_pi_y1_loc = 0x4620; - - // Challenges offsets - uint256 internal constant eta_challenge_loc = 0x4640; - uint256 internal constant eta_two_challenge_loc = 0x4660; - uint256 internal constant eta_three_challenge_loc = 0x4680; - uint256 internal constant beta_challenge_loc = 0x46a0; - uint256 internal constant gamma_challenge_loc = 0x46c0; - uint256 internal constant rho_challenge_loc = 0x46e0; - uint256 internal constant zm_x_challenge_loc = 0x4700; - uint256 internal constant zm_y_challenge_loc = 0x4720; - uint256 internal constant zm_z_challenge_loc = 0x4740; - uint256 internal constant zm_quotient_challenge_loc = 0x4760; - uint256 internal constant public_inputs_delta_challenge_loc = 0x4780; - uint256 internal constant alpha_challenge_0_loc = 0x47a0; - uint256 internal constant alpha_challenge_1_loc = 0x47c0; - uint256 internal constant alpha_challenge_2_loc = 0x47e0; - uint256 internal constant alpha_challenge_3_loc = 0x4800; - uint256 internal constant alpha_challenge_4_loc = 0x4820; - uint256 internal constant alpha_challenge_5_loc = 0x4840; - uint256 internal constant alpha_challenge_6_loc = 0x4860; - uint256 internal constant alpha_challenge_7_loc = 0x4880; - uint256 internal constant alpha_challenge_8_loc = 0x48a0; - uint256 internal constant alpha_challenge_9_loc = 0x48c0; - uint256 internal constant alpha_challenge_10_loc = 0x48e0; - uint256 internal constant alpha_challenge_11_loc = 0x4900; - uint256 internal constant alpha_challenge_12_loc = 0x4920; - uint256 internal constant alpha_challenge_13_loc = 0x4940; - uint256 internal constant alpha_challenge_14_loc = 0x4960; - uint256 internal constant alpha_challenge_15_loc = 0x4980; - uint256 internal constant alpha_challenge_16_loc = 0x49a0; - uint256 internal constant alpha_challenge_17_loc = 0x49c0; - uint256 internal constant alpha_challenge_18_loc = 0x49e0; - uint256 internal constant alpha_challenge_19_loc = 0x4a00; - uint256 internal constant alpha_challenge_20_loc = 0x4a20; - uint256 internal constant alpha_challenge_21_loc = 0x4a40; - uint256 internal constant alpha_challenge_22_loc = 0x4a60; - uint256 internal constant alpha_challenge_23_loc = 0x4a80; - uint256 internal constant alpha_challenge_24_loc = 0x4aa0; - uint256 internal constant gate_challenge_0_loc = 0x4ac0; - uint256 internal constant gate_challenge_1_loc = 0x4ae0; - uint256 internal constant gate_challenge_2_loc = 0x4b00; - uint256 internal constant gate_challenge_3_loc = 0x4b20; - uint256 internal constant gate_challenge_4_loc = 0x4b40; - uint256 internal constant gate_challenge_5_loc = 0x4b60; - uint256 internal constant gate_challenge_6_loc = 0x4b80; - uint256 internal constant gate_challenge_7_loc = 0x4ba0; - uint256 internal constant gate_challenge_8_loc = 0x4bc0; - uint256 internal constant gate_challenge_9_loc = 0x4be0; - uint256 internal constant gate_challenge_10_loc = 0x4c00; - uint256 internal constant gate_challenge_11_loc = 0x4c20; - uint256 internal constant gate_challenge_12_loc = 0x4c40; - uint256 internal constant gate_challenge_13_loc = 0x4c60; - uint256 internal constant gate_challenge_14_loc = 0x4c80; - uint256 internal constant gate_challenge_15_loc = 0x4ca0; - uint256 internal constant gate_challenge_16_loc = 0x4cc0; - uint256 internal constant gate_challenge_17_loc = 0x4ce0; - uint256 internal constant gate_challenge_18_loc = 0x4d00; - uint256 internal constant gate_challenge_19_loc = 0x4d20; - uint256 internal constant gate_challenge_20_loc = 0x4d40; - uint256 internal constant gate_challenge_21_loc = 0x4d60; - uint256 internal constant gate_challenge_22_loc = 0x4d80; - uint256 internal constant gate_challenge_23_loc = 0x4da0; - uint256 internal constant gate_challenge_24_loc = 0x4dc0; - uint256 internal constant gate_challenge_25_loc = 0x4de0; - uint256 internal constant gate_challenge_26_loc = 0x4e00; - uint256 internal constant gate_challenge_27_loc = 0x4e20; - uint256 internal constant sum_u_challenge_0_loc = 0x4e40; - uint256 internal constant sum_u_challenge_1_loc = 0x4e60; - uint256 internal constant sum_u_challenge_2_loc = 0x4e80; - uint256 internal constant sum_u_challenge_3_loc = 0x4ea0; - uint256 internal constant sum_u_challenge_4_loc = 0x4ec0; - uint256 internal constant sum_u_challenge_5_loc = 0x4ee0; - uint256 internal constant sum_u_challenge_6_loc = 0x4f00; - uint256 internal constant sum_u_challenge_7_loc = 0x4f20; - uint256 internal constant sum_u_challenge_8_loc = 0x4f40; - uint256 internal constant sum_u_challenge_9_loc = 0x4f60; - uint256 internal constant sum_u_challenge_10_loc = 0x4f80; - uint256 internal constant sum_u_challenge_11_loc = 0x4fa0; - uint256 internal constant sum_u_challenge_12_loc = 0x4fc0; - uint256 internal constant sum_u_challenge_13_loc = 0x4fe0; - uint256 internal constant sum_u_challenge_14_loc = 0x5000; - uint256 internal constant sum_u_challenge_15_loc = 0x5020; - uint256 internal constant sum_u_challenge_16_loc = 0x5040; - uint256 internal constant sum_u_challenge_17_loc = 0x5060; - uint256 internal constant sum_u_challenge_18_loc = 0x5080; - uint256 internal constant sum_u_challenge_19_loc = 0x50a0; - uint256 internal constant sum_u_challenge_20_loc = 0x50c0; - uint256 internal constant sum_u_challenge_21_loc = 0x50e0; - uint256 internal constant sum_u_challenge_22_loc = 0x5100; - uint256 internal constant sum_u_challenge_23_loc = 0x5120; - uint256 internal constant sum_u_challenge_24_loc = 0x5140; - uint256 internal constant sum_u_challenge_25_loc = 0x5160; - uint256 internal constant sum_u_challenge_26_loc = 0x5180; - uint256 internal constant sum_u_challenge_27_loc = 0x51a0; - - uint256 internal constant prev_challenge_loc = 0x51c0; - - uint256 internal constant PUBLIC_INPUTS_DELTA_NUMERATOR_LOC = 0x51e0; - uint256 internal constant PUBLIC_INPUTS_DELTA_DENOMINATOR_LOC = 0x5200; - - // The number of barycentric domain values is dependant on the highest degree relation - // Number of barycentric domain values is 8 - // We write slab memory addresses manually as i dont trust the compiler - uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATORS_LOC = 0x5220; - uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATORS_1_LOC = 0x5240; - uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATORS_2_LOC = 0x5260; - uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATORS_3_LOC = 0x5280; - uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATORS_4_LOC = 0x52a0; - uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATORS_5_LOC = 0x52c0; - uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATORS_6_LOC = 0x52e0; - uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATORS_7_LOC = 0x5300; - - // = BARYCENTRIC_LAGRANGE_DENOMINATORS_LOC + 8 * 0x20 - uint256 internal constant BARYCENTRIC_DOMAIN_LOC = 0x5320; - uint256 internal constant BARYCENTRIC_DOMAIN_1_LOC = 0x5340; - uint256 internal constant BARYCENTRIC_DOMAIN_2_LOC = 0x5360; - uint256 internal constant BARYCENTRIC_DOMAIN_3_LOC = 0x5380; - uint256 internal constant BARYCENTRIC_DOMAIN_4_LOC = 0x53a0; - uint256 internal constant BARYCENTRIC_DOMAIN_5_LOC = 0x53c0; - uint256 internal constant BARYCENTRIC_DOMAIN_6_LOC = 0x53e0; - uint256 internal constant BARYCENTRIC_DOMAIN_7_LOC = 0x5400; - - uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_LOC = 0x5420; - uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_1_LOC = 0x5440; - uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_2_LOC = 0x5460; - uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_3_LOC = 0x5480; - uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_4_LOC = 0x54a0; - uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_5_LOC = 0x54c0; - uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_6_LOC = 0x54e0; - uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_7_LOC = 0x5500; - - // How many are there -> 26 - uint256 internal constant SUBRELATION_EVAL_LOC = 0x5520; - uint256 internal constant SUBRELATION_EVAL_1_LOC = 0x5540; - uint256 internal constant SUBRELATION_EVAL_2_LOC = 0x5560; - uint256 internal constant SUBRELATION_EVAL_3_LOC = 0x5580; - uint256 internal constant SUBRELATION_EVAL_4_LOC = 0x55a0; - uint256 internal constant SUBRELATION_EVAL_5_LOC = 0x55c0; - uint256 internal constant SUBRELATION_EVAL_6_LOC = 0x55e0; - uint256 internal constant SUBRELATION_EVAL_7_LOC = 0x5600; - uint256 internal constant SUBRELATION_EVAL_8_LOC = 0x5620; - uint256 internal constant SUBRELATION_EVAL_9_LOC = 0x5640; - uint256 internal constant SUBRELATION_EVAL_10_LOC = 0x5660; - uint256 internal constant SUBRELATION_EVAL_11_LOC = 0x5680; - uint256 internal constant SUBRELATION_EVAL_12_LOC = 0x56a0; - uint256 internal constant SUBRELATION_EVAL_13_LOC = 0x56c0; - uint256 internal constant SUBRELATION_EVAL_14_LOC = 0x56e0; - uint256 internal constant SUBRELATION_EVAL_15_LOC = 0x5700; - uint256 internal constant SUBRELATION_EVAL_16_LOC = 0x5720; - uint256 internal constant SUBRELATION_EVAL_17_LOC = 0x5740; - uint256 internal constant SUBRELATION_EVAL_18_LOC = 0x5760; - uint256 internal constant SUBRELATION_EVAL_19_LOC = 0x5780; - uint256 internal constant SUBRELATION_EVAL_20_LOC = 0x57a0; - uint256 internal constant SUBRELATION_EVAL_21_LOC = 0x57c0; - uint256 internal constant SUBRELATION_EVAL_22_LOC = 0x57e0; - uint256 internal constant SUBRELATION_EVAL_23_LOC = 0x5800; - uint256 internal constant SUBRELATION_EVAL_24_LOC = 0x5820; - uint256 internal constant SUBRELATION_EVAL_25_LOC = 0x5840; - - uint256 internal constant POW_PARTIAL_EVALUATION_LOC = 0x5860; - uint256 internal constant FINAL_ROUND_TARGET_LOC = 0x5880; - - // Temporary storage for the auxiliary relation evaluations - uint256 internal constant AUX_NON_NATIVE_FIELD_IDENTITY = 0x58a0; - uint256 internal constant AUX_LIMB_ACCUMULATOR_IDENTITY = 0x58c0; - uint256 internal constant AUX_RAM_CONSISTENCY_CHECK_IDENTITY = 0x58e0; - uint256 internal constant AUX_ROM_CONSISTENCY_CHECK_IDENTITY = 0x5900; - uint256 internal constant AUX_MEMORY_CHECK_IDENTITY = 0x5920; - - uint256 internal constant NEXT_FREE_LOC = 0x5940; + // Shplemini +uint256 internal constant GEMINI_FOLD_UNIVARIATE_0_X0_LOC = 0x3740 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_0_X1_LOC = 0x3760 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_0_Y0_LOC = 0x3780 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_0_Y1_LOC = 0x37a0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_1_X0_LOC = 0x37c0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_1_X1_LOC = 0x37e0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_1_Y0_LOC = 0x3800 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_1_Y1_LOC = 0x3820 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_2_X0_LOC = 0x3840 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_2_X1_LOC = 0x3860 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_2_Y0_LOC = 0x3880 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_2_Y1_LOC = 0x38a0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_3_X0_LOC = 0x38c0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_3_X1_LOC = 0x38e0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_3_Y0_LOC = 0x3900 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_3_Y1_LOC = 0x3920 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_4_X0_LOC = 0x3940 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_4_X1_LOC = 0x3960 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_4_Y0_LOC = 0x3980 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_4_Y1_LOC = 0x39a0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_5_X0_LOC = 0x39c0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_5_X1_LOC = 0x39e0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_5_Y0_LOC = 0x3a00 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_5_Y1_LOC = 0x3a20 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_6_X0_LOC = 0x3a40 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_6_X1_LOC = 0x3a60 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_6_Y0_LOC = 0x3a80 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_6_Y1_LOC = 0x3aa0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_7_X0_LOC = 0x3ac0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_7_X1_LOC = 0x3ae0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_7_Y0_LOC = 0x3b00 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_7_Y1_LOC = 0x3b20 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_8_X0_LOC = 0x3b40 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_8_X1_LOC = 0x3b60 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_8_Y0_LOC = 0x3b80 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_8_Y1_LOC = 0x3ba0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_9_X0_LOC = 0x3bc0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_9_X1_LOC = 0x3be0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_9_Y0_LOC = 0x3c00 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_9_Y1_LOC = 0x3c20 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_10_X0_LOC = 0x3c40 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_10_X1_LOC = 0x3c60 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_10_Y0_LOC = 0x3c80 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_10_Y1_LOC = 0x3ca0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_11_X0_LOC = 0x3cc0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_11_X1_LOC = 0x3ce0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_11_Y0_LOC = 0x3d00 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_11_Y1_LOC = 0x3d20 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_12_X0_LOC = 0x3d40 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_12_X1_LOC = 0x3d60 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_12_Y0_LOC = 0x3d80 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_12_Y1_LOC = 0x3da0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_13_X0_LOC = 0x3dc0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_13_X1_LOC = 0x3de0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_13_Y0_LOC = 0x3e00 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_13_Y1_LOC = 0x3e20 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_14_X0_LOC = 0x3e40 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_14_X1_LOC = 0x3e60 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_14_Y0_LOC = 0x3e80 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_14_Y1_LOC = 0x3ea0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_15_X0_LOC = 0x3ec0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_15_X1_LOC = 0x3ee0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_15_Y0_LOC = 0x3f00 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_15_Y1_LOC = 0x3f20 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_16_X0_LOC = 0x3f40 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_16_X1_LOC = 0x3f60 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_16_Y0_LOC = 0x3f80 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_16_Y1_LOC = 0x3fa0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_17_X0_LOC = 0x3fc0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_17_X1_LOC = 0x3fe0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_17_Y0_LOC = 0x4000 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_17_Y1_LOC = 0x4020 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_18_X0_LOC = 0x4040 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_18_X1_LOC = 0x4060 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_18_Y0_LOC = 0x4080 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_18_Y1_LOC = 0x40a0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_19_X0_LOC = 0x40c0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_19_X1_LOC = 0x40e0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_19_Y0_LOC = 0x4100 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_19_Y1_LOC = 0x4120 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_20_X0_LOC = 0x4140 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_20_X1_LOC = 0x4160 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_20_Y0_LOC = 0x4180 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_20_Y1_LOC = 0x41a0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_21_X0_LOC = 0x41c0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_21_X1_LOC = 0x41e0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_21_Y0_LOC = 0x4200 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_21_Y1_LOC = 0x4220 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_22_X0_LOC = 0x4240 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_22_X1_LOC = 0x4260 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_22_Y0_LOC = 0x4280 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_22_Y1_LOC = 0x42a0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_23_X0_LOC = 0x42c0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_23_X1_LOC = 0x42e0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_23_Y0_LOC = 0x4300 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_23_Y1_LOC = 0x4320 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_24_X0_LOC = 0x4340 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_24_X1_LOC = 0x4360 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_24_Y0_LOC = 0x4380 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_24_Y1_LOC = 0x43a0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_25_X0_LOC = 0x43c0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_25_X1_LOC = 0x43e0 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_25_Y0_LOC = 0x4400 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_25_Y1_LOC = 0x4420 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_26_X0_LOC = 0x4440 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_26_X1_LOC = 0x4460 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_26_Y0_LOC = 0x4480 ; +uint256 internal constant GEMINI_FOLD_UNIVARIATE_26_Y1_LOC = 0x44a0 ; +uint256 internal constant GEMINI_A_EVAL_0 = 0x44c0 ; +uint256 internal constant GEMINI_A_EVAL_1 = 0x44e0 ; +uint256 internal constant GEMINI_A_EVAL_2 = 0x4500 ; +uint256 internal constant GEMINI_A_EVAL_3 = 0x4520 ; +uint256 internal constant GEMINI_A_EVAL_4 = 0x4540 ; +uint256 internal constant GEMINI_A_EVAL_5 = 0x4560 ; +uint256 internal constant GEMINI_A_EVAL_6 = 0x4580 ; +uint256 internal constant GEMINI_A_EVAL_7 = 0x45a0 ; +uint256 internal constant GEMINI_A_EVAL_8 = 0x45c0 ; +uint256 internal constant GEMINI_A_EVAL_9 = 0x45e0 ; +uint256 internal constant GEMINI_A_EVAL_10 = 0x4600 ; +uint256 internal constant GEMINI_A_EVAL_11 = 0x4620 ; +uint256 internal constant GEMINI_A_EVAL_12 = 0x4640 ; +uint256 internal constant GEMINI_A_EVAL_13 = 0x4660 ; +uint256 internal constant GEMINI_A_EVAL_14 = 0x4680 ; +uint256 internal constant GEMINI_A_EVAL_15 = 0x46a0 ; +uint256 internal constant GEMINI_A_EVAL_16 = 0x46c0 ; +uint256 internal constant GEMINI_A_EVAL_17 = 0x46e0 ; +uint256 internal constant GEMINI_A_EVAL_18 = 0x4700 ; +uint256 internal constant GEMINI_A_EVAL_19 = 0x4720 ; +uint256 internal constant GEMINI_A_EVAL_20 = 0x4740 ; +uint256 internal constant GEMINI_A_EVAL_21 = 0x4760 ; +uint256 internal constant GEMINI_A_EVAL_22 = 0x4780 ; +uint256 internal constant GEMINI_A_EVAL_23 = 0x47a0 ; +uint256 internal constant GEMINI_A_EVAL_24 = 0x47c0 ; +uint256 internal constant GEMINI_A_EVAL_25 = 0x47e0 ; +uint256 internal constant GEMINI_A_EVAL_26 = 0x4800 ; +uint256 internal constant GEMINI_A_EVAL_27 = 0x4820 ; +uint256 internal constant SHPLONK_Q_X0_LOC = 0x4840 ; +uint256 internal constant SHPLONK_Q_X1_LOC = 0x4860 ; +uint256 internal constant SHPLONK_Q_Y0_LOC = 0x4880 ; +uint256 internal constant SHPLONK_Q_Y1_LOC = 0x48a0 ; +uint256 internal constant KZG_QUOTIENT_X0_LOC = 0x48c0 ; +uint256 internal constant KZG_QUOTIENT_X1_LOC = 0x48e0 ; +uint256 internal constant KZG_QUOTIENT_Y0_LOC = 0x4900 ; +uint256 internal constant KZG_QUOTIENT_Y1_LOC = 0x4920 ; + +// Challenges +uint256 internal constant ETA_CHALLENGE = 0x4940 ; +uint256 internal constant ETA_TWO_CHALLENGE = 0x4960 ; +uint256 internal constant ETA_THREE_CHALLENGE = 0x4980 ; +uint256 internal constant BETA_CHALLENGE = 0x49a0 ; +uint256 internal constant GAMMA_CHALLENGE = 0x49c0 ; +uint256 internal constant RHO_CHALLENGE = 0x49e0 ; +uint256 internal constant GEMINI_R_CHALLENGE = 0x4a00 ; +uint256 internal constant SHPLONK_NU_CHALLENGE = 0x4a20 ; +uint256 internal constant SHPLONK_Z_CHALLENGE = 0x4a40 ; +uint256 internal constant PUBLIC_INPUTS_DELTA_NUMERATOR = 0x4a60 ; +uint256 internal constant PUBLIC_INPUTS_DELTA_DENOMINATOR = 0x4a80 ; +uint256 internal constant ALPHA_CHALLENGE_0 = 0x4aa0 ; +uint256 internal constant ALPHA_CHALLENGE_1 = 0x4ac0 ; +uint256 internal constant ALPHA_CHALLENGE_2 = 0x4ae0 ; +uint256 internal constant ALPHA_CHALLENGE_3 = 0x4b00 ; +uint256 internal constant ALPHA_CHALLENGE_4 = 0x4b20 ; +uint256 internal constant ALPHA_CHALLENGE_5 = 0x4b40 ; +uint256 internal constant ALPHA_CHALLENGE_6 = 0x4b60 ; +uint256 internal constant ALPHA_CHALLENGE_7 = 0x4b80 ; +uint256 internal constant ALPHA_CHALLENGE_8 = 0x4ba0 ; +uint256 internal constant ALPHA_CHALLENGE_9 = 0x4bc0 ; +uint256 internal constant ALPHA_CHALLENGE_10 = 0x4be0 ; +uint256 internal constant ALPHA_CHALLENGE_11 = 0x4c00 ; +uint256 internal constant ALPHA_CHALLENGE_12 = 0x4c20 ; +uint256 internal constant ALPHA_CHALLENGE_13 = 0x4c40 ; +uint256 internal constant ALPHA_CHALLENGE_14 = 0x4c60 ; +uint256 internal constant ALPHA_CHALLENGE_15 = 0x4c80 ; +uint256 internal constant ALPHA_CHALLENGE_16 = 0x4ca0 ; +uint256 internal constant ALPHA_CHALLENGE_17 = 0x4cc0 ; +uint256 internal constant ALPHA_CHALLENGE_18 = 0x4ce0 ; +uint256 internal constant ALPHA_CHALLENGE_19 = 0x4d00 ; +uint256 internal constant ALPHA_CHALLENGE_20 = 0x4d20 ; +uint256 internal constant ALPHA_CHALLENGE_21 = 0x4d40 ; +uint256 internal constant ALPHA_CHALLENGE_22 = 0x4d60 ; +uint256 internal constant ALPHA_CHALLENGE_23 = 0x4d80 ; +uint256 internal constant ALPHA_CHALLENGE_24 = 0x4da0 ; +uint256 internal constant GATE_CHALLENGE_0 = 0x4dc0 ; +uint256 internal constant GATE_CHALLENGE_1 = 0x4de0 ; +uint256 internal constant GATE_CHALLENGE_2 = 0x4e00 ; +uint256 internal constant GATE_CHALLENGE_3 = 0x4e20 ; +uint256 internal constant GATE_CHALLENGE_4 = 0x4e40 ; +uint256 internal constant GATE_CHALLENGE_5 = 0x4e60 ; +uint256 internal constant GATE_CHALLENGE_6 = 0x4e80 ; +uint256 internal constant GATE_CHALLENGE_7 = 0x4ea0 ; +uint256 internal constant GATE_CHALLENGE_8 = 0x4ec0 ; +uint256 internal constant GATE_CHALLENGE_9 = 0x4ee0 ; +uint256 internal constant GATE_CHALLENGE_10 = 0x4f00 ; +uint256 internal constant GATE_CHALLENGE_11 = 0x4f20 ; +uint256 internal constant GATE_CHALLENGE_12 = 0x4f40 ; +uint256 internal constant GATE_CHALLENGE_13 = 0x4f60 ; +uint256 internal constant GATE_CHALLENGE_14 = 0x4f80 ; +uint256 internal constant GATE_CHALLENGE_15 = 0x4fa0 ; +uint256 internal constant GATE_CHALLENGE_16 = 0x4fc0 ; +uint256 internal constant GATE_CHALLENGE_17 = 0x4fe0 ; +uint256 internal constant GATE_CHALLENGE_18 = 0x5000 ; +uint256 internal constant GATE_CHALLENGE_19 = 0x5020 ; +uint256 internal constant GATE_CHALLENGE_20 = 0x5040 ; +uint256 internal constant GATE_CHALLENGE_21 = 0x5060 ; +uint256 internal constant GATE_CHALLENGE_22 = 0x5080 ; +uint256 internal constant GATE_CHALLENGE_23 = 0x50a0 ; +uint256 internal constant GATE_CHALLENGE_24 = 0x50c0 ; +uint256 internal constant GATE_CHALLENGE_25 = 0x50e0 ; +uint256 internal constant GATE_CHALLENGE_26 = 0x5100 ; +uint256 internal constant GATE_CHALLENGE_27 = 0x5120 ; +uint256 internal constant SUM_U_CHALLENGE_0 = 0x5140 ; +uint256 internal constant SUM_U_CHALLENGE_1 = 0x5160 ; +uint256 internal constant SUM_U_CHALLENGE_2 = 0x5180 ; +uint256 internal constant SUM_U_CHALLENGE_3 = 0x51a0 ; +uint256 internal constant SUM_U_CHALLENGE_4 = 0x51c0 ; +uint256 internal constant SUM_U_CHALLENGE_5 = 0x51e0 ; +uint256 internal constant SUM_U_CHALLENGE_6 = 0x5200 ; +uint256 internal constant SUM_U_CHALLENGE_7 = 0x5220 ; +uint256 internal constant SUM_U_CHALLENGE_8 = 0x5240 ; +uint256 internal constant SUM_U_CHALLENGE_9 = 0x5260 ; +uint256 internal constant SUM_U_CHALLENGE_10 = 0x5280 ; +uint256 internal constant SUM_U_CHALLENGE_11 = 0x52a0 ; +uint256 internal constant SUM_U_CHALLENGE_12 = 0x52c0 ; +uint256 internal constant SUM_U_CHALLENGE_13 = 0x52e0 ; +uint256 internal constant SUM_U_CHALLENGE_14 = 0x5300 ; +uint256 internal constant SUM_U_CHALLENGE_15 = 0x5320 ; +uint256 internal constant SUM_U_CHALLENGE_16 = 0x5340 ; +uint256 internal constant SUM_U_CHALLENGE_17 = 0x5360 ; +uint256 internal constant SUM_U_CHALLENGE_18 = 0x5380 ; +uint256 internal constant SUM_U_CHALLENGE_19 = 0x53a0 ; +uint256 internal constant SUM_U_CHALLENGE_20 = 0x53c0 ; +uint256 internal constant SUM_U_CHALLENGE_21 = 0x53e0 ; +uint256 internal constant SUM_U_CHALLENGE_22 = 0x5400 ; +uint256 internal constant SUM_U_CHALLENGE_23 = 0x5420 ; +uint256 internal constant SUM_U_CHALLENGE_24 = 0x5440 ; +uint256 internal constant SUM_U_CHALLENGE_25 = 0x5460 ; +uint256 internal constant SUM_U_CHALLENGE_26 = 0x5480 ; +uint256 internal constant SUM_U_CHALLENGE_27 = 0x54a0 ; + +// Barycentric domain +uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_0_LOC = 0x54c0 ; +uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_1_LOC = 0x54e0 ; +uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_2_LOC = 0x5500 ; +uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_3_LOC = 0x5520 ; +uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_4_LOC = 0x5540 ; +uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_5_LOC = 0x5560 ; +uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_6_LOC = 0x5580 ; +uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_7_LOC = 0x55a0 ; +uint256 internal constant BARYCENTRIC_DOMAIN_0_LOC = 0x55c0 ; +uint256 internal constant BARYCENTRIC_DOMAIN_1_LOC = 0x55e0 ; +uint256 internal constant BARYCENTRIC_DOMAIN_2_LOC = 0x5600 ; +uint256 internal constant BARYCENTRIC_DOMAIN_3_LOC = 0x5620 ; +uint256 internal constant BARYCENTRIC_DOMAIN_4_LOC = 0x5640 ; +uint256 internal constant BARYCENTRIC_DOMAIN_5_LOC = 0x5660 ; +uint256 internal constant BARYCENTRIC_DOMAIN_6_LOC = 0x5680 ; +uint256 internal constant BARYCENTRIC_DOMAIN_7_LOC = 0x56a0 ; +uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_0_LOC = 0x56c0 ; +uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_1_LOC = 0x56e0 ; +uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_2_LOC = 0x5700 ; +uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_3_LOC = 0x5720 ; +uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_4_LOC = 0x5740 ; +uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_5_LOC = 0x5760 ; +uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_6_LOC = 0x5780 ; +uint256 internal constant BARYCENTRIC_DENOMINATOR_INVERSES_7_LOC = 0x57a0 ; + +// Subrelation evaluations +uint256 internal constant SUBRELATION_EVAL_0_LOC = 0x57c0 ; +uint256 internal constant SUBRELATION_EVAL_1_LOC = 0x57e0 ; +uint256 internal constant SUBRELATION_EVAL_2_LOC = 0x5800 ; +uint256 internal constant SUBRELATION_EVAL_3_LOC = 0x5820 ; +uint256 internal constant SUBRELATION_EVAL_4_LOC = 0x5840 ; +uint256 internal constant SUBRELATION_EVAL_5_LOC = 0x5860 ; +uint256 internal constant SUBRELATION_EVAL_6_LOC = 0x5880 ; +uint256 internal constant SUBRELATION_EVAL_7_LOC = 0x58a0 ; +uint256 internal constant SUBRELATION_EVAL_8_LOC = 0x58c0 ; +uint256 internal constant SUBRELATION_EVAL_9_LOC = 0x58e0 ; +uint256 internal constant SUBRELATION_EVAL_10_LOC = 0x5900 ; +uint256 internal constant SUBRELATION_EVAL_11_LOC = 0x5920 ; +uint256 internal constant SUBRELATION_EVAL_12_LOC = 0x5940 ; +uint256 internal constant SUBRELATION_EVAL_13_LOC = 0x5960 ; +uint256 internal constant SUBRELATION_EVAL_14_LOC = 0x5980 ; +uint256 internal constant SUBRELATION_EVAL_15_LOC = 0x59a0 ; +uint256 internal constant SUBRELATION_EVAL_16_LOC = 0x59c0 ; +uint256 internal constant SUBRELATION_EVAL_17_LOC = 0x59e0 ; +uint256 internal constant SUBRELATION_EVAL_18_LOC = 0x5a00 ; +uint256 internal constant SUBRELATION_EVAL_19_LOC = 0x5a20 ; +uint256 internal constant SUBRELATION_EVAL_20_LOC = 0x5a40 ; +uint256 internal constant SUBRELATION_EVAL_21_LOC = 0x5a60 ; +uint256 internal constant SUBRELATION_EVAL_22_LOC = 0x5a80 ; +uint256 internal constant SUBRELATION_EVAL_23_LOC = 0x5aa0 ; +uint256 internal constant SUBRELATION_EVAL_24_LOC = 0x5ac0 ; +uint256 internal constant SUBRELATION_EVAL_25_LOC = 0x5ae0 ; + +// Subrelation intermediates +uint256 internal constant FINAL_ROUND_TARGET_LOC = 0x5b00 ; +uint256 internal constant POW_PARTIAL_EVALUATION_LOC = 0x5b20 ; +uint256 internal constant AUX_NON_NATIVE_FIELD_IDENTITY = 0x5b40 ; +uint256 internal constant AUX_LIMB_ACCUMULATOR_IDENTITY = 0x5b60 ; +uint256 internal constant AUX_RAM_CONSISTENCY_CHECK_IDENTITY = 0x5b80 ; +uint256 internal constant AUX_ROM_CONSISTENCY_CHECK_IDENTITY = 0x5ba0 ; +uint256 internal constant AUX_MEMORY_CHECK_IDENTITY = 0x5bc0 ; + + + // TODO(md): shplemini regions can be reused for the reserved sumcheck regions + // 28 powers of evaluation challenge + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_0_LOC = 0x5be0; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_1_LOC = 0x5c00; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_2_LOC = 0x5c20; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_3_LOC = 0x5c40; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_4_LOC = 0x5c60; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_5_LOC = 0x5c80; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_6_LOC = 0x5ca0; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_7_LOC = 0x5cc0; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_8_LOC = 0x5ce0; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_9_LOC = 0x5d00; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_10_LOC = 0x5d20; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_11_LOC = 0x5d40; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_12_LOC = 0x5d60; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_13_LOC = 0x5d80; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_14_LOC = 0x5da0; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_15_LOC = 0x5dc0; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_16_LOC = 0x5de0; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_17_LOC = 0x5e00; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_18_LOC = 0x5e20; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_19_LOC = 0x5e40; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_20_LOC = 0x5e60; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_21_LOC = 0x5e80; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_22_LOC = 0x5ea0; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_23_LOC = 0x5ec0; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_24_LOC = 0x5ee0; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_25_LOC = 0x5f00; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_26_LOC = 0x5f20; + uint256 internal constant POWERS_OF_EVALUATION_CHALLENGE_27_LOC = 0x5f40; + + // 29 Inverted Gemini Denominators + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_0_LOC = 0x5f60; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_1_LOC = 0x5f80; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_2_LOC = 0x5fa0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_3_LOC = 0x5fc0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_4_LOC = 0x5fe0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_5_LOC = 0x6000; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_6_LOC = 0x6020; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_7_LOC = 0x6040; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_8_LOC = 0x6060; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_9_LOC = 0x6080; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_10_LOC = 0x60a0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_11_LOC = 0x60c0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_12_LOC = 0x60e0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_13_LOC = 0x6100; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_14_LOC = 0x6120; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_15_LOC = 0x6140; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_16_LOC = 0x6160; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_17_LOC = 0x6180; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_18_LOC = 0x61a0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_19_LOC = 0x61c0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_20_LOC = 0x61e0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_21_LOC = 0x6200; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_22_LOC = 0x6220; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_23_LOC = 0x6240; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_24_LOC = 0x6260; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_25_LOC = 0x6280; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_26_LOC = 0x62a0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_27_LOC = 0x62c0; + uint256 internal constant INVERTED_GEMINI_DENOMINATOR_28_LOC = 0x62e0; + + // TODO: memory slots can be used and this will be deleted in time + // The batch accumulator stores intermediate values when calculating the + // Inverted Gemini Denominator + // For the given circuit, this will require LOG_N + 1 iterations - we store the intermediate + // accumulators in montgomery batch inversion up until this LOG_N. So there are LOG_N + 1 + // intermediate values to store + // Note: not all LOG_N + 1 values are stored in memory as some will live on the stack + // + // Note: We have left enough scratch space that we could possibly use that instead for + // storing these values + uint256 internal constant BATCH_ACCUMULATOR_0_LOC = 0x6300; + uint256 internal constant BATCH_ACCUMULATOR_1_LOC = 0x6320; + uint256 internal constant BATCH_ACCUMULATOR_2_LOC = 0x6340; + uint256 internal constant BATCH_ACCUMULATOR_3_LOC = 0x6360; + uint256 internal constant BATCH_ACCUMULATOR_4_LOC = 0x6380; + uint256 internal constant BATCH_ACCUMULATOR_5_LOC = 0x63a0; + uint256 internal constant BATCH_ACCUMULATOR_6_LOC = 0x63c0; + uint256 internal constant BATCH_ACCUMULATOR_7_LOC = 0x63e0; + uint256 internal constant BATCH_ACCUMULATOR_8_LOC = 0x6400; + + + // WORKTODO: We should NOT need these values, we can instead reuse the sumcheck evaluations memory regions + // SCALARS FOR SHPLONK BATCHING + // + // TODO: write a more thorough explaination of what these are for and how they are used + // NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2 = 44 + 28 + 2 = 74 + uint256 internal constant BATCH_SCALAR_0_LOC = 0x6420 ; + uint256 internal constant BATCH_SCALAR_1_LOC = 0x6440 ; + uint256 internal constant BATCH_SCALAR_2_LOC = 0x6460 ; + uint256 internal constant BATCH_SCALAR_3_LOC = 0x6480 ; + uint256 internal constant BATCH_SCALAR_4_LOC = 0x64a0 ; + uint256 internal constant BATCH_SCALAR_5_LOC = 0x64c0 ; + uint256 internal constant BATCH_SCALAR_6_LOC = 0x64e0 ; + uint256 internal constant BATCH_SCALAR_7_LOC = 0x6500 ; + uint256 internal constant BATCH_SCALAR_8_LOC = 0x6520 ; + uint256 internal constant BATCH_SCALAR_9_LOC = 0x6540 ; + uint256 internal constant BATCH_SCALAR_10_LOC = 0x6560 ; + uint256 internal constant BATCH_SCALAR_11_LOC = 0x6580 ; + uint256 internal constant BATCH_SCALAR_12_LOC = 0x65a0 ; + uint256 internal constant BATCH_SCALAR_13_LOC = 0x65c0 ; + uint256 internal constant BATCH_SCALAR_14_LOC = 0x65e0 ; + uint256 internal constant BATCH_SCALAR_15_LOC = 0x6600 ; + uint256 internal constant BATCH_SCALAR_16_LOC = 0x6620 ; + uint256 internal constant BATCH_SCALAR_17_LOC = 0x6640 ; + uint256 internal constant BATCH_SCALAR_18_LOC = 0x6660 ; + uint256 internal constant BATCH_SCALAR_19_LOC = 0x6680 ; + uint256 internal constant BATCH_SCALAR_20_LOC = 0x66a0 ; + uint256 internal constant BATCH_SCALAR_21_LOC = 0x66c0 ; + uint256 internal constant BATCH_SCALAR_22_LOC = 0x66e0 ; + uint256 internal constant BATCH_SCALAR_23_LOC = 0x6700 ; + uint256 internal constant BATCH_SCALAR_24_LOC = 0x6720 ; + uint256 internal constant BATCH_SCALAR_25_LOC = 0x6740 ; + uint256 internal constant BATCH_SCALAR_26_LOC = 0x6760 ; + uint256 internal constant BATCH_SCALAR_27_LOC = 0x6780 ; + uint256 internal constant BATCH_SCALAR_28_LOC = 0x67a0 ; + uint256 internal constant BATCH_SCALAR_29_LOC = 0x67c0 ; + uint256 internal constant BATCH_SCALAR_30_LOC = 0x67e0 ; + uint256 internal constant BATCH_SCALAR_31_LOC = 0x6800 ; + uint256 internal constant BATCH_SCALAR_32_LOC = 0x6820 ; + uint256 internal constant BATCH_SCALAR_33_LOC = 0x6840 ; + uint256 internal constant BATCH_SCALAR_34_LOC = 0x6860 ; + uint256 internal constant BATCH_SCALAR_35_LOC = 0x6880 ; + uint256 internal constant BATCH_SCALAR_36_LOC = 0x68a0 ; + uint256 internal constant BATCH_SCALAR_37_LOC = 0x68c0 ; + uint256 internal constant BATCH_SCALAR_38_LOC = 0x68e0 ; + uint256 internal constant BATCH_SCALAR_39_LOC = 0x6900 ; + uint256 internal constant BATCH_SCALAR_40_LOC = 0x6920 ; + uint256 internal constant BATCH_SCALAR_41_LOC = 0x6940 ; + uint256 internal constant BATCH_SCALAR_42_LOC = 0x6960 ; + uint256 internal constant BATCH_SCALAR_43_LOC = 0x6980 ; + uint256 internal constant BATCH_SCALAR_44_LOC = 0x69a0 ; + uint256 internal constant BATCH_SCALAR_45_LOC = 0x69c0 ; + uint256 internal constant BATCH_SCALAR_46_LOC = 0x69e0 ; + uint256 internal constant BATCH_SCALAR_47_LOC = 0x6a00 ; + uint256 internal constant BATCH_SCALAR_48_LOC = 0x6a20 ; + uint256 internal constant BATCH_SCALAR_49_LOC = 0x6a40 ; + uint256 internal constant BATCH_SCALAR_50_LOC = 0x6a60 ; + uint256 internal constant BATCH_SCALAR_51_LOC = 0x6a80 ; + uint256 internal constant BATCH_SCALAR_52_LOC = 0x6aa0 ; + uint256 internal constant BATCH_SCALAR_53_LOC = 0x6ac0 ; + uint256 internal constant BATCH_SCALAR_54_LOC = 0x6ae0 ; + uint256 internal constant BATCH_SCALAR_55_LOC = 0x6b00 ; + uint256 internal constant BATCH_SCALAR_56_LOC = 0x6b20 ; + uint256 internal constant BATCH_SCALAR_57_LOC = 0x6b40 ; + uint256 internal constant BATCH_SCALAR_58_LOC = 0x6b60 ; + uint256 internal constant BATCH_SCALAR_59_LOC = 0x6b80 ; + uint256 internal constant BATCH_SCALAR_60_LOC = 0x6ba0 ; + uint256 internal constant BATCH_SCALAR_61_LOC = 0x6bc0 ; + uint256 internal constant BATCH_SCALAR_62_LOC = 0x6be0 ; + uint256 internal constant BATCH_SCALAR_63_LOC = 0x6c00 ; + uint256 internal constant BATCH_SCALAR_64_LOC = 0x6c20 ; + uint256 internal constant BATCH_SCALAR_65_LOC = 0x6c40 ; + uint256 internal constant BATCH_SCALAR_66_LOC = 0x6c60 ; + uint256 internal constant BATCH_SCALAR_67_LOC = 0x6c80 ; + uint256 internal constant BATCH_SCALAR_68_LOC = 0x6ca0 ; + uint256 internal constant BATCH_SCALAR_69_LOC = 0x6cc0 ; + uint256 internal constant BATCH_SCALAR_70_LOC = 0x6ce0 ; + uint256 internal constant BATCH_SCALAR_71_LOC = 0x6d00 ; + uint256 internal constant BATCH_SCALAR_72_LOC = 0x6d20 ; + uint256 internal constant BATCH_SCALAR_73_LOC = 0x6d40 ; + + // TODO: PROSE + // LOG_N inverted values, used in calculating inversions + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_0_LOC = 0x6d60; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_1_LOC = 0x6d80; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_2_LOC = 0x6da0; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_3_LOC = 0x6dc0; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_4_LOC = 0x6de0; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_5_LOC = 0x6e00; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_6_LOC = 0x6e20; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_7_LOC = 0x6e40; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_8_LOC = 0x6e60; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_9_LOC = 0x6e80; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_10_LOC = 0x6ea0; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_11_LOC = 0x6ec0; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_12_LOC = 0x6ee0; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_13_LOC = 0x6f00; + uint256 internal constant BATCHED_EVALUATION_ACCUMULATOR_INVERSION_14_LOC = 0x6f20; + + // WORKTODO: could another place be reused here? + uint256 internal constant BATCHED_EVALUATION_LOC = 0x6f40; + uint256 internal constant CONSTANT_TERM_ACCUMULATOR_LOC = 0x6f60; // Aliases // Aliases for wire values (Elliptic curve gadget) @@ -709,90 +920,120 @@ contract BlakeOptHonkVerifier is IVerifier { uint256 internal constant POS_INTENAL_MATRIX_D_2 = 0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15; uint256 internal constant POS_INTENAL_MATRIX_D_3 = 0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b; + // Constants inspecting proof components + uint256 internal constant NUMBER_OF_UNSHIFTED_ENTITIES = 35; + uint256 internal constant NUMBER_OF_SHIFTED_ENTITIES = 9; + uint256 internal constant TOTAL_NUMBER_OF_ENTITIES = 44; + + // Constants for performing batch multiplication + uint256 internal constant ACCUMULATOR = 0x00; + uint256 internal constant ACCUMULATOR_2 = 0x40; + uint256 internal constant G1_LOCATION = 0x60; + uint256 internal constant SCALAR_LOCATION = 0xa0; + + + // Error selectors + uint256 internal constant PUBLIC_INPUT_TOO_LARGE_SELECTOR = 0x01; + uint256 internal constant SUMCHECK_FAILED_SELECTOR = 0x02; + uint256 internal constant PAIRING_FAILED_SELECTOR = 0x03; + uint256 internal constant BATCH_ACCUMULATION_FAILED_SELECTOR = 0x04; + uint256 internal constant MODEXP_FAILED_SELECTOR = 0x05; + uint256 internal constant PROOF_POINT_NOT_ON_CURVE_SELECTOR = 0x06; + constructor() { // TODO: verify the points are on the curve in the constructor } - // Inline the verification key code here for the meantime - // will be in it's own library - // Note the split committments here will make a difference to costs in the end - function loadVk() internal view { - assembly { - // TODO: in the vk swap the location of l and m - mstore(q_l_x_loc, 0x2e5f133c25f7e05bd6660196c892121f7fa686cb9a8717a5deea6cd0881e618e) - mstore(q_l_y_loc, 0x1189bba9eeea96ba8935052434f4b0a60b0a481e3464dd81dfcd89e23def001b) - mstore(q_r_x_loc, 0x2a93ffb34002da94f5b156ba5a212ac3616c848bd9c44c9821bbdd64cfd848af) - mstore(q_r_y_loc, 0x015699dcc0b28766d45f5ddce8258393e84c40619d26034e76f778460a1e4d89) - mstore(q_o_x_loc, 0x2057928e8c5eb539c32c3025007b7be1e1663c358f59540c6f949794c274f886) - mstore(q_o_y_loc, 0x12bf0b15c3aa92792330f58b04512714c4a902e537fe87cc438293e1805eaabf) - mstore(q_4_x_loc, 0x304f47a08d4687afa0e2502a9782c32c458bf873ef50c169b732a367e567aaf3) - mstore(q_4_y_loc, 0x0bb37044594e7de200408a4db6bc46adf7790b06f17dce6f38b7deed480aa9f0) - mstore(q_m_x_loc, 0x0aea5b04332ad8781411f7edde21266857ffe11e93af334b14a2b948429afaa4) - mstore(q_m_y_loc, 0x2bd2e3884d486b387122effa12e8698daef82e9b99d7d25b7d5df91a9d738495) - mstore(q_c_x_loc, 0x0e3b418ea1924b4514d5009cd983b5a8074fa95cd1fb200f019fdebe944e4225) - mstore(q_c_y_loc, 0x1e6ef5bde7a9727f1c1d07c91461ae1b40524650b35fdd92ac7a129f263b1beb) - mstore(q_arith_x_loc, 0x096841bfa8ec2295a5af5bf69ec539c31a05b221c84ed1d24c702e31ce1cbc95) - mstore(q_arith_y_loc, 0x10b14cca7e9ff05fcf1e3084f4fc9ab098cf379864b2e2e2e0d33fc5df9d9a50) - mstore(q_delta_range_x_loc, 0x2d27fd1a30a0ab04a05144c27ac41187d5cf89a6022e47b263d1ccb93b3cbea5) - mstore(q_delta_range_y_loc, 0x238eb233e9aebc81285a2647f2598bab00a4367da47b12c2b0476afc2d94ab1d) - mstore(q_elliptic_x_loc, 0x1c6fc8e14453adf64e6d9643ef9f1fb55e3a307ac1ec84f86cd736fc866e05ab) - mstore(q_elliptic_y_loc, 0x1bf8619b1704b99ab8820ed94dd760da2945e8e1c771c0bdeadbe40aa5700cdd) - mstore(q_aux_x_loc, 0x1c6fc8e14453adf64e6d9643ef9f1fb55e3a307ac1ec84f86cd736fc866e05ab) - mstore(q_aux_y_loc, 0x1bf8619b1704b99ab8820ed94dd760da2945e8e1c771c0bdeadbe40aa5700cdd) - mstore(q_lookup_x_loc, 0x1375bbfbf5ed31b38460f46a43ac14e2cda93a3bc5cfd6e8a93cca356694a346) - mstore(q_lookup_y_loc, 0x204c5173892c19a97a04b5f8419898063df5136489809ddb9f7eabb58d6858ab) - mstore(q_poseidon_2_external_x_loc, 0x1fa8529236d7eacdab8dcd8169af30d334be103357577353e9ef08dfda841785) - mstore(q_poseidon_2_external_y_loc, 0x055251b013746385e921b4620e55ef4f08b4d8afc4dbca7e6c3ca0f1b52c5a2b) - mstore(q_poseidon_2_internal_x_loc, 0x1515283648ab8622ac6447f1fcf201a598d8df325279bfac9a6564924df97ee5) - mstore(q_poseidon_2_internal_y_loc, 0x0335bb595984ad38686009bca08f5f420e3b4cf888fad5af4a99eca08190a315) - mstore(sigma_1_x_loc, 0x26cec5ff3eb1b803c52fa1fefaac7a2be5cd13c1a1cc20bb9f22049c7f8597d2) - mstore(sigma_1_y_loc, 0x07e80e74eb0e06d7c0c9a3fbbdea4e86e5934faa8142625f175320778bcba65f) - mstore(sigma_2_x_loc, 0x140b2faaf30cb5fc528621f4a395943e7fab8198dc734ac13253dd249682dd2a) - mstore(sigma_2_y_loc, 0x12709c4a13428f4704d284c90a81cc83280680185ae6298187e86debcd3e00f7) - mstore(sigma_3_x_loc, 0x0aca5621e9f49279969497b3da0eb8a74c68c3513f4cf98e8b1d6f88567557a8) - mstore(sigma_3_y_loc, 0x2664811311f75057a16267bc0479eaeea2424156417cc4d3f8bd286fac9aa5d2) - mstore(sigma_4_x_loc, 0x04417c606a41393e73113ec3f834883dbeb302889199b888c0f5ea58a008ff98) - mstore(sigma_4_y_loc, 0x0865670de7962d29b6a9012f28ea52113c4e2b55d7de44e829edec87dba1d5c2) - // TODO: in the proog pointers above swap id and table - to line up with how they actually should be - mstore(table_1_x_loc, 0x1ec1b607634e31421b5047dc99d7674d6505fed978df0f42a3504f9771a8a7fa) - mstore(table_1_y_loc, 0x1da802c6dc2fe6cffc6f9ae983080c66690ceee40c181b4d51fdba6c5c360297) - mstore(table_2_x_loc, 0x1e38a0a482b7174f429a3bef25fb0a7656abc88cfd215b8e8404132601620784) - mstore(table_2_y_loc, 0x2e9ea07a995fa6d589e37fba2715f3f1fa338652ddf84d4e2e4f33dccadb9156) - mstore(table_3_x_loc, 0x211a0833bb3c6f9ae6c94519b6878ed6157c4a080df786a053d9a19796b9a7f8) - mstore(table_3_y_loc, 0x211a0833bb3c6f9ae6c94519b6878ed6157c4a080df786a053d9a19796b9a7f8) - mstore(table_4_x_loc, 0x281a984aef14716cd5d8fc2759eb8ea2464909b5c57d97b6bc50e4dad74d92d3) - mstore(table_4_y_loc, 0x169160e1505685aabd5bd60e994bac45162c6868235cc4252c8b87d0f12603fd) - mstore(id_1_x_loc, 0x01c082a85908fea4c69c4e51436fba7d965e1d88e485da16e35d8f4e8af3b8bd) - mstore(id_1_y_loc, 0x11b0ada021468b059aa6c27f4d4950ef65b98d4d8808ae21718bd8b90f9bb365) - mstore(id_2_x_loc, 0x0b8667619755bd09c7970defeae2c920df2b17b41608303ae1d7393615dd04e4) - mstore(id_2_y_loc, 0x1c5419cd435c5516ac566a9d1dfecdb4e10190c63f2dbd8a1932785caf022e2c) - mstore(id_3_x_loc, 0x110aee72793c4b4ede92c1375f058b4170fcf01bf18f8f1ee934f7ae0fa26da5) - mstore(id_3_y_loc, 0x15c4f6a01ff04ef6b5225c896dfb7060a7a2c320395bda410e756d6b507b7eb8) - mstore(id_4_x_loc, 0x2472aba130e7ed2aefad128109415ec2bdeb56e81e3cbeacc93e00c95f203579) - mstore(id_4_y_loc, 0x0c867d0f8e2f9c861574383b89020980358d898497f80c198a6c17c2f4daf9a4) - mstore(lagrange_first_x_loc, 0x0000000000000000000000000000000000000000000000000000000000000001) - mstore(lagrange_first_y_loc, 0x0000000000000000000000000000000000000000000000000000000000000002) - mstore(lagrange_last_x_loc, 0x13b825e996cc8d600f363dca4481a54d6dd3da85900cd9f0a61fa02600851998) - mstore(lagrange_last_y_loc, 0x151cb86205f2dc38a5651840c1a4b4928f3f3c98f77c2abd08336562986dc404) - } - } uint256 internal constant LOWER_128_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - function verify(bytes calldata proof, bytes32[] calldata publicInputs) public override view returns (bool) { - uint256 gasBefore = gasleft(); + function verify(bytes calldata proof, bytes32[] calldata publicInputs) public override returns (bool) { + // uint256 gasBefore = gasleft(); // Load the verification key into memory - loadVk(); // Load the proof from calldata in one large chunk assembly { + // Inline the verification key code here for the meantime + // will be in it's own library + // Note the split committments here will make a difference to costs in the end + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* LOAD VERIFCATION KEY */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // Write the verification key into memory + function loadVk() { + // TODO: in the vk GENERATOR swap the location of l and m + + mstore(q_l_x_loc, 0x2e5f133c25f7e05bd6660196c892121f7fa686cb9a8717a5deea6cd0881e618e) + mstore(q_l_y_loc, 0x1189bba9eeea96ba8935052434f4b0a60b0a481e3464dd81dfcd89e23def001b) + mstore(q_r_x_loc, 0x2a93ffb34002da94f5b156ba5a212ac3616c848bd9c44c9821bbdd64cfd848af) + mstore(q_r_y_loc, 0x015699dcc0b28766d45f5ddce8258393e84c40619d26034e76f778460a1e4d89) + mstore(q_o_x_loc, 0x2057928e8c5eb539c32c3025007b7be1e1663c358f59540c6f949794c274f886) + mstore(q_o_y_loc, 0x12bf0b15c3aa92792330f58b04512714c4a902e537fe87cc438293e1805eaabf) + mstore(q_4_x_loc, 0x304f47a08d4687afa0e2502a9782c32c458bf873ef50c169b732a367e567aaf3) + mstore(q_4_y_loc, 0x0bb37044594e7de200408a4db6bc46adf7790b06f17dce6f38b7deed480aa9f0) + mstore(q_m_x_loc, 0x0aea5b04332ad8781411f7edde21266857ffe11e93af334b14a2b948429afaa4) + mstore(q_m_y_loc, 0x2bd2e3884d486b387122effa12e8698daef82e9b99d7d25b7d5df91a9d738495) + mstore(q_c_x_loc, 0x0e3b418ea1924b4514d5009cd983b5a8074fa95cd1fb200f019fdebe944e4225) + mstore(q_c_y_loc, 0x1e6ef5bde7a9727f1c1d07c91461ae1b40524650b35fdd92ac7a129f263b1beb) + mstore(q_arith_x_loc, 0x096841bfa8ec2295a5af5bf69ec539c31a05b221c84ed1d24c702e31ce1cbc95) + mstore(q_arith_y_loc, 0x10b14cca7e9ff05fcf1e3084f4fc9ab098cf379864b2e2e2e0d33fc5df9d9a50) + mstore(q_delta_range_x_loc, 0x2d27fd1a30a0ab04a05144c27ac41187d5cf89a6022e47b263d1ccb93b3cbea5) + mstore(q_delta_range_y_loc, 0x238eb233e9aebc81285a2647f2598bab00a4367da47b12c2b0476afc2d94ab1d) + mstore(q_elliptic_x_loc, 0x1c6fc8e14453adf64e6d9643ef9f1fb55e3a307ac1ec84f86cd736fc866e05ab) + mstore(q_elliptic_y_loc, 0x1bf8619b1704b99ab8820ed94dd760da2945e8e1c771c0bdeadbe40aa5700cdd) + mstore(q_aux_x_loc, 0x023fe0703623b99c93358348d76eb620f26ceafa58df018e3a8f1d599a61e76f) + mstore(q_aux_y_loc, 0x2ceb9c4c4ca12ea769157ef10cde9644f9f0549805e48d5fd5d73a634d2cdcb5) + mstore(q_lookup_x_loc, 0x1375bbfbf5ed31b38460f46a43ac14e2cda93a3bc5cfd6e8a93cca356694a346) + mstore(q_lookup_y_loc, 0x204c5173892c19a97a04b5f8419898063df5136489809ddb9f7eabb58d6858ab) + mstore(q_poseidon_2_external_x_loc, 0x1fa8529236d7eacdab8dcd8169af30d334be103357577353e9ef08dfda841785) + mstore(q_poseidon_2_external_y_loc, 0x055251b013746385e921b4620e55ef4f08b4d8afc4dbca7e6c3ca0f1b52c5a2b) + mstore(q_poseidon_2_internal_x_loc, 0x1515283648ab8622ac6447f1fcf201a598d8df325279bfac9a6564924df97ee5) + mstore(q_poseidon_2_internal_y_loc, 0x0335bb595984ad38686009bca08f5f420e3b4cf888fad5af4a99eca08190a315) + mstore(sigma_1_x_loc, 0x26cec5ff3eb1b803c52fa1fefaac7a2be5cd13c1a1cc20bb9f22049c7f8597d2) + mstore(sigma_1_y_loc, 0x07e80e74eb0e06d7c0c9a3fbbdea4e86e5934faa8142625f175320778bcba65f) + mstore(sigma_2_x_loc, 0x140b2faaf30cb5fc528621f4a395943e7fab8198dc734ac13253dd249682dd2a) + mstore(sigma_2_y_loc, 0x12709c4a13428f4704d284c90a81cc83280680185ae6298187e86debcd3e00f7) + mstore(sigma_3_x_loc, 0x0aca5621e9f49279969497b3da0eb8a74c68c3513f4cf98e8b1d6f88567557a8) + mstore(sigma_3_y_loc, 0x2664811311f75057a16267bc0479eaeea2424156417cc4d3f8bd286fac9aa5d2) + mstore(sigma_4_x_loc, 0x04417c606a41393e73113ec3f834883dbeb302889199b888c0f5ea58a008ff98) + mstore(sigma_4_y_loc, 0x0865670de7962d29b6a9012f28ea52113c4e2b55d7de44e829edec87dba1d5c2) + // TODO: in the proog pointers above swap id and table - to line up with how they actually should be + mstore(table_1_x_loc, 0x1ec1b607634e31421b5047dc99d7674d6505fed978df0f42a3504f9771a8a7fa) + mstore(table_1_y_loc, 0x1da802c6dc2fe6cffc6f9ae983080c66690ceee40c181b4d51fdba6c5c360297) + mstore(table_2_x_loc, 0x1e38a0a482b7174f429a3bef25fb0a7656abc88cfd215b8e8404132601620784) + mstore(table_2_y_loc, 0x2e9ea07a995fa6d589e37fba2715f3f1fa338652ddf84d4e2e4f33dccadb9156) + mstore(table_3_x_loc, 0x211a0833bb3c6f9ae6c94519b6878ed6157c4a080df786a053d9a19796b9a7f8) + mstore(table_3_y_loc, 0x1a3a450e1a272aa1fe9f097acf359502ff69df617de4918b37a497def94db2b5) + mstore(table_4_x_loc, 0x281a984aef14716cd5d8fc2759eb8ea2464909b5c57d97b6bc50e4dad74d92d3) + mstore(table_4_y_loc, 0x169160e1505685aabd5bd60e994bac45162c6868235cc4252c8b87d0f12603fd) + mstore(id_1_x_loc, 0x01c082a85908fea4c69c4e51436fba7d965e1d88e485da16e35d8f4e8af3b8bd) + mstore(id_1_y_loc, 0x11b0ada021468b059aa6c27f4d4950ef65b98d4d8808ae21718bd8b90f9bb365) + mstore(id_2_x_loc, 0x0b8667619755bd09c7970defeae2c920df2b17b41608303ae1d7393615dd04e4) + mstore(id_2_y_loc, 0x1c5419cd435c5516ac566a9d1dfecdb4e10190c63f2dbd8a1932785caf022e2c) + mstore(id_3_x_loc, 0x110aee72793c4b4ede92c1375f058b4170fcf01bf18f8f1ee934f7ae0fa26da5) + mstore(id_3_y_loc, 0x15c4f6a01ff04ef6b5225c896dfb7060a7a2c320395bda410e756d6b507b7eb8) + mstore(id_4_x_loc, 0x2472aba130e7ed2aefad128109415ec2bdeb56e81e3cbeacc93e00c95f203579) + mstore(id_4_y_loc, 0x0c867d0f8e2f9c861574383b89020980358d898497f80c198a6c17c2f4daf9a4) + mstore(lagrange_first_x_loc, 0x0000000000000000000000000000000000000000000000000000000000000001) + mstore(lagrange_first_y_loc, 0x0000000000000000000000000000000000000000000000000000000000000002) + mstore(lagrange_last_x_loc, 0x13b825e996cc8d600f363dca4481a54d6dd3da85900cd9f0a61fa02600851998) + mstore(lagrange_last_y_loc, 0x151cb86205f2dc38a5651840c1a4b4928f3f3c98f77c2abd08336562986dc404) + + } + + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Split Challenge */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /**We can reduce the amount of hashing done in the verifier by splitting the output of + * hash functions into two 128 bit values + */ function splitChallenge(challenge) -> first, second { first := and(challenge, LOWER_128_MASK) second := shr(128, challenge) } - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order // Add the skip offset to the given pointer @@ -802,28 +1043,58 @@ contract BlakeOptHonkVerifier is IVerifier { // into the value before ( by caching the value we are swapping it with in scratch space ) and then // copying the value back when we are done hashing // rather than copying the entire section over to the lower registers + loadVk() { - let proof_ptr := add(calldataload(0x04), 0x24) + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* LOAD PROOF INTO MEMORY */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // As all of our proof points are written in contiguous parts of memory, we call use a single // calldatacopy to place all of our proof into the correct memory regions + // We copy the entire proof into memory as we must hash each proof section for challenge + // evaluation + let proof_ptr := add(calldataload(0x04), 0x24) - // Load the proof into memory - // TODO: make sure this is evaluated as const + // TODO: make sure this is evaluated as const before shipping // The last item in the proof, and the first item in the proof - let proof_size := sub(zm_pi_y1_loc, proof_circuit_size_loc) + let proof_size := sub(ETA_CHALLENGE, proof_circuit_size_loc) calldatacopy(proof_circuit_size_loc, proof_ptr, proof_size) // TODO(md): IMPORTANT: Mod all of the base field items by q, and all prime field items by p // for the sake of testing we are assuming that these are correct - // Generate challenges + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* GENERATE CHALLENGES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /* + * Proof points (affine coordinates) in the proof are in the following format, where offset is + * the offset in the entire proof until the first bit of the x coordinate + * offset + 0x00: x - lower bits + * offset + 0x20: x - higher bits + * offset + 0x40: y - lower bits + * offset + 0x60: y - higher bits + * + * Proof points are in this extended format at the moment as the proofs are optimised for + * consumption by recursive verifiers + * In the future, it is expect that these proofs will be shortened to be 64 bytes + */ - // TODO: nice section headers ASCII - /** - * Generate Eta Challenges + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* GENERATE ETA CHALLENGE */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /* Eta challenge participants + * - circuit size + * - number of public inputs + * - public inputs offset + * - w1 + * - w2 + * - w3 + * + * Where circuit size, number of public inputs and public inputs offset are all 32 byte values + * and w1,w2,w3 are all proof points values */ + // The use of mcpy will be a life saver here // TODO: make sure that we have enough of a scratch space to work with here // TODO: use an mcpy alternative once off plane - is it available in yul yet? @@ -832,11 +1103,7 @@ contract BlakeOptHonkVerifier is IVerifier { // Note: can be mcpyed from proof // TODO: work what memory can be used here - if we use 0 solidity at all we can get // away with ignoring free memory practices entirely - - // TODO(md): This section could be an mcpy - mstore(0x00, mload(proof_circuit_size_loc)) - mstore(0x20, number_of_public_inputs) - mstore(0x40, mload(proof_pub_inputs_offset_loc)) + mcopy(0x00, proof_circuit_size_loc, 0x60) let public_inputs_start := add(calldataload(0x24), 0x24) let public_inputs_size := mul(number_of_public_inputs, 0x20) @@ -856,16 +1123,18 @@ contract BlakeOptHonkVerifier is IVerifier { // TODO: remember how to function jump let eta, etaTwo := splitChallenge(prev_challenge) - mstore(eta_challenge_loc, eta) - mstore(eta_two_challenge_loc, etaTwo) + mstore(ETA_CHALLENGE, eta) + mstore(ETA_TWO_CHALLENGE, etaTwo) prev_challenge := mod(keccak256(0x00, 0x20), p) - // TODO: update memory pointer mstore(0x00, prev_challenge) let eta_three := and(prev_challenge, LOWER_128_MASK) + mstore(ETA_THREE_CHALLENGE, eta_three) - mstore(eta_three_challenge_loc, eta_three) + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* GENERATE BETA and GAMMAA CHALLENGE */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Generate Beta and Gamma Chalenges mcopy(0x20, lookup_read_counts_x0_loc, 0x180) @@ -874,17 +1143,29 @@ contract BlakeOptHonkVerifier is IVerifier { mstore(0x00, prev_challenge) let beta, gamma := splitChallenge(prev_challenge) - mstore(beta_challenge_loc, beta) - mstore(gamma_challenge_loc, gamma) + mstore(BETA_CHALLENGE, beta) + mstore(GAMMA_CHALLENGE, gamma) + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* ALPHA CHALLENGES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Generate Alpha challenges - non-linearise the gate contributions + // + // There are 26 total subrelations in this honk relation, we do not need to non linearise the first sub relation. + // There are 25 total gate contributions, a gate contribution is analogous to + // a custom gate, it is an expression which must evaluate to zero for each + // row in the constraint matrix + // + // If we do not non-linearise sub relations, then sub relations which rely + // on the same wire will interact with each other's sums. + mcopy(0x20, lookup_inverses_x0_loc, 0x100) prev_challenge := mod(keccak256(0x00, 0x120), p) mstore(0x00, prev_challenge) let alphas_0, alphas_1 := splitChallenge(prev_challenge) - mstore(alpha_challenge_0_loc, alphas_0) - mstore(alpha_challenge_1_loc, alphas_1) + mstore(ALPHA_CHALLENGE_0, alphas_0) + mstore(ALPHA_CHALLENGE_1, alphas_1) let i := 1 // TODO: if we can afford bytecode size - unroll this @@ -895,7 +1176,7 @@ contract BlakeOptHonkVerifier is IVerifier { let alpha_even, alpha_odd := splitChallenge(prev_challenge) - let alpha_off_set := add(alpha_challenge_0_loc, mul(i, 0x40)) + let alpha_off_set := add(ALPHA_CHALLENGE_0, mul(i, 0x40)) mstore(alpha_off_set, alpha_even) mstore(add(alpha_off_set, 0x20), alpha_odd) } @@ -904,14 +1185,18 @@ contract BlakeOptHonkVerifier is IVerifier { mstore(0x00, prev_challenge) let alpha_24 := and(prev_challenge, LOWER_128_MASK) - mstore(alpha_challenge_24_loc, alpha_24) + mstore(ALPHA_CHALLENGE_24, alpha_24) - // GENERATE GATE Challenges + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* GATE CHALLENGES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // TODO: PROSE + // i := 0 for {} lt(i, CONST_PROOF_SIZE_LOG_N) {} { prev_challenge := mod(keccak256(0x00, 0x20), p) mstore(0x00, prev_challenge) - let gate_off := add(gate_challenge_0_loc, mul(0x20, i)) + let gate_off := add(GATE_CHALLENGE_0, mul(0x20, i)) let gate_challenge := and(prev_challenge, LOWER_128_MASK) mstore(gate_off, gate_challenge) @@ -922,7 +1207,7 @@ contract BlakeOptHonkVerifier is IVerifier { // TODO: I think that the order of the values taken from the univariates is wrong // it should be [proof_size, batched length] // rather than as written above [batched_size]{proof_size} - // Total nuber of iterations is 28 , with 8 for each univariate + // Total nuber of iterations is 28 ,with 8 for each univariate i := 0 for {} lt(i, CONST_PROOF_SIZE_LOG_N) {} { // Increase by 20 * batched relation length (8) @@ -938,14 +1223,62 @@ contract BlakeOptHonkVerifier is IVerifier { let sumcheck_u_challenge := and(prev_challenge, LOWER_128_MASK) - let write_off := add(sum_u_challenge_0_loc, mul(i, 0x20)) + let write_off := add(SUM_U_CHALLENGE_0, mul(i, 0x20)) mstore(write_off, sumcheck_u_challenge) i := add(i, 1) } - // Generate Rho Challenge - // Hash all of the sumcheck evaluations + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* RHO CHALLENGES */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // The RHO challenge is the hash of the evaluations of all of the wire values + // As per usual, it includes the previous challenge + // Evaluations of the following wires and their shifts (for relevant wires): + // - QM + // - QC + // - Q1 (QL) + // - Q2 (QR) + // - Q3 (QO) + // - Q4 + // - QARITH + // - QRANGE + // - QELLIPTIC + // - QAUX + // - QLOOKUP + // - QPOSEIDON2_EXTERNAL + // - QPOSEIDON2_INTERNAL + // - SIGMA1 + // - SIGMA2 + // - SIGMA3 + // - SIGMA4 + // - ID1 + // - ID2 + // - ID3 + // - ID4 + // - TABLE1 + // - TABLE2 + // - TABLE3 + // - TABLE4 + // - W1 (WL) + // - W2 (WR) + // - W3 (WO) + // - W4 + // - Z_PERM + // - LOOKUP_INVERSES + // - LOOKUP_READ_COUNTS + // - LOOKUP_READ_TAGS + // - TABLE1_SHIFT + // - TABLE2_SHIFT + // - TABLE3_SHIFT + // - TABLE4_SHIFT + // - W1_SHIFT + // - W2_SHIFT + // - W3_SHIFT + // - W4_SHIFT + // - Z_PERM_SHIFT + // + // Hash of all of the above evaluations // Number of bytes to copy = 0x20 * NUMBER_OF_ENTITIES (44) = 0x580 mcopy(0x20, QM_EVAL_LOC, 0x580) prev_challenge := mod(keccak256(0x00, 0x5a0), p) @@ -953,37 +1286,85 @@ contract BlakeOptHonkVerifier is IVerifier { let rho := and(prev_challenge, LOWER_128_MASK) - mstore(rho_challenge_loc, rho) + mstore(RHO_CHALLENGE, rho) + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* GEMINI R CHALLENGE */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // The Gemini R challenge contains a of all of commitments to all of the univariates + // evaluated in the Gemini Protocol + // So for multivariate polynomials in l variables, we will hash l - 1 commitments. + // For this implementation, we have a fixed number of of rounds and thus 27 committments + // The format of these commitments are proof points, which are explained above + // 0x80 * 27 = 0xd80 + mcopy(0x20, GEMINI_FOLD_UNIVARIATE_0_X0_LOC, 0xd80) - // Generate ZMY Challenge - // This is a hash of all of the zm cq's - // Each cq is a proof g1 point (0x80 bytes) for log n of circuit size - // 0x80 * 28 = 0xe00 - mcopy(0x20, zm_cqs_0_x0_loc, 0xe00) - prev_challenge := mod(keccak256(0x00, 0xe20), p) + prev_challenge := mod(keccak256(0x00, 0xda0), p) mstore(0x00, prev_challenge) - let zmY := and(prev_challenge, LOWER_128_MASK) + let geminiR := and(prev_challenge, LOWER_128_MASK) - mstore(zm_y_challenge_loc, zmY) + mstore(GEMINI_R_CHALLENGE, geminiR) - // Generate zmX, zmZ Challenges - mcopy(0x20, zm_cq_x0_loc, 0x80) + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* SHPLONK NU CHALLENGE */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // The shplonk nu challenge hashes the evaluations of the above gemini univariates + // 0x20 * 28 = 0x380 + mcopy(0x20, GEMINI_A_EVAL_0, 0x380) + prev_challenge := mod(keccak256(0x00, 0x3a0), p) + mstore(0x00, prev_challenge) + + let shplonkNu := and(prev_challenge, LOWER_128_MASK) + mstore(SHPLONK_NU_CHALLENGE, shplonkNu) + + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* SHPLONK Z CHALLENGE */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // Generate Shplonk Z + // Hash of the single shplonk Q commitment + mcopy(0x20, SHPLONK_Q_X0_LOC, 0x80) prev_challenge := mod(keccak256(0x00, 0xa0), p) - let zmX, zmZ := splitChallenge(prev_challenge) - mstore(zm_x_challenge_loc, zmX) - mstore(zm_z_challenge_loc, zmZ) + let shplonkZ := and(prev_challenge, LOWER_128_MASK) + mstore(SHPLONK_Z_CHALLENGE, shplonkZ) - // All challenges have been generated + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* CHALLENGES COMPLETE */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ } - // Generate public inputa delta + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* PUBLIC INPUT DELTA */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + /**Generate public inputa delta + * + * The public inputs delta leverages plonk's copy constraints in order to + * evaluate public inputs. + * + * For each row of the execution trace, the prover will calculate the following value + * There are 4 witness wires, 4 id wires and 4 sigma wires in this instantiation of the proof system + * So there will be 4 groups of wires (w_i, id_i and sigma_i) + * + * (w_0 + β(id_0) + γ) * ∏(w_1 + β(id_1) + γ) * ∏(w_2 + β(id_2) + γ) * ∏(w_3 + β(id_3) + γ) + * ∏------------------------------------------------------------------------------------------ * public_inputs_delta + * (w_0 + β(σ_0) + γ) * ∏(w_1 + β(σ_1) + γ) * ∏(w_2 + β(σ_2) + γ) * ∏(w_3 + β(σ_3) + γ) + * + * The above product is accumulated for all rows in the trace. + * + * The above equation enforces that for each cell in the trace, if the id and sigma pair are equal, then the + * witness value in that cell is equal. + * + * We extra terms to add to this product that correspond to public input values + * + */ + // TODO: think about how to optimize this further { - let beta := mload(beta_challenge_loc) - let gamma := mload(gamma_challenge_loc) + let beta := mload(BETA_CHALLENGE) + let gamma := mload(GAMMA_CHALLENGE) let domain_size := mload(proof_circuit_size_loc) // NOTE(md): compiler broken when offset is used in a variable name? let pub_off := mload(proof_pub_inputs_offset_loc) @@ -1023,14 +1404,12 @@ contract BlakeOptHonkVerifier is IVerifier { // Revert if not all public inputs are field elements (i.e. < p) if iszero(valid_inputs) { - // TODO: custom errors - // mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) - revert(0x00, 0x0) + mstore(0x00, PUBLIC_INPUT_TOO_LARGE_SELECTOR) + revert(0x00, 0x04) } - // TODO(md): do not need to store these if inverting now???? - mstore(PUBLIC_INPUTS_DELTA_NUMERATOR_LOC, numerator_value) - mstore(PUBLIC_INPUTS_DELTA_DENOMINATOR_LOC, denominator_value) + mstore(PUBLIC_INPUTS_DELTA_NUMERATOR, numerator_value) + mstore(PUBLIC_INPUTS_DELTA_DENOMINATOR, denominator_value) // TODO(md): optimise this by performing the inversion later - but just doing it here for now let dom_inverse := 0 @@ -1042,15 +1421,14 @@ contract BlakeOptHonkVerifier is IVerifier { mstore(0x80, sub(p, 2)) mstore(0xa0, p) if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { - // TODO: custom error - mstore(0x0, 0x69696969) + mstore(0x00, MODEXP_FAILED_SELECTOR) revert(0x00, 0x04) } // 1 / (0 . 1 . 2 . 3 . 4 . 5 . 6 . 7) dom_inverse := mload(0x00) } // Calculate the public inputs delta - mstore(PUBLIC_INPUTS_DELTA_NUMERATOR_LOC, mulmod(numerator_value, dom_inverse, p)) + mstore(PUBLIC_INPUTS_DELTA_NUMERATOR, mulmod(numerator_value, dom_inverse, p)) // TODO(md): store the result in the numerator location } @@ -1063,42 +1441,52 @@ contract BlakeOptHonkVerifier is IVerifier { // TODO: Optimisation: If we can write these into the program bytecode then // we could use a codecopy to load them into memory as a single slab, rather than // writing a series of individual values + + // WORKTODO: The non-via ir compiler will be able to take a long bytes constant + // and it will write as a code copy, so we can optimise this table write further + // by writing it as a single large bytes constant + + // TASK: + // Write to the free memory pointer where we want this to go + // Outside of assembly at the beginning of the verify function + // Attempt to allocate this variable, when it will codecopy it to the + // free memory pointer, - in the place we want it :) function writeBarycentricTables() { // We write into hardcoded memory regions mstore( - BARYCENTRIC_LAGRANGE_DENOMINATORS_LOC, + BARYCENTRIC_LAGRANGE_DENOMINATOR_0_LOC, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51 ) mstore( - BARYCENTRIC_LAGRANGE_DENOMINATORS_1_LOC, + BARYCENTRIC_LAGRANGE_DENOMINATOR_1_LOC, 0x00000000000000000000000000000000000000000000000000000000000002d0 ) mstore( - BARYCENTRIC_LAGRANGE_DENOMINATORS_2_LOC, + BARYCENTRIC_LAGRANGE_DENOMINATOR_2_LOC, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff11 ) mstore( - BARYCENTRIC_LAGRANGE_DENOMINATORS_3_LOC, + BARYCENTRIC_LAGRANGE_DENOMINATOR_3_LOC, 0x0000000000000000000000000000000000000000000000000000000000000090 ) mstore( - BARYCENTRIC_LAGRANGE_DENOMINATORS_4_LOC, + BARYCENTRIC_LAGRANGE_DENOMINATOR_4_LOC, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff71 ) mstore( - BARYCENTRIC_LAGRANGE_DENOMINATORS_5_LOC, + BARYCENTRIC_LAGRANGE_DENOMINATOR_5_LOC, 0x00000000000000000000000000000000000000000000000000000000000000f0 ) mstore( - BARYCENTRIC_LAGRANGE_DENOMINATORS_6_LOC, + BARYCENTRIC_LAGRANGE_DENOMINATOR_6_LOC, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31 ) mstore( - BARYCENTRIC_LAGRANGE_DENOMINATORS_7_LOC, + BARYCENTRIC_LAGRANGE_DENOMINATOR_7_LOC, 0x00000000000000000000000000000000000000000000000000000000000013b0 ) - mstore(BARYCENTRIC_DOMAIN_LOC, 0x00) + mstore(BARYCENTRIC_DOMAIN_0_LOC, 0x00) mstore(BARYCENTRIC_DOMAIN_1_LOC, 0x01) mstore(BARYCENTRIC_DOMAIN_2_LOC, 0x02) mstore(BARYCENTRIC_DOMAIN_3_LOC, 0x03) @@ -1127,7 +1515,7 @@ contract BlakeOptHonkVerifier is IVerifier { */ function batchInvertInplace(p_clone) { // We know that there will be 8 denominators - let accumulator := mload(BARYCENTRIC_DENOMINATOR_INVERSES_LOC) + let accumulator := mload(BARYCENTRIC_DENOMINATOR_INVERSES_0_LOC) // 0 let t0 := accumulator @@ -1160,8 +1548,7 @@ contract BlakeOptHonkVerifier is IVerifier { mstore(0x80, sub(p_clone, 2)) mstore(0xa0, p_clone) if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { - // TODO: custom error - mstore(0x0, 0x69696969) + mstore(0x00, MODEXP_FAILED_SELECTOR) revert(0x00, 0x04) } // 1 / (0 . 1 . 2 . 3 . 4 . 5 . 6 . 7) @@ -1232,7 +1619,7 @@ contract BlakeOptHonkVerifier is IVerifier { mstore(BARYCENTRIC_DENOMINATOR_INVERSES_1_LOC, t0) accumulator := mulmod(accumulator, temp, p_clone) - mstore(BARYCENTRIC_DENOMINATOR_INVERSES_LOC, accumulator) + mstore(BARYCENTRIC_DENOMINATOR_INVERSES_0_LOC, accumulator) } // Note: pass around p to keep it on the stack @@ -1257,12 +1644,12 @@ contract BlakeOptHonkVerifier is IVerifier { // TODO_OPT(md): could be unrolled i := 0 for {} lt(i, BATCHED_RELATION_PARTIAL_LENGTH) {} { - let inv := mload(add(BARYCENTRIC_LAGRANGE_DENOMINATORS_LOC, mul(i, 0x20))) + let inv := mload(add(BARYCENTRIC_LAGRANGE_DENOMINATOR_0_LOC, mul(i, 0x20))) let rc_minus_domain := - addmod(round_challenge, sub(p_clone, mload(add(BARYCENTRIC_DOMAIN_LOC, mul(i, 0x20)))), p_clone) + addmod(round_challenge, sub(p_clone, mload(add(BARYCENTRIC_DOMAIN_0_LOC, mul(i, 0x20)))), p_clone) inv := mulmod(inv, rc_minus_domain, p_clone) - mstore(add(BARYCENTRIC_DENOMINATOR_INVERSES_LOC, mul(i, 0x20)), inv) + mstore(add(BARYCENTRIC_DENOMINATOR_INVERSES_0_LOC, mul(i, 0x20)), inv) i := add(i, 1) } @@ -1274,7 +1661,7 @@ contract BlakeOptHonkVerifier is IVerifier { for {} lt(i, BATCHED_RELATION_PARTIAL_LENGTH) {} { let off := mul(i, 0x20) let term := mload(add(round_univariates_ptr, off)) - let inverse := mload(add(BARYCENTRIC_DENOMINATOR_INVERSES_LOC, off)) + let inverse := mload(add(BARYCENTRIC_DENOMINATOR_INVERSES_0_LOC, off)) term := mulmod(term, inverse, p_clone) next_target := addmod(next_target, term, p_clone) @@ -1287,7 +1674,7 @@ contract BlakeOptHonkVerifier is IVerifier { function partiallyEvaluatePOW( round_challenge, /*: uint256 */ current_evaluation, /*: uint256 */ round, /*: uint256 */ p_clone ) -> /*: uint256 */ next_evaluation /*: uint256 */ { - let gate_challenge := mload(add(gate_challenge_0_loc, mul(round, 0x20))) + let gate_challenge := mload(add(GATE_CHALLENGE_0, mul(round, 0x20))) let gate_challenge_minus_one := sub(gate_challenge, 1) let univariate_evaluation := @@ -1303,10 +1690,9 @@ contract BlakeOptHonkVerifier is IVerifier { let round_target := 0 let pow_partial_evaluation := 1 - // TODO(md): update, but set at 2 for now for {} lt(round, 15) {} { let round_univariates_off := add(sumcheck_univariate_0_0, mul(round, 0x100)) - let challenge_off := add(sum_u_challenge_0_loc, mul(round, 0x20)) + let challenge_off := add(SUM_U_CHALLENGE_0, mul(round, 0x20)) let round_challenge := mload(challenge_off) @@ -1321,8 +1707,8 @@ contract BlakeOptHonkVerifier is IVerifier { } if iszero(valid) { - // TODO: custom error - revert(0x00, 0x00) + mstore(0x00, SUMCHECK_FAILED_SELECTOR) + revert(0x00, 0x04) } @@ -1330,6 +1716,7 @@ contract BlakeOptHonkVerifier is IVerifier { // Uses pow partial evaluation as the gate scaling factor // NOTE: maybe mstore pow_partial_evaluation here rather than keeping on the stack + // TODO(md): add to offsets script mstore(POW_PARTIAL_EVALUATION_LOC, pow_partial_evaluation) mstore(FINAL_ROUND_TARGET_LOC, round_target) @@ -1418,7 +1805,7 @@ contract BlakeOptHonkVerifier is IVerifier { // Split up the two relations let contribution_0 := addmod(identity, mulmod(addmod(q_arith, sub(p, 1), p), mload(W4_SHIFT_EVAL_LOC), p), p) contribution_0 := mulmod(mulmod(contribution_0, q_arith, p), mload(POW_PARTIAL_EVALUATION_LOC), p) - mstore(SUBRELATION_EVAL_LOC, contribution_0) + mstore(SUBRELATION_EVAL_0_LOC, contribution_0) let contribution_1 := mulmod(extra_small_addition_gate_identity, addmod(q_arith, sub(p, 1), p), p) contribution_1 := mulmod(contribution_1, q_arith, p) @@ -1430,8 +1817,8 @@ contract BlakeOptHonkVerifier is IVerifier { * COMPUTE PERMUTATION WIDGET EVALUATION */ { - let beta := mload(beta_challenge_loc) - let gamma := mload(gamma_challenge_loc) + let beta := mload(BETA_CHALLENGE) + let gamma := mload(GAMMA_CHALLENGE) /** * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) @@ -1480,7 +1867,7 @@ contract BlakeOptHonkVerifier is IVerifier { mload(Z_PERM_SHIFT_EVAL_LOC), mulmod( mload(LAGRANGE_LAST_EVAL_LOC), - mload(PUBLIC_INPUTS_DELTA_NUMERATOR_LOC), + mload(PUBLIC_INPUTS_DELTA_NUMERATOR), p ), p @@ -1504,12 +1891,12 @@ contract BlakeOptHonkVerifier is IVerifier { * LOGUP WIDGET EVALUATION */ { - let eta := mload(eta_challenge_loc) - let eta_two := mload(eta_two_challenge_loc) - let eta_three := mload(eta_three_challenge_loc) + let eta := mload(ETA_CHALLENGE) + let eta_two := mload(ETA_TWO_CHALLENGE) + let eta_three := mload(ETA_THREE_CHALLENGE) - let beta := mload(beta_challenge_loc) - let gamma := mload(gamma_challenge_loc) + let beta := mload(BETA_CHALLENGE) + let gamma := mload(GAMMA_CHALLENGE) let t0 := addmod(addmod(mload(TABLE1_EVAL_LOC), gamma, p), mulmod(mload(TABLE2_EVAL_LOC), eta, p), p) let t1 := addmod(mulmod(mload(TABLE3_EVAL_LOC), eta_two, p), mulmod(mload(TABLE4_EVAL_LOC), eta_three, p), p) @@ -1858,9 +2245,9 @@ contract BlakeOptHonkVerifier is IVerifier { * memory_record_check -= w_4; */ // TODO(md): update these - formula has changed with lower degree - let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(eta_three_challenge_loc), p) - memory_record_check := addmod(memory_record_check, mulmod(mload(W2_EVAL_LOC), mload(eta_two_challenge_loc), p), p) - memory_record_check := addmod(memory_record_check, mulmod(mload(W1_EVAL_LOC), mload(eta_challenge_loc), p), p) + let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(ETA_THREE_CHALLENGE), p) + memory_record_check := addmod(memory_record_check, mulmod(mload(W2_EVAL_LOC), mload(ETA_TWO_CHALLENGE), p), p) + memory_record_check := addmod(memory_record_check, mulmod(mload(W1_EVAL_LOC), mload(ETA_CHALLENGE), p), p) memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) let partial_record_check := memory_record_check @@ -1979,9 +2366,9 @@ contract BlakeOptHonkVerifier is IVerifier { * next_gate_access_type *= eta; * next_gate_access_type = w_4_omega - next_gate_access_type; */ - let next_gate_access_type := mulmod(mload(W3_SHIFT_EVAL_LOC), mload(eta_three_challenge_loc), p) - next_gate_access_type := addmod(next_gate_access_type, mulmod(mload(W2_SHIFT_EVAL_LOC), mload(eta_two_challenge_loc), p), p) - next_gate_access_type := addmod(next_gate_access_type, mulmod(mload(W1_SHIFT_EVAL_LOC), mload(eta_challenge_loc), p), p) + let next_gate_access_type := mulmod(mload(W3_SHIFT_EVAL_LOC), mload(ETA_THREE_CHALLENGE), p) + next_gate_access_type := addmod(next_gate_access_type, mulmod(mload(W2_SHIFT_EVAL_LOC), mload(ETA_TWO_CHALLENGE), p), p) + next_gate_access_type := addmod(next_gate_access_type, mulmod(mload(W1_SHIFT_EVAL_LOC), mload(ETA_CHALLENGE), p), p) next_gate_access_type := addmod(mload(W4_SHIFT_EVAL_LOC), sub(p, next_gate_access_type), p) // value_delta = w_3_omega - w_3 @@ -2227,7 +2614,7 @@ contract BlakeOptHonkVerifier is IVerifier { // Scale and batch subrelations by subrelation challenges // linear combination of subrelations - let accumulator := mload(SUBRELATION_EVAL_LOC) + let accumulator := mload(SUBRELATION_EVAL_0_LOC) // TODO(md): unroll??? // TODO(md): not optimal @@ -2238,8 +2625,8 @@ contract BlakeOptHonkVerifier is IVerifier { accumulator := addmod( accumulator, mulmod( - mload(add(SUBRELATION_EVAL_LOC, evaluation_off)), - mload(add(alpha_challenge_0_loc, challenge_off)), + mload(add(SUBRELATION_EVAL_0_LOC, evaluation_off)), + mload(add(ALPHA_CHALLENGE_0, challenge_off)), p), p) } @@ -2252,12 +2639,1305 @@ contract BlakeOptHonkVerifier is IVerifier { } } - let gasAfter := gas() - log1(0x00, 0x00, sub(gasBefore, gasAfter)) + // Shplemini Commitment scheme + + // Compute powers of evaluation challenge + let cache := mload(GEMINI_R_CHALLENGE) + let off := POWERS_OF_EVALUATION_CHALLENGE_0_LOC + mstore(off, cache) + for {let i := 1} lt(i, CONST_PROOF_SIZE_LOG_N) {i := add(i, 1)} { + off := add(off, 0x20) + cache := mulmod(cache, cache, p) + mstore(off, cache) + } + + // Compute Inverted Gemini Denominators + let eval_challenge := mload(SHPLONK_Z_CHALLENGE) + mstore(INVERTED_GEMINI_DENOMINATOR_0_LOC, addmod(eval_challenge, sub(p, mload(POWERS_OF_EVALUATION_CHALLENGE_0_LOC)), p)) + + let vanishing_eval_off := INVERTED_GEMINI_DENOMINATOR_1_LOC + let eval_challenge_powers_off := POWERS_OF_EVALUATION_CHALLENGE_0_LOC + for {let i := 0} lt(i, add(LOG_N, 2)) {i := add(i, 1)} { + + // TODO: Branchless dummy proof selection + // If (i <= LOG_N + 1) in our loop, then the inverted denominator contribution will + // need to be 0 - so we can multiply the result of the eval challenge by the result + // + // TODO: reason more if i decide to go that direction + // TODO: measure - is an addmod + stack operations cheaper than a jump??? + + // TODO: add(CONSTANT, CONSTANT) is evaluated at comptime + let temp := addmod(eval_challenge, mload(eval_challenge_powers_off), p) + + mstore(vanishing_eval_off, addmod(eval_challenge, mload(eval_challenge_powers_off), p)) + + // NOTES - + // These notes are related to the non yul version of this code + // ------------------ + // TODO: can we assume that memory inside inverse_vanishing_evals is zeroed + // But also, DO we want it to be zeroed + // The efficient algorithm here will invert the field elements in a batch + // we cannot invert this in a batch as it may contain zeros - so multiplying them + // is unsafe. + + // If we know what LOG_N is + // We need to produce a different verifier that will perform a different batch inversion + // function depending on the value of LOG_N + // This version of the function is only going to write up to the LOG_N that we KNOW + // But in cpp we can `template` this function such that it generates the correct output code + // If we do decide to do this - we will need to very intently document this process + + vanishing_eval_off := add(vanishing_eval_off, 0x20) + eval_challenge_powers_off := add(eval_challenge_powers_off, 0x20) + } + + // Invert all of the round_inverted denominators AND invert the geminiR challenge + // ---------------- + // To do this, we again use montgomery's batch inversion trick + // The following code will invert up until LOG_N scalars writing their result back into the memory + // location that they came from + // In this example, LOG_N + 1 is 16, plus an additional element for geminiR so we have 17 inversions + // + // REVIEWTODO: check that the comment made here is correct + + // There will be 16 intermediate values + // So we will need to store many of the original accumulator values in memory + // TODO: update this comment with the number that were chosen + + // Remark: We store the accumulator outside this scope, as it's final value is immediately used + // as soon as this current scope resumes - as geminiR challenge's inversion + let accumulator := mload(GEMINI_R_CHALLENGE) + { + mstore(BATCH_ACCUMULATOR_0_LOC, accumulator) + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_0_LOC), p) + + mstore(BATCH_ACCUMULATOR_1_LOC, accumulator) + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_1_LOC), p) + + mstore(BATCH_ACCUMULATOR_2_LOC , accumulator) + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_2_LOC), p) + + mstore(BATCH_ACCUMULATOR_3_LOC, accumulator) + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_3_LOC), p) + + mstore(BATCH_ACCUMULATOR_4_LOC, accumulator) + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_4_LOC), p) + + mstore(BATCH_ACCUMULATOR_5_LOC, accumulator) + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_5_LOC), p) + + mstore(BATCH_ACCUMULATOR_6_LOC, accumulator) + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_6_LOC), p) + + mstore(BATCH_ACCUMULATOR_7_LOC, accumulator) + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_7_LOC), p) + + mstore(BATCH_ACCUMULATOR_8_LOC, accumulator) + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_8_LOC), p) + + let t9 := accumulator + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_9_LOC), p) + + let t10 := accumulator + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_10_LOC), p) + + let t11 := accumulator + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_11_LOC), p) + + let t12 := accumulator + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_12_LOC), p) + + let t13 := accumulator + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_13_LOC), p) + + let t14 := accumulator + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_14_LOC), p) + + let t15 := accumulator + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_15_LOC), p) + + let t16 := accumulator + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_16_LOC), p) + + let t17 := accumulator + accumulator := mulmod(accumulator, mload(INVERTED_GEMINI_DENOMINATOR_17_LOC), p) + + { + mstore(0, 0x20) + mstore(0x20, 0x20) + mstore(0x40, 0x20) + mstore(0x60, accumulator) + mstore(0x80, sub(p, 2)) + mstore(0xa0, p) + if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { + mstore(0x00, MODEXP_FAILED_SELECTOR) + revert(0x00, 0x04) + } + // 1 / (0 . 1 . 2 . 3 . 4 . 5 . 6 . 7) + accumulator := mload(0x00) + } + + t17 := mulmod(accumulator, t17, p) + let temp := mload(INVERTED_GEMINI_DENOMINATOR_17_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_17_LOC, t17) + + accumulator := mulmod(accumulator, temp, p) + + t16 := mulmod(accumulator, t16, p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_16_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_16_LOC, t16) + + accumulator := mulmod(accumulator, temp, p) + + t15 := mulmod(accumulator, t15, p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_15_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_15_LOC, t15) + + accumulator := mulmod(accumulator, temp, p) + + t14 := mulmod(accumulator, t14, p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_14_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_14_LOC, t14) + + accumulator := mulmod(accumulator, temp, p) + + t13 := mulmod(accumulator, t13, p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_13_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_13_LOC, t13) + + accumulator := mulmod(accumulator, temp, p) + + t12 := mulmod(accumulator, t12, p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_12_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_12_LOC, t12) + + accumulator := mulmod(accumulator, temp, p) + + t11 := mulmod(accumulator, t11, p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_11_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_11_LOC, t11) + + accumulator := mulmod(accumulator, temp, p) + + t10 := mulmod(accumulator, t10, p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_10_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_10_LOC, t10) + + accumulator := mulmod(accumulator, temp, p) + + t9 := mulmod(accumulator, t9, p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_9_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_9_LOC, t9) + + accumulator := mulmod(accumulator, temp, p) + + let t8 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_8_LOC), p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_8_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_8_LOC, t8) + + accumulator := mulmod(accumulator, temp, p) + + let t7 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_7_LOC), p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_7_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_7_LOC, t7) + + accumulator := mulmod(accumulator, temp, p) + + let t6 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_6_LOC), p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_6_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_6_LOC, t6) + + accumulator := mulmod(accumulator, temp, p) + + let t5 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_5_LOC), p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_5_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_5_LOC, t5) + + accumulator := mulmod(accumulator, temp, p) + + let t4 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_4_LOC), p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_4_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_4_LOC, t4) + + accumulator := mulmod(accumulator, temp, p) + + let t3 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_3_LOC), p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_3_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_3_LOC, t3) + + accumulator := mulmod(accumulator, temp, p) + + let t2 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_2_LOC), p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_2_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_2_LOC, t2) + + accumulator := mulmod(accumulator, temp, p) + + let t1 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_1_LOC), p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_1_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_1_LOC, t1) + + accumulator := mulmod(accumulator, temp, p) + + let t0 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_0_LOC), p) + temp := mload(INVERTED_GEMINI_DENOMINATOR_0_LOC) + mstore(INVERTED_GEMINI_DENOMINATOR_0_LOC, t0) + + // The accumulator now stores the inversion of the GEMINI_R_CHALLENGE + accumulator := mulmod(accumulator, temp, p) + } + + let unshifted_scalar := 0 + let shifted_scalar := 0 + { + let inverted_gemini_denominator_0 := mload(INVERTED_GEMINI_DENOMINATOR_0_LOC) + let inverted_gemini_denominator_1 := mload(INVERTED_GEMINI_DENOMINATOR_1_LOC) + let shplonk_nu := mload(SHPLONK_NU_CHALLENGE) + + // accumulator takes the value of `INVERTED_GEMINI_DENOMINATOR_0` here + unshifted_scalar := addmod( + inverted_gemini_denominator_0, + mulmod(shplonk_nu, inverted_gemini_denominator_1, p), + p + ) + + // WORKTODO: MAKE A COMMENT ABOUT HOW WE ALSO STORE GEMINI R + shifted_scalar := mulmod( + accumulator, // (1 / gemini_r_challenge) + // (inverse_vanishing_evals[0]) - (shplonk_nu * inverse_vanishing_evals[1]) + addmod( + inverted_gemini_denominator_0, + // - (shplonk_nu * inverse_vanishing_evals[1]) + sub( + p, + mulmod( + shplonk_nu, + inverted_gemini_denominator_1, + p + ) + ), + p + ), + p + ) + + } + + // This function takes a proof point from its field element representaiton into its + // functional bytes representation + // + // WORKTODO: check that these offsets are correct!! + // Proof points are sent in the proof in the format: + // 0x00: x_coordinate_low + // 0x20: x_coordinate_high + // 0x40: y_coordinate_low + // 0x60: y_coordinate_high + // + // The reason being, proofs in their current form are optimised to make recursive proving + // simpler. In essence this is tech debt, and will be updated at a future point + // + // This function converts the proofs into their correct version + // 0x00: x_coordinate + // 0x20: y_coordinate + // + // This is the form that the bn254 ecMul precompile expects, and such is the form we will use + // + // The expected usage of this function is to convert proof points on the fly + // and write them into the scratch space in order to be accumulated with the + // ecMul precompile + // + // TODO: write in here where the scalar is expected in scratch space + function writeProofPointIntoScratchSpace(proof_memory_location) { + let x_low := mload(proof_memory_location) + let x_high := mload(add(proof_memory_location, 0x20)) + + // x_low | x_high < 136 + mstore(0x60, or(shl(136, x_high), x_low)) + + let y_low := mload(add(proof_memory_location, 0x40)) + let y_high := mload(add(proof_memory_location, 0x60)) + + // y_low | y_high < 136 + mstore(0x80, or(shl(136, y_high), y_low)) + + // By now, we should expect our scratch space to look as follows + // 0x00: scalar + // 0x20: x_coordinate + // 0x40: y_coordinate + } + + // TODO: cleanup multiple implementations + function writeProofPointOntoStack(proof_point_memory_location) -> x, y { + let x_low := mload(proof_point_memory_location) + let x_high := mload(add(proof_point_memory_location, 0x20)) + + let y_low := mload(add(proof_point_memory_location, 0x40)) + let y_high := mload(add(proof_point_memory_location, 0x60)) + + + x := or(shl(136, x_high), x_low) + y := or(shl(136, y_high), y_low) + } + + function validateProofPointOnCurve(success_flag, proof_point_memory_location, p_clone, q_clone) -> success_return { + let x, y := writeProofPointOntoStack(proof_point_memory_location) + + let xx := mulmod(x, x, p_clone) + let yy := mulmod(y, y, p_clone) + let xy := mulmod(x, y, p_clone) + + success_return := and(success_flag, iszero(eq(mulmod(y, y, q_clone), addmod(mulmod(x, xx, q_clone), 3, q_clone)))) + } + + // This function takes the values currently in scratch space, and performs an EC MUL + // Adding the result to the point stored in an accumulator + // We assume that the accumulator is stored within scratch space at + // + // 0x00: Accumulator_x_coordinate + // 0x20: Accumulator_y_coordinate + // function ecMulAndAccumulate(accumulator) -> success_flag { + + // let success := staticcall( + // gas(), + // 7, + // 0x40, + // 0x60, + + // ) + + // } + + + // TODO: Write a comment that describes the process of accumulating commitments and scalars + // into one large value that will be used on the rhs of the pairing check + + // Accumulators + // TODO: explain what these are for more in depth + { + + } + let batchingChallenge := 1 + let batchedEvaluation := 0 + let neg_unshifted_scalar := sub(p, unshifted_scalar) + let neg_shifted_scalar := sub(p, shifted_scalar) - mstore(0x00, 0x01) - return(0x00, 0x20) + // TODO: there is a tradeoff between doing this in a loop / just unrolling the whole thing + // For now i have decided to calculate all of the scalars in this loop. + // But accumulate the commitments unrolled + + // WORKTODO: THIS IS NOT USED, WE MANUALLY WRITE THIS AGAIN??? + mstore(BATCH_SCALAR_0_LOC, 1) + for {let i := 1} lt(i, add(NUMBER_OF_UNSHIFTED_ENTITIES, 1)) {i := add(i, 1)} { + let arr_index_off := mul(i, 0x20) + // TODO: opt this - redundant comp here + let index_minus_one := mul(sub(i, 1), 0x20) + + // We write into the scalars offset + let scalars_off := add(BATCH_SCALAR_0_LOC, arr_index_off) + // Sumcheck evaluations offset + let evaluation_off := add(QM_EVAL_LOC, index_minus_one) + + mstore(scalars_off, mulmod(neg_unshifted_scalar, batchingChallenge, p) ) + + batchedEvaluation := addmod(batchedEvaluation, mulmod(mload(evaluation_off), batchingChallenge, p), p) + batchingChallenge := mulmod(batchingChallenge, mload(RHO_CHALLENGE), p) + } + + for {let i:= add(NUMBER_OF_UNSHIFTED_ENTITIES, 1)} lt(i, add(NUMBER_OF_ENTITIES, 1)) {i := add(i, 1)} { + let arr_index_off := mul(i, 0x20) + // TODO: opt this - redundant comp here + let index_minus_one := mul(sub(i, 1), 0x20) + + // We write into the scalars offset + let scalars_off := add(BATCH_SCALAR_0_LOC, arr_index_off) + // Sumcheck evaluations offset + let evaluation_off := add(QM_EVAL_LOC, index_minus_one) + + mstore(scalars_off, mulmod(neg_shifted_scalar, batchingChallenge, p) ) + + batchedEvaluation := addmod(batchedEvaluation, mulmod(mload(evaluation_off), batchingChallenge, p), p) + batchingChallenge := mulmod(batchingChallenge, mload(RHO_CHALLENGE), p) + } + + mstore(BATCHED_EVALUATION_LOC, batchedEvaluation) + + // Validate the proof points are on the curve + { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + let success_flag := 1 + success_flag := validateProofPointOnCurve(success_flag, w_l_x0_loc, p, q) + success_flag := validateProofPointOnCurve(success_flag, w_r_x0_loc, p, q) + success_flag := validateProofPointOnCurve(success_flag, w_o_x0_loc, p, q) + success_flag := validateProofPointOnCurve(success_flag, lookup_read_counts_x0_loc, p, q) + success_flag := validateProofPointOnCurve(success_flag, lookup_read_tags_x0_loc, p, q) + success_flag := validateProofPointOnCurve(success_flag, w_4_x0_loc, p, q) + success_flag := validateProofPointOnCurve(success_flag, lookup_inverses_x0_loc, p, q) + success_flag := validateProofPointOnCurve(success_flag, z_perm_x0_loc, p, q) + + if iszero(success_flag) { + mstore(0x00, PROOF_POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + } + + let precomp_success_flag := 1 + // THe initial accumulator is 1 * shplonk + + // TODO make constant + { + // accumulator = 1 * shplonk_q + // WORKTODO(md): we can ignore this accumulation as we are multiplying by 1, + // Just set the accumulator instead + mstore(SCALAR_LOCATION, 0x1) + writeProofPointIntoScratchSpace(SHPLONK_Q_X0_LOC) + precomp_success_flag := staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR, 0x40) + } + + // Accumulate vk points + // TODO: this method of copying into scrath space could be avoided? + // OPT: An alternative i can think of is storing the location the scalar need to go onto the stack, + // then call the precompile with the proof point in place. + // WORKTODO: I may have overridden the vk by this point + // although we only use it from this point onwards - + // WARNING: DUPLICATED + loadVk() + { + // Acumulator = acumulator + scalar[1] * vk[0] + mcopy(G1_LOCATION, q_m_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_1_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[2] * vk[1] + mcopy(G1_LOCATION, q_c_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_2_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[3] * vk[2] + mcopy(G1_LOCATION, q_l_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_3_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[4] * vk[3] + mcopy(G1_LOCATION, q_r_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_4_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[5] * vk[4] + mcopy(G1_LOCATION, q_o_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_5_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[6] * vk[5] + mcopy(G1_LOCATION, q_4_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_6_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[7] * vk[6] + mcopy(G1_LOCATION, q_arith_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_7_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[8] * vk[7] + mcopy(G1_LOCATION, q_delta_range_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_8_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[9] * vk[8] + mcopy(G1_LOCATION, q_elliptic_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_9_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[10] * vk[9] + mcopy(G1_LOCATION, q_aux_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_10_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[11] * vk[10] + mcopy(G1_LOCATION, q_lookup_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_11_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[12] * vk[11] + mcopy(G1_LOCATION, q_poseidon_2_external_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_12_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[13] * vk[12] + mcopy(G1_LOCATION, q_poseidon_2_internal_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_13_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[14] * vk[13] + mcopy(G1_LOCATION, sigma_1_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_14_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[15] * vk[14] + mcopy(G1_LOCATION, sigma_2_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_15_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[16] * vk[15] + mcopy(G1_LOCATION, sigma_3_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_16_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[17] * vk[16] + mcopy(G1_LOCATION, sigma_4_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_17_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[18] * vk[17] + mcopy(G1_LOCATION, id_1_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_18_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[19] * vk[18] + mcopy(G1_LOCATION, id_2_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_19_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[20] * vk[19] + mcopy(G1_LOCATION, id_3_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_20_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[21] * vk[20] + mcopy(G1_LOCATION, id_4_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_21_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[22] * vk[21] + mcopy(G1_LOCATION, table_1_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_22_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[23] * vk[22] + mcopy(G1_LOCATION, table_2_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_23_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[24] * vk[23] + mcopy(G1_LOCATION, table_3_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_24_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[25] * vk[24] + mcopy(G1_LOCATION, table_4_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_25_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[26] * vk[25] + mcopy(G1_LOCATION, lagrange_first_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_26_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[27] * vk[26] + mcopy(G1_LOCATION, lagrange_last_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_27_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulate proof points + // Accumulator = accumulator + scalar[28] * w_l + writeProofPointIntoScratchSpace(w_l_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_28_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[28] * w_l + writeProofPointIntoScratchSpace(w_r_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_29_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[30] * w_o + writeProofPointIntoScratchSpace(w_o_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_30_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[31] * w_4 + writeProofPointIntoScratchSpace(w_4_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_31_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[32] * z_perm + writeProofPointIntoScratchSpace(z_perm_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_32_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[33] * lookup_inverses + writeProofPointIntoScratchSpace(lookup_inverses_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_33_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[34] * lookup_read_counts + writeProofPointIntoScratchSpace(lookup_read_counts_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_34_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[35] * lookup_read_tags + writeProofPointIntoScratchSpace(lookup_read_tags_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_35_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // To be shifted accumulators + // Accumulator = accumulator + scalar[36] * table_1 + mcopy(G1_LOCATION, table_1_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_36_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[37] * table_2 + mcopy(G1_LOCATION, table_2_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_37_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[38] * table_3 + mcopy(G1_LOCATION, table_3_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_38_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[39] * table_4 + mcopy(G1_LOCATION, table_4_x_loc, 0x40) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_39_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[40] * w_l + writeProofPointIntoScratchSpace(w_l_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_40_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[41] * w_r + writeProofPointIntoScratchSpace(w_r_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_41_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[42] * w_o + writeProofPointIntoScratchSpace(w_o_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_42_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // Accumulator = accumulator + scalar[43] * w_4 + writeProofPointIntoScratchSpace(w_4_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_43_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[44] * z_perm + writeProofPointIntoScratchSpace(z_perm_x0_loc) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_44_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + } + + // TODO(md): there is no reason that this isnt done before the accumulation above + // Batch gemini claims from the prover + + // WORKTODO: note we can reuse all of the batch scalar memory locations up to 44 at this point + // We can also accumulate commitments in place + + { + + let constantTermAcc := 0 + let shplonkNu := mload(SHPLONK_NU_CHALLENGE) + let batchingChallenge2 := mulmod(shplonkNu, shplonkNu , p) + + // TOOD: unwrap??? + let bound := sub(LOG_N, 2) + for {let i := 0} lt(i, CONST_PROOF_SIZE_LOG_N) {i := add(i, 1)} { + off := mul(i, 0x20) + let vanishing_evals_off := add(INVERTED_GEMINI_DENOMINATOR_2_LOC, off) + let scalarOff := add(BATCH_SCALAR_0_LOC, off) + let evaluationsOff := add(GEMINI_A_EVAL_1, off) + + // i >= LOG_N -1 + let scalingFactor := 0 // update + + // TODO: optimise + let dum := gt(i, bound) + if iszero(dum) { + scalingFactor := mulmod(batchingChallenge2, mload(vanishing_evals_off), p) + } + // If the scalingFactor is 0, this will be 0 as (p mod p == 0 mod p) + mstore(scalarOff, sub(p, scalingFactor)) + + constantTermAcc := addmod(constantTermAcc, mulmod(scalingFactor, mload(evaluationsOff), p), p) + batchingChallenge2 := mulmod(batchingChallenge2, shplonkNu, p) + } + mstore(CONSTANT_TERM_ACCUMULATOR_LOC, constantTermAcc) + } + + // Accumulate these LOG_N scalars with the gemini fold univariates + { + { + // accumulator = accumulator + scalar[45] * gemini_fold_univariates[0] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_0_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_0_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[46] * gemini_fold_univariates[1] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_1_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_1_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[47] * gemini_fold_univariates[2] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_2_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_2_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[48] * gemini_fold_univariates[3] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_3_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_3_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[49] * gemini_fold_univariates[4] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_4_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_4_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + } + + { + // accumulator = accumulator + scalar[50] * gemini_fold_univariates[5] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_5_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_5_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[51] * gemini_fold_univariates[6] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_6_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_6_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[52] * gemini_fold_univariates[7] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_7_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_7_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[53] * gemini_fold_univariates[8] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_8_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_8_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[54] * gemini_fold_univariates[9] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_9_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_9_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[55] * gemini_fold_univariates[10] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_10_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_10_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + } + + { + // accumulator = accumulator + scalar[56] * gemini_fold_univariates[11] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_11_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_11_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[57] * gemini_fold_univariates[12] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_12_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_12_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[58] * gemini_fold_univariates[13] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_13_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_13_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[59] * gemini_fold_univariates[14] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_14_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_14_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[60] * gemini_fold_univariates[15] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_15_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_15_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + } + + + { + // accumulator = accumulator + scalar[61] * gemini_fold_univariates[16] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_16_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_16_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[62] * gemini_fold_univariates[17] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_17_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_17_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[63] * gemini_fold_univariates[18] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_18_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_18_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[64] * gemini_fold_univariates[19] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_19_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_19_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[65] * gemini_fold_univariates[20] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_20_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_20_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + } + + { + + // accumulator = accumulator + scalar[66] * gemini_fold_univariates[21] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_21_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_21_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[67] * gemini_fold_univariates[22] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_22_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_22_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[68] * gemini_fold_univariates[23] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_23_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_23_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[69] * gemini_fold_univariates[24] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_24_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_24_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[70] * gemini_fold_univariates[25] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_25_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_25_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + // accumulator = accumulator + scalar[71] * gemini_fold_univariates[26] + writeProofPointIntoScratchSpace(GEMINI_FOLD_UNIVARIATE_26_X0_LOC) + mstore(SCALAR_LOCATION, mload(BATCH_SCALAR_26_LOC)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + } + + } + + + // TODO: bundle this batch inversion with the other batch inversions + // Yet another batched inversion + // We need to invert (1 - u) + u + // This u value is known earlier in the code as it calculated in the transcript + // So we can perforn the inversion earlier + // Although a modexp is only 200 gas so it doesnt cost that much + + // Batch invert the (1 - u) + u for each LOG_N u values - LOG_N is 15 for this program + { + let p_plus_one := add(p, 1) + // WARNING: We overwrite the SUM_U_CHALLENGES HERE + // TODO: write aliases for these variables + // Explain at the top of the file why we have used an alias for the value + let u := mload(SUM_U_CHALLENGE_14) + let pow := mload(POWERS_OF_EVALUATION_CHALLENGE_14_LOC) + // OPT: P + 1 in here should be a constant + let product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_14_LOC, product) + accumulator := product + + mstore(BATCH_ACCUMULATOR_0_LOC, accumulator) + u := mload(SUM_U_CHALLENGE_13) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_13_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_13_LOC, product) + accumulator := mulmod(accumulator, product, p) + + mstore(BATCH_ACCUMULATOR_1_LOC, accumulator) + u := mload(SUM_U_CHALLENGE_12) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_12_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_12_LOC, product) + accumulator := mulmod(accumulator, product, p) + + mstore(BATCH_ACCUMULATOR_2_LOC, accumulator) + u := mload(SUM_U_CHALLENGE_11) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_11_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_11_LOC, product) + accumulator := mulmod(accumulator, product, p) + + mstore(BATCH_ACCUMULATOR_3_LOC, accumulator) + u := mload(SUM_U_CHALLENGE_10) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_10_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_10_LOC, product) + accumulator := mulmod(accumulator, product, p) + + mstore(BATCH_ACCUMULATOR_4_LOC, accumulator) + u := mload(SUM_U_CHALLENGE_9) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_9_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_9_LOC, product) + accumulator := mulmod(accumulator, product, p) + + mstore(BATCH_ACCUMULATOR_5_LOC, accumulator) + u := mload(SUM_U_CHALLENGE_8) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_8_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_8_LOC, product) + accumulator := mulmod(accumulator, product, p) + + mstore(BATCH_ACCUMULATOR_6_LOC, accumulator) + u := mload(SUM_U_CHALLENGE_7) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_7_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_7_LOC, product) + accumulator := mulmod(accumulator, product, p) + + mstore(BATCH_ACCUMULATOR_7_LOC, accumulator) + u := mload(SUM_U_CHALLENGE_6) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_6_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_6_LOC, product) + accumulator := mulmod(accumulator, product, p) + + mstore(BATCH_ACCUMULATOR_8_LOC, accumulator) + u := mload(SUM_U_CHALLENGE_5) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_5_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_5_LOC, product) + accumulator := mulmod(accumulator, product, p) + + let t9 := accumulator + u := mload(SUM_U_CHALLENGE_4) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_4_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_4_LOC, product) + accumulator := mulmod(accumulator, product, p) + + let t10 := accumulator + u := mload(SUM_U_CHALLENGE_3) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_3_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_3_LOC, product) + accumulator := mulmod(accumulator, product, p) + + let t11 := accumulator + u := mload(SUM_U_CHALLENGE_2) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_2_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_2_LOC, product) + accumulator := mulmod(accumulator, product, p) + + let t12 := accumulator + u := mload(SUM_U_CHALLENGE_1) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_1_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_1_LOC, product) + accumulator := mulmod(accumulator, product, p) + + let t13 := accumulator + u := mload(SUM_U_CHALLENGE_0) + pow := mload(POWERS_OF_EVALUATION_CHALLENGE_0_LOC) + product := addmod(mulmod(sub(p_plus_one, u), pow, p), u, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_0_LOC, product) + accumulator := mulmod(accumulator, product, p) + + { + // There is an accumulator for batchMUL stored within 0x00 -> 0x3f + mstore(0x40, 0x20) + mstore(0x60, 0x20) + mstore(0x80, 0x20) + mstore(0xa0, accumulator) + mstore(0xc0, sub(p, 2)) + mstore(0xe0, p) + if iszero(staticcall(gas(), 0x05, 0x40, 0xe0, 0x40, 0x20)) { + mstore(0x00, MODEXP_FAILED_SELECTOR) + revert(0x00, 0x04) + } + accumulator := mload(0x40) + } + + // TODO: as noted above - alias the sum us + t13 := mulmod(accumulator, t13, p) + let temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_0_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_0_LOC, t13) + + accumulator := mulmod(accumulator, temp, p) + + t12 := mulmod(accumulator, t12, p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_1_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_1_LOC, t12) + + accumulator := mulmod(accumulator, temp, p) + + t11 := mulmod(accumulator, t11, p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_2_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_2_LOC, t11) + + accumulator := mulmod(accumulator, temp, p) + + t10 := mulmod(accumulator, t10, p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_3_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_3_LOC, t10) + + accumulator := mulmod(accumulator, temp, p) + + t9 := mulmod(accumulator, t9, p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_4_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_4_LOC, t9) + + accumulator := mulmod(accumulator, temp, p) + + let t8 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_8_LOC), p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_5_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_5_LOC, t8) + + accumulator := mulmod(accumulator, temp, p) + + let t7 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_7_LOC), p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_6_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_6_LOC, t7) + + accumulator := mulmod(accumulator, temp, p) + + let t6 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_6_LOC), p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_7_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_7_LOC, t6) + + accumulator := mulmod(accumulator, temp, p) + + let t5 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_5_LOC), p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_8_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_8_LOC, t5) + + accumulator := mulmod(accumulator, temp, p) + + let t4 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_4_LOC), p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_9_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_9_LOC, t4) + + accumulator := mulmod(accumulator, temp, p) + + let t3 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_3_LOC), p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_10_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_10_LOC, t3) + + accumulator := mulmod(accumulator, temp, p) + + let t2 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_2_LOC), p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_11_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_11_LOC, t2) + + accumulator := mulmod(accumulator, temp, p) + + let t1 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_1_LOC), p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_12_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_12_LOC, t1) + + accumulator := mulmod(accumulator, temp, p) + + let t0 := mulmod(accumulator, mload(BATCH_ACCUMULATOR_0_LOC), p) + temp := mload(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_13_LOC) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_13_LOC, t0) + + accumulator := mulmod(accumulator, temp, p) + mstore(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_14_LOC, accumulator) + } + + { + let batchedEvalRoundAcc := mload(BATCHED_EVALUATION_LOC) + + // Compute Gemini Batched Univariate Evaluation + for {let i := LOG_N} gt(i, 0) {i := sub(i, 1)} { + // TODO: opt + let p_plus_one := add(p, 1) + + // TODO: remove the sub 1 here + off := mul(sub(i, 1), 0x20) + + // TODO: think about how pow is used here: it is used in the above batch inversion + // so we probabaly want to avoid loading it to often + + let challPower := mload(add(POWERS_OF_EVALUATION_CHALLENGE_0_LOC, off)) + let u := mload(add(SUM_U_CHALLENGE_0, off)) + let inversion := mload(add(BATCHED_EVALUATION_ACCUMULATOR_INVERSION_0_LOC, off)) + let evalNeg := mload(add(GEMINI_A_EVAL_0, off)) + + batchedEvalRoundAcc := mulmod(challPower, + mulmod( + batchedEvalRoundAcc, + 2, + p + ), + p + ) + batchedEvalRoundAcc := addmod(batchedEvalRoundAcc, sub(p, + mulmod( + evalNeg, + sub( + mulmod(challPower, sub(p_plus_one, u), p), + u + ), + p + ) + ),p) + + batchedEvalRoundAcc := mulmod(batchedEvalRoundAcc, inversion, p) + } + + let a0Pos := batchedEvalRoundAcc + + let constantTermAcc := addmod(mload(CONSTANT_TERM_ACCUMULATOR_LOC), + mulmod( + a0Pos, + mload(INVERTED_GEMINI_DENOMINATOR_0_LOC), + p + ), + p + ) + constantTermAcc := addmod(constantTermAcc, + mulmod( + mload(GEMINI_A_EVAL_0), + mulmod( + mload(SHPLONK_NU_CHALLENGE), + mload(INVERTED_GEMINI_DENOMINATOR_1_LOC), + p + ), + p + ), + p + ) + + // Accumulate the constant term accumulator + // Accumulator = accumulator + 1 * costant term accumulator + mstore(G1_LOCATION, 0x01) + mstore(add(G1_LOCATION, 0x20), 0x02) + mstore(SCALAR_LOCATION, constantTermAcc) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + + + // Accumlate final quotient commitment into shplonk check + // Accumulator = accumulator + shplonkZ * quotient commitment + writeProofPointIntoScratchSpace(KZG_QUOTIENT_X0_LOC) + let x := mload(0x60) + let y := mload(0x80) + + mstore(SCALAR_LOCATION, mload(SHPLONK_Z_CHALLENGE)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 7, G1_LOCATION, 0x60, ACCUMULATOR_2, 0x40)) + precomp_success_flag := and(precomp_success_flag, staticcall(gas(), 6, ACCUMULATOR, 0x80, ACCUMULATOR, 0x40)) + } + + if iszero(precomp_success_flag) { + mstore(0x00, BATCH_ACCUMULATION_FAILED_SELECTOR) + revert(0x00, 0x04) + } + + { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + // NOTE: this was written to scratch space above, OPT? + // P_1 + let x, y := writeProofPointOntoStack(KZG_QUOTIENT_X0_LOC) + mstore(0xc0, x) + mstore(0xe0, sub(q, y)) + + // Move values around for the pairing check + // pairing check - layout TODO and prose + + // p_0 + mcopy(0x00, ACCUMULATOR, 0x40) + + // G2 [1] + mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) + mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + + // G2 [x] + mstore(0x100, 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) + mstore(0x120, 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) + mstore(0x140, 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) + mstore(0x160, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + + let pairing_success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) + if iszero(and(pairing_success, mload(0x00))) { + mstore(0x00, PAIRING_FAILED_SELECTOR) + revert(0x00, 0x04) + } + + } + { + mstore(0x00, 0x01) + return(0x00, 0x20) // Proof succeeded! + } } + } } diff --git a/barretenberg/sol/src/honk/optimised/generate_offsets.py b/barretenberg/sol/src/honk/optimised/generate_offsets.py old mode 100644 new mode 100755 index c6b03c2febf7..43232bb5f021 --- a/barretenberg/sol/src/honk/optimised/generate_offsets.py +++ b/barretenberg/sol/src/honk/optimised/generate_offsets.py @@ -3,59 +3,12 @@ ## A mini python script to help generate the locations in memory of the indicies requred to generate a proof vk_fr = [ - "vk_circuit_size", - "vk_num_public_inputs", - "vk_pub_inputs_offset", + "VK_CIRCUIT_SIZE", + "VK_NUM_PUBLIC_INPUTS", + "VK_PUB_INPUTS_OFFSET", ] vk_g1 = [ - "q_m", - "q_c", - "q_l", - "q_r", - "q_o", - "q_4", - "q_arith", - "q_delta_range", - "q_elliptic", - "q_aux", - "q_lookup", - "q_poseidon_2_external", - "q_poseidon_2_Inernal", - "sigma_1", - "sigma_2", - "sigma_3", - "sigma_4", - "id_1", - "id_2", - "id_3", - "id_4", - "table_1", - "table_2", - "table_3", - "table_4", - "lagrange_first", - "lagrange_last" -] - -proof_fr = [ - "proof_circuit_size", - "proof_num_public_inputs", - "proof_pub_inputs_offset", -] - -proof_g1 = [ - "w_l", - "w_r", - "w_o", - "lookup_read_counts", - "lookup_read_tags" - "lookup_inverses", - "z_perm", - "w_4", -] - -entities = [ "Q_M", "Q_C", "Q_L", @@ -63,10 +16,12 @@ "Q_O", "Q_4", "Q_ARITH", - "Q_RANGE", + "Q_DELTA_RANGE", "Q_ELLIPTIC", "Q_AUX", "Q_LOOKUP", + "Q_POSEIDON_2_EXTERNAL", + "Q_POSEIDON_2_INERNAL", "SIGMA_1", "SIGMA_2", "SIGMA_3", @@ -80,43 +35,94 @@ "TABLE_3", "TABLE_4", "LAGRANGE_FIRST", - "LAGRANGE_LAST", + "LAGRANGE_LAST" +] + +proof_fr = [ + "PROOF_CIRCUIT_SIZE", + "PROOF_NUM_PUBLIC_INPUTS", + "PROOF_PUB_INPUTS_OFFSET", +] + +proof_g1 = [ "W_L", "W_R", "W_O", + "LOOKUP_READ_COUNTS", + "LOOKUP_READ_TAGS", "W_4", + "LOOKUP_INVERSES", + "Z_PERM", +] + +entities = [ + "QM", + "QC", + "QL", + "QR", + "QO", + "Q4", + "QARITH", + "QRANGE", + "QELLIPTIC", + "QAUX", + "QLOOKUP", + "QPOSEIDON2_EXTERNAL", + "QPOSEIDON2_INTERNAL", + "SIGMA1", + "SIGMA2", + "SIGMA3", + "SIGMA4", + "ID1", + "ID2", + "ID3", + "ID4", + "TABLE1", + "TABLE2", + "TABLE3", + "TABLE4", + "LAGRANGE_FIRST", + "LAGRANGE_LAST", + "W1", + "W2", + "W3", + "W4", "Z_PERM", "LOOKUP_INVERSES", "LOOKUP_READ_COUNTS", "LOOKUP_READ_TAGS", - "TABLE_1_SHIFT", - "TABLE_2_SHIFT", - "TABLE_3_SHIFT", - "TABLE_4_SHIFT", - "W_L_SHIFT", - "W_R_SHIFT", - "W_O_SHIFT", - "W_4_SHIFT", + "TABLE1_SHIFT", + "TABLE2_SHIFT", + "TABLE3_SHIFT", + "TABLE4_SHIFT", + "W1_SHIFT", + "W2_SHIFT", + "W3_SHIFT", + "W4_SHIFT", "Z_PERM_SHIFT" ] challenges = [ - "eta", - "eta_two", - "eta_three", - "beta", - "gamma", - "rho", - - #zm - "zm_x", - "zm_y", - "zm_Z", - "zm_quotient", - "public_inputs_delta" + # Sumcheck + relations + "ETA", + "ETA_TWO", + "ETA_THREE", + "BETA", + "GAMMA", + "RHO", + + # shplemini + "GEMINI_R", + "SHPLONK_NU", + "SHPLONK_Z", + + # public inputs + "PUBLIC_INPUTS_DELTA_NUMERATOR", + "PUBLIC_INPUTS_DELTA_DENOMINATOR" ] + # Generate the verification key memory locations, leaving plenty of room for scratch space def print_loc(pointer: int, name: str): @@ -128,14 +134,14 @@ def print_fr(pointer:int , name: str): # Smalle g1 is releavant to the points in the verification key def print_small_g1(pointer:int, name: str): - print_loc(pointer, name + "_x_loc") - print_loc(pointer + 32, name + "_y_loc") + print_loc(pointer, name + "_X_LOC") + print_loc(pointer + 32, name + "_Y_LOC") def print_g1(pointer: int, name: str): - print_loc(pointer, name + "_x0_loc") - print_loc(pointer + 32, name + "_x1_loc") - print_loc(pointer + 64, name + "_y0_loc") - print_loc(pointer + 96, name + "_y1_loc") + print_loc(pointer, name + "_X0_LOC") + print_loc(pointer + 32, name + "_X1_LOC") + print_loc(pointer + 64, name + "_Y0_LOC") + print_loc(pointer + 96, name + "_Y1_LOC") def print_vk(pointer: int): @@ -171,7 +177,7 @@ def print_proof(pointer: int): def print_sumcheck_univariates(pointer: int): for relation_len in range(0, BATCHED_RELATION_PARTIAL_LENGTH): for size in range(0, PROOF_SIZE_LOG_N): - name = "sumcheck_univariate_" + str(relation_len) + "_" + str(size) + name = "SUMCHECK_UNIVARIATE_" + str(relation_len) + "_" + str(size) + "_LOC" print_fr(pointer, name) pointer += 32 @@ -179,40 +185,100 @@ def print_sumcheck_univariates(pointer: int): def print_entities(pointer: int): for entity in entities: - print_fr(pointer, "eval_"+entity) + print_fr(pointer, entity + "_EVAL_LOC") pointer += 32 return pointer -def print_zeromorph(pointer: int): - for size in range(0, PROOF_SIZE_LOG_N): - print_g1(pointer, "zm_cqs_" + str(size)) +def print_shplemini(pointer: int): + for size in range(0, PROOF_SIZE_LOG_N - 1): + print_g1(pointer, "GEMINI_FOLD_UNIVARIATE_" + str(size)) pointer += (4*32) - print_g1(pointer, "zm_cq") + for size in range(0, PROOF_SIZE_LOG_N): + print_fr(pointer, "GEMINI_A_EVAL_" + str(size)) + pointer += 32 + + print_g1(pointer, "SHPLONK_Q") pointer += 32 - print_g1(pointer, "zm_pi") + print_g1(pointer, "KZG_QUOTIENT") pointer += 32 return pointer def print_challenges(pointer: int): for chall in challenges: - print_fr(pointer, chall + "_challenge") + print_fr(pointer, chall + "_CHALLENGE") pointer += 32 for alpha in range(0, NUMBER_OF_ALPHAS): - print_fr(pointer, "alpha_challenge_" + str(alpha)) + print_fr(pointer, "ALPHA_CHALLENGE_" + str(alpha)) pointer += 32 # TODO: this NOT THE PROOF SIZE LOG_N????? for gate in range(0, PROOF_SIZE_LOG_N): - print_fr(pointer, "gate_challenge_" + str(gate)) + print_fr(pointer, "GATE_CHALLENGE_" + str(gate)) pointer += 32 for sum_u in range(0, PROOF_SIZE_LOG_N): - print_fr(pointer, "sum_u_challenge_" + str(sum_u)) + print_fr(pointer, "SUM_U_CHALLENGE_" + str(sum_u)) + pointer += 32 + + return pointer + +BARYCENTRIC_DOMAIN_SIZE = 8 +def print_barycentric_domain(pointer: int): + for i in range(0, BARYCENTRIC_DOMAIN_SIZE): + print_fr(pointer, "BARYCENTRIC_LAGRANGE_DENOMINATOR_" + str(i) + "_LOC") + pointer += 32 + + for i in range(0, BARYCENTRIC_DOMAIN_SIZE): + print_fr(pointer, "BARYCENTRIC_DOMAIN_" + str(i) + "_LOC") + pointer += 32 + + for i in range(0, BARYCENTRIC_DOMAIN_SIZE): + print_fr(pointer, "BARYCENTRIC_DENOMINATOR_INVERSES_" + str(i) + "_LOC") + pointer += 32 + + return pointer + +def print_subrelation_eval(pointer: int): + for i in range(0, NUMBER_OF_SUBRELATIONS): + print_fr(pointer, "SUBRELATION_EVAL_" + str(i) + "_LOC") + pointer += 32 + + return pointer + +subrelation_intermediates = [ + "AUX_NON_NATIVE_FIELD_IDENTITY", + "AUX_LIMB_ACCUMULATOR_IDENTITY", + "AUX_RAM_CONSISTENCY_CHECK_IDENTITY", + "AUX_ROM_CONSISTENCY_CHECK_IDENTITY", + "AUX_MEMORY_CHECK_IDENTITY" +] + +general_intermediates = [ + "FINAL_ROUND_TARGET_LOC", + "POW_PARTIAL_EVALUATION_LOC", +] + + +def print_subrelation_intermediates(pointer: int): + for item in general_intermediates: + print_fr(pointer, item) + pointer += 32 + + for item in subrelation_intermediates: + print_fr(pointer, item) + pointer += 32 + + return pointer + +def print_batch_scalars(pointer: int): + BATCH_SIZE = 74 + for i in range(0, BATCH_SIZE): + print_fr(pointer, "BATCH_SCALAR_" + str(i) + "_LOC") pointer += 32 return pointer @@ -223,18 +289,47 @@ def main(): pointer = 0x380 # Print the verification key indicies + print("// Verification key indicies") pointer = print_vk(pointer) + print("") + print("// Proof indicies") + # Print the proof with the given indicies pointer = print_proof(pointer) + print("") + print("// Sumcheck univariates") pointer = print_sumcheck_univariates(pointer) + print("") + print("// Entities") pointer = print_entities(pointer) - pointer = print_zeromorph(pointer) + print("") + print("// Shplemini") + pointer = print_shplemini(pointer) + print("") + print("// Challenges") pointer = print_challenges(pointer) + print("") + print("// Barycentric domain") + pointer = print_barycentric_domain(pointer) + + print("") + print("// Subrelation evaluations") + pointer = print_subrelation_eval(pointer) + + print("") + print("// Subrelation intermediates") + pointer = print_subrelation_intermediates(pointer) + + # This is a temporary method to write where the batch scalars should be + # But in reality it will overlap with the sumcheck univariates + pointer = 0x6420 + pointer = print_batch_scalars(pointer) + main() diff --git a/barretenberg/sol/src/honk/utils.sol b/barretenberg/sol/src/honk/utils.sol index 4ace25db0462..c63b75e34a4f 100644 --- a/barretenberg/sol/src/honk/utils.sol +++ b/barretenberg/sol/src/honk/utils.sol @@ -43,7 +43,6 @@ function logAsmG1(string memory name, uint256 startPointer) pure { } function logG1(string memory name, Honk.G1ProofPoint memory point) pure { - // TODO: convert both to hex before printing to line up with cpp string memory x_0 = bytes32ToString(bytes32(point.x_0)); string memory x_1 = bytes32ToString(bytes32(point.x_1)); string memory y_0 = bytes32ToString(bytes32(point.y_0)); @@ -53,6 +52,16 @@ function logG1(string memory name, Honk.G1ProofPoint memory point) pure { console2.log(message); } +function logG1(string memory name, uint256 i, Honk.G1ProofPoint memory point) pure { + string memory x_0 = bytes32ToString(bytes32(point.x_0)); + string memory x_1 = bytes32ToString(bytes32(point.x_1)); + string memory y_0 = bytes32ToString(bytes32(point.y_0)); + string memory y_1 = bytes32ToString(bytes32(point.y_1)); + + string memory message = string(abi.encodePacked(" x: ", x_0, x_1, " y: ", y_0, y_1)); + console2.log(name, i, message); +} + function logG(string memory name, Honk.G1Point memory point) pure { // TODO: convert both to hex before printing to line up with cpp string memory x = bytes32ToString(bytes32(point.x)); diff --git a/barretenberg/sol/test/honk/blakeOpt.t.sol b/barretenberg/sol/test/honk/blakeOpt.t.sol index 0db44b2ebe3c..dc5da720bf4b 100644 --- a/barretenberg/sol/test/honk/blakeOpt.t.sol +++ b/barretenberg/sol/test/honk/blakeOpt.t.sol @@ -6,9 +6,8 @@ import "forge-std/console.sol"; contract BlakeOptTest is Test { // The base proof, without the public inputs - bytes proof = - hex"00000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000048A7D18CE712399825CFB40CD180D9D27E000000000000000000000000000000000021CD98351CCDC38890C0CB417BDDB3000000000000000000000000000000FED4E368E3185871FB3474CADA373761DE000000000000000000000000000000000021661929D7E463717A20655B7AF9BC000000000000000000000000000000B6F5D9DC03CF38C047D6165FF8C2C781D9000000000000000000000000000000000020176EF436F35AC608C0677982810C00000000000000000000000000000078491612A313CFFE291A4E834C39DEB9BD000000000000000000000000000000000011DC5E934EB0A1E74F8050C3C60DDA00000000000000000000000000000019DAF11B0607A0C5C30F574EB80CC2554600000000000000000000000000000000002CFC2EC0AE3B7ABFAB7C5182DFD317000000000000000000000000000000ADF632A35D955E9DA39783DBBE6FD98DA4000000000000000000000000000000000012B71E269C0A3A524BDE68DA168E40000000000000000000000000000000234F6784B7B0E4EBD2787C20125D5AF84500000000000000000000000000000000001326B11934E0018CBA4E8FFF3BBA3D000000000000000000000000000000655693C82A2D9F5E98FFE667B97475923400000000000000000000000000000000000F7C70310555CE93AD2C380C593A0900000000000000000000000000000036AC69F7F7D3E8DBE49400ACB9393B3A6800000000000000000000000000000000001552B0BE75FD4F74CA4254039FDEE4000000000000000000000000000000328F5DDF4DBC9DF00C72ACDB59B8210FB4000000000000000000000000000000000002AC50C5F14C1F469B4FBC0EE0AD91000000000000000000000000000000D9883290A5980A215A1724CAC64BE74F010000000000000000000000000000000000247045838549349E2BC4F9E46220B50000000000000000000000000000007DF070F2CEA4CB683011E1074C0D66EB87000000000000000000000000000000000006A6DDAD0316B9018BDA6482D2573B00000000000000000000000000000016006D816CBC999594E21BE0DC613C5274000000000000000000000000000000000021AF905EADE2B71129C1DD1DF6AC8200000000000000000000000000000029067CE14C0776EAEBBDF1942EA1BF955B00000000000000000000000000000000002FAE43C693AD80A0D41C1BADE794A4000000000000000000000000000000B336D49B3907B3290D430FC1CFBC9FEC6E00000000000000000000000000000000002E7A45FBAB6B7078996924D150EEA1000000000000000000000000000000F9484A9699E802A97C334D0AB7B66334CE00000000000000000000000000000000001F81242AF902BBF9667C20AF82411700B8E61B58199893E653318F81C972B030E5BE88FA17577E71D387D2052DFE752FAB685789180795D1FD1426FFB7E5ACF74E29BF7FA21912D20E6DC1EAD2018C20684A2A70435AB52A734E978123EBFD8F1F344ECEEB3655056308880E71142E001C6A3501D4686BC2FBD90A7580E1CF9944724817BB78EFF01D27F7D8F64C8A290DB26FEA93E76D2401A048F84890D03665A05048CA14D6768A2527012D5C4123A67ADF897DE12809A3D9879437CF4DC8922D2DB79E49D377D4F18AB5D3089B1D0A46E90ABEFB8FB4EEDF5DD86EB85AE23BEEE207CB742C638FBEA8D8CE68DF14211A1F6A942683683FA187D45AB36E06AE82A81F3F49BFD98152CEAF9F99CC037659EA45F2F5B532ED2393D7953893A88089BA4D05F45E09B13725F7E44065287E1FE5D3044544D3805241B0026ADD91F0701147CA7785FBB2D480530F310504A812E3821DB34912485E2125D83E26035428FAB33801F669F3DD8401D3FFC9098CBE68D4E0CF2B8558F4580AAC2DE233ACC66957BC258F55ABB08B08989D9C1EB78D57BA2C0443A26CC332D71A18B1D9065C86C683262BF0F5C69D00A4FB980CF0A142421677706889B5847DAB25626476DFF25B75CFFC52CE056FBE96294B1BD9272DB7482E667AA8B32DE3653CA3A95F0CF3E78DD4EE097F614286B193CE1687BED2B684CBC3E526AB4886C415D125F13096CF0A1F4009B1AA6D8C4D59152DE9E877AB3E3BFD242DDF7596426B3BFD5D75378F6A3C9AE66DD058DDACB66712376D7D30411C69DE56277411B37FF74C4244AF09685D2AB00728CA5108D1DF276B321C4E05058A9255F9A4FC713BFEA178832997410CB938CFCE6371A728C2297E027859374E5D05E6DCE9A6BEA6A1B0BECE4AADBF8798779B7EF2318136FA2B8478FE29C23208983E9AC368EB38C78D17FEC81BC3424BE68AD185A66DB33D283B26C73C8FCDFDC63464C460F8E643944F0715239743ADE54C2109CA1CC36E1437D214A6262D974F6AF8B9070D063CE9CC04E9CA39EBA4324DCB7AAE2C49E518339576CF05F4F85A252883437A5099B1924551A2CFF68EF114841E0ED03E2E0C058649E3D08962B973F032466710676E44B9E5CA9BF1A6B74FCC1535CCAAD80082F724807573A8D8E26EEDE5B07C45CE36E649B6F2E4024928A318D9B3332B0E4445ED89665AF33F8EDF108444035E672974DE5F6A19E0BDCC274022892888214D4DDF92B05B00638F76DBB65358E770815BB07DA9F56B9B09CBAC68A107B029DA81C034B93247C0AD4188BB589982939E0A190F7BE22763B3E450EEC7D9FD1CD8681CB84DE3BD794F96E32C78DB1F5CA5877FEE874423B96C58B4E47E9B3B20AD8F6B62355E31FD671934FD320628E5940C299870E0A372E4FCA2C1FFEEE30EF6B69937B9CAD10BA9E3F71EA12B16255F5890A6245D5F782DF0D3D5279A8322BD6A9624364D328D3B1752FC69938B385D9245C9971519AAC533C1E61CF49208BDC0BF003FFFBE8747EC75B6EA3533651A1A193E4D5A97DB0C48F485CEAF4209F99EEFAB95EBB07DD1B9853B5E9CDC4DFAFE007254931159C163FE3FD8172C2CAEE447B3188A2AA0628B647AF7CE4B72244E74AA2DC8D30E0A61A55D401F491DD669160D372080CCB611EA3986655813E0146575BF2B792CA9BD0A7743B765074347D60B3A0C2C6D22B0A73A1DE35AA3D8F29EC41CCC55EBDCB19FFD71FF06297D78DEA14B293562CB5A0C86B2E42F0F694D24FEE90F7F10B4B04388B1C94B15328AB8C5767451B0C48552A27256DC39673527D415A6453351697BD58F61D60EF9C8862E07FE33F4C31BAA264C45B7C8312A1B380905C7C49CF9B249CDC0812B5AF215CAC0830C2FCE3D186707C4D0F1959B4F175F550DF604A51661B4868D297300CE3AD5AEDC4D3B6535834CD55C4812B2E001334500E2A9BB9EF3AF6B47106E243E92EAC29D90758C59F9A96F381FF528CC32DA8502AE0B64EAC78467092E9A48AADE85E9CA890BC72A3C1DB23741DF929E5F1E2B8F44195E35DBDE4865139F9FE8CC9B64DD5A37CE09FED0B071600FF60D19E2788809B78EB9DAFB52910044BFB4D8CD566B9EC7150103413023A02A7D2335D3D5ECFE6AE8089B006E3C1A464AFEE8925A4A9A6438B9F6F3B750E414F3A5329E86F8530BAEEFD31350F91848118319D37E726AF6D6B89C27CABD95C382AA999D3059B3561FB20ABB3ABB25B01A4F286C23F01F253FA2E35D85CF50E2D0121DC77F2537D012E7F450B1D726FEEE196164848D64C1B6887EB26863AC9B34BFF52E3801E19B6F636410CB9024EC490C3582B4A8C2BEFF1BD578CFC1102CBDDC6243782C90D4F0EBB1D24B5506FF0E865EA5FF56B675C0444C5F99A5939B2279329A5263B3CA4AB4778CA17A272943F046234444D1DAFBE2AF8393E241F89D0ADBDCD8B1B5168DFA4338B19A1B0670B185E3650DE08F16593B9C4B63C6019A99CCE67C18F917E9CD085647620C0C5D32AB8AE3B7BF472082F8C51F0BC7419450CF4935D0B1A4DF1137D2297E039745B55D2F64411A2D0B6CFAD956FDA9EEE1B3CDC3779CBC0A1053F201D2541DCB454EE033C2D5190FFAB5D3034DF2F84C703C52026A65634A5CB17D93F14B023223996FBB60FDEC7F2B1AEC1A7453615E77BB74517CBE1316CDAD94B8A1D017718AEECCD78FEF11F9224083FE8BECDC982C1AE6D9B067841682565CFEC312072E68370796CDEE0D766A120ECEDDD17AC56351535AC70AC1237D7AC5D914C20E038A674D28BB8028CAF3EB18FA868686FCA24633760AF581538CC9E1B7139908E9C011B2E92592B18D907B686C037EB0DF5C5EE96F83C4308F920DAD4757AB23FFCCD1B459B6D12D9C2D13A587A423AABABD2CB16DA836AC71C672B54F64A103A39C574894CC925267A977E86F72F0FB88DB760EF49AA4B3AEC55B694EA6A71A7765A58882F7F906E6A1EF55FAE742172866CE29E4AD627B0D770F457C708311AD952904E358D8D8577649493EEF8F6ACBF5610133C568C96F82B04142E2950F68028ADA72D90216B0F3417DD64FB05C6A545A4D59C99A193C5296B07A1FBB29803F7FB6A94C6EC188597385D7C9625921B2288A43CE3D1784B17F6DA5B81E21AD42A1ADFE17B661E2063A8035B268B0E25D19D80251AF1023D7C3DB32094A1E96032D369C13F99957CAE4EF63F80329291E40D482EE9252E3459DEF9048BD00C9F7AE4E41E17817694F16B13FB4E3C0BCE5F6B7580D4CBBDFF2AD442024A52385E667D2CF671DDEA153684E944651879A5A7B910F94F013DE25B48530C8A8232317438D3D3C53BA08F8D390EAB0DBC6CDF09730193CFAC83D9F41B037F68F155A2E3BB557CCDA5A3AF6FF71300864BA0F14FE50FEEF015D8ED8A0697E7DF21E91D5527F8741C165D4E2E7686B74EABD061C96F93151067D9D3D743E5CE50205E5836118CBE9C7C2FD8544DA890D18FD854BA624855459ABE9C32A1AE4B73D1B27C0C90B8A9E3E48DFF6CF1F45ED19A4802153F6C1EB8A2EEF5A1536E569891932B8443AC3C45007A81CB33BC9E88359CFCC762AD3F52EECF60A4AEC4DAB2A23FB5DA0429DDFF20BFBAE5F52AE3F9959789984CF9A1B066E5981FB2AE00BD92F4FB3A346E76E8B8D9E9686792F26E172B9DD7DC16AF0D43F3A9357F29C89160D8009C3AF5564E0EBF157F2FC12C648EE2484A4DBC185625EBB487CD348A85C16044AE36F191C77BD1B2CD842B815A199757606D40C620A8380823E971C492109FCE6AFFB23E01015602EDE0665C627BE6FD7A9A6792E9672985B5E57344DD004F85F617219CA3840E09B6DCC0B7AC1852DE9DD8A422F11CAD9EB54EA29499122D0E152333086F761DAAB64068752B3871F418D9C029C3889AFE2FB325DB88912F40763FC90950B744566EBE1FA186B1767F7B7A1D0398DAAA40681E33445F51E1417E5CAF625DD9BACAA951221515220C17A6252FBC2F9925BA31CD8CCA23B29EF1482C638845CE92E35B7308E2AB513452B74F4F1674922CF182E4E402D4503CDC9494AB4F97E7AB0FB12FD3E122579DFEF559A8904278249A72553B3E1FE17F20CEB9A62706199FB5E92CFA5CA2278E28FE3F2F7518236100B7B58EBB5D725C37E4ED9C8948688DF6412AE9CDA20A45B0499FBBB335339BDDF6A878B8360091E3632EF4BFAA016979CBAA3BA8FF275F14A3C64CCA1185236C6F20E5058141F181C3CAEB05CCABC57671867F7442FAB7D8C88D71733CDF5908741D0A3BCED17E24C215F2A83BE60E1790591C6206D5D7E8A30ABCD852CEADB2E596BC330DA0FC90C06BE7EAF56ED66D2E9EB96E0D2E3FFBF985D08D7B559C8492DE7D84C9F1764E3476E332EA11912D1EDC5EAAA792C4BFDF44A990A0E34DC88DDC4517B9627DC7D90D6C81E65003064636AC0E35224020A9B2026607C8FE9D9F7FDA76B060077254E44E2A32A4CEA03B3490F6E966734A86CA424EEF554D9951655F3062B218256B95C69A079FB1A1F286FF949CB30A5785D4829189291D9330C0567406921992640E74093E9B9A382B13E54E9C0599F0C1C8C6715664F263A50A5EF9027035C6D04204344E07688BA79F15A25708200C326AFFF3C017290843C96D3ED342D5929E21363EF64CCE488E9DCCD0D7E318486FD63E2B6E0D1B7F63AF8FED872119091A333B824BF5ED6C711C0FB1896EC6E1A89F7032E133561973CC37E2BCA0B613C18FA38588CF6DDE1DE955DBA5E340475BE433A8709F4C45D943B8709801A10593F9D106220F46E6724722B31000FF19C8B203E0A1E32F7F1B9439BB9D22F32183C98799F1D2FEDDD285E73AC2D630F8D3A8DEA5F450559C6AF8902814C04C93312A859E3F82093C38CA1425EE04D006AB11F7E6C87E22DADE0B1EF2BB7047EA35893A1B797D41299DAA2BE691890F38C2A10374450520F83F1A3D21A04147C11EA15DDF41F4B5CE97283B1DBDD44C80BAE018C16FF020BAC03462CC25027051049BBA632E03BF036AF771CAD0711D2979D3D0A373B7665E7F04504CAF905C047996F3EDAC08E34CCE97F27046FE46473172E679300C4461323034D211727724596D21BC211E313E7A9A462EACB51F7378C6D9C001CC85F61EFEA7B5FB711690F5437BDC5B439ED07A6FD6E9A14FC7425627963DF7119365C492129D1A117FD2B3B76F980F85D3C8C11A9DF6720D3E1241AC640C0C0FE39BF9B47474A5702C4644B3AA14312074F41F61504E9E1291149050714E61E59AFEB376296D7730D2F202B550C11A495764B30BFC3BD62FCE2942E5F067438D7D25486437DA1961D805789A7432A8C8D1643C0930BB2A626CD1DF3E58FFEB48DECBE035E0F10652A845FA234AB9FADF190B02B1262F3575F8AD43B89990D268E9BDBC547525A21291B134D16E81FADA18BFF8BBCE000412D8DB7AC2B6112F65C54FC3DD9353EE7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FB55CB12EE8B51E19C6BE590AD7838ABB4A42A02B3B241386AA8C2D62A14BC2221BF2EFC73AB6D71D1592E2CC6DBF3FD8666A0880EBA9B23B272E24465D759208853B518D42171DA6A4DBEDF815D6ACD648BF263ADFD924D6F81454A8136D5416F04F72788F02256D43678197B7917FBC516BAA71CCB9E6861AAE5C4A48547500C525F26A0716D1D5E02561150C83DD60126CAF0FDE6AB1C8D7518BA11B40AD23C2B1EAB1B990134834A6C544955E06C91716A33CB57C968500A02D6A2970DF2330793863C1DA938188C0E5A219507622A73E7120A27013288E68645BEF70B326124DA926B9AC40A8FEF05DD96550966E946B6B9C541441F3BAE57EB044939825AE459813D6BF051F7A63716E826492B4D04EBA086D341434112731F6E268F21DD01C2F32816B0CB7B65248996582BAEDA8DB5FFA9217BA9C106E2FB3D225161CA0FCAB818619B0CCDB3060C7B186D89BB846697D6B081C90DA5E6673DE11CD1520EEAB9747DE29E84519E23583370E2B3E44D6C505FE0CB3D9028BE08964CA004CDCE24681F0FFDAF12180D9E610C7818D2614AB462A7B5CD8222F2E26DC5B0C156D39477F3BE7D22BB593FB28B414260BFA74D43A56228D1E1404CDA012542568E79723C116B9720607F1F911F77551BE57EDF7913B5FF076ECDBC4D16B121D93DCFC5DFC299CB45F43BF66EC84A568136E5CBF05E72ADB5371560AF19B330AA5A243C70F2C75F1DFF03D4ED4F743FE239606B381D6D4A80D7DE44BE148742F1BD60B5785B92AFF68163039965D258607CD5C3259C059801D7C69B51DAA432BD5F5AAC52FDE2F8FF6DBD84D80288DE50DCBCAA04041775298E24D4BF60C35105DD397A38F94CFB3E19B7168AE43C7CA8953F3CB428A8BCF311D85906CE3670BE6610333FF6EC1B9AFC3CA034D87EE7770016BAAC0601108709C1B64B411FA245683A114925A35BE66E8D7710C527CD7842ABB0F4A3C1FB1CC4E0083BF09E31F0C969CB73BB275844F2819F17AD24E03821538A3213AF8104C166A46326A092D9E605064AAB127555C8F7A714090FB9E3D4BD1FC668FA45C84D20D7CC9513D0FE0FCF092D7C087148B7CCF9A89D7A96BBBFDA85FCDACB42FD8B0FB6F8B6ACD08F2A51909B57015E7F22615152A0E0E6418FB5730298A4A3D20A49BA7F6C7A7173AF17C423CA177FB83C81DDD11F6EC7CDD2B5EB9814B87830EBD3936D0E4F9119D602F577EC3A299C6419F60183E663EBD37154C77BDF8ACECF4A674DE6F93294CCFFCDA8E827D06A164264408615BAA0B43958F5AD4450A22580AF81BFB8506337806EA715E8FFB0B619C43C49FC40E6C2CBD53D74B9B547B6DC04567B0E105EF5C23727F9867A752CDF4D566E9A182DCDE7BA79FE7AEB959B349D4629605139ABED96C125903EE00ECF3F51190132E9D7DEB7C6ABC5632FF21675E35C57F198B70FAF7DB28F3BDF16069B38186C69A58710227ADFD3CC98F8C5ED7A3DE143017D4A776BD1FB14E53A5D4C54A3316B12BB5CAC261318D689F2C49A95D996A0C16A9D74E502F28AD146968F1713A6F67296FCD727F15854313595629CE392611AC6026BA0A85004A92210CF7A9EA18FF9D494DD557CB294BCC15981332F0BA1478B6BA2BAC583A1C623AF44E3C0BB8C779FCA33F9EF821D4B684D70059466B1A9242B8CB4DBA031269C8FD0EA3AE4946958AF78C4BFFEB579014D276BB527D2D220B1516959C7A3F868A937FADCB735D9443C4BC35CCDDEA7456C2F129CD971A10CFD8D402DCF93650FDE19A8A7FB8AAB7ECB88322C03C4108C5AE51109CCA21C95F8185DED1478D8FF48868E625F47D931F99705B0C075C58FF634A9BA4901739B97AC7DB98F3215DE604524D65CB6337ECB6E41C95D528CA08A19E8EB1070727705B86DC4F39A2F374A5D1C37D3821040B9D5B70B59B136E7409627BC0AB12CA004CAED2C49C47BB849D57E1073C493522A05181029D3CBDB08083BBDDB1000000000000000000000000000000326C38466A5C1BB34AFD6B9F40DF68CA5D000000000000000000000000000000000026FD15D9130F14FBEE2E0D726A637C00000000000000000000000000000098EEE1B55F682003FC26741D8CFB20479400000000000000000000000000000000002836ACD0816B87A4424F80FAD066B20000000000000000000000000000000BCD294161490327C5F767B1A6DF6D1CAF00000000000000000000000000000000002DD5F1289F67EDD3AEDD276B0404B7000000000000000000000000000000542B4FEC217039C45953A7E19A727832420000000000000000000000000000000000047600F1EA0E157DFCA4B31BB5EE87000000000000000000000000000000317F2002B9A8AF09564810144FB5A1448000000000000000000000000000000000000AC63B21EF17EB766F8EFEC095E2880000000000000000000000000000005606F66723DB3BB1189B661AB8137E4E120000000000000000000000000000000000012890BEE421ABDA5827BC16E2725D000000000000000000000000000000F429C874FD7EE8A54A2B8C001BA0F10A8D00000000000000000000000000000000002417E80A2C9244A7845EBCB5CC94AA000000000000000000000000000000A15095571E300AD10970C9E3BF5810101B00000000000000000000000000000000001ABA9EBCD1A053721931ACDFB336C0000000000000000000000000000000C04CA850ADD72954C29DEE4EE56EAE19730000000000000000000000000000000000138ECC957CB8A8E487B8B4341FE5C5000000000000000000000000000000D66D981195E2E0250122F98E1D25DAE56A00000000000000000000000000000000000DBFEAFBF8DD751F489B243458DF03000000000000000000000000000000E2C04DCBE113A4210CD577B72FB20C72A90000000000000000000000000000000000034991D7F50F5D2FE247B3EB7812430000000000000000000000000000000FF92CCE2007B30D86D4B40C24B7B3CE960000000000000000000000000000000000049D5E161DDD4CACDF3CDE221874A0000000000000000000000000000000250FEDD4E2547CB91AF3F7CE4A3750BE83000000000000000000000000000000000000F1C47E22BB218799C1B6A8FD47E400000000000000000000000000000024F1B10AEB12701A5FF4EB35165C614A050000000000000000000000000000000000227D988F3644548FC9F98D26BFDBF30000000000000000000000000000008A12177EB15BCD47DB39539D71D9E1B5A1000000000000000000000000000000000003EDFB88E732723AEAE60A03F74B10000000000000000000000000000000DD1DCC97B9484E0AC156C5F388D470A88800000000000000000000000000000000000D5B8AD798D66534EEBD59D49E369100000000000000000000000000000017F5E6EFAF783B4C9407A09E6FB8BB49B6000000000000000000000000000000000023C23647CDACAD4E298E0E276625530000000000000000000000000000003C62524C10B3DCB0E9F38FB56648F3472E000000000000000000000000000000000014D783F98D74F28824C896185158320000000000000000000000000000006858EBB4C276A3238B7A33D4660DF1FC1700000000000000000000000000000000000CE87D898C3293C11016FCAAB24204000000000000000000000000000000F57EE6406087F4E4C4162141C73BC7B616000000000000000000000000000000000007FB3E08B56B2CE73DA7BEDD6A1F6D0000000000000000000000000000004EE22282A3D21116CB02F4CCC38E860FE20000000000000000000000000000000000107BBA42D90EE46133D31433B8EB19000000000000000000000000000000C40C16DE32312EE6B442DE1587E2A521390000000000000000000000000000000000275E8C801593B8133D81E8019B76830000000000000000000000000000004DBBA681792C938B0791D82AB3C5DD040300000000000000000000000000000000000567B7124F9096012D07F0AC4B3324000000000000000000000000000000944E7C8417401D4761CE4B8881D68513210000000000000000000000000000000000187C3BAC5A378EC6E3857B427E06760000000000000000000000000000004CEFF0535DFC03E966B4A6487FDD69FD25000000000000000000000000000000000029FE419E36A89DEDA5D998E804A49C0000000000000000000000000000005966B853B10D24506C108700D811F577150000000000000000000000000000000000242A7F7BCDA3739C02BC8424C987E000000000000000000000000000000009F2D0C8375C093BE4E8193F02AD05026400000000000000000000000000000000000D0FEC8DC0FA81076F10281C32F15C000000000000000000000000000000565BC6144EE35BB9F284C8C09CB8725833000000000000000000000000000000000026F82CE3DA6578410C2013EB0A8073000000000000000000000000000000534C12D36AC8DED5EA874CE10AB44E507F000000000000000000000000000000000028884281C4B09F056D3B4194668250000000000000000000000000000000FCCC3483B46824AA1BB481E420C403DCF100000000000000000000000000000000001964A1131F0DE57B613DCA32967B5E00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F9853B4F3F917331D74D259C10608306F0000000000000000000000000000000000269B1DAE9B18D707A85A24E344593200000000000000000000000000000073A16FFC3E0B31779B15A3ACB0FC17FA2A0000000000000000000000000000000000152A4AEB8124CE68909B3544F130C4000000000000000000000000000000BA08B9ADF036EC5594FE1AC363B8E10B5A000000000000000000000000000000000022238F4C7A2CE483B73FD40EB3FCDB000000000000000000000000000000A7F11964B03C3CE244DCAB490326202AD600000000000000000000000000000000000F07B44943550683F9AF5C04988047"; + hex"00000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000048A7D18CE712399825CFB40CD180D9D27E000000000000000000000000000000000021CD98351CCDC38890C0CB417BDDB3000000000000000000000000000000FED4E368E3185871FB3474CADA373761DE000000000000000000000000000000000021661929D7E463717A20655B7AF9BC000000000000000000000000000000B6F5D9DC03CF38C047D6165FF8C2C781D9000000000000000000000000000000000020176EF436F35AC608C0677982810C00000000000000000000000000000078491612A313CFFE291A4E834C39DEB9BD000000000000000000000000000000000011DC5E934EB0A1E74F8050C3C60DDA00000000000000000000000000000019DAF11B0607A0C5C30F574EB80CC2554600000000000000000000000000000000002CFC2EC0AE3B7ABFAB7C5182DFD317000000000000000000000000000000ADF632A35D955E9DA39783DBBE6FD98DA4000000000000000000000000000000000012B71E269C0A3A524BDE68DA168E40000000000000000000000000000000234F6784B7B0E4EBD2787C20125D5AF84500000000000000000000000000000000001326B11934E0018CBA4E8FFF3BBA3D000000000000000000000000000000655693C82A2D9F5E98FFE667B97475923400000000000000000000000000000000000F7C70310555CE93AD2C380C593A0900000000000000000000000000000036AC69F7F7D3E8DBE49400ACB9393B3A6800000000000000000000000000000000001552B0BE75FD4F74CA4254039FDEE4000000000000000000000000000000328F5DDF4DBC9DF00C72ACDB59B8210FB4000000000000000000000000000000000002AC50C5F14C1F469B4FBC0EE0AD91000000000000000000000000000000D9883290A5980A215A1724CAC64BE74F010000000000000000000000000000000000247045838549349E2BC4F9E46220B50000000000000000000000000000007DF070F2CEA4CB683011E1074C0D66EB87000000000000000000000000000000000006A6DDAD0316B9018BDA6482D2573B00000000000000000000000000000016006D816CBC999594E21BE0DC613C5274000000000000000000000000000000000021AF905EADE2B71129C1DD1DF6AC8200000000000000000000000000000029067CE14C0776EAEBBDF1942EA1BF955B00000000000000000000000000000000002FAE43C693AD80A0D41C1BADE794A4000000000000000000000000000000B336D49B3907B3290D430FC1CFBC9FEC6E00000000000000000000000000000000002E7A45FBAB6B7078996924D150EEA1000000000000000000000000000000F9484A9699E802A97C334D0AB7B66334CE00000000000000000000000000000000001F81242AF902BBF9667C20AF82411700B8E61B58199893E653318F81C972B030E5BE88FA17577E71D387D2052DFE752FAB685789180795D1FD1426FFB7E5ACF74E29BF7FA21912D20E6DC1EAD2018C20684A2A70435AB52A734E978123EBFD8F1F344ECEEB3655056308880E71142E001C6A3501D4686BC2FBD90A7580E1CF9944724817BB78EFF01D27F7D8F64C8A290DB26FEA93E76D2401A048F84890D03665A05048CA14D6768A2527012D5C4123A67ADF897DE12809A3D9879437CF4DC8922D2DB79E49D377D4F18AB5D3089B1D0A46E90ABEFB8FB4EEDF5DD86EB85AE23BEEE207CB742C638FBEA8D8CE68DF14211A1F6A942683683FA187D45AB36E06AE82A81F3F49BFD98152CEAF9F99CC037659EA45F2F5B532ED2393D7953893A88089BA4D05F45E09B13725F7E44065287E1FE5D3044544D3805241B0026ADD91F0701147CA7785FBB2D480530F310504A812E3821DB34912485E2125D83E26035428FAB33801F669F3DD8401D3FFC9098CBE68D4E0CF2B8558F4580AAC2DE233ACC66957BC258F55ABB08B08989D9C1EB78D57BA2C0443A26CC332D71A18B1D9065C86C683262BF0F5C69D00A4FB980CF0A142421677706889B5847DAB25626476DFF25B75CFFC52CE056FBE96294B1BD9272DB7482E667AA8B32DE3653CA3A95F0CF3E78DD4EE097F614286B193CE1687BED2B684CBC3E526AB4886C415D125F13096CF0A1F4009B1AA6D8C4D59152DE9E877AB3E3BFD242DDF7596426B3BFD5D75378F6A3C9AE66DD058DDACB66712376D7D30411C69DE56277411B37FF74C4244AF09685D2AB00728CA5108D1DF276B321C4E05058A9255F9A4FC713BFEA178832997410CB938CFCE6371A728C2297E027859374E5D05E6DCE9A6BEA6A1B0BECE4AADBF8798779B7EF2318136FA2B8478FE29C23208983E9AC368EB38C78D17FEC81BC3424BE68AD185A66DB33D283B26C73C8FCDFDC63464C460F8E643944F0715239743ADE54C2109CA1CC36E1437D214A6262D974F6AF8B9070D063CE9CC04E9CA39EBA4324DCB7AAE2C49E518339576CF05F4F85A252883437A5099B1924551A2CFF68EF114841E0ED03E2E0C058649E3D08962B973F032466710676E44B9E5CA9BF1A6B74FCC1535CCAAD80082F724807573A8D8E26EEDE5B07C45CE36E649B6F2E4024928A318D9B3332B0E4445ED89665AF33F8EDF108444035E672974DE5F6A19E0BDCC274022892888214D4DDF92B05B00638F76DBB65358E770815BB07DA9F56B9B09CBAC68A107B029DA81C034B93247C0AD4188BB589982939E0A190F7BE22763B3E450EEC7D9FD1CD8681CB84DE3BD794F96E32C78DB1F5CA5877FEE874423B96C58B4E47E9B3B20AD8F6B62355E31FD671934FD320628E5940C299870E0A372E4FCA2C1FFEEE30EF6B69937B9CAD10BA9E3F71EA12B16255F5890A6245D5F782DF0D3D5279A8322BD6A9624364D328D3B1752FC69938B385D9245C9971519AAC533C1E61CF49208BDC0BF003FFFBE8747EC75B6EA3533651A1A193E4D5A97DB0C48F485CEAF4209F99EEFAB95EBB07DD1B9853B5E9CDC4DFAFE007254931159C163FE3FD8172C2CAEE447B3188A2AA0628B647AF7CE4B72244E74AA2DC8D30E0A61A55D401F491DD669160D372080CCB611EA3986655813E0146575BF2B792CA9BD0A7743B765074347D60B3A0C2C6D22B0A73A1DE35AA3D8F29EC41CCC55EBDCB19FFD71FF06297D78DEA14B293562CB5A0C86B2E42F0F694D24FEE90F7F10B4B04388B1C94B15328AB8C5767451B0C48552A27256DC39673527D415A6453351697BD58F61D60EF9C8862E07FE33F4C31BAA264C45B7C8312A1B380905C7C49CF9B249CDC0812B5AF215CAC0830C2FCE3D186707C4D0F1959B4F175F550DF604A51661B4868D297300CE3AD5AEDC4D3B6535834CD55C4812B2E001334500E2A9BB9EF3AF6B47106E243E92EAC29D90758C59F9A96F381FF528CC32DA8502AE0B64EAC78467092E9A48AADE85E9CA890BC72A3C1DB23741DF929E5F1E2B8F44195E35DBDE4865139F9FE8CC9B64DD5A37CE09FED0B071600FF60D19E2788809B78EB9DAFB52910044BFB4D8CD566B9EC7150103413023A02A7D2335D3D5ECFE6AE8089B006E3C1A464AFEE8925A4A9A6438B9F6F3B750E414F3A5329E86F8530BAEEFD31350F91848118319D37E726AF6D6B89C27CABD95C382AA999D3059B3561FB20ABB3ABB25B01A4F286C23F01F253FA2E35D85CF50E2D0121DC77F2537D012E7F450B1D726FEEE196164848D64C1B6887EB26863AC9B34BFF52E3801E19B6F636410CB9024EC490C3582B4A8C2BEFF1BD578CFC1102CBDDC6243782C90D4F0EBB1D24B5506FF0E865EA5FF56B675C0444C5F99A5939B2279329A5263B3CA4AB4778CA17A272943F046234444D1DAFBE2AF8393E241F89D0ADBDCD8B1B5168DFA4338B19A1B0670B185E3650DE08F16593B9C4B63C6019A99CCE67C18F917E9CD085647620C0C5D32AB8AE3B7BF472082F8C51F0BC7419450CF4935D0B1A4DF1137D2297E039745B55D2F64411A2D0B6CFAD956FDA9EEE1B3CDC3779CBC0A1053F201D2541DCB454EE033C2D5190FFAB5D3034DF2F84C703C52026A65634A5CB17D93F14B023223996FBB60FDEC7F2B1AEC1A7453615E77BB74517CBE1316CDAD94B8A1D017718AEECCD78FEF11F9224083FE8BECDC982C1AE6D9B067841682565CFEC312072E68370796CDEE0D766A120ECEDDD17AC56351535AC70AC1237D7AC5D914C20E038A674D28BB8028CAF3EB18FA868686FCA24633760AF581538CC9E1B7139908E9C011B2E92592B18D907B686C037EB0DF5C5EE96F83C4308F920DAD4757AB23FFCCD1B459B6D12D9C2D13A587A423AABABD2CB16DA836AC71C672B54F64A103A39C574894CC925267A977E86F72F0FB88DB760EF49AA4B3AEC55B694EA6A71A7765A58882F7F906E6A1EF55FAE742172866CE29E4AD627B0D770F457C708311AD952904E358D8D8577649493EEF8F6ACBF5610133C568C96F82B04142E2950F68028ADA72D90216B0F3417DD64FB05C6A545A4D59C99A193C5296B07A1FBB29803F7FB6A94C6EC188597385D7C9625921B2288A43CE3D1784B17F6DA5B81E21AD42A1ADFE17B661E2063A8035B268B0E25D19D80251AF1023D7C3DB32094A1E96032D369C13F99957CAE4EF63F80329291E40D482EE9252E3459DEF9048BD00C9F7AE4E41E17817694F16B13FB4E3C0BCE5F6B7580D4CBBDFF2AD442024A52385E667D2CF671DDEA153684E944651879A5A7B910F94F013DE25B48530C8A8232317438D3D3C53BA08F8D390EAB0DBC6CDF09730193CFAC83D9F41B037F68F155A2E3BB557CCDA5A3AF6FF71300864BA0F14FE50FEEF015D8ED8A0697E7DF21E91D5527F8741C165D4E2E7686B74EABD061C96F93151067D9D3D743E5CE50205E5836118CBE9C7C2FD8544DA890D18FD854BA624855459ABE9C32A1AE4B73D1B27C0C90B8A9E3E48DFF6CF1F45ED19A4802153F6C1EB8A2EEF5A1536E569891932B8443AC3C45007A81CB33BC9E88359CFCC762AD3F52EECF60A4AEC4DAB2A23FB5DA0429DDFF20BFBAE5F52AE3F9959789984CF9A1B066E5981FB2AE00BD92F4FB3A346E76E8B8D9E9686792F26E172B9DD7DC16AF0D43F3A9357F29C89160D8009C3AF5564E0EBF157F2FC12C648EE2484A4DBC185625EBB487CD348A85C16044AE36F191C77BD1B2CD842B815A199757606D40C620A8380823E971C492109FCE6AFFB23E01015602EDE0665C627BE6FD7A9A6792E9672985B5E57344DD004F85F617219CA3840E09B6DCC0B7AC1852DE9DD8A422F11CAD9EB54EA29499122D0E152333086F761DAAB64068752B3871F418D9C029C3889AFE2FB325DB88912F40763FC90950B744566EBE1FA186B1767F7B7A1D0398DAAA40681E33445F51E1417E5CAF625DD9BACAA951221515220C17A6252FBC2F9925BA31CD8CCA23B29EF1482C638845CE92E35B7308E2AB513452B74F4F1674922CF182E4E402D4503CDC9494AB4F97E7AB0FB12FD3E122579DFEF559A8904278249A72553B3E1FE17F20CEB9A62706199FB5E92CFA5CA2278E28FE3F2F7518236100B7B58EBB5D725C37E4ED9C8948688DF6412AE9CDA20A45B0499FBBB335339BDDF6A878B8360091E3632EF4BFAA016979CBAA3BA8FF275F14A3C64CCA1185236C6F20E5058141F181C3CAEB05CCABC57671867F7442FAB7D8C88D71733CDF5908741D0A3BCED17E24C215F2A83BE60E1790591C6206D5D7E8A30ABCD852CEADB2E596BC330DA0FC90C06BE7EAF56ED66D2E9EB96E0D2E3FFBF985D08D7B559C8492DE7D84C9F1764E3476E332EA11912D1EDC5EAAA792C4BFDF44A990A0E34DC88DDC4517B9627DC7D90D6C81E65003064636AC0E35224020A9B2026607C8FE9D9F7FDA76B060077254E44E2A32A4CEA03B3490F6E966734A86CA424EEF554D9951655F3062B218256B95C69A079FB1A1F286FF949CB30A5785D4829189291D9330C0567406921992640E74093E9B9A382B13E54E9C0599F0C1C8C6715664F263A50A5EF9027035C6D04204344E07688BA79F15A25708200C326AFFF3C017290843C96D3ED342D5929E21363EF64CCE488E9DCCD0D7E318486FD63E2B6E0D1B7F63AF8FED872119091A333B824BF5ED6C711C0FB1896EC6E1A89F7032E133561973CC37E2BCA0B613C18FA38588CF6DDE1DE955DBA5E340475BE433A8709F4C45D943B8709801A10593F9D106220F46E6724722B31000FF19C8B203E0A1E32F7F1B9439BB9D22F32183C98799F1D2FEDDD285E73AC2D630F8D3A8DEA5F450559C6AF8902814C04C93312A859E3F82093C38CA1425EE04D006AB11F7E6C87E22DADE0B1EF2BB7047EA35893A1B797D41299DAA2BE691890F38C2A10374450520F83F1A3D21A04147C11EA15DDF41F4B5CE97283B1DBDD44C80BAE018C16FF020BAC03462CC25027051049BBA632E03BF036AF771CAD0711D2979D3D0A373B7665E7F04504CAF905C047996F3EDAC08E34CCE97F27046FE46473172E679300C4461323034D211727724596D21BC211E313E7A9A462EACB51F7378C6D9C001CC85F61EFEA7B5FB711690F5437BDC5B439ED07A6FD6E9A14FC7425627963DF7119365C492129D1A117FD2B3B76F980F85D3C8C11A9DF6720D3E1241AC640C0C0FE39BF9B47474A5702C4644B3AA14312074F41F61504E9E1291149050714E61E59AFEB376296D7730D2F202B550C11A495764B30BFC3BD62FCE2942E5F067438D7D25486437DA1961D805789A7432A8C8D1643C0930BB2A626CD1DF3E58FFEB48DECBE035E0F10652A845FA234AB9FADF190B02B1262F3575F8AD43B89990D268E9BDBC547525A21291B134D16E81FADA18BFF8BBCE000412D8DB7AC2B6112F65C54FC3DD9353EE7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FB55CB12EE8B51E19C6BE590AD7838ABB4A42A02B3B241386AA8C2D62A14BC2221BF2EFC73AB6D71D1592E2CC6DBF3FD8666A0880EBA9B23B272E24465D759208853B518D42171DA6A4DBEDF815D6ACD648BF263ADFD924D6F81454A8136D5416F04F72788F02256D43678197B7917FBC516BAA71CCB9E6861AAE5C4A48547500C525F26A0716D1D5E02561150C83DD60126CAF0FDE6AB1C8D7518BA11B40AD23C2B1EAB1B990134834A6C544955E06C91716A33CB57C968500A02D6A2970DF2330793863C1DA938188C0E5A219507622A73E7120A27013288E68645BEF70B326124DA926B9AC40A8FEF05DD96550966E946B6B9C541441F3BAE57EB044939825AE459813D6BF051F7A63716E826492B4D04EBA086D341434112731F6E268F21DD01C2F32816B0CB7B65248996582BAEDA8DB5FFA9217BA9C106E2FB3D225161CA0FCAB818619B0CCDB3060C7B186D89BB846697D6B081C90DA5E6673DE11CD1520EEAB9747DE29E84519E23583370E2B3E44D6C505FE0CB3D9028BE08964CA004CDCE24681F0FFDAF12180D9E610C7818D2614AB462A7B5CD8222F2E26DC5B0C156D39477F3BE7D22BB593FB28B414260BFA74D43A56228D1E1404CDA012542568E79723C116B9720607F1F911F77551BE57EDF7913B5FF076ECDBC4D16B121D93DCFC5DFC299CB45F43BF66EC84A568136E5CBF05E72ADB5371560AF19B330AA5A243C70F2C75F1DFF03D4ED4F743FE239606B381D6D4A80D7DE44BE148742F1BD60B5785B92AFF68163039965D258607CD5C3259C059801D7C69B51DAA432BD5F5AAC52FDE2F8FF6DBD84D80288DE50DCBCAA04041775298E24D4BF60C35105DD397A38F94CFB3E19B7168AE43C7CA8953F3CB428A8BCF311D85906CE3670BE6610333FF6EC1B9AFC3CA034D87EE7770016BAAC0601108709C1B64B411FA245683A114925A35BE66E8D7710C527CD7842ABB0F4A3C1FB1CC4E0083BF09E31F0C969CB73BB275844F2819F17AD24E03821538A3213AF8104C166A46326A092D9E605064AAB127555C8F7A714090FB9E3D4BD1FC668FA45C84D20D7CC9513D0FE0FCF092D7C087148B7CCF9A89D7A96BBBFDA85FCDACB42FD8B0FB6F8B6ACD08F2A51909B57015E7F22615152A0E0E6418FB5730298A4A3D20A49BA7F6C7A7173AF17C423CA177FB83C81DDD11F6EC7CDD2B5EB9814B87830EBD3936D0E4F9119D602F577EC3A299C6419F60183E663EBD37154C77BDF8ACECF4A674DE6F93294CCFFCDA8E827D06A164264408615BAA0B43958F5AD4450A22580AF81BFB8506337806EA715E8FFB0B619C43C49FC40E6C2CBD53D74B9B547B6DC04567B0E105EF5C23727F9867A752CDF4D566E9A182DCDE7BA79FE7AEB959B349D4629605139ABED96C125903EE00ECF3F51190132E9D7DEB7C6ABC5632FF21675E35C57F198B70FAF7DB28F3BDF16069B38186C69A58710227ADFD3CC98F8C5ED7A3DE143017D4A776BD1FB14E53A5D4C54A3316B12BB5CAC261318D689F2C49A95D996A0C16A9D74E502F28AD146968F1713A6F67296FCD727F15854313595629CE392611AC6026BA0A85004A92210CF7A9EA18FF9D494DD557CB294BCC15981332F0BA1478B6BA2BAC583A1C623AF44E3C0BB8C779FCA33F9EF821D4B684D70059466B1A9242B8CB4DBA031269C8FD0EA3AE4946958AF78C4BFFEB579014D276BB527D2D220B1516959C7A3F868A937FADCB735D9443C4BC35CCDDEA7456C2F129CD971A10CFD8D402DCF93650FDE19A8A7FB8AAB7ECB88322C03C4108C5AE51109CCA21C95F8185DED1478D8FF48868E625F47D931F99705B0C075C58FF634A9BA4901739B97AC7DB98F3215DE604524D65CB6337ECB6E41C95D528CA08A19E8EB1070727705B86DC4F39A2F374A5D1C37D3821040B9D5B70B59B136E7409627BC0AB12CA004CAED2C49C47BB849D57E1073C493522A05181029D3CBDB08083BBDDB1000000000000000000000000000000F21E752032183ECF1C011C23E1B5281CC100000000000000000000000000000000000976DEB4F6B12EDAE9F16B57BC64280000000000000000000000000000008E7B6E1736E79B7F1408A3057FE519C18C000000000000000000000000000000000000EC095D53124ADAA24C9CFE7C73E40000000000000000000000000000003A06CF506AC5C44849B1DA854AE1F3BE420000000000000000000000000000000000212B6E0689A1BDD1F578AF0154CEF5000000000000000000000000000000ED5D2A8572E0EB24F41DC78594259219460000000000000000000000000000000000168DAC018DC10E4B416CAAE6DF896300000000000000000000000000000073CA87CFEC729566A537D61F900E28FF85000000000000000000000000000000000029E79106E8FA958BB9A4773C34AA9A0000000000000000000000000000008F96EB32DFF8B930452E5225F7D87A41E300000000000000000000000000000000001C1042F377DD058F1CEB27532132E1000000000000000000000000000000D7E53C2C623E29C842CC33866B50B19E3F00000000000000000000000000000000000E5CB7E6834EC6862F69760778084400000000000000000000000000000032D37D78FECD13AC46D5252101BA83290F000000000000000000000000000000000029CA1F0E12FAF2AC651FE5728D76BB00000000000000000000000000000043CCF9E057EB7C59DF029840F38048694C00000000000000000000000000000000002C98DFEA387D8944D913820AEB4FD40000000000000000000000000000006C07E9E78B5BB47C3A5D2767D9A455730E0000000000000000000000000000000000118CC68678A22F592510D8F0F4672F0000000000000000000000000000004DD4776B5A5B6EBF86A4E508B64D0BBDFB0000000000000000000000000000000000265CE942834761C294DDCB23CDD284000000000000000000000000000000101A7A093D743EF189B92392B552CF6655000000000000000000000000000000000012682C3662C4AEF51F38B68E6822CC000000000000000000000000000000AD6844ADC1816EA21A1E8BA8AB279848FB00000000000000000000000000000000002BB8B06D458F3AF7BAFCD31161572E000000000000000000000000000000279B01AD7E26487B7B365BFE4457264B350000000000000000000000000000000000076DD132DD3857B3BB67EB443F67420000000000000000000000000000002E4D702B9EFA6D0832D669553DF2196C7F00000000000000000000000000000000001D7946ABE43879EEB3FEFAB39CA48A00000000000000000000000000000059EB3611FA5DFC8852F1737A5E7C9CC15500000000000000000000000000000000000372C24BB9A5F3CCCF74FCD6040443000000000000000000000000000000F4080205A087B8E512CB8F75E0BD21854E00000000000000000000000000000000000FC200D8BFE8A065E1779F6F4835E000000000000000000000000000000094A4854A5514676BD401B499A97E78EE710000000000000000000000000000000000102541A8E1C665CF45B539AD7B8059000000000000000000000000000000AA098141C23C7B8221EEBFACCAF31113CE000000000000000000000000000000000007DA4F2F2C122F396F51227F6191EB000000000000000000000000000000EF5DEFDD9A15715E7E97E0B31CD01DA9B6000000000000000000000000000000000003B21006319DD531CFBC7A91C88416000000000000000000000000000000E4EC55F683394277130A8AF365761D1229000000000000000000000000000000000015C07D1584993101DD2455FC32D899000000000000000000000000000000171ADA555D4D15E3659591727284EF2FA500000000000000000000000000000000002DAE3703D2072394333D9DD808667500000000000000000000000000000091BC2570012187C75643536707DEB4A5AC000000000000000000000000000000000011C886FCC33ABADBFF5B4778B8898B0000000000000000000000000000002CA852F79B873942483BDA35770C8B00C60000000000000000000000000000000000001F5974E66E67FB7C72E80B294882000000000000000000000000000000996052997063EFAE3D36018D476FD4CCDC00000000000000000000000000000000001332990E0B3AA1CF9CC90A77A07A3B000000000000000000000000000000BBF27840FB3D5ADC7D41B78098DA77BDE400000000000000000000000000000000001C5FA59AE98A43ABCCD37CA84F48DB0000000000000000000000000000004AF96552E82A6F4AD2B6FF0768E7A7A8310000000000000000000000000000000000009F96396B068854C191200108E22800000000000000000000000000000035C1BAC09E9346F68D8800615C2C10A7040000000000000000000000000000000000212B4F115B831C5E46530974931C3A000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000027A43DBD3D644FAEB417B039514797D41A85B9C70143D78057C83423EC1897670A57201460D45034C62DFA755FC18A9CE9254A5F8727486D366EF4BA510ED7EC193AFFED2A21B3771470CC7BF2385FFDA90D07FE025EE207A1C9B9DA5510DBE30CFFB3EC6F84DC45884A5D8FBE467AA52CD466742865C2875BB309067E20815A01C62BB26EA9B37F29283CD899711E176804C56ABF64AAD6B18F9EAB8BBAB71016288D0933E7EC2EE8638195834ADA632C30D342D8AA0EAB087E581F2EF2566806D37BDBA173C06AC633CB8A454C93C582C26C88C8206883AFB18B0EF26B923C1848AA586DE893836C9DBC139052B93279CA030C0209473B29E066E04B95297A059E0211E23C907C65C2D10DDB5DDD3837653B43C324D913ADBF9338E44A39C82A485ABFBC5FF74731CD42686056C3186150B4F59701D42DD166AD743A241A87204DA0C646B0E6CBF5E8FB86A335729EFD1329B06D9FC04C25230BE43AA495AC2E33F8E91FA03F06061F50162288EBAFC6960325484A65846C59BD0856F41296222739B5AC363886BBC2E108BCF126214B5180181AA064F92D4F98503F8A3B4614AF2A51628BC97AEAE6DD670E1DF89FB94AAA1EF995FF436D0A39DCA98C6654097965E1AF9511D9D20C6CF419BE7ED9158FC88412BFC027DBC72F6F3FE993730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BE0C953EBFAF8004BF8D6A753DB1DFAA0500000000000000000000000000000000001570BE51F3F72B258440FB1D4425EA000000000000000000000000000000BA2EA360CE6689021DB6075F9EA745DFC9000000000000000000000000000000000008A326DD16029AD5E522B9BDE7EC91000000000000000000000000000000704CE24D74627783EA7A39118584EC5C42000000000000000000000000000000000025D0F6AD2357F96318E6E16FD7EE09000000000000000000000000000000FDAB6CA2EFF48DAD56D867C6A2EF2E5A9300000000000000000000000000000000001C8A9C4FBECC7389A852885FEA8629"; // The proof with the public inputs removed @@ -29,9 +28,7 @@ contract BlakeOptTest is Test { publicInputs[3] = 0x0000000000000000000000000000000000000000000000000000000000000004; bool baseVerified = referenceVerifier.verify(proof, publicInputs); - console.log("baseVerified", baseVerified); bool optVerified = optVerifier.verify(proof, publicInputs); - console.log("optVerified", optVerified); assertEq(baseVerified, optVerified); }