From fb882d1bbe6f350dc24fe79f3cca298c922cfa68 Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Wed, 19 Mar 2025 16:26:43 -0400 Subject: [PATCH 01/15] feat: add OpenVmHalo2Verifier that will wrap a snark-verifier outputted verifier contract to expose a more user-friendly interface --- .gitignore | 2 + foundry.toml | 25 +- script/Counter.s.sol | 19 - src/Halo2Verifier.sol | 1569 ++++++++++++++++++++++++++++++++ src/OpenVmHalo2Verifier.sol | 139 +++ src/ProofFormatter.sol | 77 -- test/OpenVmHalo2Verifier.t.sol | 90 ++ 7 files changed, 1824 insertions(+), 97 deletions(-) delete mode 100644 script/Counter.s.sol create mode 100644 src/Halo2Verifier.sol create mode 100644 src/OpenVmHalo2Verifier.sol delete mode 100644 src/ProofFormatter.sol create mode 100644 test/OpenVmHalo2Verifier.t.sol diff --git a/.gitignore b/.gitignore index 85198aa..a93ba6f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ docs/ # Dotenv file .env + +.vscode diff --git a/foundry.toml b/foundry.toml index 25b918f..52753ce 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,5 +2,28 @@ src = "src" out = "out" libs = ["lib"] +verbosity = 2 +solc = "0.8.19" +optimizer = true +optimizer_runs = 100000 +evm_version = "cancun" +show_progress = true -# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options +[profile.default.optimizer_details] + constantOptimizer = false + yul = false + +[fuzz] + runs = 1000 + +[fmt] + bracket_spacing = true + int_types = "long" + line_length = 120 + multiline_func_header = "attributes_first" + number_underscore = "thousands" + quote_style = "double" + single_line_statement_blocks = "single" + tab_width = 4 + wrap_comments = false + \ No newline at end of file diff --git a/script/Counter.s.sol b/script/Counter.s.sol deleted file mode 100644 index cdc1fe9..0000000 --- a/script/Counter.s.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Script, console} from "forge-std/Script.sol"; -import {Counter} from "../src/Counter.sol"; - -contract CounterScript is Script { - Counter public counter; - - function setUp() public {} - - function run() public { - vm.startBroadcast(); - - counter = new Counter(); - - vm.stopBroadcast(); - } -} diff --git a/src/Halo2Verifier.sol b/src/Halo2Verifier.sol new file mode 100644 index 0000000..b2c4f9c --- /dev/null +++ b/src/Halo2Verifier.sol @@ -0,0 +1,1569 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import { OpenVmHalo2Verifier } from "./OpenVmHalo2Verifier.sol"; + +contract AxiomV2QueryVerifier is OpenVmHalo2Verifier { + fallback(bytes calldata) external returns (bytes memory) { + assembly ("memory-safe") { + // Enforce that Solidity memory layout is respected + let data := mload(0x40) + if iszero(eq(data, 0x80)) { revert(0, 0) } + + let success := true + let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + let f_q := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 + function validate_ec_point(x, y) -> valid { + { + let x_lt_p := lt(x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let y_lt_p := lt(y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + valid := and(x_lt_p, y_lt_p) + } + { + let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_cube := + mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_cube_plus_3 := + addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let is_affine := eq(x_cube_plus_3, y_square) + valid := and(valid, is_affine) + } + } + mstore(0xa0, mod(calldataload(0x0), f_q)) + mstore(0xc0, mod(calldataload(0x20), f_q)) + mstore(0xe0, mod(calldataload(0x40), f_q)) + mstore(0x100, mod(calldataload(0x60), f_q)) + mstore(0x120, mod(calldataload(0x80), f_q)) + mstore(0x140, mod(calldataload(0xa0), f_q)) + mstore(0x160, mod(calldataload(0xc0), f_q)) + mstore(0x180, mod(calldataload(0xe0), f_q)) + mstore(0x1a0, mod(calldataload(0x100), f_q)) + mstore(0x1c0, mod(calldataload(0x120), f_q)) + mstore(0x1e0, mod(calldataload(0x140), f_q)) + mstore(0x200, mod(calldataload(0x160), f_q)) + mstore(0x220, mod(calldataload(0x180), f_q)) + mstore(0x240, mod(calldataload(0x1a0), f_q)) + mstore(0x260, mod(calldataload(0x1c0), f_q)) + mstore(0x280, mod(calldataload(0x1e0), f_q)) + mstore(0x2a0, mod(calldataload(0x200), f_q)) + mstore(0x2c0, mod(calldataload(0x220), f_q)) + mstore(0x2e0, mod(calldataload(0x240), f_q)) + mstore(0x300, mod(calldataload(0x260), f_q)) + mstore(0x320, mod(calldataload(0x280), f_q)) + mstore(0x340, mod(calldataload(0x2a0), f_q)) + mstore(0x360, mod(calldataload(0x2c0), f_q)) + mstore(0x80, 15186165512185359347397944531838604952299016691786397857821503921188369501699) + + { + let x := calldataload(0x2e0) + mstore(0x380, x) + let y := calldataload(0x300) + mstore(0x3a0, y) + success := and(validate_ec_point(x, y), success) + } + mstore(0x3c0, keccak256(0x80, 832)) + { + let hash := mload(0x3c0) + mstore(0x3e0, mod(hash, f_q)) + mstore(0x400, hash) + } + + { + let x := calldataload(0x320) + mstore(0x420, x) + let y := calldataload(0x340) + mstore(0x440, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x360) + mstore(0x460, x) + let y := calldataload(0x380) + mstore(0x480, y) + success := and(validate_ec_point(x, y), success) + } + mstore(0x4a0, keccak256(0x400, 160)) + { + let hash := mload(0x4a0) + mstore(0x4c0, mod(hash, f_q)) + mstore(0x4e0, hash) + } + mstore8(1280, 1) + mstore(0x500, keccak256(0x4e0, 33)) + { + let hash := mload(0x500) + mstore(0x520, mod(hash, f_q)) + mstore(0x540, hash) + } + + { + let x := calldataload(0x3a0) + mstore(0x560, x) + let y := calldataload(0x3c0) + mstore(0x580, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x3e0) + mstore(0x5a0, x) + let y := calldataload(0x400) + mstore(0x5c0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x420) + mstore(0x5e0, x) + let y := calldataload(0x440) + mstore(0x600, y) + success := and(validate_ec_point(x, y), success) + } + mstore(0x620, keccak256(0x540, 224)) + { + let hash := mload(0x620) + mstore(0x640, mod(hash, f_q)) + mstore(0x660, hash) + } + + { + let x := calldataload(0x460) + mstore(0x680, x) + let y := calldataload(0x480) + mstore(0x6a0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x4a0) + mstore(0x6c0, x) + let y := calldataload(0x4c0) + mstore(0x6e0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x4e0) + mstore(0x700, x) + let y := calldataload(0x500) + mstore(0x720, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x520) + mstore(0x740, x) + let y := calldataload(0x540) + mstore(0x760, y) + success := and(validate_ec_point(x, y), success) + } + mstore(0x780, keccak256(0x660, 288)) + { + let hash := mload(0x780) + mstore(0x7a0, mod(hash, f_q)) + mstore(0x7c0, hash) + } + mstore(0x7e0, mod(calldataload(0x560), f_q)) + mstore(0x800, mod(calldataload(0x580), f_q)) + mstore(0x820, mod(calldataload(0x5a0), f_q)) + mstore(0x840, mod(calldataload(0x5c0), f_q)) + mstore(0x860, mod(calldataload(0x5e0), f_q)) + mstore(0x880, mod(calldataload(0x600), f_q)) + mstore(0x8a0, mod(calldataload(0x620), f_q)) + mstore(0x8c0, mod(calldataload(0x640), f_q)) + mstore(0x8e0, mod(calldataload(0x660), f_q)) + mstore(0x900, mod(calldataload(0x680), f_q)) + mstore(0x920, mod(calldataload(0x6a0), f_q)) + mstore(0x940, mod(calldataload(0x6c0), f_q)) + mstore(0x960, mod(calldataload(0x6e0), f_q)) + mstore(0x980, mod(calldataload(0x700), f_q)) + mstore(0x9a0, mod(calldataload(0x720), f_q)) + mstore(0x9c0, mod(calldataload(0x740), f_q)) + mstore(0x9e0, mod(calldataload(0x760), f_q)) + mstore(0xa00, mod(calldataload(0x780), f_q)) + mstore(0xa20, mod(calldataload(0x7a0), f_q)) + mstore(0xa40, keccak256(0x7c0, 640)) + { + let hash := mload(0xa40) + mstore(0xa60, mod(hash, f_q)) + mstore(0xa80, hash) + } + mstore8(2720, 1) + mstore(0xaa0, keccak256(0xa80, 33)) + { + let hash := mload(0xaa0) + mstore(0xac0, mod(hash, f_q)) + mstore(0xae0, hash) + } + + { + let x := calldataload(0x7c0) + mstore(0xb00, x) + let y := calldataload(0x7e0) + mstore(0xb20, y) + success := and(validate_ec_point(x, y), success) + } + mstore(0xb40, keccak256(0xae0, 96)) + { + let hash := mload(0xb40) + mstore(0xb60, mod(hash, f_q)) + mstore(0xb80, hash) + } + + { + let x := calldataload(0x800) + mstore(0xba0, x) + let y := calldataload(0x820) + mstore(0xbc0, y) + success := and(validate_ec_point(x, y), success) + } + { + let x := mload(0xa0) + x := add(x, shl(88, mload(0xc0))) + x := add(x, shl(176, mload(0xe0))) + mstore(3040, x) + let y := mload(0x100) + y := add(y, shl(88, mload(0x120))) + y := add(y, shl(176, mload(0x140))) + mstore(3072, y) + + success := and(validate_ec_point(x, y), success) + } + { + let x := mload(0x160) + x := add(x, shl(88, mload(0x180))) + x := add(x, shl(176, mload(0x1a0))) + mstore(3104, x) + let y := mload(0x1c0) + y := add(y, shl(88, mload(0x1e0))) + y := add(y, shl(176, mload(0x200))) + mstore(3136, y) + + success := and(validate_ec_point(x, y), success) + } + mstore(0xc60, mulmod(mload(0x7a0), mload(0x7a0), f_q)) + mstore(0xc80, mulmod(mload(0xc60), mload(0xc60), f_q)) + mstore(0xca0, mulmod(mload(0xc80), mload(0xc80), f_q)) + mstore(0xcc0, mulmod(mload(0xca0), mload(0xca0), f_q)) + mstore(0xce0, mulmod(mload(0xcc0), mload(0xcc0), f_q)) + mstore(0xd00, mulmod(mload(0xce0), mload(0xce0), f_q)) + mstore(0xd20, mulmod(mload(0xd00), mload(0xd00), f_q)) + mstore(0xd40, mulmod(mload(0xd20), mload(0xd20), f_q)) + mstore(0xd60, mulmod(mload(0xd40), mload(0xd40), f_q)) + mstore(0xd80, mulmod(mload(0xd60), mload(0xd60), f_q)) + mstore(0xda0, mulmod(mload(0xd80), mload(0xd80), f_q)) + mstore(0xdc0, mulmod(mload(0xda0), mload(0xda0), f_q)) + mstore(0xde0, mulmod(mload(0xdc0), mload(0xdc0), f_q)) + mstore(0xe00, mulmod(mload(0xde0), mload(0xde0), f_q)) + mstore(0xe20, mulmod(mload(0xe00), mload(0xe00), f_q)) + mstore(0xe40, mulmod(mload(0xe20), mload(0xe20), f_q)) + mstore(0xe60, mulmod(mload(0xe40), mload(0xe40), f_q)) + mstore(0xe80, mulmod(mload(0xe60), mload(0xe60), f_q)) + mstore(0xea0, mulmod(mload(0xe80), mload(0xe80), f_q)) + mstore(0xec0, mulmod(mload(0xea0), mload(0xea0), f_q)) + mstore(0xee0, mulmod(mload(0xec0), mload(0xec0), f_q)) + mstore(0xf00, mulmod(mload(0xee0), mload(0xee0), f_q)) + mstore(0xf20, mulmod(mload(0xf00), mload(0xf00), f_q)) + mstore( + 0xf40, + addmod(mload(0xf20), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) + ) + mstore( + 0xf60, + mulmod(mload(0xf40), 21888240262557392955334514970720457388010314637169927192662615958087340972065, f_q) + ) + mstore( + 0xf80, + mulmod(mload(0xf60), 4506835738822104338668100540817374747935106310012997856968187171738630203507, f_q) + ) + mstore( + 0xfa0, + addmod(mload(0x7a0), 17381407133017170883578305204439900340613258090403036486730017014837178292110, f_q) + ) + mstore( + 0xfc0, + mulmod(mload(0xf60), 21710372849001950800533397158415938114909991150039389063546734567764856596059, f_q) + ) + mstore( + 0xfe0, + addmod(mload(0x7a0), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q) + ) + mstore( + 0x1000, + mulmod(mload(0xf60), 1887003188133998471169152042388914354640772748308168868301418279904560637395, f_q) + ) + mstore( + 0x1020, + addmod(mload(0x7a0), 20001239683705276751077253702868360733907591652107865475396785906671247858222, f_q) + ) + mstore( + 0x1040, + mulmod(mload(0xf60), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q) + ) + mstore( + 0x1060, + addmod(mload(0x7a0), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q) + ) + mstore( + 0x1080, + mulmod(mload(0xf60), 14655294445420895451632927078981340937842238432098198055057679026789553137428, f_q) + ) + mstore( + 0x10a0, + addmod(mload(0x7a0), 7232948426418379770613478666275934150706125968317836288640525159786255358189, f_q) + ) + mstore( + 0x10c0, + mulmod(mload(0xf60), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) + ) + mstore( + 0x10e0, + addmod(mload(0x7a0), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q) + ) + mstore( + 0x1100, + mulmod(mload(0xf60), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + ) + mstore( + 0x1120, + addmod(mload(0x7a0), 12146688980418810893951125255607130521645347193942732958664170801695864621270, f_q) + ) + mstore(0x1140, mulmod(mload(0xf60), 1, f_q)) + mstore( + 0x1160, + addmod(mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) + ) + mstore( + 0x1180, + mulmod(mload(0xf60), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + ) + mstore( + 0x11a0, + addmod(mload(0x7a0), 13513867906530865119835332133273263211836799082674232843258448413103731898270, f_q) + ) + mstore( + 0x11c0, + mulmod(mload(0xf60), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) + ) + mstore( + 0x11e0, + addmod(mload(0x7a0), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q) + ) + mstore( + 0x1200, + mulmod(mload(0xf60), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + ) + mstore( + 0x1220, + addmod(mload(0x7a0), 18272764063556419981698118473909131571661591947471949595929891197711371770216, f_q) + ) + mstore( + 0x1240, + mulmod(mload(0xf60), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) + ) + mstore( + 0x1260, + addmod(mload(0x7a0), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q) + ) + mstore( + 0x1280, + mulmod(mload(0xf60), 216092043779272773661818549620449970334216366264741118684015851799902419467, f_q) + ) + mstore( + 0x12a0, + addmod(mload(0x7a0), 21672150828060002448584587195636825118214148034151293225014188334775906076150, f_q) + ) + mstore( + 0x12c0, + mulmod(mload(0xf60), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q) + ) + mstore( + 0x12e0, + addmod(mload(0x7a0), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q) + ) + mstore( + 0x1300, + mulmod(mload(0xf60), 18610195890048912503953886742825279624920778288956610528523679659246523534888, f_q) + ) + mstore( + 0x1320, + addmod(mload(0x7a0), 3278046981790362718292519002431995463627586111459423815174524527329284960729, f_q) + ) + mstore( + 0x1340, + mulmod(mload(0xf60), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q) + ) + mstore( + 0x1360, + addmod(mload(0x7a0), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q) + ) + mstore( + 0x1380, + mulmod(mload(0xf60), 14875928112196239563830800280253496262679717528621719058794366823499719730250, f_q) + ) + mstore( + 0x13a0, + addmod(mload(0x7a0), 7012314759643035658415605465003778825868646871794315284903837363076088765367, f_q) + ) + mstore( + 0x13c0, + mulmod(mload(0xf60), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q) + ) + mstore( + 0x13e0, + addmod(mload(0x7a0), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q) + ) + mstore( + 0x1400, + mulmod(mload(0xf60), 5522161504810533295870699551020523636289972223872138525048055197429246400245, f_q) + ) + mstore( + 0x1420, + addmod(mload(0x7a0), 16366081367028741926375706194236751452258392176543895818650148989146562095372, f_q) + ) + mstore( + 0x1440, + mulmod(mload(0xf60), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q) + ) + mstore( + 0x1460, + addmod(mload(0x7a0), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q) + ) + mstore( + 0x1480, + mulmod(mload(0xf60), 9100833993744738801214480881117348002768153232283708533639316963648253510584, f_q) + ) + mstore( + 0x14a0, + addmod(mload(0x7a0), 12787408878094536421031924864139927085780211168132325810058887222927554985033, f_q) + ) + mstore( + 0x14c0, + mulmod(mload(0xf60), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q) + ) + mstore( + 0x14e0, + addmod(mload(0x7a0), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q) + ) + mstore( + 0x1500, + mulmod(mload(0xf60), 6132660129994545119218258312491950835441607143741804980633129304664017206141, f_q) + ) + mstore( + 0x1520, + addmod(mload(0x7a0), 15755582741844730103028147432765324253106757256674229363065074881911791289476, f_q) + ) + mstore( + 0x1540, + mulmod(mload(0xf60), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q) + ) + mstore( + 0x1560, + addmod(mload(0x7a0), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q) + ) + mstore( + 0x1580, + mulmod(mload(0xf60), 515148244606945972463850631189471072103916690263705052318085725998468254533, f_q) + ) + mstore( + 0x15a0, + addmod(mload(0x7a0), 21373094627232329249782555114067804016444447710152329291380118460577340241084, f_q) + ) + mstore( + 0x15c0, + mulmod(mload(0xf60), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q) + ) + mstore( + 0x15e0, + addmod(mload(0x7a0), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q) + ) + mstore( + 0x1600, + mulmod(mload(0xf60), 5223738580615264174925218065001555728265216895679471490312087802465486318994, f_q) + ) + mstore( + 0x1620, + addmod(mload(0x7a0), 16664504291224011047321187680255719360283147504736562853386116384110322176623, f_q) + ) + mstore( + 0x1640, + mulmod(mload(0xf60), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q) + ) + mstore( + 0x1660, + addmod(mload(0x7a0), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q) + ) + mstore( + 0x1680, + mulmod(mload(0xf60), 16976236069879939850923145256911338076234942200101755618884183331004076579046, f_q) + ) + mstore( + 0x16a0, + addmod(mload(0x7a0), 4912006801959335371323260488345937012313422200314278724814020855571731916571, f_q) + ) + mstore( + 0x16c0, + mulmod(mload(0xf60), 13553911191894110065493137367144919847521088405945523452288398666974237857208, f_q) + ) + mstore( + 0x16e0, + addmod(mload(0x7a0), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q) + ) + { + let prod := mload(0xfa0) + + prod := mulmod(mload(0xfe0), prod, f_q) + mstore(0x1700, prod) + + prod := mulmod(mload(0x1020), prod, f_q) + mstore(0x1720, prod) + + prod := mulmod(mload(0x1060), prod, f_q) + mstore(0x1740, prod) + + prod := mulmod(mload(0x10a0), prod, f_q) + mstore(0x1760, prod) + + prod := mulmod(mload(0x10e0), prod, f_q) + mstore(0x1780, prod) + + prod := mulmod(mload(0x1120), prod, f_q) + mstore(0x17a0, prod) + + prod := mulmod(mload(0x1160), prod, f_q) + mstore(0x17c0, prod) + + prod := mulmod(mload(0x11a0), prod, f_q) + mstore(0x17e0, prod) + + prod := mulmod(mload(0x11e0), prod, f_q) + mstore(0x1800, prod) + + prod := mulmod(mload(0x1220), prod, f_q) + mstore(0x1820, prod) + + prod := mulmod(mload(0x1260), prod, f_q) + mstore(0x1840, prod) + + prod := mulmod(mload(0x12a0), prod, f_q) + mstore(0x1860, prod) + + prod := mulmod(mload(0x12e0), prod, f_q) + mstore(0x1880, prod) + + prod := mulmod(mload(0x1320), prod, f_q) + mstore(0x18a0, prod) + + prod := mulmod(mload(0x1360), prod, f_q) + mstore(0x18c0, prod) + + prod := mulmod(mload(0x13a0), prod, f_q) + mstore(0x18e0, prod) + + prod := mulmod(mload(0x13e0), prod, f_q) + mstore(0x1900, prod) + + prod := mulmod(mload(0x1420), prod, f_q) + mstore(0x1920, prod) + + prod := mulmod(mload(0x1460), prod, f_q) + mstore(0x1940, prod) + + prod := mulmod(mload(0x14a0), prod, f_q) + mstore(0x1960, prod) + + prod := mulmod(mload(0x14e0), prod, f_q) + mstore(0x1980, prod) + + prod := mulmod(mload(0x1520), prod, f_q) + mstore(0x19a0, prod) + + prod := mulmod(mload(0x1560), prod, f_q) + mstore(0x19c0, prod) + + prod := mulmod(mload(0x15a0), prod, f_q) + mstore(0x19e0, prod) + + prod := mulmod(mload(0x15e0), prod, f_q) + mstore(0x1a00, prod) + + prod := mulmod(mload(0x1620), prod, f_q) + mstore(0x1a20, prod) + + prod := mulmod(mload(0x1660), prod, f_q) + mstore(0x1a40, prod) + + prod := mulmod(mload(0x16a0), prod, f_q) + mstore(0x1a60, prod) + + prod := mulmod(mload(0x16e0), prod, f_q) + mstore(0x1a80, prod) + + prod := mulmod(mload(0xf40), prod, f_q) + mstore(0x1aa0, prod) + } + mstore(0x1ae0, 32) + mstore(0x1b00, 32) + mstore(0x1b20, 32) + mstore(0x1b40, mload(0x1aa0)) + mstore(0x1b60, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + mstore(0x1b80, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + success := and(eq(staticcall(gas(), 0x5, 0x1ae0, 0xc0, 0x1ac0, 0x20), 1), success) + { + let inv := mload(0x1ac0) + let v + + v := mload(0xf40) + mstore(3904, mulmod(mload(0x1a80), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x16e0) + mstore(5856, mulmod(mload(0x1a60), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x16a0) + mstore(5792, mulmod(mload(0x1a40), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1660) + mstore(5728, mulmod(mload(0x1a20), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1620) + mstore(5664, mulmod(mload(0x1a00), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x15e0) + mstore(5600, mulmod(mload(0x19e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x15a0) + mstore(5536, mulmod(mload(0x19c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1560) + mstore(5472, mulmod(mload(0x19a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1520) + mstore(5408, mulmod(mload(0x1980), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x14e0) + mstore(5344, mulmod(mload(0x1960), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x14a0) + mstore(5280, mulmod(mload(0x1940), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1460) + mstore(5216, mulmod(mload(0x1920), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1420) + mstore(5152, mulmod(mload(0x1900), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13e0) + mstore(5088, mulmod(mload(0x18e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13a0) + mstore(5024, mulmod(mload(0x18c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1360) + mstore(4960, mulmod(mload(0x18a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1320) + mstore(4896, mulmod(mload(0x1880), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12e0) + mstore(4832, mulmod(mload(0x1860), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12a0) + mstore(4768, mulmod(mload(0x1840), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1260) + mstore(4704, mulmod(mload(0x1820), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1220) + mstore(4640, mulmod(mload(0x1800), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x11e0) + mstore(4576, mulmod(mload(0x17e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x11a0) + mstore(4512, mulmod(mload(0x17c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1160) + mstore(4448, mulmod(mload(0x17a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1120) + mstore(4384, mulmod(mload(0x1780), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x10e0) + mstore(4320, mulmod(mload(0x1760), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x10a0) + mstore(4256, mulmod(mload(0x1740), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1060) + mstore(4192, mulmod(mload(0x1720), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1020) + mstore(4128, mulmod(mload(0x1700), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0xfe0) + mstore(4064, mulmod(mload(0xfa0), inv, f_q)) + inv := mulmod(v, inv, f_q) + mstore(0xfa0, inv) + } + mstore(0x1ba0, mulmod(mload(0xf80), mload(0xfa0), f_q)) + mstore(0x1bc0, mulmod(mload(0xfc0), mload(0xfe0), f_q)) + mstore(0x1be0, mulmod(mload(0x1000), mload(0x1020), f_q)) + mstore(0x1c00, mulmod(mload(0x1040), mload(0x1060), f_q)) + mstore(0x1c20, mulmod(mload(0x1080), mload(0x10a0), f_q)) + mstore(0x1c40, mulmod(mload(0x10c0), mload(0x10e0), f_q)) + mstore(0x1c60, mulmod(mload(0x1100), mload(0x1120), f_q)) + mstore(0x1c80, mulmod(mload(0x1140), mload(0x1160), f_q)) + mstore(0x1ca0, mulmod(mload(0x1180), mload(0x11a0), f_q)) + mstore(0x1cc0, mulmod(mload(0x11c0), mload(0x11e0), f_q)) + mstore(0x1ce0, mulmod(mload(0x1200), mload(0x1220), f_q)) + mstore(0x1d00, mulmod(mload(0x1240), mload(0x1260), f_q)) + mstore(0x1d20, mulmod(mload(0x1280), mload(0x12a0), f_q)) + mstore(0x1d40, mulmod(mload(0x12c0), mload(0x12e0), f_q)) + mstore(0x1d60, mulmod(mload(0x1300), mload(0x1320), f_q)) + mstore(0x1d80, mulmod(mload(0x1340), mload(0x1360), f_q)) + mstore(0x1da0, mulmod(mload(0x1380), mload(0x13a0), f_q)) + mstore(0x1dc0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) + mstore(0x1de0, mulmod(mload(0x1400), mload(0x1420), f_q)) + mstore(0x1e00, mulmod(mload(0x1440), mload(0x1460), f_q)) + mstore(0x1e20, mulmod(mload(0x1480), mload(0x14a0), f_q)) + mstore(0x1e40, mulmod(mload(0x14c0), mload(0x14e0), f_q)) + mstore(0x1e60, mulmod(mload(0x1500), mload(0x1520), f_q)) + mstore(0x1e80, mulmod(mload(0x1540), mload(0x1560), f_q)) + mstore(0x1ea0, mulmod(mload(0x1580), mload(0x15a0), f_q)) + mstore(0x1ec0, mulmod(mload(0x15c0), mload(0x15e0), f_q)) + mstore(0x1ee0, mulmod(mload(0x1600), mload(0x1620), f_q)) + mstore(0x1f00, mulmod(mload(0x1640), mload(0x1660), f_q)) + mstore(0x1f20, mulmod(mload(0x1680), mload(0x16a0), f_q)) + mstore(0x1f40, mulmod(mload(0x16c0), mload(0x16e0), f_q)) + { + let result := mulmod(mload(0x1c80), mload(0xa0), f_q) + result := addmod(mulmod(mload(0x1ca0), mload(0xc0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1cc0), mload(0xe0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1ce0), mload(0x100), f_q), result, f_q) + result := addmod(mulmod(mload(0x1d00), mload(0x120), f_q), result, f_q) + result := addmod(mulmod(mload(0x1d20), mload(0x140), f_q), result, f_q) + result := addmod(mulmod(mload(0x1d40), mload(0x160), f_q), result, f_q) + result := addmod(mulmod(mload(0x1d60), mload(0x180), f_q), result, f_q) + result := addmod(mulmod(mload(0x1d80), mload(0x1a0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1da0), mload(0x1c0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1dc0), mload(0x1e0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1de0), mload(0x200), f_q), result, f_q) + result := addmod(mulmod(mload(0x1e00), mload(0x220), f_q), result, f_q) + result := addmod(mulmod(mload(0x1e20), mload(0x240), f_q), result, f_q) + result := addmod(mulmod(mload(0x1e40), mload(0x260), f_q), result, f_q) + result := addmod(mulmod(mload(0x1e60), mload(0x280), f_q), result, f_q) + result := addmod(mulmod(mload(0x1e80), mload(0x2a0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1ea0), mload(0x2c0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1ec0), mload(0x2e0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1ee0), mload(0x300), f_q), result, f_q) + result := addmod(mulmod(mload(0x1f00), mload(0x320), f_q), result, f_q) + result := addmod(mulmod(mload(0x1f20), mload(0x340), f_q), result, f_q) + result := addmod(mulmod(mload(0x1f40), mload(0x360), f_q), result, f_q) + mstore(8032, result) + } + mstore(0x1f80, mulmod(mload(0x820), mload(0x800), f_q)) + mstore(0x1fa0, addmod(mload(0x7e0), mload(0x1f80), f_q)) + mstore(0x1fc0, addmod(mload(0x1fa0), sub(f_q, mload(0x840)), f_q)) + mstore(0x1fe0, mulmod(mload(0x1fc0), mload(0x8a0), f_q)) + mstore(0x2000, mulmod(mload(0x640), mload(0x1fe0), f_q)) + mstore(0x2020, addmod(1, sub(f_q, mload(0x960)), f_q)) + mstore(0x2040, mulmod(mload(0x2020), mload(0x1c80), f_q)) + mstore(0x2060, addmod(mload(0x2000), mload(0x2040), f_q)) + mstore(0x2080, mulmod(mload(0x640), mload(0x2060), f_q)) + mstore(0x20a0, mulmod(mload(0x960), mload(0x960), f_q)) + mstore(0x20c0, addmod(mload(0x20a0), sub(f_q, mload(0x960)), f_q)) + mstore(0x20e0, mulmod(mload(0x20c0), mload(0x1ba0), f_q)) + mstore(0x2100, addmod(mload(0x2080), mload(0x20e0), f_q)) + mstore(0x2120, mulmod(mload(0x640), mload(0x2100), f_q)) + mstore(0x2140, addmod(1, sub(f_q, mload(0x1ba0)), f_q)) + mstore(0x2160, addmod(mload(0x1bc0), mload(0x1be0), f_q)) + mstore(0x2180, addmod(mload(0x2160), mload(0x1c00), f_q)) + mstore(0x21a0, addmod(mload(0x2180), mload(0x1c20), f_q)) + mstore(0x21c0, addmod(mload(0x21a0), mload(0x1c40), f_q)) + mstore(0x21e0, addmod(mload(0x21c0), mload(0x1c60), f_q)) + mstore(0x2200, addmod(mload(0x2140), sub(f_q, mload(0x21e0)), f_q)) + mstore(0x2220, mulmod(mload(0x900), mload(0x4c0), f_q)) + mstore(0x2240, addmod(mload(0x860), mload(0x2220), f_q)) + mstore(0x2260, addmod(mload(0x2240), mload(0x520), f_q)) + mstore(0x2280, mulmod(mload(0x920), mload(0x4c0), f_q)) + mstore(0x22a0, addmod(mload(0x7e0), mload(0x2280), f_q)) + mstore(0x22c0, addmod(mload(0x22a0), mload(0x520), f_q)) + mstore(0x22e0, mulmod(mload(0x22c0), mload(0x2260), f_q)) + mstore(0x2300, mulmod(mload(0x940), mload(0x4c0), f_q)) + mstore(0x2320, addmod(mload(0x1f60), mload(0x2300), f_q)) + mstore(0x2340, addmod(mload(0x2320), mload(0x520), f_q)) + mstore(0x2360, mulmod(mload(0x2340), mload(0x22e0), f_q)) + mstore(0x2380, mulmod(mload(0x2360), mload(0x980), f_q)) + mstore(0x23a0, mulmod(1, mload(0x4c0), f_q)) + mstore(0x23c0, mulmod(mload(0x7a0), mload(0x23a0), f_q)) + mstore(0x23e0, addmod(mload(0x860), mload(0x23c0), f_q)) + mstore(0x2400, addmod(mload(0x23e0), mload(0x520), f_q)) + mstore( + 0x2420, + mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x4c0), f_q) + ) + mstore(0x2440, mulmod(mload(0x7a0), mload(0x2420), f_q)) + mstore(0x2460, addmod(mload(0x7e0), mload(0x2440), f_q)) + mstore(0x2480, addmod(mload(0x2460), mload(0x520), f_q)) + mstore(0x24a0, mulmod(mload(0x2480), mload(0x2400), f_q)) + mstore( + 0x24c0, + mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x4c0), f_q) + ) + mstore(0x24e0, mulmod(mload(0x7a0), mload(0x24c0), f_q)) + mstore(0x2500, addmod(mload(0x1f60), mload(0x24e0), f_q)) + mstore(0x2520, addmod(mload(0x2500), mload(0x520), f_q)) + mstore(0x2540, mulmod(mload(0x2520), mload(0x24a0), f_q)) + mstore(0x2560, mulmod(mload(0x2540), mload(0x960), f_q)) + mstore(0x2580, addmod(mload(0x2380), sub(f_q, mload(0x2560)), f_q)) + mstore(0x25a0, mulmod(mload(0x2580), mload(0x2200), f_q)) + mstore(0x25c0, addmod(mload(0x2120), mload(0x25a0), f_q)) + mstore(0x25e0, mulmod(mload(0x640), mload(0x25c0), f_q)) + mstore(0x2600, addmod(1, sub(f_q, mload(0x9a0)), f_q)) + mstore(0x2620, mulmod(mload(0x2600), mload(0x1c80), f_q)) + mstore(0x2640, addmod(mload(0x25e0), mload(0x2620), f_q)) + mstore(0x2660, mulmod(mload(0x640), mload(0x2640), f_q)) + mstore(0x2680, mulmod(mload(0x9a0), mload(0x9a0), f_q)) + mstore(0x26a0, addmod(mload(0x2680), sub(f_q, mload(0x9a0)), f_q)) + mstore(0x26c0, mulmod(mload(0x26a0), mload(0x1ba0), f_q)) + mstore(0x26e0, addmod(mload(0x2660), mload(0x26c0), f_q)) + mstore(0x2700, mulmod(mload(0x640), mload(0x26e0), f_q)) + mstore(0x2720, addmod(mload(0x9e0), mload(0x4c0), f_q)) + mstore(0x2740, mulmod(mload(0x2720), mload(0x9c0), f_q)) + mstore(0x2760, addmod(mload(0xa20), mload(0x520), f_q)) + mstore(0x2780, mulmod(mload(0x2760), mload(0x2740), f_q)) + mstore(0x27a0, mulmod(mload(0x7e0), mload(0x8c0), f_q)) + mstore(0x27c0, addmod(mload(0x27a0), mload(0x4c0), f_q)) + mstore(0x27e0, mulmod(mload(0x27c0), mload(0x9a0), f_q)) + mstore(0x2800, addmod(mload(0x880), mload(0x520), f_q)) + mstore(0x2820, mulmod(mload(0x2800), mload(0x27e0), f_q)) + mstore(0x2840, addmod(mload(0x2780), sub(f_q, mload(0x2820)), f_q)) + mstore(0x2860, mulmod(mload(0x2840), mload(0x2200), f_q)) + mstore(0x2880, addmod(mload(0x2700), mload(0x2860), f_q)) + mstore(0x28a0, mulmod(mload(0x640), mload(0x2880), f_q)) + mstore(0x28c0, addmod(mload(0x9e0), sub(f_q, mload(0xa20)), f_q)) + mstore(0x28e0, mulmod(mload(0x28c0), mload(0x1c80), f_q)) + mstore(0x2900, addmod(mload(0x28a0), mload(0x28e0), f_q)) + mstore(0x2920, mulmod(mload(0x640), mload(0x2900), f_q)) + mstore(0x2940, mulmod(mload(0x28c0), mload(0x2200), f_q)) + mstore(0x2960, addmod(mload(0x9e0), sub(f_q, mload(0xa00)), f_q)) + mstore(0x2980, mulmod(mload(0x2960), mload(0x2940), f_q)) + mstore(0x29a0, addmod(mload(0x2920), mload(0x2980), f_q)) + mstore(0x29c0, mulmod(mload(0xf20), mload(0xf20), f_q)) + mstore(0x29e0, mulmod(mload(0x29c0), mload(0xf20), f_q)) + mstore(0x2a00, mulmod(mload(0x29e0), mload(0xf20), f_q)) + mstore(0x2a20, mulmod(1, mload(0xf20), f_q)) + mstore(0x2a40, mulmod(1, mload(0x29c0), f_q)) + mstore(0x2a60, mulmod(1, mload(0x29e0), f_q)) + mstore(0x2a80, mulmod(mload(0x29a0), mload(0xf40), f_q)) + mstore(0x2aa0, mulmod(mload(0xc60), mload(0x7a0), f_q)) + mstore(0x2ac0, mulmod(mload(0x2aa0), mload(0x7a0), f_q)) + mstore( + 0x2ae0, + mulmod(mload(0x7a0), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + ) + mstore(0x2b00, addmod(mload(0xb60), sub(f_q, mload(0x2ae0)), f_q)) + mstore(0x2b20, mulmod(mload(0x7a0), 1, f_q)) + mstore(0x2b40, addmod(mload(0xb60), sub(f_q, mload(0x2b20)), f_q)) + mstore( + 0x2b60, + mulmod(mload(0x7a0), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + ) + mstore(0x2b80, addmod(mload(0xb60), sub(f_q, mload(0x2b60)), f_q)) + mstore( + 0x2ba0, + mulmod(mload(0x7a0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) + ) + mstore(0x2bc0, addmod(mload(0xb60), sub(f_q, mload(0x2ba0)), f_q)) + mstore( + 0x2be0, + mulmod(mload(0x7a0), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + ) + mstore(0x2c00, addmod(mload(0xb60), sub(f_q, mload(0x2be0)), f_q)) + mstore( + 0x2c20, + mulmod( + 13213688729882003894512633350385593288217014177373218494356903340348818451480, mload(0x2aa0), f_q + ) + ) + mstore(0x2c40, mulmod(mload(0x2c20), 1, f_q)) + { + let result := mulmod(mload(0xb60), mload(0x2c20), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2c40)), f_q), result, f_q) + mstore(11360, result) + } + mstore( + 0x2c80, + mulmod(8207090019724696496350398458716998472718344609680392612601596849934418295470, mload(0x2aa0), f_q) + ) + mstore( + 0x2ca0, + mulmod(mload(0x2c80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + ) + { + let result := mulmod(mload(0xb60), mload(0x2c80), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ca0)), f_q), result, f_q) + mstore(11456, result) + } + mstore( + 0x2ce0, + mulmod(7391709068497399131897422873231908718558236401035363928063603272120120747483, mload(0x2aa0), f_q) + ) + mstore( + 0x2d00, + mulmod( + mload(0x2ce0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q + ) + ) + { + let result := mulmod(mload(0xb60), mload(0x2ce0), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d00)), f_q), result, f_q) + mstore(11552, result) + } + mstore( + 0x2d40, + mulmod( + 19036273796805830823244991598792794567595348772040298280440552631112242221017, mload(0x2aa0), f_q + ) + ) + mstore( + 0x2d60, + mulmod(mload(0x2d40), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + ) + { + let result := mulmod(mload(0xb60), mload(0x2d40), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d60)), f_q), result, f_q) + mstore(11648, result) + } + mstore(0x2da0, mulmod(1, mload(0x2b40), f_q)) + mstore(0x2dc0, mulmod(mload(0x2da0), mload(0x2b80), f_q)) + mstore(0x2de0, mulmod(mload(0x2dc0), mload(0x2bc0), f_q)) + mstore(0x2e00, mulmod(mload(0x2de0), mload(0x2c00), f_q)) + mstore( + 0x2e20, + mulmod(13513867906530865119835332133273263211836799082674232843258448413103731898271, mload(0x7a0), f_q) + ) + mstore(0x2e40, mulmod(mload(0x2e20), 1, f_q)) + { + let result := mulmod(mload(0xb60), mload(0x2e20), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2e40)), f_q), result, f_q) + mstore(11872, result) + } + mstore( + 0x2e80, + mulmod(8374374965308410102411073611984011876711565317741801500439755773472076597346, mload(0x7a0), f_q) + ) + mstore( + 0x2ea0, + mulmod(mload(0x2e80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + ) + { + let result := mulmod(mload(0xb60), mload(0x2e80), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ea0)), f_q), result, f_q) + mstore(11968, result) + } + mstore( + 0x2ee0, + mulmod(12146688980418810893951125255607130521645347193942732958664170801695864621271, mload(0x7a0), f_q) + ) + mstore(0x2f00, mulmod(mload(0x2ee0), 1, f_q)) + { + let result := mulmod(mload(0xb60), mload(0x2ee0), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f00)), f_q), result, f_q) + mstore(12064, result) + } + mstore( + 0x2f40, + mulmod(9741553891420464328295280489650144566903017206473301385034033384879943874346, mload(0x7a0), f_q) + ) + mstore( + 0x2f60, + mulmod(mload(0x2f40), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + ) + { + let result := mulmod(mload(0xb60), mload(0x2f40), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f60)), f_q), result, f_q) + mstore(12160, result) + } + mstore(0x2fa0, mulmod(mload(0x2da0), mload(0x2b00), f_q)) + { + let result := mulmod(mload(0xb60), 1, f_q) + result := + addmod( + mulmod( + mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q + ), + result, + f_q + ) + mstore(12224, result) + } + { + let prod := mload(0x2c60) + + prod := mulmod(mload(0x2cc0), prod, f_q) + mstore(0x2fe0, prod) + + prod := mulmod(mload(0x2d20), prod, f_q) + mstore(0x3000, prod) + + prod := mulmod(mload(0x2d80), prod, f_q) + mstore(0x3020, prod) + + prod := mulmod(mload(0x2e60), prod, f_q) + mstore(0x3040, prod) + + prod := mulmod(mload(0x2ec0), prod, f_q) + mstore(0x3060, prod) + + prod := mulmod(mload(0x2dc0), prod, f_q) + mstore(0x3080, prod) + + prod := mulmod(mload(0x2f20), prod, f_q) + mstore(0x30a0, prod) + + prod := mulmod(mload(0x2f80), prod, f_q) + mstore(0x30c0, prod) + + prod := mulmod(mload(0x2fa0), prod, f_q) + mstore(0x30e0, prod) + + prod := mulmod(mload(0x2fc0), prod, f_q) + mstore(0x3100, prod) + + prod := mulmod(mload(0x2da0), prod, f_q) + mstore(0x3120, prod) + } + mstore(0x3160, 32) + mstore(0x3180, 32) + mstore(0x31a0, 32) + mstore(0x31c0, mload(0x3120)) + mstore(0x31e0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + mstore(0x3200, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + success := and(eq(staticcall(gas(), 0x5, 0x3160, 0xc0, 0x3140, 0x20), 1), success) + { + let inv := mload(0x3140) + let v + + v := mload(0x2da0) + mstore(11680, mulmod(mload(0x3100), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2fc0) + mstore(12224, mulmod(mload(0x30e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2fa0) + mstore(12192, mulmod(mload(0x30c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2f80) + mstore(12160, mulmod(mload(0x30a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2f20) + mstore(12064, mulmod(mload(0x3080), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2dc0) + mstore(11712, mulmod(mload(0x3060), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2ec0) + mstore(11968, mulmod(mload(0x3040), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2e60) + mstore(11872, mulmod(mload(0x3020), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2d80) + mstore(11648, mulmod(mload(0x3000), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2d20) + mstore(11552, mulmod(mload(0x2fe0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2cc0) + mstore(11456, mulmod(mload(0x2c60), inv, f_q)) + inv := mulmod(v, inv, f_q) + mstore(0x2c60, inv) + } + { + let result := mload(0x2c60) + result := addmod(mload(0x2cc0), result, f_q) + result := addmod(mload(0x2d20), result, f_q) + result := addmod(mload(0x2d80), result, f_q) + mstore(12832, result) + } + mstore(0x3240, mulmod(mload(0x2e00), mload(0x2dc0), f_q)) + { + let result := mload(0x2e60) + result := addmod(mload(0x2ec0), result, f_q) + mstore(12896, result) + } + mstore(0x3280, mulmod(mload(0x2e00), mload(0x2fa0), f_q)) + { + let result := mload(0x2f20) + result := addmod(mload(0x2f80), result, f_q) + mstore(12960, result) + } + mstore(0x32c0, mulmod(mload(0x2e00), mload(0x2da0), f_q)) + { + let result := mload(0x2fc0) + mstore(13024, result) + } + { + let prod := mload(0x3220) + + prod := mulmod(mload(0x3260), prod, f_q) + mstore(0x3300, prod) + + prod := mulmod(mload(0x32a0), prod, f_q) + mstore(0x3320, prod) + + prod := mulmod(mload(0x32e0), prod, f_q) + mstore(0x3340, prod) + } + mstore(0x3380, 32) + mstore(0x33a0, 32) + mstore(0x33c0, 32) + mstore(0x33e0, mload(0x3340)) + mstore(0x3400, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + mstore(0x3420, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + success := and(eq(staticcall(gas(), 0x5, 0x3380, 0xc0, 0x3360, 0x20), 1), success) + { + let inv := mload(0x3360) + let v + + v := mload(0x32e0) + mstore(13024, mulmod(mload(0x3320), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x32a0) + mstore(12960, mulmod(mload(0x3300), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3260) + mstore(12896, mulmod(mload(0x3220), inv, f_q)) + inv := mulmod(v, inv, f_q) + mstore(0x3220, inv) + } + mstore(0x3440, mulmod(mload(0x3240), mload(0x3260), f_q)) + mstore(0x3460, mulmod(mload(0x3280), mload(0x32a0), f_q)) + mstore(0x3480, mulmod(mload(0x32c0), mload(0x32e0), f_q)) + mstore(0x34a0, mulmod(mload(0xa60), mload(0xa60), f_q)) + mstore(0x34c0, mulmod(mload(0x34a0), mload(0xa60), f_q)) + mstore(0x34e0, mulmod(mload(0x34c0), mload(0xa60), f_q)) + mstore(0x3500, mulmod(mload(0x34e0), mload(0xa60), f_q)) + mstore(0x3520, mulmod(mload(0x3500), mload(0xa60), f_q)) + mstore(0x3540, mulmod(mload(0x3520), mload(0xa60), f_q)) + mstore(0x3560, mulmod(mload(0x3540), mload(0xa60), f_q)) + mstore(0x3580, mulmod(mload(0x3560), mload(0xa60), f_q)) + mstore(0x35a0, mulmod(mload(0x3580), mload(0xa60), f_q)) + mstore(0x35c0, mulmod(mload(0xac0), mload(0xac0), f_q)) + mstore(0x35e0, mulmod(mload(0x35c0), mload(0xac0), f_q)) + mstore(0x3600, mulmod(mload(0x35e0), mload(0xac0), f_q)) + { + let result := mulmod(mload(0x7e0), mload(0x2c60), f_q) + result := addmod(mulmod(mload(0x800), mload(0x2cc0), f_q), result, f_q) + result := addmod(mulmod(mload(0x820), mload(0x2d20), f_q), result, f_q) + result := addmod(mulmod(mload(0x840), mload(0x2d80), f_q), result, f_q) + mstore(13856, result) + } + mstore(0x3640, mulmod(mload(0x3620), mload(0x3220), f_q)) + mstore(0x3660, mulmod(sub(f_q, mload(0x3640)), 1, f_q)) + mstore(0x3680, mulmod(mload(0x3660), 1, f_q)) + mstore(0x36a0, mulmod(1, mload(0x3240), f_q)) + { + let result := mulmod(mload(0x960), mload(0x2e60), f_q) + result := addmod(mulmod(mload(0x980), mload(0x2ec0), f_q), result, f_q) + mstore(14016, result) + } + mstore(0x36e0, mulmod(mload(0x36c0), mload(0x3440), f_q)) + mstore(0x3700, mulmod(sub(f_q, mload(0x36e0)), 1, f_q)) + mstore(0x3720, mulmod(mload(0x36a0), 1, f_q)) + { + let result := mulmod(mload(0x9a0), mload(0x2e60), f_q) + result := addmod(mulmod(mload(0x9c0), mload(0x2ec0), f_q), result, f_q) + mstore(14144, result) + } + mstore(0x3760, mulmod(mload(0x3740), mload(0x3440), f_q)) + mstore(0x3780, mulmod(sub(f_q, mload(0x3760)), mload(0xa60), f_q)) + mstore(0x37a0, mulmod(mload(0x36a0), mload(0xa60), f_q)) + mstore(0x37c0, addmod(mload(0x3700), mload(0x3780), f_q)) + mstore(0x37e0, mulmod(mload(0x37c0), mload(0xac0), f_q)) + mstore(0x3800, mulmod(mload(0x3720), mload(0xac0), f_q)) + mstore(0x3820, mulmod(mload(0x37a0), mload(0xac0), f_q)) + mstore(0x3840, addmod(mload(0x3680), mload(0x37e0), f_q)) + mstore(0x3860, mulmod(1, mload(0x3280), f_q)) + { + let result := mulmod(mload(0x9e0), mload(0x2f20), f_q) + result := addmod(mulmod(mload(0xa00), mload(0x2f80), f_q), result, f_q) + mstore(14464, result) + } + mstore(0x38a0, mulmod(mload(0x3880), mload(0x3460), f_q)) + mstore(0x38c0, mulmod(sub(f_q, mload(0x38a0)), 1, f_q)) + mstore(0x38e0, mulmod(mload(0x3860), 1, f_q)) + mstore(0x3900, mulmod(mload(0x38c0), mload(0x35c0), f_q)) + mstore(0x3920, mulmod(mload(0x38e0), mload(0x35c0), f_q)) + mstore(0x3940, addmod(mload(0x3840), mload(0x3900), f_q)) + mstore(0x3960, mulmod(1, mload(0x32c0), f_q)) + { + let result := mulmod(mload(0xa20), mload(0x2fc0), f_q) + mstore(14720, result) + } + mstore(0x39a0, mulmod(mload(0x3980), mload(0x3480), f_q)) + mstore(0x39c0, mulmod(sub(f_q, mload(0x39a0)), 1, f_q)) + mstore(0x39e0, mulmod(mload(0x3960), 1, f_q)) + { + let result := mulmod(mload(0x860), mload(0x2fc0), f_q) + mstore(14848, result) + } + mstore(0x3a20, mulmod(mload(0x3a00), mload(0x3480), f_q)) + mstore(0x3a40, mulmod(sub(f_q, mload(0x3a20)), mload(0xa60), f_q)) + mstore(0x3a60, mulmod(mload(0x3960), mload(0xa60), f_q)) + mstore(0x3a80, addmod(mload(0x39c0), mload(0x3a40), f_q)) + { + let result := mulmod(mload(0x880), mload(0x2fc0), f_q) + mstore(15008, result) + } + mstore(0x3ac0, mulmod(mload(0x3aa0), mload(0x3480), f_q)) + mstore(0x3ae0, mulmod(sub(f_q, mload(0x3ac0)), mload(0x34a0), f_q)) + mstore(0x3b00, mulmod(mload(0x3960), mload(0x34a0), f_q)) + mstore(0x3b20, addmod(mload(0x3a80), mload(0x3ae0), f_q)) + { + let result := mulmod(mload(0x8a0), mload(0x2fc0), f_q) + mstore(15168, result) + } + mstore(0x3b60, mulmod(mload(0x3b40), mload(0x3480), f_q)) + mstore(0x3b80, mulmod(sub(f_q, mload(0x3b60)), mload(0x34c0), f_q)) + mstore(0x3ba0, mulmod(mload(0x3960), mload(0x34c0), f_q)) + mstore(0x3bc0, addmod(mload(0x3b20), mload(0x3b80), f_q)) + { + let result := mulmod(mload(0x8c0), mload(0x2fc0), f_q) + mstore(15328, result) + } + mstore(0x3c00, mulmod(mload(0x3be0), mload(0x3480), f_q)) + mstore(0x3c20, mulmod(sub(f_q, mload(0x3c00)), mload(0x34e0), f_q)) + mstore(0x3c40, mulmod(mload(0x3960), mload(0x34e0), f_q)) + mstore(0x3c60, addmod(mload(0x3bc0), mload(0x3c20), f_q)) + { + let result := mulmod(mload(0x900), mload(0x2fc0), f_q) + mstore(15488, result) + } + mstore(0x3ca0, mulmod(mload(0x3c80), mload(0x3480), f_q)) + mstore(0x3cc0, mulmod(sub(f_q, mload(0x3ca0)), mload(0x3500), f_q)) + mstore(0x3ce0, mulmod(mload(0x3960), mload(0x3500), f_q)) + mstore(0x3d00, addmod(mload(0x3c60), mload(0x3cc0), f_q)) + { + let result := mulmod(mload(0x920), mload(0x2fc0), f_q) + mstore(15648, result) + } + mstore(0x3d40, mulmod(mload(0x3d20), mload(0x3480), f_q)) + mstore(0x3d60, mulmod(sub(f_q, mload(0x3d40)), mload(0x3520), f_q)) + mstore(0x3d80, mulmod(mload(0x3960), mload(0x3520), f_q)) + mstore(0x3da0, addmod(mload(0x3d00), mload(0x3d60), f_q)) + { + let result := mulmod(mload(0x940), mload(0x2fc0), f_q) + mstore(15808, result) + } + mstore(0x3de0, mulmod(mload(0x3dc0), mload(0x3480), f_q)) + mstore(0x3e00, mulmod(sub(f_q, mload(0x3de0)), mload(0x3540), f_q)) + mstore(0x3e20, mulmod(mload(0x3960), mload(0x3540), f_q)) + mstore(0x3e40, addmod(mload(0x3da0), mload(0x3e00), f_q)) + mstore(0x3e60, mulmod(mload(0x2a20), mload(0x32c0), f_q)) + mstore(0x3e80, mulmod(mload(0x2a40), mload(0x32c0), f_q)) + mstore(0x3ea0, mulmod(mload(0x2a60), mload(0x32c0), f_q)) + { + let result := mulmod(mload(0x2a80), mload(0x2fc0), f_q) + mstore(16064, result) + } + mstore(0x3ee0, mulmod(mload(0x3ec0), mload(0x3480), f_q)) + mstore(0x3f00, mulmod(sub(f_q, mload(0x3ee0)), mload(0x3560), f_q)) + mstore(0x3f20, mulmod(mload(0x3960), mload(0x3560), f_q)) + mstore(0x3f40, mulmod(mload(0x3e60), mload(0x3560), f_q)) + mstore(0x3f60, mulmod(mload(0x3e80), mload(0x3560), f_q)) + mstore(0x3f80, mulmod(mload(0x3ea0), mload(0x3560), f_q)) + mstore(0x3fa0, addmod(mload(0x3e40), mload(0x3f00), f_q)) + { + let result := mulmod(mload(0x8e0), mload(0x2fc0), f_q) + mstore(16320, result) + } + mstore(0x3fe0, mulmod(mload(0x3fc0), mload(0x3480), f_q)) + mstore(0x4000, mulmod(sub(f_q, mload(0x3fe0)), mload(0x3580), f_q)) + mstore(0x4020, mulmod(mload(0x3960), mload(0x3580), f_q)) + mstore(0x4040, addmod(mload(0x3fa0), mload(0x4000), f_q)) + mstore(0x4060, mulmod(mload(0x4040), mload(0x35e0), f_q)) + mstore(0x4080, mulmod(mload(0x39e0), mload(0x35e0), f_q)) + mstore(0x40a0, mulmod(mload(0x3a60), mload(0x35e0), f_q)) + mstore(0x40c0, mulmod(mload(0x3b00), mload(0x35e0), f_q)) + mstore(0x40e0, mulmod(mload(0x3ba0), mload(0x35e0), f_q)) + mstore(0x4100, mulmod(mload(0x3c40), mload(0x35e0), f_q)) + mstore(0x4120, mulmod(mload(0x3ce0), mload(0x35e0), f_q)) + mstore(0x4140, mulmod(mload(0x3d80), mload(0x35e0), f_q)) + mstore(0x4160, mulmod(mload(0x3e20), mload(0x35e0), f_q)) + mstore(0x4180, mulmod(mload(0x3f20), mload(0x35e0), f_q)) + mstore(0x41a0, mulmod(mload(0x3f40), mload(0x35e0), f_q)) + mstore(0x41c0, mulmod(mload(0x3f60), mload(0x35e0), f_q)) + mstore(0x41e0, mulmod(mload(0x3f80), mload(0x35e0), f_q)) + mstore(0x4200, mulmod(mload(0x4020), mload(0x35e0), f_q)) + mstore(0x4220, addmod(mload(0x3940), mload(0x4060), f_q)) + mstore(0x4240, mulmod(1, mload(0x2e00), f_q)) + mstore(0x4260, mulmod(1, mload(0xb60), f_q)) + mstore(0x4280, 0x0000000000000000000000000000000000000000000000000000000000000001) + mstore(0x42a0, 0x0000000000000000000000000000000000000000000000000000000000000002) + mstore(0x42c0, mload(0x4220)) + success := and(eq(staticcall(gas(), 0x7, 0x4280, 0x60, 0x4280, 0x40), 1), success) + mstore(0x42e0, mload(0x4280)) + mstore(0x4300, mload(0x42a0)) + mstore(0x4320, mload(0x380)) + mstore(0x4340, mload(0x3a0)) + success := and(eq(staticcall(gas(), 0x6, 0x42e0, 0x80, 0x42e0, 0x40), 1), success) + mstore(0x4360, mload(0x560)) + mstore(0x4380, mload(0x580)) + mstore(0x43a0, mload(0x3800)) + success := and(eq(staticcall(gas(), 0x7, 0x4360, 0x60, 0x4360, 0x40), 1), success) + mstore(0x43c0, mload(0x42e0)) + mstore(0x43e0, mload(0x4300)) + mstore(0x4400, mload(0x4360)) + mstore(0x4420, mload(0x4380)) + success := and(eq(staticcall(gas(), 0x6, 0x43c0, 0x80, 0x43c0, 0x40), 1), success) + mstore(0x4440, mload(0x5a0)) + mstore(0x4460, mload(0x5c0)) + mstore(0x4480, mload(0x3820)) + success := and(eq(staticcall(gas(), 0x7, 0x4440, 0x60, 0x4440, 0x40), 1), success) + mstore(0x44a0, mload(0x43c0)) + mstore(0x44c0, mload(0x43e0)) + mstore(0x44e0, mload(0x4440)) + mstore(0x4500, mload(0x4460)) + success := and(eq(staticcall(gas(), 0x6, 0x44a0, 0x80, 0x44a0, 0x40), 1), success) + mstore(0x4520, mload(0x420)) + mstore(0x4540, mload(0x440)) + mstore(0x4560, mload(0x3920)) + success := and(eq(staticcall(gas(), 0x7, 0x4520, 0x60, 0x4520, 0x40), 1), success) + mstore(0x4580, mload(0x44a0)) + mstore(0x45a0, mload(0x44c0)) + mstore(0x45c0, mload(0x4520)) + mstore(0x45e0, mload(0x4540)) + success := and(eq(staticcall(gas(), 0x6, 0x4580, 0x80, 0x4580, 0x40), 1), success) + mstore(0x4600, mload(0x460)) + mstore(0x4620, mload(0x480)) + mstore(0x4640, mload(0x4080)) + success := and(eq(staticcall(gas(), 0x7, 0x4600, 0x60, 0x4600, 0x40), 1), success) + mstore(0x4660, mload(0x4580)) + mstore(0x4680, mload(0x45a0)) + mstore(0x46a0, mload(0x4600)) + mstore(0x46c0, mload(0x4620)) + success := and(eq(staticcall(gas(), 0x6, 0x4660, 0x80, 0x4660, 0x40), 1), success) + mstore(0x46e0, 0x21b14b6e8ea36289961bde7f1d8f191389a815740d09f34f13190341383dfb13) + mstore(0x4700, 0x16740f9c3982e02aeb0cb10086339afaca1bb103d5ae3f114c45a569d60c88ce) + mstore(0x4720, mload(0x40a0)) + success := and(eq(staticcall(gas(), 0x7, 0x46e0, 0x60, 0x46e0, 0x40), 1), success) + mstore(0x4740, mload(0x4660)) + mstore(0x4760, mload(0x4680)) + mstore(0x4780, mload(0x46e0)) + mstore(0x47a0, mload(0x4700)) + success := and(eq(staticcall(gas(), 0x6, 0x4740, 0x80, 0x4740, 0x40), 1), success) + mstore(0x47c0, 0x2eb40e2b0c13a6f4b989cffa9dbc452447bfd9f04a79f6379aefea8c9850a550) + mstore(0x47e0, 0x0efe5496541e2bd648d490f11ad542e1dec3127f818b8065843d0dd81358416c) + mstore(0x4800, mload(0x40c0)) + success := and(eq(staticcall(gas(), 0x7, 0x47c0, 0x60, 0x47c0, 0x40), 1), success) + mstore(0x4820, mload(0x4740)) + mstore(0x4840, mload(0x4760)) + mstore(0x4860, mload(0x47c0)) + mstore(0x4880, mload(0x47e0)) + success := and(eq(staticcall(gas(), 0x6, 0x4820, 0x80, 0x4820, 0x40), 1), success) + mstore(0x48a0, 0x1c6707c73bce576eb360ffcb2fa9a0b17ad541ea0a0e8001439bca524f2f5a43) + mstore(0x48c0, 0x03b899b999df6cf57b7755535b1dc5014a9dbd21d55c31d826d8338dc2fe8722) + mstore(0x48e0, mload(0x40e0)) + success := and(eq(staticcall(gas(), 0x7, 0x48a0, 0x60, 0x48a0, 0x40), 1), success) + mstore(0x4900, mload(0x4820)) + mstore(0x4920, mload(0x4840)) + mstore(0x4940, mload(0x48a0)) + mstore(0x4960, mload(0x48c0)) + success := and(eq(staticcall(gas(), 0x6, 0x4900, 0x80, 0x4900, 0x40), 1), success) + mstore(0x4980, 0x1d309220cdb6694a08a8c77f89984557e19bbda422f41d50b47bf30b30b3dec3) + mstore(0x49a0, 0x138c263b3cbc7de6f5f92f88c44a3e7fc278a4b69008db2340097131e43dbb1a) + mstore(0x49c0, mload(0x4100)) + success := and(eq(staticcall(gas(), 0x7, 0x4980, 0x60, 0x4980, 0x40), 1), success) + mstore(0x49e0, mload(0x4900)) + mstore(0x4a00, mload(0x4920)) + mstore(0x4a20, mload(0x4980)) + mstore(0x4a40, mload(0x49a0)) + success := and(eq(staticcall(gas(), 0x6, 0x49e0, 0x80, 0x49e0, 0x40), 1), success) + mstore(0x4a60, 0x2529da4dfe20ec7564dc8738f2477daf565052f29117d9a2c1a0cbe846ab95fb) + mstore(0x4a80, 0x2a3971e5a786b7e8b0039d1100621af00a8743921a36ef7aafc430b09a5bd279) + mstore(0x4aa0, mload(0x4120)) + success := and(eq(staticcall(gas(), 0x7, 0x4a60, 0x60, 0x4a60, 0x40), 1), success) + mstore(0x4ac0, mload(0x49e0)) + mstore(0x4ae0, mload(0x4a00)) + mstore(0x4b00, mload(0x4a60)) + mstore(0x4b20, mload(0x4a80)) + success := and(eq(staticcall(gas(), 0x6, 0x4ac0, 0x80, 0x4ac0, 0x40), 1), success) + mstore(0x4b40, 0x132e1a4125c783ea4817ea96d967c5f06a49933ca71f7e99f7be022ef1e3ca35) + mstore(0x4b60, 0x0eb726ae10479119d87b2e1d0d2b72db88506d263ae939b2154b0f3f5c7012f7) + mstore(0x4b80, mload(0x4140)) + success := and(eq(staticcall(gas(), 0x7, 0x4b40, 0x60, 0x4b40, 0x40), 1), success) + mstore(0x4ba0, mload(0x4ac0)) + mstore(0x4bc0, mload(0x4ae0)) + mstore(0x4be0, mload(0x4b40)) + mstore(0x4c00, mload(0x4b60)) + success := and(eq(staticcall(gas(), 0x6, 0x4ba0, 0x80, 0x4ba0, 0x40), 1), success) + mstore(0x4c20, 0x1bc70a16efa4ef34c9ee86dc04d041fc8430240113b09ef71d5bbb8b685af6b7) + mstore(0x4c40, 0x25064309a3b7ab3efd593b9e6c2f1294b50c12e237412186d7af94b1591dc937) + mstore(0x4c60, mload(0x4160)) + success := and(eq(staticcall(gas(), 0x7, 0x4c20, 0x60, 0x4c20, 0x40), 1), success) + mstore(0x4c80, mload(0x4ba0)) + mstore(0x4ca0, mload(0x4bc0)) + mstore(0x4cc0, mload(0x4c20)) + mstore(0x4ce0, mload(0x4c40)) + success := and(eq(staticcall(gas(), 0x6, 0x4c80, 0x80, 0x4c80, 0x40), 1), success) + mstore(0x4d00, mload(0x680)) + mstore(0x4d20, mload(0x6a0)) + mstore(0x4d40, mload(0x4180)) + success := and(eq(staticcall(gas(), 0x7, 0x4d00, 0x60, 0x4d00, 0x40), 1), success) + mstore(0x4d60, mload(0x4c80)) + mstore(0x4d80, mload(0x4ca0)) + mstore(0x4da0, mload(0x4d00)) + mstore(0x4dc0, mload(0x4d20)) + success := and(eq(staticcall(gas(), 0x6, 0x4d60, 0x80, 0x4d60, 0x40), 1), success) + mstore(0x4de0, mload(0x6c0)) + mstore(0x4e00, mload(0x6e0)) + mstore(0x4e20, mload(0x41a0)) + success := and(eq(staticcall(gas(), 0x7, 0x4de0, 0x60, 0x4de0, 0x40), 1), success) + mstore(0x4e40, mload(0x4d60)) + mstore(0x4e60, mload(0x4d80)) + mstore(0x4e80, mload(0x4de0)) + mstore(0x4ea0, mload(0x4e00)) + success := and(eq(staticcall(gas(), 0x6, 0x4e40, 0x80, 0x4e40, 0x40), 1), success) + mstore(0x4ec0, mload(0x700)) + mstore(0x4ee0, mload(0x720)) + mstore(0x4f00, mload(0x41c0)) + success := and(eq(staticcall(gas(), 0x7, 0x4ec0, 0x60, 0x4ec0, 0x40), 1), success) + mstore(0x4f20, mload(0x4e40)) + mstore(0x4f40, mload(0x4e60)) + mstore(0x4f60, mload(0x4ec0)) + mstore(0x4f80, mload(0x4ee0)) + success := and(eq(staticcall(gas(), 0x6, 0x4f20, 0x80, 0x4f20, 0x40), 1), success) + mstore(0x4fa0, mload(0x740)) + mstore(0x4fc0, mload(0x760)) + mstore(0x4fe0, mload(0x41e0)) + success := and(eq(staticcall(gas(), 0x7, 0x4fa0, 0x60, 0x4fa0, 0x40), 1), success) + mstore(0x5000, mload(0x4f20)) + mstore(0x5020, mload(0x4f40)) + mstore(0x5040, mload(0x4fa0)) + mstore(0x5060, mload(0x4fc0)) + success := and(eq(staticcall(gas(), 0x6, 0x5000, 0x80, 0x5000, 0x40), 1), success) + mstore(0x5080, mload(0x5e0)) + mstore(0x50a0, mload(0x600)) + mstore(0x50c0, mload(0x4200)) + success := and(eq(staticcall(gas(), 0x7, 0x5080, 0x60, 0x5080, 0x40), 1), success) + mstore(0x50e0, mload(0x5000)) + mstore(0x5100, mload(0x5020)) + mstore(0x5120, mload(0x5080)) + mstore(0x5140, mload(0x50a0)) + success := and(eq(staticcall(gas(), 0x6, 0x50e0, 0x80, 0x50e0, 0x40), 1), success) + mstore(0x5160, mload(0xb00)) + mstore(0x5180, mload(0xb20)) + mstore(0x51a0, sub(f_q, mload(0x4240))) + success := and(eq(staticcall(gas(), 0x7, 0x5160, 0x60, 0x5160, 0x40), 1), success) + mstore(0x51c0, mload(0x50e0)) + mstore(0x51e0, mload(0x5100)) + mstore(0x5200, mload(0x5160)) + mstore(0x5220, mload(0x5180)) + success := and(eq(staticcall(gas(), 0x6, 0x51c0, 0x80, 0x51c0, 0x40), 1), success) + mstore(0x5240, mload(0xba0)) + mstore(0x5260, mload(0xbc0)) + mstore(0x5280, mload(0x4260)) + success := and(eq(staticcall(gas(), 0x7, 0x5240, 0x60, 0x5240, 0x40), 1), success) + mstore(0x52a0, mload(0x51c0)) + mstore(0x52c0, mload(0x51e0)) + mstore(0x52e0, mload(0x5240)) + mstore(0x5300, mload(0x5260)) + success := and(eq(staticcall(gas(), 0x6, 0x52a0, 0x80, 0x52a0, 0x40), 1), success) + mstore(0x5320, mload(0x52a0)) + mstore(0x5340, mload(0x52c0)) + mstore(0x5360, mload(0xba0)) + mstore(0x5380, mload(0xbc0)) + mstore(0x53a0, mload(0xbe0)) + mstore(0x53c0, mload(0xc00)) + mstore(0x53e0, mload(0xc20)) + mstore(0x5400, mload(0xc40)) + mstore(0x5420, keccak256(0x5320, 256)) + mstore(21568, mod(mload(21536), f_q)) + mstore(0x5460, mulmod(mload(0x5440), mload(0x5440), f_q)) + mstore(0x5480, mulmod(1, mload(0x5440), f_q)) + mstore(0x54a0, mload(0x53a0)) + mstore(0x54c0, mload(0x53c0)) + mstore(0x54e0, mload(0x5480)) + success := and(eq(staticcall(gas(), 0x7, 0x54a0, 0x60, 0x54a0, 0x40), 1), success) + mstore(0x5500, mload(0x5320)) + mstore(0x5520, mload(0x5340)) + mstore(0x5540, mload(0x54a0)) + mstore(0x5560, mload(0x54c0)) + success := and(eq(staticcall(gas(), 0x6, 0x5500, 0x80, 0x5500, 0x40), 1), success) + mstore(0x5580, mload(0x53e0)) + mstore(0x55a0, mload(0x5400)) + mstore(0x55c0, mload(0x5480)) + success := and(eq(staticcall(gas(), 0x7, 0x5580, 0x60, 0x5580, 0x40), 1), success) + mstore(0x55e0, mload(0x5360)) + mstore(0x5600, mload(0x5380)) + mstore(0x5620, mload(0x5580)) + mstore(0x5640, mload(0x55a0)) + success := and(eq(staticcall(gas(), 0x6, 0x55e0, 0x80, 0x55e0, 0x40), 1), success) + mstore(0x5660, mload(0x5500)) + mstore(0x5680, mload(0x5520)) + mstore(0x56a0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) + mstore(0x56c0, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x56e0, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0x5700, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + mstore(0x5720, mload(0x55e0)) + mstore(0x5740, mload(0x5600)) + mstore(0x5760, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) + mstore(0x5780, 0x2ae0c8c3a090f7200ff398ee9845bbae8f8c1445ae7b632212775f60a0e21600) + mstore(0x57a0, 0x190fa476a5b352809ed41d7a0d7fe12b8f685e3c12a6d83855dba27aaf469643) + mstore(0x57c0, 0x1c0a500618907df9e4273d5181e31088deb1f05132de037cbfe73888f97f77c9) + success := and(eq(staticcall(gas(), 0x8, 0x5660, 0x180, 0x5660, 0x20), 1), success) + success := and(eq(mload(0x5660), 1), success) + + // Revert if anything fails + if iszero(success) { revert(0, 0) } + + // Return empty bytes on success + return(0, 0) + } + } +} diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol new file mode 100644 index 0000000..2456ad9 --- /dev/null +++ b/src/OpenVmHalo2Verifier.sol @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +/// @notice This contract provides a thin wrapper around the Halo2 verifier +/// outputted by `snark-verifier`. +/// +/// @dev This contract should be inherited by the `snark-verifier` output. +abstract contract OpenVmHalo2Verifier { + error InvalidPartialProofLength(); + error InvalidGuestPvsLength(); + error ProofVerificationFailed(); + + uint256 private constant PARTIAL_PROOF_LENGTH = (12 + 43) * 32; + + uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + 32 + 43) * 32; + + /// @notice A wrapper that constructs the proof into the right format for + /// use with the `snark-verifier` verification. + /// + /// @dev This function assumes that `publicValues` encodes one `bytes32` + /// hash which is the hash of the public values. + /// + /// The verifier expected proof format is: + /// proof[..12 * 32]: KZG accumulators + /// proof[12 * 32..13 * 32]: app exe commit + /// proof[13 * 32..14 * 32]: leaf exe commit + /// proof[14 * 32..46 * 32]: guestPvsHash[0..32] + /// proof[46 * 32..]: Guest PVs Suffix + /// + /// Or with hex offsets + /// + /// proof[..0x180]: KZG accumulators + /// proof[0x180..0x1a0]: app exe commit + /// proof[0x1a0..0x1c0]: leaf exe commit + /// proof[0x1c0..0x5c0]: guestPvsHash[0..32] + /// proof[0x5c0..]: Guest PVs Suffix + /// + /// @param partialProof All components of the proof except the Guest PVs, + /// leaf and app exe commits. The expected format is: + /// `abi.encodePacked(KZG accumulators, Guest PVs Suffix)` + /// @param guestPvs The PVs revealed by the OpenVM guest program. This + /// contract is only compatible with a reveal of exactly 32 bytes. + /// @param appExeCommit The commitment to the RISC-V executable whose execution + /// is being verified. + /// @param leafExeCommit The commitment to the leaf verifier. + function verifyProof( + bytes calldata partialProof, + bytes calldata guestPvs, + bytes32 appExeCommit, + bytes32 leafExeCommit + ) external view { + if (guestPvs.length != 32) revert InvalidGuestPvsLength(); + if (partialProof.length != PARTIAL_PROOF_LENGTH) revert InvalidPartialProofLength(); + + // We will format the pvsHash and construct the full proof payload + // below for submission to the verifier. + + // The assembly code should perform the same function as the following + // solidity code: + // + // bytes memory guestPvsPayload = new bytes(32 * 32); + // for (uint256 i = 0; i < 32; ++i) { + // bytes1 pvsByte = guestPvs[i]; + // guestPvsPayload = bytes.concat(guestPvsPayload, bytes32(uint256(uint8(pvsByte)))); + // } + // + // bytes memory proof = + // abi.encodePacked(partialProof[0:0x180], appExeCommit, leafExeCommit, guestPvsPayload, partialProof[0x180:]); + // + // (bool success,) = address(this).staticcall(proof); + // if (!success) revert ProofVerificationFailed(); + + /// @solidity memory-safe-assembly + assembly { + let fmp := mload(0x40) + mstore(0x40, add(fmp, FULL_PROOF_LENGTH)) + + let guestPvsHash := calldataload(guestPvs.offset) + + // Copy the KZG accumulators (length 0x180) into the beginning of + // the memory buffer + calldatacopy(fmp, partialProof.offset, 0x180) + + // Copy the App Exe Commit and Leaf Exe Commit into the memory buffer + mstore(add(fmp, 0x180), appExeCommit) + mstore(add(fmp, 0x1a0), leafExeCommit) + + // Copy the Guest PVs Suffix (length 43 * 32 = 0x560) into the + // end of the memory buffer (between 0x5c0 - TOTAL_PROOF_LENGTH), + // leaving 32 words in between for the guestPvsHash. + // + // Begin copying from the end of the KZG accumulators in the + // calldata buffer (0x180) + calldatacopy(add(fmp, 0x5c0), add(partialProof.offset, 0x180), 0x560) + + // Copy each byte of the guestPvsHash into the proof. It copies the + // most significant bytes of guestPvsHash first. + let guestPvsMemOffset := add(fmp, 0x1c0) + mstore(add(guestPvsMemOffset, 0x00), byte(0x00, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x20), byte(0x01, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x40), byte(0x02, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x60), byte(0x03, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x80), byte(0x04, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0xa0), byte(0x05, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0xc0), byte(0x06, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0xe0), byte(0x07, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x100), byte(0x08, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x120), byte(0x09, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x140), byte(0x0a, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x160), byte(0x0b, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x180), byte(0x0c, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x1a0), byte(0x0d, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x1c0), byte(0x0e, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x1e0), byte(0x0f, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x200), byte(0x10, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x220), byte(0x11, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x240), byte(0x12, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x260), byte(0x13, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x280), byte(0x14, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x2a0), byte(0x15, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x2c0), byte(0x16, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x2e0), byte(0x17, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x300), byte(0x18, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x320), byte(0x19, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x340), byte(0x1a, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x360), byte(0x1b, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x380), byte(0x1c, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x3a0), byte(0x1d, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x3c0), byte(0x1e, guestPvsHash)) + mstore(add(guestPvsMemOffset, 0x3e0), byte(0x1f, guestPvsHash)) + + // Self-call using the proof as calldata + if iszero(staticcall(gas(), address(), fmp, FULL_PROOF_LENGTH, 0, 0)) { + mstore(0x00, 0xd611c318) // ProofVerificationFailed() + revert(0x1c, 0x04) + } + } + } +} diff --git a/src/ProofFormatter.sol b/src/ProofFormatter.sol deleted file mode 100644 index 0a3346c..0000000 --- a/src/ProofFormatter.sol +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.19; - -error ProofVerificationFailed(); -error InvalidAppExeCommit(); -error InvalidLeafExeCommit(); - -function formatAndVerifyProof( - bytes calldata partialProof, - bytes memory publicValues, - address verifier, - bytes32 appExeCommit, - bytes32 leafExeCommit -) view { - /// @solidity memory-safe-assembly - assembly { - let partialProofLength := partialProof.length - let pvsLength := mload(publicValues) - let totalProofLength := add(partialProofLength, pvsLength) - let suffixOffset := add(pvsLength, 0x1c0) - - // Allocate for the memory usage as a safety measure. - let fmp := mload(0x40) - mstore(0x40, add(fmp, totalProofLength)) - - if iszero(eq(calldataload(add(partialProof.offset, 0x180)), appExeCommit)) { - mstore(0x00, 0x8cda48cf) // InvalidAppExeCommit() - revert(0x1c, 0x04) - } - - if iszero(eq(calldataload(add(partialProof.offset, 0x1a0)), leafExeCommit)) { - mstore(0x00, 0x438a69e7) // InvalidLeafExeCommit() - revert(0x1c, 0x04) - } - - // Copy the Guest PVs Prefix (length 0x1c0) into the beginning of - // the memory buffer - calldatacopy(fmp, partialProof.offset, 0x1c0) - - // Copy the Guest PVs Suffix (length 43 * 32 = 0x560) into the - // end of the memory buffer (between suffixOffset - TOTAL_PROOF_LENGTH), - // leaving 32 words in between for the guestPvsHash. - // - // Begin copying from the end of the Guest PVs Prefix in the - // calldata buffer (0x1c0) - calldatacopy(add(fmp, suffixOffset), add(partialProof.offset, 0x1c0), 0x560) - - // Copy each byte of the guestPvsHash into the proof. It copies the - // most significant bytes of guestPvsHash first. - - // Begin by loading 32-byte segments and copying each byte into its own memory slot. - let wordCount := div(pvsLength, 32) - let pvsReadOffset := add(publicValues, 0x20) - - let guestPvsMemOffset := add(fmp, 0x1c0) - for { let i := 0 } iszero(eq(i, wordCount)) { i := add(i, 1) } { - let word := mload(add(pvsReadOffset, shl(5, i))) - for { let j := 0 } iszero(eq(j, 32)) { j := add(j, 1) } { - mstore(add(guestPvsMemOffset, add(shl(5, i), j)), byte(j, word)) - } - } - - // Then, copy the remaining bytes into the memory buffer. - let remainder := mod(pvsLength, 32) - guestPvsMemOffset := add(guestPvsMemOffset, shl(5, wordCount)) - - let remainingBytes := mload(add(pvsReadOffset, shl(5, wordCount))) - for { let i := 0 } iszero(eq(i, remainder)) { i := add(i, 1) } { - mstore(add(guestPvsMemOffset, shl(5, i)), byte(i, remainingBytes)) - } - - if iszero(staticcall(gas(), verifier, fmp, totalProofLength, 0, 0)) { - mstore(0x00, 0xd611c318) // ProofVerificationFailed() - revert(0x1c, 0x04) - } - } -} diff --git a/test/OpenVmHalo2Verifier.t.sol b/test/OpenVmHalo2Verifier.t.sol new file mode 100644 index 0000000..146aee8 --- /dev/null +++ b/test/OpenVmHalo2Verifier.t.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import { OpenVmHalo2Verifier } from "../src/OpenVmHalo2Verifier.sol"; +import { Test, console2, safeconsole as console } from "forge-std/Test.sol"; + +contract MockVerifier is OpenVmHalo2Verifier { + fallback(bytes calldata) external returns (bytes memory) { + return hex""; + } +} + +contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { + bytes partialProof; + bytes32 appExeCommit = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + bytes32 leafExeCommit = 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; + bytes32 guestPvsHash = 0xDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; + + function setUp() public { + partialProof = new bytes(55 * 32); + for (uint256 i = 0; i < 55; i++) { + for (uint256 j = 0; j < 32; j++) { + partialProof[i * 32 + j] = bytes1(uint8(i)); + } + } + } + + function test_proofFormat() public view { + this.verifyProof(partialProof, abi.encodePacked(guestPvsHash), appExeCommit, leafExeCommit); + } + + function testFuzz_proofFormat( + uint256 partialProofSeed, + bytes32 _guestPvsHash, + bytes32 _appExeCommit, + bytes32 _leafExeCommit + ) public { + vm.assume(_guestPvsHash != bytes32(0)); + vm.assume(_appExeCommit != bytes32(0)); + vm.assume(_leafExeCommit != bytes32(0)); + + bytes memory _partialProof = new bytes(55 * 32); + for (uint256 i = 0; i < 55 * 32; ++i) { + bytes1 _byte = bytes1(uint8(uint256(keccak256(abi.encodePacked(partialProofSeed, i))))); + _partialProof[i] = _byte; + } + + partialProof = _partialProof; + guestPvsHash = _guestPvsHash; + appExeCommit = _appExeCommit; + leafExeCommit = _leafExeCommit; + + test_proofFormat(); + } + + function test_RevertWhen_InvalidPartialProofLength() public { + vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidPartialProofLength.selector)); + this.verifyProof(hex"aa", abi.encodePacked(guestPvsHash), appExeCommit, leafExeCommit); + } + + function test_RevertWhen_InvalidGuestPvsLength() public { + vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidGuestPvsLength.selector)); + this.verifyProof(partialProof, hex"aa", appExeCommit, leafExeCommit); + } + + fallback(bytes calldata) external returns (bytes memory) { + bytes memory partialProofExpected = partialProof; + + bytes memory kzgAccumulators = msg.data[0:0x180]; + bytes memory guestPvsSuffix = msg.data[0x5c0:]; + bytes memory _partialProof = abi.encodePacked(kzgAccumulators, guestPvsSuffix); + require(keccak256(_partialProof) == keccak256(partialProofExpected), "Partial proof mismatch"); + + bytes memory _appExeCommit = msg.data[0x180:0x1a0]; + bytes memory _leafExeCommit = msg.data[0x1a0:0x1c0]; + + require(bytes32(_appExeCommit) == appExeCommit, "App exe commit mismatch"); + require(bytes32(_leafExeCommit) == leafExeCommit, "Leaf exe commit mismatch"); + + bytes32 guestPvsHashExpected = guestPvsHash; + bytes calldata _guestPvsHash = msg.data[0x1c0:0x5c0]; + for (uint256 i = 0; i < 32; ++i) { + uint256 expected = uint256(uint8(guestPvsHashExpected[i])); + uint256 actual = uint256(bytes32(_guestPvsHash[i * 32:(i + 1) * 32])); + require(expected == actual, "Guest PVs hash mismatch"); + } + + return hex""; + } +} From 958c96cb931dd9c15731881947918aa0648a5a1f Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Wed, 19 Mar 2025 17:04:07 -0400 Subject: [PATCH 02/15] refactor: flip args --- src/OpenVmHalo2Verifier.sol | 2 +- test/OpenVmHalo2Verifier.t.sol | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index 2456ad9..0795b49 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -44,8 +44,8 @@ abstract contract OpenVmHalo2Verifier { /// is being verified. /// @param leafExeCommit The commitment to the leaf verifier. function verifyProof( - bytes calldata partialProof, bytes calldata guestPvs, + bytes calldata partialProof, bytes32 appExeCommit, bytes32 leafExeCommit ) external view { diff --git a/test/OpenVmHalo2Verifier.t.sol b/test/OpenVmHalo2Verifier.t.sol index 146aee8..5935fd8 100644 --- a/test/OpenVmHalo2Verifier.t.sol +++ b/test/OpenVmHalo2Verifier.t.sol @@ -26,7 +26,7 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { } function test_proofFormat() public view { - this.verifyProof(partialProof, abi.encodePacked(guestPvsHash), appExeCommit, leafExeCommit); + this.verifyProof(abi.encodePacked(guestPvsHash), partialProof, appExeCommit, leafExeCommit); } function testFuzz_proofFormat( @@ -55,7 +55,7 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { function test_RevertWhen_InvalidPartialProofLength() public { vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidPartialProofLength.selector)); - this.verifyProof(hex"aa", abi.encodePacked(guestPvsHash), appExeCommit, leafExeCommit); + this.verifyProof(abi.encodePacked(guestPvsHash), hex"aa", appExeCommit, leafExeCommit); } function test_RevertWhen_InvalidGuestPvsLength() public { From 0a6416e71244b3a56366c15268ee2f105492c505 Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Wed, 19 Mar 2025 20:48:13 -0400 Subject: [PATCH 03/15] refactor: separate the proof construction into its own function --- src/Halo2Verifier.sol | 3100 ++++++++++++++++---------------- src/OpenVmHalo2Verifier.sol | 134 +- test/OpenVmHalo2Verifier.t.sol | 89 +- 3 files changed, 1688 insertions(+), 1635 deletions(-) diff --git a/src/Halo2Verifier.sol b/src/Halo2Verifier.sol index b2c4f9c..caa5bbc 100644 --- a/src/Halo2Verifier.sol +++ b/src/Halo2Verifier.sol @@ -1,1569 +1,1567 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import { OpenVmHalo2Verifier } from "./OpenVmHalo2Verifier.sol"; - -contract AxiomV2QueryVerifier is OpenVmHalo2Verifier { +contract AxiomV2QueryVerifier { fallback(bytes calldata) external returns (bytes memory) { - assembly ("memory-safe") { - // Enforce that Solidity memory layout is respected - let data := mload(0x40) - if iszero(eq(data, 0x80)) { revert(0, 0) } - - let success := true - let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - let f_q := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 - function validate_ec_point(x, y) -> valid { - { - let x_lt_p := lt(x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let y_lt_p := lt(y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - valid := and(x_lt_p, y_lt_p) - } - { - let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube := - mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube_plus_3 := - addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let is_affine := eq(x_cube_plus_3, y_square) - valid := and(valid, is_affine) - } - } - mstore(0xa0, mod(calldataload(0x0), f_q)) - mstore(0xc0, mod(calldataload(0x20), f_q)) - mstore(0xe0, mod(calldataload(0x40), f_q)) - mstore(0x100, mod(calldataload(0x60), f_q)) - mstore(0x120, mod(calldataload(0x80), f_q)) - mstore(0x140, mod(calldataload(0xa0), f_q)) - mstore(0x160, mod(calldataload(0xc0), f_q)) - mstore(0x180, mod(calldataload(0xe0), f_q)) - mstore(0x1a0, mod(calldataload(0x100), f_q)) - mstore(0x1c0, mod(calldataload(0x120), f_q)) - mstore(0x1e0, mod(calldataload(0x140), f_q)) - mstore(0x200, mod(calldataload(0x160), f_q)) - mstore(0x220, mod(calldataload(0x180), f_q)) - mstore(0x240, mod(calldataload(0x1a0), f_q)) - mstore(0x260, mod(calldataload(0x1c0), f_q)) - mstore(0x280, mod(calldataload(0x1e0), f_q)) - mstore(0x2a0, mod(calldataload(0x200), f_q)) - mstore(0x2c0, mod(calldataload(0x220), f_q)) - mstore(0x2e0, mod(calldataload(0x240), f_q)) - mstore(0x300, mod(calldataload(0x260), f_q)) - mstore(0x320, mod(calldataload(0x280), f_q)) - mstore(0x340, mod(calldataload(0x2a0), f_q)) - mstore(0x360, mod(calldataload(0x2c0), f_q)) - mstore(0x80, 15186165512185359347397944531838604952299016691786397857821503921188369501699) - - { - let x := calldataload(0x2e0) - mstore(0x380, x) - let y := calldataload(0x300) - mstore(0x3a0, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0x3c0, keccak256(0x80, 832)) - { - let hash := mload(0x3c0) - mstore(0x3e0, mod(hash, f_q)) - mstore(0x400, hash) - } - - { - let x := calldataload(0x320) - mstore(0x420, x) - let y := calldataload(0x340) - mstore(0x440, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x360) - mstore(0x460, x) - let y := calldataload(0x380) - mstore(0x480, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0x4a0, keccak256(0x400, 160)) - { - let hash := mload(0x4a0) - mstore(0x4c0, mod(hash, f_q)) - mstore(0x4e0, hash) - } - mstore8(1280, 1) - mstore(0x500, keccak256(0x4e0, 33)) - { - let hash := mload(0x500) - mstore(0x520, mod(hash, f_q)) - mstore(0x540, hash) - } - - { - let x := calldataload(0x3a0) - mstore(0x560, x) - let y := calldataload(0x3c0) - mstore(0x580, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x3e0) - mstore(0x5a0, x) - let y := calldataload(0x400) - mstore(0x5c0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x420) - mstore(0x5e0, x) - let y := calldataload(0x440) - mstore(0x600, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0x620, keccak256(0x540, 224)) - { - let hash := mload(0x620) - mstore(0x640, mod(hash, f_q)) - mstore(0x660, hash) - } - - { - let x := calldataload(0x460) - mstore(0x680, x) - let y := calldataload(0x480) - mstore(0x6a0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x4a0) - mstore(0x6c0, x) - let y := calldataload(0x4c0) - mstore(0x6e0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x4e0) - mstore(0x700, x) - let y := calldataload(0x500) - mstore(0x720, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x520) - mstore(0x740, x) - let y := calldataload(0x540) - mstore(0x760, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0x780, keccak256(0x660, 288)) - { - let hash := mload(0x780) - mstore(0x7a0, mod(hash, f_q)) - mstore(0x7c0, hash) - } - mstore(0x7e0, mod(calldataload(0x560), f_q)) - mstore(0x800, mod(calldataload(0x580), f_q)) - mstore(0x820, mod(calldataload(0x5a0), f_q)) - mstore(0x840, mod(calldataload(0x5c0), f_q)) - mstore(0x860, mod(calldataload(0x5e0), f_q)) - mstore(0x880, mod(calldataload(0x600), f_q)) - mstore(0x8a0, mod(calldataload(0x620), f_q)) - mstore(0x8c0, mod(calldataload(0x640), f_q)) - mstore(0x8e0, mod(calldataload(0x660), f_q)) - mstore(0x900, mod(calldataload(0x680), f_q)) - mstore(0x920, mod(calldataload(0x6a0), f_q)) - mstore(0x940, mod(calldataload(0x6c0), f_q)) - mstore(0x960, mod(calldataload(0x6e0), f_q)) - mstore(0x980, mod(calldataload(0x700), f_q)) - mstore(0x9a0, mod(calldataload(0x720), f_q)) - mstore(0x9c0, mod(calldataload(0x740), f_q)) - mstore(0x9e0, mod(calldataload(0x760), f_q)) - mstore(0xa00, mod(calldataload(0x780), f_q)) - mstore(0xa20, mod(calldataload(0x7a0), f_q)) - mstore(0xa40, keccak256(0x7c0, 640)) - { - let hash := mload(0xa40) - mstore(0xa60, mod(hash, f_q)) - mstore(0xa80, hash) - } - mstore8(2720, 1) - mstore(0xaa0, keccak256(0xa80, 33)) - { - let hash := mload(0xaa0) - mstore(0xac0, mod(hash, f_q)) - mstore(0xae0, hash) - } - - { - let x := calldataload(0x7c0) - mstore(0xb00, x) - let y := calldataload(0x7e0) - mstore(0xb20, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0xb40, keccak256(0xae0, 96)) - { - let hash := mload(0xb40) - mstore(0xb60, mod(hash, f_q)) - mstore(0xb80, hash) - } - - { - let x := calldataload(0x800) - mstore(0xba0, x) - let y := calldataload(0x820) - mstore(0xbc0, y) - success := and(validate_ec_point(x, y), success) - } - { - let x := mload(0xa0) - x := add(x, shl(88, mload(0xc0))) - x := add(x, shl(176, mload(0xe0))) - mstore(3040, x) - let y := mload(0x100) - y := add(y, shl(88, mload(0x120))) - y := add(y, shl(176, mload(0x140))) - mstore(3072, y) - - success := and(validate_ec_point(x, y), success) - } - { - let x := mload(0x160) - x := add(x, shl(88, mload(0x180))) - x := add(x, shl(176, mload(0x1a0))) - mstore(3104, x) - let y := mload(0x1c0) - y := add(y, shl(88, mload(0x1e0))) - y := add(y, shl(176, mload(0x200))) - mstore(3136, y) - - success := and(validate_ec_point(x, y), success) - } - mstore(0xc60, mulmod(mload(0x7a0), mload(0x7a0), f_q)) - mstore(0xc80, mulmod(mload(0xc60), mload(0xc60), f_q)) - mstore(0xca0, mulmod(mload(0xc80), mload(0xc80), f_q)) - mstore(0xcc0, mulmod(mload(0xca0), mload(0xca0), f_q)) - mstore(0xce0, mulmod(mload(0xcc0), mload(0xcc0), f_q)) - mstore(0xd00, mulmod(mload(0xce0), mload(0xce0), f_q)) - mstore(0xd20, mulmod(mload(0xd00), mload(0xd00), f_q)) - mstore(0xd40, mulmod(mload(0xd20), mload(0xd20), f_q)) - mstore(0xd60, mulmod(mload(0xd40), mload(0xd40), f_q)) - mstore(0xd80, mulmod(mload(0xd60), mload(0xd60), f_q)) - mstore(0xda0, mulmod(mload(0xd80), mload(0xd80), f_q)) - mstore(0xdc0, mulmod(mload(0xda0), mload(0xda0), f_q)) - mstore(0xde0, mulmod(mload(0xdc0), mload(0xdc0), f_q)) - mstore(0xe00, mulmod(mload(0xde0), mload(0xde0), f_q)) - mstore(0xe20, mulmod(mload(0xe00), mload(0xe00), f_q)) - mstore(0xe40, mulmod(mload(0xe20), mload(0xe20), f_q)) - mstore(0xe60, mulmod(mload(0xe40), mload(0xe40), f_q)) - mstore(0xe80, mulmod(mload(0xe60), mload(0xe60), f_q)) - mstore(0xea0, mulmod(mload(0xe80), mload(0xe80), f_q)) - mstore(0xec0, mulmod(mload(0xea0), mload(0xea0), f_q)) - mstore(0xee0, mulmod(mload(0xec0), mload(0xec0), f_q)) - mstore(0xf00, mulmod(mload(0xee0), mload(0xee0), f_q)) - mstore(0xf20, mulmod(mload(0xf00), mload(0xf00), f_q)) - mstore( - 0xf40, - addmod(mload(0xf20), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) - ) - mstore( - 0xf60, - mulmod(mload(0xf40), 21888240262557392955334514970720457388010314637169927192662615958087340972065, f_q) - ) - mstore( - 0xf80, - mulmod(mload(0xf60), 4506835738822104338668100540817374747935106310012997856968187171738630203507, f_q) - ) - mstore( - 0xfa0, - addmod(mload(0x7a0), 17381407133017170883578305204439900340613258090403036486730017014837178292110, f_q) - ) - mstore( - 0xfc0, - mulmod(mload(0xf60), 21710372849001950800533397158415938114909991150039389063546734567764856596059, f_q) - ) - mstore( - 0xfe0, - addmod(mload(0x7a0), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q) - ) - mstore( - 0x1000, - mulmod(mload(0xf60), 1887003188133998471169152042388914354640772748308168868301418279904560637395, f_q) - ) - mstore( - 0x1020, - addmod(mload(0x7a0), 20001239683705276751077253702868360733907591652107865475396785906671247858222, f_q) - ) - mstore( - 0x1040, - mulmod(mload(0xf60), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q) - ) - mstore( - 0x1060, - addmod(mload(0x7a0), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q) - ) - mstore( - 0x1080, - mulmod(mload(0xf60), 14655294445420895451632927078981340937842238432098198055057679026789553137428, f_q) - ) - mstore( - 0x10a0, - addmod(mload(0x7a0), 7232948426418379770613478666275934150706125968317836288640525159786255358189, f_q) - ) - mstore( - 0x10c0, - mulmod(mload(0xf60), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) - ) - mstore( - 0x10e0, - addmod(mload(0x7a0), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q) - ) - mstore( - 0x1100, - mulmod(mload(0xf60), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) - ) - mstore( - 0x1120, - addmod(mload(0x7a0), 12146688980418810893951125255607130521645347193942732958664170801695864621270, f_q) - ) - mstore(0x1140, mulmod(mload(0xf60), 1, f_q)) - mstore( - 0x1160, - addmod(mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) - ) - mstore( - 0x1180, - mulmod(mload(0xf60), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) - ) - mstore( - 0x11a0, - addmod(mload(0x7a0), 13513867906530865119835332133273263211836799082674232843258448413103731898270, f_q) - ) - mstore( - 0x11c0, - mulmod(mload(0xf60), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) - ) - mstore( - 0x11e0, - addmod(mload(0x7a0), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q) - ) - mstore( - 0x1200, - mulmod(mload(0xf60), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) - ) - mstore( - 0x1220, - addmod(mload(0x7a0), 18272764063556419981698118473909131571661591947471949595929891197711371770216, f_q) - ) - mstore( - 0x1240, - mulmod(mload(0xf60), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) - ) - mstore( - 0x1260, - addmod(mload(0x7a0), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q) - ) - mstore( - 0x1280, - mulmod(mload(0xf60), 216092043779272773661818549620449970334216366264741118684015851799902419467, f_q) - ) - mstore( - 0x12a0, - addmod(mload(0x7a0), 21672150828060002448584587195636825118214148034151293225014188334775906076150, f_q) - ) - mstore( - 0x12c0, - mulmod(mload(0xf60), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q) - ) - mstore( - 0x12e0, - addmod(mload(0x7a0), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q) - ) - mstore( - 0x1300, - mulmod(mload(0xf60), 18610195890048912503953886742825279624920778288956610528523679659246523534888, f_q) - ) - mstore( - 0x1320, - addmod(mload(0x7a0), 3278046981790362718292519002431995463627586111459423815174524527329284960729, f_q) - ) - mstore( - 0x1340, - mulmod(mload(0xf60), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q) - ) - mstore( - 0x1360, - addmod(mload(0x7a0), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q) - ) - mstore( - 0x1380, - mulmod(mload(0xf60), 14875928112196239563830800280253496262679717528621719058794366823499719730250, f_q) - ) - mstore( - 0x13a0, - addmod(mload(0x7a0), 7012314759643035658415605465003778825868646871794315284903837363076088765367, f_q) - ) - mstore( - 0x13c0, - mulmod(mload(0xf60), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q) - ) - mstore( - 0x13e0, - addmod(mload(0x7a0), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q) - ) - mstore( - 0x1400, - mulmod(mload(0xf60), 5522161504810533295870699551020523636289972223872138525048055197429246400245, f_q) - ) - mstore( - 0x1420, - addmod(mload(0x7a0), 16366081367028741926375706194236751452258392176543895818650148989146562095372, f_q) - ) - mstore( - 0x1440, - mulmod(mload(0xf60), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q) - ) - mstore( - 0x1460, - addmod(mload(0x7a0), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q) - ) - mstore( - 0x1480, - mulmod(mload(0xf60), 9100833993744738801214480881117348002768153232283708533639316963648253510584, f_q) - ) - mstore( - 0x14a0, - addmod(mload(0x7a0), 12787408878094536421031924864139927085780211168132325810058887222927554985033, f_q) - ) - mstore( - 0x14c0, - mulmod(mload(0xf60), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q) - ) - mstore( - 0x14e0, - addmod(mload(0x7a0), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q) - ) - mstore( - 0x1500, - mulmod(mload(0xf60), 6132660129994545119218258312491950835441607143741804980633129304664017206141, f_q) - ) - mstore( - 0x1520, - addmod(mload(0x7a0), 15755582741844730103028147432765324253106757256674229363065074881911791289476, f_q) - ) - mstore( - 0x1540, - mulmod(mload(0xf60), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q) - ) - mstore( - 0x1560, - addmod(mload(0x7a0), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q) - ) - mstore( - 0x1580, - mulmod(mload(0xf60), 515148244606945972463850631189471072103916690263705052318085725998468254533, f_q) - ) - mstore( - 0x15a0, - addmod(mload(0x7a0), 21373094627232329249782555114067804016444447710152329291380118460577340241084, f_q) - ) - mstore( - 0x15c0, - mulmod(mload(0xf60), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q) - ) - mstore( - 0x15e0, - addmod(mload(0x7a0), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q) - ) - mstore( - 0x1600, - mulmod(mload(0xf60), 5223738580615264174925218065001555728265216895679471490312087802465486318994, f_q) - ) - mstore( - 0x1620, - addmod(mload(0x7a0), 16664504291224011047321187680255719360283147504736562853386116384110322176623, f_q) - ) - mstore( - 0x1640, - mulmod(mload(0xf60), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q) - ) - mstore( - 0x1660, - addmod(mload(0x7a0), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q) - ) - mstore( - 0x1680, - mulmod(mload(0xf60), 16976236069879939850923145256911338076234942200101755618884183331004076579046, f_q) - ) - mstore( - 0x16a0, - addmod(mload(0x7a0), 4912006801959335371323260488345937012313422200314278724814020855571731916571, f_q) - ) - mstore( - 0x16c0, - mulmod(mload(0xf60), 13553911191894110065493137367144919847521088405945523452288398666974237857208, f_q) - ) - mstore( - 0x16e0, - addmod(mload(0x7a0), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q) - ) - { - let prod := mload(0xfa0) - - prod := mulmod(mload(0xfe0), prod, f_q) - mstore(0x1700, prod) - - prod := mulmod(mload(0x1020), prod, f_q) - mstore(0x1720, prod) - - prod := mulmod(mload(0x1060), prod, f_q) - mstore(0x1740, prod) - - prod := mulmod(mload(0x10a0), prod, f_q) - mstore(0x1760, prod) - - prod := mulmod(mload(0x10e0), prod, f_q) - mstore(0x1780, prod) - - prod := mulmod(mload(0x1120), prod, f_q) - mstore(0x17a0, prod) - - prod := mulmod(mload(0x1160), prod, f_q) - mstore(0x17c0, prod) - - prod := mulmod(mload(0x11a0), prod, f_q) - mstore(0x17e0, prod) - - prod := mulmod(mload(0x11e0), prod, f_q) - mstore(0x1800, prod) - - prod := mulmod(mload(0x1220), prod, f_q) - mstore(0x1820, prod) - - prod := mulmod(mload(0x1260), prod, f_q) - mstore(0x1840, prod) - - prod := mulmod(mload(0x12a0), prod, f_q) - mstore(0x1860, prod) - - prod := mulmod(mload(0x12e0), prod, f_q) - mstore(0x1880, prod) - - prod := mulmod(mload(0x1320), prod, f_q) - mstore(0x18a0, prod) - - prod := mulmod(mload(0x1360), prod, f_q) - mstore(0x18c0, prod) - - prod := mulmod(mload(0x13a0), prod, f_q) - mstore(0x18e0, prod) - - prod := mulmod(mload(0x13e0), prod, f_q) - mstore(0x1900, prod) - - prod := mulmod(mload(0x1420), prod, f_q) - mstore(0x1920, prod) - - prod := mulmod(mload(0x1460), prod, f_q) - mstore(0x1940, prod) - - prod := mulmod(mload(0x14a0), prod, f_q) - mstore(0x1960, prod) - - prod := mulmod(mload(0x14e0), prod, f_q) - mstore(0x1980, prod) - - prod := mulmod(mload(0x1520), prod, f_q) - mstore(0x19a0, prod) - - prod := mulmod(mload(0x1560), prod, f_q) - mstore(0x19c0, prod) - - prod := mulmod(mload(0x15a0), prod, f_q) - mstore(0x19e0, prod) - - prod := mulmod(mload(0x15e0), prod, f_q) - mstore(0x1a00, prod) - - prod := mulmod(mload(0x1620), prod, f_q) - mstore(0x1a20, prod) + // assembly ("memory-safe") { + // // Enforce that Solidity memory layout is respected + // let data := mload(0x40) + // if iszero(eq(data, 0x80)) { revert(0, 0) } + + // let success := true + // let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + // let f_q := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 + // function validate_ec_point(x, y) -> valid { + // { + // let x_lt_p := lt(x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + // let y_lt_p := lt(y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + // valid := and(x_lt_p, y_lt_p) + // } + // { + // let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + // let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + // let x_cube := + // mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + // let x_cube_plus_3 := + // addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + // let is_affine := eq(x_cube_plus_3, y_square) + // valid := and(valid, is_affine) + // } + // } + // mstore(0xa0, mod(calldataload(0x0), f_q)) + // mstore(0xc0, mod(calldataload(0x20), f_q)) + // mstore(0xe0, mod(calldataload(0x40), f_q)) + // mstore(0x100, mod(calldataload(0x60), f_q)) + // mstore(0x120, mod(calldataload(0x80), f_q)) + // mstore(0x140, mod(calldataload(0xa0), f_q)) + // mstore(0x160, mod(calldataload(0xc0), f_q)) + // mstore(0x180, mod(calldataload(0xe0), f_q)) + // mstore(0x1a0, mod(calldataload(0x100), f_q)) + // mstore(0x1c0, mod(calldataload(0x120), f_q)) + // mstore(0x1e0, mod(calldataload(0x140), f_q)) + // mstore(0x200, mod(calldataload(0x160), f_q)) + // mstore(0x220, mod(calldataload(0x180), f_q)) + // mstore(0x240, mod(calldataload(0x1a0), f_q)) + // mstore(0x260, mod(calldataload(0x1c0), f_q)) + // mstore(0x280, mod(calldataload(0x1e0), f_q)) + // mstore(0x2a0, mod(calldataload(0x200), f_q)) + // mstore(0x2c0, mod(calldataload(0x220), f_q)) + // mstore(0x2e0, mod(calldataload(0x240), f_q)) + // mstore(0x300, mod(calldataload(0x260), f_q)) + // mstore(0x320, mod(calldataload(0x280), f_q)) + // mstore(0x340, mod(calldataload(0x2a0), f_q)) + // mstore(0x360, mod(calldataload(0x2c0), f_q)) + // mstore(0x80, 15186165512185359347397944531838604952299016691786397857821503921188369501699) + + // { + // let x := calldataload(0x2e0) + // mstore(0x380, x) + // let y := calldataload(0x300) + // mstore(0x3a0, y) + // success := and(validate_ec_point(x, y), success) + // } + // mstore(0x3c0, keccak256(0x80, 832)) + // { + // let hash := mload(0x3c0) + // mstore(0x3e0, mod(hash, f_q)) + // mstore(0x400, hash) + // } + + // { + // let x := calldataload(0x320) + // mstore(0x420, x) + // let y := calldataload(0x340) + // mstore(0x440, y) + // success := and(validate_ec_point(x, y), success) + // } + + // { + // let x := calldataload(0x360) + // mstore(0x460, x) + // let y := calldataload(0x380) + // mstore(0x480, y) + // success := and(validate_ec_point(x, y), success) + // } + // mstore(0x4a0, keccak256(0x400, 160)) + // { + // let hash := mload(0x4a0) + // mstore(0x4c0, mod(hash, f_q)) + // mstore(0x4e0, hash) + // } + // mstore8(1280, 1) + // mstore(0x500, keccak256(0x4e0, 33)) + // { + // let hash := mload(0x500) + // mstore(0x520, mod(hash, f_q)) + // mstore(0x540, hash) + // } + + // { + // let x := calldataload(0x3a0) + // mstore(0x560, x) + // let y := calldataload(0x3c0) + // mstore(0x580, y) + // success := and(validate_ec_point(x, y), success) + // } + + // { + // let x := calldataload(0x3e0) + // mstore(0x5a0, x) + // let y := calldataload(0x400) + // mstore(0x5c0, y) + // success := and(validate_ec_point(x, y), success) + // } + + // { + // let x := calldataload(0x420) + // mstore(0x5e0, x) + // let y := calldataload(0x440) + // mstore(0x600, y) + // success := and(validate_ec_point(x, y), success) + // } + // mstore(0x620, keccak256(0x540, 224)) + // { + // let hash := mload(0x620) + // mstore(0x640, mod(hash, f_q)) + // mstore(0x660, hash) + // } + + // { + // let x := calldataload(0x460) + // mstore(0x680, x) + // let y := calldataload(0x480) + // mstore(0x6a0, y) + // success := and(validate_ec_point(x, y), success) + // } + + // { + // let x := calldataload(0x4a0) + // mstore(0x6c0, x) + // let y := calldataload(0x4c0) + // mstore(0x6e0, y) + // success := and(validate_ec_point(x, y), success) + // } + + // { + // let x := calldataload(0x4e0) + // mstore(0x700, x) + // let y := calldataload(0x500) + // mstore(0x720, y) + // success := and(validate_ec_point(x, y), success) + // } + + // { + // let x := calldataload(0x520) + // mstore(0x740, x) + // let y := calldataload(0x540) + // mstore(0x760, y) + // success := and(validate_ec_point(x, y), success) + // } + // mstore(0x780, keccak256(0x660, 288)) + // { + // let hash := mload(0x780) + // mstore(0x7a0, mod(hash, f_q)) + // mstore(0x7c0, hash) + // } + // mstore(0x7e0, mod(calldataload(0x560), f_q)) + // mstore(0x800, mod(calldataload(0x580), f_q)) + // mstore(0x820, mod(calldataload(0x5a0), f_q)) + // mstore(0x840, mod(calldataload(0x5c0), f_q)) + // mstore(0x860, mod(calldataload(0x5e0), f_q)) + // mstore(0x880, mod(calldataload(0x600), f_q)) + // mstore(0x8a0, mod(calldataload(0x620), f_q)) + // mstore(0x8c0, mod(calldataload(0x640), f_q)) + // mstore(0x8e0, mod(calldataload(0x660), f_q)) + // mstore(0x900, mod(calldataload(0x680), f_q)) + // mstore(0x920, mod(calldataload(0x6a0), f_q)) + // mstore(0x940, mod(calldataload(0x6c0), f_q)) + // mstore(0x960, mod(calldataload(0x6e0), f_q)) + // mstore(0x980, mod(calldataload(0x700), f_q)) + // mstore(0x9a0, mod(calldataload(0x720), f_q)) + // mstore(0x9c0, mod(calldataload(0x740), f_q)) + // mstore(0x9e0, mod(calldataload(0x760), f_q)) + // mstore(0xa00, mod(calldataload(0x780), f_q)) + // mstore(0xa20, mod(calldataload(0x7a0), f_q)) + // mstore(0xa40, keccak256(0x7c0, 640)) + // { + // let hash := mload(0xa40) + // mstore(0xa60, mod(hash, f_q)) + // mstore(0xa80, hash) + // } + // mstore8(2720, 1) + // mstore(0xaa0, keccak256(0xa80, 33)) + // { + // let hash := mload(0xaa0) + // mstore(0xac0, mod(hash, f_q)) + // mstore(0xae0, hash) + // } + + // { + // let x := calldataload(0x7c0) + // mstore(0xb00, x) + // let y := calldataload(0x7e0) + // mstore(0xb20, y) + // success := and(validate_ec_point(x, y), success) + // } + // mstore(0xb40, keccak256(0xae0, 96)) + // { + // let hash := mload(0xb40) + // mstore(0xb60, mod(hash, f_q)) + // mstore(0xb80, hash) + // } + + // { + // let x := calldataload(0x800) + // mstore(0xba0, x) + // let y := calldataload(0x820) + // mstore(0xbc0, y) + // success := and(validate_ec_point(x, y), success) + // } + // { + // let x := mload(0xa0) + // x := add(x, shl(88, mload(0xc0))) + // x := add(x, shl(176, mload(0xe0))) + // mstore(3040, x) + // let y := mload(0x100) + // y := add(y, shl(88, mload(0x120))) + // y := add(y, shl(176, mload(0x140))) + // mstore(3072, y) + + // success := and(validate_ec_point(x, y), success) + // } + // { + // let x := mload(0x160) + // x := add(x, shl(88, mload(0x180))) + // x := add(x, shl(176, mload(0x1a0))) + // mstore(3104, x) + // let y := mload(0x1c0) + // y := add(y, shl(88, mload(0x1e0))) + // y := add(y, shl(176, mload(0x200))) + // mstore(3136, y) + + // success := and(validate_ec_point(x, y), success) + // } + // mstore(0xc60, mulmod(mload(0x7a0), mload(0x7a0), f_q)) + // mstore(0xc80, mulmod(mload(0xc60), mload(0xc60), f_q)) + // mstore(0xca0, mulmod(mload(0xc80), mload(0xc80), f_q)) + // mstore(0xcc0, mulmod(mload(0xca0), mload(0xca0), f_q)) + // mstore(0xce0, mulmod(mload(0xcc0), mload(0xcc0), f_q)) + // mstore(0xd00, mulmod(mload(0xce0), mload(0xce0), f_q)) + // mstore(0xd20, mulmod(mload(0xd00), mload(0xd00), f_q)) + // mstore(0xd40, mulmod(mload(0xd20), mload(0xd20), f_q)) + // mstore(0xd60, mulmod(mload(0xd40), mload(0xd40), f_q)) + // mstore(0xd80, mulmod(mload(0xd60), mload(0xd60), f_q)) + // mstore(0xda0, mulmod(mload(0xd80), mload(0xd80), f_q)) + // mstore(0xdc0, mulmod(mload(0xda0), mload(0xda0), f_q)) + // mstore(0xde0, mulmod(mload(0xdc0), mload(0xdc0), f_q)) + // mstore(0xe00, mulmod(mload(0xde0), mload(0xde0), f_q)) + // mstore(0xe20, mulmod(mload(0xe00), mload(0xe00), f_q)) + // mstore(0xe40, mulmod(mload(0xe20), mload(0xe20), f_q)) + // mstore(0xe60, mulmod(mload(0xe40), mload(0xe40), f_q)) + // mstore(0xe80, mulmod(mload(0xe60), mload(0xe60), f_q)) + // mstore(0xea0, mulmod(mload(0xe80), mload(0xe80), f_q)) + // mstore(0xec0, mulmod(mload(0xea0), mload(0xea0), f_q)) + // mstore(0xee0, mulmod(mload(0xec0), mload(0xec0), f_q)) + // mstore(0xf00, mulmod(mload(0xee0), mload(0xee0), f_q)) + // mstore(0xf20, mulmod(mload(0xf00), mload(0xf00), f_q)) + // mstore( + // 0xf40, + // addmod(mload(0xf20), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) + // ) + // mstore( + // 0xf60, + // mulmod(mload(0xf40), 21888240262557392955334514970720457388010314637169927192662615958087340972065, f_q) + // ) + // mstore( + // 0xf80, + // mulmod(mload(0xf60), 4506835738822104338668100540817374747935106310012997856968187171738630203507, f_q) + // ) + // mstore( + // 0xfa0, + // addmod(mload(0x7a0), 17381407133017170883578305204439900340613258090403036486730017014837178292110, f_q) + // ) + // mstore( + // 0xfc0, + // mulmod(mload(0xf60), 21710372849001950800533397158415938114909991150039389063546734567764856596059, f_q) + // ) + // mstore( + // 0xfe0, + // addmod(mload(0x7a0), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q) + // ) + // mstore( + // 0x1000, + // mulmod(mload(0xf60), 1887003188133998471169152042388914354640772748308168868301418279904560637395, f_q) + // ) + // mstore( + // 0x1020, + // addmod(mload(0x7a0), 20001239683705276751077253702868360733907591652107865475396785906671247858222, f_q) + // ) + // mstore( + // 0x1040, + // mulmod(mload(0xf60), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q) + // ) + // mstore( + // 0x1060, + // addmod(mload(0x7a0), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q) + // ) + // mstore( + // 0x1080, + // mulmod(mload(0xf60), 14655294445420895451632927078981340937842238432098198055057679026789553137428, f_q) + // ) + // mstore( + // 0x10a0, + // addmod(mload(0x7a0), 7232948426418379770613478666275934150706125968317836288640525159786255358189, f_q) + // ) + // mstore( + // 0x10c0, + // mulmod(mload(0xf60), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) + // ) + // mstore( + // 0x10e0, + // addmod(mload(0x7a0), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q) + // ) + // mstore( + // 0x1100, + // mulmod(mload(0xf60), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + // ) + // mstore( + // 0x1120, + // addmod(mload(0x7a0), 12146688980418810893951125255607130521645347193942732958664170801695864621270, f_q) + // ) + // mstore(0x1140, mulmod(mload(0xf60), 1, f_q)) + // mstore( + // 0x1160, + // addmod(mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) + // ) + // mstore( + // 0x1180, + // mulmod(mload(0xf60), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + // ) + // mstore( + // 0x11a0, + // addmod(mload(0x7a0), 13513867906530865119835332133273263211836799082674232843258448413103731898270, f_q) + // ) + // mstore( + // 0x11c0, + // mulmod(mload(0xf60), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) + // ) + // mstore( + // 0x11e0, + // addmod(mload(0x7a0), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q) + // ) + // mstore( + // 0x1200, + // mulmod(mload(0xf60), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + // ) + // mstore( + // 0x1220, + // addmod(mload(0x7a0), 18272764063556419981698118473909131571661591947471949595929891197711371770216, f_q) + // ) + // mstore( + // 0x1240, + // mulmod(mload(0xf60), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) + // ) + // mstore( + // 0x1260, + // addmod(mload(0x7a0), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q) + // ) + // mstore( + // 0x1280, + // mulmod(mload(0xf60), 216092043779272773661818549620449970334216366264741118684015851799902419467, f_q) + // ) + // mstore( + // 0x12a0, + // addmod(mload(0x7a0), 21672150828060002448584587195636825118214148034151293225014188334775906076150, f_q) + // ) + // mstore( + // 0x12c0, + // mulmod(mload(0xf60), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q) + // ) + // mstore( + // 0x12e0, + // addmod(mload(0x7a0), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q) + // ) + // mstore( + // 0x1300, + // mulmod(mload(0xf60), 18610195890048912503953886742825279624920778288956610528523679659246523534888, f_q) + // ) + // mstore( + // 0x1320, + // addmod(mload(0x7a0), 3278046981790362718292519002431995463627586111459423815174524527329284960729, f_q) + // ) + // mstore( + // 0x1340, + // mulmod(mload(0xf60), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q) + // ) + // mstore( + // 0x1360, + // addmod(mload(0x7a0), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q) + // ) + // mstore( + // 0x1380, + // mulmod(mload(0xf60), 14875928112196239563830800280253496262679717528621719058794366823499719730250, f_q) + // ) + // mstore( + // 0x13a0, + // addmod(mload(0x7a0), 7012314759643035658415605465003778825868646871794315284903837363076088765367, f_q) + // ) + // mstore( + // 0x13c0, + // mulmod(mload(0xf60), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q) + // ) + // mstore( + // 0x13e0, + // addmod(mload(0x7a0), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q) + // ) + // mstore( + // 0x1400, + // mulmod(mload(0xf60), 5522161504810533295870699551020523636289972223872138525048055197429246400245, f_q) + // ) + // mstore( + // 0x1420, + // addmod(mload(0x7a0), 16366081367028741926375706194236751452258392176543895818650148989146562095372, f_q) + // ) + // mstore( + // 0x1440, + // mulmod(mload(0xf60), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q) + // ) + // mstore( + // 0x1460, + // addmod(mload(0x7a0), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q) + // ) + // mstore( + // 0x1480, + // mulmod(mload(0xf60), 9100833993744738801214480881117348002768153232283708533639316963648253510584, f_q) + // ) + // mstore( + // 0x14a0, + // addmod(mload(0x7a0), 12787408878094536421031924864139927085780211168132325810058887222927554985033, f_q) + // ) + // mstore( + // 0x14c0, + // mulmod(mload(0xf60), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q) + // ) + // mstore( + // 0x14e0, + // addmod(mload(0x7a0), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q) + // ) + // mstore( + // 0x1500, + // mulmod(mload(0xf60), 6132660129994545119218258312491950835441607143741804980633129304664017206141, f_q) + // ) + // mstore( + // 0x1520, + // addmod(mload(0x7a0), 15755582741844730103028147432765324253106757256674229363065074881911791289476, f_q) + // ) + // mstore( + // 0x1540, + // mulmod(mload(0xf60), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q) + // ) + // mstore( + // 0x1560, + // addmod(mload(0x7a0), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q) + // ) + // mstore( + // 0x1580, + // mulmod(mload(0xf60), 515148244606945972463850631189471072103916690263705052318085725998468254533, f_q) + // ) + // mstore( + // 0x15a0, + // addmod(mload(0x7a0), 21373094627232329249782555114067804016444447710152329291380118460577340241084, f_q) + // ) + // mstore( + // 0x15c0, + // mulmod(mload(0xf60), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q) + // ) + // mstore( + // 0x15e0, + // addmod(mload(0x7a0), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q) + // ) + // mstore( + // 0x1600, + // mulmod(mload(0xf60), 5223738580615264174925218065001555728265216895679471490312087802465486318994, f_q) + // ) + // mstore( + // 0x1620, + // addmod(mload(0x7a0), 16664504291224011047321187680255719360283147504736562853386116384110322176623, f_q) + // ) + // mstore( + // 0x1640, + // mulmod(mload(0xf60), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q) + // ) + // mstore( + // 0x1660, + // addmod(mload(0x7a0), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q) + // ) + // mstore( + // 0x1680, + // mulmod(mload(0xf60), 16976236069879939850923145256911338076234942200101755618884183331004076579046, f_q) + // ) + // mstore( + // 0x16a0, + // addmod(mload(0x7a0), 4912006801959335371323260488345937012313422200314278724814020855571731916571, f_q) + // ) + // mstore( + // 0x16c0, + // mulmod(mload(0xf60), 13553911191894110065493137367144919847521088405945523452288398666974237857208, f_q) + // ) + // mstore( + // 0x16e0, + // addmod(mload(0x7a0), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q) + // ) + // { + // let prod := mload(0xfa0) + + // prod := mulmod(mload(0xfe0), prod, f_q) + // mstore(0x1700, prod) + + // prod := mulmod(mload(0x1020), prod, f_q) + // mstore(0x1720, prod) + + // prod := mulmod(mload(0x1060), prod, f_q) + // mstore(0x1740, prod) + + // prod := mulmod(mload(0x10a0), prod, f_q) + // mstore(0x1760, prod) + + // prod := mulmod(mload(0x10e0), prod, f_q) + // mstore(0x1780, prod) + + // prod := mulmod(mload(0x1120), prod, f_q) + // mstore(0x17a0, prod) + + // prod := mulmod(mload(0x1160), prod, f_q) + // mstore(0x17c0, prod) + + // prod := mulmod(mload(0x11a0), prod, f_q) + // mstore(0x17e0, prod) + + // prod := mulmod(mload(0x11e0), prod, f_q) + // mstore(0x1800, prod) + + // prod := mulmod(mload(0x1220), prod, f_q) + // mstore(0x1820, prod) + + // prod := mulmod(mload(0x1260), prod, f_q) + // mstore(0x1840, prod) + + // prod := mulmod(mload(0x12a0), prod, f_q) + // mstore(0x1860, prod) + + // prod := mulmod(mload(0x12e0), prod, f_q) + // mstore(0x1880, prod) + + // prod := mulmod(mload(0x1320), prod, f_q) + // mstore(0x18a0, prod) + + // prod := mulmod(mload(0x1360), prod, f_q) + // mstore(0x18c0, prod) + + // prod := mulmod(mload(0x13a0), prod, f_q) + // mstore(0x18e0, prod) + + // prod := mulmod(mload(0x13e0), prod, f_q) + // mstore(0x1900, prod) + + // prod := mulmod(mload(0x1420), prod, f_q) + // mstore(0x1920, prod) + + // prod := mulmod(mload(0x1460), prod, f_q) + // mstore(0x1940, prod) + + // prod := mulmod(mload(0x14a0), prod, f_q) + // mstore(0x1960, prod) + + // prod := mulmod(mload(0x14e0), prod, f_q) + // mstore(0x1980, prod) + + // prod := mulmod(mload(0x1520), prod, f_q) + // mstore(0x19a0, prod) + + // prod := mulmod(mload(0x1560), prod, f_q) + // mstore(0x19c0, prod) + + // prod := mulmod(mload(0x15a0), prod, f_q) + // mstore(0x19e0, prod) + + // prod := mulmod(mload(0x15e0), prod, f_q) + // mstore(0x1a00, prod) + + // prod := mulmod(mload(0x1620), prod, f_q) + // mstore(0x1a20, prod) - prod := mulmod(mload(0x1660), prod, f_q) - mstore(0x1a40, prod) + // prod := mulmod(mload(0x1660), prod, f_q) + // mstore(0x1a40, prod) - prod := mulmod(mload(0x16a0), prod, f_q) - mstore(0x1a60, prod) + // prod := mulmod(mload(0x16a0), prod, f_q) + // mstore(0x1a60, prod) - prod := mulmod(mload(0x16e0), prod, f_q) - mstore(0x1a80, prod) + // prod := mulmod(mload(0x16e0), prod, f_q) + // mstore(0x1a80, prod) - prod := mulmod(mload(0xf40), prod, f_q) - mstore(0x1aa0, prod) - } - mstore(0x1ae0, 32) - mstore(0x1b00, 32) - mstore(0x1b20, 32) - mstore(0x1b40, mload(0x1aa0)) - mstore(0x1b60, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x1b80, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x1ae0, 0xc0, 0x1ac0, 0x20), 1), success) - { - let inv := mload(0x1ac0) - let v + // prod := mulmod(mload(0xf40), prod, f_q) + // mstore(0x1aa0, prod) + // } + // mstore(0x1ae0, 32) + // mstore(0x1b00, 32) + // mstore(0x1b20, 32) + // mstore(0x1b40, mload(0x1aa0)) + // mstore(0x1b60, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + // mstore(0x1b80, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + // success := and(eq(staticcall(gas(), 0x5, 0x1ae0, 0xc0, 0x1ac0, 0x20), 1), success) + // { + // let inv := mload(0x1ac0) + // let v - v := mload(0xf40) - mstore(3904, mulmod(mload(0x1a80), inv, f_q)) - inv := mulmod(v, inv, f_q) + // v := mload(0xf40) + // mstore(3904, mulmod(mload(0x1a80), inv, f_q)) + // inv := mulmod(v, inv, f_q) - v := mload(0x16e0) - mstore(5856, mulmod(mload(0x1a60), inv, f_q)) - inv := mulmod(v, inv, f_q) + // v := mload(0x16e0) + // mstore(5856, mulmod(mload(0x1a60), inv, f_q)) + // inv := mulmod(v, inv, f_q) - v := mload(0x16a0) - mstore(5792, mulmod(mload(0x1a40), inv, f_q)) - inv := mulmod(v, inv, f_q) + // v := mload(0x16a0) + // mstore(5792, mulmod(mload(0x1a40), inv, f_q)) + // inv := mulmod(v, inv, f_q) - v := mload(0x1660) - mstore(5728, mulmod(mload(0x1a20), inv, f_q)) - inv := mulmod(v, inv, f_q) + // v := mload(0x1660) + // mstore(5728, mulmod(mload(0x1a20), inv, f_q)) + // inv := mulmod(v, inv, f_q) - v := mload(0x1620) - mstore(5664, mulmod(mload(0x1a00), inv, f_q)) - inv := mulmod(v, inv, f_q) + // v := mload(0x1620) + // mstore(5664, mulmod(mload(0x1a00), inv, f_q)) + // inv := mulmod(v, inv, f_q) - v := mload(0x15e0) - mstore(5600, mulmod(mload(0x19e0), inv, f_q)) - inv := mulmod(v, inv, f_q) + // v := mload(0x15e0) + // mstore(5600, mulmod(mload(0x19e0), inv, f_q)) + // inv := mulmod(v, inv, f_q) - v := mload(0x15a0) - mstore(5536, mulmod(mload(0x19c0), inv, f_q)) - inv := mulmod(v, inv, f_q) + // v := mload(0x15a0) + // mstore(5536, mulmod(mload(0x19c0), inv, f_q)) + // inv := mulmod(v, inv, f_q) - v := mload(0x1560) - mstore(5472, mulmod(mload(0x19a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1520) - mstore(5408, mulmod(mload(0x1980), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x14e0) - mstore(5344, mulmod(mload(0x1960), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x14a0) - mstore(5280, mulmod(mload(0x1940), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1460) - mstore(5216, mulmod(mload(0x1920), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1420) - mstore(5152, mulmod(mload(0x1900), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x13e0) - mstore(5088, mulmod(mload(0x18e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x13a0) - mstore(5024, mulmod(mload(0x18c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1360) - mstore(4960, mulmod(mload(0x18a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1320) - mstore(4896, mulmod(mload(0x1880), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x12e0) - mstore(4832, mulmod(mload(0x1860), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x12a0) - mstore(4768, mulmod(mload(0x1840), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1260) - mstore(4704, mulmod(mload(0x1820), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1220) - mstore(4640, mulmod(mload(0x1800), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x11e0) - mstore(4576, mulmod(mload(0x17e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x11a0) - mstore(4512, mulmod(mload(0x17c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1160) - mstore(4448, mulmod(mload(0x17a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1120) - mstore(4384, mulmod(mload(0x1780), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x10e0) - mstore(4320, mulmod(mload(0x1760), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x10a0) - mstore(4256, mulmod(mload(0x1740), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1060) - mstore(4192, mulmod(mload(0x1720), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1020) - mstore(4128, mulmod(mload(0x1700), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xfe0) - mstore(4064, mulmod(mload(0xfa0), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0xfa0, inv) - } - mstore(0x1ba0, mulmod(mload(0xf80), mload(0xfa0), f_q)) - mstore(0x1bc0, mulmod(mload(0xfc0), mload(0xfe0), f_q)) - mstore(0x1be0, mulmod(mload(0x1000), mload(0x1020), f_q)) - mstore(0x1c00, mulmod(mload(0x1040), mload(0x1060), f_q)) - mstore(0x1c20, mulmod(mload(0x1080), mload(0x10a0), f_q)) - mstore(0x1c40, mulmod(mload(0x10c0), mload(0x10e0), f_q)) - mstore(0x1c60, mulmod(mload(0x1100), mload(0x1120), f_q)) - mstore(0x1c80, mulmod(mload(0x1140), mload(0x1160), f_q)) - mstore(0x1ca0, mulmod(mload(0x1180), mload(0x11a0), f_q)) - mstore(0x1cc0, mulmod(mload(0x11c0), mload(0x11e0), f_q)) - mstore(0x1ce0, mulmod(mload(0x1200), mload(0x1220), f_q)) - mstore(0x1d00, mulmod(mload(0x1240), mload(0x1260), f_q)) - mstore(0x1d20, mulmod(mload(0x1280), mload(0x12a0), f_q)) - mstore(0x1d40, mulmod(mload(0x12c0), mload(0x12e0), f_q)) - mstore(0x1d60, mulmod(mload(0x1300), mload(0x1320), f_q)) - mstore(0x1d80, mulmod(mload(0x1340), mload(0x1360), f_q)) - mstore(0x1da0, mulmod(mload(0x1380), mload(0x13a0), f_q)) - mstore(0x1dc0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) - mstore(0x1de0, mulmod(mload(0x1400), mload(0x1420), f_q)) - mstore(0x1e00, mulmod(mload(0x1440), mload(0x1460), f_q)) - mstore(0x1e20, mulmod(mload(0x1480), mload(0x14a0), f_q)) - mstore(0x1e40, mulmod(mload(0x14c0), mload(0x14e0), f_q)) - mstore(0x1e60, mulmod(mload(0x1500), mload(0x1520), f_q)) - mstore(0x1e80, mulmod(mload(0x1540), mload(0x1560), f_q)) - mstore(0x1ea0, mulmod(mload(0x1580), mload(0x15a0), f_q)) - mstore(0x1ec0, mulmod(mload(0x15c0), mload(0x15e0), f_q)) - mstore(0x1ee0, mulmod(mload(0x1600), mload(0x1620), f_q)) - mstore(0x1f00, mulmod(mload(0x1640), mload(0x1660), f_q)) - mstore(0x1f20, mulmod(mload(0x1680), mload(0x16a0), f_q)) - mstore(0x1f40, mulmod(mload(0x16c0), mload(0x16e0), f_q)) - { - let result := mulmod(mload(0x1c80), mload(0xa0), f_q) - result := addmod(mulmod(mload(0x1ca0), mload(0xc0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1cc0), mload(0xe0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1ce0), mload(0x100), f_q), result, f_q) - result := addmod(mulmod(mload(0x1d00), mload(0x120), f_q), result, f_q) - result := addmod(mulmod(mload(0x1d20), mload(0x140), f_q), result, f_q) - result := addmod(mulmod(mload(0x1d40), mload(0x160), f_q), result, f_q) - result := addmod(mulmod(mload(0x1d60), mload(0x180), f_q), result, f_q) - result := addmod(mulmod(mload(0x1d80), mload(0x1a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1da0), mload(0x1c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1dc0), mload(0x1e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1de0), mload(0x200), f_q), result, f_q) - result := addmod(mulmod(mload(0x1e00), mload(0x220), f_q), result, f_q) - result := addmod(mulmod(mload(0x1e20), mload(0x240), f_q), result, f_q) - result := addmod(mulmod(mload(0x1e40), mload(0x260), f_q), result, f_q) - result := addmod(mulmod(mload(0x1e60), mload(0x280), f_q), result, f_q) - result := addmod(mulmod(mload(0x1e80), mload(0x2a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1ea0), mload(0x2c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1ec0), mload(0x2e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1ee0), mload(0x300), f_q), result, f_q) - result := addmod(mulmod(mload(0x1f00), mload(0x320), f_q), result, f_q) - result := addmod(mulmod(mload(0x1f20), mload(0x340), f_q), result, f_q) - result := addmod(mulmod(mload(0x1f40), mload(0x360), f_q), result, f_q) - mstore(8032, result) - } - mstore(0x1f80, mulmod(mload(0x820), mload(0x800), f_q)) - mstore(0x1fa0, addmod(mload(0x7e0), mload(0x1f80), f_q)) - mstore(0x1fc0, addmod(mload(0x1fa0), sub(f_q, mload(0x840)), f_q)) - mstore(0x1fe0, mulmod(mload(0x1fc0), mload(0x8a0), f_q)) - mstore(0x2000, mulmod(mload(0x640), mload(0x1fe0), f_q)) - mstore(0x2020, addmod(1, sub(f_q, mload(0x960)), f_q)) - mstore(0x2040, mulmod(mload(0x2020), mload(0x1c80), f_q)) - mstore(0x2060, addmod(mload(0x2000), mload(0x2040), f_q)) - mstore(0x2080, mulmod(mload(0x640), mload(0x2060), f_q)) - mstore(0x20a0, mulmod(mload(0x960), mload(0x960), f_q)) - mstore(0x20c0, addmod(mload(0x20a0), sub(f_q, mload(0x960)), f_q)) - mstore(0x20e0, mulmod(mload(0x20c0), mload(0x1ba0), f_q)) - mstore(0x2100, addmod(mload(0x2080), mload(0x20e0), f_q)) - mstore(0x2120, mulmod(mload(0x640), mload(0x2100), f_q)) - mstore(0x2140, addmod(1, sub(f_q, mload(0x1ba0)), f_q)) - mstore(0x2160, addmod(mload(0x1bc0), mload(0x1be0), f_q)) - mstore(0x2180, addmod(mload(0x2160), mload(0x1c00), f_q)) - mstore(0x21a0, addmod(mload(0x2180), mload(0x1c20), f_q)) - mstore(0x21c0, addmod(mload(0x21a0), mload(0x1c40), f_q)) - mstore(0x21e0, addmod(mload(0x21c0), mload(0x1c60), f_q)) - mstore(0x2200, addmod(mload(0x2140), sub(f_q, mload(0x21e0)), f_q)) - mstore(0x2220, mulmod(mload(0x900), mload(0x4c0), f_q)) - mstore(0x2240, addmod(mload(0x860), mload(0x2220), f_q)) - mstore(0x2260, addmod(mload(0x2240), mload(0x520), f_q)) - mstore(0x2280, mulmod(mload(0x920), mload(0x4c0), f_q)) - mstore(0x22a0, addmod(mload(0x7e0), mload(0x2280), f_q)) - mstore(0x22c0, addmod(mload(0x22a0), mload(0x520), f_q)) - mstore(0x22e0, mulmod(mload(0x22c0), mload(0x2260), f_q)) - mstore(0x2300, mulmod(mload(0x940), mload(0x4c0), f_q)) - mstore(0x2320, addmod(mload(0x1f60), mload(0x2300), f_q)) - mstore(0x2340, addmod(mload(0x2320), mload(0x520), f_q)) - mstore(0x2360, mulmod(mload(0x2340), mload(0x22e0), f_q)) - mstore(0x2380, mulmod(mload(0x2360), mload(0x980), f_q)) - mstore(0x23a0, mulmod(1, mload(0x4c0), f_q)) - mstore(0x23c0, mulmod(mload(0x7a0), mload(0x23a0), f_q)) - mstore(0x23e0, addmod(mload(0x860), mload(0x23c0), f_q)) - mstore(0x2400, addmod(mload(0x23e0), mload(0x520), f_q)) - mstore( - 0x2420, - mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x4c0), f_q) - ) - mstore(0x2440, mulmod(mload(0x7a0), mload(0x2420), f_q)) - mstore(0x2460, addmod(mload(0x7e0), mload(0x2440), f_q)) - mstore(0x2480, addmod(mload(0x2460), mload(0x520), f_q)) - mstore(0x24a0, mulmod(mload(0x2480), mload(0x2400), f_q)) - mstore( - 0x24c0, - mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x4c0), f_q) - ) - mstore(0x24e0, mulmod(mload(0x7a0), mload(0x24c0), f_q)) - mstore(0x2500, addmod(mload(0x1f60), mload(0x24e0), f_q)) - mstore(0x2520, addmod(mload(0x2500), mload(0x520), f_q)) - mstore(0x2540, mulmod(mload(0x2520), mload(0x24a0), f_q)) - mstore(0x2560, mulmod(mload(0x2540), mload(0x960), f_q)) - mstore(0x2580, addmod(mload(0x2380), sub(f_q, mload(0x2560)), f_q)) - mstore(0x25a0, mulmod(mload(0x2580), mload(0x2200), f_q)) - mstore(0x25c0, addmod(mload(0x2120), mload(0x25a0), f_q)) - mstore(0x25e0, mulmod(mload(0x640), mload(0x25c0), f_q)) - mstore(0x2600, addmod(1, sub(f_q, mload(0x9a0)), f_q)) - mstore(0x2620, mulmod(mload(0x2600), mload(0x1c80), f_q)) - mstore(0x2640, addmod(mload(0x25e0), mload(0x2620), f_q)) - mstore(0x2660, mulmod(mload(0x640), mload(0x2640), f_q)) - mstore(0x2680, mulmod(mload(0x9a0), mload(0x9a0), f_q)) - mstore(0x26a0, addmod(mload(0x2680), sub(f_q, mload(0x9a0)), f_q)) - mstore(0x26c0, mulmod(mload(0x26a0), mload(0x1ba0), f_q)) - mstore(0x26e0, addmod(mload(0x2660), mload(0x26c0), f_q)) - mstore(0x2700, mulmod(mload(0x640), mload(0x26e0), f_q)) - mstore(0x2720, addmod(mload(0x9e0), mload(0x4c0), f_q)) - mstore(0x2740, mulmod(mload(0x2720), mload(0x9c0), f_q)) - mstore(0x2760, addmod(mload(0xa20), mload(0x520), f_q)) - mstore(0x2780, mulmod(mload(0x2760), mload(0x2740), f_q)) - mstore(0x27a0, mulmod(mload(0x7e0), mload(0x8c0), f_q)) - mstore(0x27c0, addmod(mload(0x27a0), mload(0x4c0), f_q)) - mstore(0x27e0, mulmod(mload(0x27c0), mload(0x9a0), f_q)) - mstore(0x2800, addmod(mload(0x880), mload(0x520), f_q)) - mstore(0x2820, mulmod(mload(0x2800), mload(0x27e0), f_q)) - mstore(0x2840, addmod(mload(0x2780), sub(f_q, mload(0x2820)), f_q)) - mstore(0x2860, mulmod(mload(0x2840), mload(0x2200), f_q)) - mstore(0x2880, addmod(mload(0x2700), mload(0x2860), f_q)) - mstore(0x28a0, mulmod(mload(0x640), mload(0x2880), f_q)) - mstore(0x28c0, addmod(mload(0x9e0), sub(f_q, mload(0xa20)), f_q)) - mstore(0x28e0, mulmod(mload(0x28c0), mload(0x1c80), f_q)) - mstore(0x2900, addmod(mload(0x28a0), mload(0x28e0), f_q)) - mstore(0x2920, mulmod(mload(0x640), mload(0x2900), f_q)) - mstore(0x2940, mulmod(mload(0x28c0), mload(0x2200), f_q)) - mstore(0x2960, addmod(mload(0x9e0), sub(f_q, mload(0xa00)), f_q)) - mstore(0x2980, mulmod(mload(0x2960), mload(0x2940), f_q)) - mstore(0x29a0, addmod(mload(0x2920), mload(0x2980), f_q)) - mstore(0x29c0, mulmod(mload(0xf20), mload(0xf20), f_q)) - mstore(0x29e0, mulmod(mload(0x29c0), mload(0xf20), f_q)) - mstore(0x2a00, mulmod(mload(0x29e0), mload(0xf20), f_q)) - mstore(0x2a20, mulmod(1, mload(0xf20), f_q)) - mstore(0x2a40, mulmod(1, mload(0x29c0), f_q)) - mstore(0x2a60, mulmod(1, mload(0x29e0), f_q)) - mstore(0x2a80, mulmod(mload(0x29a0), mload(0xf40), f_q)) - mstore(0x2aa0, mulmod(mload(0xc60), mload(0x7a0), f_q)) - mstore(0x2ac0, mulmod(mload(0x2aa0), mload(0x7a0), f_q)) - mstore( - 0x2ae0, - mulmod(mload(0x7a0), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) - ) - mstore(0x2b00, addmod(mload(0xb60), sub(f_q, mload(0x2ae0)), f_q)) - mstore(0x2b20, mulmod(mload(0x7a0), 1, f_q)) - mstore(0x2b40, addmod(mload(0xb60), sub(f_q, mload(0x2b20)), f_q)) - mstore( - 0x2b60, - mulmod(mload(0x7a0), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) - ) - mstore(0x2b80, addmod(mload(0xb60), sub(f_q, mload(0x2b60)), f_q)) - mstore( - 0x2ba0, - mulmod(mload(0x7a0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) - ) - mstore(0x2bc0, addmod(mload(0xb60), sub(f_q, mload(0x2ba0)), f_q)) - mstore( - 0x2be0, - mulmod(mload(0x7a0), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) - ) - mstore(0x2c00, addmod(mload(0xb60), sub(f_q, mload(0x2be0)), f_q)) - mstore( - 0x2c20, - mulmod( - 13213688729882003894512633350385593288217014177373218494356903340348818451480, mload(0x2aa0), f_q - ) - ) - mstore(0x2c40, mulmod(mload(0x2c20), 1, f_q)) - { - let result := mulmod(mload(0xb60), mload(0x2c20), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2c40)), f_q), result, f_q) - mstore(11360, result) - } - mstore( - 0x2c80, - mulmod(8207090019724696496350398458716998472718344609680392612601596849934418295470, mload(0x2aa0), f_q) - ) - mstore( - 0x2ca0, - mulmod(mload(0x2c80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) - ) - { - let result := mulmod(mload(0xb60), mload(0x2c80), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ca0)), f_q), result, f_q) - mstore(11456, result) - } - mstore( - 0x2ce0, - mulmod(7391709068497399131897422873231908718558236401035363928063603272120120747483, mload(0x2aa0), f_q) - ) - mstore( - 0x2d00, - mulmod( - mload(0x2ce0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q - ) - ) - { - let result := mulmod(mload(0xb60), mload(0x2ce0), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d00)), f_q), result, f_q) - mstore(11552, result) - } - mstore( - 0x2d40, - mulmod( - 19036273796805830823244991598792794567595348772040298280440552631112242221017, mload(0x2aa0), f_q - ) - ) - mstore( - 0x2d60, - mulmod(mload(0x2d40), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) - ) - { - let result := mulmod(mload(0xb60), mload(0x2d40), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d60)), f_q), result, f_q) - mstore(11648, result) - } - mstore(0x2da0, mulmod(1, mload(0x2b40), f_q)) - mstore(0x2dc0, mulmod(mload(0x2da0), mload(0x2b80), f_q)) - mstore(0x2de0, mulmod(mload(0x2dc0), mload(0x2bc0), f_q)) - mstore(0x2e00, mulmod(mload(0x2de0), mload(0x2c00), f_q)) - mstore( - 0x2e20, - mulmod(13513867906530865119835332133273263211836799082674232843258448413103731898271, mload(0x7a0), f_q) - ) - mstore(0x2e40, mulmod(mload(0x2e20), 1, f_q)) - { - let result := mulmod(mload(0xb60), mload(0x2e20), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2e40)), f_q), result, f_q) - mstore(11872, result) - } - mstore( - 0x2e80, - mulmod(8374374965308410102411073611984011876711565317741801500439755773472076597346, mload(0x7a0), f_q) - ) - mstore( - 0x2ea0, - mulmod(mload(0x2e80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) - ) - { - let result := mulmod(mload(0xb60), mload(0x2e80), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ea0)), f_q), result, f_q) - mstore(11968, result) - } - mstore( - 0x2ee0, - mulmod(12146688980418810893951125255607130521645347193942732958664170801695864621271, mload(0x7a0), f_q) - ) - mstore(0x2f00, mulmod(mload(0x2ee0), 1, f_q)) - { - let result := mulmod(mload(0xb60), mload(0x2ee0), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f00)), f_q), result, f_q) - mstore(12064, result) - } - mstore( - 0x2f40, - mulmod(9741553891420464328295280489650144566903017206473301385034033384879943874346, mload(0x7a0), f_q) - ) - mstore( - 0x2f60, - mulmod(mload(0x2f40), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) - ) - { - let result := mulmod(mload(0xb60), mload(0x2f40), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f60)), f_q), result, f_q) - mstore(12160, result) - } - mstore(0x2fa0, mulmod(mload(0x2da0), mload(0x2b00), f_q)) - { - let result := mulmod(mload(0xb60), 1, f_q) - result := - addmod( - mulmod( - mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q - ), - result, - f_q - ) - mstore(12224, result) - } - { - let prod := mload(0x2c60) - - prod := mulmod(mload(0x2cc0), prod, f_q) - mstore(0x2fe0, prod) - - prod := mulmod(mload(0x2d20), prod, f_q) - mstore(0x3000, prod) - - prod := mulmod(mload(0x2d80), prod, f_q) - mstore(0x3020, prod) - - prod := mulmod(mload(0x2e60), prod, f_q) - mstore(0x3040, prod) - - prod := mulmod(mload(0x2ec0), prod, f_q) - mstore(0x3060, prod) - - prod := mulmod(mload(0x2dc0), prod, f_q) - mstore(0x3080, prod) - - prod := mulmod(mload(0x2f20), prod, f_q) - mstore(0x30a0, prod) - - prod := mulmod(mload(0x2f80), prod, f_q) - mstore(0x30c0, prod) - - prod := mulmod(mload(0x2fa0), prod, f_q) - mstore(0x30e0, prod) - - prod := mulmod(mload(0x2fc0), prod, f_q) - mstore(0x3100, prod) - - prod := mulmod(mload(0x2da0), prod, f_q) - mstore(0x3120, prod) - } - mstore(0x3160, 32) - mstore(0x3180, 32) - mstore(0x31a0, 32) - mstore(0x31c0, mload(0x3120)) - mstore(0x31e0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x3200, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x3160, 0xc0, 0x3140, 0x20), 1), success) - { - let inv := mload(0x3140) - let v - - v := mload(0x2da0) - mstore(11680, mulmod(mload(0x3100), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2fc0) - mstore(12224, mulmod(mload(0x30e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2fa0) - mstore(12192, mulmod(mload(0x30c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2f80) - mstore(12160, mulmod(mload(0x30a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2f20) - mstore(12064, mulmod(mload(0x3080), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2dc0) - mstore(11712, mulmod(mload(0x3060), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2ec0) - mstore(11968, mulmod(mload(0x3040), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2e60) - mstore(11872, mulmod(mload(0x3020), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2d80) - mstore(11648, mulmod(mload(0x3000), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2d20) - mstore(11552, mulmod(mload(0x2fe0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2cc0) - mstore(11456, mulmod(mload(0x2c60), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x2c60, inv) - } - { - let result := mload(0x2c60) - result := addmod(mload(0x2cc0), result, f_q) - result := addmod(mload(0x2d20), result, f_q) - result := addmod(mload(0x2d80), result, f_q) - mstore(12832, result) - } - mstore(0x3240, mulmod(mload(0x2e00), mload(0x2dc0), f_q)) - { - let result := mload(0x2e60) - result := addmod(mload(0x2ec0), result, f_q) - mstore(12896, result) - } - mstore(0x3280, mulmod(mload(0x2e00), mload(0x2fa0), f_q)) - { - let result := mload(0x2f20) - result := addmod(mload(0x2f80), result, f_q) - mstore(12960, result) - } - mstore(0x32c0, mulmod(mload(0x2e00), mload(0x2da0), f_q)) - { - let result := mload(0x2fc0) - mstore(13024, result) - } - { - let prod := mload(0x3220) - - prod := mulmod(mload(0x3260), prod, f_q) - mstore(0x3300, prod) - - prod := mulmod(mload(0x32a0), prod, f_q) - mstore(0x3320, prod) - - prod := mulmod(mload(0x32e0), prod, f_q) - mstore(0x3340, prod) - } - mstore(0x3380, 32) - mstore(0x33a0, 32) - mstore(0x33c0, 32) - mstore(0x33e0, mload(0x3340)) - mstore(0x3400, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x3420, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x3380, 0xc0, 0x3360, 0x20), 1), success) - { - let inv := mload(0x3360) - let v - - v := mload(0x32e0) - mstore(13024, mulmod(mload(0x3320), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x32a0) - mstore(12960, mulmod(mload(0x3300), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3260) - mstore(12896, mulmod(mload(0x3220), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x3220, inv) - } - mstore(0x3440, mulmod(mload(0x3240), mload(0x3260), f_q)) - mstore(0x3460, mulmod(mload(0x3280), mload(0x32a0), f_q)) - mstore(0x3480, mulmod(mload(0x32c0), mload(0x32e0), f_q)) - mstore(0x34a0, mulmod(mload(0xa60), mload(0xa60), f_q)) - mstore(0x34c0, mulmod(mload(0x34a0), mload(0xa60), f_q)) - mstore(0x34e0, mulmod(mload(0x34c0), mload(0xa60), f_q)) - mstore(0x3500, mulmod(mload(0x34e0), mload(0xa60), f_q)) - mstore(0x3520, mulmod(mload(0x3500), mload(0xa60), f_q)) - mstore(0x3540, mulmod(mload(0x3520), mload(0xa60), f_q)) - mstore(0x3560, mulmod(mload(0x3540), mload(0xa60), f_q)) - mstore(0x3580, mulmod(mload(0x3560), mload(0xa60), f_q)) - mstore(0x35a0, mulmod(mload(0x3580), mload(0xa60), f_q)) - mstore(0x35c0, mulmod(mload(0xac0), mload(0xac0), f_q)) - mstore(0x35e0, mulmod(mload(0x35c0), mload(0xac0), f_q)) - mstore(0x3600, mulmod(mload(0x35e0), mload(0xac0), f_q)) - { - let result := mulmod(mload(0x7e0), mload(0x2c60), f_q) - result := addmod(mulmod(mload(0x800), mload(0x2cc0), f_q), result, f_q) - result := addmod(mulmod(mload(0x820), mload(0x2d20), f_q), result, f_q) - result := addmod(mulmod(mload(0x840), mload(0x2d80), f_q), result, f_q) - mstore(13856, result) - } - mstore(0x3640, mulmod(mload(0x3620), mload(0x3220), f_q)) - mstore(0x3660, mulmod(sub(f_q, mload(0x3640)), 1, f_q)) - mstore(0x3680, mulmod(mload(0x3660), 1, f_q)) - mstore(0x36a0, mulmod(1, mload(0x3240), f_q)) - { - let result := mulmod(mload(0x960), mload(0x2e60), f_q) - result := addmod(mulmod(mload(0x980), mload(0x2ec0), f_q), result, f_q) - mstore(14016, result) - } - mstore(0x36e0, mulmod(mload(0x36c0), mload(0x3440), f_q)) - mstore(0x3700, mulmod(sub(f_q, mload(0x36e0)), 1, f_q)) - mstore(0x3720, mulmod(mload(0x36a0), 1, f_q)) - { - let result := mulmod(mload(0x9a0), mload(0x2e60), f_q) - result := addmod(mulmod(mload(0x9c0), mload(0x2ec0), f_q), result, f_q) - mstore(14144, result) - } - mstore(0x3760, mulmod(mload(0x3740), mload(0x3440), f_q)) - mstore(0x3780, mulmod(sub(f_q, mload(0x3760)), mload(0xa60), f_q)) - mstore(0x37a0, mulmod(mload(0x36a0), mload(0xa60), f_q)) - mstore(0x37c0, addmod(mload(0x3700), mload(0x3780), f_q)) - mstore(0x37e0, mulmod(mload(0x37c0), mload(0xac0), f_q)) - mstore(0x3800, mulmod(mload(0x3720), mload(0xac0), f_q)) - mstore(0x3820, mulmod(mload(0x37a0), mload(0xac0), f_q)) - mstore(0x3840, addmod(mload(0x3680), mload(0x37e0), f_q)) - mstore(0x3860, mulmod(1, mload(0x3280), f_q)) - { - let result := mulmod(mload(0x9e0), mload(0x2f20), f_q) - result := addmod(mulmod(mload(0xa00), mload(0x2f80), f_q), result, f_q) - mstore(14464, result) - } - mstore(0x38a0, mulmod(mload(0x3880), mload(0x3460), f_q)) - mstore(0x38c0, mulmod(sub(f_q, mload(0x38a0)), 1, f_q)) - mstore(0x38e0, mulmod(mload(0x3860), 1, f_q)) - mstore(0x3900, mulmod(mload(0x38c0), mload(0x35c0), f_q)) - mstore(0x3920, mulmod(mload(0x38e0), mload(0x35c0), f_q)) - mstore(0x3940, addmod(mload(0x3840), mload(0x3900), f_q)) - mstore(0x3960, mulmod(1, mload(0x32c0), f_q)) - { - let result := mulmod(mload(0xa20), mload(0x2fc0), f_q) - mstore(14720, result) - } - mstore(0x39a0, mulmod(mload(0x3980), mload(0x3480), f_q)) - mstore(0x39c0, mulmod(sub(f_q, mload(0x39a0)), 1, f_q)) - mstore(0x39e0, mulmod(mload(0x3960), 1, f_q)) - { - let result := mulmod(mload(0x860), mload(0x2fc0), f_q) - mstore(14848, result) - } - mstore(0x3a20, mulmod(mload(0x3a00), mload(0x3480), f_q)) - mstore(0x3a40, mulmod(sub(f_q, mload(0x3a20)), mload(0xa60), f_q)) - mstore(0x3a60, mulmod(mload(0x3960), mload(0xa60), f_q)) - mstore(0x3a80, addmod(mload(0x39c0), mload(0x3a40), f_q)) - { - let result := mulmod(mload(0x880), mload(0x2fc0), f_q) - mstore(15008, result) - } - mstore(0x3ac0, mulmod(mload(0x3aa0), mload(0x3480), f_q)) - mstore(0x3ae0, mulmod(sub(f_q, mload(0x3ac0)), mload(0x34a0), f_q)) - mstore(0x3b00, mulmod(mload(0x3960), mload(0x34a0), f_q)) - mstore(0x3b20, addmod(mload(0x3a80), mload(0x3ae0), f_q)) - { - let result := mulmod(mload(0x8a0), mload(0x2fc0), f_q) - mstore(15168, result) - } - mstore(0x3b60, mulmod(mload(0x3b40), mload(0x3480), f_q)) - mstore(0x3b80, mulmod(sub(f_q, mload(0x3b60)), mload(0x34c0), f_q)) - mstore(0x3ba0, mulmod(mload(0x3960), mload(0x34c0), f_q)) - mstore(0x3bc0, addmod(mload(0x3b20), mload(0x3b80), f_q)) - { - let result := mulmod(mload(0x8c0), mload(0x2fc0), f_q) - mstore(15328, result) - } - mstore(0x3c00, mulmod(mload(0x3be0), mload(0x3480), f_q)) - mstore(0x3c20, mulmod(sub(f_q, mload(0x3c00)), mload(0x34e0), f_q)) - mstore(0x3c40, mulmod(mload(0x3960), mload(0x34e0), f_q)) - mstore(0x3c60, addmod(mload(0x3bc0), mload(0x3c20), f_q)) - { - let result := mulmod(mload(0x900), mload(0x2fc0), f_q) - mstore(15488, result) - } - mstore(0x3ca0, mulmod(mload(0x3c80), mload(0x3480), f_q)) - mstore(0x3cc0, mulmod(sub(f_q, mload(0x3ca0)), mload(0x3500), f_q)) - mstore(0x3ce0, mulmod(mload(0x3960), mload(0x3500), f_q)) - mstore(0x3d00, addmod(mload(0x3c60), mload(0x3cc0), f_q)) - { - let result := mulmod(mload(0x920), mload(0x2fc0), f_q) - mstore(15648, result) - } - mstore(0x3d40, mulmod(mload(0x3d20), mload(0x3480), f_q)) - mstore(0x3d60, mulmod(sub(f_q, mload(0x3d40)), mload(0x3520), f_q)) - mstore(0x3d80, mulmod(mload(0x3960), mload(0x3520), f_q)) - mstore(0x3da0, addmod(mload(0x3d00), mload(0x3d60), f_q)) - { - let result := mulmod(mload(0x940), mload(0x2fc0), f_q) - mstore(15808, result) - } - mstore(0x3de0, mulmod(mload(0x3dc0), mload(0x3480), f_q)) - mstore(0x3e00, mulmod(sub(f_q, mload(0x3de0)), mload(0x3540), f_q)) - mstore(0x3e20, mulmod(mload(0x3960), mload(0x3540), f_q)) - mstore(0x3e40, addmod(mload(0x3da0), mload(0x3e00), f_q)) - mstore(0x3e60, mulmod(mload(0x2a20), mload(0x32c0), f_q)) - mstore(0x3e80, mulmod(mload(0x2a40), mload(0x32c0), f_q)) - mstore(0x3ea0, mulmod(mload(0x2a60), mload(0x32c0), f_q)) - { - let result := mulmod(mload(0x2a80), mload(0x2fc0), f_q) - mstore(16064, result) - } - mstore(0x3ee0, mulmod(mload(0x3ec0), mload(0x3480), f_q)) - mstore(0x3f00, mulmod(sub(f_q, mload(0x3ee0)), mload(0x3560), f_q)) - mstore(0x3f20, mulmod(mload(0x3960), mload(0x3560), f_q)) - mstore(0x3f40, mulmod(mload(0x3e60), mload(0x3560), f_q)) - mstore(0x3f60, mulmod(mload(0x3e80), mload(0x3560), f_q)) - mstore(0x3f80, mulmod(mload(0x3ea0), mload(0x3560), f_q)) - mstore(0x3fa0, addmod(mload(0x3e40), mload(0x3f00), f_q)) - { - let result := mulmod(mload(0x8e0), mload(0x2fc0), f_q) - mstore(16320, result) - } - mstore(0x3fe0, mulmod(mload(0x3fc0), mload(0x3480), f_q)) - mstore(0x4000, mulmod(sub(f_q, mload(0x3fe0)), mload(0x3580), f_q)) - mstore(0x4020, mulmod(mload(0x3960), mload(0x3580), f_q)) - mstore(0x4040, addmod(mload(0x3fa0), mload(0x4000), f_q)) - mstore(0x4060, mulmod(mload(0x4040), mload(0x35e0), f_q)) - mstore(0x4080, mulmod(mload(0x39e0), mload(0x35e0), f_q)) - mstore(0x40a0, mulmod(mload(0x3a60), mload(0x35e0), f_q)) - mstore(0x40c0, mulmod(mload(0x3b00), mload(0x35e0), f_q)) - mstore(0x40e0, mulmod(mload(0x3ba0), mload(0x35e0), f_q)) - mstore(0x4100, mulmod(mload(0x3c40), mload(0x35e0), f_q)) - mstore(0x4120, mulmod(mload(0x3ce0), mload(0x35e0), f_q)) - mstore(0x4140, mulmod(mload(0x3d80), mload(0x35e0), f_q)) - mstore(0x4160, mulmod(mload(0x3e20), mload(0x35e0), f_q)) - mstore(0x4180, mulmod(mload(0x3f20), mload(0x35e0), f_q)) - mstore(0x41a0, mulmod(mload(0x3f40), mload(0x35e0), f_q)) - mstore(0x41c0, mulmod(mload(0x3f60), mload(0x35e0), f_q)) - mstore(0x41e0, mulmod(mload(0x3f80), mload(0x35e0), f_q)) - mstore(0x4200, mulmod(mload(0x4020), mload(0x35e0), f_q)) - mstore(0x4220, addmod(mload(0x3940), mload(0x4060), f_q)) - mstore(0x4240, mulmod(1, mload(0x2e00), f_q)) - mstore(0x4260, mulmod(1, mload(0xb60), f_q)) - mstore(0x4280, 0x0000000000000000000000000000000000000000000000000000000000000001) - mstore(0x42a0, 0x0000000000000000000000000000000000000000000000000000000000000002) - mstore(0x42c0, mload(0x4220)) - success := and(eq(staticcall(gas(), 0x7, 0x4280, 0x60, 0x4280, 0x40), 1), success) - mstore(0x42e0, mload(0x4280)) - mstore(0x4300, mload(0x42a0)) - mstore(0x4320, mload(0x380)) - mstore(0x4340, mload(0x3a0)) - success := and(eq(staticcall(gas(), 0x6, 0x42e0, 0x80, 0x42e0, 0x40), 1), success) - mstore(0x4360, mload(0x560)) - mstore(0x4380, mload(0x580)) - mstore(0x43a0, mload(0x3800)) - success := and(eq(staticcall(gas(), 0x7, 0x4360, 0x60, 0x4360, 0x40), 1), success) - mstore(0x43c0, mload(0x42e0)) - mstore(0x43e0, mload(0x4300)) - mstore(0x4400, mload(0x4360)) - mstore(0x4420, mload(0x4380)) - success := and(eq(staticcall(gas(), 0x6, 0x43c0, 0x80, 0x43c0, 0x40), 1), success) - mstore(0x4440, mload(0x5a0)) - mstore(0x4460, mload(0x5c0)) - mstore(0x4480, mload(0x3820)) - success := and(eq(staticcall(gas(), 0x7, 0x4440, 0x60, 0x4440, 0x40), 1), success) - mstore(0x44a0, mload(0x43c0)) - mstore(0x44c0, mload(0x43e0)) - mstore(0x44e0, mload(0x4440)) - mstore(0x4500, mload(0x4460)) - success := and(eq(staticcall(gas(), 0x6, 0x44a0, 0x80, 0x44a0, 0x40), 1), success) - mstore(0x4520, mload(0x420)) - mstore(0x4540, mload(0x440)) - mstore(0x4560, mload(0x3920)) - success := and(eq(staticcall(gas(), 0x7, 0x4520, 0x60, 0x4520, 0x40), 1), success) - mstore(0x4580, mload(0x44a0)) - mstore(0x45a0, mload(0x44c0)) - mstore(0x45c0, mload(0x4520)) - mstore(0x45e0, mload(0x4540)) - success := and(eq(staticcall(gas(), 0x6, 0x4580, 0x80, 0x4580, 0x40), 1), success) - mstore(0x4600, mload(0x460)) - mstore(0x4620, mload(0x480)) - mstore(0x4640, mload(0x4080)) - success := and(eq(staticcall(gas(), 0x7, 0x4600, 0x60, 0x4600, 0x40), 1), success) - mstore(0x4660, mload(0x4580)) - mstore(0x4680, mload(0x45a0)) - mstore(0x46a0, mload(0x4600)) - mstore(0x46c0, mload(0x4620)) - success := and(eq(staticcall(gas(), 0x6, 0x4660, 0x80, 0x4660, 0x40), 1), success) - mstore(0x46e0, 0x21b14b6e8ea36289961bde7f1d8f191389a815740d09f34f13190341383dfb13) - mstore(0x4700, 0x16740f9c3982e02aeb0cb10086339afaca1bb103d5ae3f114c45a569d60c88ce) - mstore(0x4720, mload(0x40a0)) - success := and(eq(staticcall(gas(), 0x7, 0x46e0, 0x60, 0x46e0, 0x40), 1), success) - mstore(0x4740, mload(0x4660)) - mstore(0x4760, mload(0x4680)) - mstore(0x4780, mload(0x46e0)) - mstore(0x47a0, mload(0x4700)) - success := and(eq(staticcall(gas(), 0x6, 0x4740, 0x80, 0x4740, 0x40), 1), success) - mstore(0x47c0, 0x2eb40e2b0c13a6f4b989cffa9dbc452447bfd9f04a79f6379aefea8c9850a550) - mstore(0x47e0, 0x0efe5496541e2bd648d490f11ad542e1dec3127f818b8065843d0dd81358416c) - mstore(0x4800, mload(0x40c0)) - success := and(eq(staticcall(gas(), 0x7, 0x47c0, 0x60, 0x47c0, 0x40), 1), success) - mstore(0x4820, mload(0x4740)) - mstore(0x4840, mload(0x4760)) - mstore(0x4860, mload(0x47c0)) - mstore(0x4880, mload(0x47e0)) - success := and(eq(staticcall(gas(), 0x6, 0x4820, 0x80, 0x4820, 0x40), 1), success) - mstore(0x48a0, 0x1c6707c73bce576eb360ffcb2fa9a0b17ad541ea0a0e8001439bca524f2f5a43) - mstore(0x48c0, 0x03b899b999df6cf57b7755535b1dc5014a9dbd21d55c31d826d8338dc2fe8722) - mstore(0x48e0, mload(0x40e0)) - success := and(eq(staticcall(gas(), 0x7, 0x48a0, 0x60, 0x48a0, 0x40), 1), success) - mstore(0x4900, mload(0x4820)) - mstore(0x4920, mload(0x4840)) - mstore(0x4940, mload(0x48a0)) - mstore(0x4960, mload(0x48c0)) - success := and(eq(staticcall(gas(), 0x6, 0x4900, 0x80, 0x4900, 0x40), 1), success) - mstore(0x4980, 0x1d309220cdb6694a08a8c77f89984557e19bbda422f41d50b47bf30b30b3dec3) - mstore(0x49a0, 0x138c263b3cbc7de6f5f92f88c44a3e7fc278a4b69008db2340097131e43dbb1a) - mstore(0x49c0, mload(0x4100)) - success := and(eq(staticcall(gas(), 0x7, 0x4980, 0x60, 0x4980, 0x40), 1), success) - mstore(0x49e0, mload(0x4900)) - mstore(0x4a00, mload(0x4920)) - mstore(0x4a20, mload(0x4980)) - mstore(0x4a40, mload(0x49a0)) - success := and(eq(staticcall(gas(), 0x6, 0x49e0, 0x80, 0x49e0, 0x40), 1), success) - mstore(0x4a60, 0x2529da4dfe20ec7564dc8738f2477daf565052f29117d9a2c1a0cbe846ab95fb) - mstore(0x4a80, 0x2a3971e5a786b7e8b0039d1100621af00a8743921a36ef7aafc430b09a5bd279) - mstore(0x4aa0, mload(0x4120)) - success := and(eq(staticcall(gas(), 0x7, 0x4a60, 0x60, 0x4a60, 0x40), 1), success) - mstore(0x4ac0, mload(0x49e0)) - mstore(0x4ae0, mload(0x4a00)) - mstore(0x4b00, mload(0x4a60)) - mstore(0x4b20, mload(0x4a80)) - success := and(eq(staticcall(gas(), 0x6, 0x4ac0, 0x80, 0x4ac0, 0x40), 1), success) - mstore(0x4b40, 0x132e1a4125c783ea4817ea96d967c5f06a49933ca71f7e99f7be022ef1e3ca35) - mstore(0x4b60, 0x0eb726ae10479119d87b2e1d0d2b72db88506d263ae939b2154b0f3f5c7012f7) - mstore(0x4b80, mload(0x4140)) - success := and(eq(staticcall(gas(), 0x7, 0x4b40, 0x60, 0x4b40, 0x40), 1), success) - mstore(0x4ba0, mload(0x4ac0)) - mstore(0x4bc0, mload(0x4ae0)) - mstore(0x4be0, mload(0x4b40)) - mstore(0x4c00, mload(0x4b60)) - success := and(eq(staticcall(gas(), 0x6, 0x4ba0, 0x80, 0x4ba0, 0x40), 1), success) - mstore(0x4c20, 0x1bc70a16efa4ef34c9ee86dc04d041fc8430240113b09ef71d5bbb8b685af6b7) - mstore(0x4c40, 0x25064309a3b7ab3efd593b9e6c2f1294b50c12e237412186d7af94b1591dc937) - mstore(0x4c60, mload(0x4160)) - success := and(eq(staticcall(gas(), 0x7, 0x4c20, 0x60, 0x4c20, 0x40), 1), success) - mstore(0x4c80, mload(0x4ba0)) - mstore(0x4ca0, mload(0x4bc0)) - mstore(0x4cc0, mload(0x4c20)) - mstore(0x4ce0, mload(0x4c40)) - success := and(eq(staticcall(gas(), 0x6, 0x4c80, 0x80, 0x4c80, 0x40), 1), success) - mstore(0x4d00, mload(0x680)) - mstore(0x4d20, mload(0x6a0)) - mstore(0x4d40, mload(0x4180)) - success := and(eq(staticcall(gas(), 0x7, 0x4d00, 0x60, 0x4d00, 0x40), 1), success) - mstore(0x4d60, mload(0x4c80)) - mstore(0x4d80, mload(0x4ca0)) - mstore(0x4da0, mload(0x4d00)) - mstore(0x4dc0, mload(0x4d20)) - success := and(eq(staticcall(gas(), 0x6, 0x4d60, 0x80, 0x4d60, 0x40), 1), success) - mstore(0x4de0, mload(0x6c0)) - mstore(0x4e00, mload(0x6e0)) - mstore(0x4e20, mload(0x41a0)) - success := and(eq(staticcall(gas(), 0x7, 0x4de0, 0x60, 0x4de0, 0x40), 1), success) - mstore(0x4e40, mload(0x4d60)) - mstore(0x4e60, mload(0x4d80)) - mstore(0x4e80, mload(0x4de0)) - mstore(0x4ea0, mload(0x4e00)) - success := and(eq(staticcall(gas(), 0x6, 0x4e40, 0x80, 0x4e40, 0x40), 1), success) - mstore(0x4ec0, mload(0x700)) - mstore(0x4ee0, mload(0x720)) - mstore(0x4f00, mload(0x41c0)) - success := and(eq(staticcall(gas(), 0x7, 0x4ec0, 0x60, 0x4ec0, 0x40), 1), success) - mstore(0x4f20, mload(0x4e40)) - mstore(0x4f40, mload(0x4e60)) - mstore(0x4f60, mload(0x4ec0)) - mstore(0x4f80, mload(0x4ee0)) - success := and(eq(staticcall(gas(), 0x6, 0x4f20, 0x80, 0x4f20, 0x40), 1), success) - mstore(0x4fa0, mload(0x740)) - mstore(0x4fc0, mload(0x760)) - mstore(0x4fe0, mload(0x41e0)) - success := and(eq(staticcall(gas(), 0x7, 0x4fa0, 0x60, 0x4fa0, 0x40), 1), success) - mstore(0x5000, mload(0x4f20)) - mstore(0x5020, mload(0x4f40)) - mstore(0x5040, mload(0x4fa0)) - mstore(0x5060, mload(0x4fc0)) - success := and(eq(staticcall(gas(), 0x6, 0x5000, 0x80, 0x5000, 0x40), 1), success) - mstore(0x5080, mload(0x5e0)) - mstore(0x50a0, mload(0x600)) - mstore(0x50c0, mload(0x4200)) - success := and(eq(staticcall(gas(), 0x7, 0x5080, 0x60, 0x5080, 0x40), 1), success) - mstore(0x50e0, mload(0x5000)) - mstore(0x5100, mload(0x5020)) - mstore(0x5120, mload(0x5080)) - mstore(0x5140, mload(0x50a0)) - success := and(eq(staticcall(gas(), 0x6, 0x50e0, 0x80, 0x50e0, 0x40), 1), success) - mstore(0x5160, mload(0xb00)) - mstore(0x5180, mload(0xb20)) - mstore(0x51a0, sub(f_q, mload(0x4240))) - success := and(eq(staticcall(gas(), 0x7, 0x5160, 0x60, 0x5160, 0x40), 1), success) - mstore(0x51c0, mload(0x50e0)) - mstore(0x51e0, mload(0x5100)) - mstore(0x5200, mload(0x5160)) - mstore(0x5220, mload(0x5180)) - success := and(eq(staticcall(gas(), 0x6, 0x51c0, 0x80, 0x51c0, 0x40), 1), success) - mstore(0x5240, mload(0xba0)) - mstore(0x5260, mload(0xbc0)) - mstore(0x5280, mload(0x4260)) - success := and(eq(staticcall(gas(), 0x7, 0x5240, 0x60, 0x5240, 0x40), 1), success) - mstore(0x52a0, mload(0x51c0)) - mstore(0x52c0, mload(0x51e0)) - mstore(0x52e0, mload(0x5240)) - mstore(0x5300, mload(0x5260)) - success := and(eq(staticcall(gas(), 0x6, 0x52a0, 0x80, 0x52a0, 0x40), 1), success) - mstore(0x5320, mload(0x52a0)) - mstore(0x5340, mload(0x52c0)) - mstore(0x5360, mload(0xba0)) - mstore(0x5380, mload(0xbc0)) - mstore(0x53a0, mload(0xbe0)) - mstore(0x53c0, mload(0xc00)) - mstore(0x53e0, mload(0xc20)) - mstore(0x5400, mload(0xc40)) - mstore(0x5420, keccak256(0x5320, 256)) - mstore(21568, mod(mload(21536), f_q)) - mstore(0x5460, mulmod(mload(0x5440), mload(0x5440), f_q)) - mstore(0x5480, mulmod(1, mload(0x5440), f_q)) - mstore(0x54a0, mload(0x53a0)) - mstore(0x54c0, mload(0x53c0)) - mstore(0x54e0, mload(0x5480)) - success := and(eq(staticcall(gas(), 0x7, 0x54a0, 0x60, 0x54a0, 0x40), 1), success) - mstore(0x5500, mload(0x5320)) - mstore(0x5520, mload(0x5340)) - mstore(0x5540, mload(0x54a0)) - mstore(0x5560, mload(0x54c0)) - success := and(eq(staticcall(gas(), 0x6, 0x5500, 0x80, 0x5500, 0x40), 1), success) - mstore(0x5580, mload(0x53e0)) - mstore(0x55a0, mload(0x5400)) - mstore(0x55c0, mload(0x5480)) - success := and(eq(staticcall(gas(), 0x7, 0x5580, 0x60, 0x5580, 0x40), 1), success) - mstore(0x55e0, mload(0x5360)) - mstore(0x5600, mload(0x5380)) - mstore(0x5620, mload(0x5580)) - mstore(0x5640, mload(0x55a0)) - success := and(eq(staticcall(gas(), 0x6, 0x55e0, 0x80, 0x55e0, 0x40), 1), success) - mstore(0x5660, mload(0x5500)) - mstore(0x5680, mload(0x5520)) - mstore(0x56a0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) - mstore(0x56c0, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x56e0, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0x5700, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - mstore(0x5720, mload(0x55e0)) - mstore(0x5740, mload(0x5600)) - mstore(0x5760, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) - mstore(0x5780, 0x2ae0c8c3a090f7200ff398ee9845bbae8f8c1445ae7b632212775f60a0e21600) - mstore(0x57a0, 0x190fa476a5b352809ed41d7a0d7fe12b8f685e3c12a6d83855dba27aaf469643) - mstore(0x57c0, 0x1c0a500618907df9e4273d5181e31088deb1f05132de037cbfe73888f97f77c9) - success := and(eq(staticcall(gas(), 0x8, 0x5660, 0x180, 0x5660, 0x20), 1), success) - success := and(eq(mload(0x5660), 1), success) - - // Revert if anything fails - if iszero(success) { revert(0, 0) } - - // Return empty bytes on success - return(0, 0) - } + // v := mload(0x1560) + // mstore(5472, mulmod(mload(0x19a0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1520) + // mstore(5408, mulmod(mload(0x1980), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x14e0) + // mstore(5344, mulmod(mload(0x1960), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x14a0) + // mstore(5280, mulmod(mload(0x1940), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1460) + // mstore(5216, mulmod(mload(0x1920), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1420) + // mstore(5152, mulmod(mload(0x1900), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x13e0) + // mstore(5088, mulmod(mload(0x18e0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x13a0) + // mstore(5024, mulmod(mload(0x18c0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1360) + // mstore(4960, mulmod(mload(0x18a0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1320) + // mstore(4896, mulmod(mload(0x1880), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x12e0) + // mstore(4832, mulmod(mload(0x1860), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x12a0) + // mstore(4768, mulmod(mload(0x1840), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1260) + // mstore(4704, mulmod(mload(0x1820), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1220) + // mstore(4640, mulmod(mload(0x1800), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x11e0) + // mstore(4576, mulmod(mload(0x17e0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x11a0) + // mstore(4512, mulmod(mload(0x17c0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1160) + // mstore(4448, mulmod(mload(0x17a0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1120) + // mstore(4384, mulmod(mload(0x1780), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x10e0) + // mstore(4320, mulmod(mload(0x1760), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x10a0) + // mstore(4256, mulmod(mload(0x1740), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1060) + // mstore(4192, mulmod(mload(0x1720), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x1020) + // mstore(4128, mulmod(mload(0x1700), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0xfe0) + // mstore(4064, mulmod(mload(0xfa0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + // mstore(0xfa0, inv) + // } + // mstore(0x1ba0, mulmod(mload(0xf80), mload(0xfa0), f_q)) + // mstore(0x1bc0, mulmod(mload(0xfc0), mload(0xfe0), f_q)) + // mstore(0x1be0, mulmod(mload(0x1000), mload(0x1020), f_q)) + // mstore(0x1c00, mulmod(mload(0x1040), mload(0x1060), f_q)) + // mstore(0x1c20, mulmod(mload(0x1080), mload(0x10a0), f_q)) + // mstore(0x1c40, mulmod(mload(0x10c0), mload(0x10e0), f_q)) + // mstore(0x1c60, mulmod(mload(0x1100), mload(0x1120), f_q)) + // mstore(0x1c80, mulmod(mload(0x1140), mload(0x1160), f_q)) + // mstore(0x1ca0, mulmod(mload(0x1180), mload(0x11a0), f_q)) + // mstore(0x1cc0, mulmod(mload(0x11c0), mload(0x11e0), f_q)) + // mstore(0x1ce0, mulmod(mload(0x1200), mload(0x1220), f_q)) + // mstore(0x1d00, mulmod(mload(0x1240), mload(0x1260), f_q)) + // mstore(0x1d20, mulmod(mload(0x1280), mload(0x12a0), f_q)) + // mstore(0x1d40, mulmod(mload(0x12c0), mload(0x12e0), f_q)) + // mstore(0x1d60, mulmod(mload(0x1300), mload(0x1320), f_q)) + // mstore(0x1d80, mulmod(mload(0x1340), mload(0x1360), f_q)) + // mstore(0x1da0, mulmod(mload(0x1380), mload(0x13a0), f_q)) + // mstore(0x1dc0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) + // mstore(0x1de0, mulmod(mload(0x1400), mload(0x1420), f_q)) + // mstore(0x1e00, mulmod(mload(0x1440), mload(0x1460), f_q)) + // mstore(0x1e20, mulmod(mload(0x1480), mload(0x14a0), f_q)) + // mstore(0x1e40, mulmod(mload(0x14c0), mload(0x14e0), f_q)) + // mstore(0x1e60, mulmod(mload(0x1500), mload(0x1520), f_q)) + // mstore(0x1e80, mulmod(mload(0x1540), mload(0x1560), f_q)) + // mstore(0x1ea0, mulmod(mload(0x1580), mload(0x15a0), f_q)) + // mstore(0x1ec0, mulmod(mload(0x15c0), mload(0x15e0), f_q)) + // mstore(0x1ee0, mulmod(mload(0x1600), mload(0x1620), f_q)) + // mstore(0x1f00, mulmod(mload(0x1640), mload(0x1660), f_q)) + // mstore(0x1f20, mulmod(mload(0x1680), mload(0x16a0), f_q)) + // mstore(0x1f40, mulmod(mload(0x16c0), mload(0x16e0), f_q)) + // { + // let result := mulmod(mload(0x1c80), mload(0xa0), f_q) + // result := addmod(mulmod(mload(0x1ca0), mload(0xc0), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1cc0), mload(0xe0), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1ce0), mload(0x100), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1d00), mload(0x120), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1d20), mload(0x140), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1d40), mload(0x160), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1d60), mload(0x180), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1d80), mload(0x1a0), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1da0), mload(0x1c0), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1dc0), mload(0x1e0), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1de0), mload(0x200), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1e00), mload(0x220), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1e20), mload(0x240), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1e40), mload(0x260), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1e60), mload(0x280), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1e80), mload(0x2a0), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1ea0), mload(0x2c0), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1ec0), mload(0x2e0), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1ee0), mload(0x300), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1f00), mload(0x320), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1f20), mload(0x340), f_q), result, f_q) + // result := addmod(mulmod(mload(0x1f40), mload(0x360), f_q), result, f_q) + // mstore(8032, result) + // } + // mstore(0x1f80, mulmod(mload(0x820), mload(0x800), f_q)) + // mstore(0x1fa0, addmod(mload(0x7e0), mload(0x1f80), f_q)) + // mstore(0x1fc0, addmod(mload(0x1fa0), sub(f_q, mload(0x840)), f_q)) + // mstore(0x1fe0, mulmod(mload(0x1fc0), mload(0x8a0), f_q)) + // mstore(0x2000, mulmod(mload(0x640), mload(0x1fe0), f_q)) + // mstore(0x2020, addmod(1, sub(f_q, mload(0x960)), f_q)) + // mstore(0x2040, mulmod(mload(0x2020), mload(0x1c80), f_q)) + // mstore(0x2060, addmod(mload(0x2000), mload(0x2040), f_q)) + // mstore(0x2080, mulmod(mload(0x640), mload(0x2060), f_q)) + // mstore(0x20a0, mulmod(mload(0x960), mload(0x960), f_q)) + // mstore(0x20c0, addmod(mload(0x20a0), sub(f_q, mload(0x960)), f_q)) + // mstore(0x20e0, mulmod(mload(0x20c0), mload(0x1ba0), f_q)) + // mstore(0x2100, addmod(mload(0x2080), mload(0x20e0), f_q)) + // mstore(0x2120, mulmod(mload(0x640), mload(0x2100), f_q)) + // mstore(0x2140, addmod(1, sub(f_q, mload(0x1ba0)), f_q)) + // mstore(0x2160, addmod(mload(0x1bc0), mload(0x1be0), f_q)) + // mstore(0x2180, addmod(mload(0x2160), mload(0x1c00), f_q)) + // mstore(0x21a0, addmod(mload(0x2180), mload(0x1c20), f_q)) + // mstore(0x21c0, addmod(mload(0x21a0), mload(0x1c40), f_q)) + // mstore(0x21e0, addmod(mload(0x21c0), mload(0x1c60), f_q)) + // mstore(0x2200, addmod(mload(0x2140), sub(f_q, mload(0x21e0)), f_q)) + // mstore(0x2220, mulmod(mload(0x900), mload(0x4c0), f_q)) + // mstore(0x2240, addmod(mload(0x860), mload(0x2220), f_q)) + // mstore(0x2260, addmod(mload(0x2240), mload(0x520), f_q)) + // mstore(0x2280, mulmod(mload(0x920), mload(0x4c0), f_q)) + // mstore(0x22a0, addmod(mload(0x7e0), mload(0x2280), f_q)) + // mstore(0x22c0, addmod(mload(0x22a0), mload(0x520), f_q)) + // mstore(0x22e0, mulmod(mload(0x22c0), mload(0x2260), f_q)) + // mstore(0x2300, mulmod(mload(0x940), mload(0x4c0), f_q)) + // mstore(0x2320, addmod(mload(0x1f60), mload(0x2300), f_q)) + // mstore(0x2340, addmod(mload(0x2320), mload(0x520), f_q)) + // mstore(0x2360, mulmod(mload(0x2340), mload(0x22e0), f_q)) + // mstore(0x2380, mulmod(mload(0x2360), mload(0x980), f_q)) + // mstore(0x23a0, mulmod(1, mload(0x4c0), f_q)) + // mstore(0x23c0, mulmod(mload(0x7a0), mload(0x23a0), f_q)) + // mstore(0x23e0, addmod(mload(0x860), mload(0x23c0), f_q)) + // mstore(0x2400, addmod(mload(0x23e0), mload(0x520), f_q)) + // mstore( + // 0x2420, + // mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x4c0), f_q) + // ) + // mstore(0x2440, mulmod(mload(0x7a0), mload(0x2420), f_q)) + // mstore(0x2460, addmod(mload(0x7e0), mload(0x2440), f_q)) + // mstore(0x2480, addmod(mload(0x2460), mload(0x520), f_q)) + // mstore(0x24a0, mulmod(mload(0x2480), mload(0x2400), f_q)) + // mstore( + // 0x24c0, + // mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x4c0), f_q) + // ) + // mstore(0x24e0, mulmod(mload(0x7a0), mload(0x24c0), f_q)) + // mstore(0x2500, addmod(mload(0x1f60), mload(0x24e0), f_q)) + // mstore(0x2520, addmod(mload(0x2500), mload(0x520), f_q)) + // mstore(0x2540, mulmod(mload(0x2520), mload(0x24a0), f_q)) + // mstore(0x2560, mulmod(mload(0x2540), mload(0x960), f_q)) + // mstore(0x2580, addmod(mload(0x2380), sub(f_q, mload(0x2560)), f_q)) + // mstore(0x25a0, mulmod(mload(0x2580), mload(0x2200), f_q)) + // mstore(0x25c0, addmod(mload(0x2120), mload(0x25a0), f_q)) + // mstore(0x25e0, mulmod(mload(0x640), mload(0x25c0), f_q)) + // mstore(0x2600, addmod(1, sub(f_q, mload(0x9a0)), f_q)) + // mstore(0x2620, mulmod(mload(0x2600), mload(0x1c80), f_q)) + // mstore(0x2640, addmod(mload(0x25e0), mload(0x2620), f_q)) + // mstore(0x2660, mulmod(mload(0x640), mload(0x2640), f_q)) + // mstore(0x2680, mulmod(mload(0x9a0), mload(0x9a0), f_q)) + // mstore(0x26a0, addmod(mload(0x2680), sub(f_q, mload(0x9a0)), f_q)) + // mstore(0x26c0, mulmod(mload(0x26a0), mload(0x1ba0), f_q)) + // mstore(0x26e0, addmod(mload(0x2660), mload(0x26c0), f_q)) + // mstore(0x2700, mulmod(mload(0x640), mload(0x26e0), f_q)) + // mstore(0x2720, addmod(mload(0x9e0), mload(0x4c0), f_q)) + // mstore(0x2740, mulmod(mload(0x2720), mload(0x9c0), f_q)) + // mstore(0x2760, addmod(mload(0xa20), mload(0x520), f_q)) + // mstore(0x2780, mulmod(mload(0x2760), mload(0x2740), f_q)) + // mstore(0x27a0, mulmod(mload(0x7e0), mload(0x8c0), f_q)) + // mstore(0x27c0, addmod(mload(0x27a0), mload(0x4c0), f_q)) + // mstore(0x27e0, mulmod(mload(0x27c0), mload(0x9a0), f_q)) + // mstore(0x2800, addmod(mload(0x880), mload(0x520), f_q)) + // mstore(0x2820, mulmod(mload(0x2800), mload(0x27e0), f_q)) + // mstore(0x2840, addmod(mload(0x2780), sub(f_q, mload(0x2820)), f_q)) + // mstore(0x2860, mulmod(mload(0x2840), mload(0x2200), f_q)) + // mstore(0x2880, addmod(mload(0x2700), mload(0x2860), f_q)) + // mstore(0x28a0, mulmod(mload(0x640), mload(0x2880), f_q)) + // mstore(0x28c0, addmod(mload(0x9e0), sub(f_q, mload(0xa20)), f_q)) + // mstore(0x28e0, mulmod(mload(0x28c0), mload(0x1c80), f_q)) + // mstore(0x2900, addmod(mload(0x28a0), mload(0x28e0), f_q)) + // mstore(0x2920, mulmod(mload(0x640), mload(0x2900), f_q)) + // mstore(0x2940, mulmod(mload(0x28c0), mload(0x2200), f_q)) + // mstore(0x2960, addmod(mload(0x9e0), sub(f_q, mload(0xa00)), f_q)) + // mstore(0x2980, mulmod(mload(0x2960), mload(0x2940), f_q)) + // mstore(0x29a0, addmod(mload(0x2920), mload(0x2980), f_q)) + // mstore(0x29c0, mulmod(mload(0xf20), mload(0xf20), f_q)) + // mstore(0x29e0, mulmod(mload(0x29c0), mload(0xf20), f_q)) + // mstore(0x2a00, mulmod(mload(0x29e0), mload(0xf20), f_q)) + // mstore(0x2a20, mulmod(1, mload(0xf20), f_q)) + // mstore(0x2a40, mulmod(1, mload(0x29c0), f_q)) + // mstore(0x2a60, mulmod(1, mload(0x29e0), f_q)) + // mstore(0x2a80, mulmod(mload(0x29a0), mload(0xf40), f_q)) + // mstore(0x2aa0, mulmod(mload(0xc60), mload(0x7a0), f_q)) + // mstore(0x2ac0, mulmod(mload(0x2aa0), mload(0x7a0), f_q)) + // mstore( + // 0x2ae0, + // mulmod(mload(0x7a0), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + // ) + // mstore(0x2b00, addmod(mload(0xb60), sub(f_q, mload(0x2ae0)), f_q)) + // mstore(0x2b20, mulmod(mload(0x7a0), 1, f_q)) + // mstore(0x2b40, addmod(mload(0xb60), sub(f_q, mload(0x2b20)), f_q)) + // mstore( + // 0x2b60, + // mulmod(mload(0x7a0), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + // ) + // mstore(0x2b80, addmod(mload(0xb60), sub(f_q, mload(0x2b60)), f_q)) + // mstore( + // 0x2ba0, + // mulmod(mload(0x7a0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) + // ) + // mstore(0x2bc0, addmod(mload(0xb60), sub(f_q, mload(0x2ba0)), f_q)) + // mstore( + // 0x2be0, + // mulmod(mload(0x7a0), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + // ) + // mstore(0x2c00, addmod(mload(0xb60), sub(f_q, mload(0x2be0)), f_q)) + // mstore( + // 0x2c20, + // mulmod( + // 13213688729882003894512633350385593288217014177373218494356903340348818451480, mload(0x2aa0), f_q + // ) + // ) + // mstore(0x2c40, mulmod(mload(0x2c20), 1, f_q)) + // { + // let result := mulmod(mload(0xb60), mload(0x2c20), f_q) + // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2c40)), f_q), result, f_q) + // mstore(11360, result) + // } + // mstore( + // 0x2c80, + // mulmod(8207090019724696496350398458716998472718344609680392612601596849934418295470, mload(0x2aa0), f_q) + // ) + // mstore( + // 0x2ca0, + // mulmod(mload(0x2c80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + // ) + // { + // let result := mulmod(mload(0xb60), mload(0x2c80), f_q) + // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ca0)), f_q), result, f_q) + // mstore(11456, result) + // } + // mstore( + // 0x2ce0, + // mulmod(7391709068497399131897422873231908718558236401035363928063603272120120747483, mload(0x2aa0), f_q) + // ) + // mstore( + // 0x2d00, + // mulmod( + // mload(0x2ce0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q + // ) + // ) + // { + // let result := mulmod(mload(0xb60), mload(0x2ce0), f_q) + // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d00)), f_q), result, f_q) + // mstore(11552, result) + // } + // mstore( + // 0x2d40, + // mulmod( + // 19036273796805830823244991598792794567595348772040298280440552631112242221017, mload(0x2aa0), f_q + // ) + // ) + // mstore( + // 0x2d60, + // mulmod(mload(0x2d40), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + // ) + // { + // let result := mulmod(mload(0xb60), mload(0x2d40), f_q) + // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d60)), f_q), result, f_q) + // mstore(11648, result) + // } + // mstore(0x2da0, mulmod(1, mload(0x2b40), f_q)) + // mstore(0x2dc0, mulmod(mload(0x2da0), mload(0x2b80), f_q)) + // mstore(0x2de0, mulmod(mload(0x2dc0), mload(0x2bc0), f_q)) + // mstore(0x2e00, mulmod(mload(0x2de0), mload(0x2c00), f_q)) + // mstore( + // 0x2e20, + // mulmod(13513867906530865119835332133273263211836799082674232843258448413103731898271, mload(0x7a0), f_q) + // ) + // mstore(0x2e40, mulmod(mload(0x2e20), 1, f_q)) + // { + // let result := mulmod(mload(0xb60), mload(0x2e20), f_q) + // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2e40)), f_q), result, f_q) + // mstore(11872, result) + // } + // mstore( + // 0x2e80, + // mulmod(8374374965308410102411073611984011876711565317741801500439755773472076597346, mload(0x7a0), f_q) + // ) + // mstore( + // 0x2ea0, + // mulmod(mload(0x2e80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + // ) + // { + // let result := mulmod(mload(0xb60), mload(0x2e80), f_q) + // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ea0)), f_q), result, f_q) + // mstore(11968, result) + // } + // mstore( + // 0x2ee0, + // mulmod(12146688980418810893951125255607130521645347193942732958664170801695864621271, mload(0x7a0), f_q) + // ) + // mstore(0x2f00, mulmod(mload(0x2ee0), 1, f_q)) + // { + // let result := mulmod(mload(0xb60), mload(0x2ee0), f_q) + // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f00)), f_q), result, f_q) + // mstore(12064, result) + // } + // mstore( + // 0x2f40, + // mulmod(9741553891420464328295280489650144566903017206473301385034033384879943874346, mload(0x7a0), f_q) + // ) + // mstore( + // 0x2f60, + // mulmod(mload(0x2f40), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + // ) + // { + // let result := mulmod(mload(0xb60), mload(0x2f40), f_q) + // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f60)), f_q), result, f_q) + // mstore(12160, result) + // } + // mstore(0x2fa0, mulmod(mload(0x2da0), mload(0x2b00), f_q)) + // { + // let result := mulmod(mload(0xb60), 1, f_q) + // result := + // addmod( + // mulmod( + // mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q + // ), + // result, + // f_q + // ) + // mstore(12224, result) + // } + // { + // let prod := mload(0x2c60) + + // prod := mulmod(mload(0x2cc0), prod, f_q) + // mstore(0x2fe0, prod) + + // prod := mulmod(mload(0x2d20), prod, f_q) + // mstore(0x3000, prod) + + // prod := mulmod(mload(0x2d80), prod, f_q) + // mstore(0x3020, prod) + + // prod := mulmod(mload(0x2e60), prod, f_q) + // mstore(0x3040, prod) + + // prod := mulmod(mload(0x2ec0), prod, f_q) + // mstore(0x3060, prod) + + // prod := mulmod(mload(0x2dc0), prod, f_q) + // mstore(0x3080, prod) + + // prod := mulmod(mload(0x2f20), prod, f_q) + // mstore(0x30a0, prod) + + // prod := mulmod(mload(0x2f80), prod, f_q) + // mstore(0x30c0, prod) + + // prod := mulmod(mload(0x2fa0), prod, f_q) + // mstore(0x30e0, prod) + + // prod := mulmod(mload(0x2fc0), prod, f_q) + // mstore(0x3100, prod) + + // prod := mulmod(mload(0x2da0), prod, f_q) + // mstore(0x3120, prod) + // } + // mstore(0x3160, 32) + // mstore(0x3180, 32) + // mstore(0x31a0, 32) + // mstore(0x31c0, mload(0x3120)) + // mstore(0x31e0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + // mstore(0x3200, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + // success := and(eq(staticcall(gas(), 0x5, 0x3160, 0xc0, 0x3140, 0x20), 1), success) + // { + // let inv := mload(0x3140) + // let v + + // v := mload(0x2da0) + // mstore(11680, mulmod(mload(0x3100), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x2fc0) + // mstore(12224, mulmod(mload(0x30e0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x2fa0) + // mstore(12192, mulmod(mload(0x30c0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x2f80) + // mstore(12160, mulmod(mload(0x30a0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x2f20) + // mstore(12064, mulmod(mload(0x3080), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x2dc0) + // mstore(11712, mulmod(mload(0x3060), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x2ec0) + // mstore(11968, mulmod(mload(0x3040), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x2e60) + // mstore(11872, mulmod(mload(0x3020), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x2d80) + // mstore(11648, mulmod(mload(0x3000), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x2d20) + // mstore(11552, mulmod(mload(0x2fe0), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x2cc0) + // mstore(11456, mulmod(mload(0x2c60), inv, f_q)) + // inv := mulmod(v, inv, f_q) + // mstore(0x2c60, inv) + // } + // { + // let result := mload(0x2c60) + // result := addmod(mload(0x2cc0), result, f_q) + // result := addmod(mload(0x2d20), result, f_q) + // result := addmod(mload(0x2d80), result, f_q) + // mstore(12832, result) + // } + // mstore(0x3240, mulmod(mload(0x2e00), mload(0x2dc0), f_q)) + // { + // let result := mload(0x2e60) + // result := addmod(mload(0x2ec0), result, f_q) + // mstore(12896, result) + // } + // mstore(0x3280, mulmod(mload(0x2e00), mload(0x2fa0), f_q)) + // { + // let result := mload(0x2f20) + // result := addmod(mload(0x2f80), result, f_q) + // mstore(12960, result) + // } + // mstore(0x32c0, mulmod(mload(0x2e00), mload(0x2da0), f_q)) + // { + // let result := mload(0x2fc0) + // mstore(13024, result) + // } + // { + // let prod := mload(0x3220) + + // prod := mulmod(mload(0x3260), prod, f_q) + // mstore(0x3300, prod) + + // prod := mulmod(mload(0x32a0), prod, f_q) + // mstore(0x3320, prod) + + // prod := mulmod(mload(0x32e0), prod, f_q) + // mstore(0x3340, prod) + // } + // mstore(0x3380, 32) + // mstore(0x33a0, 32) + // mstore(0x33c0, 32) + // mstore(0x33e0, mload(0x3340)) + // mstore(0x3400, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + // mstore(0x3420, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + // success := and(eq(staticcall(gas(), 0x5, 0x3380, 0xc0, 0x3360, 0x20), 1), success) + // { + // let inv := mload(0x3360) + // let v + + // v := mload(0x32e0) + // mstore(13024, mulmod(mload(0x3320), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x32a0) + // mstore(12960, mulmod(mload(0x3300), inv, f_q)) + // inv := mulmod(v, inv, f_q) + + // v := mload(0x3260) + // mstore(12896, mulmod(mload(0x3220), inv, f_q)) + // inv := mulmod(v, inv, f_q) + // mstore(0x3220, inv) + // } + // mstore(0x3440, mulmod(mload(0x3240), mload(0x3260), f_q)) + // mstore(0x3460, mulmod(mload(0x3280), mload(0x32a0), f_q)) + // mstore(0x3480, mulmod(mload(0x32c0), mload(0x32e0), f_q)) + // mstore(0x34a0, mulmod(mload(0xa60), mload(0xa60), f_q)) + // mstore(0x34c0, mulmod(mload(0x34a0), mload(0xa60), f_q)) + // mstore(0x34e0, mulmod(mload(0x34c0), mload(0xa60), f_q)) + // mstore(0x3500, mulmod(mload(0x34e0), mload(0xa60), f_q)) + // mstore(0x3520, mulmod(mload(0x3500), mload(0xa60), f_q)) + // mstore(0x3540, mulmod(mload(0x3520), mload(0xa60), f_q)) + // mstore(0x3560, mulmod(mload(0x3540), mload(0xa60), f_q)) + // mstore(0x3580, mulmod(mload(0x3560), mload(0xa60), f_q)) + // mstore(0x35a0, mulmod(mload(0x3580), mload(0xa60), f_q)) + // mstore(0x35c0, mulmod(mload(0xac0), mload(0xac0), f_q)) + // mstore(0x35e0, mulmod(mload(0x35c0), mload(0xac0), f_q)) + // mstore(0x3600, mulmod(mload(0x35e0), mload(0xac0), f_q)) + // { + // let result := mulmod(mload(0x7e0), mload(0x2c60), f_q) + // result := addmod(mulmod(mload(0x800), mload(0x2cc0), f_q), result, f_q) + // result := addmod(mulmod(mload(0x820), mload(0x2d20), f_q), result, f_q) + // result := addmod(mulmod(mload(0x840), mload(0x2d80), f_q), result, f_q) + // mstore(13856, result) + // } + // mstore(0x3640, mulmod(mload(0x3620), mload(0x3220), f_q)) + // mstore(0x3660, mulmod(sub(f_q, mload(0x3640)), 1, f_q)) + // mstore(0x3680, mulmod(mload(0x3660), 1, f_q)) + // mstore(0x36a0, mulmod(1, mload(0x3240), f_q)) + // { + // let result := mulmod(mload(0x960), mload(0x2e60), f_q) + // result := addmod(mulmod(mload(0x980), mload(0x2ec0), f_q), result, f_q) + // mstore(14016, result) + // } + // mstore(0x36e0, mulmod(mload(0x36c0), mload(0x3440), f_q)) + // mstore(0x3700, mulmod(sub(f_q, mload(0x36e0)), 1, f_q)) + // mstore(0x3720, mulmod(mload(0x36a0), 1, f_q)) + // { + // let result := mulmod(mload(0x9a0), mload(0x2e60), f_q) + // result := addmod(mulmod(mload(0x9c0), mload(0x2ec0), f_q), result, f_q) + // mstore(14144, result) + // } + // mstore(0x3760, mulmod(mload(0x3740), mload(0x3440), f_q)) + // mstore(0x3780, mulmod(sub(f_q, mload(0x3760)), mload(0xa60), f_q)) + // mstore(0x37a0, mulmod(mload(0x36a0), mload(0xa60), f_q)) + // mstore(0x37c0, addmod(mload(0x3700), mload(0x3780), f_q)) + // mstore(0x37e0, mulmod(mload(0x37c0), mload(0xac0), f_q)) + // mstore(0x3800, mulmod(mload(0x3720), mload(0xac0), f_q)) + // mstore(0x3820, mulmod(mload(0x37a0), mload(0xac0), f_q)) + // mstore(0x3840, addmod(mload(0x3680), mload(0x37e0), f_q)) + // mstore(0x3860, mulmod(1, mload(0x3280), f_q)) + // { + // let result := mulmod(mload(0x9e0), mload(0x2f20), f_q) + // result := addmod(mulmod(mload(0xa00), mload(0x2f80), f_q), result, f_q) + // mstore(14464, result) + // } + // mstore(0x38a0, mulmod(mload(0x3880), mload(0x3460), f_q)) + // mstore(0x38c0, mulmod(sub(f_q, mload(0x38a0)), 1, f_q)) + // mstore(0x38e0, mulmod(mload(0x3860), 1, f_q)) + // mstore(0x3900, mulmod(mload(0x38c0), mload(0x35c0), f_q)) + // mstore(0x3920, mulmod(mload(0x38e0), mload(0x35c0), f_q)) + // mstore(0x3940, addmod(mload(0x3840), mload(0x3900), f_q)) + // mstore(0x3960, mulmod(1, mload(0x32c0), f_q)) + // { + // let result := mulmod(mload(0xa20), mload(0x2fc0), f_q) + // mstore(14720, result) + // } + // mstore(0x39a0, mulmod(mload(0x3980), mload(0x3480), f_q)) + // mstore(0x39c0, mulmod(sub(f_q, mload(0x39a0)), 1, f_q)) + // mstore(0x39e0, mulmod(mload(0x3960), 1, f_q)) + // { + // let result := mulmod(mload(0x860), mload(0x2fc0), f_q) + // mstore(14848, result) + // } + // mstore(0x3a20, mulmod(mload(0x3a00), mload(0x3480), f_q)) + // mstore(0x3a40, mulmod(sub(f_q, mload(0x3a20)), mload(0xa60), f_q)) + // mstore(0x3a60, mulmod(mload(0x3960), mload(0xa60), f_q)) + // mstore(0x3a80, addmod(mload(0x39c0), mload(0x3a40), f_q)) + // { + // let result := mulmod(mload(0x880), mload(0x2fc0), f_q) + // mstore(15008, result) + // } + // mstore(0x3ac0, mulmod(mload(0x3aa0), mload(0x3480), f_q)) + // mstore(0x3ae0, mulmod(sub(f_q, mload(0x3ac0)), mload(0x34a0), f_q)) + // mstore(0x3b00, mulmod(mload(0x3960), mload(0x34a0), f_q)) + // mstore(0x3b20, addmod(mload(0x3a80), mload(0x3ae0), f_q)) + // { + // let result := mulmod(mload(0x8a0), mload(0x2fc0), f_q) + // mstore(15168, result) + // } + // mstore(0x3b60, mulmod(mload(0x3b40), mload(0x3480), f_q)) + // mstore(0x3b80, mulmod(sub(f_q, mload(0x3b60)), mload(0x34c0), f_q)) + // mstore(0x3ba0, mulmod(mload(0x3960), mload(0x34c0), f_q)) + // mstore(0x3bc0, addmod(mload(0x3b20), mload(0x3b80), f_q)) + // { + // let result := mulmod(mload(0x8c0), mload(0x2fc0), f_q) + // mstore(15328, result) + // } + // mstore(0x3c00, mulmod(mload(0x3be0), mload(0x3480), f_q)) + // mstore(0x3c20, mulmod(sub(f_q, mload(0x3c00)), mload(0x34e0), f_q)) + // mstore(0x3c40, mulmod(mload(0x3960), mload(0x34e0), f_q)) + // mstore(0x3c60, addmod(mload(0x3bc0), mload(0x3c20), f_q)) + // { + // let result := mulmod(mload(0x900), mload(0x2fc0), f_q) + // mstore(15488, result) + // } + // mstore(0x3ca0, mulmod(mload(0x3c80), mload(0x3480), f_q)) + // mstore(0x3cc0, mulmod(sub(f_q, mload(0x3ca0)), mload(0x3500), f_q)) + // mstore(0x3ce0, mulmod(mload(0x3960), mload(0x3500), f_q)) + // mstore(0x3d00, addmod(mload(0x3c60), mload(0x3cc0), f_q)) + // { + // let result := mulmod(mload(0x920), mload(0x2fc0), f_q) + // mstore(15648, result) + // } + // mstore(0x3d40, mulmod(mload(0x3d20), mload(0x3480), f_q)) + // mstore(0x3d60, mulmod(sub(f_q, mload(0x3d40)), mload(0x3520), f_q)) + // mstore(0x3d80, mulmod(mload(0x3960), mload(0x3520), f_q)) + // mstore(0x3da0, addmod(mload(0x3d00), mload(0x3d60), f_q)) + // { + // let result := mulmod(mload(0x940), mload(0x2fc0), f_q) + // mstore(15808, result) + // } + // mstore(0x3de0, mulmod(mload(0x3dc0), mload(0x3480), f_q)) + // mstore(0x3e00, mulmod(sub(f_q, mload(0x3de0)), mload(0x3540), f_q)) + // mstore(0x3e20, mulmod(mload(0x3960), mload(0x3540), f_q)) + // mstore(0x3e40, addmod(mload(0x3da0), mload(0x3e00), f_q)) + // mstore(0x3e60, mulmod(mload(0x2a20), mload(0x32c0), f_q)) + // mstore(0x3e80, mulmod(mload(0x2a40), mload(0x32c0), f_q)) + // mstore(0x3ea0, mulmod(mload(0x2a60), mload(0x32c0), f_q)) + // { + // let result := mulmod(mload(0x2a80), mload(0x2fc0), f_q) + // mstore(16064, result) + // } + // mstore(0x3ee0, mulmod(mload(0x3ec0), mload(0x3480), f_q)) + // mstore(0x3f00, mulmod(sub(f_q, mload(0x3ee0)), mload(0x3560), f_q)) + // mstore(0x3f20, mulmod(mload(0x3960), mload(0x3560), f_q)) + // mstore(0x3f40, mulmod(mload(0x3e60), mload(0x3560), f_q)) + // mstore(0x3f60, mulmod(mload(0x3e80), mload(0x3560), f_q)) + // mstore(0x3f80, mulmod(mload(0x3ea0), mload(0x3560), f_q)) + // mstore(0x3fa0, addmod(mload(0x3e40), mload(0x3f00), f_q)) + // { + // let result := mulmod(mload(0x8e0), mload(0x2fc0), f_q) + // mstore(16320, result) + // } + // mstore(0x3fe0, mulmod(mload(0x3fc0), mload(0x3480), f_q)) + // mstore(0x4000, mulmod(sub(f_q, mload(0x3fe0)), mload(0x3580), f_q)) + // mstore(0x4020, mulmod(mload(0x3960), mload(0x3580), f_q)) + // mstore(0x4040, addmod(mload(0x3fa0), mload(0x4000), f_q)) + // mstore(0x4060, mulmod(mload(0x4040), mload(0x35e0), f_q)) + // mstore(0x4080, mulmod(mload(0x39e0), mload(0x35e0), f_q)) + // mstore(0x40a0, mulmod(mload(0x3a60), mload(0x35e0), f_q)) + // mstore(0x40c0, mulmod(mload(0x3b00), mload(0x35e0), f_q)) + // mstore(0x40e0, mulmod(mload(0x3ba0), mload(0x35e0), f_q)) + // mstore(0x4100, mulmod(mload(0x3c40), mload(0x35e0), f_q)) + // mstore(0x4120, mulmod(mload(0x3ce0), mload(0x35e0), f_q)) + // mstore(0x4140, mulmod(mload(0x3d80), mload(0x35e0), f_q)) + // mstore(0x4160, mulmod(mload(0x3e20), mload(0x35e0), f_q)) + // mstore(0x4180, mulmod(mload(0x3f20), mload(0x35e0), f_q)) + // mstore(0x41a0, mulmod(mload(0x3f40), mload(0x35e0), f_q)) + // mstore(0x41c0, mulmod(mload(0x3f60), mload(0x35e0), f_q)) + // mstore(0x41e0, mulmod(mload(0x3f80), mload(0x35e0), f_q)) + // mstore(0x4200, mulmod(mload(0x4020), mload(0x35e0), f_q)) + // mstore(0x4220, addmod(mload(0x3940), mload(0x4060), f_q)) + // mstore(0x4240, mulmod(1, mload(0x2e00), f_q)) + // mstore(0x4260, mulmod(1, mload(0xb60), f_q)) + // mstore(0x4280, 0x0000000000000000000000000000000000000000000000000000000000000001) + // mstore(0x42a0, 0x0000000000000000000000000000000000000000000000000000000000000002) + // mstore(0x42c0, mload(0x4220)) + // success := and(eq(staticcall(gas(), 0x7, 0x4280, 0x60, 0x4280, 0x40), 1), success) + // mstore(0x42e0, mload(0x4280)) + // mstore(0x4300, mload(0x42a0)) + // mstore(0x4320, mload(0x380)) + // mstore(0x4340, mload(0x3a0)) + // success := and(eq(staticcall(gas(), 0x6, 0x42e0, 0x80, 0x42e0, 0x40), 1), success) + // mstore(0x4360, mload(0x560)) + // mstore(0x4380, mload(0x580)) + // mstore(0x43a0, mload(0x3800)) + // success := and(eq(staticcall(gas(), 0x7, 0x4360, 0x60, 0x4360, 0x40), 1), success) + // mstore(0x43c0, mload(0x42e0)) + // mstore(0x43e0, mload(0x4300)) + // mstore(0x4400, mload(0x4360)) + // mstore(0x4420, mload(0x4380)) + // success := and(eq(staticcall(gas(), 0x6, 0x43c0, 0x80, 0x43c0, 0x40), 1), success) + // mstore(0x4440, mload(0x5a0)) + // mstore(0x4460, mload(0x5c0)) + // mstore(0x4480, mload(0x3820)) + // success := and(eq(staticcall(gas(), 0x7, 0x4440, 0x60, 0x4440, 0x40), 1), success) + // mstore(0x44a0, mload(0x43c0)) + // mstore(0x44c0, mload(0x43e0)) + // mstore(0x44e0, mload(0x4440)) + // mstore(0x4500, mload(0x4460)) + // success := and(eq(staticcall(gas(), 0x6, 0x44a0, 0x80, 0x44a0, 0x40), 1), success) + // mstore(0x4520, mload(0x420)) + // mstore(0x4540, mload(0x440)) + // mstore(0x4560, mload(0x3920)) + // success := and(eq(staticcall(gas(), 0x7, 0x4520, 0x60, 0x4520, 0x40), 1), success) + // mstore(0x4580, mload(0x44a0)) + // mstore(0x45a0, mload(0x44c0)) + // mstore(0x45c0, mload(0x4520)) + // mstore(0x45e0, mload(0x4540)) + // success := and(eq(staticcall(gas(), 0x6, 0x4580, 0x80, 0x4580, 0x40), 1), success) + // mstore(0x4600, mload(0x460)) + // mstore(0x4620, mload(0x480)) + // mstore(0x4640, mload(0x4080)) + // success := and(eq(staticcall(gas(), 0x7, 0x4600, 0x60, 0x4600, 0x40), 1), success) + // mstore(0x4660, mload(0x4580)) + // mstore(0x4680, mload(0x45a0)) + // mstore(0x46a0, mload(0x4600)) + // mstore(0x46c0, mload(0x4620)) + // success := and(eq(staticcall(gas(), 0x6, 0x4660, 0x80, 0x4660, 0x40), 1), success) + // mstore(0x46e0, 0x21b14b6e8ea36289961bde7f1d8f191389a815740d09f34f13190341383dfb13) + // mstore(0x4700, 0x16740f9c3982e02aeb0cb10086339afaca1bb103d5ae3f114c45a569d60c88ce) + // mstore(0x4720, mload(0x40a0)) + // success := and(eq(staticcall(gas(), 0x7, 0x46e0, 0x60, 0x46e0, 0x40), 1), success) + // mstore(0x4740, mload(0x4660)) + // mstore(0x4760, mload(0x4680)) + // mstore(0x4780, mload(0x46e0)) + // mstore(0x47a0, mload(0x4700)) + // success := and(eq(staticcall(gas(), 0x6, 0x4740, 0x80, 0x4740, 0x40), 1), success) + // mstore(0x47c0, 0x2eb40e2b0c13a6f4b989cffa9dbc452447bfd9f04a79f6379aefea8c9850a550) + // mstore(0x47e0, 0x0efe5496541e2bd648d490f11ad542e1dec3127f818b8065843d0dd81358416c) + // mstore(0x4800, mload(0x40c0)) + // success := and(eq(staticcall(gas(), 0x7, 0x47c0, 0x60, 0x47c0, 0x40), 1), success) + // mstore(0x4820, mload(0x4740)) + // mstore(0x4840, mload(0x4760)) + // mstore(0x4860, mload(0x47c0)) + // mstore(0x4880, mload(0x47e0)) + // success := and(eq(staticcall(gas(), 0x6, 0x4820, 0x80, 0x4820, 0x40), 1), success) + // mstore(0x48a0, 0x1c6707c73bce576eb360ffcb2fa9a0b17ad541ea0a0e8001439bca524f2f5a43) + // mstore(0x48c0, 0x03b899b999df6cf57b7755535b1dc5014a9dbd21d55c31d826d8338dc2fe8722) + // mstore(0x48e0, mload(0x40e0)) + // success := and(eq(staticcall(gas(), 0x7, 0x48a0, 0x60, 0x48a0, 0x40), 1), success) + // mstore(0x4900, mload(0x4820)) + // mstore(0x4920, mload(0x4840)) + // mstore(0x4940, mload(0x48a0)) + // mstore(0x4960, mload(0x48c0)) + // success := and(eq(staticcall(gas(), 0x6, 0x4900, 0x80, 0x4900, 0x40), 1), success) + // mstore(0x4980, 0x1d309220cdb6694a08a8c77f89984557e19bbda422f41d50b47bf30b30b3dec3) + // mstore(0x49a0, 0x138c263b3cbc7de6f5f92f88c44a3e7fc278a4b69008db2340097131e43dbb1a) + // mstore(0x49c0, mload(0x4100)) + // success := and(eq(staticcall(gas(), 0x7, 0x4980, 0x60, 0x4980, 0x40), 1), success) + // mstore(0x49e0, mload(0x4900)) + // mstore(0x4a00, mload(0x4920)) + // mstore(0x4a20, mload(0x4980)) + // mstore(0x4a40, mload(0x49a0)) + // success := and(eq(staticcall(gas(), 0x6, 0x49e0, 0x80, 0x49e0, 0x40), 1), success) + // mstore(0x4a60, 0x2529da4dfe20ec7564dc8738f2477daf565052f29117d9a2c1a0cbe846ab95fb) + // mstore(0x4a80, 0x2a3971e5a786b7e8b0039d1100621af00a8743921a36ef7aafc430b09a5bd279) + // mstore(0x4aa0, mload(0x4120)) + // success := and(eq(staticcall(gas(), 0x7, 0x4a60, 0x60, 0x4a60, 0x40), 1), success) + // mstore(0x4ac0, mload(0x49e0)) + // mstore(0x4ae0, mload(0x4a00)) + // mstore(0x4b00, mload(0x4a60)) + // mstore(0x4b20, mload(0x4a80)) + // success := and(eq(staticcall(gas(), 0x6, 0x4ac0, 0x80, 0x4ac0, 0x40), 1), success) + // mstore(0x4b40, 0x132e1a4125c783ea4817ea96d967c5f06a49933ca71f7e99f7be022ef1e3ca35) + // mstore(0x4b60, 0x0eb726ae10479119d87b2e1d0d2b72db88506d263ae939b2154b0f3f5c7012f7) + // mstore(0x4b80, mload(0x4140)) + // success := and(eq(staticcall(gas(), 0x7, 0x4b40, 0x60, 0x4b40, 0x40), 1), success) + // mstore(0x4ba0, mload(0x4ac0)) + // mstore(0x4bc0, mload(0x4ae0)) + // mstore(0x4be0, mload(0x4b40)) + // mstore(0x4c00, mload(0x4b60)) + // success := and(eq(staticcall(gas(), 0x6, 0x4ba0, 0x80, 0x4ba0, 0x40), 1), success) + // mstore(0x4c20, 0x1bc70a16efa4ef34c9ee86dc04d041fc8430240113b09ef71d5bbb8b685af6b7) + // mstore(0x4c40, 0x25064309a3b7ab3efd593b9e6c2f1294b50c12e237412186d7af94b1591dc937) + // mstore(0x4c60, mload(0x4160)) + // success := and(eq(staticcall(gas(), 0x7, 0x4c20, 0x60, 0x4c20, 0x40), 1), success) + // mstore(0x4c80, mload(0x4ba0)) + // mstore(0x4ca0, mload(0x4bc0)) + // mstore(0x4cc0, mload(0x4c20)) + // mstore(0x4ce0, mload(0x4c40)) + // success := and(eq(staticcall(gas(), 0x6, 0x4c80, 0x80, 0x4c80, 0x40), 1), success) + // mstore(0x4d00, mload(0x680)) + // mstore(0x4d20, mload(0x6a0)) + // mstore(0x4d40, mload(0x4180)) + // success := and(eq(staticcall(gas(), 0x7, 0x4d00, 0x60, 0x4d00, 0x40), 1), success) + // mstore(0x4d60, mload(0x4c80)) + // mstore(0x4d80, mload(0x4ca0)) + // mstore(0x4da0, mload(0x4d00)) + // mstore(0x4dc0, mload(0x4d20)) + // success := and(eq(staticcall(gas(), 0x6, 0x4d60, 0x80, 0x4d60, 0x40), 1), success) + // mstore(0x4de0, mload(0x6c0)) + // mstore(0x4e00, mload(0x6e0)) + // mstore(0x4e20, mload(0x41a0)) + // success := and(eq(staticcall(gas(), 0x7, 0x4de0, 0x60, 0x4de0, 0x40), 1), success) + // mstore(0x4e40, mload(0x4d60)) + // mstore(0x4e60, mload(0x4d80)) + // mstore(0x4e80, mload(0x4de0)) + // mstore(0x4ea0, mload(0x4e00)) + // success := and(eq(staticcall(gas(), 0x6, 0x4e40, 0x80, 0x4e40, 0x40), 1), success) + // mstore(0x4ec0, mload(0x700)) + // mstore(0x4ee0, mload(0x720)) + // mstore(0x4f00, mload(0x41c0)) + // success := and(eq(staticcall(gas(), 0x7, 0x4ec0, 0x60, 0x4ec0, 0x40), 1), success) + // mstore(0x4f20, mload(0x4e40)) + // mstore(0x4f40, mload(0x4e60)) + // mstore(0x4f60, mload(0x4ec0)) + // mstore(0x4f80, mload(0x4ee0)) + // success := and(eq(staticcall(gas(), 0x6, 0x4f20, 0x80, 0x4f20, 0x40), 1), success) + // mstore(0x4fa0, mload(0x740)) + // mstore(0x4fc0, mload(0x760)) + // mstore(0x4fe0, mload(0x41e0)) + // success := and(eq(staticcall(gas(), 0x7, 0x4fa0, 0x60, 0x4fa0, 0x40), 1), success) + // mstore(0x5000, mload(0x4f20)) + // mstore(0x5020, mload(0x4f40)) + // mstore(0x5040, mload(0x4fa0)) + // mstore(0x5060, mload(0x4fc0)) + // success := and(eq(staticcall(gas(), 0x6, 0x5000, 0x80, 0x5000, 0x40), 1), success) + // mstore(0x5080, mload(0x5e0)) + // mstore(0x50a0, mload(0x600)) + // mstore(0x50c0, mload(0x4200)) + // success := and(eq(staticcall(gas(), 0x7, 0x5080, 0x60, 0x5080, 0x40), 1), success) + // mstore(0x50e0, mload(0x5000)) + // mstore(0x5100, mload(0x5020)) + // mstore(0x5120, mload(0x5080)) + // mstore(0x5140, mload(0x50a0)) + // success := and(eq(staticcall(gas(), 0x6, 0x50e0, 0x80, 0x50e0, 0x40), 1), success) + // mstore(0x5160, mload(0xb00)) + // mstore(0x5180, mload(0xb20)) + // mstore(0x51a0, sub(f_q, mload(0x4240))) + // success := and(eq(staticcall(gas(), 0x7, 0x5160, 0x60, 0x5160, 0x40), 1), success) + // mstore(0x51c0, mload(0x50e0)) + // mstore(0x51e0, mload(0x5100)) + // mstore(0x5200, mload(0x5160)) + // mstore(0x5220, mload(0x5180)) + // success := and(eq(staticcall(gas(), 0x6, 0x51c0, 0x80, 0x51c0, 0x40), 1), success) + // mstore(0x5240, mload(0xba0)) + // mstore(0x5260, mload(0xbc0)) + // mstore(0x5280, mload(0x4260)) + // success := and(eq(staticcall(gas(), 0x7, 0x5240, 0x60, 0x5240, 0x40), 1), success) + // mstore(0x52a0, mload(0x51c0)) + // mstore(0x52c0, mload(0x51e0)) + // mstore(0x52e0, mload(0x5240)) + // mstore(0x5300, mload(0x5260)) + // success := and(eq(staticcall(gas(), 0x6, 0x52a0, 0x80, 0x52a0, 0x40), 1), success) + // mstore(0x5320, mload(0x52a0)) + // mstore(0x5340, mload(0x52c0)) + // mstore(0x5360, mload(0xba0)) + // mstore(0x5380, mload(0xbc0)) + // mstore(0x53a0, mload(0xbe0)) + // mstore(0x53c0, mload(0xc00)) + // mstore(0x53e0, mload(0xc20)) + // mstore(0x5400, mload(0xc40)) + // mstore(0x5420, keccak256(0x5320, 256)) + // mstore(21568, mod(mload(21536), f_q)) + // mstore(0x5460, mulmod(mload(0x5440), mload(0x5440), f_q)) + // mstore(0x5480, mulmod(1, mload(0x5440), f_q)) + // mstore(0x54a0, mload(0x53a0)) + // mstore(0x54c0, mload(0x53c0)) + // mstore(0x54e0, mload(0x5480)) + // success := and(eq(staticcall(gas(), 0x7, 0x54a0, 0x60, 0x54a0, 0x40), 1), success) + // mstore(0x5500, mload(0x5320)) + // mstore(0x5520, mload(0x5340)) + // mstore(0x5540, mload(0x54a0)) + // mstore(0x5560, mload(0x54c0)) + // success := and(eq(staticcall(gas(), 0x6, 0x5500, 0x80, 0x5500, 0x40), 1), success) + // mstore(0x5580, mload(0x53e0)) + // mstore(0x55a0, mload(0x5400)) + // mstore(0x55c0, mload(0x5480)) + // success := and(eq(staticcall(gas(), 0x7, 0x5580, 0x60, 0x5580, 0x40), 1), success) + // mstore(0x55e0, mload(0x5360)) + // mstore(0x5600, mload(0x5380)) + // mstore(0x5620, mload(0x5580)) + // mstore(0x5640, mload(0x55a0)) + // success := and(eq(staticcall(gas(), 0x6, 0x55e0, 0x80, 0x55e0, 0x40), 1), success) + // mstore(0x5660, mload(0x5500)) + // mstore(0x5680, mload(0x5520)) + // mstore(0x56a0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) + // mstore(0x56c0, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + // mstore(0x56e0, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + // mstore(0x5700, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + // mstore(0x5720, mload(0x55e0)) + // mstore(0x5740, mload(0x5600)) + // mstore(0x5760, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) + // mstore(0x5780, 0x2ae0c8c3a090f7200ff398ee9845bbae8f8c1445ae7b632212775f60a0e21600) + // mstore(0x57a0, 0x190fa476a5b352809ed41d7a0d7fe12b8f685e3c12a6d83855dba27aaf469643) + // mstore(0x57c0, 0x1c0a500618907df9e4273d5181e31088deb1f05132de037cbfe73888f97f77c9) + // success := and(eq(staticcall(gas(), 0x8, 0x5660, 0x180, 0x5660, 0x20), 1), success) + // success := and(eq(mload(0x5660), 1), success) + + // // Revert if anything fails + // if iszero(success) { revert(0, 0) } + + // // Return empty bytes on success + // return(0, 0) + // } } } diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index 0795b49..e778d88 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -1,18 +1,22 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19; +import { AxiomV2QueryVerifier } from "./Halo2Verifier.sol"; + +type MemoryPointer is uint256; + /// @notice This contract provides a thin wrapper around the Halo2 verifier -/// outputted by `snark-verifier`. -/// -/// @dev This contract should be inherited by the `snark-verifier` output. -abstract contract OpenVmHalo2Verifier { +/// outputted by `snark-verifier`, exposing a more user-friendly interface. +contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { error InvalidPartialProofLength(); error InvalidGuestPvsLength(); error ProofVerificationFailed(); uint256 private constant PARTIAL_PROOF_LENGTH = (12 + 43) * 32; - uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + 32 + 43) * 32; + uint256 private constant GUEST_PVS_LENGTH = 32; + + uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + GUEST_PVS_LENGTH + 43) * 32; /// @notice A wrapper that constructs the proof into the right format for /// use with the `snark-verifier` verification. @@ -24,7 +28,7 @@ abstract contract OpenVmHalo2Verifier { /// proof[..12 * 32]: KZG accumulators /// proof[12 * 32..13 * 32]: app exe commit /// proof[13 * 32..14 * 32]: leaf exe commit - /// proof[14 * 32..46 * 32]: guestPvsHash[0..32] + /// proof[14 * 32..46 * 32]: guestPvsHash[0..GUEST_PVS_LENGTH] /// proof[46 * 32..]: Guest PVs Suffix /// /// Or with hex offsets @@ -32,7 +36,7 @@ abstract contract OpenVmHalo2Verifier { /// proof[..0x180]: KZG accumulators /// proof[0x180..0x1a0]: app exe commit /// proof[0x1a0..0x1c0]: leaf exe commit - /// proof[0x1c0..0x5c0]: guestPvsHash[0..32] + /// proof[0x1c0..0x5c0]: guestPvsHash[0..GUEST_PVS_LENGTH] /// proof[0x5c0..]: Guest PVs Suffix /// /// @param partialProof All components of the proof except the Guest PVs, @@ -49,90 +53,96 @@ abstract contract OpenVmHalo2Verifier { bytes32 appExeCommit, bytes32 leafExeCommit ) external view { - if (guestPvs.length != 32) revert InvalidGuestPvsLength(); - if (partialProof.length != PARTIAL_PROOF_LENGTH) revert InvalidPartialProofLength(); - // We will format the pvsHash and construct the full proof payload // below for submission to the verifier. + MemoryPointer proofPtr = _constructProof(guestPvs, partialProof, appExeCommit, leafExeCommit); + + uint256 fullProofLength = FULL_PROOF_LENGTH; + assembly { + // Self-call using the proof as calldata + if iszero(staticcall(gas(), address(), proofPtr, fullProofLength, 0, 0)) { + mstore(0x00, 0xd611c318) // ProofVerificationFailed() + revert(0x1c, 0x04) + } + } + } + + function _constructProof( + bytes calldata guestPvs, + bytes calldata partialProof, + bytes32 appExeCommit, + bytes32 leafExeCommit + ) internal pure returns (MemoryPointer proofPtr) { + if (guestPvs.length != GUEST_PVS_LENGTH) revert InvalidGuestPvsLength(); + if (partialProof.length != PARTIAL_PROOF_LENGTH) revert InvalidPartialProofLength(); + // The assembly code should perform the same function as the following // solidity code: // - // bytes memory guestPvsPayload = new bytes(32 * 32); - // for (uint256 i = 0; i < 32; ++i) { + // bytes memory guestPvsPayload = new bytes(GUEST_PVS_LENGTH * 32); + // for (uint256 i = 0; i < GUEST_PVS_LENGTH; ++i) { // bytes1 pvsByte = guestPvs[i]; // guestPvsPayload = bytes.concat(guestPvsPayload, bytes32(uint256(uint8(pvsByte)))); // } // // bytes memory proof = // abi.encodePacked(partialProof[0:0x180], appExeCommit, leafExeCommit, guestPvsPayload, partialProof[0x180:]); - // - // (bool success,) = address(this).staticcall(proof); - // if (!success) revert ProofVerificationFailed(); + + uint256 fullProofLength = FULL_PROOF_LENGTH; /// @solidity memory-safe-assembly assembly { - let fmp := mload(0x40) - mstore(0x40, add(fmp, FULL_PROOF_LENGTH)) - - let guestPvsHash := calldataload(guestPvs.offset) + proofPtr := mload(0x40) + // Allocate the memory as a safety measure + mstore(0x40, add(proofPtr, fullProofLength)) // Copy the KZG accumulators (length 0x180) into the beginning of // the memory buffer - calldatacopy(fmp, partialProof.offset, 0x180) + calldatacopy(proofPtr, partialProof.offset, 0x180) // Copy the App Exe Commit and Leaf Exe Commit into the memory buffer - mstore(add(fmp, 0x180), appExeCommit) - mstore(add(fmp, 0x1a0), leafExeCommit) + mstore(add(proofPtr, 0x180), appExeCommit) + mstore(add(proofPtr, 0x1a0), leafExeCommit) // Copy the Guest PVs Suffix (length 43 * 32 = 0x560) into the - // end of the memory buffer (between 0x5c0 - TOTAL_PROOF_LENGTH), - // leaving 32 words in between for the guestPvsHash. + // end of the memory buffer, leaving GUEST_PVS_LENGTH words in + // between for the guestPvsHash. // // Begin copying from the end of the KZG accumulators in the // calldata buffer (0x180) - calldatacopy(add(fmp, 0x5c0), add(partialProof.offset, 0x180), 0x560) + let suffixProofOffset := add(0x1c0, shl(5, GUEST_PVS_LENGTH)) + calldatacopy(add(proofPtr, suffixProofOffset), add(partialProof.offset, 0x180), 0x560) // Copy each byte of the guestPvsHash into the proof. It copies the // most significant bytes of guestPvsHash first. - let guestPvsMemOffset := add(fmp, 0x1c0) - mstore(add(guestPvsMemOffset, 0x00), byte(0x00, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x20), byte(0x01, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x40), byte(0x02, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x60), byte(0x03, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x80), byte(0x04, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0xa0), byte(0x05, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0xc0), byte(0x06, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0xe0), byte(0x07, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x100), byte(0x08, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x120), byte(0x09, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x140), byte(0x0a, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x160), byte(0x0b, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x180), byte(0x0c, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x1a0), byte(0x0d, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x1c0), byte(0x0e, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x1e0), byte(0x0f, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x200), byte(0x10, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x220), byte(0x11, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x240), byte(0x12, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x260), byte(0x13, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x280), byte(0x14, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x2a0), byte(0x15, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x2c0), byte(0x16, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x2e0), byte(0x17, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x300), byte(0x18, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x320), byte(0x19, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x340), byte(0x1a, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x360), byte(0x1b, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x380), byte(0x1c, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x3a0), byte(0x1d, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x3c0), byte(0x1e, guestPvsHash)) - mstore(add(guestPvsMemOffset, 0x3e0), byte(0x1f, guestPvsHash)) - // Self-call using the proof as calldata - if iszero(staticcall(gas(), address(), fmp, FULL_PROOF_LENGTH, 0, 0)) { - mstore(0x00, 0xd611c318) // ProofVerificationFailed() - revert(0x1c, 0x04) + // Begin by loading 32-byte segments and copying each byte of each + // segment into its own memory slot. + let wordCount := div(GUEST_PVS_LENGTH, 32) + + let guestPvsMemOffset := add(proofPtr, 0x1c0) + for { let i := 0 } iszero(eq(i, wordCount)) { i := add(i, 1) } { + // Load the current word + let word := calldataload(add(guestPvs.offset, shl(5, i))) + + // Copy each byte of the word into the proof + for { let j := 0 } iszero(eq(j, 32)) { j := add(j, 1) } { + // 32 * 32 * i + 32 * j + let pvsByteOffset := add(shl(10, i), shl(5, j)) + mstore(add(guestPvsMemOffset, pvsByteOffset), byte(j, word)) + } + } + + // Then, copy the remaining bytes into the memory buffer. + let remainder := mod(GUEST_PVS_LENGTH, 32) + guestPvsMemOffset := add(guestPvsMemOffset, shl(5, wordCount)) + + let remainingBytes := calldataload(add(guestPvs.offset, shl(5, wordCount))) + for { let j := 0 } iszero(eq(j, remainder)) { j := add(j, 1) } { + // 32 * 32 * wordCount + 32 * j + let pvsByteOffset := add(shl(10, wordCount), shl(5, j)) + mstore(add(guestPvsMemOffset, pvsByteOffset), byte(j, remainingBytes)) } } } diff --git a/test/OpenVmHalo2Verifier.t.sol b/test/OpenVmHalo2Verifier.t.sol index 5935fd8..5d2d49c 100644 --- a/test/OpenVmHalo2Verifier.t.sol +++ b/test/OpenVmHalo2Verifier.t.sol @@ -1,21 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import { OpenVmHalo2Verifier } from "../src/OpenVmHalo2Verifier.sol"; +import { OpenVmHalo2Verifier, MemoryPointer } from "../src/OpenVmHalo2Verifier.sol"; import { Test, console2, safeconsole as console } from "forge-std/Test.sol"; -contract MockVerifier is OpenVmHalo2Verifier { - fallback(bytes calldata) external returns (bytes memory) { - return hex""; - } -} - contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { bytes partialProof; bytes32 appExeCommit = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; bytes32 leafExeCommit = 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; bytes32 guestPvsHash = 0xDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; + uint256 private constant FULL_PROOF_WORDS = (12 + 2 + 32 + 43); + + uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + 32 + 43) * 32; + function setUp() public { partialProof = new bytes(55 * 32); for (uint256 i = 0; i < 55; i++) { @@ -25,10 +23,14 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { } } - function test_proofFormat() public view { + function test_verifyProof() public view { this.verifyProof(abi.encodePacked(guestPvsHash), partialProof, appExeCommit, leafExeCommit); } + function test_proofFormat() public view { + this.constructAndCheckProof(abi.encodePacked(guestPvsHash), partialProof, appExeCommit, leafExeCommit); + } + function testFuzz_proofFormat( uint256 partialProofSeed, bytes32 _guestPvsHash, @@ -53,38 +55,81 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { test_proofFormat(); } - function test_RevertWhen_InvalidPartialProofLength() public { - vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidPartialProofLength.selector)); - this.verifyProof(abi.encodePacked(guestPvsHash), hex"aa", appExeCommit, leafExeCommit); - } + function constructAndCheckProof( + bytes calldata _guestPvs, + bytes calldata _partialProof, + bytes32 _appExeCommit, + bytes32 _leafExeCommit + ) external view { + MemoryPointer proofPtr = _constructProof(_guestPvs, _partialProof, _appExeCommit, _leafExeCommit); + + // _constructProof will return a pointer to memory that will hold the + // proof data in a block of size FULL_PROOF_LENGTH. However, this won't + // be directly compatible with `bytes memory` since it will be missing + // the length as the first word. So below, we will + // + // 1. Move all the data down by 32 bytes in memory + // 2. Set the length in the first word which we just created the space for + // 3. Allocate the memory for the length (32 bytes) + // 4. Create a `bytes memory` pointer which points to the length + + uint256 i = FULL_PROOF_WORDS - 1; + while (true) { + uint256 currentPtr = MemoryPointer.unwrap(proofPtr) + i * 32; + // console.log("currentPtr", currentPtr); + uint256 destPtr = MemoryPointer.unwrap(proofPtr) + ((i + 1) * 32); + // console.log("destPtr", destPtr); + assembly { + mstore(destPtr, mload(currentPtr)) + } + if (i == 0) break; + i--; + } - function test_RevertWhen_InvalidGuestPvsLength() public { - vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidGuestPvsLength.selector)); - this.verifyProof(partialProof, hex"aa", appExeCommit, leafExeCommit); + bytes memory proof; + assembly { + // 2. + mstore(proofPtr, FULL_PROOF_LENGTH) + // 3. + mstore(0x40, add(mload(0x40), 0x20)) + + // 4. + proof := proofPtr + } + + this.checkProofFormat(proof); } - fallback(bytes calldata) external returns (bytes memory) { + function checkProofFormat(bytes calldata proof) external view { bytes memory partialProofExpected = partialProof; - bytes memory kzgAccumulators = msg.data[0:0x180]; - bytes memory guestPvsSuffix = msg.data[0x5c0:]; + bytes memory kzgAccumulators = proof[0:0x180]; + bytes memory guestPvsSuffix = proof[0x5c0:]; bytes memory _partialProof = abi.encodePacked(kzgAccumulators, guestPvsSuffix); require(keccak256(_partialProof) == keccak256(partialProofExpected), "Partial proof mismatch"); - bytes memory _appExeCommit = msg.data[0x180:0x1a0]; - bytes memory _leafExeCommit = msg.data[0x1a0:0x1c0]; + bytes memory _appExeCommit = proof[0x180:0x1a0]; + bytes memory _leafExeCommit = proof[0x1a0:0x1c0]; require(bytes32(_appExeCommit) == appExeCommit, "App exe commit mismatch"); require(bytes32(_leafExeCommit) == leafExeCommit, "Leaf exe commit mismatch"); bytes32 guestPvsHashExpected = guestPvsHash; - bytes calldata _guestPvsHash = msg.data[0x1c0:0x5c0]; + bytes calldata _guestPvsHash = proof[0x1c0:0x5c0]; for (uint256 i = 0; i < 32; ++i) { uint256 expected = uint256(uint8(guestPvsHashExpected[i])); uint256 actual = uint256(bytes32(_guestPvsHash[i * 32:(i + 1) * 32])); require(expected == actual, "Guest PVs hash mismatch"); } + } - return hex""; + function test_RevertWhen_InvalidPartialProofLength() public { + vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidPartialProofLength.selector)); + this.verifyProof(abi.encodePacked(guestPvsHash), hex"aa", appExeCommit, leafExeCommit); + } + + function test_RevertWhen_InvalidGuestPvsLength() public { + vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidGuestPvsLength.selector)); + this.verifyProof(partialProof, hex"aa", appExeCommit, leafExeCommit); } } From 8b7e38797533f9d74e7b11d524b9f23d2f9dc9e8 Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Wed, 19 Mar 2025 21:03:19 -0400 Subject: [PATCH 04/15] refactor: simplify pvs copying --- src/OpenVmHalo2Verifier.sol | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index e778d88..69df153 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -122,27 +122,8 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { let wordCount := div(GUEST_PVS_LENGTH, 32) let guestPvsMemOffset := add(proofPtr, 0x1c0) - for { let i := 0 } iszero(eq(i, wordCount)) { i := add(i, 1) } { - // Load the current word - let word := calldataload(add(guestPvs.offset, shl(5, i))) - - // Copy each byte of the word into the proof - for { let j := 0 } iszero(eq(j, 32)) { j := add(j, 1) } { - // 32 * 32 * i + 32 * j - let pvsByteOffset := add(shl(10, i), shl(5, j)) - mstore(add(guestPvsMemOffset, pvsByteOffset), byte(j, word)) - } - } - - // Then, copy the remaining bytes into the memory buffer. - let remainder := mod(GUEST_PVS_LENGTH, 32) - guestPvsMemOffset := add(guestPvsMemOffset, shl(5, wordCount)) - - let remainingBytes := calldataload(add(guestPvs.offset, shl(5, wordCount))) - for { let j := 0 } iszero(eq(j, remainder)) { j := add(j, 1) } { - // 32 * 32 * wordCount + 32 * j - let pvsByteOffset := add(shl(10, wordCount), shl(5, j)) - mstore(add(guestPvsMemOffset, pvsByteOffset), byte(j, remainingBytes)) + for { let i := 0 } lt(i, GUEST_PVS_LENGTH) { i := add(i, 1) } { + calldatacopy(add(guestPvsMemOffset, add(shl(5, i), 0x1f)), add(guestPvs.offset, i), 0x01) } } } From 5d3cd40894859eacc4bbd580e4bcf64dc428da34 Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Wed, 19 Mar 2025 21:12:29 -0400 Subject: [PATCH 05/15] chore: update docs and cleanup --- src/OpenVmHalo2Verifier.sol | 45 +++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index 69df153..7cf52c6 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -8,14 +8,22 @@ type MemoryPointer is uint256; /// @notice This contract provides a thin wrapper around the Halo2 verifier /// outputted by `snark-verifier`, exposing a more user-friendly interface. contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { + /// @dev Invalid partial proof length error InvalidPartialProofLength(); + + /// @dev Invalid guest PVs length error InvalidGuestPvsLength(); + + /// @dev Proof verification failed error ProofVerificationFailed(); + /// @dev The length of the partial proof, in bytes uint256 private constant PARTIAL_PROOF_LENGTH = (12 + 43) * 32; + /// @dev The length of the guest PVs, in bytes. This value is set by OpenVM. uint256 private constant GUEST_PVS_LENGTH = 32; + /// @dev The length of the full proof, in bytes uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + GUEST_PVS_LENGTH + 43) * 32; /// @notice A wrapper that constructs the proof into the right format for @@ -28,22 +36,21 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { /// proof[..12 * 32]: KZG accumulators /// proof[12 * 32..13 * 32]: app exe commit /// proof[13 * 32..14 * 32]: leaf exe commit - /// proof[14 * 32..46 * 32]: guestPvsHash[0..GUEST_PVS_LENGTH] - /// proof[46 * 32..]: Guest PVs Suffix + /// proof[14 * 32..(14 + GUEST_PVS_LENGTH) * 32]: guestPvs[0..GUEST_PVS_LENGTH] + /// proof[(14 + GUEST_PVS_LENGTH) * 32..]: Guest PVs Suffix /// /// Or with hex offsets /// /// proof[..0x180]: KZG accumulators /// proof[0x180..0x1a0]: app exe commit /// proof[0x1a0..0x1c0]: leaf exe commit - /// proof[0x1c0..0x5c0]: guestPvsHash[0..GUEST_PVS_LENGTH] - /// proof[0x5c0..]: Guest PVs Suffix + /// proof[0x1c0..(0x1c0 + GUEST_PVS_LENGTH * 32)]: guestPvs[0..GUEST_PVS_LENGTH] + /// proof[(0x1c0 + GUEST_PVS_LENGTH * 32)..]: Guest PVs Suffix /// /// @param partialProof All components of the proof except the Guest PVs, /// leaf and app exe commits. The expected format is: /// `abi.encodePacked(KZG accumulators, Guest PVs Suffix)` - /// @param guestPvs The PVs revealed by the OpenVM guest program. This - /// contract is only compatible with a reveal of exactly 32 bytes. + /// @param guestPvs The PVs revealed by the OpenVM guest program. /// @param appExeCommit The commitment to the RISC-V executable whose execution /// is being verified. /// @param leafExeCommit The commitment to the leaf verifier. @@ -53,8 +60,8 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { bytes32 appExeCommit, bytes32 leafExeCommit ) external view { - // We will format the pvsHash and construct the full proof payload - // below for submission to the verifier. + // We will format the public values and construct the full proof payload + // below. MemoryPointer proofPtr = _constructProof(guestPvs, partialProof, appExeCommit, leafExeCommit); @@ -80,14 +87,13 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { // The assembly code should perform the same function as the following // solidity code: // - // bytes memory guestPvsPayload = new bytes(GUEST_PVS_LENGTH * 32); - // for (uint256 i = 0; i < GUEST_PVS_LENGTH; ++i) { - // bytes1 pvsByte = guestPvs[i]; - // guestPvsPayload = bytes.concat(guestPvsPayload, bytes32(uint256(uint8(pvsByte)))); - // } - // + // ```solidity // bytes memory proof = // abi.encodePacked(partialProof[0:0x180], appExeCommit, leafExeCommit, guestPvsPayload, partialProof[0x180:]); + // ``` + // + // where `guestPvsPayload` is a memory payload with each byte in + // `guestPvs` separated into its own word. uint256 fullProofLength = FULL_PROOF_LENGTH; @@ -107,20 +113,15 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { // Copy the Guest PVs Suffix (length 43 * 32 = 0x560) into the // end of the memory buffer, leaving GUEST_PVS_LENGTH words in - // between for the guestPvsHash. + // between for the guestPvsPayload. // // Begin copying from the end of the KZG accumulators in the // calldata buffer (0x180) let suffixProofOffset := add(0x1c0, shl(5, GUEST_PVS_LENGTH)) calldatacopy(add(proofPtr, suffixProofOffset), add(partialProof.offset, 0x180), 0x560) - // Copy each byte of the guestPvsHash into the proof. It copies the - // most significant bytes of guestPvsHash first. - - // Begin by loading 32-byte segments and copying each byte of each - // segment into its own memory slot. - let wordCount := div(GUEST_PVS_LENGTH, 32) - + // Copy each byte of the guestPvs into the proof. It copies the + // most significant bytes of guestPvs first. let guestPvsMemOffset := add(proofPtr, 0x1c0) for { let i := 0 } lt(i, GUEST_PVS_LENGTH) { i := add(i, 1) } { calldatacopy(add(guestPvsMemOffset, add(shl(5, i), 0x1f)), add(guestPvs.offset, i), 0x01) From 98346d83233546dc246ae8859861fc86daf579a6 Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Thu, 20 Mar 2025 01:27:06 -0400 Subject: [PATCH 06/15] chore: address comments --- src/Halo2Verifier.sol | 2 +- src/OpenVmHalo2Verifier.sol | 40 ++++++++++++++++++---------------- test/OpenVmHalo2Verifier.t.sol | 34 ++++++++++------------------- 3 files changed, 34 insertions(+), 42 deletions(-) diff --git a/src/Halo2Verifier.sol b/src/Halo2Verifier.sol index caa5bbc..5b3cc1a 100644 --- a/src/Halo2Verifier.sol +++ b/src/Halo2Verifier.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -contract AxiomV2QueryVerifier { +contract Halo2Verifier { fallback(bytes calldata) external returns (bytes memory) { // assembly ("memory-safe") { // // Enforce that Solidity memory layout is respected diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index 7cf52c6..6525b86 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19; -import { AxiomV2QueryVerifier } from "./Halo2Verifier.sol"; +import { Halo2Verifier } from "./Halo2Verifier.sol"; type MemoryPointer is uint256; /// @notice This contract provides a thin wrapper around the Halo2 verifier /// outputted by `snark-verifier`, exposing a more user-friendly interface. -contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { +contract OpenVmHalo2Verifier is Halo2Verifier { /// @dev Invalid partial proof length error InvalidPartialProofLength(); @@ -26,6 +26,12 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { /// @dev The length of the full proof, in bytes uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + GUEST_PVS_LENGTH + 43) * 32; + /// @dev The leaf verifier commitment. This value is set by OpenVM. + bytes32 public constant LEAF_EXE_COMMIT = + bytes32(0x0000000000000000000000000000000000000000000000000000000000000000); + + string public constant OPENVM_VERSION = "v1.0.0"; + /// @notice A wrapper that constructs the proof into the right format for /// use with the `snark-verifier` verification. /// @@ -53,19 +59,18 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { /// @param guestPvs The PVs revealed by the OpenVM guest program. /// @param appExeCommit The commitment to the RISC-V executable whose execution /// is being verified. - /// @param leafExeCommit The commitment to the leaf verifier. - function verifyProof( - bytes calldata guestPvs, - bytes calldata partialProof, - bytes32 appExeCommit, - bytes32 leafExeCommit - ) external view { + function verify(bytes calldata guestPvs, bytes calldata partialProof, bytes32 appExeCommit) external view { + if (guestPvs.length != GUEST_PVS_LENGTH) revert InvalidGuestPvsLength(); + if (partialProof.length != PARTIAL_PROOF_LENGTH) revert InvalidPartialProofLength(); + // We will format the public values and construct the full proof payload // below. - MemoryPointer proofPtr = _constructProof(guestPvs, partialProof, appExeCommit, leafExeCommit); + MemoryPointer proofPtr = _constructProof(guestPvs, partialProof, appExeCommit); uint256 fullProofLength = FULL_PROOF_LENGTH; + + /// @solidity memory-safe-assembly assembly { // Self-call using the proof as calldata if iszero(staticcall(gas(), address(), proofPtr, fullProofLength, 0, 0)) { @@ -75,15 +80,11 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { } } - function _constructProof( - bytes calldata guestPvs, - bytes calldata partialProof, - bytes32 appExeCommit, - bytes32 leafExeCommit - ) internal pure returns (MemoryPointer proofPtr) { - if (guestPvs.length != GUEST_PVS_LENGTH) revert InvalidGuestPvsLength(); - if (partialProof.length != PARTIAL_PROOF_LENGTH) revert InvalidPartialProofLength(); - + function _constructProof(bytes calldata guestPvs, bytes calldata partialProof, bytes32 appExeCommit) + internal + pure + returns (MemoryPointer proofPtr) + { // The assembly code should perform the same function as the following // solidity code: // @@ -96,6 +97,7 @@ contract OpenVmHalo2Verifier is AxiomV2QueryVerifier { // `guestPvs` separated into its own word. uint256 fullProofLength = FULL_PROOF_LENGTH; + bytes32 leafExeCommit = LEAF_EXE_COMMIT; /// @solidity memory-safe-assembly assembly { diff --git a/test/OpenVmHalo2Verifier.t.sol b/test/OpenVmHalo2Verifier.t.sol index 5d2d49c..ecdf91f 100644 --- a/test/OpenVmHalo2Verifier.t.sol +++ b/test/OpenVmHalo2Verifier.t.sol @@ -7,8 +7,7 @@ import { Test, console2, safeconsole as console } from "forge-std/Test.sol"; contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { bytes partialProof; bytes32 appExeCommit = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - bytes32 leafExeCommit = 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; - bytes32 guestPvsHash = 0xDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; + bytes32 guestPvsHash = 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; uint256 private constant FULL_PROOF_WORDS = (12 + 2 + 32 + 43); @@ -24,22 +23,16 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { } function test_verifyProof() public view { - this.verifyProof(abi.encodePacked(guestPvsHash), partialProof, appExeCommit, leafExeCommit); + this.verify(abi.encodePacked(guestPvsHash), partialProof, appExeCommit); } function test_proofFormat() public view { - this.constructAndCheckProof(abi.encodePacked(guestPvsHash), partialProof, appExeCommit, leafExeCommit); + this.constructAndCheckProof(abi.encodePacked(guestPvsHash), partialProof, appExeCommit); } - function testFuzz_proofFormat( - uint256 partialProofSeed, - bytes32 _guestPvsHash, - bytes32 _appExeCommit, - bytes32 _leafExeCommit - ) public { + function testFuzz_proofFormat(uint256 partialProofSeed, bytes32 _guestPvsHash, bytes32 _appExeCommit) public { vm.assume(_guestPvsHash != bytes32(0)); vm.assume(_appExeCommit != bytes32(0)); - vm.assume(_leafExeCommit != bytes32(0)); bytes memory _partialProof = new bytes(55 * 32); for (uint256 i = 0; i < 55 * 32; ++i) { @@ -50,18 +43,15 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { partialProof = _partialProof; guestPvsHash = _guestPvsHash; appExeCommit = _appExeCommit; - leafExeCommit = _leafExeCommit; test_proofFormat(); } - function constructAndCheckProof( - bytes calldata _guestPvs, - bytes calldata _partialProof, - bytes32 _appExeCommit, - bytes32 _leafExeCommit - ) external view { - MemoryPointer proofPtr = _constructProof(_guestPvs, _partialProof, _appExeCommit, _leafExeCommit); + function constructAndCheckProof(bytes calldata _guestPvs, bytes calldata _partialProof, bytes32 _appExeCommit) + external + view + { + MemoryPointer proofPtr = _constructProof(_guestPvs, _partialProof, _appExeCommit); // _constructProof will return a pointer to memory that will hold the // proof data in a block of size FULL_PROOF_LENGTH. However, this won't @@ -112,7 +102,7 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { bytes memory _leafExeCommit = proof[0x1a0:0x1c0]; require(bytes32(_appExeCommit) == appExeCommit, "App exe commit mismatch"); - require(bytes32(_leafExeCommit) == leafExeCommit, "Leaf exe commit mismatch"); + require(bytes32(_leafExeCommit) == LEAF_EXE_COMMIT, "Leaf exe commit mismatch"); bytes32 guestPvsHashExpected = guestPvsHash; bytes calldata _guestPvsHash = proof[0x1c0:0x5c0]; @@ -125,11 +115,11 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { function test_RevertWhen_InvalidPartialProofLength() public { vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidPartialProofLength.selector)); - this.verifyProof(abi.encodePacked(guestPvsHash), hex"aa", appExeCommit, leafExeCommit); + this.verify(abi.encodePacked(guestPvsHash), hex"aa", appExeCommit); } function test_RevertWhen_InvalidGuestPvsLength() public { vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidGuestPvsLength.selector)); - this.verifyProof(partialProof, hex"aa", appExeCommit, leafExeCommit); + this.verify(partialProof, hex"aa", appExeCommit); } } From c2a795f6251ded985eaa94fe4a1dd9e99f1d8ed3 Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:06:33 -0400 Subject: [PATCH 07/15] perf: optimize pvs injection --- src/OpenVmHalo2Verifier.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index 6525b86..377fdcc 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -124,9 +124,9 @@ contract OpenVmHalo2Verifier is Halo2Verifier { // Copy each byte of the guestPvs into the proof. It copies the // most significant bytes of guestPvs first. - let guestPvsMemOffset := add(proofPtr, 0x1c0) - for { let i := 0 } lt(i, GUEST_PVS_LENGTH) { i := add(i, 1) } { - calldatacopy(add(guestPvsMemOffset, add(shl(5, i), 0x1f)), add(guestPvs.offset, i), 0x01) + let guestPvsMemOffset := add(add(proofPtr, 0x1c0), 0x1f) + for { let i := 0 } iszero(eq(i, GUEST_PVS_LENGTH)) { i := add(i, 1) } { + calldatacopy(add(guestPvsMemOffset, shl(5, i)), add(guestPvs.offset, i), 0x01) } } } From 41c44c4bf8081cb4f6706fee1f5983693dafc70b Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:06:41 -0400 Subject: [PATCH 08/15] chore: address comments --- src/OpenVmHalo2Verifier.sol | 27 +++++++++++++------------ src/interfaces/IOpenVmHalo2Verifier.sol | 6 ++++++ 2 files changed, 20 insertions(+), 13 deletions(-) create mode 100644 src/interfaces/IOpenVmHalo2Verifier.sol diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index 377fdcc..62053b3 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -2,12 +2,13 @@ pragma solidity 0.8.19; import { Halo2Verifier } from "./Halo2Verifier.sol"; +import { IOpenVmHalo2Verifier } from "./interfaces/IOpenVmHalo2Verifier.sol"; type MemoryPointer is uint256; /// @notice This contract provides a thin wrapper around the Halo2 verifier /// outputted by `snark-verifier`, exposing a more user-friendly interface. -contract OpenVmHalo2Verifier is Halo2Verifier { +contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// @dev Invalid partial proof length error InvalidPartialProofLength(); @@ -35,7 +36,7 @@ contract OpenVmHalo2Verifier is Halo2Verifier { /// @notice A wrapper that constructs the proof into the right format for /// use with the `snark-verifier` verification. /// - /// @dev This function assumes that `publicValues` encodes one `bytes32` + /// @dev This function assumes that `guestPvs` encodes one `bytes32` /// hash which is the hash of the public values. /// /// The verifier expected proof format is: @@ -45,19 +46,11 @@ contract OpenVmHalo2Verifier is Halo2Verifier { /// proof[14 * 32..(14 + GUEST_PVS_LENGTH) * 32]: guestPvs[0..GUEST_PVS_LENGTH] /// proof[(14 + GUEST_PVS_LENGTH) * 32..]: Guest PVs Suffix /// - /// Or with hex offsets - /// - /// proof[..0x180]: KZG accumulators - /// proof[0x180..0x1a0]: app exe commit - /// proof[0x1a0..0x1c0]: leaf exe commit - /// proof[0x1c0..(0x1c0 + GUEST_PVS_LENGTH * 32)]: guestPvs[0..GUEST_PVS_LENGTH] - /// proof[(0x1c0 + GUEST_PVS_LENGTH * 32)..]: Guest PVs Suffix - /// /// @param partialProof All components of the proof except the Guest PVs, /// leaf and app exe commits. The expected format is: - /// `abi.encodePacked(KZG accumulators, Guest PVs Suffix)` + /// `abi.encodePacked(kzgAccumulators, proofSuffix)` /// @param guestPvs The PVs revealed by the OpenVM guest program. - /// @param appExeCommit The commitment to the RISC-V executable whose execution + /// @param appExeCommit The commitment to the OpenVM application executable whose execution /// is being verified. function verify(bytes calldata guestPvs, bytes calldata partialProof, bytes32 appExeCommit) external view { if (guestPvs.length != GUEST_PVS_LENGTH) revert InvalidGuestPvsLength(); @@ -94,11 +87,19 @@ contract OpenVmHalo2Verifier is Halo2Verifier { // ``` // // where `guestPvsPayload` is a memory payload with each byte in - // `guestPvs` separated into its own word. + // `guestPvs` separated into its own `bytes32` word. uint256 fullProofLength = FULL_PROOF_LENGTH; bytes32 leafExeCommit = LEAF_EXE_COMMIT; + // The expected proof format using hex offsets: + // + // proof[..0x180]: KZG accumulators + // proof[0x180..0x1a0]: app exe commit + // proof[0x1a0..0x1c0]: leaf exe commit + // proof[0x1c0..(0x1c0 + GUEST_PVS_LENGTH * 32)]: guestPvs[0..GUEST_PVS_LENGTH] + // proof[(0x1c0 + GUEST_PVS_LENGTH * 32)..]: Guest PVs Suffix + /// @solidity memory-safe-assembly assembly { proofPtr := mload(0x40) diff --git a/src/interfaces/IOpenVmHalo2Verifier.sol b/src/interfaces/IOpenVmHalo2Verifier.sol new file mode 100644 index 0000000..e94461e --- /dev/null +++ b/src/interfaces/IOpenVmHalo2Verifier.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +interface IOpenVmHalo2Verifier { + function verify(bytes calldata guestPvs, bytes calldata partialProof, bytes32 appExeCommit) external view; +} From b43ecc9b71c3e7ebee2a66ca566a09cb8c390e1e Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Thu, 20 Mar 2025 23:23:39 -0400 Subject: [PATCH 09/15] chore: uncomment verifier --- src/Halo2Verifier.sol | 3096 ++++++++++++++++++++--------------------- 1 file changed, 1548 insertions(+), 1548 deletions(-) diff --git a/src/Halo2Verifier.sol b/src/Halo2Verifier.sol index 5b3cc1a..812ab5e 100644 --- a/src/Halo2Verifier.sol +++ b/src/Halo2Verifier.sol @@ -3,1565 +3,1565 @@ pragma solidity 0.8.19; contract Halo2Verifier { fallback(bytes calldata) external returns (bytes memory) { - // assembly ("memory-safe") { - // // Enforce that Solidity memory layout is respected - // let data := mload(0x40) - // if iszero(eq(data, 0x80)) { revert(0, 0) } - - // let success := true - // let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - // let f_q := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 - // function validate_ec_point(x, y) -> valid { - // { - // let x_lt_p := lt(x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - // let y_lt_p := lt(y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - // valid := and(x_lt_p, y_lt_p) - // } - // { - // let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - // let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - // let x_cube := - // mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - // let x_cube_plus_3 := - // addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - // let is_affine := eq(x_cube_plus_3, y_square) - // valid := and(valid, is_affine) - // } - // } - // mstore(0xa0, mod(calldataload(0x0), f_q)) - // mstore(0xc0, mod(calldataload(0x20), f_q)) - // mstore(0xe0, mod(calldataload(0x40), f_q)) - // mstore(0x100, mod(calldataload(0x60), f_q)) - // mstore(0x120, mod(calldataload(0x80), f_q)) - // mstore(0x140, mod(calldataload(0xa0), f_q)) - // mstore(0x160, mod(calldataload(0xc0), f_q)) - // mstore(0x180, mod(calldataload(0xe0), f_q)) - // mstore(0x1a0, mod(calldataload(0x100), f_q)) - // mstore(0x1c0, mod(calldataload(0x120), f_q)) - // mstore(0x1e0, mod(calldataload(0x140), f_q)) - // mstore(0x200, mod(calldataload(0x160), f_q)) - // mstore(0x220, mod(calldataload(0x180), f_q)) - // mstore(0x240, mod(calldataload(0x1a0), f_q)) - // mstore(0x260, mod(calldataload(0x1c0), f_q)) - // mstore(0x280, mod(calldataload(0x1e0), f_q)) - // mstore(0x2a0, mod(calldataload(0x200), f_q)) - // mstore(0x2c0, mod(calldataload(0x220), f_q)) - // mstore(0x2e0, mod(calldataload(0x240), f_q)) - // mstore(0x300, mod(calldataload(0x260), f_q)) - // mstore(0x320, mod(calldataload(0x280), f_q)) - // mstore(0x340, mod(calldataload(0x2a0), f_q)) - // mstore(0x360, mod(calldataload(0x2c0), f_q)) - // mstore(0x80, 15186165512185359347397944531838604952299016691786397857821503921188369501699) - - // { - // let x := calldataload(0x2e0) - // mstore(0x380, x) - // let y := calldataload(0x300) - // mstore(0x3a0, y) - // success := and(validate_ec_point(x, y), success) - // } - // mstore(0x3c0, keccak256(0x80, 832)) - // { - // let hash := mload(0x3c0) - // mstore(0x3e0, mod(hash, f_q)) - // mstore(0x400, hash) - // } - - // { - // let x := calldataload(0x320) - // mstore(0x420, x) - // let y := calldataload(0x340) - // mstore(0x440, y) - // success := and(validate_ec_point(x, y), success) - // } - - // { - // let x := calldataload(0x360) - // mstore(0x460, x) - // let y := calldataload(0x380) - // mstore(0x480, y) - // success := and(validate_ec_point(x, y), success) - // } - // mstore(0x4a0, keccak256(0x400, 160)) - // { - // let hash := mload(0x4a0) - // mstore(0x4c0, mod(hash, f_q)) - // mstore(0x4e0, hash) - // } - // mstore8(1280, 1) - // mstore(0x500, keccak256(0x4e0, 33)) - // { - // let hash := mload(0x500) - // mstore(0x520, mod(hash, f_q)) - // mstore(0x540, hash) - // } - - // { - // let x := calldataload(0x3a0) - // mstore(0x560, x) - // let y := calldataload(0x3c0) - // mstore(0x580, y) - // success := and(validate_ec_point(x, y), success) - // } - - // { - // let x := calldataload(0x3e0) - // mstore(0x5a0, x) - // let y := calldataload(0x400) - // mstore(0x5c0, y) - // success := and(validate_ec_point(x, y), success) - // } - - // { - // let x := calldataload(0x420) - // mstore(0x5e0, x) - // let y := calldataload(0x440) - // mstore(0x600, y) - // success := and(validate_ec_point(x, y), success) - // } - // mstore(0x620, keccak256(0x540, 224)) - // { - // let hash := mload(0x620) - // mstore(0x640, mod(hash, f_q)) - // mstore(0x660, hash) - // } - - // { - // let x := calldataload(0x460) - // mstore(0x680, x) - // let y := calldataload(0x480) - // mstore(0x6a0, y) - // success := and(validate_ec_point(x, y), success) - // } - - // { - // let x := calldataload(0x4a0) - // mstore(0x6c0, x) - // let y := calldataload(0x4c0) - // mstore(0x6e0, y) - // success := and(validate_ec_point(x, y), success) - // } - - // { - // let x := calldataload(0x4e0) - // mstore(0x700, x) - // let y := calldataload(0x500) - // mstore(0x720, y) - // success := and(validate_ec_point(x, y), success) - // } - - // { - // let x := calldataload(0x520) - // mstore(0x740, x) - // let y := calldataload(0x540) - // mstore(0x760, y) - // success := and(validate_ec_point(x, y), success) - // } - // mstore(0x780, keccak256(0x660, 288)) - // { - // let hash := mload(0x780) - // mstore(0x7a0, mod(hash, f_q)) - // mstore(0x7c0, hash) - // } - // mstore(0x7e0, mod(calldataload(0x560), f_q)) - // mstore(0x800, mod(calldataload(0x580), f_q)) - // mstore(0x820, mod(calldataload(0x5a0), f_q)) - // mstore(0x840, mod(calldataload(0x5c0), f_q)) - // mstore(0x860, mod(calldataload(0x5e0), f_q)) - // mstore(0x880, mod(calldataload(0x600), f_q)) - // mstore(0x8a0, mod(calldataload(0x620), f_q)) - // mstore(0x8c0, mod(calldataload(0x640), f_q)) - // mstore(0x8e0, mod(calldataload(0x660), f_q)) - // mstore(0x900, mod(calldataload(0x680), f_q)) - // mstore(0x920, mod(calldataload(0x6a0), f_q)) - // mstore(0x940, mod(calldataload(0x6c0), f_q)) - // mstore(0x960, mod(calldataload(0x6e0), f_q)) - // mstore(0x980, mod(calldataload(0x700), f_q)) - // mstore(0x9a0, mod(calldataload(0x720), f_q)) - // mstore(0x9c0, mod(calldataload(0x740), f_q)) - // mstore(0x9e0, mod(calldataload(0x760), f_q)) - // mstore(0xa00, mod(calldataload(0x780), f_q)) - // mstore(0xa20, mod(calldataload(0x7a0), f_q)) - // mstore(0xa40, keccak256(0x7c0, 640)) - // { - // let hash := mload(0xa40) - // mstore(0xa60, mod(hash, f_q)) - // mstore(0xa80, hash) - // } - // mstore8(2720, 1) - // mstore(0xaa0, keccak256(0xa80, 33)) - // { - // let hash := mload(0xaa0) - // mstore(0xac0, mod(hash, f_q)) - // mstore(0xae0, hash) - // } - - // { - // let x := calldataload(0x7c0) - // mstore(0xb00, x) - // let y := calldataload(0x7e0) - // mstore(0xb20, y) - // success := and(validate_ec_point(x, y), success) - // } - // mstore(0xb40, keccak256(0xae0, 96)) - // { - // let hash := mload(0xb40) - // mstore(0xb60, mod(hash, f_q)) - // mstore(0xb80, hash) - // } - - // { - // let x := calldataload(0x800) - // mstore(0xba0, x) - // let y := calldataload(0x820) - // mstore(0xbc0, y) - // success := and(validate_ec_point(x, y), success) - // } - // { - // let x := mload(0xa0) - // x := add(x, shl(88, mload(0xc0))) - // x := add(x, shl(176, mload(0xe0))) - // mstore(3040, x) - // let y := mload(0x100) - // y := add(y, shl(88, mload(0x120))) - // y := add(y, shl(176, mload(0x140))) - // mstore(3072, y) - - // success := and(validate_ec_point(x, y), success) - // } - // { - // let x := mload(0x160) - // x := add(x, shl(88, mload(0x180))) - // x := add(x, shl(176, mload(0x1a0))) - // mstore(3104, x) - // let y := mload(0x1c0) - // y := add(y, shl(88, mload(0x1e0))) - // y := add(y, shl(176, mload(0x200))) - // mstore(3136, y) - - // success := and(validate_ec_point(x, y), success) - // } - // mstore(0xc60, mulmod(mload(0x7a0), mload(0x7a0), f_q)) - // mstore(0xc80, mulmod(mload(0xc60), mload(0xc60), f_q)) - // mstore(0xca0, mulmod(mload(0xc80), mload(0xc80), f_q)) - // mstore(0xcc0, mulmod(mload(0xca0), mload(0xca0), f_q)) - // mstore(0xce0, mulmod(mload(0xcc0), mload(0xcc0), f_q)) - // mstore(0xd00, mulmod(mload(0xce0), mload(0xce0), f_q)) - // mstore(0xd20, mulmod(mload(0xd00), mload(0xd00), f_q)) - // mstore(0xd40, mulmod(mload(0xd20), mload(0xd20), f_q)) - // mstore(0xd60, mulmod(mload(0xd40), mload(0xd40), f_q)) - // mstore(0xd80, mulmod(mload(0xd60), mload(0xd60), f_q)) - // mstore(0xda0, mulmod(mload(0xd80), mload(0xd80), f_q)) - // mstore(0xdc0, mulmod(mload(0xda0), mload(0xda0), f_q)) - // mstore(0xde0, mulmod(mload(0xdc0), mload(0xdc0), f_q)) - // mstore(0xe00, mulmod(mload(0xde0), mload(0xde0), f_q)) - // mstore(0xe20, mulmod(mload(0xe00), mload(0xe00), f_q)) - // mstore(0xe40, mulmod(mload(0xe20), mload(0xe20), f_q)) - // mstore(0xe60, mulmod(mload(0xe40), mload(0xe40), f_q)) - // mstore(0xe80, mulmod(mload(0xe60), mload(0xe60), f_q)) - // mstore(0xea0, mulmod(mload(0xe80), mload(0xe80), f_q)) - // mstore(0xec0, mulmod(mload(0xea0), mload(0xea0), f_q)) - // mstore(0xee0, mulmod(mload(0xec0), mload(0xec0), f_q)) - // mstore(0xf00, mulmod(mload(0xee0), mload(0xee0), f_q)) - // mstore(0xf20, mulmod(mload(0xf00), mload(0xf00), f_q)) - // mstore( - // 0xf40, - // addmod(mload(0xf20), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) - // ) - // mstore( - // 0xf60, - // mulmod(mload(0xf40), 21888240262557392955334514970720457388010314637169927192662615958087340972065, f_q) - // ) - // mstore( - // 0xf80, - // mulmod(mload(0xf60), 4506835738822104338668100540817374747935106310012997856968187171738630203507, f_q) - // ) - // mstore( - // 0xfa0, - // addmod(mload(0x7a0), 17381407133017170883578305204439900340613258090403036486730017014837178292110, f_q) - // ) - // mstore( - // 0xfc0, - // mulmod(mload(0xf60), 21710372849001950800533397158415938114909991150039389063546734567764856596059, f_q) - // ) - // mstore( - // 0xfe0, - // addmod(mload(0x7a0), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q) - // ) - // mstore( - // 0x1000, - // mulmod(mload(0xf60), 1887003188133998471169152042388914354640772748308168868301418279904560637395, f_q) - // ) - // mstore( - // 0x1020, - // addmod(mload(0x7a0), 20001239683705276751077253702868360733907591652107865475396785906671247858222, f_q) - // ) - // mstore( - // 0x1040, - // mulmod(mload(0xf60), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q) - // ) - // mstore( - // 0x1060, - // addmod(mload(0x7a0), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q) - // ) - // mstore( - // 0x1080, - // mulmod(mload(0xf60), 14655294445420895451632927078981340937842238432098198055057679026789553137428, f_q) - // ) - // mstore( - // 0x10a0, - // addmod(mload(0x7a0), 7232948426418379770613478666275934150706125968317836288640525159786255358189, f_q) - // ) - // mstore( - // 0x10c0, - // mulmod(mload(0xf60), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) - // ) - // mstore( - // 0x10e0, - // addmod(mload(0x7a0), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q) - // ) - // mstore( - // 0x1100, - // mulmod(mload(0xf60), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) - // ) - // mstore( - // 0x1120, - // addmod(mload(0x7a0), 12146688980418810893951125255607130521645347193942732958664170801695864621270, f_q) - // ) - // mstore(0x1140, mulmod(mload(0xf60), 1, f_q)) - // mstore( - // 0x1160, - // addmod(mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) - // ) - // mstore( - // 0x1180, - // mulmod(mload(0xf60), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) - // ) - // mstore( - // 0x11a0, - // addmod(mload(0x7a0), 13513867906530865119835332133273263211836799082674232843258448413103731898270, f_q) - // ) - // mstore( - // 0x11c0, - // mulmod(mload(0xf60), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) - // ) - // mstore( - // 0x11e0, - // addmod(mload(0x7a0), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q) - // ) - // mstore( - // 0x1200, - // mulmod(mload(0xf60), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) - // ) - // mstore( - // 0x1220, - // addmod(mload(0x7a0), 18272764063556419981698118473909131571661591947471949595929891197711371770216, f_q) - // ) - // mstore( - // 0x1240, - // mulmod(mload(0xf60), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) - // ) - // mstore( - // 0x1260, - // addmod(mload(0x7a0), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q) - // ) - // mstore( - // 0x1280, - // mulmod(mload(0xf60), 216092043779272773661818549620449970334216366264741118684015851799902419467, f_q) - // ) - // mstore( - // 0x12a0, - // addmod(mload(0x7a0), 21672150828060002448584587195636825118214148034151293225014188334775906076150, f_q) - // ) - // mstore( - // 0x12c0, - // mulmod(mload(0xf60), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q) - // ) - // mstore( - // 0x12e0, - // addmod(mload(0x7a0), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q) - // ) - // mstore( - // 0x1300, - // mulmod(mload(0xf60), 18610195890048912503953886742825279624920778288956610528523679659246523534888, f_q) - // ) - // mstore( - // 0x1320, - // addmod(mload(0x7a0), 3278046981790362718292519002431995463627586111459423815174524527329284960729, f_q) - // ) - // mstore( - // 0x1340, - // mulmod(mload(0xf60), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q) - // ) - // mstore( - // 0x1360, - // addmod(mload(0x7a0), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q) - // ) - // mstore( - // 0x1380, - // mulmod(mload(0xf60), 14875928112196239563830800280253496262679717528621719058794366823499719730250, f_q) - // ) - // mstore( - // 0x13a0, - // addmod(mload(0x7a0), 7012314759643035658415605465003778825868646871794315284903837363076088765367, f_q) - // ) - // mstore( - // 0x13c0, - // mulmod(mload(0xf60), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q) - // ) - // mstore( - // 0x13e0, - // addmod(mload(0x7a0), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q) - // ) - // mstore( - // 0x1400, - // mulmod(mload(0xf60), 5522161504810533295870699551020523636289972223872138525048055197429246400245, f_q) - // ) - // mstore( - // 0x1420, - // addmod(mload(0x7a0), 16366081367028741926375706194236751452258392176543895818650148989146562095372, f_q) - // ) - // mstore( - // 0x1440, - // mulmod(mload(0xf60), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q) - // ) - // mstore( - // 0x1460, - // addmod(mload(0x7a0), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q) - // ) - // mstore( - // 0x1480, - // mulmod(mload(0xf60), 9100833993744738801214480881117348002768153232283708533639316963648253510584, f_q) - // ) - // mstore( - // 0x14a0, - // addmod(mload(0x7a0), 12787408878094536421031924864139927085780211168132325810058887222927554985033, f_q) - // ) - // mstore( - // 0x14c0, - // mulmod(mload(0xf60), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q) - // ) - // mstore( - // 0x14e0, - // addmod(mload(0x7a0), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q) - // ) - // mstore( - // 0x1500, - // mulmod(mload(0xf60), 6132660129994545119218258312491950835441607143741804980633129304664017206141, f_q) - // ) - // mstore( - // 0x1520, - // addmod(mload(0x7a0), 15755582741844730103028147432765324253106757256674229363065074881911791289476, f_q) - // ) - // mstore( - // 0x1540, - // mulmod(mload(0xf60), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q) - // ) - // mstore( - // 0x1560, - // addmod(mload(0x7a0), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q) - // ) - // mstore( - // 0x1580, - // mulmod(mload(0xf60), 515148244606945972463850631189471072103916690263705052318085725998468254533, f_q) - // ) - // mstore( - // 0x15a0, - // addmod(mload(0x7a0), 21373094627232329249782555114067804016444447710152329291380118460577340241084, f_q) - // ) - // mstore( - // 0x15c0, - // mulmod(mload(0xf60), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q) - // ) - // mstore( - // 0x15e0, - // addmod(mload(0x7a0), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q) - // ) - // mstore( - // 0x1600, - // mulmod(mload(0xf60), 5223738580615264174925218065001555728265216895679471490312087802465486318994, f_q) - // ) - // mstore( - // 0x1620, - // addmod(mload(0x7a0), 16664504291224011047321187680255719360283147504736562853386116384110322176623, f_q) - // ) - // mstore( - // 0x1640, - // mulmod(mload(0xf60), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q) - // ) - // mstore( - // 0x1660, - // addmod(mload(0x7a0), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q) - // ) - // mstore( - // 0x1680, - // mulmod(mload(0xf60), 16976236069879939850923145256911338076234942200101755618884183331004076579046, f_q) - // ) - // mstore( - // 0x16a0, - // addmod(mload(0x7a0), 4912006801959335371323260488345937012313422200314278724814020855571731916571, f_q) - // ) - // mstore( - // 0x16c0, - // mulmod(mload(0xf60), 13553911191894110065493137367144919847521088405945523452288398666974237857208, f_q) - // ) - // mstore( - // 0x16e0, - // addmod(mload(0x7a0), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q) - // ) - // { - // let prod := mload(0xfa0) - - // prod := mulmod(mload(0xfe0), prod, f_q) - // mstore(0x1700, prod) - - // prod := mulmod(mload(0x1020), prod, f_q) - // mstore(0x1720, prod) - - // prod := mulmod(mload(0x1060), prod, f_q) - // mstore(0x1740, prod) - - // prod := mulmod(mload(0x10a0), prod, f_q) - // mstore(0x1760, prod) - - // prod := mulmod(mload(0x10e0), prod, f_q) - // mstore(0x1780, prod) - - // prod := mulmod(mload(0x1120), prod, f_q) - // mstore(0x17a0, prod) - - // prod := mulmod(mload(0x1160), prod, f_q) - // mstore(0x17c0, prod) - - // prod := mulmod(mload(0x11a0), prod, f_q) - // mstore(0x17e0, prod) - - // prod := mulmod(mload(0x11e0), prod, f_q) - // mstore(0x1800, prod) - - // prod := mulmod(mload(0x1220), prod, f_q) - // mstore(0x1820, prod) - - // prod := mulmod(mload(0x1260), prod, f_q) - // mstore(0x1840, prod) - - // prod := mulmod(mload(0x12a0), prod, f_q) - // mstore(0x1860, prod) - - // prod := mulmod(mload(0x12e0), prod, f_q) - // mstore(0x1880, prod) - - // prod := mulmod(mload(0x1320), prod, f_q) - // mstore(0x18a0, prod) - - // prod := mulmod(mload(0x1360), prod, f_q) - // mstore(0x18c0, prod) - - // prod := mulmod(mload(0x13a0), prod, f_q) - // mstore(0x18e0, prod) - - // prod := mulmod(mload(0x13e0), prod, f_q) - // mstore(0x1900, prod) - - // prod := mulmod(mload(0x1420), prod, f_q) - // mstore(0x1920, prod) - - // prod := mulmod(mload(0x1460), prod, f_q) - // mstore(0x1940, prod) - - // prod := mulmod(mload(0x14a0), prod, f_q) - // mstore(0x1960, prod) - - // prod := mulmod(mload(0x14e0), prod, f_q) - // mstore(0x1980, prod) - - // prod := mulmod(mload(0x1520), prod, f_q) - // mstore(0x19a0, prod) - - // prod := mulmod(mload(0x1560), prod, f_q) - // mstore(0x19c0, prod) - - // prod := mulmod(mload(0x15a0), prod, f_q) - // mstore(0x19e0, prod) - - // prod := mulmod(mload(0x15e0), prod, f_q) - // mstore(0x1a00, prod) - - // prod := mulmod(mload(0x1620), prod, f_q) - // mstore(0x1a20, prod) + assembly ("memory-safe") { + // Enforce that Solidity memory layout is respected + let data := mload(0x40) + if iszero(eq(data, 0x80)) { revert(0, 0) } + + let success := true + let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + let f_q := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 + function validate_ec_point(x, y) -> valid { + { + let x_lt_p := lt(x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let y_lt_p := lt(y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + valid := and(x_lt_p, y_lt_p) + } + { + let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_cube := + mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_cube_plus_3 := + addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let is_affine := eq(x_cube_plus_3, y_square) + valid := and(valid, is_affine) + } + } + mstore(0xa0, mod(calldataload(0x0), f_q)) + mstore(0xc0, mod(calldataload(0x20), f_q)) + mstore(0xe0, mod(calldataload(0x40), f_q)) + mstore(0x100, mod(calldataload(0x60), f_q)) + mstore(0x120, mod(calldataload(0x80), f_q)) + mstore(0x140, mod(calldataload(0xa0), f_q)) + mstore(0x160, mod(calldataload(0xc0), f_q)) + mstore(0x180, mod(calldataload(0xe0), f_q)) + mstore(0x1a0, mod(calldataload(0x100), f_q)) + mstore(0x1c0, mod(calldataload(0x120), f_q)) + mstore(0x1e0, mod(calldataload(0x140), f_q)) + mstore(0x200, mod(calldataload(0x160), f_q)) + mstore(0x220, mod(calldataload(0x180), f_q)) + mstore(0x240, mod(calldataload(0x1a0), f_q)) + mstore(0x260, mod(calldataload(0x1c0), f_q)) + mstore(0x280, mod(calldataload(0x1e0), f_q)) + mstore(0x2a0, mod(calldataload(0x200), f_q)) + mstore(0x2c0, mod(calldataload(0x220), f_q)) + mstore(0x2e0, mod(calldataload(0x240), f_q)) + mstore(0x300, mod(calldataload(0x260), f_q)) + mstore(0x320, mod(calldataload(0x280), f_q)) + mstore(0x340, mod(calldataload(0x2a0), f_q)) + mstore(0x360, mod(calldataload(0x2c0), f_q)) + mstore(0x80, 15186165512185359347397944531838604952299016691786397857821503921188369501699) + + { + let x := calldataload(0x2e0) + mstore(0x380, x) + let y := calldataload(0x300) + mstore(0x3a0, y) + success := and(validate_ec_point(x, y), success) + } + mstore(0x3c0, keccak256(0x80, 832)) + { + let hash := mload(0x3c0) + mstore(0x3e0, mod(hash, f_q)) + mstore(0x400, hash) + } + + { + let x := calldataload(0x320) + mstore(0x420, x) + let y := calldataload(0x340) + mstore(0x440, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x360) + mstore(0x460, x) + let y := calldataload(0x380) + mstore(0x480, y) + success := and(validate_ec_point(x, y), success) + } + mstore(0x4a0, keccak256(0x400, 160)) + { + let hash := mload(0x4a0) + mstore(0x4c0, mod(hash, f_q)) + mstore(0x4e0, hash) + } + mstore8(1280, 1) + mstore(0x500, keccak256(0x4e0, 33)) + { + let hash := mload(0x500) + mstore(0x520, mod(hash, f_q)) + mstore(0x540, hash) + } + + { + let x := calldataload(0x3a0) + mstore(0x560, x) + let y := calldataload(0x3c0) + mstore(0x580, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x3e0) + mstore(0x5a0, x) + let y := calldataload(0x400) + mstore(0x5c0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x420) + mstore(0x5e0, x) + let y := calldataload(0x440) + mstore(0x600, y) + success := and(validate_ec_point(x, y), success) + } + mstore(0x620, keccak256(0x540, 224)) + { + let hash := mload(0x620) + mstore(0x640, mod(hash, f_q)) + mstore(0x660, hash) + } + + { + let x := calldataload(0x460) + mstore(0x680, x) + let y := calldataload(0x480) + mstore(0x6a0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x4a0) + mstore(0x6c0, x) + let y := calldataload(0x4c0) + mstore(0x6e0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x4e0) + mstore(0x700, x) + let y := calldataload(0x500) + mstore(0x720, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x520) + mstore(0x740, x) + let y := calldataload(0x540) + mstore(0x760, y) + success := and(validate_ec_point(x, y), success) + } + mstore(0x780, keccak256(0x660, 288)) + { + let hash := mload(0x780) + mstore(0x7a0, mod(hash, f_q)) + mstore(0x7c0, hash) + } + mstore(0x7e0, mod(calldataload(0x560), f_q)) + mstore(0x800, mod(calldataload(0x580), f_q)) + mstore(0x820, mod(calldataload(0x5a0), f_q)) + mstore(0x840, mod(calldataload(0x5c0), f_q)) + mstore(0x860, mod(calldataload(0x5e0), f_q)) + mstore(0x880, mod(calldataload(0x600), f_q)) + mstore(0x8a0, mod(calldataload(0x620), f_q)) + mstore(0x8c0, mod(calldataload(0x640), f_q)) + mstore(0x8e0, mod(calldataload(0x660), f_q)) + mstore(0x900, mod(calldataload(0x680), f_q)) + mstore(0x920, mod(calldataload(0x6a0), f_q)) + mstore(0x940, mod(calldataload(0x6c0), f_q)) + mstore(0x960, mod(calldataload(0x6e0), f_q)) + mstore(0x980, mod(calldataload(0x700), f_q)) + mstore(0x9a0, mod(calldataload(0x720), f_q)) + mstore(0x9c0, mod(calldataload(0x740), f_q)) + mstore(0x9e0, mod(calldataload(0x760), f_q)) + mstore(0xa00, mod(calldataload(0x780), f_q)) + mstore(0xa20, mod(calldataload(0x7a0), f_q)) + mstore(0xa40, keccak256(0x7c0, 640)) + { + let hash := mload(0xa40) + mstore(0xa60, mod(hash, f_q)) + mstore(0xa80, hash) + } + mstore8(2720, 1) + mstore(0xaa0, keccak256(0xa80, 33)) + { + let hash := mload(0xaa0) + mstore(0xac0, mod(hash, f_q)) + mstore(0xae0, hash) + } + + { + let x := calldataload(0x7c0) + mstore(0xb00, x) + let y := calldataload(0x7e0) + mstore(0xb20, y) + success := and(validate_ec_point(x, y), success) + } + mstore(0xb40, keccak256(0xae0, 96)) + { + let hash := mload(0xb40) + mstore(0xb60, mod(hash, f_q)) + mstore(0xb80, hash) + } + + { + let x := calldataload(0x800) + mstore(0xba0, x) + let y := calldataload(0x820) + mstore(0xbc0, y) + success := and(validate_ec_point(x, y), success) + } + { + let x := mload(0xa0) + x := add(x, shl(88, mload(0xc0))) + x := add(x, shl(176, mload(0xe0))) + mstore(3040, x) + let y := mload(0x100) + y := add(y, shl(88, mload(0x120))) + y := add(y, shl(176, mload(0x140))) + mstore(3072, y) + + success := and(validate_ec_point(x, y), success) + } + { + let x := mload(0x160) + x := add(x, shl(88, mload(0x180))) + x := add(x, shl(176, mload(0x1a0))) + mstore(3104, x) + let y := mload(0x1c0) + y := add(y, shl(88, mload(0x1e0))) + y := add(y, shl(176, mload(0x200))) + mstore(3136, y) + + success := and(validate_ec_point(x, y), success) + } + mstore(0xc60, mulmod(mload(0x7a0), mload(0x7a0), f_q)) + mstore(0xc80, mulmod(mload(0xc60), mload(0xc60), f_q)) + mstore(0xca0, mulmod(mload(0xc80), mload(0xc80), f_q)) + mstore(0xcc0, mulmod(mload(0xca0), mload(0xca0), f_q)) + mstore(0xce0, mulmod(mload(0xcc0), mload(0xcc0), f_q)) + mstore(0xd00, mulmod(mload(0xce0), mload(0xce0), f_q)) + mstore(0xd20, mulmod(mload(0xd00), mload(0xd00), f_q)) + mstore(0xd40, mulmod(mload(0xd20), mload(0xd20), f_q)) + mstore(0xd60, mulmod(mload(0xd40), mload(0xd40), f_q)) + mstore(0xd80, mulmod(mload(0xd60), mload(0xd60), f_q)) + mstore(0xda0, mulmod(mload(0xd80), mload(0xd80), f_q)) + mstore(0xdc0, mulmod(mload(0xda0), mload(0xda0), f_q)) + mstore(0xde0, mulmod(mload(0xdc0), mload(0xdc0), f_q)) + mstore(0xe00, mulmod(mload(0xde0), mload(0xde0), f_q)) + mstore(0xe20, mulmod(mload(0xe00), mload(0xe00), f_q)) + mstore(0xe40, mulmod(mload(0xe20), mload(0xe20), f_q)) + mstore(0xe60, mulmod(mload(0xe40), mload(0xe40), f_q)) + mstore(0xe80, mulmod(mload(0xe60), mload(0xe60), f_q)) + mstore(0xea0, mulmod(mload(0xe80), mload(0xe80), f_q)) + mstore(0xec0, mulmod(mload(0xea0), mload(0xea0), f_q)) + mstore(0xee0, mulmod(mload(0xec0), mload(0xec0), f_q)) + mstore(0xf00, mulmod(mload(0xee0), mload(0xee0), f_q)) + mstore(0xf20, mulmod(mload(0xf00), mload(0xf00), f_q)) + mstore( + 0xf40, + addmod(mload(0xf20), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) + ) + mstore( + 0xf60, + mulmod(mload(0xf40), 21888240262557392955334514970720457388010314637169927192662615958087340972065, f_q) + ) + mstore( + 0xf80, + mulmod(mload(0xf60), 4506835738822104338668100540817374747935106310012997856968187171738630203507, f_q) + ) + mstore( + 0xfa0, + addmod(mload(0x7a0), 17381407133017170883578305204439900340613258090403036486730017014837178292110, f_q) + ) + mstore( + 0xfc0, + mulmod(mload(0xf60), 21710372849001950800533397158415938114909991150039389063546734567764856596059, f_q) + ) + mstore( + 0xfe0, + addmod(mload(0x7a0), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q) + ) + mstore( + 0x1000, + mulmod(mload(0xf60), 1887003188133998471169152042388914354640772748308168868301418279904560637395, f_q) + ) + mstore( + 0x1020, + addmod(mload(0x7a0), 20001239683705276751077253702868360733907591652107865475396785906671247858222, f_q) + ) + mstore( + 0x1040, + mulmod(mload(0xf60), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q) + ) + mstore( + 0x1060, + addmod(mload(0x7a0), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q) + ) + mstore( + 0x1080, + mulmod(mload(0xf60), 14655294445420895451632927078981340937842238432098198055057679026789553137428, f_q) + ) + mstore( + 0x10a0, + addmod(mload(0x7a0), 7232948426418379770613478666275934150706125968317836288640525159786255358189, f_q) + ) + mstore( + 0x10c0, + mulmod(mload(0xf60), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) + ) + mstore( + 0x10e0, + addmod(mload(0x7a0), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q) + ) + mstore( + 0x1100, + mulmod(mload(0xf60), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + ) + mstore( + 0x1120, + addmod(mload(0x7a0), 12146688980418810893951125255607130521645347193942732958664170801695864621270, f_q) + ) + mstore(0x1140, mulmod(mload(0xf60), 1, f_q)) + mstore( + 0x1160, + addmod(mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) + ) + mstore( + 0x1180, + mulmod(mload(0xf60), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + ) + mstore( + 0x11a0, + addmod(mload(0x7a0), 13513867906530865119835332133273263211836799082674232843258448413103731898270, f_q) + ) + mstore( + 0x11c0, + mulmod(mload(0xf60), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) + ) + mstore( + 0x11e0, + addmod(mload(0x7a0), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q) + ) + mstore( + 0x1200, + mulmod(mload(0xf60), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + ) + mstore( + 0x1220, + addmod(mload(0x7a0), 18272764063556419981698118473909131571661591947471949595929891197711371770216, f_q) + ) + mstore( + 0x1240, + mulmod(mload(0xf60), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) + ) + mstore( + 0x1260, + addmod(mload(0x7a0), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q) + ) + mstore( + 0x1280, + mulmod(mload(0xf60), 216092043779272773661818549620449970334216366264741118684015851799902419467, f_q) + ) + mstore( + 0x12a0, + addmod(mload(0x7a0), 21672150828060002448584587195636825118214148034151293225014188334775906076150, f_q) + ) + mstore( + 0x12c0, + mulmod(mload(0xf60), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q) + ) + mstore( + 0x12e0, + addmod(mload(0x7a0), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q) + ) + mstore( + 0x1300, + mulmod(mload(0xf60), 18610195890048912503953886742825279624920778288956610528523679659246523534888, f_q) + ) + mstore( + 0x1320, + addmod(mload(0x7a0), 3278046981790362718292519002431995463627586111459423815174524527329284960729, f_q) + ) + mstore( + 0x1340, + mulmod(mload(0xf60), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q) + ) + mstore( + 0x1360, + addmod(mload(0x7a0), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q) + ) + mstore( + 0x1380, + mulmod(mload(0xf60), 14875928112196239563830800280253496262679717528621719058794366823499719730250, f_q) + ) + mstore( + 0x13a0, + addmod(mload(0x7a0), 7012314759643035658415605465003778825868646871794315284903837363076088765367, f_q) + ) + mstore( + 0x13c0, + mulmod(mload(0xf60), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q) + ) + mstore( + 0x13e0, + addmod(mload(0x7a0), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q) + ) + mstore( + 0x1400, + mulmod(mload(0xf60), 5522161504810533295870699551020523636289972223872138525048055197429246400245, f_q) + ) + mstore( + 0x1420, + addmod(mload(0x7a0), 16366081367028741926375706194236751452258392176543895818650148989146562095372, f_q) + ) + mstore( + 0x1440, + mulmod(mload(0xf60), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q) + ) + mstore( + 0x1460, + addmod(mload(0x7a0), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q) + ) + mstore( + 0x1480, + mulmod(mload(0xf60), 9100833993744738801214480881117348002768153232283708533639316963648253510584, f_q) + ) + mstore( + 0x14a0, + addmod(mload(0x7a0), 12787408878094536421031924864139927085780211168132325810058887222927554985033, f_q) + ) + mstore( + 0x14c0, + mulmod(mload(0xf60), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q) + ) + mstore( + 0x14e0, + addmod(mload(0x7a0), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q) + ) + mstore( + 0x1500, + mulmod(mload(0xf60), 6132660129994545119218258312491950835441607143741804980633129304664017206141, f_q) + ) + mstore( + 0x1520, + addmod(mload(0x7a0), 15755582741844730103028147432765324253106757256674229363065074881911791289476, f_q) + ) + mstore( + 0x1540, + mulmod(mload(0xf60), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q) + ) + mstore( + 0x1560, + addmod(mload(0x7a0), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q) + ) + mstore( + 0x1580, + mulmod(mload(0xf60), 515148244606945972463850631189471072103916690263705052318085725998468254533, f_q) + ) + mstore( + 0x15a0, + addmod(mload(0x7a0), 21373094627232329249782555114067804016444447710152329291380118460577340241084, f_q) + ) + mstore( + 0x15c0, + mulmod(mload(0xf60), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q) + ) + mstore( + 0x15e0, + addmod(mload(0x7a0), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q) + ) + mstore( + 0x1600, + mulmod(mload(0xf60), 5223738580615264174925218065001555728265216895679471490312087802465486318994, f_q) + ) + mstore( + 0x1620, + addmod(mload(0x7a0), 16664504291224011047321187680255719360283147504736562853386116384110322176623, f_q) + ) + mstore( + 0x1640, + mulmod(mload(0xf60), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q) + ) + mstore( + 0x1660, + addmod(mload(0x7a0), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q) + ) + mstore( + 0x1680, + mulmod(mload(0xf60), 16976236069879939850923145256911338076234942200101755618884183331004076579046, f_q) + ) + mstore( + 0x16a0, + addmod(mload(0x7a0), 4912006801959335371323260488345937012313422200314278724814020855571731916571, f_q) + ) + mstore( + 0x16c0, + mulmod(mload(0xf60), 13553911191894110065493137367144919847521088405945523452288398666974237857208, f_q) + ) + mstore( + 0x16e0, + addmod(mload(0x7a0), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q) + ) + { + let prod := mload(0xfa0) + + prod := mulmod(mload(0xfe0), prod, f_q) + mstore(0x1700, prod) + + prod := mulmod(mload(0x1020), prod, f_q) + mstore(0x1720, prod) + + prod := mulmod(mload(0x1060), prod, f_q) + mstore(0x1740, prod) + + prod := mulmod(mload(0x10a0), prod, f_q) + mstore(0x1760, prod) + + prod := mulmod(mload(0x10e0), prod, f_q) + mstore(0x1780, prod) + + prod := mulmod(mload(0x1120), prod, f_q) + mstore(0x17a0, prod) + + prod := mulmod(mload(0x1160), prod, f_q) + mstore(0x17c0, prod) + + prod := mulmod(mload(0x11a0), prod, f_q) + mstore(0x17e0, prod) + + prod := mulmod(mload(0x11e0), prod, f_q) + mstore(0x1800, prod) + + prod := mulmod(mload(0x1220), prod, f_q) + mstore(0x1820, prod) + + prod := mulmod(mload(0x1260), prod, f_q) + mstore(0x1840, prod) + + prod := mulmod(mload(0x12a0), prod, f_q) + mstore(0x1860, prod) + + prod := mulmod(mload(0x12e0), prod, f_q) + mstore(0x1880, prod) + + prod := mulmod(mload(0x1320), prod, f_q) + mstore(0x18a0, prod) + + prod := mulmod(mload(0x1360), prod, f_q) + mstore(0x18c0, prod) + + prod := mulmod(mload(0x13a0), prod, f_q) + mstore(0x18e0, prod) + + prod := mulmod(mload(0x13e0), prod, f_q) + mstore(0x1900, prod) + + prod := mulmod(mload(0x1420), prod, f_q) + mstore(0x1920, prod) + + prod := mulmod(mload(0x1460), prod, f_q) + mstore(0x1940, prod) + + prod := mulmod(mload(0x14a0), prod, f_q) + mstore(0x1960, prod) + + prod := mulmod(mload(0x14e0), prod, f_q) + mstore(0x1980, prod) + + prod := mulmod(mload(0x1520), prod, f_q) + mstore(0x19a0, prod) + + prod := mulmod(mload(0x1560), prod, f_q) + mstore(0x19c0, prod) + + prod := mulmod(mload(0x15a0), prod, f_q) + mstore(0x19e0, prod) + + prod := mulmod(mload(0x15e0), prod, f_q) + mstore(0x1a00, prod) + + prod := mulmod(mload(0x1620), prod, f_q) + mstore(0x1a20, prod) - // prod := mulmod(mload(0x1660), prod, f_q) - // mstore(0x1a40, prod) + prod := mulmod(mload(0x1660), prod, f_q) + mstore(0x1a40, prod) - // prod := mulmod(mload(0x16a0), prod, f_q) - // mstore(0x1a60, prod) + prod := mulmod(mload(0x16a0), prod, f_q) + mstore(0x1a60, prod) - // prod := mulmod(mload(0x16e0), prod, f_q) - // mstore(0x1a80, prod) + prod := mulmod(mload(0x16e0), prod, f_q) + mstore(0x1a80, prod) - // prod := mulmod(mload(0xf40), prod, f_q) - // mstore(0x1aa0, prod) - // } - // mstore(0x1ae0, 32) - // mstore(0x1b00, 32) - // mstore(0x1b20, 32) - // mstore(0x1b40, mload(0x1aa0)) - // mstore(0x1b60, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - // mstore(0x1b80, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - // success := and(eq(staticcall(gas(), 0x5, 0x1ae0, 0xc0, 0x1ac0, 0x20), 1), success) - // { - // let inv := mload(0x1ac0) - // let v + prod := mulmod(mload(0xf40), prod, f_q) + mstore(0x1aa0, prod) + } + mstore(0x1ae0, 32) + mstore(0x1b00, 32) + mstore(0x1b20, 32) + mstore(0x1b40, mload(0x1aa0)) + mstore(0x1b60, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + mstore(0x1b80, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + success := and(eq(staticcall(gas(), 0x5, 0x1ae0, 0xc0, 0x1ac0, 0x20), 1), success) + { + let inv := mload(0x1ac0) + let v - // v := mload(0xf40) - // mstore(3904, mulmod(mload(0x1a80), inv, f_q)) - // inv := mulmod(v, inv, f_q) + v := mload(0xf40) + mstore(3904, mulmod(mload(0x1a80), inv, f_q)) + inv := mulmod(v, inv, f_q) - // v := mload(0x16e0) - // mstore(5856, mulmod(mload(0x1a60), inv, f_q)) - // inv := mulmod(v, inv, f_q) + v := mload(0x16e0) + mstore(5856, mulmod(mload(0x1a60), inv, f_q)) + inv := mulmod(v, inv, f_q) - // v := mload(0x16a0) - // mstore(5792, mulmod(mload(0x1a40), inv, f_q)) - // inv := mulmod(v, inv, f_q) + v := mload(0x16a0) + mstore(5792, mulmod(mload(0x1a40), inv, f_q)) + inv := mulmod(v, inv, f_q) - // v := mload(0x1660) - // mstore(5728, mulmod(mload(0x1a20), inv, f_q)) - // inv := mulmod(v, inv, f_q) + v := mload(0x1660) + mstore(5728, mulmod(mload(0x1a20), inv, f_q)) + inv := mulmod(v, inv, f_q) - // v := mload(0x1620) - // mstore(5664, mulmod(mload(0x1a00), inv, f_q)) - // inv := mulmod(v, inv, f_q) + v := mload(0x1620) + mstore(5664, mulmod(mload(0x1a00), inv, f_q)) + inv := mulmod(v, inv, f_q) - // v := mload(0x15e0) - // mstore(5600, mulmod(mload(0x19e0), inv, f_q)) - // inv := mulmod(v, inv, f_q) + v := mload(0x15e0) + mstore(5600, mulmod(mload(0x19e0), inv, f_q)) + inv := mulmod(v, inv, f_q) - // v := mload(0x15a0) - // mstore(5536, mulmod(mload(0x19c0), inv, f_q)) - // inv := mulmod(v, inv, f_q) + v := mload(0x15a0) + mstore(5536, mulmod(mload(0x19c0), inv, f_q)) + inv := mulmod(v, inv, f_q) - // v := mload(0x1560) - // mstore(5472, mulmod(mload(0x19a0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1520) - // mstore(5408, mulmod(mload(0x1980), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x14e0) - // mstore(5344, mulmod(mload(0x1960), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x14a0) - // mstore(5280, mulmod(mload(0x1940), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1460) - // mstore(5216, mulmod(mload(0x1920), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1420) - // mstore(5152, mulmod(mload(0x1900), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x13e0) - // mstore(5088, mulmod(mload(0x18e0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x13a0) - // mstore(5024, mulmod(mload(0x18c0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1360) - // mstore(4960, mulmod(mload(0x18a0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1320) - // mstore(4896, mulmod(mload(0x1880), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x12e0) - // mstore(4832, mulmod(mload(0x1860), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x12a0) - // mstore(4768, mulmod(mload(0x1840), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1260) - // mstore(4704, mulmod(mload(0x1820), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1220) - // mstore(4640, mulmod(mload(0x1800), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x11e0) - // mstore(4576, mulmod(mload(0x17e0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x11a0) - // mstore(4512, mulmod(mload(0x17c0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1160) - // mstore(4448, mulmod(mload(0x17a0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1120) - // mstore(4384, mulmod(mload(0x1780), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x10e0) - // mstore(4320, mulmod(mload(0x1760), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x10a0) - // mstore(4256, mulmod(mload(0x1740), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1060) - // mstore(4192, mulmod(mload(0x1720), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x1020) - // mstore(4128, mulmod(mload(0x1700), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0xfe0) - // mstore(4064, mulmod(mload(0xfa0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - // mstore(0xfa0, inv) - // } - // mstore(0x1ba0, mulmod(mload(0xf80), mload(0xfa0), f_q)) - // mstore(0x1bc0, mulmod(mload(0xfc0), mload(0xfe0), f_q)) - // mstore(0x1be0, mulmod(mload(0x1000), mload(0x1020), f_q)) - // mstore(0x1c00, mulmod(mload(0x1040), mload(0x1060), f_q)) - // mstore(0x1c20, mulmod(mload(0x1080), mload(0x10a0), f_q)) - // mstore(0x1c40, mulmod(mload(0x10c0), mload(0x10e0), f_q)) - // mstore(0x1c60, mulmod(mload(0x1100), mload(0x1120), f_q)) - // mstore(0x1c80, mulmod(mload(0x1140), mload(0x1160), f_q)) - // mstore(0x1ca0, mulmod(mload(0x1180), mload(0x11a0), f_q)) - // mstore(0x1cc0, mulmod(mload(0x11c0), mload(0x11e0), f_q)) - // mstore(0x1ce0, mulmod(mload(0x1200), mload(0x1220), f_q)) - // mstore(0x1d00, mulmod(mload(0x1240), mload(0x1260), f_q)) - // mstore(0x1d20, mulmod(mload(0x1280), mload(0x12a0), f_q)) - // mstore(0x1d40, mulmod(mload(0x12c0), mload(0x12e0), f_q)) - // mstore(0x1d60, mulmod(mload(0x1300), mload(0x1320), f_q)) - // mstore(0x1d80, mulmod(mload(0x1340), mload(0x1360), f_q)) - // mstore(0x1da0, mulmod(mload(0x1380), mload(0x13a0), f_q)) - // mstore(0x1dc0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) - // mstore(0x1de0, mulmod(mload(0x1400), mload(0x1420), f_q)) - // mstore(0x1e00, mulmod(mload(0x1440), mload(0x1460), f_q)) - // mstore(0x1e20, mulmod(mload(0x1480), mload(0x14a0), f_q)) - // mstore(0x1e40, mulmod(mload(0x14c0), mload(0x14e0), f_q)) - // mstore(0x1e60, mulmod(mload(0x1500), mload(0x1520), f_q)) - // mstore(0x1e80, mulmod(mload(0x1540), mload(0x1560), f_q)) - // mstore(0x1ea0, mulmod(mload(0x1580), mload(0x15a0), f_q)) - // mstore(0x1ec0, mulmod(mload(0x15c0), mload(0x15e0), f_q)) - // mstore(0x1ee0, mulmod(mload(0x1600), mload(0x1620), f_q)) - // mstore(0x1f00, mulmod(mload(0x1640), mload(0x1660), f_q)) - // mstore(0x1f20, mulmod(mload(0x1680), mload(0x16a0), f_q)) - // mstore(0x1f40, mulmod(mload(0x16c0), mload(0x16e0), f_q)) - // { - // let result := mulmod(mload(0x1c80), mload(0xa0), f_q) - // result := addmod(mulmod(mload(0x1ca0), mload(0xc0), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1cc0), mload(0xe0), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1ce0), mload(0x100), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1d00), mload(0x120), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1d20), mload(0x140), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1d40), mload(0x160), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1d60), mload(0x180), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1d80), mload(0x1a0), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1da0), mload(0x1c0), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1dc0), mload(0x1e0), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1de0), mload(0x200), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1e00), mload(0x220), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1e20), mload(0x240), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1e40), mload(0x260), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1e60), mload(0x280), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1e80), mload(0x2a0), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1ea0), mload(0x2c0), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1ec0), mload(0x2e0), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1ee0), mload(0x300), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1f00), mload(0x320), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1f20), mload(0x340), f_q), result, f_q) - // result := addmod(mulmod(mload(0x1f40), mload(0x360), f_q), result, f_q) - // mstore(8032, result) - // } - // mstore(0x1f80, mulmod(mload(0x820), mload(0x800), f_q)) - // mstore(0x1fa0, addmod(mload(0x7e0), mload(0x1f80), f_q)) - // mstore(0x1fc0, addmod(mload(0x1fa0), sub(f_q, mload(0x840)), f_q)) - // mstore(0x1fe0, mulmod(mload(0x1fc0), mload(0x8a0), f_q)) - // mstore(0x2000, mulmod(mload(0x640), mload(0x1fe0), f_q)) - // mstore(0x2020, addmod(1, sub(f_q, mload(0x960)), f_q)) - // mstore(0x2040, mulmod(mload(0x2020), mload(0x1c80), f_q)) - // mstore(0x2060, addmod(mload(0x2000), mload(0x2040), f_q)) - // mstore(0x2080, mulmod(mload(0x640), mload(0x2060), f_q)) - // mstore(0x20a0, mulmod(mload(0x960), mload(0x960), f_q)) - // mstore(0x20c0, addmod(mload(0x20a0), sub(f_q, mload(0x960)), f_q)) - // mstore(0x20e0, mulmod(mload(0x20c0), mload(0x1ba0), f_q)) - // mstore(0x2100, addmod(mload(0x2080), mload(0x20e0), f_q)) - // mstore(0x2120, mulmod(mload(0x640), mload(0x2100), f_q)) - // mstore(0x2140, addmod(1, sub(f_q, mload(0x1ba0)), f_q)) - // mstore(0x2160, addmod(mload(0x1bc0), mload(0x1be0), f_q)) - // mstore(0x2180, addmod(mload(0x2160), mload(0x1c00), f_q)) - // mstore(0x21a0, addmod(mload(0x2180), mload(0x1c20), f_q)) - // mstore(0x21c0, addmod(mload(0x21a0), mload(0x1c40), f_q)) - // mstore(0x21e0, addmod(mload(0x21c0), mload(0x1c60), f_q)) - // mstore(0x2200, addmod(mload(0x2140), sub(f_q, mload(0x21e0)), f_q)) - // mstore(0x2220, mulmod(mload(0x900), mload(0x4c0), f_q)) - // mstore(0x2240, addmod(mload(0x860), mload(0x2220), f_q)) - // mstore(0x2260, addmod(mload(0x2240), mload(0x520), f_q)) - // mstore(0x2280, mulmod(mload(0x920), mload(0x4c0), f_q)) - // mstore(0x22a0, addmod(mload(0x7e0), mload(0x2280), f_q)) - // mstore(0x22c0, addmod(mload(0x22a0), mload(0x520), f_q)) - // mstore(0x22e0, mulmod(mload(0x22c0), mload(0x2260), f_q)) - // mstore(0x2300, mulmod(mload(0x940), mload(0x4c0), f_q)) - // mstore(0x2320, addmod(mload(0x1f60), mload(0x2300), f_q)) - // mstore(0x2340, addmod(mload(0x2320), mload(0x520), f_q)) - // mstore(0x2360, mulmod(mload(0x2340), mload(0x22e0), f_q)) - // mstore(0x2380, mulmod(mload(0x2360), mload(0x980), f_q)) - // mstore(0x23a0, mulmod(1, mload(0x4c0), f_q)) - // mstore(0x23c0, mulmod(mload(0x7a0), mload(0x23a0), f_q)) - // mstore(0x23e0, addmod(mload(0x860), mload(0x23c0), f_q)) - // mstore(0x2400, addmod(mload(0x23e0), mload(0x520), f_q)) - // mstore( - // 0x2420, - // mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x4c0), f_q) - // ) - // mstore(0x2440, mulmod(mload(0x7a0), mload(0x2420), f_q)) - // mstore(0x2460, addmod(mload(0x7e0), mload(0x2440), f_q)) - // mstore(0x2480, addmod(mload(0x2460), mload(0x520), f_q)) - // mstore(0x24a0, mulmod(mload(0x2480), mload(0x2400), f_q)) - // mstore( - // 0x24c0, - // mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x4c0), f_q) - // ) - // mstore(0x24e0, mulmod(mload(0x7a0), mload(0x24c0), f_q)) - // mstore(0x2500, addmod(mload(0x1f60), mload(0x24e0), f_q)) - // mstore(0x2520, addmod(mload(0x2500), mload(0x520), f_q)) - // mstore(0x2540, mulmod(mload(0x2520), mload(0x24a0), f_q)) - // mstore(0x2560, mulmod(mload(0x2540), mload(0x960), f_q)) - // mstore(0x2580, addmod(mload(0x2380), sub(f_q, mload(0x2560)), f_q)) - // mstore(0x25a0, mulmod(mload(0x2580), mload(0x2200), f_q)) - // mstore(0x25c0, addmod(mload(0x2120), mload(0x25a0), f_q)) - // mstore(0x25e0, mulmod(mload(0x640), mload(0x25c0), f_q)) - // mstore(0x2600, addmod(1, sub(f_q, mload(0x9a0)), f_q)) - // mstore(0x2620, mulmod(mload(0x2600), mload(0x1c80), f_q)) - // mstore(0x2640, addmod(mload(0x25e0), mload(0x2620), f_q)) - // mstore(0x2660, mulmod(mload(0x640), mload(0x2640), f_q)) - // mstore(0x2680, mulmod(mload(0x9a0), mload(0x9a0), f_q)) - // mstore(0x26a0, addmod(mload(0x2680), sub(f_q, mload(0x9a0)), f_q)) - // mstore(0x26c0, mulmod(mload(0x26a0), mload(0x1ba0), f_q)) - // mstore(0x26e0, addmod(mload(0x2660), mload(0x26c0), f_q)) - // mstore(0x2700, mulmod(mload(0x640), mload(0x26e0), f_q)) - // mstore(0x2720, addmod(mload(0x9e0), mload(0x4c0), f_q)) - // mstore(0x2740, mulmod(mload(0x2720), mload(0x9c0), f_q)) - // mstore(0x2760, addmod(mload(0xa20), mload(0x520), f_q)) - // mstore(0x2780, mulmod(mload(0x2760), mload(0x2740), f_q)) - // mstore(0x27a0, mulmod(mload(0x7e0), mload(0x8c0), f_q)) - // mstore(0x27c0, addmod(mload(0x27a0), mload(0x4c0), f_q)) - // mstore(0x27e0, mulmod(mload(0x27c0), mload(0x9a0), f_q)) - // mstore(0x2800, addmod(mload(0x880), mload(0x520), f_q)) - // mstore(0x2820, mulmod(mload(0x2800), mload(0x27e0), f_q)) - // mstore(0x2840, addmod(mload(0x2780), sub(f_q, mload(0x2820)), f_q)) - // mstore(0x2860, mulmod(mload(0x2840), mload(0x2200), f_q)) - // mstore(0x2880, addmod(mload(0x2700), mload(0x2860), f_q)) - // mstore(0x28a0, mulmod(mload(0x640), mload(0x2880), f_q)) - // mstore(0x28c0, addmod(mload(0x9e0), sub(f_q, mload(0xa20)), f_q)) - // mstore(0x28e0, mulmod(mload(0x28c0), mload(0x1c80), f_q)) - // mstore(0x2900, addmod(mload(0x28a0), mload(0x28e0), f_q)) - // mstore(0x2920, mulmod(mload(0x640), mload(0x2900), f_q)) - // mstore(0x2940, mulmod(mload(0x28c0), mload(0x2200), f_q)) - // mstore(0x2960, addmod(mload(0x9e0), sub(f_q, mload(0xa00)), f_q)) - // mstore(0x2980, mulmod(mload(0x2960), mload(0x2940), f_q)) - // mstore(0x29a0, addmod(mload(0x2920), mload(0x2980), f_q)) - // mstore(0x29c0, mulmod(mload(0xf20), mload(0xf20), f_q)) - // mstore(0x29e0, mulmod(mload(0x29c0), mload(0xf20), f_q)) - // mstore(0x2a00, mulmod(mload(0x29e0), mload(0xf20), f_q)) - // mstore(0x2a20, mulmod(1, mload(0xf20), f_q)) - // mstore(0x2a40, mulmod(1, mload(0x29c0), f_q)) - // mstore(0x2a60, mulmod(1, mload(0x29e0), f_q)) - // mstore(0x2a80, mulmod(mload(0x29a0), mload(0xf40), f_q)) - // mstore(0x2aa0, mulmod(mload(0xc60), mload(0x7a0), f_q)) - // mstore(0x2ac0, mulmod(mload(0x2aa0), mload(0x7a0), f_q)) - // mstore( - // 0x2ae0, - // mulmod(mload(0x7a0), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) - // ) - // mstore(0x2b00, addmod(mload(0xb60), sub(f_q, mload(0x2ae0)), f_q)) - // mstore(0x2b20, mulmod(mload(0x7a0), 1, f_q)) - // mstore(0x2b40, addmod(mload(0xb60), sub(f_q, mload(0x2b20)), f_q)) - // mstore( - // 0x2b60, - // mulmod(mload(0x7a0), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) - // ) - // mstore(0x2b80, addmod(mload(0xb60), sub(f_q, mload(0x2b60)), f_q)) - // mstore( - // 0x2ba0, - // mulmod(mload(0x7a0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) - // ) - // mstore(0x2bc0, addmod(mload(0xb60), sub(f_q, mload(0x2ba0)), f_q)) - // mstore( - // 0x2be0, - // mulmod(mload(0x7a0), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) - // ) - // mstore(0x2c00, addmod(mload(0xb60), sub(f_q, mload(0x2be0)), f_q)) - // mstore( - // 0x2c20, - // mulmod( - // 13213688729882003894512633350385593288217014177373218494356903340348818451480, mload(0x2aa0), f_q - // ) - // ) - // mstore(0x2c40, mulmod(mload(0x2c20), 1, f_q)) - // { - // let result := mulmod(mload(0xb60), mload(0x2c20), f_q) - // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2c40)), f_q), result, f_q) - // mstore(11360, result) - // } - // mstore( - // 0x2c80, - // mulmod(8207090019724696496350398458716998472718344609680392612601596849934418295470, mload(0x2aa0), f_q) - // ) - // mstore( - // 0x2ca0, - // mulmod(mload(0x2c80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) - // ) - // { - // let result := mulmod(mload(0xb60), mload(0x2c80), f_q) - // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ca0)), f_q), result, f_q) - // mstore(11456, result) - // } - // mstore( - // 0x2ce0, - // mulmod(7391709068497399131897422873231908718558236401035363928063603272120120747483, mload(0x2aa0), f_q) - // ) - // mstore( - // 0x2d00, - // mulmod( - // mload(0x2ce0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q - // ) - // ) - // { - // let result := mulmod(mload(0xb60), mload(0x2ce0), f_q) - // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d00)), f_q), result, f_q) - // mstore(11552, result) - // } - // mstore( - // 0x2d40, - // mulmod( - // 19036273796805830823244991598792794567595348772040298280440552631112242221017, mload(0x2aa0), f_q - // ) - // ) - // mstore( - // 0x2d60, - // mulmod(mload(0x2d40), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) - // ) - // { - // let result := mulmod(mload(0xb60), mload(0x2d40), f_q) - // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d60)), f_q), result, f_q) - // mstore(11648, result) - // } - // mstore(0x2da0, mulmod(1, mload(0x2b40), f_q)) - // mstore(0x2dc0, mulmod(mload(0x2da0), mload(0x2b80), f_q)) - // mstore(0x2de0, mulmod(mload(0x2dc0), mload(0x2bc0), f_q)) - // mstore(0x2e00, mulmod(mload(0x2de0), mload(0x2c00), f_q)) - // mstore( - // 0x2e20, - // mulmod(13513867906530865119835332133273263211836799082674232843258448413103731898271, mload(0x7a0), f_q) - // ) - // mstore(0x2e40, mulmod(mload(0x2e20), 1, f_q)) - // { - // let result := mulmod(mload(0xb60), mload(0x2e20), f_q) - // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2e40)), f_q), result, f_q) - // mstore(11872, result) - // } - // mstore( - // 0x2e80, - // mulmod(8374374965308410102411073611984011876711565317741801500439755773472076597346, mload(0x7a0), f_q) - // ) - // mstore( - // 0x2ea0, - // mulmod(mload(0x2e80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) - // ) - // { - // let result := mulmod(mload(0xb60), mload(0x2e80), f_q) - // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ea0)), f_q), result, f_q) - // mstore(11968, result) - // } - // mstore( - // 0x2ee0, - // mulmod(12146688980418810893951125255607130521645347193942732958664170801695864621271, mload(0x7a0), f_q) - // ) - // mstore(0x2f00, mulmod(mload(0x2ee0), 1, f_q)) - // { - // let result := mulmod(mload(0xb60), mload(0x2ee0), f_q) - // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f00)), f_q), result, f_q) - // mstore(12064, result) - // } - // mstore( - // 0x2f40, - // mulmod(9741553891420464328295280489650144566903017206473301385034033384879943874346, mload(0x7a0), f_q) - // ) - // mstore( - // 0x2f60, - // mulmod(mload(0x2f40), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) - // ) - // { - // let result := mulmod(mload(0xb60), mload(0x2f40), f_q) - // result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f60)), f_q), result, f_q) - // mstore(12160, result) - // } - // mstore(0x2fa0, mulmod(mload(0x2da0), mload(0x2b00), f_q)) - // { - // let result := mulmod(mload(0xb60), 1, f_q) - // result := - // addmod( - // mulmod( - // mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q - // ), - // result, - // f_q - // ) - // mstore(12224, result) - // } - // { - // let prod := mload(0x2c60) - - // prod := mulmod(mload(0x2cc0), prod, f_q) - // mstore(0x2fe0, prod) - - // prod := mulmod(mload(0x2d20), prod, f_q) - // mstore(0x3000, prod) - - // prod := mulmod(mload(0x2d80), prod, f_q) - // mstore(0x3020, prod) - - // prod := mulmod(mload(0x2e60), prod, f_q) - // mstore(0x3040, prod) - - // prod := mulmod(mload(0x2ec0), prod, f_q) - // mstore(0x3060, prod) - - // prod := mulmod(mload(0x2dc0), prod, f_q) - // mstore(0x3080, prod) - - // prod := mulmod(mload(0x2f20), prod, f_q) - // mstore(0x30a0, prod) - - // prod := mulmod(mload(0x2f80), prod, f_q) - // mstore(0x30c0, prod) - - // prod := mulmod(mload(0x2fa0), prod, f_q) - // mstore(0x30e0, prod) - - // prod := mulmod(mload(0x2fc0), prod, f_q) - // mstore(0x3100, prod) - - // prod := mulmod(mload(0x2da0), prod, f_q) - // mstore(0x3120, prod) - // } - // mstore(0x3160, 32) - // mstore(0x3180, 32) - // mstore(0x31a0, 32) - // mstore(0x31c0, mload(0x3120)) - // mstore(0x31e0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - // mstore(0x3200, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - // success := and(eq(staticcall(gas(), 0x5, 0x3160, 0xc0, 0x3140, 0x20), 1), success) - // { - // let inv := mload(0x3140) - // let v - - // v := mload(0x2da0) - // mstore(11680, mulmod(mload(0x3100), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x2fc0) - // mstore(12224, mulmod(mload(0x30e0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x2fa0) - // mstore(12192, mulmod(mload(0x30c0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x2f80) - // mstore(12160, mulmod(mload(0x30a0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x2f20) - // mstore(12064, mulmod(mload(0x3080), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x2dc0) - // mstore(11712, mulmod(mload(0x3060), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x2ec0) - // mstore(11968, mulmod(mload(0x3040), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x2e60) - // mstore(11872, mulmod(mload(0x3020), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x2d80) - // mstore(11648, mulmod(mload(0x3000), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x2d20) - // mstore(11552, mulmod(mload(0x2fe0), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x2cc0) - // mstore(11456, mulmod(mload(0x2c60), inv, f_q)) - // inv := mulmod(v, inv, f_q) - // mstore(0x2c60, inv) - // } - // { - // let result := mload(0x2c60) - // result := addmod(mload(0x2cc0), result, f_q) - // result := addmod(mload(0x2d20), result, f_q) - // result := addmod(mload(0x2d80), result, f_q) - // mstore(12832, result) - // } - // mstore(0x3240, mulmod(mload(0x2e00), mload(0x2dc0), f_q)) - // { - // let result := mload(0x2e60) - // result := addmod(mload(0x2ec0), result, f_q) - // mstore(12896, result) - // } - // mstore(0x3280, mulmod(mload(0x2e00), mload(0x2fa0), f_q)) - // { - // let result := mload(0x2f20) - // result := addmod(mload(0x2f80), result, f_q) - // mstore(12960, result) - // } - // mstore(0x32c0, mulmod(mload(0x2e00), mload(0x2da0), f_q)) - // { - // let result := mload(0x2fc0) - // mstore(13024, result) - // } - // { - // let prod := mload(0x3220) - - // prod := mulmod(mload(0x3260), prod, f_q) - // mstore(0x3300, prod) - - // prod := mulmod(mload(0x32a0), prod, f_q) - // mstore(0x3320, prod) - - // prod := mulmod(mload(0x32e0), prod, f_q) - // mstore(0x3340, prod) - // } - // mstore(0x3380, 32) - // mstore(0x33a0, 32) - // mstore(0x33c0, 32) - // mstore(0x33e0, mload(0x3340)) - // mstore(0x3400, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - // mstore(0x3420, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - // success := and(eq(staticcall(gas(), 0x5, 0x3380, 0xc0, 0x3360, 0x20), 1), success) - // { - // let inv := mload(0x3360) - // let v - - // v := mload(0x32e0) - // mstore(13024, mulmod(mload(0x3320), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x32a0) - // mstore(12960, mulmod(mload(0x3300), inv, f_q)) - // inv := mulmod(v, inv, f_q) - - // v := mload(0x3260) - // mstore(12896, mulmod(mload(0x3220), inv, f_q)) - // inv := mulmod(v, inv, f_q) - // mstore(0x3220, inv) - // } - // mstore(0x3440, mulmod(mload(0x3240), mload(0x3260), f_q)) - // mstore(0x3460, mulmod(mload(0x3280), mload(0x32a0), f_q)) - // mstore(0x3480, mulmod(mload(0x32c0), mload(0x32e0), f_q)) - // mstore(0x34a0, mulmod(mload(0xa60), mload(0xa60), f_q)) - // mstore(0x34c0, mulmod(mload(0x34a0), mload(0xa60), f_q)) - // mstore(0x34e0, mulmod(mload(0x34c0), mload(0xa60), f_q)) - // mstore(0x3500, mulmod(mload(0x34e0), mload(0xa60), f_q)) - // mstore(0x3520, mulmod(mload(0x3500), mload(0xa60), f_q)) - // mstore(0x3540, mulmod(mload(0x3520), mload(0xa60), f_q)) - // mstore(0x3560, mulmod(mload(0x3540), mload(0xa60), f_q)) - // mstore(0x3580, mulmod(mload(0x3560), mload(0xa60), f_q)) - // mstore(0x35a0, mulmod(mload(0x3580), mload(0xa60), f_q)) - // mstore(0x35c0, mulmod(mload(0xac0), mload(0xac0), f_q)) - // mstore(0x35e0, mulmod(mload(0x35c0), mload(0xac0), f_q)) - // mstore(0x3600, mulmod(mload(0x35e0), mload(0xac0), f_q)) - // { - // let result := mulmod(mload(0x7e0), mload(0x2c60), f_q) - // result := addmod(mulmod(mload(0x800), mload(0x2cc0), f_q), result, f_q) - // result := addmod(mulmod(mload(0x820), mload(0x2d20), f_q), result, f_q) - // result := addmod(mulmod(mload(0x840), mload(0x2d80), f_q), result, f_q) - // mstore(13856, result) - // } - // mstore(0x3640, mulmod(mload(0x3620), mload(0x3220), f_q)) - // mstore(0x3660, mulmod(sub(f_q, mload(0x3640)), 1, f_q)) - // mstore(0x3680, mulmod(mload(0x3660), 1, f_q)) - // mstore(0x36a0, mulmod(1, mload(0x3240), f_q)) - // { - // let result := mulmod(mload(0x960), mload(0x2e60), f_q) - // result := addmod(mulmod(mload(0x980), mload(0x2ec0), f_q), result, f_q) - // mstore(14016, result) - // } - // mstore(0x36e0, mulmod(mload(0x36c0), mload(0x3440), f_q)) - // mstore(0x3700, mulmod(sub(f_q, mload(0x36e0)), 1, f_q)) - // mstore(0x3720, mulmod(mload(0x36a0), 1, f_q)) - // { - // let result := mulmod(mload(0x9a0), mload(0x2e60), f_q) - // result := addmod(mulmod(mload(0x9c0), mload(0x2ec0), f_q), result, f_q) - // mstore(14144, result) - // } - // mstore(0x3760, mulmod(mload(0x3740), mload(0x3440), f_q)) - // mstore(0x3780, mulmod(sub(f_q, mload(0x3760)), mload(0xa60), f_q)) - // mstore(0x37a0, mulmod(mload(0x36a0), mload(0xa60), f_q)) - // mstore(0x37c0, addmod(mload(0x3700), mload(0x3780), f_q)) - // mstore(0x37e0, mulmod(mload(0x37c0), mload(0xac0), f_q)) - // mstore(0x3800, mulmod(mload(0x3720), mload(0xac0), f_q)) - // mstore(0x3820, mulmod(mload(0x37a0), mload(0xac0), f_q)) - // mstore(0x3840, addmod(mload(0x3680), mload(0x37e0), f_q)) - // mstore(0x3860, mulmod(1, mload(0x3280), f_q)) - // { - // let result := mulmod(mload(0x9e0), mload(0x2f20), f_q) - // result := addmod(mulmod(mload(0xa00), mload(0x2f80), f_q), result, f_q) - // mstore(14464, result) - // } - // mstore(0x38a0, mulmod(mload(0x3880), mload(0x3460), f_q)) - // mstore(0x38c0, mulmod(sub(f_q, mload(0x38a0)), 1, f_q)) - // mstore(0x38e0, mulmod(mload(0x3860), 1, f_q)) - // mstore(0x3900, mulmod(mload(0x38c0), mload(0x35c0), f_q)) - // mstore(0x3920, mulmod(mload(0x38e0), mload(0x35c0), f_q)) - // mstore(0x3940, addmod(mload(0x3840), mload(0x3900), f_q)) - // mstore(0x3960, mulmod(1, mload(0x32c0), f_q)) - // { - // let result := mulmod(mload(0xa20), mload(0x2fc0), f_q) - // mstore(14720, result) - // } - // mstore(0x39a0, mulmod(mload(0x3980), mload(0x3480), f_q)) - // mstore(0x39c0, mulmod(sub(f_q, mload(0x39a0)), 1, f_q)) - // mstore(0x39e0, mulmod(mload(0x3960), 1, f_q)) - // { - // let result := mulmod(mload(0x860), mload(0x2fc0), f_q) - // mstore(14848, result) - // } - // mstore(0x3a20, mulmod(mload(0x3a00), mload(0x3480), f_q)) - // mstore(0x3a40, mulmod(sub(f_q, mload(0x3a20)), mload(0xa60), f_q)) - // mstore(0x3a60, mulmod(mload(0x3960), mload(0xa60), f_q)) - // mstore(0x3a80, addmod(mload(0x39c0), mload(0x3a40), f_q)) - // { - // let result := mulmod(mload(0x880), mload(0x2fc0), f_q) - // mstore(15008, result) - // } - // mstore(0x3ac0, mulmod(mload(0x3aa0), mload(0x3480), f_q)) - // mstore(0x3ae0, mulmod(sub(f_q, mload(0x3ac0)), mload(0x34a0), f_q)) - // mstore(0x3b00, mulmod(mload(0x3960), mload(0x34a0), f_q)) - // mstore(0x3b20, addmod(mload(0x3a80), mload(0x3ae0), f_q)) - // { - // let result := mulmod(mload(0x8a0), mload(0x2fc0), f_q) - // mstore(15168, result) - // } - // mstore(0x3b60, mulmod(mload(0x3b40), mload(0x3480), f_q)) - // mstore(0x3b80, mulmod(sub(f_q, mload(0x3b60)), mload(0x34c0), f_q)) - // mstore(0x3ba0, mulmod(mload(0x3960), mload(0x34c0), f_q)) - // mstore(0x3bc0, addmod(mload(0x3b20), mload(0x3b80), f_q)) - // { - // let result := mulmod(mload(0x8c0), mload(0x2fc0), f_q) - // mstore(15328, result) - // } - // mstore(0x3c00, mulmod(mload(0x3be0), mload(0x3480), f_q)) - // mstore(0x3c20, mulmod(sub(f_q, mload(0x3c00)), mload(0x34e0), f_q)) - // mstore(0x3c40, mulmod(mload(0x3960), mload(0x34e0), f_q)) - // mstore(0x3c60, addmod(mload(0x3bc0), mload(0x3c20), f_q)) - // { - // let result := mulmod(mload(0x900), mload(0x2fc0), f_q) - // mstore(15488, result) - // } - // mstore(0x3ca0, mulmod(mload(0x3c80), mload(0x3480), f_q)) - // mstore(0x3cc0, mulmod(sub(f_q, mload(0x3ca0)), mload(0x3500), f_q)) - // mstore(0x3ce0, mulmod(mload(0x3960), mload(0x3500), f_q)) - // mstore(0x3d00, addmod(mload(0x3c60), mload(0x3cc0), f_q)) - // { - // let result := mulmod(mload(0x920), mload(0x2fc0), f_q) - // mstore(15648, result) - // } - // mstore(0x3d40, mulmod(mload(0x3d20), mload(0x3480), f_q)) - // mstore(0x3d60, mulmod(sub(f_q, mload(0x3d40)), mload(0x3520), f_q)) - // mstore(0x3d80, mulmod(mload(0x3960), mload(0x3520), f_q)) - // mstore(0x3da0, addmod(mload(0x3d00), mload(0x3d60), f_q)) - // { - // let result := mulmod(mload(0x940), mload(0x2fc0), f_q) - // mstore(15808, result) - // } - // mstore(0x3de0, mulmod(mload(0x3dc0), mload(0x3480), f_q)) - // mstore(0x3e00, mulmod(sub(f_q, mload(0x3de0)), mload(0x3540), f_q)) - // mstore(0x3e20, mulmod(mload(0x3960), mload(0x3540), f_q)) - // mstore(0x3e40, addmod(mload(0x3da0), mload(0x3e00), f_q)) - // mstore(0x3e60, mulmod(mload(0x2a20), mload(0x32c0), f_q)) - // mstore(0x3e80, mulmod(mload(0x2a40), mload(0x32c0), f_q)) - // mstore(0x3ea0, mulmod(mload(0x2a60), mload(0x32c0), f_q)) - // { - // let result := mulmod(mload(0x2a80), mload(0x2fc0), f_q) - // mstore(16064, result) - // } - // mstore(0x3ee0, mulmod(mload(0x3ec0), mload(0x3480), f_q)) - // mstore(0x3f00, mulmod(sub(f_q, mload(0x3ee0)), mload(0x3560), f_q)) - // mstore(0x3f20, mulmod(mload(0x3960), mload(0x3560), f_q)) - // mstore(0x3f40, mulmod(mload(0x3e60), mload(0x3560), f_q)) - // mstore(0x3f60, mulmod(mload(0x3e80), mload(0x3560), f_q)) - // mstore(0x3f80, mulmod(mload(0x3ea0), mload(0x3560), f_q)) - // mstore(0x3fa0, addmod(mload(0x3e40), mload(0x3f00), f_q)) - // { - // let result := mulmod(mload(0x8e0), mload(0x2fc0), f_q) - // mstore(16320, result) - // } - // mstore(0x3fe0, mulmod(mload(0x3fc0), mload(0x3480), f_q)) - // mstore(0x4000, mulmod(sub(f_q, mload(0x3fe0)), mload(0x3580), f_q)) - // mstore(0x4020, mulmod(mload(0x3960), mload(0x3580), f_q)) - // mstore(0x4040, addmod(mload(0x3fa0), mload(0x4000), f_q)) - // mstore(0x4060, mulmod(mload(0x4040), mload(0x35e0), f_q)) - // mstore(0x4080, mulmod(mload(0x39e0), mload(0x35e0), f_q)) - // mstore(0x40a0, mulmod(mload(0x3a60), mload(0x35e0), f_q)) - // mstore(0x40c0, mulmod(mload(0x3b00), mload(0x35e0), f_q)) - // mstore(0x40e0, mulmod(mload(0x3ba0), mload(0x35e0), f_q)) - // mstore(0x4100, mulmod(mload(0x3c40), mload(0x35e0), f_q)) - // mstore(0x4120, mulmod(mload(0x3ce0), mload(0x35e0), f_q)) - // mstore(0x4140, mulmod(mload(0x3d80), mload(0x35e0), f_q)) - // mstore(0x4160, mulmod(mload(0x3e20), mload(0x35e0), f_q)) - // mstore(0x4180, mulmod(mload(0x3f20), mload(0x35e0), f_q)) - // mstore(0x41a0, mulmod(mload(0x3f40), mload(0x35e0), f_q)) - // mstore(0x41c0, mulmod(mload(0x3f60), mload(0x35e0), f_q)) - // mstore(0x41e0, mulmod(mload(0x3f80), mload(0x35e0), f_q)) - // mstore(0x4200, mulmod(mload(0x4020), mload(0x35e0), f_q)) - // mstore(0x4220, addmod(mload(0x3940), mload(0x4060), f_q)) - // mstore(0x4240, mulmod(1, mload(0x2e00), f_q)) - // mstore(0x4260, mulmod(1, mload(0xb60), f_q)) - // mstore(0x4280, 0x0000000000000000000000000000000000000000000000000000000000000001) - // mstore(0x42a0, 0x0000000000000000000000000000000000000000000000000000000000000002) - // mstore(0x42c0, mload(0x4220)) - // success := and(eq(staticcall(gas(), 0x7, 0x4280, 0x60, 0x4280, 0x40), 1), success) - // mstore(0x42e0, mload(0x4280)) - // mstore(0x4300, mload(0x42a0)) - // mstore(0x4320, mload(0x380)) - // mstore(0x4340, mload(0x3a0)) - // success := and(eq(staticcall(gas(), 0x6, 0x42e0, 0x80, 0x42e0, 0x40), 1), success) - // mstore(0x4360, mload(0x560)) - // mstore(0x4380, mload(0x580)) - // mstore(0x43a0, mload(0x3800)) - // success := and(eq(staticcall(gas(), 0x7, 0x4360, 0x60, 0x4360, 0x40), 1), success) - // mstore(0x43c0, mload(0x42e0)) - // mstore(0x43e0, mload(0x4300)) - // mstore(0x4400, mload(0x4360)) - // mstore(0x4420, mload(0x4380)) - // success := and(eq(staticcall(gas(), 0x6, 0x43c0, 0x80, 0x43c0, 0x40), 1), success) - // mstore(0x4440, mload(0x5a0)) - // mstore(0x4460, mload(0x5c0)) - // mstore(0x4480, mload(0x3820)) - // success := and(eq(staticcall(gas(), 0x7, 0x4440, 0x60, 0x4440, 0x40), 1), success) - // mstore(0x44a0, mload(0x43c0)) - // mstore(0x44c0, mload(0x43e0)) - // mstore(0x44e0, mload(0x4440)) - // mstore(0x4500, mload(0x4460)) - // success := and(eq(staticcall(gas(), 0x6, 0x44a0, 0x80, 0x44a0, 0x40), 1), success) - // mstore(0x4520, mload(0x420)) - // mstore(0x4540, mload(0x440)) - // mstore(0x4560, mload(0x3920)) - // success := and(eq(staticcall(gas(), 0x7, 0x4520, 0x60, 0x4520, 0x40), 1), success) - // mstore(0x4580, mload(0x44a0)) - // mstore(0x45a0, mload(0x44c0)) - // mstore(0x45c0, mload(0x4520)) - // mstore(0x45e0, mload(0x4540)) - // success := and(eq(staticcall(gas(), 0x6, 0x4580, 0x80, 0x4580, 0x40), 1), success) - // mstore(0x4600, mload(0x460)) - // mstore(0x4620, mload(0x480)) - // mstore(0x4640, mload(0x4080)) - // success := and(eq(staticcall(gas(), 0x7, 0x4600, 0x60, 0x4600, 0x40), 1), success) - // mstore(0x4660, mload(0x4580)) - // mstore(0x4680, mload(0x45a0)) - // mstore(0x46a0, mload(0x4600)) - // mstore(0x46c0, mload(0x4620)) - // success := and(eq(staticcall(gas(), 0x6, 0x4660, 0x80, 0x4660, 0x40), 1), success) - // mstore(0x46e0, 0x21b14b6e8ea36289961bde7f1d8f191389a815740d09f34f13190341383dfb13) - // mstore(0x4700, 0x16740f9c3982e02aeb0cb10086339afaca1bb103d5ae3f114c45a569d60c88ce) - // mstore(0x4720, mload(0x40a0)) - // success := and(eq(staticcall(gas(), 0x7, 0x46e0, 0x60, 0x46e0, 0x40), 1), success) - // mstore(0x4740, mload(0x4660)) - // mstore(0x4760, mload(0x4680)) - // mstore(0x4780, mload(0x46e0)) - // mstore(0x47a0, mload(0x4700)) - // success := and(eq(staticcall(gas(), 0x6, 0x4740, 0x80, 0x4740, 0x40), 1), success) - // mstore(0x47c0, 0x2eb40e2b0c13a6f4b989cffa9dbc452447bfd9f04a79f6379aefea8c9850a550) - // mstore(0x47e0, 0x0efe5496541e2bd648d490f11ad542e1dec3127f818b8065843d0dd81358416c) - // mstore(0x4800, mload(0x40c0)) - // success := and(eq(staticcall(gas(), 0x7, 0x47c0, 0x60, 0x47c0, 0x40), 1), success) - // mstore(0x4820, mload(0x4740)) - // mstore(0x4840, mload(0x4760)) - // mstore(0x4860, mload(0x47c0)) - // mstore(0x4880, mload(0x47e0)) - // success := and(eq(staticcall(gas(), 0x6, 0x4820, 0x80, 0x4820, 0x40), 1), success) - // mstore(0x48a0, 0x1c6707c73bce576eb360ffcb2fa9a0b17ad541ea0a0e8001439bca524f2f5a43) - // mstore(0x48c0, 0x03b899b999df6cf57b7755535b1dc5014a9dbd21d55c31d826d8338dc2fe8722) - // mstore(0x48e0, mload(0x40e0)) - // success := and(eq(staticcall(gas(), 0x7, 0x48a0, 0x60, 0x48a0, 0x40), 1), success) - // mstore(0x4900, mload(0x4820)) - // mstore(0x4920, mload(0x4840)) - // mstore(0x4940, mload(0x48a0)) - // mstore(0x4960, mload(0x48c0)) - // success := and(eq(staticcall(gas(), 0x6, 0x4900, 0x80, 0x4900, 0x40), 1), success) - // mstore(0x4980, 0x1d309220cdb6694a08a8c77f89984557e19bbda422f41d50b47bf30b30b3dec3) - // mstore(0x49a0, 0x138c263b3cbc7de6f5f92f88c44a3e7fc278a4b69008db2340097131e43dbb1a) - // mstore(0x49c0, mload(0x4100)) - // success := and(eq(staticcall(gas(), 0x7, 0x4980, 0x60, 0x4980, 0x40), 1), success) - // mstore(0x49e0, mload(0x4900)) - // mstore(0x4a00, mload(0x4920)) - // mstore(0x4a20, mload(0x4980)) - // mstore(0x4a40, mload(0x49a0)) - // success := and(eq(staticcall(gas(), 0x6, 0x49e0, 0x80, 0x49e0, 0x40), 1), success) - // mstore(0x4a60, 0x2529da4dfe20ec7564dc8738f2477daf565052f29117d9a2c1a0cbe846ab95fb) - // mstore(0x4a80, 0x2a3971e5a786b7e8b0039d1100621af00a8743921a36ef7aafc430b09a5bd279) - // mstore(0x4aa0, mload(0x4120)) - // success := and(eq(staticcall(gas(), 0x7, 0x4a60, 0x60, 0x4a60, 0x40), 1), success) - // mstore(0x4ac0, mload(0x49e0)) - // mstore(0x4ae0, mload(0x4a00)) - // mstore(0x4b00, mload(0x4a60)) - // mstore(0x4b20, mload(0x4a80)) - // success := and(eq(staticcall(gas(), 0x6, 0x4ac0, 0x80, 0x4ac0, 0x40), 1), success) - // mstore(0x4b40, 0x132e1a4125c783ea4817ea96d967c5f06a49933ca71f7e99f7be022ef1e3ca35) - // mstore(0x4b60, 0x0eb726ae10479119d87b2e1d0d2b72db88506d263ae939b2154b0f3f5c7012f7) - // mstore(0x4b80, mload(0x4140)) - // success := and(eq(staticcall(gas(), 0x7, 0x4b40, 0x60, 0x4b40, 0x40), 1), success) - // mstore(0x4ba0, mload(0x4ac0)) - // mstore(0x4bc0, mload(0x4ae0)) - // mstore(0x4be0, mload(0x4b40)) - // mstore(0x4c00, mload(0x4b60)) - // success := and(eq(staticcall(gas(), 0x6, 0x4ba0, 0x80, 0x4ba0, 0x40), 1), success) - // mstore(0x4c20, 0x1bc70a16efa4ef34c9ee86dc04d041fc8430240113b09ef71d5bbb8b685af6b7) - // mstore(0x4c40, 0x25064309a3b7ab3efd593b9e6c2f1294b50c12e237412186d7af94b1591dc937) - // mstore(0x4c60, mload(0x4160)) - // success := and(eq(staticcall(gas(), 0x7, 0x4c20, 0x60, 0x4c20, 0x40), 1), success) - // mstore(0x4c80, mload(0x4ba0)) - // mstore(0x4ca0, mload(0x4bc0)) - // mstore(0x4cc0, mload(0x4c20)) - // mstore(0x4ce0, mload(0x4c40)) - // success := and(eq(staticcall(gas(), 0x6, 0x4c80, 0x80, 0x4c80, 0x40), 1), success) - // mstore(0x4d00, mload(0x680)) - // mstore(0x4d20, mload(0x6a0)) - // mstore(0x4d40, mload(0x4180)) - // success := and(eq(staticcall(gas(), 0x7, 0x4d00, 0x60, 0x4d00, 0x40), 1), success) - // mstore(0x4d60, mload(0x4c80)) - // mstore(0x4d80, mload(0x4ca0)) - // mstore(0x4da0, mload(0x4d00)) - // mstore(0x4dc0, mload(0x4d20)) - // success := and(eq(staticcall(gas(), 0x6, 0x4d60, 0x80, 0x4d60, 0x40), 1), success) - // mstore(0x4de0, mload(0x6c0)) - // mstore(0x4e00, mload(0x6e0)) - // mstore(0x4e20, mload(0x41a0)) - // success := and(eq(staticcall(gas(), 0x7, 0x4de0, 0x60, 0x4de0, 0x40), 1), success) - // mstore(0x4e40, mload(0x4d60)) - // mstore(0x4e60, mload(0x4d80)) - // mstore(0x4e80, mload(0x4de0)) - // mstore(0x4ea0, mload(0x4e00)) - // success := and(eq(staticcall(gas(), 0x6, 0x4e40, 0x80, 0x4e40, 0x40), 1), success) - // mstore(0x4ec0, mload(0x700)) - // mstore(0x4ee0, mload(0x720)) - // mstore(0x4f00, mload(0x41c0)) - // success := and(eq(staticcall(gas(), 0x7, 0x4ec0, 0x60, 0x4ec0, 0x40), 1), success) - // mstore(0x4f20, mload(0x4e40)) - // mstore(0x4f40, mload(0x4e60)) - // mstore(0x4f60, mload(0x4ec0)) - // mstore(0x4f80, mload(0x4ee0)) - // success := and(eq(staticcall(gas(), 0x6, 0x4f20, 0x80, 0x4f20, 0x40), 1), success) - // mstore(0x4fa0, mload(0x740)) - // mstore(0x4fc0, mload(0x760)) - // mstore(0x4fe0, mload(0x41e0)) - // success := and(eq(staticcall(gas(), 0x7, 0x4fa0, 0x60, 0x4fa0, 0x40), 1), success) - // mstore(0x5000, mload(0x4f20)) - // mstore(0x5020, mload(0x4f40)) - // mstore(0x5040, mload(0x4fa0)) - // mstore(0x5060, mload(0x4fc0)) - // success := and(eq(staticcall(gas(), 0x6, 0x5000, 0x80, 0x5000, 0x40), 1), success) - // mstore(0x5080, mload(0x5e0)) - // mstore(0x50a0, mload(0x600)) - // mstore(0x50c0, mload(0x4200)) - // success := and(eq(staticcall(gas(), 0x7, 0x5080, 0x60, 0x5080, 0x40), 1), success) - // mstore(0x50e0, mload(0x5000)) - // mstore(0x5100, mload(0x5020)) - // mstore(0x5120, mload(0x5080)) - // mstore(0x5140, mload(0x50a0)) - // success := and(eq(staticcall(gas(), 0x6, 0x50e0, 0x80, 0x50e0, 0x40), 1), success) - // mstore(0x5160, mload(0xb00)) - // mstore(0x5180, mload(0xb20)) - // mstore(0x51a0, sub(f_q, mload(0x4240))) - // success := and(eq(staticcall(gas(), 0x7, 0x5160, 0x60, 0x5160, 0x40), 1), success) - // mstore(0x51c0, mload(0x50e0)) - // mstore(0x51e0, mload(0x5100)) - // mstore(0x5200, mload(0x5160)) - // mstore(0x5220, mload(0x5180)) - // success := and(eq(staticcall(gas(), 0x6, 0x51c0, 0x80, 0x51c0, 0x40), 1), success) - // mstore(0x5240, mload(0xba0)) - // mstore(0x5260, mload(0xbc0)) - // mstore(0x5280, mload(0x4260)) - // success := and(eq(staticcall(gas(), 0x7, 0x5240, 0x60, 0x5240, 0x40), 1), success) - // mstore(0x52a0, mload(0x51c0)) - // mstore(0x52c0, mload(0x51e0)) - // mstore(0x52e0, mload(0x5240)) - // mstore(0x5300, mload(0x5260)) - // success := and(eq(staticcall(gas(), 0x6, 0x52a0, 0x80, 0x52a0, 0x40), 1), success) - // mstore(0x5320, mload(0x52a0)) - // mstore(0x5340, mload(0x52c0)) - // mstore(0x5360, mload(0xba0)) - // mstore(0x5380, mload(0xbc0)) - // mstore(0x53a0, mload(0xbe0)) - // mstore(0x53c0, mload(0xc00)) - // mstore(0x53e0, mload(0xc20)) - // mstore(0x5400, mload(0xc40)) - // mstore(0x5420, keccak256(0x5320, 256)) - // mstore(21568, mod(mload(21536), f_q)) - // mstore(0x5460, mulmod(mload(0x5440), mload(0x5440), f_q)) - // mstore(0x5480, mulmod(1, mload(0x5440), f_q)) - // mstore(0x54a0, mload(0x53a0)) - // mstore(0x54c0, mload(0x53c0)) - // mstore(0x54e0, mload(0x5480)) - // success := and(eq(staticcall(gas(), 0x7, 0x54a0, 0x60, 0x54a0, 0x40), 1), success) - // mstore(0x5500, mload(0x5320)) - // mstore(0x5520, mload(0x5340)) - // mstore(0x5540, mload(0x54a0)) - // mstore(0x5560, mload(0x54c0)) - // success := and(eq(staticcall(gas(), 0x6, 0x5500, 0x80, 0x5500, 0x40), 1), success) - // mstore(0x5580, mload(0x53e0)) - // mstore(0x55a0, mload(0x5400)) - // mstore(0x55c0, mload(0x5480)) - // success := and(eq(staticcall(gas(), 0x7, 0x5580, 0x60, 0x5580, 0x40), 1), success) - // mstore(0x55e0, mload(0x5360)) - // mstore(0x5600, mload(0x5380)) - // mstore(0x5620, mload(0x5580)) - // mstore(0x5640, mload(0x55a0)) - // success := and(eq(staticcall(gas(), 0x6, 0x55e0, 0x80, 0x55e0, 0x40), 1), success) - // mstore(0x5660, mload(0x5500)) - // mstore(0x5680, mload(0x5520)) - // mstore(0x56a0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) - // mstore(0x56c0, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - // mstore(0x56e0, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - // mstore(0x5700, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - // mstore(0x5720, mload(0x55e0)) - // mstore(0x5740, mload(0x5600)) - // mstore(0x5760, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) - // mstore(0x5780, 0x2ae0c8c3a090f7200ff398ee9845bbae8f8c1445ae7b632212775f60a0e21600) - // mstore(0x57a0, 0x190fa476a5b352809ed41d7a0d7fe12b8f685e3c12a6d83855dba27aaf469643) - // mstore(0x57c0, 0x1c0a500618907df9e4273d5181e31088deb1f05132de037cbfe73888f97f77c9) - // success := and(eq(staticcall(gas(), 0x8, 0x5660, 0x180, 0x5660, 0x20), 1), success) - // success := and(eq(mload(0x5660), 1), success) - - // // Revert if anything fails - // if iszero(success) { revert(0, 0) } - - // // Return empty bytes on success - // return(0, 0) - // } + v := mload(0x1560) + mstore(5472, mulmod(mload(0x19a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1520) + mstore(5408, mulmod(mload(0x1980), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x14e0) + mstore(5344, mulmod(mload(0x1960), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x14a0) + mstore(5280, mulmod(mload(0x1940), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1460) + mstore(5216, mulmod(mload(0x1920), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1420) + mstore(5152, mulmod(mload(0x1900), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13e0) + mstore(5088, mulmod(mload(0x18e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13a0) + mstore(5024, mulmod(mload(0x18c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1360) + mstore(4960, mulmod(mload(0x18a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1320) + mstore(4896, mulmod(mload(0x1880), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12e0) + mstore(4832, mulmod(mload(0x1860), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12a0) + mstore(4768, mulmod(mload(0x1840), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1260) + mstore(4704, mulmod(mload(0x1820), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1220) + mstore(4640, mulmod(mload(0x1800), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x11e0) + mstore(4576, mulmod(mload(0x17e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x11a0) + mstore(4512, mulmod(mload(0x17c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1160) + mstore(4448, mulmod(mload(0x17a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1120) + mstore(4384, mulmod(mload(0x1780), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x10e0) + mstore(4320, mulmod(mload(0x1760), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x10a0) + mstore(4256, mulmod(mload(0x1740), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1060) + mstore(4192, mulmod(mload(0x1720), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1020) + mstore(4128, mulmod(mload(0x1700), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0xfe0) + mstore(4064, mulmod(mload(0xfa0), inv, f_q)) + inv := mulmod(v, inv, f_q) + mstore(0xfa0, inv) + } + mstore(0x1ba0, mulmod(mload(0xf80), mload(0xfa0), f_q)) + mstore(0x1bc0, mulmod(mload(0xfc0), mload(0xfe0), f_q)) + mstore(0x1be0, mulmod(mload(0x1000), mload(0x1020), f_q)) + mstore(0x1c00, mulmod(mload(0x1040), mload(0x1060), f_q)) + mstore(0x1c20, mulmod(mload(0x1080), mload(0x10a0), f_q)) + mstore(0x1c40, mulmod(mload(0x10c0), mload(0x10e0), f_q)) + mstore(0x1c60, mulmod(mload(0x1100), mload(0x1120), f_q)) + mstore(0x1c80, mulmod(mload(0x1140), mload(0x1160), f_q)) + mstore(0x1ca0, mulmod(mload(0x1180), mload(0x11a0), f_q)) + mstore(0x1cc0, mulmod(mload(0x11c0), mload(0x11e0), f_q)) + mstore(0x1ce0, mulmod(mload(0x1200), mload(0x1220), f_q)) + mstore(0x1d00, mulmod(mload(0x1240), mload(0x1260), f_q)) + mstore(0x1d20, mulmod(mload(0x1280), mload(0x12a0), f_q)) + mstore(0x1d40, mulmod(mload(0x12c0), mload(0x12e0), f_q)) + mstore(0x1d60, mulmod(mload(0x1300), mload(0x1320), f_q)) + mstore(0x1d80, mulmod(mload(0x1340), mload(0x1360), f_q)) + mstore(0x1da0, mulmod(mload(0x1380), mload(0x13a0), f_q)) + mstore(0x1dc0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) + mstore(0x1de0, mulmod(mload(0x1400), mload(0x1420), f_q)) + mstore(0x1e00, mulmod(mload(0x1440), mload(0x1460), f_q)) + mstore(0x1e20, mulmod(mload(0x1480), mload(0x14a0), f_q)) + mstore(0x1e40, mulmod(mload(0x14c0), mload(0x14e0), f_q)) + mstore(0x1e60, mulmod(mload(0x1500), mload(0x1520), f_q)) + mstore(0x1e80, mulmod(mload(0x1540), mload(0x1560), f_q)) + mstore(0x1ea0, mulmod(mload(0x1580), mload(0x15a0), f_q)) + mstore(0x1ec0, mulmod(mload(0x15c0), mload(0x15e0), f_q)) + mstore(0x1ee0, mulmod(mload(0x1600), mload(0x1620), f_q)) + mstore(0x1f00, mulmod(mload(0x1640), mload(0x1660), f_q)) + mstore(0x1f20, mulmod(mload(0x1680), mload(0x16a0), f_q)) + mstore(0x1f40, mulmod(mload(0x16c0), mload(0x16e0), f_q)) + { + let result := mulmod(mload(0x1c80), mload(0xa0), f_q) + result := addmod(mulmod(mload(0x1ca0), mload(0xc0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1cc0), mload(0xe0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1ce0), mload(0x100), f_q), result, f_q) + result := addmod(mulmod(mload(0x1d00), mload(0x120), f_q), result, f_q) + result := addmod(mulmod(mload(0x1d20), mload(0x140), f_q), result, f_q) + result := addmod(mulmod(mload(0x1d40), mload(0x160), f_q), result, f_q) + result := addmod(mulmod(mload(0x1d60), mload(0x180), f_q), result, f_q) + result := addmod(mulmod(mload(0x1d80), mload(0x1a0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1da0), mload(0x1c0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1dc0), mload(0x1e0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1de0), mload(0x200), f_q), result, f_q) + result := addmod(mulmod(mload(0x1e00), mload(0x220), f_q), result, f_q) + result := addmod(mulmod(mload(0x1e20), mload(0x240), f_q), result, f_q) + result := addmod(mulmod(mload(0x1e40), mload(0x260), f_q), result, f_q) + result := addmod(mulmod(mload(0x1e60), mload(0x280), f_q), result, f_q) + result := addmod(mulmod(mload(0x1e80), mload(0x2a0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1ea0), mload(0x2c0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1ec0), mload(0x2e0), f_q), result, f_q) + result := addmod(mulmod(mload(0x1ee0), mload(0x300), f_q), result, f_q) + result := addmod(mulmod(mload(0x1f00), mload(0x320), f_q), result, f_q) + result := addmod(mulmod(mload(0x1f20), mload(0x340), f_q), result, f_q) + result := addmod(mulmod(mload(0x1f40), mload(0x360), f_q), result, f_q) + mstore(8032, result) + } + mstore(0x1f80, mulmod(mload(0x820), mload(0x800), f_q)) + mstore(0x1fa0, addmod(mload(0x7e0), mload(0x1f80), f_q)) + mstore(0x1fc0, addmod(mload(0x1fa0), sub(f_q, mload(0x840)), f_q)) + mstore(0x1fe0, mulmod(mload(0x1fc0), mload(0x8a0), f_q)) + mstore(0x2000, mulmod(mload(0x640), mload(0x1fe0), f_q)) + mstore(0x2020, addmod(1, sub(f_q, mload(0x960)), f_q)) + mstore(0x2040, mulmod(mload(0x2020), mload(0x1c80), f_q)) + mstore(0x2060, addmod(mload(0x2000), mload(0x2040), f_q)) + mstore(0x2080, mulmod(mload(0x640), mload(0x2060), f_q)) + mstore(0x20a0, mulmod(mload(0x960), mload(0x960), f_q)) + mstore(0x20c0, addmod(mload(0x20a0), sub(f_q, mload(0x960)), f_q)) + mstore(0x20e0, mulmod(mload(0x20c0), mload(0x1ba0), f_q)) + mstore(0x2100, addmod(mload(0x2080), mload(0x20e0), f_q)) + mstore(0x2120, mulmod(mload(0x640), mload(0x2100), f_q)) + mstore(0x2140, addmod(1, sub(f_q, mload(0x1ba0)), f_q)) + mstore(0x2160, addmod(mload(0x1bc0), mload(0x1be0), f_q)) + mstore(0x2180, addmod(mload(0x2160), mload(0x1c00), f_q)) + mstore(0x21a0, addmod(mload(0x2180), mload(0x1c20), f_q)) + mstore(0x21c0, addmod(mload(0x21a0), mload(0x1c40), f_q)) + mstore(0x21e0, addmod(mload(0x21c0), mload(0x1c60), f_q)) + mstore(0x2200, addmod(mload(0x2140), sub(f_q, mload(0x21e0)), f_q)) + mstore(0x2220, mulmod(mload(0x900), mload(0x4c0), f_q)) + mstore(0x2240, addmod(mload(0x860), mload(0x2220), f_q)) + mstore(0x2260, addmod(mload(0x2240), mload(0x520), f_q)) + mstore(0x2280, mulmod(mload(0x920), mload(0x4c0), f_q)) + mstore(0x22a0, addmod(mload(0x7e0), mload(0x2280), f_q)) + mstore(0x22c0, addmod(mload(0x22a0), mload(0x520), f_q)) + mstore(0x22e0, mulmod(mload(0x22c0), mload(0x2260), f_q)) + mstore(0x2300, mulmod(mload(0x940), mload(0x4c0), f_q)) + mstore(0x2320, addmod(mload(0x1f60), mload(0x2300), f_q)) + mstore(0x2340, addmod(mload(0x2320), mload(0x520), f_q)) + mstore(0x2360, mulmod(mload(0x2340), mload(0x22e0), f_q)) + mstore(0x2380, mulmod(mload(0x2360), mload(0x980), f_q)) + mstore(0x23a0, mulmod(1, mload(0x4c0), f_q)) + mstore(0x23c0, mulmod(mload(0x7a0), mload(0x23a0), f_q)) + mstore(0x23e0, addmod(mload(0x860), mload(0x23c0), f_q)) + mstore(0x2400, addmod(mload(0x23e0), mload(0x520), f_q)) + mstore( + 0x2420, + mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x4c0), f_q) + ) + mstore(0x2440, mulmod(mload(0x7a0), mload(0x2420), f_q)) + mstore(0x2460, addmod(mload(0x7e0), mload(0x2440), f_q)) + mstore(0x2480, addmod(mload(0x2460), mload(0x520), f_q)) + mstore(0x24a0, mulmod(mload(0x2480), mload(0x2400), f_q)) + mstore( + 0x24c0, + mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x4c0), f_q) + ) + mstore(0x24e0, mulmod(mload(0x7a0), mload(0x24c0), f_q)) + mstore(0x2500, addmod(mload(0x1f60), mload(0x24e0), f_q)) + mstore(0x2520, addmod(mload(0x2500), mload(0x520), f_q)) + mstore(0x2540, mulmod(mload(0x2520), mload(0x24a0), f_q)) + mstore(0x2560, mulmod(mload(0x2540), mload(0x960), f_q)) + mstore(0x2580, addmod(mload(0x2380), sub(f_q, mload(0x2560)), f_q)) + mstore(0x25a0, mulmod(mload(0x2580), mload(0x2200), f_q)) + mstore(0x25c0, addmod(mload(0x2120), mload(0x25a0), f_q)) + mstore(0x25e0, mulmod(mload(0x640), mload(0x25c0), f_q)) + mstore(0x2600, addmod(1, sub(f_q, mload(0x9a0)), f_q)) + mstore(0x2620, mulmod(mload(0x2600), mload(0x1c80), f_q)) + mstore(0x2640, addmod(mload(0x25e0), mload(0x2620), f_q)) + mstore(0x2660, mulmod(mload(0x640), mload(0x2640), f_q)) + mstore(0x2680, mulmod(mload(0x9a0), mload(0x9a0), f_q)) + mstore(0x26a0, addmod(mload(0x2680), sub(f_q, mload(0x9a0)), f_q)) + mstore(0x26c0, mulmod(mload(0x26a0), mload(0x1ba0), f_q)) + mstore(0x26e0, addmod(mload(0x2660), mload(0x26c0), f_q)) + mstore(0x2700, mulmod(mload(0x640), mload(0x26e0), f_q)) + mstore(0x2720, addmod(mload(0x9e0), mload(0x4c0), f_q)) + mstore(0x2740, mulmod(mload(0x2720), mload(0x9c0), f_q)) + mstore(0x2760, addmod(mload(0xa20), mload(0x520), f_q)) + mstore(0x2780, mulmod(mload(0x2760), mload(0x2740), f_q)) + mstore(0x27a0, mulmod(mload(0x7e0), mload(0x8c0), f_q)) + mstore(0x27c0, addmod(mload(0x27a0), mload(0x4c0), f_q)) + mstore(0x27e0, mulmod(mload(0x27c0), mload(0x9a0), f_q)) + mstore(0x2800, addmod(mload(0x880), mload(0x520), f_q)) + mstore(0x2820, mulmod(mload(0x2800), mload(0x27e0), f_q)) + mstore(0x2840, addmod(mload(0x2780), sub(f_q, mload(0x2820)), f_q)) + mstore(0x2860, mulmod(mload(0x2840), mload(0x2200), f_q)) + mstore(0x2880, addmod(mload(0x2700), mload(0x2860), f_q)) + mstore(0x28a0, mulmod(mload(0x640), mload(0x2880), f_q)) + mstore(0x28c0, addmod(mload(0x9e0), sub(f_q, mload(0xa20)), f_q)) + mstore(0x28e0, mulmod(mload(0x28c0), mload(0x1c80), f_q)) + mstore(0x2900, addmod(mload(0x28a0), mload(0x28e0), f_q)) + mstore(0x2920, mulmod(mload(0x640), mload(0x2900), f_q)) + mstore(0x2940, mulmod(mload(0x28c0), mload(0x2200), f_q)) + mstore(0x2960, addmod(mload(0x9e0), sub(f_q, mload(0xa00)), f_q)) + mstore(0x2980, mulmod(mload(0x2960), mload(0x2940), f_q)) + mstore(0x29a0, addmod(mload(0x2920), mload(0x2980), f_q)) + mstore(0x29c0, mulmod(mload(0xf20), mload(0xf20), f_q)) + mstore(0x29e0, mulmod(mload(0x29c0), mload(0xf20), f_q)) + mstore(0x2a00, mulmod(mload(0x29e0), mload(0xf20), f_q)) + mstore(0x2a20, mulmod(1, mload(0xf20), f_q)) + mstore(0x2a40, mulmod(1, mload(0x29c0), f_q)) + mstore(0x2a60, mulmod(1, mload(0x29e0), f_q)) + mstore(0x2a80, mulmod(mload(0x29a0), mload(0xf40), f_q)) + mstore(0x2aa0, mulmod(mload(0xc60), mload(0x7a0), f_q)) + mstore(0x2ac0, mulmod(mload(0x2aa0), mload(0x7a0), f_q)) + mstore( + 0x2ae0, + mulmod(mload(0x7a0), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + ) + mstore(0x2b00, addmod(mload(0xb60), sub(f_q, mload(0x2ae0)), f_q)) + mstore(0x2b20, mulmod(mload(0x7a0), 1, f_q)) + mstore(0x2b40, addmod(mload(0xb60), sub(f_q, mload(0x2b20)), f_q)) + mstore( + 0x2b60, + mulmod(mload(0x7a0), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + ) + mstore(0x2b80, addmod(mload(0xb60), sub(f_q, mload(0x2b60)), f_q)) + mstore( + 0x2ba0, + mulmod(mload(0x7a0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) + ) + mstore(0x2bc0, addmod(mload(0xb60), sub(f_q, mload(0x2ba0)), f_q)) + mstore( + 0x2be0, + mulmod(mload(0x7a0), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + ) + mstore(0x2c00, addmod(mload(0xb60), sub(f_q, mload(0x2be0)), f_q)) + mstore( + 0x2c20, + mulmod( + 13213688729882003894512633350385593288217014177373218494356903340348818451480, mload(0x2aa0), f_q + ) + ) + mstore(0x2c40, mulmod(mload(0x2c20), 1, f_q)) + { + let result := mulmod(mload(0xb60), mload(0x2c20), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2c40)), f_q), result, f_q) + mstore(11360, result) + } + mstore( + 0x2c80, + mulmod(8207090019724696496350398458716998472718344609680392612601596849934418295470, mload(0x2aa0), f_q) + ) + mstore( + 0x2ca0, + mulmod(mload(0x2c80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + ) + { + let result := mulmod(mload(0xb60), mload(0x2c80), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ca0)), f_q), result, f_q) + mstore(11456, result) + } + mstore( + 0x2ce0, + mulmod(7391709068497399131897422873231908718558236401035363928063603272120120747483, mload(0x2aa0), f_q) + ) + mstore( + 0x2d00, + mulmod( + mload(0x2ce0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q + ) + ) + { + let result := mulmod(mload(0xb60), mload(0x2ce0), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d00)), f_q), result, f_q) + mstore(11552, result) + } + mstore( + 0x2d40, + mulmod( + 19036273796805830823244991598792794567595348772040298280440552631112242221017, mload(0x2aa0), f_q + ) + ) + mstore( + 0x2d60, + mulmod(mload(0x2d40), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + ) + { + let result := mulmod(mload(0xb60), mload(0x2d40), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d60)), f_q), result, f_q) + mstore(11648, result) + } + mstore(0x2da0, mulmod(1, mload(0x2b40), f_q)) + mstore(0x2dc0, mulmod(mload(0x2da0), mload(0x2b80), f_q)) + mstore(0x2de0, mulmod(mload(0x2dc0), mload(0x2bc0), f_q)) + mstore(0x2e00, mulmod(mload(0x2de0), mload(0x2c00), f_q)) + mstore( + 0x2e20, + mulmod(13513867906530865119835332133273263211836799082674232843258448413103731898271, mload(0x7a0), f_q) + ) + mstore(0x2e40, mulmod(mload(0x2e20), 1, f_q)) + { + let result := mulmod(mload(0xb60), mload(0x2e20), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2e40)), f_q), result, f_q) + mstore(11872, result) + } + mstore( + 0x2e80, + mulmod(8374374965308410102411073611984011876711565317741801500439755773472076597346, mload(0x7a0), f_q) + ) + mstore( + 0x2ea0, + mulmod(mload(0x2e80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + ) + { + let result := mulmod(mload(0xb60), mload(0x2e80), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ea0)), f_q), result, f_q) + mstore(11968, result) + } + mstore( + 0x2ee0, + mulmod(12146688980418810893951125255607130521645347193942732958664170801695864621271, mload(0x7a0), f_q) + ) + mstore(0x2f00, mulmod(mload(0x2ee0), 1, f_q)) + { + let result := mulmod(mload(0xb60), mload(0x2ee0), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f00)), f_q), result, f_q) + mstore(12064, result) + } + mstore( + 0x2f40, + mulmod(9741553891420464328295280489650144566903017206473301385034033384879943874346, mload(0x7a0), f_q) + ) + mstore( + 0x2f60, + mulmod(mload(0x2f40), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + ) + { + let result := mulmod(mload(0xb60), mload(0x2f40), f_q) + result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f60)), f_q), result, f_q) + mstore(12160, result) + } + mstore(0x2fa0, mulmod(mload(0x2da0), mload(0x2b00), f_q)) + { + let result := mulmod(mload(0xb60), 1, f_q) + result := + addmod( + mulmod( + mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q + ), + result, + f_q + ) + mstore(12224, result) + } + { + let prod := mload(0x2c60) + + prod := mulmod(mload(0x2cc0), prod, f_q) + mstore(0x2fe0, prod) + + prod := mulmod(mload(0x2d20), prod, f_q) + mstore(0x3000, prod) + + prod := mulmod(mload(0x2d80), prod, f_q) + mstore(0x3020, prod) + + prod := mulmod(mload(0x2e60), prod, f_q) + mstore(0x3040, prod) + + prod := mulmod(mload(0x2ec0), prod, f_q) + mstore(0x3060, prod) + + prod := mulmod(mload(0x2dc0), prod, f_q) + mstore(0x3080, prod) + + prod := mulmod(mload(0x2f20), prod, f_q) + mstore(0x30a0, prod) + + prod := mulmod(mload(0x2f80), prod, f_q) + mstore(0x30c0, prod) + + prod := mulmod(mload(0x2fa0), prod, f_q) + mstore(0x30e0, prod) + + prod := mulmod(mload(0x2fc0), prod, f_q) + mstore(0x3100, prod) + + prod := mulmod(mload(0x2da0), prod, f_q) + mstore(0x3120, prod) + } + mstore(0x3160, 32) + mstore(0x3180, 32) + mstore(0x31a0, 32) + mstore(0x31c0, mload(0x3120)) + mstore(0x31e0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + mstore(0x3200, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + success := and(eq(staticcall(gas(), 0x5, 0x3160, 0xc0, 0x3140, 0x20), 1), success) + { + let inv := mload(0x3140) + let v + + v := mload(0x2da0) + mstore(11680, mulmod(mload(0x3100), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2fc0) + mstore(12224, mulmod(mload(0x30e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2fa0) + mstore(12192, mulmod(mload(0x30c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2f80) + mstore(12160, mulmod(mload(0x30a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2f20) + mstore(12064, mulmod(mload(0x3080), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2dc0) + mstore(11712, mulmod(mload(0x3060), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2ec0) + mstore(11968, mulmod(mload(0x3040), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2e60) + mstore(11872, mulmod(mload(0x3020), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2d80) + mstore(11648, mulmod(mload(0x3000), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2d20) + mstore(11552, mulmod(mload(0x2fe0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2cc0) + mstore(11456, mulmod(mload(0x2c60), inv, f_q)) + inv := mulmod(v, inv, f_q) + mstore(0x2c60, inv) + } + { + let result := mload(0x2c60) + result := addmod(mload(0x2cc0), result, f_q) + result := addmod(mload(0x2d20), result, f_q) + result := addmod(mload(0x2d80), result, f_q) + mstore(12832, result) + } + mstore(0x3240, mulmod(mload(0x2e00), mload(0x2dc0), f_q)) + { + let result := mload(0x2e60) + result := addmod(mload(0x2ec0), result, f_q) + mstore(12896, result) + } + mstore(0x3280, mulmod(mload(0x2e00), mload(0x2fa0), f_q)) + { + let result := mload(0x2f20) + result := addmod(mload(0x2f80), result, f_q) + mstore(12960, result) + } + mstore(0x32c0, mulmod(mload(0x2e00), mload(0x2da0), f_q)) + { + let result := mload(0x2fc0) + mstore(13024, result) + } + { + let prod := mload(0x3220) + + prod := mulmod(mload(0x3260), prod, f_q) + mstore(0x3300, prod) + + prod := mulmod(mload(0x32a0), prod, f_q) + mstore(0x3320, prod) + + prod := mulmod(mload(0x32e0), prod, f_q) + mstore(0x3340, prod) + } + mstore(0x3380, 32) + mstore(0x33a0, 32) + mstore(0x33c0, 32) + mstore(0x33e0, mload(0x3340)) + mstore(0x3400, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + mstore(0x3420, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + success := and(eq(staticcall(gas(), 0x5, 0x3380, 0xc0, 0x3360, 0x20), 1), success) + { + let inv := mload(0x3360) + let v + + v := mload(0x32e0) + mstore(13024, mulmod(mload(0x3320), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x32a0) + mstore(12960, mulmod(mload(0x3300), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3260) + mstore(12896, mulmod(mload(0x3220), inv, f_q)) + inv := mulmod(v, inv, f_q) + mstore(0x3220, inv) + } + mstore(0x3440, mulmod(mload(0x3240), mload(0x3260), f_q)) + mstore(0x3460, mulmod(mload(0x3280), mload(0x32a0), f_q)) + mstore(0x3480, mulmod(mload(0x32c0), mload(0x32e0), f_q)) + mstore(0x34a0, mulmod(mload(0xa60), mload(0xa60), f_q)) + mstore(0x34c0, mulmod(mload(0x34a0), mload(0xa60), f_q)) + mstore(0x34e0, mulmod(mload(0x34c0), mload(0xa60), f_q)) + mstore(0x3500, mulmod(mload(0x34e0), mload(0xa60), f_q)) + mstore(0x3520, mulmod(mload(0x3500), mload(0xa60), f_q)) + mstore(0x3540, mulmod(mload(0x3520), mload(0xa60), f_q)) + mstore(0x3560, mulmod(mload(0x3540), mload(0xa60), f_q)) + mstore(0x3580, mulmod(mload(0x3560), mload(0xa60), f_q)) + mstore(0x35a0, mulmod(mload(0x3580), mload(0xa60), f_q)) + mstore(0x35c0, mulmod(mload(0xac0), mload(0xac0), f_q)) + mstore(0x35e0, mulmod(mload(0x35c0), mload(0xac0), f_q)) + mstore(0x3600, mulmod(mload(0x35e0), mload(0xac0), f_q)) + { + let result := mulmod(mload(0x7e0), mload(0x2c60), f_q) + result := addmod(mulmod(mload(0x800), mload(0x2cc0), f_q), result, f_q) + result := addmod(mulmod(mload(0x820), mload(0x2d20), f_q), result, f_q) + result := addmod(mulmod(mload(0x840), mload(0x2d80), f_q), result, f_q) + mstore(13856, result) + } + mstore(0x3640, mulmod(mload(0x3620), mload(0x3220), f_q)) + mstore(0x3660, mulmod(sub(f_q, mload(0x3640)), 1, f_q)) + mstore(0x3680, mulmod(mload(0x3660), 1, f_q)) + mstore(0x36a0, mulmod(1, mload(0x3240), f_q)) + { + let result := mulmod(mload(0x960), mload(0x2e60), f_q) + result := addmod(mulmod(mload(0x980), mload(0x2ec0), f_q), result, f_q) + mstore(14016, result) + } + mstore(0x36e0, mulmod(mload(0x36c0), mload(0x3440), f_q)) + mstore(0x3700, mulmod(sub(f_q, mload(0x36e0)), 1, f_q)) + mstore(0x3720, mulmod(mload(0x36a0), 1, f_q)) + { + let result := mulmod(mload(0x9a0), mload(0x2e60), f_q) + result := addmod(mulmod(mload(0x9c0), mload(0x2ec0), f_q), result, f_q) + mstore(14144, result) + } + mstore(0x3760, mulmod(mload(0x3740), mload(0x3440), f_q)) + mstore(0x3780, mulmod(sub(f_q, mload(0x3760)), mload(0xa60), f_q)) + mstore(0x37a0, mulmod(mload(0x36a0), mload(0xa60), f_q)) + mstore(0x37c0, addmod(mload(0x3700), mload(0x3780), f_q)) + mstore(0x37e0, mulmod(mload(0x37c0), mload(0xac0), f_q)) + mstore(0x3800, mulmod(mload(0x3720), mload(0xac0), f_q)) + mstore(0x3820, mulmod(mload(0x37a0), mload(0xac0), f_q)) + mstore(0x3840, addmod(mload(0x3680), mload(0x37e0), f_q)) + mstore(0x3860, mulmod(1, mload(0x3280), f_q)) + { + let result := mulmod(mload(0x9e0), mload(0x2f20), f_q) + result := addmod(mulmod(mload(0xa00), mload(0x2f80), f_q), result, f_q) + mstore(14464, result) + } + mstore(0x38a0, mulmod(mload(0x3880), mload(0x3460), f_q)) + mstore(0x38c0, mulmod(sub(f_q, mload(0x38a0)), 1, f_q)) + mstore(0x38e0, mulmod(mload(0x3860), 1, f_q)) + mstore(0x3900, mulmod(mload(0x38c0), mload(0x35c0), f_q)) + mstore(0x3920, mulmod(mload(0x38e0), mload(0x35c0), f_q)) + mstore(0x3940, addmod(mload(0x3840), mload(0x3900), f_q)) + mstore(0x3960, mulmod(1, mload(0x32c0), f_q)) + { + let result := mulmod(mload(0xa20), mload(0x2fc0), f_q) + mstore(14720, result) + } + mstore(0x39a0, mulmod(mload(0x3980), mload(0x3480), f_q)) + mstore(0x39c0, mulmod(sub(f_q, mload(0x39a0)), 1, f_q)) + mstore(0x39e0, mulmod(mload(0x3960), 1, f_q)) + { + let result := mulmod(mload(0x860), mload(0x2fc0), f_q) + mstore(14848, result) + } + mstore(0x3a20, mulmod(mload(0x3a00), mload(0x3480), f_q)) + mstore(0x3a40, mulmod(sub(f_q, mload(0x3a20)), mload(0xa60), f_q)) + mstore(0x3a60, mulmod(mload(0x3960), mload(0xa60), f_q)) + mstore(0x3a80, addmod(mload(0x39c0), mload(0x3a40), f_q)) + { + let result := mulmod(mload(0x880), mload(0x2fc0), f_q) + mstore(15008, result) + } + mstore(0x3ac0, mulmod(mload(0x3aa0), mload(0x3480), f_q)) + mstore(0x3ae0, mulmod(sub(f_q, mload(0x3ac0)), mload(0x34a0), f_q)) + mstore(0x3b00, mulmod(mload(0x3960), mload(0x34a0), f_q)) + mstore(0x3b20, addmod(mload(0x3a80), mload(0x3ae0), f_q)) + { + let result := mulmod(mload(0x8a0), mload(0x2fc0), f_q) + mstore(15168, result) + } + mstore(0x3b60, mulmod(mload(0x3b40), mload(0x3480), f_q)) + mstore(0x3b80, mulmod(sub(f_q, mload(0x3b60)), mload(0x34c0), f_q)) + mstore(0x3ba0, mulmod(mload(0x3960), mload(0x34c0), f_q)) + mstore(0x3bc0, addmod(mload(0x3b20), mload(0x3b80), f_q)) + { + let result := mulmod(mload(0x8c0), mload(0x2fc0), f_q) + mstore(15328, result) + } + mstore(0x3c00, mulmod(mload(0x3be0), mload(0x3480), f_q)) + mstore(0x3c20, mulmod(sub(f_q, mload(0x3c00)), mload(0x34e0), f_q)) + mstore(0x3c40, mulmod(mload(0x3960), mload(0x34e0), f_q)) + mstore(0x3c60, addmod(mload(0x3bc0), mload(0x3c20), f_q)) + { + let result := mulmod(mload(0x900), mload(0x2fc0), f_q) + mstore(15488, result) + } + mstore(0x3ca0, mulmod(mload(0x3c80), mload(0x3480), f_q)) + mstore(0x3cc0, mulmod(sub(f_q, mload(0x3ca0)), mload(0x3500), f_q)) + mstore(0x3ce0, mulmod(mload(0x3960), mload(0x3500), f_q)) + mstore(0x3d00, addmod(mload(0x3c60), mload(0x3cc0), f_q)) + { + let result := mulmod(mload(0x920), mload(0x2fc0), f_q) + mstore(15648, result) + } + mstore(0x3d40, mulmod(mload(0x3d20), mload(0x3480), f_q)) + mstore(0x3d60, mulmod(sub(f_q, mload(0x3d40)), mload(0x3520), f_q)) + mstore(0x3d80, mulmod(mload(0x3960), mload(0x3520), f_q)) + mstore(0x3da0, addmod(mload(0x3d00), mload(0x3d60), f_q)) + { + let result := mulmod(mload(0x940), mload(0x2fc0), f_q) + mstore(15808, result) + } + mstore(0x3de0, mulmod(mload(0x3dc0), mload(0x3480), f_q)) + mstore(0x3e00, mulmod(sub(f_q, mload(0x3de0)), mload(0x3540), f_q)) + mstore(0x3e20, mulmod(mload(0x3960), mload(0x3540), f_q)) + mstore(0x3e40, addmod(mload(0x3da0), mload(0x3e00), f_q)) + mstore(0x3e60, mulmod(mload(0x2a20), mload(0x32c0), f_q)) + mstore(0x3e80, mulmod(mload(0x2a40), mload(0x32c0), f_q)) + mstore(0x3ea0, mulmod(mload(0x2a60), mload(0x32c0), f_q)) + { + let result := mulmod(mload(0x2a80), mload(0x2fc0), f_q) + mstore(16064, result) + } + mstore(0x3ee0, mulmod(mload(0x3ec0), mload(0x3480), f_q)) + mstore(0x3f00, mulmod(sub(f_q, mload(0x3ee0)), mload(0x3560), f_q)) + mstore(0x3f20, mulmod(mload(0x3960), mload(0x3560), f_q)) + mstore(0x3f40, mulmod(mload(0x3e60), mload(0x3560), f_q)) + mstore(0x3f60, mulmod(mload(0x3e80), mload(0x3560), f_q)) + mstore(0x3f80, mulmod(mload(0x3ea0), mload(0x3560), f_q)) + mstore(0x3fa0, addmod(mload(0x3e40), mload(0x3f00), f_q)) + { + let result := mulmod(mload(0x8e0), mload(0x2fc0), f_q) + mstore(16320, result) + } + mstore(0x3fe0, mulmod(mload(0x3fc0), mload(0x3480), f_q)) + mstore(0x4000, mulmod(sub(f_q, mload(0x3fe0)), mload(0x3580), f_q)) + mstore(0x4020, mulmod(mload(0x3960), mload(0x3580), f_q)) + mstore(0x4040, addmod(mload(0x3fa0), mload(0x4000), f_q)) + mstore(0x4060, mulmod(mload(0x4040), mload(0x35e0), f_q)) + mstore(0x4080, mulmod(mload(0x39e0), mload(0x35e0), f_q)) + mstore(0x40a0, mulmod(mload(0x3a60), mload(0x35e0), f_q)) + mstore(0x40c0, mulmod(mload(0x3b00), mload(0x35e0), f_q)) + mstore(0x40e0, mulmod(mload(0x3ba0), mload(0x35e0), f_q)) + mstore(0x4100, mulmod(mload(0x3c40), mload(0x35e0), f_q)) + mstore(0x4120, mulmod(mload(0x3ce0), mload(0x35e0), f_q)) + mstore(0x4140, mulmod(mload(0x3d80), mload(0x35e0), f_q)) + mstore(0x4160, mulmod(mload(0x3e20), mload(0x35e0), f_q)) + mstore(0x4180, mulmod(mload(0x3f20), mload(0x35e0), f_q)) + mstore(0x41a0, mulmod(mload(0x3f40), mload(0x35e0), f_q)) + mstore(0x41c0, mulmod(mload(0x3f60), mload(0x35e0), f_q)) + mstore(0x41e0, mulmod(mload(0x3f80), mload(0x35e0), f_q)) + mstore(0x4200, mulmod(mload(0x4020), mload(0x35e0), f_q)) + mstore(0x4220, addmod(mload(0x3940), mload(0x4060), f_q)) + mstore(0x4240, mulmod(1, mload(0x2e00), f_q)) + mstore(0x4260, mulmod(1, mload(0xb60), f_q)) + mstore(0x4280, 0x0000000000000000000000000000000000000000000000000000000000000001) + mstore(0x42a0, 0x0000000000000000000000000000000000000000000000000000000000000002) + mstore(0x42c0, mload(0x4220)) + success := and(eq(staticcall(gas(), 0x7, 0x4280, 0x60, 0x4280, 0x40), 1), success) + mstore(0x42e0, mload(0x4280)) + mstore(0x4300, mload(0x42a0)) + mstore(0x4320, mload(0x380)) + mstore(0x4340, mload(0x3a0)) + success := and(eq(staticcall(gas(), 0x6, 0x42e0, 0x80, 0x42e0, 0x40), 1), success) + mstore(0x4360, mload(0x560)) + mstore(0x4380, mload(0x580)) + mstore(0x43a0, mload(0x3800)) + success := and(eq(staticcall(gas(), 0x7, 0x4360, 0x60, 0x4360, 0x40), 1), success) + mstore(0x43c0, mload(0x42e0)) + mstore(0x43e0, mload(0x4300)) + mstore(0x4400, mload(0x4360)) + mstore(0x4420, mload(0x4380)) + success := and(eq(staticcall(gas(), 0x6, 0x43c0, 0x80, 0x43c0, 0x40), 1), success) + mstore(0x4440, mload(0x5a0)) + mstore(0x4460, mload(0x5c0)) + mstore(0x4480, mload(0x3820)) + success := and(eq(staticcall(gas(), 0x7, 0x4440, 0x60, 0x4440, 0x40), 1), success) + mstore(0x44a0, mload(0x43c0)) + mstore(0x44c0, mload(0x43e0)) + mstore(0x44e0, mload(0x4440)) + mstore(0x4500, mload(0x4460)) + success := and(eq(staticcall(gas(), 0x6, 0x44a0, 0x80, 0x44a0, 0x40), 1), success) + mstore(0x4520, mload(0x420)) + mstore(0x4540, mload(0x440)) + mstore(0x4560, mload(0x3920)) + success := and(eq(staticcall(gas(), 0x7, 0x4520, 0x60, 0x4520, 0x40), 1), success) + mstore(0x4580, mload(0x44a0)) + mstore(0x45a0, mload(0x44c0)) + mstore(0x45c0, mload(0x4520)) + mstore(0x45e0, mload(0x4540)) + success := and(eq(staticcall(gas(), 0x6, 0x4580, 0x80, 0x4580, 0x40), 1), success) + mstore(0x4600, mload(0x460)) + mstore(0x4620, mload(0x480)) + mstore(0x4640, mload(0x4080)) + success := and(eq(staticcall(gas(), 0x7, 0x4600, 0x60, 0x4600, 0x40), 1), success) + mstore(0x4660, mload(0x4580)) + mstore(0x4680, mload(0x45a0)) + mstore(0x46a0, mload(0x4600)) + mstore(0x46c0, mload(0x4620)) + success := and(eq(staticcall(gas(), 0x6, 0x4660, 0x80, 0x4660, 0x40), 1), success) + mstore(0x46e0, 0x21b14b6e8ea36289961bde7f1d8f191389a815740d09f34f13190341383dfb13) + mstore(0x4700, 0x16740f9c3982e02aeb0cb10086339afaca1bb103d5ae3f114c45a569d60c88ce) + mstore(0x4720, mload(0x40a0)) + success := and(eq(staticcall(gas(), 0x7, 0x46e0, 0x60, 0x46e0, 0x40), 1), success) + mstore(0x4740, mload(0x4660)) + mstore(0x4760, mload(0x4680)) + mstore(0x4780, mload(0x46e0)) + mstore(0x47a0, mload(0x4700)) + success := and(eq(staticcall(gas(), 0x6, 0x4740, 0x80, 0x4740, 0x40), 1), success) + mstore(0x47c0, 0x2eb40e2b0c13a6f4b989cffa9dbc452447bfd9f04a79f6379aefea8c9850a550) + mstore(0x47e0, 0x0efe5496541e2bd648d490f11ad542e1dec3127f818b8065843d0dd81358416c) + mstore(0x4800, mload(0x40c0)) + success := and(eq(staticcall(gas(), 0x7, 0x47c0, 0x60, 0x47c0, 0x40), 1), success) + mstore(0x4820, mload(0x4740)) + mstore(0x4840, mload(0x4760)) + mstore(0x4860, mload(0x47c0)) + mstore(0x4880, mload(0x47e0)) + success := and(eq(staticcall(gas(), 0x6, 0x4820, 0x80, 0x4820, 0x40), 1), success) + mstore(0x48a0, 0x1c6707c73bce576eb360ffcb2fa9a0b17ad541ea0a0e8001439bca524f2f5a43) + mstore(0x48c0, 0x03b899b999df6cf57b7755535b1dc5014a9dbd21d55c31d826d8338dc2fe8722) + mstore(0x48e0, mload(0x40e0)) + success := and(eq(staticcall(gas(), 0x7, 0x48a0, 0x60, 0x48a0, 0x40), 1), success) + mstore(0x4900, mload(0x4820)) + mstore(0x4920, mload(0x4840)) + mstore(0x4940, mload(0x48a0)) + mstore(0x4960, mload(0x48c0)) + success := and(eq(staticcall(gas(), 0x6, 0x4900, 0x80, 0x4900, 0x40), 1), success) + mstore(0x4980, 0x1d309220cdb6694a08a8c77f89984557e19bbda422f41d50b47bf30b30b3dec3) + mstore(0x49a0, 0x138c263b3cbc7de6f5f92f88c44a3e7fc278a4b69008db2340097131e43dbb1a) + mstore(0x49c0, mload(0x4100)) + success := and(eq(staticcall(gas(), 0x7, 0x4980, 0x60, 0x4980, 0x40), 1), success) + mstore(0x49e0, mload(0x4900)) + mstore(0x4a00, mload(0x4920)) + mstore(0x4a20, mload(0x4980)) + mstore(0x4a40, mload(0x49a0)) + success := and(eq(staticcall(gas(), 0x6, 0x49e0, 0x80, 0x49e0, 0x40), 1), success) + mstore(0x4a60, 0x2529da4dfe20ec7564dc8738f2477daf565052f29117d9a2c1a0cbe846ab95fb) + mstore(0x4a80, 0x2a3971e5a786b7e8b0039d1100621af00a8743921a36ef7aafc430b09a5bd279) + mstore(0x4aa0, mload(0x4120)) + success := and(eq(staticcall(gas(), 0x7, 0x4a60, 0x60, 0x4a60, 0x40), 1), success) + mstore(0x4ac0, mload(0x49e0)) + mstore(0x4ae0, mload(0x4a00)) + mstore(0x4b00, mload(0x4a60)) + mstore(0x4b20, mload(0x4a80)) + success := and(eq(staticcall(gas(), 0x6, 0x4ac0, 0x80, 0x4ac0, 0x40), 1), success) + mstore(0x4b40, 0x132e1a4125c783ea4817ea96d967c5f06a49933ca71f7e99f7be022ef1e3ca35) + mstore(0x4b60, 0x0eb726ae10479119d87b2e1d0d2b72db88506d263ae939b2154b0f3f5c7012f7) + mstore(0x4b80, mload(0x4140)) + success := and(eq(staticcall(gas(), 0x7, 0x4b40, 0x60, 0x4b40, 0x40), 1), success) + mstore(0x4ba0, mload(0x4ac0)) + mstore(0x4bc0, mload(0x4ae0)) + mstore(0x4be0, mload(0x4b40)) + mstore(0x4c00, mload(0x4b60)) + success := and(eq(staticcall(gas(), 0x6, 0x4ba0, 0x80, 0x4ba0, 0x40), 1), success) + mstore(0x4c20, 0x1bc70a16efa4ef34c9ee86dc04d041fc8430240113b09ef71d5bbb8b685af6b7) + mstore(0x4c40, 0x25064309a3b7ab3efd593b9e6c2f1294b50c12e237412186d7af94b1591dc937) + mstore(0x4c60, mload(0x4160)) + success := and(eq(staticcall(gas(), 0x7, 0x4c20, 0x60, 0x4c20, 0x40), 1), success) + mstore(0x4c80, mload(0x4ba0)) + mstore(0x4ca0, mload(0x4bc0)) + mstore(0x4cc0, mload(0x4c20)) + mstore(0x4ce0, mload(0x4c40)) + success := and(eq(staticcall(gas(), 0x6, 0x4c80, 0x80, 0x4c80, 0x40), 1), success) + mstore(0x4d00, mload(0x680)) + mstore(0x4d20, mload(0x6a0)) + mstore(0x4d40, mload(0x4180)) + success := and(eq(staticcall(gas(), 0x7, 0x4d00, 0x60, 0x4d00, 0x40), 1), success) + mstore(0x4d60, mload(0x4c80)) + mstore(0x4d80, mload(0x4ca0)) + mstore(0x4da0, mload(0x4d00)) + mstore(0x4dc0, mload(0x4d20)) + success := and(eq(staticcall(gas(), 0x6, 0x4d60, 0x80, 0x4d60, 0x40), 1), success) + mstore(0x4de0, mload(0x6c0)) + mstore(0x4e00, mload(0x6e0)) + mstore(0x4e20, mload(0x41a0)) + success := and(eq(staticcall(gas(), 0x7, 0x4de0, 0x60, 0x4de0, 0x40), 1), success) + mstore(0x4e40, mload(0x4d60)) + mstore(0x4e60, mload(0x4d80)) + mstore(0x4e80, mload(0x4de0)) + mstore(0x4ea0, mload(0x4e00)) + success := and(eq(staticcall(gas(), 0x6, 0x4e40, 0x80, 0x4e40, 0x40), 1), success) + mstore(0x4ec0, mload(0x700)) + mstore(0x4ee0, mload(0x720)) + mstore(0x4f00, mload(0x41c0)) + success := and(eq(staticcall(gas(), 0x7, 0x4ec0, 0x60, 0x4ec0, 0x40), 1), success) + mstore(0x4f20, mload(0x4e40)) + mstore(0x4f40, mload(0x4e60)) + mstore(0x4f60, mload(0x4ec0)) + mstore(0x4f80, mload(0x4ee0)) + success := and(eq(staticcall(gas(), 0x6, 0x4f20, 0x80, 0x4f20, 0x40), 1), success) + mstore(0x4fa0, mload(0x740)) + mstore(0x4fc0, mload(0x760)) + mstore(0x4fe0, mload(0x41e0)) + success := and(eq(staticcall(gas(), 0x7, 0x4fa0, 0x60, 0x4fa0, 0x40), 1), success) + mstore(0x5000, mload(0x4f20)) + mstore(0x5020, mload(0x4f40)) + mstore(0x5040, mload(0x4fa0)) + mstore(0x5060, mload(0x4fc0)) + success := and(eq(staticcall(gas(), 0x6, 0x5000, 0x80, 0x5000, 0x40), 1), success) + mstore(0x5080, mload(0x5e0)) + mstore(0x50a0, mload(0x600)) + mstore(0x50c0, mload(0x4200)) + success := and(eq(staticcall(gas(), 0x7, 0x5080, 0x60, 0x5080, 0x40), 1), success) + mstore(0x50e0, mload(0x5000)) + mstore(0x5100, mload(0x5020)) + mstore(0x5120, mload(0x5080)) + mstore(0x5140, mload(0x50a0)) + success := and(eq(staticcall(gas(), 0x6, 0x50e0, 0x80, 0x50e0, 0x40), 1), success) + mstore(0x5160, mload(0xb00)) + mstore(0x5180, mload(0xb20)) + mstore(0x51a0, sub(f_q, mload(0x4240))) + success := and(eq(staticcall(gas(), 0x7, 0x5160, 0x60, 0x5160, 0x40), 1), success) + mstore(0x51c0, mload(0x50e0)) + mstore(0x51e0, mload(0x5100)) + mstore(0x5200, mload(0x5160)) + mstore(0x5220, mload(0x5180)) + success := and(eq(staticcall(gas(), 0x6, 0x51c0, 0x80, 0x51c0, 0x40), 1), success) + mstore(0x5240, mload(0xba0)) + mstore(0x5260, mload(0xbc0)) + mstore(0x5280, mload(0x4260)) + success := and(eq(staticcall(gas(), 0x7, 0x5240, 0x60, 0x5240, 0x40), 1), success) + mstore(0x52a0, mload(0x51c0)) + mstore(0x52c0, mload(0x51e0)) + mstore(0x52e0, mload(0x5240)) + mstore(0x5300, mload(0x5260)) + success := and(eq(staticcall(gas(), 0x6, 0x52a0, 0x80, 0x52a0, 0x40), 1), success) + mstore(0x5320, mload(0x52a0)) + mstore(0x5340, mload(0x52c0)) + mstore(0x5360, mload(0xba0)) + mstore(0x5380, mload(0xbc0)) + mstore(0x53a0, mload(0xbe0)) + mstore(0x53c0, mload(0xc00)) + mstore(0x53e0, mload(0xc20)) + mstore(0x5400, mload(0xc40)) + mstore(0x5420, keccak256(0x5320, 256)) + mstore(21568, mod(mload(21536), f_q)) + mstore(0x5460, mulmod(mload(0x5440), mload(0x5440), f_q)) + mstore(0x5480, mulmod(1, mload(0x5440), f_q)) + mstore(0x54a0, mload(0x53a0)) + mstore(0x54c0, mload(0x53c0)) + mstore(0x54e0, mload(0x5480)) + success := and(eq(staticcall(gas(), 0x7, 0x54a0, 0x60, 0x54a0, 0x40), 1), success) + mstore(0x5500, mload(0x5320)) + mstore(0x5520, mload(0x5340)) + mstore(0x5540, mload(0x54a0)) + mstore(0x5560, mload(0x54c0)) + success := and(eq(staticcall(gas(), 0x6, 0x5500, 0x80, 0x5500, 0x40), 1), success) + mstore(0x5580, mload(0x53e0)) + mstore(0x55a0, mload(0x5400)) + mstore(0x55c0, mload(0x5480)) + success := and(eq(staticcall(gas(), 0x7, 0x5580, 0x60, 0x5580, 0x40), 1), success) + mstore(0x55e0, mload(0x5360)) + mstore(0x5600, mload(0x5380)) + mstore(0x5620, mload(0x5580)) + mstore(0x5640, mload(0x55a0)) + success := and(eq(staticcall(gas(), 0x6, 0x55e0, 0x80, 0x55e0, 0x40), 1), success) + mstore(0x5660, mload(0x5500)) + mstore(0x5680, mload(0x5520)) + mstore(0x56a0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) + mstore(0x56c0, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x56e0, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0x5700, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + mstore(0x5720, mload(0x55e0)) + mstore(0x5740, mload(0x5600)) + mstore(0x5760, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) + mstore(0x5780, 0x2ae0c8c3a090f7200ff398ee9845bbae8f8c1445ae7b632212775f60a0e21600) + mstore(0x57a0, 0x190fa476a5b352809ed41d7a0d7fe12b8f685e3c12a6d83855dba27aaf469643) + mstore(0x57c0, 0x1c0a500618907df9e4273d5181e31088deb1f05132de037cbfe73888f97f77c9) + success := and(eq(staticcall(gas(), 0x8, 0x5660, 0x180, 0x5660, 0x20), 1), success) + success := and(eq(mload(0x5660), 1), success) + + // Revert if anything fails + if iszero(success) { revert(0, 0) } + + // Return empty bytes on success + return(0, 0) + } } } From 5e4cef3a4c0fe33e9073612a9c1586a08b5a8694 Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Thu, 20 Mar 2025 23:50:24 -0400 Subject: [PATCH 10/15] feat: update Halo2Verifier to use the vm config from kitchen sink benchmark --- src/Halo2Verifier.sol | 2582 +++++++++++++++++++------------- src/OpenVmHalo2Verifier.sol | 6 +- test/OpenVmHalo2Verifier.t.sol | 16 +- 3 files changed, 1537 insertions(+), 1067 deletions(-) diff --git a/src/Halo2Verifier.sol b/src/Halo2Verifier.sol index 812ab5e..f2163cd 100644 --- a/src/Halo2Verifier.sol +++ b/src/Halo2Verifier.sol @@ -51,181 +51,204 @@ contract Halo2Verifier { mstore(0x320, mod(calldataload(0x280), f_q)) mstore(0x340, mod(calldataload(0x2a0), f_q)) mstore(0x360, mod(calldataload(0x2c0), f_q)) - mstore(0x80, 15186165512185359347397944531838604952299016691786397857821503921188369501699) + mstore(0x380, mod(calldataload(0x2e0), f_q)) + mstore(0x3a0, mod(calldataload(0x300), f_q)) + mstore(0x3c0, mod(calldataload(0x320), f_q)) + mstore(0x3e0, mod(calldataload(0x340), f_q)) + mstore(0x400, mod(calldataload(0x360), f_q)) + mstore(0x420, mod(calldataload(0x380), f_q)) + mstore(0x440, mod(calldataload(0x3a0), f_q)) + mstore(0x460, mod(calldataload(0x3c0), f_q)) + mstore(0x480, mod(calldataload(0x3e0), f_q)) + mstore(0x4a0, mod(calldataload(0x400), f_q)) + mstore(0x4c0, mod(calldataload(0x420), f_q)) + mstore(0x4e0, mod(calldataload(0x440), f_q)) + mstore(0x500, mod(calldataload(0x460), f_q)) + mstore(0x520, mod(calldataload(0x480), f_q)) + mstore(0x540, mod(calldataload(0x4a0), f_q)) + mstore(0x560, mod(calldataload(0x4c0), f_q)) + mstore(0x580, mod(calldataload(0x4e0), f_q)) + mstore(0x5a0, mod(calldataload(0x500), f_q)) + mstore(0x5c0, mod(calldataload(0x520), f_q)) + mstore(0x5e0, mod(calldataload(0x540), f_q)) + mstore(0x600, mod(calldataload(0x560), f_q)) + mstore(0x620, mod(calldataload(0x580), f_q)) + mstore(0x640, mod(calldataload(0x5a0), f_q)) + mstore(0x80, 15110407967775938799674765595297831082501283201004702666478789912569454392502) { - let x := calldataload(0x2e0) - mstore(0x380, x) - let y := calldataload(0x300) - mstore(0x3a0, y) + let x := calldataload(0x5c0) + mstore(0x660, x) + let y := calldataload(0x5e0) + mstore(0x680, y) success := and(validate_ec_point(x, y), success) } - mstore(0x3c0, keccak256(0x80, 832)) + mstore(0x6a0, keccak256(0x80, 1568)) { - let hash := mload(0x3c0) - mstore(0x3e0, mod(hash, f_q)) - mstore(0x400, hash) + let hash := mload(0x6a0) + mstore(0x6c0, mod(hash, f_q)) + mstore(0x6e0, hash) } { - let x := calldataload(0x320) - mstore(0x420, x) - let y := calldataload(0x340) - mstore(0x440, y) + let x := calldataload(0x600) + mstore(0x700, x) + let y := calldataload(0x620) + mstore(0x720, y) success := and(validate_ec_point(x, y), success) } { - let x := calldataload(0x360) - mstore(0x460, x) - let y := calldataload(0x380) - mstore(0x480, y) + let x := calldataload(0x640) + mstore(0x740, x) + let y := calldataload(0x660) + mstore(0x760, y) success := and(validate_ec_point(x, y), success) } - mstore(0x4a0, keccak256(0x400, 160)) + mstore(0x780, keccak256(0x6e0, 160)) { - let hash := mload(0x4a0) - mstore(0x4c0, mod(hash, f_q)) - mstore(0x4e0, hash) + let hash := mload(0x780) + mstore(0x7a0, mod(hash, f_q)) + mstore(0x7c0, hash) } - mstore8(1280, 1) - mstore(0x500, keccak256(0x4e0, 33)) + mstore8(2016, 1) + mstore(0x7e0, keccak256(0x7c0, 33)) { - let hash := mload(0x500) - mstore(0x520, mod(hash, f_q)) - mstore(0x540, hash) + let hash := mload(0x7e0) + mstore(0x800, mod(hash, f_q)) + mstore(0x820, hash) } { - let x := calldataload(0x3a0) - mstore(0x560, x) - let y := calldataload(0x3c0) - mstore(0x580, y) + let x := calldataload(0x680) + mstore(0x840, x) + let y := calldataload(0x6a0) + mstore(0x860, y) success := and(validate_ec_point(x, y), success) } { - let x := calldataload(0x3e0) - mstore(0x5a0, x) - let y := calldataload(0x400) - mstore(0x5c0, y) + let x := calldataload(0x6c0) + mstore(0x880, x) + let y := calldataload(0x6e0) + mstore(0x8a0, y) success := and(validate_ec_point(x, y), success) } { - let x := calldataload(0x420) - mstore(0x5e0, x) - let y := calldataload(0x440) - mstore(0x600, y) + let x := calldataload(0x700) + mstore(0x8c0, x) + let y := calldataload(0x720) + mstore(0x8e0, y) success := and(validate_ec_point(x, y), success) } - mstore(0x620, keccak256(0x540, 224)) + mstore(0x900, keccak256(0x820, 224)) { - let hash := mload(0x620) - mstore(0x640, mod(hash, f_q)) - mstore(0x660, hash) + let hash := mload(0x900) + mstore(0x920, mod(hash, f_q)) + mstore(0x940, hash) } { - let x := calldataload(0x460) - mstore(0x680, x) - let y := calldataload(0x480) - mstore(0x6a0, y) + let x := calldataload(0x740) + mstore(0x960, x) + let y := calldataload(0x760) + mstore(0x980, y) success := and(validate_ec_point(x, y), success) } { - let x := calldataload(0x4a0) - mstore(0x6c0, x) - let y := calldataload(0x4c0) - mstore(0x6e0, y) + let x := calldataload(0x780) + mstore(0x9a0, x) + let y := calldataload(0x7a0) + mstore(0x9c0, y) success := and(validate_ec_point(x, y), success) } { - let x := calldataload(0x4e0) - mstore(0x700, x) - let y := calldataload(0x500) - mstore(0x720, y) + let x := calldataload(0x7c0) + mstore(0x9e0, x) + let y := calldataload(0x7e0) + mstore(0xa00, y) success := and(validate_ec_point(x, y), success) } { - let x := calldataload(0x520) - mstore(0x740, x) - let y := calldataload(0x540) - mstore(0x760, y) + let x := calldataload(0x800) + mstore(0xa20, x) + let y := calldataload(0x820) + mstore(0xa40, y) success := and(validate_ec_point(x, y), success) } - mstore(0x780, keccak256(0x660, 288)) + mstore(0xa60, keccak256(0x940, 288)) { - let hash := mload(0x780) - mstore(0x7a0, mod(hash, f_q)) - mstore(0x7c0, hash) + let hash := mload(0xa60) + mstore(0xa80, mod(hash, f_q)) + mstore(0xaa0, hash) } - mstore(0x7e0, mod(calldataload(0x560), f_q)) - mstore(0x800, mod(calldataload(0x580), f_q)) - mstore(0x820, mod(calldataload(0x5a0), f_q)) - mstore(0x840, mod(calldataload(0x5c0), f_q)) - mstore(0x860, mod(calldataload(0x5e0), f_q)) - mstore(0x880, mod(calldataload(0x600), f_q)) - mstore(0x8a0, mod(calldataload(0x620), f_q)) - mstore(0x8c0, mod(calldataload(0x640), f_q)) - mstore(0x8e0, mod(calldataload(0x660), f_q)) - mstore(0x900, mod(calldataload(0x680), f_q)) - mstore(0x920, mod(calldataload(0x6a0), f_q)) - mstore(0x940, mod(calldataload(0x6c0), f_q)) - mstore(0x960, mod(calldataload(0x6e0), f_q)) - mstore(0x980, mod(calldataload(0x700), f_q)) - mstore(0x9a0, mod(calldataload(0x720), f_q)) - mstore(0x9c0, mod(calldataload(0x740), f_q)) - mstore(0x9e0, mod(calldataload(0x760), f_q)) - mstore(0xa00, mod(calldataload(0x780), f_q)) - mstore(0xa20, mod(calldataload(0x7a0), f_q)) - mstore(0xa40, keccak256(0x7c0, 640)) + mstore(0xac0, mod(calldataload(0x840), f_q)) + mstore(0xae0, mod(calldataload(0x860), f_q)) + mstore(0xb00, mod(calldataload(0x880), f_q)) + mstore(0xb20, mod(calldataload(0x8a0), f_q)) + mstore(0xb40, mod(calldataload(0x8c0), f_q)) + mstore(0xb60, mod(calldataload(0x8e0), f_q)) + mstore(0xb80, mod(calldataload(0x900), f_q)) + mstore(0xba0, mod(calldataload(0x920), f_q)) + mstore(0xbc0, mod(calldataload(0x940), f_q)) + mstore(0xbe0, mod(calldataload(0x960), f_q)) + mstore(0xc00, mod(calldataload(0x980), f_q)) + mstore(0xc20, mod(calldataload(0x9a0), f_q)) + mstore(0xc40, mod(calldataload(0x9c0), f_q)) + mstore(0xc60, mod(calldataload(0x9e0), f_q)) + mstore(0xc80, mod(calldataload(0xa00), f_q)) + mstore(0xca0, mod(calldataload(0xa20), f_q)) + mstore(0xcc0, mod(calldataload(0xa40), f_q)) + mstore(0xce0, mod(calldataload(0xa60), f_q)) + mstore(0xd00, mod(calldataload(0xa80), f_q)) + mstore(0xd20, keccak256(0xaa0, 640)) { - let hash := mload(0xa40) - mstore(0xa60, mod(hash, f_q)) - mstore(0xa80, hash) + let hash := mload(0xd20) + mstore(0xd40, mod(hash, f_q)) + mstore(0xd60, hash) } - mstore8(2720, 1) - mstore(0xaa0, keccak256(0xa80, 33)) + mstore8(3456, 1) + mstore(0xd80, keccak256(0xd60, 33)) { - let hash := mload(0xaa0) - mstore(0xac0, mod(hash, f_q)) - mstore(0xae0, hash) + let hash := mload(0xd80) + mstore(0xda0, mod(hash, f_q)) + mstore(0xdc0, hash) } { - let x := calldataload(0x7c0) - mstore(0xb00, x) - let y := calldataload(0x7e0) - mstore(0xb20, y) + let x := calldataload(0xaa0) + mstore(0xde0, x) + let y := calldataload(0xac0) + mstore(0xe00, y) success := and(validate_ec_point(x, y), success) } - mstore(0xb40, keccak256(0xae0, 96)) + mstore(0xe20, keccak256(0xdc0, 96)) { - let hash := mload(0xb40) - mstore(0xb60, mod(hash, f_q)) - mstore(0xb80, hash) + let hash := mload(0xe20) + mstore(0xe40, mod(hash, f_q)) + mstore(0xe60, hash) } { - let x := calldataload(0x800) - mstore(0xba0, x) - let y := calldataload(0x820) - mstore(0xbc0, y) + let x := calldataload(0xae0) + mstore(0xe80, x) + let y := calldataload(0xb00) + mstore(0xea0, y) success := and(validate_ec_point(x, y), success) } { let x := mload(0xa0) x := add(x, shl(88, mload(0xc0))) x := add(x, shl(176, mload(0xe0))) - mstore(3040, x) + mstore(3776, x) let y := mload(0x100) y := add(y, shl(88, mload(0x120))) y := add(y, shl(176, mload(0x140))) - mstore(3072, y) + mstore(3808, y) success := and(validate_ec_point(x, y), success) } @@ -233,1329 +256,1774 @@ contract Halo2Verifier { let x := mload(0x160) x := add(x, shl(88, mload(0x180))) x := add(x, shl(176, mload(0x1a0))) - mstore(3104, x) + mstore(3840, x) let y := mload(0x1c0) y := add(y, shl(88, mload(0x1e0))) y := add(y, shl(176, mload(0x200))) - mstore(3136, y) + mstore(3872, y) success := and(validate_ec_point(x, y), success) } - mstore(0xc60, mulmod(mload(0x7a0), mload(0x7a0), f_q)) - mstore(0xc80, mulmod(mload(0xc60), mload(0xc60), f_q)) - mstore(0xca0, mulmod(mload(0xc80), mload(0xc80), f_q)) - mstore(0xcc0, mulmod(mload(0xca0), mload(0xca0), f_q)) - mstore(0xce0, mulmod(mload(0xcc0), mload(0xcc0), f_q)) - mstore(0xd00, mulmod(mload(0xce0), mload(0xce0), f_q)) - mstore(0xd20, mulmod(mload(0xd00), mload(0xd00), f_q)) - mstore(0xd40, mulmod(mload(0xd20), mload(0xd20), f_q)) - mstore(0xd60, mulmod(mload(0xd40), mload(0xd40), f_q)) - mstore(0xd80, mulmod(mload(0xd60), mload(0xd60), f_q)) - mstore(0xda0, mulmod(mload(0xd80), mload(0xd80), f_q)) - mstore(0xdc0, mulmod(mload(0xda0), mload(0xda0), f_q)) - mstore(0xde0, mulmod(mload(0xdc0), mload(0xdc0), f_q)) - mstore(0xe00, mulmod(mload(0xde0), mload(0xde0), f_q)) - mstore(0xe20, mulmod(mload(0xe00), mload(0xe00), f_q)) - mstore(0xe40, mulmod(mload(0xe20), mload(0xe20), f_q)) - mstore(0xe60, mulmod(mload(0xe40), mload(0xe40), f_q)) - mstore(0xe80, mulmod(mload(0xe60), mload(0xe60), f_q)) - mstore(0xea0, mulmod(mload(0xe80), mload(0xe80), f_q)) - mstore(0xec0, mulmod(mload(0xea0), mload(0xea0), f_q)) - mstore(0xee0, mulmod(mload(0xec0), mload(0xec0), f_q)) - mstore(0xf00, mulmod(mload(0xee0), mload(0xee0), f_q)) - mstore(0xf20, mulmod(mload(0xf00), mload(0xf00), f_q)) + mstore(0xf40, mulmod(mload(0xa80), mload(0xa80), f_q)) + mstore(0xf60, mulmod(mload(0xf40), mload(0xf40), f_q)) + mstore(0xf80, mulmod(mload(0xf60), mload(0xf60), f_q)) + mstore(0xfa0, mulmod(mload(0xf80), mload(0xf80), f_q)) + mstore(0xfc0, mulmod(mload(0xfa0), mload(0xfa0), f_q)) + mstore(0xfe0, mulmod(mload(0xfc0), mload(0xfc0), f_q)) + mstore(0x1000, mulmod(mload(0xfe0), mload(0xfe0), f_q)) + mstore(0x1020, mulmod(mload(0x1000), mload(0x1000), f_q)) + mstore(0x1040, mulmod(mload(0x1020), mload(0x1020), f_q)) + mstore(0x1060, mulmod(mload(0x1040), mload(0x1040), f_q)) + mstore(0x1080, mulmod(mload(0x1060), mload(0x1060), f_q)) + mstore(0x10a0, mulmod(mload(0x1080), mload(0x1080), f_q)) + mstore(0x10c0, mulmod(mload(0x10a0), mload(0x10a0), f_q)) + mstore(0x10e0, mulmod(mload(0x10c0), mload(0x10c0), f_q)) + mstore(0x1100, mulmod(mload(0x10e0), mload(0x10e0), f_q)) + mstore(0x1120, mulmod(mload(0x1100), mload(0x1100), f_q)) + mstore(0x1140, mulmod(mload(0x1120), mload(0x1120), f_q)) + mstore(0x1160, mulmod(mload(0x1140), mload(0x1140), f_q)) + mstore(0x1180, mulmod(mload(0x1160), mload(0x1160), f_q)) + mstore(0x11a0, mulmod(mload(0x1180), mload(0x1180), f_q)) + mstore(0x11c0, mulmod(mload(0x11a0), mload(0x11a0), f_q)) + mstore(0x11e0, mulmod(mload(0x11c0), mload(0x11c0), f_q)) + mstore(0x1200, mulmod(mload(0x11e0), mload(0x11e0), f_q)) mstore( - 0xf40, - addmod(mload(0xf20), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) + 0x1220, + addmod( + mload(0x1200), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q + ) ) mstore( - 0xf60, - mulmod(mload(0xf40), 21888240262557392955334514970720457388010314637169927192662615958087340972065, f_q) + 0x1240, + mulmod( + mload(0x1220), 21888240262557392955334514970720457388010314637169927192662615958087340972065, f_q + ) ) mstore( - 0xf80, - mulmod(mload(0xf60), 4506835738822104338668100540817374747935106310012997856968187171738630203507, f_q) + 0x1260, + mulmod(mload(0x1240), 4506835738822104338668100540817374747935106310012997856968187171738630203507, f_q) ) mstore( - 0xfa0, - addmod(mload(0x7a0), 17381407133017170883578305204439900340613258090403036486730017014837178292110, f_q) + 0x1280, + addmod(mload(0xa80), 17381407133017170883578305204439900340613258090403036486730017014837178292110, f_q) ) mstore( - 0xfc0, - mulmod(mload(0xf60), 21710372849001950800533397158415938114909991150039389063546734567764856596059, f_q) + 0x12a0, + mulmod( + mload(0x1240), 21710372849001950800533397158415938114909991150039389063546734567764856596059, f_q + ) ) mstore( - 0xfe0, - addmod(mload(0x7a0), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q) + 0x12c0, + addmod(mload(0xa80), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q) ) mstore( - 0x1000, - mulmod(mload(0xf60), 1887003188133998471169152042388914354640772748308168868301418279904560637395, f_q) + 0x12e0, + mulmod(mload(0x1240), 1887003188133998471169152042388914354640772748308168868301418279904560637395, f_q) ) mstore( - 0x1020, - addmod(mload(0x7a0), 20001239683705276751077253702868360733907591652107865475396785906671247858222, f_q) + 0x1300, + addmod(mload(0xa80), 20001239683705276751077253702868360733907591652107865475396785906671247858222, f_q) ) mstore( - 0x1040, - mulmod(mload(0xf60), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q) + 0x1320, + mulmod(mload(0x1240), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q) ) mstore( - 0x1060, - addmod(mload(0x7a0), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q) + 0x1340, + addmod(mload(0xa80), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q) ) mstore( - 0x1080, - mulmod(mload(0xf60), 14655294445420895451632927078981340937842238432098198055057679026789553137428, f_q) + 0x1360, + mulmod( + mload(0x1240), 14655294445420895451632927078981340937842238432098198055057679026789553137428, f_q + ) ) mstore( - 0x10a0, - addmod(mload(0x7a0), 7232948426418379770613478666275934150706125968317836288640525159786255358189, f_q) + 0x1380, + addmod(mload(0xa80), 7232948426418379770613478666275934150706125968317836288640525159786255358189, f_q) ) mstore( - 0x10c0, - mulmod(mload(0xf60), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) + 0x13a0, + mulmod(mload(0x1240), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) ) mstore( - 0x10e0, - addmod(mload(0x7a0), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q) + 0x13c0, + addmod(mload(0xa80), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q) ) mstore( - 0x1100, - mulmod(mload(0xf60), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + 0x13e0, + mulmod(mload(0x1240), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) ) mstore( - 0x1120, - addmod(mload(0x7a0), 12146688980418810893951125255607130521645347193942732958664170801695864621270, f_q) + 0x1400, + addmod(mload(0xa80), 12146688980418810893951125255607130521645347193942732958664170801695864621270, f_q) ) - mstore(0x1140, mulmod(mload(0xf60), 1, f_q)) + mstore(0x1420, mulmod(mload(0x1240), 1, f_q)) mstore( - 0x1160, - addmod(mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) + 0x1440, + addmod(mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) ) mstore( - 0x1180, - mulmod(mload(0xf60), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + 0x1460, + mulmod(mload(0x1240), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) ) mstore( - 0x11a0, - addmod(mload(0x7a0), 13513867906530865119835332133273263211836799082674232843258448413103731898270, f_q) + 0x1480, + addmod(mload(0xa80), 13513867906530865119835332133273263211836799082674232843258448413103731898270, f_q) ) mstore( - 0x11c0, - mulmod(mload(0xf60), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) + 0x14a0, + mulmod( + mload(0x1240), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q + ) ) mstore( - 0x11e0, - addmod(mload(0x7a0), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q) + 0x14c0, + addmod(mload(0xa80), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q) ) mstore( - 0x1200, - mulmod(mload(0xf60), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + 0x14e0, + mulmod(mload(0x1240), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) ) mstore( - 0x1220, - addmod(mload(0x7a0), 18272764063556419981698118473909131571661591947471949595929891197711371770216, f_q) + 0x1500, + addmod(mload(0xa80), 18272764063556419981698118473909131571661591947471949595929891197711371770216, f_q) ) mstore( - 0x1240, - mulmod(mload(0xf60), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) + 0x1520, + mulmod(mload(0x1240), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) ) mstore( - 0x1260, - addmod(mload(0x7a0), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q) + 0x1540, + addmod(mload(0xa80), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q) ) mstore( - 0x1280, - mulmod(mload(0xf60), 216092043779272773661818549620449970334216366264741118684015851799902419467, f_q) + 0x1560, + mulmod(mload(0x1240), 216092043779272773661818549620449970334216366264741118684015851799902419467, f_q) ) mstore( - 0x12a0, - addmod(mload(0x7a0), 21672150828060002448584587195636825118214148034151293225014188334775906076150, f_q) + 0x1580, + addmod(mload(0xa80), 21672150828060002448584587195636825118214148034151293225014188334775906076150, f_q) ) mstore( - 0x12c0, - mulmod(mload(0xf60), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q) + 0x15a0, + mulmod( + mload(0x1240), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q + ) ) mstore( - 0x12e0, - addmod(mload(0x7a0), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q) + 0x15c0, + addmod(mload(0xa80), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q) ) mstore( - 0x1300, - mulmod(mload(0xf60), 18610195890048912503953886742825279624920778288956610528523679659246523534888, f_q) + 0x15e0, + mulmod( + mload(0x1240), 18610195890048912503953886742825279624920778288956610528523679659246523534888, f_q + ) ) mstore( - 0x1320, - addmod(mload(0x7a0), 3278046981790362718292519002431995463627586111459423815174524527329284960729, f_q) + 0x1600, + addmod(mload(0xa80), 3278046981790362718292519002431995463627586111459423815174524527329284960729, f_q) ) mstore( - 0x1340, - mulmod(mload(0xf60), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q) + 0x1620, + mulmod( + mload(0x1240), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q + ) ) mstore( - 0x1360, - addmod(mload(0x7a0), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q) + 0x1640, + addmod(mload(0xa80), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q) ) mstore( - 0x1380, - mulmod(mload(0xf60), 14875928112196239563830800280253496262679717528621719058794366823499719730250, f_q) + 0x1660, + mulmod( + mload(0x1240), 14875928112196239563830800280253496262679717528621719058794366823499719730250, f_q + ) ) mstore( - 0x13a0, - addmod(mload(0x7a0), 7012314759643035658415605465003778825868646871794315284903837363076088765367, f_q) + 0x1680, + addmod(mload(0xa80), 7012314759643035658415605465003778825868646871794315284903837363076088765367, f_q) ) mstore( - 0x13c0, - mulmod(mload(0xf60), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q) + 0x16a0, + mulmod(mload(0x1240), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q) ) mstore( - 0x13e0, - addmod(mload(0x7a0), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q) + 0x16c0, + addmod(mload(0xa80), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q) ) mstore( - 0x1400, - mulmod(mload(0xf60), 5522161504810533295870699551020523636289972223872138525048055197429246400245, f_q) + 0x16e0, + mulmod(mload(0x1240), 5522161504810533295870699551020523636289972223872138525048055197429246400245, f_q) ) mstore( - 0x1420, - addmod(mload(0x7a0), 16366081367028741926375706194236751452258392176543895818650148989146562095372, f_q) + 0x1700, + addmod(mload(0xa80), 16366081367028741926375706194236751452258392176543895818650148989146562095372, f_q) ) mstore( - 0x1440, - mulmod(mload(0xf60), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q) + 0x1720, + mulmod(mload(0x1240), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q) ) mstore( - 0x1460, - addmod(mload(0x7a0), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q) + 0x1740, + addmod(mload(0xa80), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q) ) mstore( - 0x1480, - mulmod(mload(0xf60), 9100833993744738801214480881117348002768153232283708533639316963648253510584, f_q) + 0x1760, + mulmod(mload(0x1240), 9100833993744738801214480881117348002768153232283708533639316963648253510584, f_q) ) mstore( - 0x14a0, - addmod(mload(0x7a0), 12787408878094536421031924864139927085780211168132325810058887222927554985033, f_q) + 0x1780, + addmod(mload(0xa80), 12787408878094536421031924864139927085780211168132325810058887222927554985033, f_q) ) mstore( - 0x14c0, - mulmod(mload(0xf60), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q) + 0x17a0, + mulmod(mload(0x1240), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q) ) mstore( - 0x14e0, - addmod(mload(0x7a0), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q) + 0x17c0, + addmod(mload(0xa80), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q) ) mstore( - 0x1500, - mulmod(mload(0xf60), 6132660129994545119218258312491950835441607143741804980633129304664017206141, f_q) + 0x17e0, + mulmod(mload(0x1240), 6132660129994545119218258312491950835441607143741804980633129304664017206141, f_q) ) mstore( - 0x1520, - addmod(mload(0x7a0), 15755582741844730103028147432765324253106757256674229363065074881911791289476, f_q) + 0x1800, + addmod(mload(0xa80), 15755582741844730103028147432765324253106757256674229363065074881911791289476, f_q) ) mstore( - 0x1540, - mulmod(mload(0xf60), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q) + 0x1820, + mulmod(mload(0x1240), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q) ) mstore( - 0x1560, - addmod(mload(0x7a0), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q) + 0x1840, + addmod(mload(0xa80), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q) ) mstore( - 0x1580, - mulmod(mload(0xf60), 515148244606945972463850631189471072103916690263705052318085725998468254533, f_q) + 0x1860, + mulmod(mload(0x1240), 515148244606945972463850631189471072103916690263705052318085725998468254533, f_q) ) mstore( - 0x15a0, - addmod(mload(0x7a0), 21373094627232329249782555114067804016444447710152329291380118460577340241084, f_q) + 0x1880, + addmod(mload(0xa80), 21373094627232329249782555114067804016444447710152329291380118460577340241084, f_q) ) mstore( - 0x15c0, - mulmod(mload(0xf60), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q) + 0x18a0, + mulmod(mload(0x1240), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q) ) mstore( - 0x15e0, - addmod(mload(0x7a0), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q) + 0x18c0, + addmod(mload(0xa80), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q) ) mstore( - 0x1600, - mulmod(mload(0xf60), 5223738580615264174925218065001555728265216895679471490312087802465486318994, f_q) + 0x18e0, + mulmod(mload(0x1240), 5223738580615264174925218065001555728265216895679471490312087802465486318994, f_q) ) mstore( - 0x1620, - addmod(mload(0x7a0), 16664504291224011047321187680255719360283147504736562853386116384110322176623, f_q) + 0x1900, + addmod(mload(0xa80), 16664504291224011047321187680255719360283147504736562853386116384110322176623, f_q) ) mstore( - 0x1640, - mulmod(mload(0xf60), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q) + 0x1920, + mulmod( + mload(0x1240), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q + ) ) mstore( - 0x1660, - addmod(mload(0x7a0), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q) + 0x1940, + addmod(mload(0xa80), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q) ) mstore( - 0x1680, - mulmod(mload(0xf60), 16976236069879939850923145256911338076234942200101755618884183331004076579046, f_q) + 0x1960, + mulmod( + mload(0x1240), 16976236069879939850923145256911338076234942200101755618884183331004076579046, f_q + ) ) mstore( - 0x16a0, - addmod(mload(0x7a0), 4912006801959335371323260488345937012313422200314278724814020855571731916571, f_q) + 0x1980, + addmod(mload(0xa80), 4912006801959335371323260488345937012313422200314278724814020855571731916571, f_q) ) mstore( - 0x16c0, - mulmod(mload(0xf60), 13553911191894110065493137367144919847521088405945523452288398666974237857208, f_q) + 0x19a0, + mulmod( + mload(0x1240), 13553911191894110065493137367144919847521088405945523452288398666974237857208, f_q + ) ) mstore( - 0x16e0, - addmod(mload(0x7a0), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q) + 0x19c0, + addmod(mload(0xa80), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q) + ) + mstore( + 0x19e0, + mulmod( + mload(0x1240), 12222687719926148270818604386979005738180875192307070468454582955273533101023, f_q + ) + ) + mstore( + 0x1a00, + addmod(mload(0xa80), 9665555151913126951427801358278269350367489208108963875243621231302275394594, f_q) + ) + mstore( + 0x1a20, + mulmod(mload(0x1240), 9697063347556872083384215826199993067635178715531258559890418744774301211662, f_q) + ) + mstore( + 0x1a40, + addmod(mload(0xa80), 12191179524282403138862189919057282020913185684884775783807785441801507283955, f_q) + ) + mstore( + 0x1a60, + mulmod( + mload(0x1240), 13783318220968413117070077848579881425001701814458176881760898225529300547844, f_q + ) + ) + mstore( + 0x1a80, + addmod(mload(0xa80), 8104924650870862105176327896677393663546662585957857461937305961046507947773, f_q) + ) + mstore( + 0x1aa0, + mulmod( + mload(0x1240), 10807735674816066981985242612061336605021639643453679977988966079770672437131, f_q + ) + ) + mstore( + 0x1ac0, + addmod(mload(0xa80), 11080507197023208240261163133195938483526724756962354365709238106805136058486, f_q) + ) + mstore( + 0x1ae0, + mulmod( + mload(0x1240), 15487660954688013862248478071816391715224351867581977083810729441220383572585, f_q + ) + ) + mstore( + 0x1b00, + addmod(mload(0xa80), 6400581917151261359997927673440883373324012532834057259887474745355424923032, f_q) + ) + mstore( + 0x1b20, + mulmod( + mload(0x1240), 12459868075641381822485233712013080087763946065665469821362892189399541605692, f_q + ) + ) + mstore( + 0x1b40, + addmod(mload(0xa80), 9428374796197893399761172033244195000784418334750564522335311997176266889925, f_q) + ) + mstore( + 0x1b60, + mulmod( + mload(0x1240), 12562571400845953139885120066983392294851269266041089223701347829190217414825, f_q + ) + ) + mstore( + 0x1b80, + addmod(mload(0xa80), 9325671470993322082361285678273882793697095134374945119996856357385591080792, f_q) + ) + mstore( + 0x1ba0, + mulmod( + mload(0x1240), 16038300751658239075779628684257016433412502747804121525056508685985277092575, f_q + ) + ) + mstore( + 0x1bc0, + addmod(mload(0xa80), 5849942120181036146466777061000258655135861652611912818641695500590531403042, f_q) + ) + mstore( + 0x1be0, + mulmod( + mload(0x1240), 17665522928519859765452767154433594409738037332395989540221744312194874941704, f_q + ) + ) + mstore( + 0x1c00, + addmod(mload(0xa80), 4222719943319415456793638590823680678810327068020044803476459874380933553913, f_q) + ) + mstore( + 0x1c20, + mulmod(mload(0x1240), 6955697244493336113861667751840378876927906302623587437721024018233754910398, f_q) + ) + mstore( + 0x1c40, + addmod(mload(0xa80), 14932545627345939108384737993416896211620458097792446905977180168342053585219, f_q) + ) + mstore( + 0x1c60, + mulmod(mload(0x1240), 1918679275621049296283934091410967415474987212511681231948800935495808101054, f_q) + ) + mstore( + 0x1c80, + addmod(mload(0xa80), 19969563596218225925962471653846307673073377187904353111749403251080000394563, f_q) + ) + mstore( + 0x1ca0, + mulmod( + mload(0x1240), 13498745591877810872211159461644682954739332524336278910448604883789771736885, f_q + ) + ) + mstore( + 0x1cc0, + addmod(mload(0xa80), 8389497279961464350035246283612592133809031876079755433249599302786036758732, f_q) + ) + mstore( + 0x1ce0, + mulmod(mload(0x1240), 6604851689411953560355663038203889299997924520355363678860500374111951937637, f_q) + ) + mstore( + 0x1d00, + addmod(mload(0xa80), 15283391182427321661890742707053385788550439880060670664837703812463856557980, f_q) + ) + mstore( + 0x1d20, + mulmod( + mload(0x1240), 20345677989844117909528750049476969581182118546166966482506114734614108237981, f_q + ) + ) + mstore( + 0x1d40, + addmod(mload(0xa80), 1542564881995157312717655695780305507366245854249067861192089451961700257636, f_q) + ) + mstore( + 0x1d60, + mulmod( + mload(0x1240), 11244009323710436498447061620026171700033960328162115124806024297270121927878, f_q + ) + ) + mstore( + 0x1d80, + addmod(mload(0xa80), 10644233548128838723799344125231103388514404072253919218892179889305686567739, f_q) + ) + mstore( + 0x1da0, + mulmod(mload(0x1240), 790608022292213379425324383664216541739009722347092850716054055768832299157, f_q) + ) + mstore( + 0x1dc0, + addmod(mload(0xa80), 21097634849547061842821081361593058546809354678068941492982150130806976196460, f_q) + ) + mstore( + 0x1de0, + mulmod( + mload(0x1240), 13894403229372218245111098554468346933152618215322268934207074514797092422856, f_q + ) + ) + mstore( + 0x1e00, + addmod(mload(0xa80), 7993839642467056977135307190788928155395746185093765409491129671778716072761, f_q) + ) + mstore( + 0x1e20, + mulmod(mload(0x1240), 5289443209903185443361862148540090689648485914368835830972895623576469023722, f_q) + ) + mstore( + 0x1e40, + addmod(mload(0xa80), 16598799661936089778884543596717184398899878486047198512725308562999339471895, f_q) + ) + mstore( + 0x1e60, + mulmod( + mload(0x1240), 19715528266218439644661892824912275086257866064695767122686506494361332681035, f_q + ) + ) + mstore( + 0x1e80, + addmod(mload(0xa80), 2172714605620835577584512920345000002290498335720267221011697692214475814582, f_q) + ) + mstore( + 0x1ea0, + mulmod( + mload(0x1240), 15161189183906287273290738379431332336600234154579306802151507052820126345529, f_q + ) + ) + mstore( + 0x1ec0, + addmod(mload(0xa80), 6727053687932987948955667365825942751948130245836727541546697133755682150088, f_q) + ) + mstore( + 0x1ee0, + mulmod( + mload(0x1240), 12456424076401232823832128238027368612265814450984711658287606686035629293382, f_q + ) + ) + mstore( + 0x1f00, + addmod(mload(0xa80), 9431818795438042398414277507229906476282549949431322685410597500540179202235, f_q) + ) + mstore( + 0x1f20, + mulmod(mload(0x1240), 557567375339945239933617516585967620814823575807691402619711360028043331811, f_q) + ) + mstore( + 0x1f40, + addmod(mload(0xa80), 21330675496499329982312788228671307467733540824608342941078492826547765163806, f_q) + ) + mstore( + 0x1f60, + mulmod(mload(0x1240), 3675353143102618619098608207619541954347747556257261634661810167705798540391, f_q) + ) + mstore( + 0x1f80, + addmod(mload(0xa80), 18212889728736656603147797537637733134200616844158772709036394018870009955226, f_q) ) { - let prod := mload(0xfa0) + let prod := mload(0x1280) - prod := mulmod(mload(0xfe0), prod, f_q) - mstore(0x1700, prod) + prod := mulmod(mload(0x12c0), prod, f_q) + mstore(0x1fa0, prod) - prod := mulmod(mload(0x1020), prod, f_q) - mstore(0x1720, prod) + prod := mulmod(mload(0x1300), prod, f_q) + mstore(0x1fc0, prod) - prod := mulmod(mload(0x1060), prod, f_q) - mstore(0x1740, prod) + prod := mulmod(mload(0x1340), prod, f_q) + mstore(0x1fe0, prod) - prod := mulmod(mload(0x10a0), prod, f_q) - mstore(0x1760, prod) + prod := mulmod(mload(0x1380), prod, f_q) + mstore(0x2000, prod) - prod := mulmod(mload(0x10e0), prod, f_q) - mstore(0x1780, prod) + prod := mulmod(mload(0x13c0), prod, f_q) + mstore(0x2020, prod) - prod := mulmod(mload(0x1120), prod, f_q) - mstore(0x17a0, prod) + prod := mulmod(mload(0x1400), prod, f_q) + mstore(0x2040, prod) - prod := mulmod(mload(0x1160), prod, f_q) - mstore(0x17c0, prod) + prod := mulmod(mload(0x1440), prod, f_q) + mstore(0x2060, prod) - prod := mulmod(mload(0x11a0), prod, f_q) - mstore(0x17e0, prod) + prod := mulmod(mload(0x1480), prod, f_q) + mstore(0x2080, prod) - prod := mulmod(mload(0x11e0), prod, f_q) - mstore(0x1800, prod) + prod := mulmod(mload(0x14c0), prod, f_q) + mstore(0x20a0, prod) - prod := mulmod(mload(0x1220), prod, f_q) - mstore(0x1820, prod) + prod := mulmod(mload(0x1500), prod, f_q) + mstore(0x20c0, prod) + + prod := mulmod(mload(0x1540), prod, f_q) + mstore(0x20e0, prod) + + prod := mulmod(mload(0x1580), prod, f_q) + mstore(0x2100, prod) + + prod := mulmod(mload(0x15c0), prod, f_q) + mstore(0x2120, prod) + + prod := mulmod(mload(0x1600), prod, f_q) + mstore(0x2140, prod) + + prod := mulmod(mload(0x1640), prod, f_q) + mstore(0x2160, prod) + + prod := mulmod(mload(0x1680), prod, f_q) + mstore(0x2180, prod) + + prod := mulmod(mload(0x16c0), prod, f_q) + mstore(0x21a0, prod) + + prod := mulmod(mload(0x1700), prod, f_q) + mstore(0x21c0, prod) + + prod := mulmod(mload(0x1740), prod, f_q) + mstore(0x21e0, prod) + + prod := mulmod(mload(0x1780), prod, f_q) + mstore(0x2200, prod) + + prod := mulmod(mload(0x17c0), prod, f_q) + mstore(0x2220, prod) + + prod := mulmod(mload(0x1800), prod, f_q) + mstore(0x2240, prod) + + prod := mulmod(mload(0x1840), prod, f_q) + mstore(0x2260, prod) + + prod := mulmod(mload(0x1880), prod, f_q) + mstore(0x2280, prod) + + prod := mulmod(mload(0x18c0), prod, f_q) + mstore(0x22a0, prod) + + prod := mulmod(mload(0x1900), prod, f_q) + mstore(0x22c0, prod) - prod := mulmod(mload(0x1260), prod, f_q) - mstore(0x1840, prod) + prod := mulmod(mload(0x1940), prod, f_q) + mstore(0x22e0, prod) - prod := mulmod(mload(0x12a0), prod, f_q) - mstore(0x1860, prod) + prod := mulmod(mload(0x1980), prod, f_q) + mstore(0x2300, prod) - prod := mulmod(mload(0x12e0), prod, f_q) - mstore(0x1880, prod) + prod := mulmod(mload(0x19c0), prod, f_q) + mstore(0x2320, prod) - prod := mulmod(mload(0x1320), prod, f_q) - mstore(0x18a0, prod) + prod := mulmod(mload(0x1a00), prod, f_q) + mstore(0x2340, prod) - prod := mulmod(mload(0x1360), prod, f_q) - mstore(0x18c0, prod) + prod := mulmod(mload(0x1a40), prod, f_q) + mstore(0x2360, prod) - prod := mulmod(mload(0x13a0), prod, f_q) - mstore(0x18e0, prod) + prod := mulmod(mload(0x1a80), prod, f_q) + mstore(0x2380, prod) - prod := mulmod(mload(0x13e0), prod, f_q) - mstore(0x1900, prod) + prod := mulmod(mload(0x1ac0), prod, f_q) + mstore(0x23a0, prod) - prod := mulmod(mload(0x1420), prod, f_q) - mstore(0x1920, prod) + prod := mulmod(mload(0x1b00), prod, f_q) + mstore(0x23c0, prod) - prod := mulmod(mload(0x1460), prod, f_q) - mstore(0x1940, prod) + prod := mulmod(mload(0x1b40), prod, f_q) + mstore(0x23e0, prod) - prod := mulmod(mload(0x14a0), prod, f_q) - mstore(0x1960, prod) + prod := mulmod(mload(0x1b80), prod, f_q) + mstore(0x2400, prod) - prod := mulmod(mload(0x14e0), prod, f_q) - mstore(0x1980, prod) + prod := mulmod(mload(0x1bc0), prod, f_q) + mstore(0x2420, prod) - prod := mulmod(mload(0x1520), prod, f_q) - mstore(0x19a0, prod) + prod := mulmod(mload(0x1c00), prod, f_q) + mstore(0x2440, prod) - prod := mulmod(mload(0x1560), prod, f_q) - mstore(0x19c0, prod) + prod := mulmod(mload(0x1c40), prod, f_q) + mstore(0x2460, prod) - prod := mulmod(mload(0x15a0), prod, f_q) - mstore(0x19e0, prod) + prod := mulmod(mload(0x1c80), prod, f_q) + mstore(0x2480, prod) - prod := mulmod(mload(0x15e0), prod, f_q) - mstore(0x1a00, prod) + prod := mulmod(mload(0x1cc0), prod, f_q) + mstore(0x24a0, prod) - prod := mulmod(mload(0x1620), prod, f_q) - mstore(0x1a20, prod) + prod := mulmod(mload(0x1d00), prod, f_q) + mstore(0x24c0, prod) - prod := mulmod(mload(0x1660), prod, f_q) - mstore(0x1a40, prod) + prod := mulmod(mload(0x1d40), prod, f_q) + mstore(0x24e0, prod) - prod := mulmod(mload(0x16a0), prod, f_q) - mstore(0x1a60, prod) + prod := mulmod(mload(0x1d80), prod, f_q) + mstore(0x2500, prod) - prod := mulmod(mload(0x16e0), prod, f_q) - mstore(0x1a80, prod) + prod := mulmod(mload(0x1dc0), prod, f_q) + mstore(0x2520, prod) - prod := mulmod(mload(0xf40), prod, f_q) - mstore(0x1aa0, prod) + prod := mulmod(mload(0x1e00), prod, f_q) + mstore(0x2540, prod) + + prod := mulmod(mload(0x1e40), prod, f_q) + mstore(0x2560, prod) + + prod := mulmod(mload(0x1e80), prod, f_q) + mstore(0x2580, prod) + + prod := mulmod(mload(0x1ec0), prod, f_q) + mstore(0x25a0, prod) + + prod := mulmod(mload(0x1f00), prod, f_q) + mstore(0x25c0, prod) + + prod := mulmod(mload(0x1f40), prod, f_q) + mstore(0x25e0, prod) + + prod := mulmod(mload(0x1f80), prod, f_q) + mstore(0x2600, prod) + + prod := mulmod(mload(0x1220), prod, f_q) + mstore(0x2620, prod) } - mstore(0x1ae0, 32) - mstore(0x1b00, 32) - mstore(0x1b20, 32) - mstore(0x1b40, mload(0x1aa0)) - mstore(0x1b60, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x1b80, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x1ae0, 0xc0, 0x1ac0, 0x20), 1), success) + mstore(0x2660, 32) + mstore(0x2680, 32) + mstore(0x26a0, 32) + mstore(0x26c0, mload(0x2620)) + mstore(0x26e0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + mstore(0x2700, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + success := and(eq(staticcall(gas(), 0x5, 0x2660, 0xc0, 0x2640, 0x20), 1), success) { - let inv := mload(0x1ac0) + let inv := mload(0x2640) let v - v := mload(0xf40) - mstore(3904, mulmod(mload(0x1a80), inv, f_q)) + v := mload(0x1220) + mstore(4640, mulmod(mload(0x2600), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x16e0) - mstore(5856, mulmod(mload(0x1a60), inv, f_q)) + v := mload(0x1f80) + mstore(8064, mulmod(mload(0x25e0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x16a0) - mstore(5792, mulmod(mload(0x1a40), inv, f_q)) + v := mload(0x1f40) + mstore(8000, mulmod(mload(0x25c0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1660) - mstore(5728, mulmod(mload(0x1a20), inv, f_q)) + v := mload(0x1f00) + mstore(7936, mulmod(mload(0x25a0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1620) - mstore(5664, mulmod(mload(0x1a00), inv, f_q)) + v := mload(0x1ec0) + mstore(7872, mulmod(mload(0x2580), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x15e0) - mstore(5600, mulmod(mload(0x19e0), inv, f_q)) + v := mload(0x1e80) + mstore(7808, mulmod(mload(0x2560), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x15a0) - mstore(5536, mulmod(mload(0x19c0), inv, f_q)) + v := mload(0x1e40) + mstore(7744, mulmod(mload(0x2540), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1560) - mstore(5472, mulmod(mload(0x19a0), inv, f_q)) + v := mload(0x1e00) + mstore(7680, mulmod(mload(0x2520), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1520) - mstore(5408, mulmod(mload(0x1980), inv, f_q)) + v := mload(0x1dc0) + mstore(7616, mulmod(mload(0x2500), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x14e0) - mstore(5344, mulmod(mload(0x1960), inv, f_q)) + v := mload(0x1d80) + mstore(7552, mulmod(mload(0x24e0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x14a0) - mstore(5280, mulmod(mload(0x1940), inv, f_q)) + v := mload(0x1d40) + mstore(7488, mulmod(mload(0x24c0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1460) - mstore(5216, mulmod(mload(0x1920), inv, f_q)) + v := mload(0x1d00) + mstore(7424, mulmod(mload(0x24a0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1420) - mstore(5152, mulmod(mload(0x1900), inv, f_q)) + v := mload(0x1cc0) + mstore(7360, mulmod(mload(0x2480), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x13e0) - mstore(5088, mulmod(mload(0x18e0), inv, f_q)) + v := mload(0x1c80) + mstore(7296, mulmod(mload(0x2460), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x13a0) - mstore(5024, mulmod(mload(0x18c0), inv, f_q)) + v := mload(0x1c40) + mstore(7232, mulmod(mload(0x2440), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1360) - mstore(4960, mulmod(mload(0x18a0), inv, f_q)) + v := mload(0x1c00) + mstore(7168, mulmod(mload(0x2420), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1320) - mstore(4896, mulmod(mload(0x1880), inv, f_q)) + v := mload(0x1bc0) + mstore(7104, mulmod(mload(0x2400), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x12e0) - mstore(4832, mulmod(mload(0x1860), inv, f_q)) + v := mload(0x1b80) + mstore(7040, mulmod(mload(0x23e0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x12a0) - mstore(4768, mulmod(mload(0x1840), inv, f_q)) + v := mload(0x1b40) + mstore(6976, mulmod(mload(0x23c0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1260) - mstore(4704, mulmod(mload(0x1820), inv, f_q)) + v := mload(0x1b00) + mstore(6912, mulmod(mload(0x23a0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1220) - mstore(4640, mulmod(mload(0x1800), inv, f_q)) + v := mload(0x1ac0) + mstore(6848, mulmod(mload(0x2380), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1a80) + mstore(6784, mulmod(mload(0x2360), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1a40) + mstore(6720, mulmod(mload(0x2340), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1a00) + mstore(6656, mulmod(mload(0x2320), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x19c0) + mstore(6592, mulmod(mload(0x2300), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1980) + mstore(6528, mulmod(mload(0x22e0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x11e0) - mstore(4576, mulmod(mload(0x17e0), inv, f_q)) + v := mload(0x1940) + mstore(6464, mulmod(mload(0x22c0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x11a0) - mstore(4512, mulmod(mload(0x17c0), inv, f_q)) + v := mload(0x1900) + mstore(6400, mulmod(mload(0x22a0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1160) - mstore(4448, mulmod(mload(0x17a0), inv, f_q)) + v := mload(0x18c0) + mstore(6336, mulmod(mload(0x2280), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1120) - mstore(4384, mulmod(mload(0x1780), inv, f_q)) + v := mload(0x1880) + mstore(6272, mulmod(mload(0x2260), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x10e0) - mstore(4320, mulmod(mload(0x1760), inv, f_q)) + v := mload(0x1840) + mstore(6208, mulmod(mload(0x2240), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x10a0) - mstore(4256, mulmod(mload(0x1740), inv, f_q)) + v := mload(0x1800) + mstore(6144, mulmod(mload(0x2220), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1060) - mstore(4192, mulmod(mload(0x1720), inv, f_q)) + v := mload(0x17c0) + mstore(6080, mulmod(mload(0x2200), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x1020) - mstore(4128, mulmod(mload(0x1700), inv, f_q)) + v := mload(0x1780) + mstore(6016, mulmod(mload(0x21e0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0xfe0) - mstore(4064, mulmod(mload(0xfa0), inv, f_q)) + v := mload(0x1740) + mstore(5952, mulmod(mload(0x21c0), inv, f_q)) inv := mulmod(v, inv, f_q) - mstore(0xfa0, inv) + + v := mload(0x1700) + mstore(5888, mulmod(mload(0x21a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x16c0) + mstore(5824, mulmod(mload(0x2180), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1680) + mstore(5760, mulmod(mload(0x2160), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1640) + mstore(5696, mulmod(mload(0x2140), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1600) + mstore(5632, mulmod(mload(0x2120), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x15c0) + mstore(5568, mulmod(mload(0x2100), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1580) + mstore(5504, mulmod(mload(0x20e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1540) + mstore(5440, mulmod(mload(0x20c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1500) + mstore(5376, mulmod(mload(0x20a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x14c0) + mstore(5312, mulmod(mload(0x2080), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1480) + mstore(5248, mulmod(mload(0x2060), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1440) + mstore(5184, mulmod(mload(0x2040), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1400) + mstore(5120, mulmod(mload(0x2020), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13c0) + mstore(5056, mulmod(mload(0x2000), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1380) + mstore(4992, mulmod(mload(0x1fe0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1340) + mstore(4928, mulmod(mload(0x1fc0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1300) + mstore(4864, mulmod(mload(0x1fa0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12c0) + mstore(4800, mulmod(mload(0x1280), inv, f_q)) + inv := mulmod(v, inv, f_q) + mstore(0x1280, inv) } - mstore(0x1ba0, mulmod(mload(0xf80), mload(0xfa0), f_q)) - mstore(0x1bc0, mulmod(mload(0xfc0), mload(0xfe0), f_q)) - mstore(0x1be0, mulmod(mload(0x1000), mload(0x1020), f_q)) - mstore(0x1c00, mulmod(mload(0x1040), mload(0x1060), f_q)) - mstore(0x1c20, mulmod(mload(0x1080), mload(0x10a0), f_q)) - mstore(0x1c40, mulmod(mload(0x10c0), mload(0x10e0), f_q)) - mstore(0x1c60, mulmod(mload(0x1100), mload(0x1120), f_q)) - mstore(0x1c80, mulmod(mload(0x1140), mload(0x1160), f_q)) - mstore(0x1ca0, mulmod(mload(0x1180), mload(0x11a0), f_q)) - mstore(0x1cc0, mulmod(mload(0x11c0), mload(0x11e0), f_q)) - mstore(0x1ce0, mulmod(mload(0x1200), mload(0x1220), f_q)) - mstore(0x1d00, mulmod(mload(0x1240), mload(0x1260), f_q)) - mstore(0x1d20, mulmod(mload(0x1280), mload(0x12a0), f_q)) - mstore(0x1d40, mulmod(mload(0x12c0), mload(0x12e0), f_q)) - mstore(0x1d60, mulmod(mload(0x1300), mload(0x1320), f_q)) - mstore(0x1d80, mulmod(mload(0x1340), mload(0x1360), f_q)) - mstore(0x1da0, mulmod(mload(0x1380), mload(0x13a0), f_q)) - mstore(0x1dc0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) - mstore(0x1de0, mulmod(mload(0x1400), mload(0x1420), f_q)) - mstore(0x1e00, mulmod(mload(0x1440), mload(0x1460), f_q)) - mstore(0x1e20, mulmod(mload(0x1480), mload(0x14a0), f_q)) - mstore(0x1e40, mulmod(mload(0x14c0), mload(0x14e0), f_q)) - mstore(0x1e60, mulmod(mload(0x1500), mload(0x1520), f_q)) - mstore(0x1e80, mulmod(mload(0x1540), mload(0x1560), f_q)) - mstore(0x1ea0, mulmod(mload(0x1580), mload(0x15a0), f_q)) - mstore(0x1ec0, mulmod(mload(0x15c0), mload(0x15e0), f_q)) - mstore(0x1ee0, mulmod(mload(0x1600), mload(0x1620), f_q)) - mstore(0x1f00, mulmod(mload(0x1640), mload(0x1660), f_q)) - mstore(0x1f20, mulmod(mload(0x1680), mload(0x16a0), f_q)) - mstore(0x1f40, mulmod(mload(0x16c0), mload(0x16e0), f_q)) + mstore(0x2720, mulmod(mload(0x1260), mload(0x1280), f_q)) + mstore(0x2740, mulmod(mload(0x12a0), mload(0x12c0), f_q)) + mstore(0x2760, mulmod(mload(0x12e0), mload(0x1300), f_q)) + mstore(0x2780, mulmod(mload(0x1320), mload(0x1340), f_q)) + mstore(0x27a0, mulmod(mload(0x1360), mload(0x1380), f_q)) + mstore(0x27c0, mulmod(mload(0x13a0), mload(0x13c0), f_q)) + mstore(0x27e0, mulmod(mload(0x13e0), mload(0x1400), f_q)) + mstore(0x2800, mulmod(mload(0x1420), mload(0x1440), f_q)) + mstore(0x2820, mulmod(mload(0x1460), mload(0x1480), f_q)) + mstore(0x2840, mulmod(mload(0x14a0), mload(0x14c0), f_q)) + mstore(0x2860, mulmod(mload(0x14e0), mload(0x1500), f_q)) + mstore(0x2880, mulmod(mload(0x1520), mload(0x1540), f_q)) + mstore(0x28a0, mulmod(mload(0x1560), mload(0x1580), f_q)) + mstore(0x28c0, mulmod(mload(0x15a0), mload(0x15c0), f_q)) + mstore(0x28e0, mulmod(mload(0x15e0), mload(0x1600), f_q)) + mstore(0x2900, mulmod(mload(0x1620), mload(0x1640), f_q)) + mstore(0x2920, mulmod(mload(0x1660), mload(0x1680), f_q)) + mstore(0x2940, mulmod(mload(0x16a0), mload(0x16c0), f_q)) + mstore(0x2960, mulmod(mload(0x16e0), mload(0x1700), f_q)) + mstore(0x2980, mulmod(mload(0x1720), mload(0x1740), f_q)) + mstore(0x29a0, mulmod(mload(0x1760), mload(0x1780), f_q)) + mstore(0x29c0, mulmod(mload(0x17a0), mload(0x17c0), f_q)) + mstore(0x29e0, mulmod(mload(0x17e0), mload(0x1800), f_q)) + mstore(0x2a00, mulmod(mload(0x1820), mload(0x1840), f_q)) + mstore(0x2a20, mulmod(mload(0x1860), mload(0x1880), f_q)) + mstore(0x2a40, mulmod(mload(0x18a0), mload(0x18c0), f_q)) + mstore(0x2a60, mulmod(mload(0x18e0), mload(0x1900), f_q)) + mstore(0x2a80, mulmod(mload(0x1920), mload(0x1940), f_q)) + mstore(0x2aa0, mulmod(mload(0x1960), mload(0x1980), f_q)) + mstore(0x2ac0, mulmod(mload(0x19a0), mload(0x19c0), f_q)) + mstore(0x2ae0, mulmod(mload(0x19e0), mload(0x1a00), f_q)) + mstore(0x2b00, mulmod(mload(0x1a20), mload(0x1a40), f_q)) + mstore(0x2b20, mulmod(mload(0x1a60), mload(0x1a80), f_q)) + mstore(0x2b40, mulmod(mload(0x1aa0), mload(0x1ac0), f_q)) + mstore(0x2b60, mulmod(mload(0x1ae0), mload(0x1b00), f_q)) + mstore(0x2b80, mulmod(mload(0x1b20), mload(0x1b40), f_q)) + mstore(0x2ba0, mulmod(mload(0x1b60), mload(0x1b80), f_q)) + mstore(0x2bc0, mulmod(mload(0x1ba0), mload(0x1bc0), f_q)) + mstore(0x2be0, mulmod(mload(0x1be0), mload(0x1c00), f_q)) + mstore(0x2c00, mulmod(mload(0x1c20), mload(0x1c40), f_q)) + mstore(0x2c20, mulmod(mload(0x1c60), mload(0x1c80), f_q)) + mstore(0x2c40, mulmod(mload(0x1ca0), mload(0x1cc0), f_q)) + mstore(0x2c60, mulmod(mload(0x1ce0), mload(0x1d00), f_q)) + mstore(0x2c80, mulmod(mload(0x1d20), mload(0x1d40), f_q)) + mstore(0x2ca0, mulmod(mload(0x1d60), mload(0x1d80), f_q)) + mstore(0x2cc0, mulmod(mload(0x1da0), mload(0x1dc0), f_q)) + mstore(0x2ce0, mulmod(mload(0x1de0), mload(0x1e00), f_q)) + mstore(0x2d00, mulmod(mload(0x1e20), mload(0x1e40), f_q)) + mstore(0x2d20, mulmod(mload(0x1e60), mload(0x1e80), f_q)) + mstore(0x2d40, mulmod(mload(0x1ea0), mload(0x1ec0), f_q)) + mstore(0x2d60, mulmod(mload(0x1ee0), mload(0x1f00), f_q)) + mstore(0x2d80, mulmod(mload(0x1f20), mload(0x1f40), f_q)) + mstore(0x2da0, mulmod(mload(0x1f60), mload(0x1f80), f_q)) { - let result := mulmod(mload(0x1c80), mload(0xa0), f_q) - result := addmod(mulmod(mload(0x1ca0), mload(0xc0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1cc0), mload(0xe0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1ce0), mload(0x100), f_q), result, f_q) - result := addmod(mulmod(mload(0x1d00), mload(0x120), f_q), result, f_q) - result := addmod(mulmod(mload(0x1d20), mload(0x140), f_q), result, f_q) - result := addmod(mulmod(mload(0x1d40), mload(0x160), f_q), result, f_q) - result := addmod(mulmod(mload(0x1d60), mload(0x180), f_q), result, f_q) - result := addmod(mulmod(mload(0x1d80), mload(0x1a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1da0), mload(0x1c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1dc0), mload(0x1e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1de0), mload(0x200), f_q), result, f_q) - result := addmod(mulmod(mload(0x1e00), mload(0x220), f_q), result, f_q) - result := addmod(mulmod(mload(0x1e20), mload(0x240), f_q), result, f_q) - result := addmod(mulmod(mload(0x1e40), mload(0x260), f_q), result, f_q) - result := addmod(mulmod(mload(0x1e60), mload(0x280), f_q), result, f_q) - result := addmod(mulmod(mload(0x1e80), mload(0x2a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1ea0), mload(0x2c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1ec0), mload(0x2e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x1ee0), mload(0x300), f_q), result, f_q) - result := addmod(mulmod(mload(0x1f00), mload(0x320), f_q), result, f_q) - result := addmod(mulmod(mload(0x1f20), mload(0x340), f_q), result, f_q) - result := addmod(mulmod(mload(0x1f40), mload(0x360), f_q), result, f_q) - mstore(8032, result) + let result := mulmod(mload(0x2800), mload(0xa0), f_q) + result := addmod(mulmod(mload(0x2820), mload(0xc0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2840), mload(0xe0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2860), mload(0x100), f_q), result, f_q) + result := addmod(mulmod(mload(0x2880), mload(0x120), f_q), result, f_q) + result := addmod(mulmod(mload(0x28a0), mload(0x140), f_q), result, f_q) + result := addmod(mulmod(mload(0x28c0), mload(0x160), f_q), result, f_q) + result := addmod(mulmod(mload(0x28e0), mload(0x180), f_q), result, f_q) + result := addmod(mulmod(mload(0x2900), mload(0x1a0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2920), mload(0x1c0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2940), mload(0x1e0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2960), mload(0x200), f_q), result, f_q) + result := addmod(mulmod(mload(0x2980), mload(0x220), f_q), result, f_q) + result := addmod(mulmod(mload(0x29a0), mload(0x240), f_q), result, f_q) + result := addmod(mulmod(mload(0x29c0), mload(0x260), f_q), result, f_q) + result := addmod(mulmod(mload(0x29e0), mload(0x280), f_q), result, f_q) + result := addmod(mulmod(mload(0x2a00), mload(0x2a0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2a20), mload(0x2c0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2a40), mload(0x2e0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2a60), mload(0x300), f_q), result, f_q) + result := addmod(mulmod(mload(0x2a80), mload(0x320), f_q), result, f_q) + result := addmod(mulmod(mload(0x2aa0), mload(0x340), f_q), result, f_q) + result := addmod(mulmod(mload(0x2ac0), mload(0x360), f_q), result, f_q) + result := addmod(mulmod(mload(0x2ae0), mload(0x380), f_q), result, f_q) + result := addmod(mulmod(mload(0x2b00), mload(0x3a0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2b20), mload(0x3c0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2b40), mload(0x3e0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2b60), mload(0x400), f_q), result, f_q) + result := addmod(mulmod(mload(0x2b80), mload(0x420), f_q), result, f_q) + result := addmod(mulmod(mload(0x2ba0), mload(0x440), f_q), result, f_q) + result := addmod(mulmod(mload(0x2bc0), mload(0x460), f_q), result, f_q) + result := addmod(mulmod(mload(0x2be0), mload(0x480), f_q), result, f_q) + result := addmod(mulmod(mload(0x2c00), mload(0x4a0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2c20), mload(0x4c0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2c40), mload(0x4e0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2c60), mload(0x500), f_q), result, f_q) + result := addmod(mulmod(mload(0x2c80), mload(0x520), f_q), result, f_q) + result := addmod(mulmod(mload(0x2ca0), mload(0x540), f_q), result, f_q) + result := addmod(mulmod(mload(0x2cc0), mload(0x560), f_q), result, f_q) + result := addmod(mulmod(mload(0x2ce0), mload(0x580), f_q), result, f_q) + result := addmod(mulmod(mload(0x2d00), mload(0x5a0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2d20), mload(0x5c0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2d40), mload(0x5e0), f_q), result, f_q) + result := addmod(mulmod(mload(0x2d60), mload(0x600), f_q), result, f_q) + result := addmod(mulmod(mload(0x2d80), mload(0x620), f_q), result, f_q) + result := addmod(mulmod(mload(0x2da0), mload(0x640), f_q), result, f_q) + mstore(11712, result) } - mstore(0x1f80, mulmod(mload(0x820), mload(0x800), f_q)) - mstore(0x1fa0, addmod(mload(0x7e0), mload(0x1f80), f_q)) - mstore(0x1fc0, addmod(mload(0x1fa0), sub(f_q, mload(0x840)), f_q)) - mstore(0x1fe0, mulmod(mload(0x1fc0), mload(0x8a0), f_q)) - mstore(0x2000, mulmod(mload(0x640), mload(0x1fe0), f_q)) - mstore(0x2020, addmod(1, sub(f_q, mload(0x960)), f_q)) - mstore(0x2040, mulmod(mload(0x2020), mload(0x1c80), f_q)) - mstore(0x2060, addmod(mload(0x2000), mload(0x2040), f_q)) - mstore(0x2080, mulmod(mload(0x640), mload(0x2060), f_q)) - mstore(0x20a0, mulmod(mload(0x960), mload(0x960), f_q)) - mstore(0x20c0, addmod(mload(0x20a0), sub(f_q, mload(0x960)), f_q)) - mstore(0x20e0, mulmod(mload(0x20c0), mload(0x1ba0), f_q)) - mstore(0x2100, addmod(mload(0x2080), mload(0x20e0), f_q)) - mstore(0x2120, mulmod(mload(0x640), mload(0x2100), f_q)) - mstore(0x2140, addmod(1, sub(f_q, mload(0x1ba0)), f_q)) - mstore(0x2160, addmod(mload(0x1bc0), mload(0x1be0), f_q)) - mstore(0x2180, addmod(mload(0x2160), mload(0x1c00), f_q)) - mstore(0x21a0, addmod(mload(0x2180), mload(0x1c20), f_q)) - mstore(0x21c0, addmod(mload(0x21a0), mload(0x1c40), f_q)) - mstore(0x21e0, addmod(mload(0x21c0), mload(0x1c60), f_q)) - mstore(0x2200, addmod(mload(0x2140), sub(f_q, mload(0x21e0)), f_q)) - mstore(0x2220, mulmod(mload(0x900), mload(0x4c0), f_q)) - mstore(0x2240, addmod(mload(0x860), mload(0x2220), f_q)) - mstore(0x2260, addmod(mload(0x2240), mload(0x520), f_q)) - mstore(0x2280, mulmod(mload(0x920), mload(0x4c0), f_q)) - mstore(0x22a0, addmod(mload(0x7e0), mload(0x2280), f_q)) - mstore(0x22c0, addmod(mload(0x22a0), mload(0x520), f_q)) - mstore(0x22e0, mulmod(mload(0x22c0), mload(0x2260), f_q)) - mstore(0x2300, mulmod(mload(0x940), mload(0x4c0), f_q)) - mstore(0x2320, addmod(mload(0x1f60), mload(0x2300), f_q)) - mstore(0x2340, addmod(mload(0x2320), mload(0x520), f_q)) - mstore(0x2360, mulmod(mload(0x2340), mload(0x22e0), f_q)) - mstore(0x2380, mulmod(mload(0x2360), mload(0x980), f_q)) - mstore(0x23a0, mulmod(1, mload(0x4c0), f_q)) - mstore(0x23c0, mulmod(mload(0x7a0), mload(0x23a0), f_q)) - mstore(0x23e0, addmod(mload(0x860), mload(0x23c0), f_q)) - mstore(0x2400, addmod(mload(0x23e0), mload(0x520), f_q)) - mstore( - 0x2420, - mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x4c0), f_q) - ) - mstore(0x2440, mulmod(mload(0x7a0), mload(0x2420), f_q)) - mstore(0x2460, addmod(mload(0x7e0), mload(0x2440), f_q)) - mstore(0x2480, addmod(mload(0x2460), mload(0x520), f_q)) - mstore(0x24a0, mulmod(mload(0x2480), mload(0x2400), f_q)) - mstore( - 0x24c0, - mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x4c0), f_q) - ) - mstore(0x24e0, mulmod(mload(0x7a0), mload(0x24c0), f_q)) - mstore(0x2500, addmod(mload(0x1f60), mload(0x24e0), f_q)) - mstore(0x2520, addmod(mload(0x2500), mload(0x520), f_q)) - mstore(0x2540, mulmod(mload(0x2520), mload(0x24a0), f_q)) - mstore(0x2560, mulmod(mload(0x2540), mload(0x960), f_q)) - mstore(0x2580, addmod(mload(0x2380), sub(f_q, mload(0x2560)), f_q)) - mstore(0x25a0, mulmod(mload(0x2580), mload(0x2200), f_q)) - mstore(0x25c0, addmod(mload(0x2120), mload(0x25a0), f_q)) - mstore(0x25e0, mulmod(mload(0x640), mload(0x25c0), f_q)) - mstore(0x2600, addmod(1, sub(f_q, mload(0x9a0)), f_q)) - mstore(0x2620, mulmod(mload(0x2600), mload(0x1c80), f_q)) - mstore(0x2640, addmod(mload(0x25e0), mload(0x2620), f_q)) - mstore(0x2660, mulmod(mload(0x640), mload(0x2640), f_q)) - mstore(0x2680, mulmod(mload(0x9a0), mload(0x9a0), f_q)) - mstore(0x26a0, addmod(mload(0x2680), sub(f_q, mload(0x9a0)), f_q)) - mstore(0x26c0, mulmod(mload(0x26a0), mload(0x1ba0), f_q)) - mstore(0x26e0, addmod(mload(0x2660), mload(0x26c0), f_q)) - mstore(0x2700, mulmod(mload(0x640), mload(0x26e0), f_q)) - mstore(0x2720, addmod(mload(0x9e0), mload(0x4c0), f_q)) - mstore(0x2740, mulmod(mload(0x2720), mload(0x9c0), f_q)) - mstore(0x2760, addmod(mload(0xa20), mload(0x520), f_q)) - mstore(0x2780, mulmod(mload(0x2760), mload(0x2740), f_q)) - mstore(0x27a0, mulmod(mload(0x7e0), mload(0x8c0), f_q)) - mstore(0x27c0, addmod(mload(0x27a0), mload(0x4c0), f_q)) - mstore(0x27e0, mulmod(mload(0x27c0), mload(0x9a0), f_q)) - mstore(0x2800, addmod(mload(0x880), mload(0x520), f_q)) - mstore(0x2820, mulmod(mload(0x2800), mload(0x27e0), f_q)) - mstore(0x2840, addmod(mload(0x2780), sub(f_q, mload(0x2820)), f_q)) - mstore(0x2860, mulmod(mload(0x2840), mload(0x2200), f_q)) - mstore(0x2880, addmod(mload(0x2700), mload(0x2860), f_q)) - mstore(0x28a0, mulmod(mload(0x640), mload(0x2880), f_q)) - mstore(0x28c0, addmod(mload(0x9e0), sub(f_q, mload(0xa20)), f_q)) - mstore(0x28e0, mulmod(mload(0x28c0), mload(0x1c80), f_q)) - mstore(0x2900, addmod(mload(0x28a0), mload(0x28e0), f_q)) - mstore(0x2920, mulmod(mload(0x640), mload(0x2900), f_q)) - mstore(0x2940, mulmod(mload(0x28c0), mload(0x2200), f_q)) - mstore(0x2960, addmod(mload(0x9e0), sub(f_q, mload(0xa00)), f_q)) - mstore(0x2980, mulmod(mload(0x2960), mload(0x2940), f_q)) - mstore(0x29a0, addmod(mload(0x2920), mload(0x2980), f_q)) - mstore(0x29c0, mulmod(mload(0xf20), mload(0xf20), f_q)) - mstore(0x29e0, mulmod(mload(0x29c0), mload(0xf20), f_q)) - mstore(0x2a00, mulmod(mload(0x29e0), mload(0xf20), f_q)) - mstore(0x2a20, mulmod(1, mload(0xf20), f_q)) - mstore(0x2a40, mulmod(1, mload(0x29c0), f_q)) - mstore(0x2a60, mulmod(1, mload(0x29e0), f_q)) - mstore(0x2a80, mulmod(mload(0x29a0), mload(0xf40), f_q)) - mstore(0x2aa0, mulmod(mload(0xc60), mload(0x7a0), f_q)) - mstore(0x2ac0, mulmod(mload(0x2aa0), mload(0x7a0), f_q)) - mstore( - 0x2ae0, - mulmod(mload(0x7a0), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) - ) - mstore(0x2b00, addmod(mload(0xb60), sub(f_q, mload(0x2ae0)), f_q)) - mstore(0x2b20, mulmod(mload(0x7a0), 1, f_q)) - mstore(0x2b40, addmod(mload(0xb60), sub(f_q, mload(0x2b20)), f_q)) - mstore( - 0x2b60, - mulmod(mload(0x7a0), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) - ) - mstore(0x2b80, addmod(mload(0xb60), sub(f_q, mload(0x2b60)), f_q)) - mstore( - 0x2ba0, - mulmod(mload(0x7a0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) - ) - mstore(0x2bc0, addmod(mload(0xb60), sub(f_q, mload(0x2ba0)), f_q)) - mstore( - 0x2be0, - mulmod(mload(0x7a0), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) - ) - mstore(0x2c00, addmod(mload(0xb60), sub(f_q, mload(0x2be0)), f_q)) - mstore( - 0x2c20, + mstore(0x2de0, mulmod(mload(0xb00), mload(0xae0), f_q)) + mstore(0x2e00, addmod(mload(0xac0), mload(0x2de0), f_q)) + mstore(0x2e20, addmod(mload(0x2e00), sub(f_q, mload(0xb20)), f_q)) + mstore(0x2e40, mulmod(mload(0x2e20), mload(0xb80), f_q)) + mstore(0x2e60, mulmod(mload(0x920), mload(0x2e40), f_q)) + mstore(0x2e80, addmod(1, sub(f_q, mload(0xc40)), f_q)) + mstore(0x2ea0, mulmod(mload(0x2e80), mload(0x2800), f_q)) + mstore(0x2ec0, addmod(mload(0x2e60), mload(0x2ea0), f_q)) + mstore(0x2ee0, mulmod(mload(0x920), mload(0x2ec0), f_q)) + mstore(0x2f00, mulmod(mload(0xc40), mload(0xc40), f_q)) + mstore(0x2f20, addmod(mload(0x2f00), sub(f_q, mload(0xc40)), f_q)) + mstore(0x2f40, mulmod(mload(0x2f20), mload(0x2720), f_q)) + mstore(0x2f60, addmod(mload(0x2ee0), mload(0x2f40), f_q)) + mstore(0x2f80, mulmod(mload(0x920), mload(0x2f60), f_q)) + mstore(0x2fa0, addmod(1, sub(f_q, mload(0x2720)), f_q)) + mstore(0x2fc0, addmod(mload(0x2740), mload(0x2760), f_q)) + mstore(0x2fe0, addmod(mload(0x2fc0), mload(0x2780), f_q)) + mstore(0x3000, addmod(mload(0x2fe0), mload(0x27a0), f_q)) + mstore(0x3020, addmod(mload(0x3000), mload(0x27c0), f_q)) + mstore(0x3040, addmod(mload(0x3020), mload(0x27e0), f_q)) + mstore(0x3060, addmod(mload(0x2fa0), sub(f_q, mload(0x3040)), f_q)) + mstore(0x3080, mulmod(mload(0xbe0), mload(0x7a0), f_q)) + mstore(0x30a0, addmod(mload(0xb40), mload(0x3080), f_q)) + mstore(0x30c0, addmod(mload(0x30a0), mload(0x800), f_q)) + mstore(0x30e0, mulmod(mload(0xc00), mload(0x7a0), f_q)) + mstore(0x3100, addmod(mload(0xac0), mload(0x30e0), f_q)) + mstore(0x3120, addmod(mload(0x3100), mload(0x800), f_q)) + mstore(0x3140, mulmod(mload(0x3120), mload(0x30c0), f_q)) + mstore(0x3160, mulmod(mload(0xc20), mload(0x7a0), f_q)) + mstore(0x3180, addmod(mload(0x2dc0), mload(0x3160), f_q)) + mstore(0x31a0, addmod(mload(0x3180), mload(0x800), f_q)) + mstore(0x31c0, mulmod(mload(0x31a0), mload(0x3140), f_q)) + mstore(0x31e0, mulmod(mload(0x31c0), mload(0xc60), f_q)) + mstore(0x3200, mulmod(1, mload(0x7a0), f_q)) + mstore(0x3220, mulmod(mload(0xa80), mload(0x3200), f_q)) + mstore(0x3240, addmod(mload(0xb40), mload(0x3220), f_q)) + mstore(0x3260, addmod(mload(0x3240), mload(0x800), f_q)) + mstore( + 0x3280, + mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x7a0), f_q) + ) + mstore(0x32a0, mulmod(mload(0xa80), mload(0x3280), f_q)) + mstore(0x32c0, addmod(mload(0xac0), mload(0x32a0), f_q)) + mstore(0x32e0, addmod(mload(0x32c0), mload(0x800), f_q)) + mstore(0x3300, mulmod(mload(0x32e0), mload(0x3260), f_q)) + mstore( + 0x3320, + mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x7a0), f_q) + ) + mstore(0x3340, mulmod(mload(0xa80), mload(0x3320), f_q)) + mstore(0x3360, addmod(mload(0x2dc0), mload(0x3340), f_q)) + mstore(0x3380, addmod(mload(0x3360), mload(0x800), f_q)) + mstore(0x33a0, mulmod(mload(0x3380), mload(0x3300), f_q)) + mstore(0x33c0, mulmod(mload(0x33a0), mload(0xc40), f_q)) + mstore(0x33e0, addmod(mload(0x31e0), sub(f_q, mload(0x33c0)), f_q)) + mstore(0x3400, mulmod(mload(0x33e0), mload(0x3060), f_q)) + mstore(0x3420, addmod(mload(0x2f80), mload(0x3400), f_q)) + mstore(0x3440, mulmod(mload(0x920), mload(0x3420), f_q)) + mstore(0x3460, addmod(1, sub(f_q, mload(0xc80)), f_q)) + mstore(0x3480, mulmod(mload(0x3460), mload(0x2800), f_q)) + mstore(0x34a0, addmod(mload(0x3440), mload(0x3480), f_q)) + mstore(0x34c0, mulmod(mload(0x920), mload(0x34a0), f_q)) + mstore(0x34e0, mulmod(mload(0xc80), mload(0xc80), f_q)) + mstore(0x3500, addmod(mload(0x34e0), sub(f_q, mload(0xc80)), f_q)) + mstore(0x3520, mulmod(mload(0x3500), mload(0x2720), f_q)) + mstore(0x3540, addmod(mload(0x34c0), mload(0x3520), f_q)) + mstore(0x3560, mulmod(mload(0x920), mload(0x3540), f_q)) + mstore(0x3580, addmod(mload(0xcc0), mload(0x7a0), f_q)) + mstore(0x35a0, mulmod(mload(0x3580), mload(0xca0), f_q)) + mstore(0x35c0, addmod(mload(0xd00), mload(0x800), f_q)) + mstore(0x35e0, mulmod(mload(0x35c0), mload(0x35a0), f_q)) + mstore(0x3600, mulmod(mload(0xac0), mload(0xba0), f_q)) + mstore(0x3620, addmod(mload(0x3600), mload(0x7a0), f_q)) + mstore(0x3640, mulmod(mload(0x3620), mload(0xc80), f_q)) + mstore(0x3660, addmod(mload(0xb60), mload(0x800), f_q)) + mstore(0x3680, mulmod(mload(0x3660), mload(0x3640), f_q)) + mstore(0x36a0, addmod(mload(0x35e0), sub(f_q, mload(0x3680)), f_q)) + mstore(0x36c0, mulmod(mload(0x36a0), mload(0x3060), f_q)) + mstore(0x36e0, addmod(mload(0x3560), mload(0x36c0), f_q)) + mstore(0x3700, mulmod(mload(0x920), mload(0x36e0), f_q)) + mstore(0x3720, addmod(mload(0xcc0), sub(f_q, mload(0xd00)), f_q)) + mstore(0x3740, mulmod(mload(0x3720), mload(0x2800), f_q)) + mstore(0x3760, addmod(mload(0x3700), mload(0x3740), f_q)) + mstore(0x3780, mulmod(mload(0x920), mload(0x3760), f_q)) + mstore(0x37a0, mulmod(mload(0x3720), mload(0x3060), f_q)) + mstore(0x37c0, addmod(mload(0xcc0), sub(f_q, mload(0xce0)), f_q)) + mstore(0x37e0, mulmod(mload(0x37c0), mload(0x37a0), f_q)) + mstore(0x3800, addmod(mload(0x3780), mload(0x37e0), f_q)) + mstore(0x3820, mulmod(mload(0x1200), mload(0x1200), f_q)) + mstore(0x3840, mulmod(mload(0x3820), mload(0x1200), f_q)) + mstore(0x3860, mulmod(mload(0x3840), mload(0x1200), f_q)) + mstore(0x3880, mulmod(1, mload(0x1200), f_q)) + mstore(0x38a0, mulmod(1, mload(0x3820), f_q)) + mstore(0x38c0, mulmod(1, mload(0x3840), f_q)) + mstore(0x38e0, mulmod(mload(0x3800), mload(0x1220), f_q)) + mstore(0x3900, mulmod(mload(0xf40), mload(0xa80), f_q)) + mstore(0x3920, mulmod(mload(0x3900), mload(0xa80), f_q)) + mstore( + 0x3940, + mulmod(mload(0xa80), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + ) + mstore(0x3960, addmod(mload(0xe40), sub(f_q, mload(0x3940)), f_q)) + mstore(0x3980, mulmod(mload(0xa80), 1, f_q)) + mstore(0x39a0, addmod(mload(0xe40), sub(f_q, mload(0x3980)), f_q)) + mstore( + 0x39c0, + mulmod(mload(0xa80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + ) + mstore(0x39e0, addmod(mload(0xe40), sub(f_q, mload(0x39c0)), f_q)) + mstore( + 0x3a00, + mulmod(mload(0xa80), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) + ) + mstore(0x3a20, addmod(mload(0xe40), sub(f_q, mload(0x3a00)), f_q)) + mstore( + 0x3a40, + mulmod(mload(0xa80), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + ) + mstore(0x3a60, addmod(mload(0xe40), sub(f_q, mload(0x3a40)), f_q)) + mstore( + 0x3a80, mulmod( - 13213688729882003894512633350385593288217014177373218494356903340348818451480, mload(0x2aa0), f_q + 13213688729882003894512633350385593288217014177373218494356903340348818451480, mload(0x3900), f_q ) ) - mstore(0x2c40, mulmod(mload(0x2c20), 1, f_q)) + mstore(0x3aa0, mulmod(mload(0x3a80), 1, f_q)) { - let result := mulmod(mload(0xb60), mload(0x2c20), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2c40)), f_q), result, f_q) - mstore(11360, result) + let result := mulmod(mload(0xe40), mload(0x3a80), f_q) + result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3aa0)), f_q), result, f_q) + mstore(15040, result) } mstore( - 0x2c80, - mulmod(8207090019724696496350398458716998472718344609680392612601596849934418295470, mload(0x2aa0), f_q) + 0x3ae0, + mulmod(8207090019724696496350398458716998472718344609680392612601596849934418295470, mload(0x3900), f_q) ) mstore( - 0x2ca0, - mulmod(mload(0x2c80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + 0x3b00, + mulmod(mload(0x3ae0), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) ) { - let result := mulmod(mload(0xb60), mload(0x2c80), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ca0)), f_q), result, f_q) - mstore(11456, result) + let result := mulmod(mload(0xe40), mload(0x3ae0), f_q) + result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3b00)), f_q), result, f_q) + mstore(15136, result) } mstore( - 0x2ce0, - mulmod(7391709068497399131897422873231908718558236401035363928063603272120120747483, mload(0x2aa0), f_q) + 0x3b40, + mulmod(7391709068497399131897422873231908718558236401035363928063603272120120747483, mload(0x3900), f_q) ) mstore( - 0x2d00, + 0x3b60, mulmod( - mload(0x2ce0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q + mload(0x3b40), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q ) ) { - let result := mulmod(mload(0xb60), mload(0x2ce0), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d00)), f_q), result, f_q) - mstore(11552, result) + let result := mulmod(mload(0xe40), mload(0x3b40), f_q) + result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3b60)), f_q), result, f_q) + mstore(15232, result) } mstore( - 0x2d40, + 0x3ba0, mulmod( - 19036273796805830823244991598792794567595348772040298280440552631112242221017, mload(0x2aa0), f_q + 19036273796805830823244991598792794567595348772040298280440552631112242221017, mload(0x3900), f_q ) ) mstore( - 0x2d60, - mulmod(mload(0x2d40), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) + 0x3bc0, + mulmod(mload(0x3ba0), 3615478808282855240548287271348143516886772452944084747768312988864436725401, f_q) ) { - let result := mulmod(mload(0xb60), mload(0x2d40), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2d60)), f_q), result, f_q) - mstore(11648, result) + let result := mulmod(mload(0xe40), mload(0x3ba0), f_q) + result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3bc0)), f_q), result, f_q) + mstore(15328, result) } - mstore(0x2da0, mulmod(1, mload(0x2b40), f_q)) - mstore(0x2dc0, mulmod(mload(0x2da0), mload(0x2b80), f_q)) - mstore(0x2de0, mulmod(mload(0x2dc0), mload(0x2bc0), f_q)) - mstore(0x2e00, mulmod(mload(0x2de0), mload(0x2c00), f_q)) + mstore(0x3c00, mulmod(1, mload(0x39a0), f_q)) + mstore(0x3c20, mulmod(mload(0x3c00), mload(0x39e0), f_q)) + mstore(0x3c40, mulmod(mload(0x3c20), mload(0x3a20), f_q)) + mstore(0x3c60, mulmod(mload(0x3c40), mload(0x3a60), f_q)) mstore( - 0x2e20, - mulmod(13513867906530865119835332133273263211836799082674232843258448413103731898271, mload(0x7a0), f_q) + 0x3c80, + mulmod(13513867906530865119835332133273263211836799082674232843258448413103731898271, mload(0xa80), f_q) ) - mstore(0x2e40, mulmod(mload(0x2e20), 1, f_q)) + mstore(0x3ca0, mulmod(mload(0x3c80), 1, f_q)) { - let result := mulmod(mload(0xb60), mload(0x2e20), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2e40)), f_q), result, f_q) - mstore(11872, result) + let result := mulmod(mload(0xe40), mload(0x3c80), f_q) + result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ca0)), f_q), result, f_q) + mstore(15552, result) } mstore( - 0x2e80, - mulmod(8374374965308410102411073611984011876711565317741801500439755773472076597346, mload(0x7a0), f_q) + 0x3ce0, + mulmod(8374374965308410102411073611984011876711565317741801500439755773472076597346, mload(0xa80), f_q) ) mstore( - 0x2ea0, - mulmod(mload(0x2e80), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) + 0x3d00, + mulmod(mload(0x3ce0), 8374374965308410102411073611984011876711565317741801500439755773472076597347, f_q) ) { - let result := mulmod(mload(0xb60), mload(0x2e80), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2ea0)), f_q), result, f_q) - mstore(11968, result) + let result := mulmod(mload(0xe40), mload(0x3ce0), f_q) + result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3d00)), f_q), result, f_q) + mstore(15648, result) } mstore( - 0x2ee0, - mulmod(12146688980418810893951125255607130521645347193942732958664170801695864621271, mload(0x7a0), f_q) + 0x3d40, + mulmod(12146688980418810893951125255607130521645347193942732958664170801695864621271, mload(0xa80), f_q) ) - mstore(0x2f00, mulmod(mload(0x2ee0), 1, f_q)) + mstore(0x3d60, mulmod(mload(0x3d40), 1, f_q)) { - let result := mulmod(mload(0xb60), mload(0x2ee0), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f00)), f_q), result, f_q) - mstore(12064, result) + let result := mulmod(mload(0xe40), mload(0x3d40), f_q) + result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3d60)), f_q), result, f_q) + mstore(15744, result) } mstore( - 0x2f40, - mulmod(9741553891420464328295280489650144566903017206473301385034033384879943874346, mload(0x7a0), f_q) + 0x3da0, + mulmod(9741553891420464328295280489650144566903017206473301385034033384879943874346, mload(0xa80), f_q) ) mstore( - 0x2f60, - mulmod(mload(0x2f40), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) + 0x3dc0, + mulmod(mload(0x3da0), 9741553891420464328295280489650144566903017206473301385034033384879943874347, f_q) ) { - let result := mulmod(mload(0xb60), mload(0x2f40), f_q) - result := addmod(mulmod(mload(0x7a0), sub(f_q, mload(0x2f60)), f_q), result, f_q) - mstore(12160, result) + let result := mulmod(mload(0xe40), mload(0x3da0), f_q) + result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3dc0)), f_q), result, f_q) + mstore(15840, result) } - mstore(0x2fa0, mulmod(mload(0x2da0), mload(0x2b00), f_q)) + mstore(0x3e00, mulmod(mload(0x3c00), mload(0x3960), f_q)) { - let result := mulmod(mload(0xb60), 1, f_q) + let result := mulmod(mload(0xe40), 1, f_q) result := addmod( mulmod( - mload(0x7a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q + mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q ), result, f_q ) - mstore(12224, result) + mstore(15904, result) } { - let prod := mload(0x2c60) + let prod := mload(0x3ac0) - prod := mulmod(mload(0x2cc0), prod, f_q) - mstore(0x2fe0, prod) + prod := mulmod(mload(0x3b20), prod, f_q) + mstore(0x3e40, prod) - prod := mulmod(mload(0x2d20), prod, f_q) - mstore(0x3000, prod) + prod := mulmod(mload(0x3b80), prod, f_q) + mstore(0x3e60, prod) - prod := mulmod(mload(0x2d80), prod, f_q) - mstore(0x3020, prod) + prod := mulmod(mload(0x3be0), prod, f_q) + mstore(0x3e80, prod) - prod := mulmod(mload(0x2e60), prod, f_q) - mstore(0x3040, prod) + prod := mulmod(mload(0x3cc0), prod, f_q) + mstore(0x3ea0, prod) - prod := mulmod(mload(0x2ec0), prod, f_q) - mstore(0x3060, prod) + prod := mulmod(mload(0x3d20), prod, f_q) + mstore(0x3ec0, prod) - prod := mulmod(mload(0x2dc0), prod, f_q) - mstore(0x3080, prod) + prod := mulmod(mload(0x3c20), prod, f_q) + mstore(0x3ee0, prod) - prod := mulmod(mload(0x2f20), prod, f_q) - mstore(0x30a0, prod) + prod := mulmod(mload(0x3d80), prod, f_q) + mstore(0x3f00, prod) - prod := mulmod(mload(0x2f80), prod, f_q) - mstore(0x30c0, prod) + prod := mulmod(mload(0x3de0), prod, f_q) + mstore(0x3f20, prod) - prod := mulmod(mload(0x2fa0), prod, f_q) - mstore(0x30e0, prod) + prod := mulmod(mload(0x3e00), prod, f_q) + mstore(0x3f40, prod) - prod := mulmod(mload(0x2fc0), prod, f_q) - mstore(0x3100, prod) + prod := mulmod(mload(0x3e20), prod, f_q) + mstore(0x3f60, prod) - prod := mulmod(mload(0x2da0), prod, f_q) - mstore(0x3120, prod) + prod := mulmod(mload(0x3c00), prod, f_q) + mstore(0x3f80, prod) } - mstore(0x3160, 32) - mstore(0x3180, 32) - mstore(0x31a0, 32) - mstore(0x31c0, mload(0x3120)) - mstore(0x31e0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x3200, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x3160, 0xc0, 0x3140, 0x20), 1), success) + mstore(0x3fc0, 32) + mstore(0x3fe0, 32) + mstore(0x4000, 32) + mstore(0x4020, mload(0x3f80)) + mstore(0x4040, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + mstore(0x4060, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + success := and(eq(staticcall(gas(), 0x5, 0x3fc0, 0xc0, 0x3fa0, 0x20), 1), success) { - let inv := mload(0x3140) + let inv := mload(0x3fa0) let v - v := mload(0x2da0) - mstore(11680, mulmod(mload(0x3100), inv, f_q)) + v := mload(0x3c00) + mstore(15360, mulmod(mload(0x3f60), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x2fc0) - mstore(12224, mulmod(mload(0x30e0), inv, f_q)) + v := mload(0x3e20) + mstore(15904, mulmod(mload(0x3f40), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x2fa0) - mstore(12192, mulmod(mload(0x30c0), inv, f_q)) + v := mload(0x3e00) + mstore(15872, mulmod(mload(0x3f20), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x2f80) - mstore(12160, mulmod(mload(0x30a0), inv, f_q)) + v := mload(0x3de0) + mstore(15840, mulmod(mload(0x3f00), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x2f20) - mstore(12064, mulmod(mload(0x3080), inv, f_q)) + v := mload(0x3d80) + mstore(15744, mulmod(mload(0x3ee0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x2dc0) - mstore(11712, mulmod(mload(0x3060), inv, f_q)) + v := mload(0x3c20) + mstore(15392, mulmod(mload(0x3ec0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x2ec0) - mstore(11968, mulmod(mload(0x3040), inv, f_q)) + v := mload(0x3d20) + mstore(15648, mulmod(mload(0x3ea0), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x2e60) - mstore(11872, mulmod(mload(0x3020), inv, f_q)) + v := mload(0x3cc0) + mstore(15552, mulmod(mload(0x3e80), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x2d80) - mstore(11648, mulmod(mload(0x3000), inv, f_q)) + v := mload(0x3be0) + mstore(15328, mulmod(mload(0x3e60), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x2d20) - mstore(11552, mulmod(mload(0x2fe0), inv, f_q)) + v := mload(0x3b80) + mstore(15232, mulmod(mload(0x3e40), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x2cc0) - mstore(11456, mulmod(mload(0x2c60), inv, f_q)) + v := mload(0x3b20) + mstore(15136, mulmod(mload(0x3ac0), inv, f_q)) inv := mulmod(v, inv, f_q) - mstore(0x2c60, inv) + mstore(0x3ac0, inv) } { - let result := mload(0x2c60) - result := addmod(mload(0x2cc0), result, f_q) - result := addmod(mload(0x2d20), result, f_q) - result := addmod(mload(0x2d80), result, f_q) - mstore(12832, result) + let result := mload(0x3ac0) + result := addmod(mload(0x3b20), result, f_q) + result := addmod(mload(0x3b80), result, f_q) + result := addmod(mload(0x3be0), result, f_q) + mstore(16512, result) } - mstore(0x3240, mulmod(mload(0x2e00), mload(0x2dc0), f_q)) + mstore(0x40a0, mulmod(mload(0x3c60), mload(0x3c20), f_q)) { - let result := mload(0x2e60) - result := addmod(mload(0x2ec0), result, f_q) - mstore(12896, result) + let result := mload(0x3cc0) + result := addmod(mload(0x3d20), result, f_q) + mstore(16576, result) } - mstore(0x3280, mulmod(mload(0x2e00), mload(0x2fa0), f_q)) + mstore(0x40e0, mulmod(mload(0x3c60), mload(0x3e00), f_q)) { - let result := mload(0x2f20) - result := addmod(mload(0x2f80), result, f_q) - mstore(12960, result) + let result := mload(0x3d80) + result := addmod(mload(0x3de0), result, f_q) + mstore(16640, result) } - mstore(0x32c0, mulmod(mload(0x2e00), mload(0x2da0), f_q)) + mstore(0x4120, mulmod(mload(0x3c60), mload(0x3c00), f_q)) { - let result := mload(0x2fc0) - mstore(13024, result) + let result := mload(0x3e20) + mstore(16704, result) } { - let prod := mload(0x3220) + let prod := mload(0x4080) - prod := mulmod(mload(0x3260), prod, f_q) - mstore(0x3300, prod) + prod := mulmod(mload(0x40c0), prod, f_q) + mstore(0x4160, prod) - prod := mulmod(mload(0x32a0), prod, f_q) - mstore(0x3320, prod) + prod := mulmod(mload(0x4100), prod, f_q) + mstore(0x4180, prod) - prod := mulmod(mload(0x32e0), prod, f_q) - mstore(0x3340, prod) + prod := mulmod(mload(0x4140), prod, f_q) + mstore(0x41a0, prod) } - mstore(0x3380, 32) - mstore(0x33a0, 32) - mstore(0x33c0, 32) - mstore(0x33e0, mload(0x3340)) - mstore(0x3400, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x3420, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x3380, 0xc0, 0x3360, 0x20), 1), success) + mstore(0x41e0, 32) + mstore(0x4200, 32) + mstore(0x4220, 32) + mstore(0x4240, mload(0x41a0)) + mstore(0x4260, 21888242871839275222246405745257275088548364400416034343698204186575808495615) + mstore(0x4280, 21888242871839275222246405745257275088548364400416034343698204186575808495617) + success := and(eq(staticcall(gas(), 0x5, 0x41e0, 0xc0, 0x41c0, 0x20), 1), success) { - let inv := mload(0x3360) + let inv := mload(0x41c0) let v - v := mload(0x32e0) - mstore(13024, mulmod(mload(0x3320), inv, f_q)) + v := mload(0x4140) + mstore(16704, mulmod(mload(0x4180), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x32a0) - mstore(12960, mulmod(mload(0x3300), inv, f_q)) + v := mload(0x4100) + mstore(16640, mulmod(mload(0x4160), inv, f_q)) inv := mulmod(v, inv, f_q) - v := mload(0x3260) - mstore(12896, mulmod(mload(0x3220), inv, f_q)) + v := mload(0x40c0) + mstore(16576, mulmod(mload(0x4080), inv, f_q)) inv := mulmod(v, inv, f_q) - mstore(0x3220, inv) + mstore(0x4080, inv) } - mstore(0x3440, mulmod(mload(0x3240), mload(0x3260), f_q)) - mstore(0x3460, mulmod(mload(0x3280), mload(0x32a0), f_q)) - mstore(0x3480, mulmod(mload(0x32c0), mload(0x32e0), f_q)) - mstore(0x34a0, mulmod(mload(0xa60), mload(0xa60), f_q)) - mstore(0x34c0, mulmod(mload(0x34a0), mload(0xa60), f_q)) - mstore(0x34e0, mulmod(mload(0x34c0), mload(0xa60), f_q)) - mstore(0x3500, mulmod(mload(0x34e0), mload(0xa60), f_q)) - mstore(0x3520, mulmod(mload(0x3500), mload(0xa60), f_q)) - mstore(0x3540, mulmod(mload(0x3520), mload(0xa60), f_q)) - mstore(0x3560, mulmod(mload(0x3540), mload(0xa60), f_q)) - mstore(0x3580, mulmod(mload(0x3560), mload(0xa60), f_q)) - mstore(0x35a0, mulmod(mload(0x3580), mload(0xa60), f_q)) - mstore(0x35c0, mulmod(mload(0xac0), mload(0xac0), f_q)) - mstore(0x35e0, mulmod(mload(0x35c0), mload(0xac0), f_q)) - mstore(0x3600, mulmod(mload(0x35e0), mload(0xac0), f_q)) + mstore(0x42a0, mulmod(mload(0x40a0), mload(0x40c0), f_q)) + mstore(0x42c0, mulmod(mload(0x40e0), mload(0x4100), f_q)) + mstore(0x42e0, mulmod(mload(0x4120), mload(0x4140), f_q)) + mstore(0x4300, mulmod(mload(0xd40), mload(0xd40), f_q)) + mstore(0x4320, mulmod(mload(0x4300), mload(0xd40), f_q)) + mstore(0x4340, mulmod(mload(0x4320), mload(0xd40), f_q)) + mstore(0x4360, mulmod(mload(0x4340), mload(0xd40), f_q)) + mstore(0x4380, mulmod(mload(0x4360), mload(0xd40), f_q)) + mstore(0x43a0, mulmod(mload(0x4380), mload(0xd40), f_q)) + mstore(0x43c0, mulmod(mload(0x43a0), mload(0xd40), f_q)) + mstore(0x43e0, mulmod(mload(0x43c0), mload(0xd40), f_q)) + mstore(0x4400, mulmod(mload(0x43e0), mload(0xd40), f_q)) + mstore(0x4420, mulmod(mload(0xda0), mload(0xda0), f_q)) + mstore(0x4440, mulmod(mload(0x4420), mload(0xda0), f_q)) + mstore(0x4460, mulmod(mload(0x4440), mload(0xda0), f_q)) { - let result := mulmod(mload(0x7e0), mload(0x2c60), f_q) - result := addmod(mulmod(mload(0x800), mload(0x2cc0), f_q), result, f_q) - result := addmod(mulmod(mload(0x820), mload(0x2d20), f_q), result, f_q) - result := addmod(mulmod(mload(0x840), mload(0x2d80), f_q), result, f_q) - mstore(13856, result) + let result := mulmod(mload(0xac0), mload(0x3ac0), f_q) + result := addmod(mulmod(mload(0xae0), mload(0x3b20), f_q), result, f_q) + result := addmod(mulmod(mload(0xb00), mload(0x3b80), f_q), result, f_q) + result := addmod(mulmod(mload(0xb20), mload(0x3be0), f_q), result, f_q) + mstore(17536, result) } - mstore(0x3640, mulmod(mload(0x3620), mload(0x3220), f_q)) - mstore(0x3660, mulmod(sub(f_q, mload(0x3640)), 1, f_q)) - mstore(0x3680, mulmod(mload(0x3660), 1, f_q)) - mstore(0x36a0, mulmod(1, mload(0x3240), f_q)) + mstore(0x44a0, mulmod(mload(0x4480), mload(0x4080), f_q)) + mstore(0x44c0, mulmod(sub(f_q, mload(0x44a0)), 1, f_q)) + mstore(0x44e0, mulmod(mload(0x44c0), 1, f_q)) + mstore(0x4500, mulmod(1, mload(0x40a0), f_q)) { - let result := mulmod(mload(0x960), mload(0x2e60), f_q) - result := addmod(mulmod(mload(0x980), mload(0x2ec0), f_q), result, f_q) - mstore(14016, result) + let result := mulmod(mload(0xc40), mload(0x3cc0), f_q) + result := addmod(mulmod(mload(0xc60), mload(0x3d20), f_q), result, f_q) + mstore(17696, result) } - mstore(0x36e0, mulmod(mload(0x36c0), mload(0x3440), f_q)) - mstore(0x3700, mulmod(sub(f_q, mload(0x36e0)), 1, f_q)) - mstore(0x3720, mulmod(mload(0x36a0), 1, f_q)) + mstore(0x4540, mulmod(mload(0x4520), mload(0x42a0), f_q)) + mstore(0x4560, mulmod(sub(f_q, mload(0x4540)), 1, f_q)) + mstore(0x4580, mulmod(mload(0x4500), 1, f_q)) { - let result := mulmod(mload(0x9a0), mload(0x2e60), f_q) - result := addmod(mulmod(mload(0x9c0), mload(0x2ec0), f_q), result, f_q) - mstore(14144, result) + let result := mulmod(mload(0xc80), mload(0x3cc0), f_q) + result := addmod(mulmod(mload(0xca0), mload(0x3d20), f_q), result, f_q) + mstore(17824, result) } - mstore(0x3760, mulmod(mload(0x3740), mload(0x3440), f_q)) - mstore(0x3780, mulmod(sub(f_q, mload(0x3760)), mload(0xa60), f_q)) - mstore(0x37a0, mulmod(mload(0x36a0), mload(0xa60), f_q)) - mstore(0x37c0, addmod(mload(0x3700), mload(0x3780), f_q)) - mstore(0x37e0, mulmod(mload(0x37c0), mload(0xac0), f_q)) - mstore(0x3800, mulmod(mload(0x3720), mload(0xac0), f_q)) - mstore(0x3820, mulmod(mload(0x37a0), mload(0xac0), f_q)) - mstore(0x3840, addmod(mload(0x3680), mload(0x37e0), f_q)) - mstore(0x3860, mulmod(1, mload(0x3280), f_q)) + mstore(0x45c0, mulmod(mload(0x45a0), mload(0x42a0), f_q)) + mstore(0x45e0, mulmod(sub(f_q, mload(0x45c0)), mload(0xd40), f_q)) + mstore(0x4600, mulmod(mload(0x4500), mload(0xd40), f_q)) + mstore(0x4620, addmod(mload(0x4560), mload(0x45e0), f_q)) + mstore(0x4640, mulmod(mload(0x4620), mload(0xda0), f_q)) + mstore(0x4660, mulmod(mload(0x4580), mload(0xda0), f_q)) + mstore(0x4680, mulmod(mload(0x4600), mload(0xda0), f_q)) + mstore(0x46a0, addmod(mload(0x44e0), mload(0x4640), f_q)) + mstore(0x46c0, mulmod(1, mload(0x40e0), f_q)) { - let result := mulmod(mload(0x9e0), mload(0x2f20), f_q) - result := addmod(mulmod(mload(0xa00), mload(0x2f80), f_q), result, f_q) - mstore(14464, result) + let result := mulmod(mload(0xcc0), mload(0x3d80), f_q) + result := addmod(mulmod(mload(0xce0), mload(0x3de0), f_q), result, f_q) + mstore(18144, result) } - mstore(0x38a0, mulmod(mload(0x3880), mload(0x3460), f_q)) - mstore(0x38c0, mulmod(sub(f_q, mload(0x38a0)), 1, f_q)) - mstore(0x38e0, mulmod(mload(0x3860), 1, f_q)) - mstore(0x3900, mulmod(mload(0x38c0), mload(0x35c0), f_q)) - mstore(0x3920, mulmod(mload(0x38e0), mload(0x35c0), f_q)) - mstore(0x3940, addmod(mload(0x3840), mload(0x3900), f_q)) - mstore(0x3960, mulmod(1, mload(0x32c0), f_q)) + mstore(0x4700, mulmod(mload(0x46e0), mload(0x42c0), f_q)) + mstore(0x4720, mulmod(sub(f_q, mload(0x4700)), 1, f_q)) + mstore(0x4740, mulmod(mload(0x46c0), 1, f_q)) + mstore(0x4760, mulmod(mload(0x4720), mload(0x4420), f_q)) + mstore(0x4780, mulmod(mload(0x4740), mload(0x4420), f_q)) + mstore(0x47a0, addmod(mload(0x46a0), mload(0x4760), f_q)) + mstore(0x47c0, mulmod(1, mload(0x4120), f_q)) { - let result := mulmod(mload(0xa20), mload(0x2fc0), f_q) - mstore(14720, result) + let result := mulmod(mload(0xd00), mload(0x3e20), f_q) + mstore(18400, result) } - mstore(0x39a0, mulmod(mload(0x3980), mload(0x3480), f_q)) - mstore(0x39c0, mulmod(sub(f_q, mload(0x39a0)), 1, f_q)) - mstore(0x39e0, mulmod(mload(0x3960), 1, f_q)) + mstore(0x4800, mulmod(mload(0x47e0), mload(0x42e0), f_q)) + mstore(0x4820, mulmod(sub(f_q, mload(0x4800)), 1, f_q)) + mstore(0x4840, mulmod(mload(0x47c0), 1, f_q)) { - let result := mulmod(mload(0x860), mload(0x2fc0), f_q) - mstore(14848, result) + let result := mulmod(mload(0xb40), mload(0x3e20), f_q) + mstore(18528, result) } - mstore(0x3a20, mulmod(mload(0x3a00), mload(0x3480), f_q)) - mstore(0x3a40, mulmod(sub(f_q, mload(0x3a20)), mload(0xa60), f_q)) - mstore(0x3a60, mulmod(mload(0x3960), mload(0xa60), f_q)) - mstore(0x3a80, addmod(mload(0x39c0), mload(0x3a40), f_q)) + mstore(0x4880, mulmod(mload(0x4860), mload(0x42e0), f_q)) + mstore(0x48a0, mulmod(sub(f_q, mload(0x4880)), mload(0xd40), f_q)) + mstore(0x48c0, mulmod(mload(0x47c0), mload(0xd40), f_q)) + mstore(0x48e0, addmod(mload(0x4820), mload(0x48a0), f_q)) { - let result := mulmod(mload(0x880), mload(0x2fc0), f_q) - mstore(15008, result) + let result := mulmod(mload(0xb60), mload(0x3e20), f_q) + mstore(18688, result) } - mstore(0x3ac0, mulmod(mload(0x3aa0), mload(0x3480), f_q)) - mstore(0x3ae0, mulmod(sub(f_q, mload(0x3ac0)), mload(0x34a0), f_q)) - mstore(0x3b00, mulmod(mload(0x3960), mload(0x34a0), f_q)) - mstore(0x3b20, addmod(mload(0x3a80), mload(0x3ae0), f_q)) + mstore(0x4920, mulmod(mload(0x4900), mload(0x42e0), f_q)) + mstore(0x4940, mulmod(sub(f_q, mload(0x4920)), mload(0x4300), f_q)) + mstore(0x4960, mulmod(mload(0x47c0), mload(0x4300), f_q)) + mstore(0x4980, addmod(mload(0x48e0), mload(0x4940), f_q)) { - let result := mulmod(mload(0x8a0), mload(0x2fc0), f_q) - mstore(15168, result) + let result := mulmod(mload(0xb80), mload(0x3e20), f_q) + mstore(18848, result) } - mstore(0x3b60, mulmod(mload(0x3b40), mload(0x3480), f_q)) - mstore(0x3b80, mulmod(sub(f_q, mload(0x3b60)), mload(0x34c0), f_q)) - mstore(0x3ba0, mulmod(mload(0x3960), mload(0x34c0), f_q)) - mstore(0x3bc0, addmod(mload(0x3b20), mload(0x3b80), f_q)) + mstore(0x49c0, mulmod(mload(0x49a0), mload(0x42e0), f_q)) + mstore(0x49e0, mulmod(sub(f_q, mload(0x49c0)), mload(0x4320), f_q)) + mstore(0x4a00, mulmod(mload(0x47c0), mload(0x4320), f_q)) + mstore(0x4a20, addmod(mload(0x4980), mload(0x49e0), f_q)) { - let result := mulmod(mload(0x8c0), mload(0x2fc0), f_q) - mstore(15328, result) + let result := mulmod(mload(0xba0), mload(0x3e20), f_q) + mstore(19008, result) } - mstore(0x3c00, mulmod(mload(0x3be0), mload(0x3480), f_q)) - mstore(0x3c20, mulmod(sub(f_q, mload(0x3c00)), mload(0x34e0), f_q)) - mstore(0x3c40, mulmod(mload(0x3960), mload(0x34e0), f_q)) - mstore(0x3c60, addmod(mload(0x3bc0), mload(0x3c20), f_q)) + mstore(0x4a60, mulmod(mload(0x4a40), mload(0x42e0), f_q)) + mstore(0x4a80, mulmod(sub(f_q, mload(0x4a60)), mload(0x4340), f_q)) + mstore(0x4aa0, mulmod(mload(0x47c0), mload(0x4340), f_q)) + mstore(0x4ac0, addmod(mload(0x4a20), mload(0x4a80), f_q)) { - let result := mulmod(mload(0x900), mload(0x2fc0), f_q) - mstore(15488, result) + let result := mulmod(mload(0xbe0), mload(0x3e20), f_q) + mstore(19168, result) } - mstore(0x3ca0, mulmod(mload(0x3c80), mload(0x3480), f_q)) - mstore(0x3cc0, mulmod(sub(f_q, mload(0x3ca0)), mload(0x3500), f_q)) - mstore(0x3ce0, mulmod(mload(0x3960), mload(0x3500), f_q)) - mstore(0x3d00, addmod(mload(0x3c60), mload(0x3cc0), f_q)) + mstore(0x4b00, mulmod(mload(0x4ae0), mload(0x42e0), f_q)) + mstore(0x4b20, mulmod(sub(f_q, mload(0x4b00)), mload(0x4360), f_q)) + mstore(0x4b40, mulmod(mload(0x47c0), mload(0x4360), f_q)) + mstore(0x4b60, addmod(mload(0x4ac0), mload(0x4b20), f_q)) { - let result := mulmod(mload(0x920), mload(0x2fc0), f_q) - mstore(15648, result) + let result := mulmod(mload(0xc00), mload(0x3e20), f_q) + mstore(19328, result) } - mstore(0x3d40, mulmod(mload(0x3d20), mload(0x3480), f_q)) - mstore(0x3d60, mulmod(sub(f_q, mload(0x3d40)), mload(0x3520), f_q)) - mstore(0x3d80, mulmod(mload(0x3960), mload(0x3520), f_q)) - mstore(0x3da0, addmod(mload(0x3d00), mload(0x3d60), f_q)) + mstore(0x4ba0, mulmod(mload(0x4b80), mload(0x42e0), f_q)) + mstore(0x4bc0, mulmod(sub(f_q, mload(0x4ba0)), mload(0x4380), f_q)) + mstore(0x4be0, mulmod(mload(0x47c0), mload(0x4380), f_q)) + mstore(0x4c00, addmod(mload(0x4b60), mload(0x4bc0), f_q)) { - let result := mulmod(mload(0x940), mload(0x2fc0), f_q) - mstore(15808, result) + let result := mulmod(mload(0xc20), mload(0x3e20), f_q) + mstore(19488, result) } - mstore(0x3de0, mulmod(mload(0x3dc0), mload(0x3480), f_q)) - mstore(0x3e00, mulmod(sub(f_q, mload(0x3de0)), mload(0x3540), f_q)) - mstore(0x3e20, mulmod(mload(0x3960), mload(0x3540), f_q)) - mstore(0x3e40, addmod(mload(0x3da0), mload(0x3e00), f_q)) - mstore(0x3e60, mulmod(mload(0x2a20), mload(0x32c0), f_q)) - mstore(0x3e80, mulmod(mload(0x2a40), mload(0x32c0), f_q)) - mstore(0x3ea0, mulmod(mload(0x2a60), mload(0x32c0), f_q)) + mstore(0x4c40, mulmod(mload(0x4c20), mload(0x42e0), f_q)) + mstore(0x4c60, mulmod(sub(f_q, mload(0x4c40)), mload(0x43a0), f_q)) + mstore(0x4c80, mulmod(mload(0x47c0), mload(0x43a0), f_q)) + mstore(0x4ca0, addmod(mload(0x4c00), mload(0x4c60), f_q)) + mstore(0x4cc0, mulmod(mload(0x3880), mload(0x4120), f_q)) + mstore(0x4ce0, mulmod(mload(0x38a0), mload(0x4120), f_q)) + mstore(0x4d00, mulmod(mload(0x38c0), mload(0x4120), f_q)) { - let result := mulmod(mload(0x2a80), mload(0x2fc0), f_q) - mstore(16064, result) + let result := mulmod(mload(0x38e0), mload(0x3e20), f_q) + mstore(19744, result) } - mstore(0x3ee0, mulmod(mload(0x3ec0), mload(0x3480), f_q)) - mstore(0x3f00, mulmod(sub(f_q, mload(0x3ee0)), mload(0x3560), f_q)) - mstore(0x3f20, mulmod(mload(0x3960), mload(0x3560), f_q)) - mstore(0x3f40, mulmod(mload(0x3e60), mload(0x3560), f_q)) - mstore(0x3f60, mulmod(mload(0x3e80), mload(0x3560), f_q)) - mstore(0x3f80, mulmod(mload(0x3ea0), mload(0x3560), f_q)) - mstore(0x3fa0, addmod(mload(0x3e40), mload(0x3f00), f_q)) + mstore(0x4d40, mulmod(mload(0x4d20), mload(0x42e0), f_q)) + mstore(0x4d60, mulmod(sub(f_q, mload(0x4d40)), mload(0x43c0), f_q)) + mstore(0x4d80, mulmod(mload(0x47c0), mload(0x43c0), f_q)) + mstore(0x4da0, mulmod(mload(0x4cc0), mload(0x43c0), f_q)) + mstore(0x4dc0, mulmod(mload(0x4ce0), mload(0x43c0), f_q)) + mstore(0x4de0, mulmod(mload(0x4d00), mload(0x43c0), f_q)) + mstore(0x4e00, addmod(mload(0x4ca0), mload(0x4d60), f_q)) { - let result := mulmod(mload(0x8e0), mload(0x2fc0), f_q) - mstore(16320, result) + let result := mulmod(mload(0xbc0), mload(0x3e20), f_q) + mstore(20000, result) } - mstore(0x3fe0, mulmod(mload(0x3fc0), mload(0x3480), f_q)) - mstore(0x4000, mulmod(sub(f_q, mload(0x3fe0)), mload(0x3580), f_q)) - mstore(0x4020, mulmod(mload(0x3960), mload(0x3580), f_q)) - mstore(0x4040, addmod(mload(0x3fa0), mload(0x4000), f_q)) - mstore(0x4060, mulmod(mload(0x4040), mload(0x35e0), f_q)) - mstore(0x4080, mulmod(mload(0x39e0), mload(0x35e0), f_q)) - mstore(0x40a0, mulmod(mload(0x3a60), mload(0x35e0), f_q)) - mstore(0x40c0, mulmod(mload(0x3b00), mload(0x35e0), f_q)) - mstore(0x40e0, mulmod(mload(0x3ba0), mload(0x35e0), f_q)) - mstore(0x4100, mulmod(mload(0x3c40), mload(0x35e0), f_q)) - mstore(0x4120, mulmod(mload(0x3ce0), mload(0x35e0), f_q)) - mstore(0x4140, mulmod(mload(0x3d80), mload(0x35e0), f_q)) - mstore(0x4160, mulmod(mload(0x3e20), mload(0x35e0), f_q)) - mstore(0x4180, mulmod(mload(0x3f20), mload(0x35e0), f_q)) - mstore(0x41a0, mulmod(mload(0x3f40), mload(0x35e0), f_q)) - mstore(0x41c0, mulmod(mload(0x3f60), mload(0x35e0), f_q)) - mstore(0x41e0, mulmod(mload(0x3f80), mload(0x35e0), f_q)) - mstore(0x4200, mulmod(mload(0x4020), mload(0x35e0), f_q)) - mstore(0x4220, addmod(mload(0x3940), mload(0x4060), f_q)) - mstore(0x4240, mulmod(1, mload(0x2e00), f_q)) - mstore(0x4260, mulmod(1, mload(0xb60), f_q)) - mstore(0x4280, 0x0000000000000000000000000000000000000000000000000000000000000001) - mstore(0x42a0, 0x0000000000000000000000000000000000000000000000000000000000000002) - mstore(0x42c0, mload(0x4220)) - success := and(eq(staticcall(gas(), 0x7, 0x4280, 0x60, 0x4280, 0x40), 1), success) - mstore(0x42e0, mload(0x4280)) - mstore(0x4300, mload(0x42a0)) - mstore(0x4320, mload(0x380)) - mstore(0x4340, mload(0x3a0)) - success := and(eq(staticcall(gas(), 0x6, 0x42e0, 0x80, 0x42e0, 0x40), 1), success) - mstore(0x4360, mload(0x560)) - mstore(0x4380, mload(0x580)) - mstore(0x43a0, mload(0x3800)) - success := and(eq(staticcall(gas(), 0x7, 0x4360, 0x60, 0x4360, 0x40), 1), success) - mstore(0x43c0, mload(0x42e0)) - mstore(0x43e0, mload(0x4300)) - mstore(0x4400, mload(0x4360)) - mstore(0x4420, mload(0x4380)) - success := and(eq(staticcall(gas(), 0x6, 0x43c0, 0x80, 0x43c0, 0x40), 1), success) - mstore(0x4440, mload(0x5a0)) - mstore(0x4460, mload(0x5c0)) - mstore(0x4480, mload(0x3820)) - success := and(eq(staticcall(gas(), 0x7, 0x4440, 0x60, 0x4440, 0x40), 1), success) - mstore(0x44a0, mload(0x43c0)) - mstore(0x44c0, mload(0x43e0)) - mstore(0x44e0, mload(0x4440)) - mstore(0x4500, mload(0x4460)) - success := and(eq(staticcall(gas(), 0x6, 0x44a0, 0x80, 0x44a0, 0x40), 1), success) - mstore(0x4520, mload(0x420)) - mstore(0x4540, mload(0x440)) - mstore(0x4560, mload(0x3920)) - success := and(eq(staticcall(gas(), 0x7, 0x4520, 0x60, 0x4520, 0x40), 1), success) - mstore(0x4580, mload(0x44a0)) - mstore(0x45a0, mload(0x44c0)) - mstore(0x45c0, mload(0x4520)) - mstore(0x45e0, mload(0x4540)) - success := and(eq(staticcall(gas(), 0x6, 0x4580, 0x80, 0x4580, 0x40), 1), success) - mstore(0x4600, mload(0x460)) - mstore(0x4620, mload(0x480)) - mstore(0x4640, mload(0x4080)) - success := and(eq(staticcall(gas(), 0x7, 0x4600, 0x60, 0x4600, 0x40), 1), success) - mstore(0x4660, mload(0x4580)) - mstore(0x4680, mload(0x45a0)) - mstore(0x46a0, mload(0x4600)) - mstore(0x46c0, mload(0x4620)) - success := and(eq(staticcall(gas(), 0x6, 0x4660, 0x80, 0x4660, 0x40), 1), success) - mstore(0x46e0, 0x21b14b6e8ea36289961bde7f1d8f191389a815740d09f34f13190341383dfb13) - mstore(0x4700, 0x16740f9c3982e02aeb0cb10086339afaca1bb103d5ae3f114c45a569d60c88ce) - mstore(0x4720, mload(0x40a0)) - success := and(eq(staticcall(gas(), 0x7, 0x46e0, 0x60, 0x46e0, 0x40), 1), success) - mstore(0x4740, mload(0x4660)) - mstore(0x4760, mload(0x4680)) - mstore(0x4780, mload(0x46e0)) - mstore(0x47a0, mload(0x4700)) - success := and(eq(staticcall(gas(), 0x6, 0x4740, 0x80, 0x4740, 0x40), 1), success) - mstore(0x47c0, 0x2eb40e2b0c13a6f4b989cffa9dbc452447bfd9f04a79f6379aefea8c9850a550) - mstore(0x47e0, 0x0efe5496541e2bd648d490f11ad542e1dec3127f818b8065843d0dd81358416c) - mstore(0x4800, mload(0x40c0)) - success := and(eq(staticcall(gas(), 0x7, 0x47c0, 0x60, 0x47c0, 0x40), 1), success) - mstore(0x4820, mload(0x4740)) - mstore(0x4840, mload(0x4760)) - mstore(0x4860, mload(0x47c0)) - mstore(0x4880, mload(0x47e0)) - success := and(eq(staticcall(gas(), 0x6, 0x4820, 0x80, 0x4820, 0x40), 1), success) - mstore(0x48a0, 0x1c6707c73bce576eb360ffcb2fa9a0b17ad541ea0a0e8001439bca524f2f5a43) - mstore(0x48c0, 0x03b899b999df6cf57b7755535b1dc5014a9dbd21d55c31d826d8338dc2fe8722) - mstore(0x48e0, mload(0x40e0)) - success := and(eq(staticcall(gas(), 0x7, 0x48a0, 0x60, 0x48a0, 0x40), 1), success) - mstore(0x4900, mload(0x4820)) - mstore(0x4920, mload(0x4840)) - mstore(0x4940, mload(0x48a0)) - mstore(0x4960, mload(0x48c0)) - success := and(eq(staticcall(gas(), 0x6, 0x4900, 0x80, 0x4900, 0x40), 1), success) - mstore(0x4980, 0x1d309220cdb6694a08a8c77f89984557e19bbda422f41d50b47bf30b30b3dec3) - mstore(0x49a0, 0x138c263b3cbc7de6f5f92f88c44a3e7fc278a4b69008db2340097131e43dbb1a) - mstore(0x49c0, mload(0x4100)) - success := and(eq(staticcall(gas(), 0x7, 0x4980, 0x60, 0x4980, 0x40), 1), success) - mstore(0x49e0, mload(0x4900)) - mstore(0x4a00, mload(0x4920)) - mstore(0x4a20, mload(0x4980)) - mstore(0x4a40, mload(0x49a0)) - success := and(eq(staticcall(gas(), 0x6, 0x49e0, 0x80, 0x49e0, 0x40), 1), success) - mstore(0x4a60, 0x2529da4dfe20ec7564dc8738f2477daf565052f29117d9a2c1a0cbe846ab95fb) - mstore(0x4a80, 0x2a3971e5a786b7e8b0039d1100621af00a8743921a36ef7aafc430b09a5bd279) - mstore(0x4aa0, mload(0x4120)) - success := and(eq(staticcall(gas(), 0x7, 0x4a60, 0x60, 0x4a60, 0x40), 1), success) - mstore(0x4ac0, mload(0x49e0)) - mstore(0x4ae0, mload(0x4a00)) - mstore(0x4b00, mload(0x4a60)) - mstore(0x4b20, mload(0x4a80)) - success := and(eq(staticcall(gas(), 0x6, 0x4ac0, 0x80, 0x4ac0, 0x40), 1), success) - mstore(0x4b40, 0x132e1a4125c783ea4817ea96d967c5f06a49933ca71f7e99f7be022ef1e3ca35) - mstore(0x4b60, 0x0eb726ae10479119d87b2e1d0d2b72db88506d263ae939b2154b0f3f5c7012f7) - mstore(0x4b80, mload(0x4140)) - success := and(eq(staticcall(gas(), 0x7, 0x4b40, 0x60, 0x4b40, 0x40), 1), success) - mstore(0x4ba0, mload(0x4ac0)) - mstore(0x4bc0, mload(0x4ae0)) - mstore(0x4be0, mload(0x4b40)) - mstore(0x4c00, mload(0x4b60)) - success := and(eq(staticcall(gas(), 0x6, 0x4ba0, 0x80, 0x4ba0, 0x40), 1), success) - mstore(0x4c20, 0x1bc70a16efa4ef34c9ee86dc04d041fc8430240113b09ef71d5bbb8b685af6b7) - mstore(0x4c40, 0x25064309a3b7ab3efd593b9e6c2f1294b50c12e237412186d7af94b1591dc937) - mstore(0x4c60, mload(0x4160)) - success := and(eq(staticcall(gas(), 0x7, 0x4c20, 0x60, 0x4c20, 0x40), 1), success) - mstore(0x4c80, mload(0x4ba0)) - mstore(0x4ca0, mload(0x4bc0)) - mstore(0x4cc0, mload(0x4c20)) - mstore(0x4ce0, mload(0x4c40)) - success := and(eq(staticcall(gas(), 0x6, 0x4c80, 0x80, 0x4c80, 0x40), 1), success) - mstore(0x4d00, mload(0x680)) - mstore(0x4d20, mload(0x6a0)) - mstore(0x4d40, mload(0x4180)) - success := and(eq(staticcall(gas(), 0x7, 0x4d00, 0x60, 0x4d00, 0x40), 1), success) - mstore(0x4d60, mload(0x4c80)) - mstore(0x4d80, mload(0x4ca0)) - mstore(0x4da0, mload(0x4d00)) - mstore(0x4dc0, mload(0x4d20)) - success := and(eq(staticcall(gas(), 0x6, 0x4d60, 0x80, 0x4d60, 0x40), 1), success) - mstore(0x4de0, mload(0x6c0)) - mstore(0x4e00, mload(0x6e0)) - mstore(0x4e20, mload(0x41a0)) - success := and(eq(staticcall(gas(), 0x7, 0x4de0, 0x60, 0x4de0, 0x40), 1), success) - mstore(0x4e40, mload(0x4d60)) - mstore(0x4e60, mload(0x4d80)) - mstore(0x4e80, mload(0x4de0)) - mstore(0x4ea0, mload(0x4e00)) - success := and(eq(staticcall(gas(), 0x6, 0x4e40, 0x80, 0x4e40, 0x40), 1), success) - mstore(0x4ec0, mload(0x700)) - mstore(0x4ee0, mload(0x720)) - mstore(0x4f00, mload(0x41c0)) - success := and(eq(staticcall(gas(), 0x7, 0x4ec0, 0x60, 0x4ec0, 0x40), 1), success) - mstore(0x4f20, mload(0x4e40)) - mstore(0x4f40, mload(0x4e60)) - mstore(0x4f60, mload(0x4ec0)) - mstore(0x4f80, mload(0x4ee0)) - success := and(eq(staticcall(gas(), 0x6, 0x4f20, 0x80, 0x4f20, 0x40), 1), success) - mstore(0x4fa0, mload(0x740)) - mstore(0x4fc0, mload(0x760)) - mstore(0x4fe0, mload(0x41e0)) - success := and(eq(staticcall(gas(), 0x7, 0x4fa0, 0x60, 0x4fa0, 0x40), 1), success) - mstore(0x5000, mload(0x4f20)) - mstore(0x5020, mload(0x4f40)) - mstore(0x5040, mload(0x4fa0)) - mstore(0x5060, mload(0x4fc0)) - success := and(eq(staticcall(gas(), 0x6, 0x5000, 0x80, 0x5000, 0x40), 1), success) - mstore(0x5080, mload(0x5e0)) - mstore(0x50a0, mload(0x600)) - mstore(0x50c0, mload(0x4200)) - success := and(eq(staticcall(gas(), 0x7, 0x5080, 0x60, 0x5080, 0x40), 1), success) - mstore(0x50e0, mload(0x5000)) - mstore(0x5100, mload(0x5020)) + mstore(0x4e40, mulmod(mload(0x4e20), mload(0x42e0), f_q)) + mstore(0x4e60, mulmod(sub(f_q, mload(0x4e40)), mload(0x43e0), f_q)) + mstore(0x4e80, mulmod(mload(0x47c0), mload(0x43e0), f_q)) + mstore(0x4ea0, addmod(mload(0x4e00), mload(0x4e60), f_q)) + mstore(0x4ec0, mulmod(mload(0x4ea0), mload(0x4440), f_q)) + mstore(0x4ee0, mulmod(mload(0x4840), mload(0x4440), f_q)) + mstore(0x4f00, mulmod(mload(0x48c0), mload(0x4440), f_q)) + mstore(0x4f20, mulmod(mload(0x4960), mload(0x4440), f_q)) + mstore(0x4f40, mulmod(mload(0x4a00), mload(0x4440), f_q)) + mstore(0x4f60, mulmod(mload(0x4aa0), mload(0x4440), f_q)) + mstore(0x4f80, mulmod(mload(0x4b40), mload(0x4440), f_q)) + mstore(0x4fa0, mulmod(mload(0x4be0), mload(0x4440), f_q)) + mstore(0x4fc0, mulmod(mload(0x4c80), mload(0x4440), f_q)) + mstore(0x4fe0, mulmod(mload(0x4d80), mload(0x4440), f_q)) + mstore(0x5000, mulmod(mload(0x4da0), mload(0x4440), f_q)) + mstore(0x5020, mulmod(mload(0x4dc0), mload(0x4440), f_q)) + mstore(0x5040, mulmod(mload(0x4de0), mload(0x4440), f_q)) + mstore(0x5060, mulmod(mload(0x4e80), mload(0x4440), f_q)) + mstore(0x5080, addmod(mload(0x47a0), mload(0x4ec0), f_q)) + mstore(0x50a0, mulmod(1, mload(0x3c60), f_q)) + mstore(0x50c0, mulmod(1, mload(0xe40), f_q)) + mstore(0x50e0, 0x0000000000000000000000000000000000000000000000000000000000000001) + mstore(0x5100, 0x0000000000000000000000000000000000000000000000000000000000000002) mstore(0x5120, mload(0x5080)) - mstore(0x5140, mload(0x50a0)) - success := and(eq(staticcall(gas(), 0x6, 0x50e0, 0x80, 0x50e0, 0x40), 1), success) - mstore(0x5160, mload(0xb00)) - mstore(0x5180, mload(0xb20)) - mstore(0x51a0, sub(f_q, mload(0x4240))) - success := and(eq(staticcall(gas(), 0x7, 0x5160, 0x60, 0x5160, 0x40), 1), success) - mstore(0x51c0, mload(0x50e0)) - mstore(0x51e0, mload(0x5100)) - mstore(0x5200, mload(0x5160)) - mstore(0x5220, mload(0x5180)) - success := and(eq(staticcall(gas(), 0x6, 0x51c0, 0x80, 0x51c0, 0x40), 1), success) - mstore(0x5240, mload(0xba0)) - mstore(0x5260, mload(0xbc0)) - mstore(0x5280, mload(0x4260)) - success := and(eq(staticcall(gas(), 0x7, 0x5240, 0x60, 0x5240, 0x40), 1), success) - mstore(0x52a0, mload(0x51c0)) - mstore(0x52c0, mload(0x51e0)) - mstore(0x52e0, mload(0x5240)) - mstore(0x5300, mload(0x5260)) - success := and(eq(staticcall(gas(), 0x6, 0x52a0, 0x80, 0x52a0, 0x40), 1), success) - mstore(0x5320, mload(0x52a0)) - mstore(0x5340, mload(0x52c0)) - mstore(0x5360, mload(0xba0)) - mstore(0x5380, mload(0xbc0)) - mstore(0x53a0, mload(0xbe0)) - mstore(0x53c0, mload(0xc00)) - mstore(0x53e0, mload(0xc20)) - mstore(0x5400, mload(0xc40)) - mstore(0x5420, keccak256(0x5320, 256)) - mstore(21568, mod(mload(21536), f_q)) - mstore(0x5460, mulmod(mload(0x5440), mload(0x5440), f_q)) - mstore(0x5480, mulmod(1, mload(0x5440), f_q)) - mstore(0x54a0, mload(0x53a0)) - mstore(0x54c0, mload(0x53c0)) - mstore(0x54e0, mload(0x5480)) - success := and(eq(staticcall(gas(), 0x7, 0x54a0, 0x60, 0x54a0, 0x40), 1), success) - mstore(0x5500, mload(0x5320)) - mstore(0x5520, mload(0x5340)) - mstore(0x5540, mload(0x54a0)) - mstore(0x5560, mload(0x54c0)) - success := and(eq(staticcall(gas(), 0x6, 0x5500, 0x80, 0x5500, 0x40), 1), success) - mstore(0x5580, mload(0x53e0)) - mstore(0x55a0, mload(0x5400)) - mstore(0x55c0, mload(0x5480)) - success := and(eq(staticcall(gas(), 0x7, 0x5580, 0x60, 0x5580, 0x40), 1), success) - mstore(0x55e0, mload(0x5360)) - mstore(0x5600, mload(0x5380)) - mstore(0x5620, mload(0x5580)) - mstore(0x5640, mload(0x55a0)) - success := and(eq(staticcall(gas(), 0x6, 0x55e0, 0x80, 0x55e0, 0x40), 1), success) - mstore(0x5660, mload(0x5500)) - mstore(0x5680, mload(0x5520)) - mstore(0x56a0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) - mstore(0x56c0, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x56e0, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0x5700, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - mstore(0x5720, mload(0x55e0)) - mstore(0x5740, mload(0x5600)) - mstore(0x5760, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) - mstore(0x5780, 0x2ae0c8c3a090f7200ff398ee9845bbae8f8c1445ae7b632212775f60a0e21600) - mstore(0x57a0, 0x190fa476a5b352809ed41d7a0d7fe12b8f685e3c12a6d83855dba27aaf469643) - mstore(0x57c0, 0x1c0a500618907df9e4273d5181e31088deb1f05132de037cbfe73888f97f77c9) - success := and(eq(staticcall(gas(), 0x8, 0x5660, 0x180, 0x5660, 0x20), 1), success) - success := and(eq(mload(0x5660), 1), success) + success := and(eq(staticcall(gas(), 0x7, 0x50e0, 0x60, 0x50e0, 0x40), 1), success) + mstore(0x5140, mload(0x50e0)) + mstore(0x5160, mload(0x5100)) + mstore(0x5180, mload(0x660)) + mstore(0x51a0, mload(0x680)) + success := and(eq(staticcall(gas(), 0x6, 0x5140, 0x80, 0x5140, 0x40), 1), success) + mstore(0x51c0, mload(0x840)) + mstore(0x51e0, mload(0x860)) + mstore(0x5200, mload(0x4660)) + success := and(eq(staticcall(gas(), 0x7, 0x51c0, 0x60, 0x51c0, 0x40), 1), success) + mstore(0x5220, mload(0x5140)) + mstore(0x5240, mload(0x5160)) + mstore(0x5260, mload(0x51c0)) + mstore(0x5280, mload(0x51e0)) + success := and(eq(staticcall(gas(), 0x6, 0x5220, 0x80, 0x5220, 0x40), 1), success) + mstore(0x52a0, mload(0x880)) + mstore(0x52c0, mload(0x8a0)) + mstore(0x52e0, mload(0x4680)) + success := and(eq(staticcall(gas(), 0x7, 0x52a0, 0x60, 0x52a0, 0x40), 1), success) + mstore(0x5300, mload(0x5220)) + mstore(0x5320, mload(0x5240)) + mstore(0x5340, mload(0x52a0)) + mstore(0x5360, mload(0x52c0)) + success := and(eq(staticcall(gas(), 0x6, 0x5300, 0x80, 0x5300, 0x40), 1), success) + mstore(0x5380, mload(0x700)) + mstore(0x53a0, mload(0x720)) + mstore(0x53c0, mload(0x4780)) + success := and(eq(staticcall(gas(), 0x7, 0x5380, 0x60, 0x5380, 0x40), 1), success) + mstore(0x53e0, mload(0x5300)) + mstore(0x5400, mload(0x5320)) + mstore(0x5420, mload(0x5380)) + mstore(0x5440, mload(0x53a0)) + success := and(eq(staticcall(gas(), 0x6, 0x53e0, 0x80, 0x53e0, 0x40), 1), success) + mstore(0x5460, mload(0x740)) + mstore(0x5480, mload(0x760)) + mstore(0x54a0, mload(0x4ee0)) + success := and(eq(staticcall(gas(), 0x7, 0x5460, 0x60, 0x5460, 0x40), 1), success) + mstore(0x54c0, mload(0x53e0)) + mstore(0x54e0, mload(0x5400)) + mstore(0x5500, mload(0x5460)) + mstore(0x5520, mload(0x5480)) + success := and(eq(staticcall(gas(), 0x6, 0x54c0, 0x80, 0x54c0, 0x40), 1), success) + mstore(0x5540, 0x10903f13ba202328af3a3e13021579d67557dcf3bfe705d1b7989ed2f4e4c2c4) + mstore(0x5560, 0x190b6fb9d28400025be71d2314d98e4e9a8eeb0de7130496f1b622d55abf6ff6) + mstore(0x5580, mload(0x4f00)) + success := and(eq(staticcall(gas(), 0x7, 0x5540, 0x60, 0x5540, 0x40), 1), success) + mstore(0x55a0, mload(0x54c0)) + mstore(0x55c0, mload(0x54e0)) + mstore(0x55e0, mload(0x5540)) + mstore(0x5600, mload(0x5560)) + success := and(eq(staticcall(gas(), 0x6, 0x55a0, 0x80, 0x55a0, 0x40), 1), success) + mstore(0x5620, 0x2eb40e2b0c13a6f4b989cffa9dbc452447bfd9f04a79f6379aefea8c9850a550) + mstore(0x5640, 0x0efe5496541e2bd648d490f11ad542e1dec3127f818b8065843d0dd81358416c) + mstore(0x5660, mload(0x4f20)) + success := and(eq(staticcall(gas(), 0x7, 0x5620, 0x60, 0x5620, 0x40), 1), success) + mstore(0x5680, mload(0x55a0)) + mstore(0x56a0, mload(0x55c0)) + mstore(0x56c0, mload(0x5620)) + mstore(0x56e0, mload(0x5640)) + success := and(eq(staticcall(gas(), 0x6, 0x5680, 0x80, 0x5680, 0x40), 1), success) + mstore(0x5700, 0x18dca54423b6fa7932c92beff56ce260a3c726e3613c92fe0843d86b92199bfd) + mstore(0x5720, 0x0f6641ca942a4541625b14adb25ab0fd978060c98d01eb1b036fcdb1b8f77be1) + mstore(0x5740, mload(0x4f40)) + success := and(eq(staticcall(gas(), 0x7, 0x5700, 0x60, 0x5700, 0x40), 1), success) + mstore(0x5760, mload(0x5680)) + mstore(0x5780, mload(0x56a0)) + mstore(0x57a0, mload(0x5700)) + mstore(0x57c0, mload(0x5720)) + success := and(eq(staticcall(gas(), 0x6, 0x5760, 0x80, 0x5760, 0x40), 1), success) + mstore(0x57e0, 0x23809cc9d17a8cb32381764c6234d3038148b8bec5d8573fb3470486feedd968) + mstore(0x5800, 0x1debabb870ec20dc2c4df55cbd88205b6dd234ad5805faf3a72e14b6f934f238) + mstore(0x5820, mload(0x4f60)) + success := and(eq(staticcall(gas(), 0x7, 0x57e0, 0x60, 0x57e0, 0x40), 1), success) + mstore(0x5840, mload(0x5760)) + mstore(0x5860, mload(0x5780)) + mstore(0x5880, mload(0x57e0)) + mstore(0x58a0, mload(0x5800)) + success := and(eq(staticcall(gas(), 0x6, 0x5840, 0x80, 0x5840, 0x40), 1), success) + mstore(0x58c0, 0x2b65ba9ff654f7feb0cc2b9609adc1e982ca4e01f037521c7c4196277deea800) + mstore(0x58e0, 0x0cf0f87bb9200057e5f6331cd1d7b4dc4dd1cf1fcfceb3a7eb36cad45ba6ea02) + mstore(0x5900, mload(0x4f80)) + success := and(eq(staticcall(gas(), 0x7, 0x58c0, 0x60, 0x58c0, 0x40), 1), success) + mstore(0x5920, mload(0x5840)) + mstore(0x5940, mload(0x5860)) + mstore(0x5960, mload(0x58c0)) + mstore(0x5980, mload(0x58e0)) + success := and(eq(staticcall(gas(), 0x6, 0x5920, 0x80, 0x5920, 0x40), 1), success) + mstore(0x59a0, 0x23f7bb2254ad1c43019cf50cb00a9c7354bc55d444647ce7d5345e4db3eac1ba) + mstore(0x59c0, 0x14505e073a9e6cb05d697b73577eb7cda821bff988201b7e37ccb224eba4d9d2) + mstore(0x59e0, mload(0x4fa0)) + success := and(eq(staticcall(gas(), 0x7, 0x59a0, 0x60, 0x59a0, 0x40), 1), success) + mstore(0x5a00, mload(0x5920)) + mstore(0x5a20, mload(0x5940)) + mstore(0x5a40, mload(0x59a0)) + mstore(0x5a60, mload(0x59c0)) + success := and(eq(staticcall(gas(), 0x6, 0x5a00, 0x80, 0x5a00, 0x40), 1), success) + mstore(0x5a80, 0x23eb59f4643a8f86f1bb54ebc274b4810126c9c2fae5d8de472ef0566afaa14c) + mstore(0x5aa0, 0x13b28c9220c717cac368247913075f4bb8da09cd9d0145c1292810854089c39c) + mstore(0x5ac0, mload(0x4fc0)) + success := and(eq(staticcall(gas(), 0x7, 0x5a80, 0x60, 0x5a80, 0x40), 1), success) + mstore(0x5ae0, mload(0x5a00)) + mstore(0x5b00, mload(0x5a20)) + mstore(0x5b20, mload(0x5a80)) + mstore(0x5b40, mload(0x5aa0)) + success := and(eq(staticcall(gas(), 0x6, 0x5ae0, 0x80, 0x5ae0, 0x40), 1), success) + mstore(0x5b60, mload(0x960)) + mstore(0x5b80, mload(0x980)) + mstore(0x5ba0, mload(0x4fe0)) + success := and(eq(staticcall(gas(), 0x7, 0x5b60, 0x60, 0x5b60, 0x40), 1), success) + mstore(0x5bc0, mload(0x5ae0)) + mstore(0x5be0, mload(0x5b00)) + mstore(0x5c00, mload(0x5b60)) + mstore(0x5c20, mload(0x5b80)) + success := and(eq(staticcall(gas(), 0x6, 0x5bc0, 0x80, 0x5bc0, 0x40), 1), success) + mstore(0x5c40, mload(0x9a0)) + mstore(0x5c60, mload(0x9c0)) + mstore(0x5c80, mload(0x5000)) + success := and(eq(staticcall(gas(), 0x7, 0x5c40, 0x60, 0x5c40, 0x40), 1), success) + mstore(0x5ca0, mload(0x5bc0)) + mstore(0x5cc0, mload(0x5be0)) + mstore(0x5ce0, mload(0x5c40)) + mstore(0x5d00, mload(0x5c60)) + success := and(eq(staticcall(gas(), 0x6, 0x5ca0, 0x80, 0x5ca0, 0x40), 1), success) + mstore(0x5d20, mload(0x9e0)) + mstore(0x5d40, mload(0xa00)) + mstore(0x5d60, mload(0x5020)) + success := and(eq(staticcall(gas(), 0x7, 0x5d20, 0x60, 0x5d20, 0x40), 1), success) + mstore(0x5d80, mload(0x5ca0)) + mstore(0x5da0, mload(0x5cc0)) + mstore(0x5dc0, mload(0x5d20)) + mstore(0x5de0, mload(0x5d40)) + success := and(eq(staticcall(gas(), 0x6, 0x5d80, 0x80, 0x5d80, 0x40), 1), success) + mstore(0x5e00, mload(0xa20)) + mstore(0x5e20, mload(0xa40)) + mstore(0x5e40, mload(0x5040)) + success := and(eq(staticcall(gas(), 0x7, 0x5e00, 0x60, 0x5e00, 0x40), 1), success) + mstore(0x5e60, mload(0x5d80)) + mstore(0x5e80, mload(0x5da0)) + mstore(0x5ea0, mload(0x5e00)) + mstore(0x5ec0, mload(0x5e20)) + success := and(eq(staticcall(gas(), 0x6, 0x5e60, 0x80, 0x5e60, 0x40), 1), success) + mstore(0x5ee0, mload(0x8c0)) + mstore(0x5f00, mload(0x8e0)) + mstore(0x5f20, mload(0x5060)) + success := and(eq(staticcall(gas(), 0x7, 0x5ee0, 0x60, 0x5ee0, 0x40), 1), success) + mstore(0x5f40, mload(0x5e60)) + mstore(0x5f60, mload(0x5e80)) + mstore(0x5f80, mload(0x5ee0)) + mstore(0x5fa0, mload(0x5f00)) + success := and(eq(staticcall(gas(), 0x6, 0x5f40, 0x80, 0x5f40, 0x40), 1), success) + mstore(0x5fc0, mload(0xde0)) + mstore(0x5fe0, mload(0xe00)) + mstore(0x6000, sub(f_q, mload(0x50a0))) + success := and(eq(staticcall(gas(), 0x7, 0x5fc0, 0x60, 0x5fc0, 0x40), 1), success) + mstore(0x6020, mload(0x5f40)) + mstore(0x6040, mload(0x5f60)) + mstore(0x6060, mload(0x5fc0)) + mstore(0x6080, mload(0x5fe0)) + success := and(eq(staticcall(gas(), 0x6, 0x6020, 0x80, 0x6020, 0x40), 1), success) + mstore(0x60a0, mload(0xe80)) + mstore(0x60c0, mload(0xea0)) + mstore(0x60e0, mload(0x50c0)) + success := and(eq(staticcall(gas(), 0x7, 0x60a0, 0x60, 0x60a0, 0x40), 1), success) + mstore(0x6100, mload(0x6020)) + mstore(0x6120, mload(0x6040)) + mstore(0x6140, mload(0x60a0)) + mstore(0x6160, mload(0x60c0)) + success := and(eq(staticcall(gas(), 0x6, 0x6100, 0x80, 0x6100, 0x40), 1), success) + mstore(0x6180, mload(0x6100)) + mstore(0x61a0, mload(0x6120)) + mstore(0x61c0, mload(0xe80)) + mstore(0x61e0, mload(0xea0)) + mstore(0x6200, mload(0xec0)) + mstore(0x6220, mload(0xee0)) + mstore(0x6240, mload(0xf00)) + mstore(0x6260, mload(0xf20)) + mstore(0x6280, keccak256(0x6180, 256)) + mstore(25248, mod(mload(25216), f_q)) + mstore(0x62c0, mulmod(mload(0x62a0), mload(0x62a0), f_q)) + mstore(0x62e0, mulmod(1, mload(0x62a0), f_q)) + mstore(0x6300, mload(0x6200)) + mstore(0x6320, mload(0x6220)) + mstore(0x6340, mload(0x62e0)) + success := and(eq(staticcall(gas(), 0x7, 0x6300, 0x60, 0x6300, 0x40), 1), success) + mstore(0x6360, mload(0x6180)) + mstore(0x6380, mload(0x61a0)) + mstore(0x63a0, mload(0x6300)) + mstore(0x63c0, mload(0x6320)) + success := and(eq(staticcall(gas(), 0x6, 0x6360, 0x80, 0x6360, 0x40), 1), success) + mstore(0x63e0, mload(0x6240)) + mstore(0x6400, mload(0x6260)) + mstore(0x6420, mload(0x62e0)) + success := and(eq(staticcall(gas(), 0x7, 0x63e0, 0x60, 0x63e0, 0x40), 1), success) + mstore(0x6440, mload(0x61c0)) + mstore(0x6460, mload(0x61e0)) + mstore(0x6480, mload(0x63e0)) + mstore(0x64a0, mload(0x6400)) + success := and(eq(staticcall(gas(), 0x6, 0x6440, 0x80, 0x6440, 0x40), 1), success) + mstore(0x64c0, mload(0x6360)) + mstore(0x64e0, mload(0x6380)) + mstore(0x6500, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) + mstore(0x6520, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x6540, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0x6560, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + mstore(0x6580, mload(0x6440)) + mstore(0x65a0, mload(0x6460)) + mstore(0x65c0, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) + mstore(0x65e0, 0x2ae0c8c3a090f7200ff398ee9845bbae8f8c1445ae7b632212775f60a0e21600) + mstore(0x6600, 0x190fa476a5b352809ed41d7a0d7fe12b8f685e3c12a6d83855dba27aaf469643) + mstore(0x6620, 0x1c0a500618907df9e4273d5181e31088deb1f05132de037cbfe73888f97f77c9) + success := and(eq(staticcall(gas(), 0x8, 0x64c0, 0x180, 0x64c0, 0x20), 1), success) + success := and(eq(mload(0x64c0), 1), success) // Revert if anything fails if iszero(success) { revert(0, 0) } diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index 62053b3..9648afa 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -29,7 +29,7 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// @dev The leaf verifier commitment. This value is set by OpenVM. bytes32 public constant LEAF_EXE_COMMIT = - bytes32(0x0000000000000000000000000000000000000000000000000000000000000000); + bytes32(0x0071628bff0dcb64201f77ff5c7d869c7073b842e3dadf9e618e8673ef671bfd); string public constant OPENVM_VERSION = "v1.0.0"; @@ -103,7 +103,9 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// @solidity memory-safe-assembly assembly { proofPtr := mload(0x40) - // Allocate the memory as a safety measure + // Allocate the memory as a safety measure. We know that this is the + // only memory allocation that occurs in the call frame, so we don't + // need to clean the allocated memory. mstore(0x40, add(proofPtr, fullProofLength)) // Copy the KZG accumulators (length 0x180) into the beginning of diff --git a/test/OpenVmHalo2Verifier.t.sol b/test/OpenVmHalo2Verifier.t.sol index ecdf91f..09cad77 100644 --- a/test/OpenVmHalo2Verifier.t.sol +++ b/test/OpenVmHalo2Verifier.t.sol @@ -6,20 +6,20 @@ import { Test, console2, safeconsole as console } from "forge-std/Test.sol"; contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { bytes partialProof; - bytes32 appExeCommit = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - bytes32 guestPvsHash = 0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; + + bytes private constant kzgAccumulators = + hex"000000000000000000000000000000000000000000d1437a9bb9ac3c1a16992c00000000000000000000000000000000000000000021a9ab5617c2d7d6ccf9af0000000000000000000000000000000000000000000008ba19dc0f462a92dc0900000000000000000000000000000000000000000025694ae0246cb4b406b0970000000000000000000000000000000000000000004ec055f528761bb24e7098000000000000000000000000000000000000000000000b0dcb882b8af688ddc4000000000000000000000000000000000000000000e7eb1b7903923438cc8b54000000000000000000000000000000000000000000af1197617343468c85c9d6000000000000000000000000000000000000000000002d22b55036423bb4c266000000000000000000000000000000000000000000280255aa13e24534841355000000000000000000000000000000000000000000bcffb01f01132cb2ea1eb20000000000000000000000000000000000000000000000c69662a512b8d21501"; + bytes private constant suffix = + hex"2775c493e84b4ea63465d98b4666134e274cd3d66eaf6b59a6dbeddb594de2091ae1f48e567caf12f2b888d339ba7f99ab4603cf008397276d562f67ad058c9410cc4bdb94e881438afc407093d722a48089d5784437d52a4bafc6e9819bf4e00bec156cd36cb7f7883d9ed0196b4f2ce825b2b579a08ec670d0b8708d476f610d620bbaac86de1c27ad5dfce81d3479c72e603025c1b3dc30559150467c1680022031fdd52469b8884250650abf7fb3c5a38018c285e3412d266f937aa0ef2c0d07838c09f45be93e8c0f653eddcb3565cb6c124dca1433684aba18f8cb58802af17390906939ca5d7f37bcd2f02f5138c9afcdd6ebe543dbbee0f775e1c40d2722ddbd7b4c08aba7a4f7ebd96b801afb946e453e69ea9ce118d47f6408b21914042c2f38028b0c160541d4fadb04a1a5b647cc8569247377be8202a468b1cb279b82a31e702f57385e36f7734f6b391d6a50fd14d09e0c30eab5cc4c8c6e5029bd146dea01b1b317ec886eaef10e4752867f6a0f88f20ba6e23b5a842e930d2883c12cbcf1306cedc382aa0207cb33cf01435390660f944e69687fb16ce7180c474460f997bd0efff02754973fd493cda33c7b364b89997409dbac35ca54f01b74498360f00fbf7092e589de2020641a954a27c92b862303dad302f258c9530c729d2baeccb32dbce5bf1ddc0758529f020b75806fd0b3cdf61670d88027e5028badbe0381b6eb6b68955284be0f85de4865ffcde32a8ce08182fe3cd433e91074bce48f7cb8295e8af1d1d9ccacce4490506e7adc9b29e88aba93f1b207ed28328bfe9f6cf3b6d3547bdb430f48898f78fa6c3e18234c855e0a52bb78c5d0131533e4a471a039c7cab0f266daf91f1834589a624400edc4398e7e828f582c07aa42c25d1b672cfb45eac915f8c4dbafd3205c29100c2992d45affacb9f19020535efdc88776c1c3aca1260df676ddfe99782c48ec29d38eea6b12f06d536702d6164196e22b4e348c9afe0c8f5572b4651c01cc00314a2291cc27e1763a762c1e3fbb8e98f1b99abdfdfa786508d7cc44df1d5d02f934bf3014a36090e464273f4d8c1b7877eb0b290223dac7d9cf81ec17f791d11aa4a1b68f9693796e7b0a8e03eceb1e616b44d174568825ffaca4cbeb4c4aab4e0e9c6723385e3cdeca273c175f927edc0111bc70e928bb1082a6b835e3ce1e3ed65c0dff86922d451806fb038d5521c9ba7fa99d60dc5f69d561b00799c6daa0ea4e43a3d33a456b2b19ed25f31ceebf094342dc5da14ef72395949b799483d059a7e65a246a8f45ad1c48b3b8a76fb17dc5a80bfe5d7900a9870397d653644d404cde9ab38c8b4aea0d3e6682eb89cfb1f50e1e5a8140543232c48d76b947416ee9950c0f5dc11b200e5bf99a7434f8174b56d22164d8b76bf640310d52d589a046d53b117d2bf3f9112b7a7fce911175c9801442086a89b0973b4d957ae8e947879c51835ef64fa027cbfabaddc03997a2b92fd79f0973f694696f56543e83a8f19119473ebff740014caa87269b99c0adf301358c2f3776c760068bf7b596de58dc752d758e7ed3224cbc8d6edda7bc8c4547db51d9c78ce44a178a6e03cae750dfbe643acd08972f5ae0952cd44c62797787661c879af3a7330a53b23bcdd93aa7e3d61039d95622a882f24f6ecd1fc5400d4c8abf867ec3d5a2de8388fa8d6d1026227c6716a002cbf4a89570842bd00a4c0fda5a055473d973f1115d49e77fef7a69fee3131803e935eaeea4bf493566a48ab82e4bf8c3552cc58376974341021ce82f09f4081ddbcbab8b9c65979a5643d145e8fd093cd3769a353c8c9f58830719ec0683c422b28a02f74ca326db6911af0e9bc67cb42007a65ad3e8942d823ba0c31ae2c322f45f1f54aca1193f948c49885fee5960695994cb73b2f572a8ac2be49192b5"; + bytes32 appExeCommit = bytes32(0x0063802e02e9f8db01adecac53ea5c1db95bdbacf7800b9e29e27527cfd2613b); + bytes32 guestPvsHash = bytes32(uint256(0)); uint256 private constant FULL_PROOF_WORDS = (12 + 2 + 32 + 43); uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + 32 + 43) * 32; function setUp() public { - partialProof = new bytes(55 * 32); - for (uint256 i = 0; i < 55; i++) { - for (uint256 j = 0; j < 32; j++) { - partialProof[i * 32 + j] = bytes1(uint8(i)); - } - } + partialProof = abi.encodePacked(kzgAccumulators, suffix); } function test_verifyProof() public view { From 66dc4409ce78e8529814adf59522dd6bb5a13b56 Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Thu, 20 Mar 2025 23:57:42 -0400 Subject: [PATCH 11/15] docs: update docs --- src/OpenVmHalo2Verifier.sol | 40 ++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index 9648afa..f5bc001 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -31,6 +31,7 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { bytes32 public constant LEAF_EXE_COMMIT = bytes32(0x0071628bff0dcb64201f77ff5c7d869c7073b842e3dadf9e618e8673ef671bfd); + /// @dev The version of OpenVM that generated the proof. string public constant OPENVM_VERSION = "v1.0.0"; /// @notice A wrapper that constructs the proof into the right format for @@ -73,22 +74,35 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { } } + /// @dev The assembly code should perform the same function as the following + /// solidity code: + // + /// ```solidity + /// bytes memory proof = + /// abi.encodePacked(partialProof[0:0x180], appExeCommit, leafExeCommit, guestPvsPayload, partialProof[0x180:]); + /// ``` + // + /// where `guestPvsPayload` is a memory payload with each byte in + /// `guestPvs` separated into its own `bytes32` word. + /// + /// This function does not clean the memory it allocates. Since it is the + /// only memory allocation that occurs in the call frame, we know that the + /// memory was not written to before. + /// + /// @param guestPvs The PVs revealed by the OpenVM guest program. + /// @param partialProof All components of the proof except the Guest PVs, + /// leaf and app exe commits. The expected format is: + /// `abi.encodePacked(kzgAccumulators, proofSuffix)` + /// @param appExeCommit The commitment to the OpenVM application executable + /// whose execution is being verified. + /// + /// @return proofPtr Memory pointer to the beginning of the constructed + /// proof. function _constructProof(bytes calldata guestPvs, bytes calldata partialProof, bytes32 appExeCommit) internal pure returns (MemoryPointer proofPtr) { - // The assembly code should perform the same function as the following - // solidity code: - // - // ```solidity - // bytes memory proof = - // abi.encodePacked(partialProof[0:0x180], appExeCommit, leafExeCommit, guestPvsPayload, partialProof[0x180:]); - // ``` - // - // where `guestPvsPayload` is a memory payload with each byte in - // `guestPvs` separated into its own `bytes32` word. - uint256 fullProofLength = FULL_PROOF_LENGTH; bytes32 leafExeCommit = LEAF_EXE_COMMIT; @@ -103,9 +117,7 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// @solidity memory-safe-assembly assembly { proofPtr := mload(0x40) - // Allocate the memory as a safety measure. We know that this is the - // only memory allocation that occurs in the call frame, so we don't - // need to clean the allocated memory. + // Allocate the memory as a safety measure. mstore(0x40, add(proofPtr, fullProofLength)) // Copy the KZG accumulators (length 0x180) into the beginning of From 10676dd772136c44666df12b1331e95058794ca3 Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Fri, 21 Mar 2025 00:05:25 -0400 Subject: [PATCH 12/15] chore: flip comment --- src/OpenVmHalo2Verifier.sol | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index f5bc001..190e0be 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -47,10 +47,10 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// proof[14 * 32..(14 + GUEST_PVS_LENGTH) * 32]: guestPvs[0..GUEST_PVS_LENGTH] /// proof[(14 + GUEST_PVS_LENGTH) * 32..]: Guest PVs Suffix /// + /// @param guestPvs The PVs revealed by the OpenVM guest program. /// @param partialProof All components of the proof except the Guest PVs, /// leaf and app exe commits. The expected format is: /// `abi.encodePacked(kzgAccumulators, proofSuffix)` - /// @param guestPvs The PVs revealed by the OpenVM guest program. /// @param appExeCommit The commitment to the OpenVM application executable whose execution /// is being verified. function verify(bytes calldata guestPvs, bytes calldata partialProof, bytes32 appExeCommit) external view { @@ -89,13 +89,6 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// only memory allocation that occurs in the call frame, we know that the /// memory was not written to before. /// - /// @param guestPvs The PVs revealed by the OpenVM guest program. - /// @param partialProof All components of the proof except the Guest PVs, - /// leaf and app exe commits. The expected format is: - /// `abi.encodePacked(kzgAccumulators, proofSuffix)` - /// @param appExeCommit The commitment to the OpenVM application executable - /// whose execution is being verified. - /// /// @return proofPtr Memory pointer to the beginning of the constructed /// proof. function _constructProof(bytes calldata guestPvs, bytes calldata partialProof, bytes32 appExeCommit) From 7e7d364b32c7f1ba5e1eaed6e12d2ee3fa4166ed Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Fri, 21 Mar 2025 00:36:30 -0400 Subject: [PATCH 13/15] chore: address renamings --- src/OpenVmHalo2Verifier.sol | 24 ++++++++++++------------ src/interfaces/IOpenVmHalo2Verifier.sol | 2 +- test/OpenVmHalo2Verifier.t.sol | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index 190e0be..ac4375a 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -47,20 +47,20 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// proof[14 * 32..(14 + GUEST_PVS_LENGTH) * 32]: guestPvs[0..GUEST_PVS_LENGTH] /// proof[(14 + GUEST_PVS_LENGTH) * 32..]: Guest PVs Suffix /// - /// @param guestPvs The PVs revealed by the OpenVM guest program. - /// @param partialProof All components of the proof except the Guest PVs, + /// @param publicValues The PVs revealed by the OpenVM guest program. + /// @param proofData All components of the proof except the Guest PVs, /// leaf and app exe commits. The expected format is: /// `abi.encodePacked(kzgAccumulators, proofSuffix)` /// @param appExeCommit The commitment to the OpenVM application executable whose execution /// is being verified. - function verify(bytes calldata guestPvs, bytes calldata partialProof, bytes32 appExeCommit) external view { - if (guestPvs.length != GUEST_PVS_LENGTH) revert InvalidGuestPvsLength(); - if (partialProof.length != PARTIAL_PROOF_LENGTH) revert InvalidPartialProofLength(); + function verify(bytes calldata publicValues, bytes calldata proofData, bytes32 appExeCommit) external view { + if (publicValues.length != GUEST_PVS_LENGTH) revert InvalidGuestPvsLength(); + if (proofData.length != PARTIAL_PROOF_LENGTH) revert InvalidPartialProofLength(); // We will format the public values and construct the full proof payload // below. - MemoryPointer proofPtr = _constructProof(guestPvs, partialProof, appExeCommit); + MemoryPointer proofPtr = _constructProof(publicValues, proofData, appExeCommit); uint256 fullProofLength = FULL_PROOF_LENGTH; @@ -86,12 +86,12 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// `guestPvs` separated into its own `bytes32` word. /// /// This function does not clean the memory it allocates. Since it is the - /// only memory allocation that occurs in the call frame, we know that the - /// memory was not written to before. + /// only memory allocation that occurs in the call frame, so we know that + /// the memory region was not written to before. /// /// @return proofPtr Memory pointer to the beginning of the constructed /// proof. - function _constructProof(bytes calldata guestPvs, bytes calldata partialProof, bytes32 appExeCommit) + function _constructProof(bytes calldata publicValues, bytes calldata proofData, bytes32 appExeCommit) internal pure returns (MemoryPointer proofPtr) @@ -115,7 +115,7 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { // Copy the KZG accumulators (length 0x180) into the beginning of // the memory buffer - calldatacopy(proofPtr, partialProof.offset, 0x180) + calldatacopy(proofPtr, proofData.offset, 0x180) // Copy the App Exe Commit and Leaf Exe Commit into the memory buffer mstore(add(proofPtr, 0x180), appExeCommit) @@ -128,13 +128,13 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { // Begin copying from the end of the KZG accumulators in the // calldata buffer (0x180) let suffixProofOffset := add(0x1c0, shl(5, GUEST_PVS_LENGTH)) - calldatacopy(add(proofPtr, suffixProofOffset), add(partialProof.offset, 0x180), 0x560) + calldatacopy(add(proofPtr, suffixProofOffset), add(proofData.offset, 0x180), 0x560) // Copy each byte of the guestPvs into the proof. It copies the // most significant bytes of guestPvs first. let guestPvsMemOffset := add(add(proofPtr, 0x1c0), 0x1f) for { let i := 0 } iszero(eq(i, GUEST_PVS_LENGTH)) { i := add(i, 1) } { - calldatacopy(add(guestPvsMemOffset, shl(5, i)), add(guestPvs.offset, i), 0x01) + calldatacopy(add(guestPvsMemOffset, shl(5, i)), add(publicValues.offset, i), 0x01) } } } diff --git a/src/interfaces/IOpenVmHalo2Verifier.sol b/src/interfaces/IOpenVmHalo2Verifier.sol index e94461e..231f4de 100644 --- a/src/interfaces/IOpenVmHalo2Verifier.sol +++ b/src/interfaces/IOpenVmHalo2Verifier.sol @@ -2,5 +2,5 @@ pragma solidity ^0.8.19; interface IOpenVmHalo2Verifier { - function verify(bytes calldata guestPvs, bytes calldata partialProof, bytes32 appExeCommit) external view; + function verify(bytes calldata publicValues, bytes calldata proofData, bytes32 appExeCommit) external view; } diff --git a/test/OpenVmHalo2Verifier.t.sol b/test/OpenVmHalo2Verifier.t.sol index 09cad77..bea624a 100644 --- a/test/OpenVmHalo2Verifier.t.sol +++ b/test/OpenVmHalo2Verifier.t.sol @@ -93,9 +93,9 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { function checkProofFormat(bytes calldata proof) external view { bytes memory partialProofExpected = partialProof; - bytes memory kzgAccumulators = proof[0:0x180]; + bytes memory _kzgAccumulators = proof[0:0x180]; bytes memory guestPvsSuffix = proof[0x5c0:]; - bytes memory _partialProof = abi.encodePacked(kzgAccumulators, guestPvsSuffix); + bytes memory _partialProof = abi.encodePacked(_kzgAccumulators, guestPvsSuffix); require(keccak256(_partialProof) == keccak256(partialProofExpected), "Partial proof mismatch"); bytes memory _appExeCommit = proof[0x180:0x1a0]; From e8b586c9526eeee6a75ddf0bd593bc194acfa71e Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Fri, 21 Mar 2025 00:39:19 -0400 Subject: [PATCH 14/15] chore: remove lcov.info --- lcov.info | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 lcov.info diff --git a/lcov.info b/lcov.info deleted file mode 100644 index 35f39dc..0000000 --- a/lcov.info +++ /dev/null @@ -1,35 +0,0 @@ -TN: -SF:script/Counter.s.sol -DA:10,0 -FN:10,CounterScript.setUp -FNDA:0,CounterScript.setUp -DA:12,0 -FN:12,CounterScript.run -FNDA:0,CounterScript.run -DA:13,0 -DA:15,0 -DA:17,0 -FNF:2 -FNH:0 -LF:5 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/Counter.sol -DA:7,258 -FN:7,Counter.setNumber -FNDA:258,Counter.setNumber -DA:8,258 -DA:11,1 -FN:11,Counter.increment -FNDA:1,Counter.increment -DA:12,1 -FNF:2 -FNH:2 -LF:4 -LH:4 -BRF:0 -BRH:0 -end_of_record From 38364336dbad6c7d044990c8e2fb72754d6d07e1 Mon Sep 17 00:00:00 2001 From: Hrik Bhowal <23041116+HrikB@users.noreply.github.com> Date: Fri, 21 Mar 2025 10:18:00 -0400 Subject: [PATCH 15/15] chore: rename all instances of partial proof and guest pvs --- src/OpenVmHalo2Verifier.sol | 60 +++++++++++++++--------------- test/OpenVmHalo2Verifier.t.sol | 68 +++++++++++++++++++--------------- 2 files changed, 69 insertions(+), 59 deletions(-) diff --git a/src/OpenVmHalo2Verifier.sol b/src/OpenVmHalo2Verifier.sol index ac4375a..185ff17 100644 --- a/src/OpenVmHalo2Verifier.sol +++ b/src/OpenVmHalo2Verifier.sol @@ -9,23 +9,23 @@ type MemoryPointer is uint256; /// @notice This contract provides a thin wrapper around the Halo2 verifier /// outputted by `snark-verifier`, exposing a more user-friendly interface. contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { - /// @dev Invalid partial proof length - error InvalidPartialProofLength(); + /// @dev Invalid proof data length + error InvalidProofDataLength(); - /// @dev Invalid guest PVs length - error InvalidGuestPvsLength(); + /// @dev Invalid public values length + error InvalidPublicValuesLength(); /// @dev Proof verification failed error ProofVerificationFailed(); - /// @dev The length of the partial proof, in bytes - uint256 private constant PARTIAL_PROOF_LENGTH = (12 + 43) * 32; + /// @dev The length of the proof data, in bytes + uint256 private constant PROOF_DATA_LENGTH = (12 + 43) * 32; - /// @dev The length of the guest PVs, in bytes. This value is set by OpenVM. - uint256 private constant GUEST_PVS_LENGTH = 32; + /// @dev The length of the public values, in bytes. This value is set by OpenVM. + uint256 private constant PUBLIC_VALUES_LENGTH = 32; /// @dev The length of the full proof, in bytes - uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + GUEST_PVS_LENGTH + 43) * 32; + uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + PUBLIC_VALUES_LENGTH + 43) * 32; /// @dev The leaf verifier commitment. This value is set by OpenVM. bytes32 public constant LEAF_EXE_COMMIT = @@ -37,25 +37,25 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// @notice A wrapper that constructs the proof into the right format for /// use with the `snark-verifier` verification. /// - /// @dev This function assumes that `guestPvs` encodes one `bytes32` + /// @dev This function assumes that `publicValues` encodes one `bytes32` /// hash which is the hash of the public values. /// /// The verifier expected proof format is: /// proof[..12 * 32]: KZG accumulators /// proof[12 * 32..13 * 32]: app exe commit /// proof[13 * 32..14 * 32]: leaf exe commit - /// proof[14 * 32..(14 + GUEST_PVS_LENGTH) * 32]: guestPvs[0..GUEST_PVS_LENGTH] - /// proof[(14 + GUEST_PVS_LENGTH) * 32..]: Guest PVs Suffix + /// proof[14 * 32..(14 + PUBLIC_VALUES_LENGTH) * 32]: publicValues[0..PUBLIC_VALUES_LENGTH] + /// proof[(14 + PUBLIC_VALUES_LENGTH) * 32..]: Public Values Suffix /// /// @param publicValues The PVs revealed by the OpenVM guest program. - /// @param proofData All components of the proof except the Guest PVs, + /// @param proofData All components of the proof except the public values, /// leaf and app exe commits. The expected format is: /// `abi.encodePacked(kzgAccumulators, proofSuffix)` /// @param appExeCommit The commitment to the OpenVM application executable whose execution /// is being verified. function verify(bytes calldata publicValues, bytes calldata proofData, bytes32 appExeCommit) external view { - if (publicValues.length != GUEST_PVS_LENGTH) revert InvalidGuestPvsLength(); - if (proofData.length != PARTIAL_PROOF_LENGTH) revert InvalidPartialProofLength(); + if (publicValues.length != PUBLIC_VALUES_LENGTH) revert InvalidPublicValuesLength(); + if (proofData.length != PROOF_DATA_LENGTH) revert InvalidProofDataLength(); // We will format the public values and construct the full proof payload // below. @@ -79,14 +79,14 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { // /// ```solidity /// bytes memory proof = - /// abi.encodePacked(partialProof[0:0x180], appExeCommit, leafExeCommit, guestPvsPayload, partialProof[0x180:]); + /// abi.encodePacked(proofData[0:0x180], appExeCommit, leafExeCommit, publicValuesPayload, proofData[0x180:]); /// ``` // - /// where `guestPvsPayload` is a memory payload with each byte in - /// `guestPvs` separated into its own `bytes32` word. + /// where `publicValuesPayload` is a memory payload with each byte in + /// `publicValues` separated into its own `bytes32` word. /// /// This function does not clean the memory it allocates. Since it is the - /// only memory allocation that occurs in the call frame, so we know that + /// only memory allocation that occurs in the call frame, we know that /// the memory region was not written to before. /// /// @return proofPtr Memory pointer to the beginning of the constructed @@ -104,8 +104,8 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { // proof[..0x180]: KZG accumulators // proof[0x180..0x1a0]: app exe commit // proof[0x1a0..0x1c0]: leaf exe commit - // proof[0x1c0..(0x1c0 + GUEST_PVS_LENGTH * 32)]: guestPvs[0..GUEST_PVS_LENGTH] - // proof[(0x1c0 + GUEST_PVS_LENGTH * 32)..]: Guest PVs Suffix + // proof[0x1c0..(0x1c0 + PUBLIC_VALUES_LENGTH * 32)]: publicValues[0..PUBLIC_VALUES_LENGTH] + // proof[(0x1c0 + PUBLIC_VALUES_LENGTH * 32)..]: Public Values Suffix /// @solidity memory-safe-assembly assembly { @@ -121,20 +121,20 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { mstore(add(proofPtr, 0x180), appExeCommit) mstore(add(proofPtr, 0x1a0), leafExeCommit) - // Copy the Guest PVs Suffix (length 43 * 32 = 0x560) into the - // end of the memory buffer, leaving GUEST_PVS_LENGTH words in - // between for the guestPvsPayload. + // Copy the Public Values Suffix (length 43 * 32 = 0x560) into the + // end of the memory buffer, leaving PUBLIC_VALUES_LENGTH words in + // between for the publicValuesPayload. // // Begin copying from the end of the KZG accumulators in the // calldata buffer (0x180) - let suffixProofOffset := add(0x1c0, shl(5, GUEST_PVS_LENGTH)) + let suffixProofOffset := add(0x1c0, shl(5, PUBLIC_VALUES_LENGTH)) calldatacopy(add(proofPtr, suffixProofOffset), add(proofData.offset, 0x180), 0x560) - // Copy each byte of the guestPvs into the proof. It copies the - // most significant bytes of guestPvs first. - let guestPvsMemOffset := add(add(proofPtr, 0x1c0), 0x1f) - for { let i := 0 } iszero(eq(i, GUEST_PVS_LENGTH)) { i := add(i, 1) } { - calldatacopy(add(guestPvsMemOffset, shl(5, i)), add(publicValues.offset, i), 0x01) + // Copy each byte of the public values into the proof. It copies the + // most significant bytes of public values first. + let publicValuesMemOffset := add(add(proofPtr, 0x1c0), 0x1f) + for { let i := 0 } iszero(eq(i, PUBLIC_VALUES_LENGTH)) { i := add(i, 1) } { + calldatacopy(add(publicValuesMemOffset, shl(5, i)), add(publicValues.offset, i), 0x01) } } } diff --git a/test/OpenVmHalo2Verifier.t.sol b/test/OpenVmHalo2Verifier.t.sol index bea624a..0346d64 100644 --- a/test/OpenVmHalo2Verifier.t.sol +++ b/test/OpenVmHalo2Verifier.t.sol @@ -5,53 +5,53 @@ import { OpenVmHalo2Verifier, MemoryPointer } from "../src/OpenVmHalo2Verifier.s import { Test, console2, safeconsole as console } from "forge-std/Test.sol"; contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { - bytes partialProof; + bytes proofData; bytes private constant kzgAccumulators = hex"000000000000000000000000000000000000000000d1437a9bb9ac3c1a16992c00000000000000000000000000000000000000000021a9ab5617c2d7d6ccf9af0000000000000000000000000000000000000000000008ba19dc0f462a92dc0900000000000000000000000000000000000000000025694ae0246cb4b406b0970000000000000000000000000000000000000000004ec055f528761bb24e7098000000000000000000000000000000000000000000000b0dcb882b8af688ddc4000000000000000000000000000000000000000000e7eb1b7903923438cc8b54000000000000000000000000000000000000000000af1197617343468c85c9d6000000000000000000000000000000000000000000002d22b55036423bb4c266000000000000000000000000000000000000000000280255aa13e24534841355000000000000000000000000000000000000000000bcffb01f01132cb2ea1eb20000000000000000000000000000000000000000000000c69662a512b8d21501"; bytes private constant suffix = hex"2775c493e84b4ea63465d98b4666134e274cd3d66eaf6b59a6dbeddb594de2091ae1f48e567caf12f2b888d339ba7f99ab4603cf008397276d562f67ad058c9410cc4bdb94e881438afc407093d722a48089d5784437d52a4bafc6e9819bf4e00bec156cd36cb7f7883d9ed0196b4f2ce825b2b579a08ec670d0b8708d476f610d620bbaac86de1c27ad5dfce81d3479c72e603025c1b3dc30559150467c1680022031fdd52469b8884250650abf7fb3c5a38018c285e3412d266f937aa0ef2c0d07838c09f45be93e8c0f653eddcb3565cb6c124dca1433684aba18f8cb58802af17390906939ca5d7f37bcd2f02f5138c9afcdd6ebe543dbbee0f775e1c40d2722ddbd7b4c08aba7a4f7ebd96b801afb946e453e69ea9ce118d47f6408b21914042c2f38028b0c160541d4fadb04a1a5b647cc8569247377be8202a468b1cb279b82a31e702f57385e36f7734f6b391d6a50fd14d09e0c30eab5cc4c8c6e5029bd146dea01b1b317ec886eaef10e4752867f6a0f88f20ba6e23b5a842e930d2883c12cbcf1306cedc382aa0207cb33cf01435390660f944e69687fb16ce7180c474460f997bd0efff02754973fd493cda33c7b364b89997409dbac35ca54f01b74498360f00fbf7092e589de2020641a954a27c92b862303dad302f258c9530c729d2baeccb32dbce5bf1ddc0758529f020b75806fd0b3cdf61670d88027e5028badbe0381b6eb6b68955284be0f85de4865ffcde32a8ce08182fe3cd433e91074bce48f7cb8295e8af1d1d9ccacce4490506e7adc9b29e88aba93f1b207ed28328bfe9f6cf3b6d3547bdb430f48898f78fa6c3e18234c855e0a52bb78c5d0131533e4a471a039c7cab0f266daf91f1834589a624400edc4398e7e828f582c07aa42c25d1b672cfb45eac915f8c4dbafd3205c29100c2992d45affacb9f19020535efdc88776c1c3aca1260df676ddfe99782c48ec29d38eea6b12f06d536702d6164196e22b4e348c9afe0c8f5572b4651c01cc00314a2291cc27e1763a762c1e3fbb8e98f1b99abdfdfa786508d7cc44df1d5d02f934bf3014a36090e464273f4d8c1b7877eb0b290223dac7d9cf81ec17f791d11aa4a1b68f9693796e7b0a8e03eceb1e616b44d174568825ffaca4cbeb4c4aab4e0e9c6723385e3cdeca273c175f927edc0111bc70e928bb1082a6b835e3ce1e3ed65c0dff86922d451806fb038d5521c9ba7fa99d60dc5f69d561b00799c6daa0ea4e43a3d33a456b2b19ed25f31ceebf094342dc5da14ef72395949b799483d059a7e65a246a8f45ad1c48b3b8a76fb17dc5a80bfe5d7900a9870397d653644d404cde9ab38c8b4aea0d3e6682eb89cfb1f50e1e5a8140543232c48d76b947416ee9950c0f5dc11b200e5bf99a7434f8174b56d22164d8b76bf640310d52d589a046d53b117d2bf3f9112b7a7fce911175c9801442086a89b0973b4d957ae8e947879c51835ef64fa027cbfabaddc03997a2b92fd79f0973f694696f56543e83a8f19119473ebff740014caa87269b99c0adf301358c2f3776c760068bf7b596de58dc752d758e7ed3224cbc8d6edda7bc8c4547db51d9c78ce44a178a6e03cae750dfbe643acd08972f5ae0952cd44c62797787661c879af3a7330a53b23bcdd93aa7e3d61039d95622a882f24f6ecd1fc5400d4c8abf867ec3d5a2de8388fa8d6d1026227c6716a002cbf4a89570842bd00a4c0fda5a055473d973f1115d49e77fef7a69fee3131803e935eaeea4bf493566a48ab82e4bf8c3552cc58376974341021ce82f09f4081ddbcbab8b9c65979a5643d145e8fd093cd3769a353c8c9f58830719ec0683c422b28a02f74ca326db6911af0e9bc67cb42007a65ad3e8942d823ba0c31ae2c322f45f1f54aca1193f948c49885fee5960695994cb73b2f572a8ac2be49192b5"; bytes32 appExeCommit = bytes32(0x0063802e02e9f8db01adecac53ea5c1db95bdbacf7800b9e29e27527cfd2613b); - bytes32 guestPvsHash = bytes32(uint256(0)); + bytes32 publicValues = bytes32(uint256(0)); uint256 private constant FULL_PROOF_WORDS = (12 + 2 + 32 + 43); uint256 private constant FULL_PROOF_LENGTH = (12 + 2 + 32 + 43) * 32; function setUp() public { - partialProof = abi.encodePacked(kzgAccumulators, suffix); + proofData = abi.encodePacked(kzgAccumulators, suffix); } function test_verifyProof() public view { - this.verify(abi.encodePacked(guestPvsHash), partialProof, appExeCommit); + this.verify(abi.encodePacked(publicValues), proofData, appExeCommit); } function test_proofFormat() public view { - this.constructAndCheckProof(abi.encodePacked(guestPvsHash), partialProof, appExeCommit); + this.constructAndCheckProof(abi.encodePacked(publicValues), proofData, appExeCommit); } - function testFuzz_proofFormat(uint256 partialProofSeed, bytes32 _guestPvsHash, bytes32 _appExeCommit) public { - vm.assume(_guestPvsHash != bytes32(0)); + function testFuzz_proofFormat(uint256 proofDataSeed, bytes32 _publicValues, bytes32 _appExeCommit) public { + vm.assume(_publicValues != bytes32(0)); vm.assume(_appExeCommit != bytes32(0)); - bytes memory _partialProof = new bytes(55 * 32); + bytes memory _proofData = new bytes(55 * 32); for (uint256 i = 0; i < 55 * 32; ++i) { - bytes1 _byte = bytes1(uint8(uint256(keccak256(abi.encodePacked(partialProofSeed, i))))); - _partialProof[i] = _byte; + bytes1 _byte = bytes1(uint8(uint256(keccak256(abi.encodePacked(proofDataSeed, i))))); + _proofData[i] = _byte; } - partialProof = _partialProof; - guestPvsHash = _guestPvsHash; + proofData = _proofData; + publicValues = _publicValues; appExeCommit = _appExeCommit; test_proofFormat(); } - function constructAndCheckProof(bytes calldata _guestPvs, bytes calldata _partialProof, bytes32 _appExeCommit) + function constructAndCheckProof(bytes calldata _publicValues, bytes calldata _proofData, bytes32 _appExeCommit) external view { - MemoryPointer proofPtr = _constructProof(_guestPvs, _partialProof, _appExeCommit); + MemoryPointer proofPtr = _constructProof(_publicValues, _proofData, _appExeCommit); // _constructProof will return a pointer to memory that will hold the // proof data in a block of size FULL_PROOF_LENGTH. However, this won't @@ -91,12 +91,12 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { } function checkProofFormat(bytes calldata proof) external view { - bytes memory partialProofExpected = partialProof; + bytes memory proofDataExpected = proofData; bytes memory _kzgAccumulators = proof[0:0x180]; - bytes memory guestPvsSuffix = proof[0x5c0:]; - bytes memory _partialProof = abi.encodePacked(_kzgAccumulators, guestPvsSuffix); - require(keccak256(_partialProof) == keccak256(partialProofExpected), "Partial proof mismatch"); + bytes memory publicValuesSuffix = proof[0x5c0:]; + bytes memory _proofData = abi.encodePacked(_kzgAccumulators, publicValuesSuffix); + require(keccak256(_proofData) == keccak256(proofDataExpected), "Proof data mismatch"); bytes memory _appExeCommit = proof[0x180:0x1a0]; bytes memory _leafExeCommit = proof[0x1a0:0x1c0]; @@ -104,22 +104,32 @@ contract OpenVmHalo2VerifierTest is Test, OpenVmHalo2Verifier { require(bytes32(_appExeCommit) == appExeCommit, "App exe commit mismatch"); require(bytes32(_leafExeCommit) == LEAF_EXE_COMMIT, "Leaf exe commit mismatch"); - bytes32 guestPvsHashExpected = guestPvsHash; - bytes calldata _guestPvsHash = proof[0x1c0:0x5c0]; + bytes32 publicValuesExpected = publicValues; + bytes calldata _publicValues = proof[0x1c0:0x5c0]; for (uint256 i = 0; i < 32; ++i) { - uint256 expected = uint256(uint8(guestPvsHashExpected[i])); - uint256 actual = uint256(bytes32(_guestPvsHash[i * 32:(i + 1) * 32])); - require(expected == actual, "Guest PVs hash mismatch"); + uint256 expected = uint256(uint8(publicValuesExpected[i])); + uint256 actual = uint256(bytes32(_publicValues[i * 32:(i + 1) * 32])); + require(expected == actual, "Public values mismatch"); } } - function test_RevertWhen_InvalidPartialProofLength() public { - vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidPartialProofLength.selector)); - this.verify(abi.encodePacked(guestPvsHash), hex"aa", appExeCommit); + function test_RevertWhen_InvalidProofDataLength() public { + vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidProofDataLength.selector)); + this.verify(abi.encodePacked(publicValues), hex"aa", appExeCommit); } - function test_RevertWhen_InvalidGuestPvsLength() public { - vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidGuestPvsLength.selector)); - this.verify(partialProof, hex"aa", appExeCommit); + function test_RevertWhen_InvalidPublicValuesLength() public { + vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.InvalidPublicValuesLength.selector)); + this.verify(proofData, hex"aa", appExeCommit); + } + + function test_RevertWhen_ProofVerificationFailed() public { + bytes memory corruptedKzgAccumulators = kzgAccumulators; + corruptedKzgAccumulators[0] = bytes1(uint8(0x01)); + + bytes memory corruptedProofData = abi.encodePacked(corruptedKzgAccumulators, suffix); + + vm.expectRevert(abi.encodeWithSelector(OpenVmHalo2Verifier.ProofVerificationFailed.selector)); + this.verify(abi.encodePacked(publicValues), corruptedProofData, appExeCommit); } }