diff --git a/.github/workflows/build-guest-release.yml b/.github/workflows/build-guest-release.yml index 45a2969d..8f6f2f83 100644 --- a/.github/workflows/build-guest-release.yml +++ b/.github/workflows/build-guest-release.yml @@ -4,6 +4,7 @@ on: push: tags: - 'v0.[0-9]+.[0-9]+' + - 'v0.[0-9]+.[0-9]+-*' jobs: build-guest: diff --git a/.gitignore b/.gitignore index cc34503f..081a3b39 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ /.output +!/releases/dev/verifier/verifier.bin +!/releases/dev/verifier/verifier.sol /releases *.log diff --git a/Cargo.lock b/Cargo.lock index 462547ab..8a3eab27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,6 +28,41 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aead" +version = "0.6.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" +dependencies = [ + "crypto-common 0.2.0-rc.4", + "inout", +] + +[[package]] +name = "aes" +version = "0.9.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e713c57c2a2b19159e7be83b9194600d7e8eb3b7c2cd67e671adf47ce189a05" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.11.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2be322be4a73a3a55ad74b9833238e76bfd6034ce69a05c1b41c879f6a3bdca6" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "ahash" version = "0.8.12" @@ -1320,6 +1355,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.11.0-rc.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bls12_381" version = "0.7.1" @@ -1565,6 +1609,17 @@ dependencies = [ "windows-link 0.2.0", ] +[[package]] +name = "cipher" +version = "0.5.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" +dependencies = [ + "block-buffer 0.11.0-rc.5", + "crypto-common 0.2.0-rc.4", + "inout", +] + [[package]] name = "clap" version = "4.5.47" @@ -1618,7 +1673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -1810,6 +1865,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" +dependencies = [ + "hybrid-array", + "rand_core 0.9.3", +] + [[package]] name = "csv" version = "1.3.1" @@ -1831,6 +1896,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "ctr" +version = "0.10.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27e41d01c6f73b9330177f5cf782ae5b581b5f2c7840e298e0275ceee5001434" +dependencies = [ + "cipher", +] + [[package]] name = "cuda-config" version = "0.1.0" @@ -2078,7 +2152,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid", - "crypto-common", + "crypto-common 0.1.6", "subtle", ] @@ -2132,6 +2206,19 @@ dependencies = [ "spki", ] +[[package]] +name = "ecies" +version = "0.1.0" +source = "git+https://github.com/scroll-tech/ecies-rs#e32a93f736aac2158bf5982b8e4786b82be8b854" +dependencies = [ + "aes-gcm", + "digest 0.10.7", + "hkdf", + "k256 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.10.9", + "thiserror 2.0.16", +] + [[package]] name = "educe" version = "0.6.0" @@ -2260,7 +2347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.0", + "windows-sys 0.52.0", ] [[package]] @@ -2624,6 +2711,15 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "ghash" +version = "0.6.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f88107cb02ed63adcc4282942e60c4d09d80208d33b360ce7c729ce6dae1739" +dependencies = [ + "polyval", +] + [[package]] name = "gimli" version = "0.31.1" @@ -2951,6 +3047,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -3000,6 +3105,15 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +[[package]] +name = "hybrid-array" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "1.7.0" @@ -3247,6 +3361,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "inout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7357b6e7aa75618c7864ebd0634b115a7218b0615f4cb1df33ac3eca23943d4" +dependencies = [ + "hybrid-array", +] + [[package]] name = "io-uring" version = "0.7.10" @@ -3368,6 +3491,7 @@ dependencies = [ "once_cell", "serdect", "sha2 0.10.9", + "signature", ] [[package]] @@ -5706,6 +5830,17 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "polyval" +version = "0.7.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffd40cc99d0fbb02b4b3771346b811df94194bc103983efa0203c8893755085" +dependencies = [ + "cfg-if", + "cpufeatures", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.11.1" @@ -6146,7 +6281,7 @@ dependencies = [ [[package]] name = "reth-chainspec" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-chains", "alloy-consensus", @@ -6166,7 +6301,7 @@ dependencies = [ [[package]] name = "reth-codecs" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6184,7 +6319,7 @@ dependencies = [ [[package]] name = "reth-codecs-derive" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "proc-macro2", "quote", @@ -6194,7 +6329,7 @@ dependencies = [ [[package]] name = "reth-consensus" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -6207,7 +6342,7 @@ dependencies = [ [[package]] name = "reth-consensus-common" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6219,7 +6354,7 @@ dependencies = [ [[package]] name = "reth-db-models" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-eips 1.0.38", "alloy-primitives", @@ -6229,7 +6364,7 @@ dependencies = [ [[package]] name = "reth-errors" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "reth-consensus", "reth-execution-errors", @@ -6240,7 +6375,7 @@ dependencies = [ [[package]] name = "reth-ethereum-consensus" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6256,7 +6391,7 @@ dependencies = [ [[package]] name = "reth-ethereum-forks" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-eip2124", "alloy-hardforks", @@ -6268,7 +6403,7 @@ dependencies = [ [[package]] name = "reth-ethereum-primitives" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6285,7 +6420,7 @@ dependencies = [ [[package]] name = "reth-evm" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6307,7 +6442,7 @@ dependencies = [ [[package]] name = "reth-evm-ethereum" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6327,7 +6462,7 @@ dependencies = [ [[package]] name = "reth-execution-errors" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-evm", "alloy-primitives", @@ -6340,7 +6475,7 @@ dependencies = [ [[package]] name = "reth-execution-types" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6356,7 +6491,7 @@ dependencies = [ [[package]] name = "reth-network-peers" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -6368,7 +6503,7 @@ dependencies = [ [[package]] name = "reth-primitives" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "once_cell", @@ -6381,7 +6516,7 @@ dependencies = [ [[package]] name = "reth-primitives-traits" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6409,7 +6544,7 @@ dependencies = [ [[package]] name = "reth-prune-types" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-primitives", "derive_more 2.0.1", @@ -6419,7 +6554,7 @@ dependencies = [ [[package]] name = "reth-revm" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-primitives", "reth-primitives-traits", @@ -6431,7 +6566,7 @@ dependencies = [ [[package]] name = "reth-scroll-chainspec" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-chains", "alloy-consensus", @@ -6456,7 +6591,7 @@ dependencies = [ [[package]] name = "reth-scroll-evm" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6486,7 +6621,7 @@ dependencies = [ [[package]] name = "reth-scroll-forks" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-chains", "alloy-primitives", @@ -6500,7 +6635,7 @@ dependencies = [ [[package]] name = "reth-scroll-primitives" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6517,7 +6652,7 @@ dependencies = [ [[package]] name = "reth-stages-types" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-primitives", "reth-trie-common", @@ -6526,7 +6661,7 @@ dependencies = [ [[package]] name = "reth-stateless" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -6552,7 +6687,7 @@ dependencies = [ [[package]] name = "reth-static-file-types" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-primitives", "derive_more 2.0.1", @@ -6563,7 +6698,7 @@ dependencies = [ [[package]] name = "reth-storage-api" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6585,7 +6720,7 @@ dependencies = [ [[package]] name = "reth-storage-errors" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-eips 1.0.38", "alloy-primitives", @@ -6601,7 +6736,7 @@ dependencies = [ [[package]] name = "reth-trie" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -6623,7 +6758,7 @@ dependencies = [ [[package]] name = "reth-trie-common" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -6639,7 +6774,7 @@ dependencies = [ [[package]] name = "reth-trie-sparse" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -6655,7 +6790,7 @@ dependencies = [ [[package]] name = "reth-zstd-compressors" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "zstd", ] @@ -7001,7 +7136,7 @@ dependencies = [ [[package]] name = "revm-scroll" version = "0.1.0" -source = "git+https://github.com/scroll-tech/scroll-revm#307f050ebe267492c483570356cc44990df42acf" +source = "git+https://github.com/scroll-tech/scroll-revm#d6b77e226ce20646d0ddf3dfe3b1fb3ec8a58cc3" dependencies = [ "auto_impl", "enumn", @@ -7217,7 +7352,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.0", + "windows-sys 0.52.0", ] [[package]] @@ -7256,7 +7391,7 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "sbv-core" version = "2.0.0" -source = "git+https://github.com/scroll-tech/stateless-block-verifier?branch=master#f11065e9267413ee50f51a06d29de5a49fbfa81f" +source = "git+https://github.com/scroll-tech/stateless-block-verifier?branch=master#d1b5f2ed2bd5ba4b646213b3f6ae1433ca5b396b" dependencies = [ "auto_impl", "itertools 0.14.0", @@ -7273,7 +7408,7 @@ dependencies = [ [[package]] name = "sbv-helpers" version = "2.0.0" -source = "git+https://github.com/scroll-tech/stateless-block-verifier?branch=master#f11065e9267413ee50f51a06d29de5a49fbfa81f" +source = "git+https://github.com/scroll-tech/stateless-block-verifier?branch=master#d1b5f2ed2bd5ba4b646213b3f6ae1433ca5b396b" dependencies = [ "tracing", ] @@ -7281,7 +7416,7 @@ dependencies = [ [[package]] name = "sbv-primitives" version = "2.0.0" -source = "git+https://github.com/scroll-tech/stateless-block-verifier?branch=master#f11065e9267413ee50f51a06d29de5a49fbfa81f" +source = "git+https://github.com/scroll-tech/stateless-block-verifier?branch=master#d1b5f2ed2bd5ba4b646213b3f6ae1433ca5b396b" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -7318,7 +7453,7 @@ dependencies = [ [[package]] name = "sbv-trie" version = "2.0.0" -source = "git+https://github.com/scroll-tech/stateless-block-verifier?branch=master#f11065e9267413ee50f51a06d29de5a49fbfa81f" +source = "git+https://github.com/scroll-tech/stateless-block-verifier?branch=master#d1b5f2ed2bd5ba4b646213b3f6ae1433ca5b396b" dependencies = [ "alloy-rlp", "alloy-trie 0.9.1", @@ -7335,7 +7470,7 @@ dependencies = [ [[package]] name = "sbv-utils" version = "2.0.0" -source = "git+https://github.com/scroll-tech/stateless-block-verifier?branch=master#f11065e9267413ee50f51a06d29de5a49fbfa81f" +source = "git+https://github.com/scroll-tech/stateless-block-verifier?branch=master#d1b5f2ed2bd5ba4b646213b3f6ae1433ca5b396b" dependencies = [ "alloy-provider", "alloy-rpc-client", @@ -7390,7 +7525,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scroll-alloy-consensus" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -7406,7 +7541,7 @@ dependencies = [ [[package]] name = "scroll-alloy-evm" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -7424,7 +7559,7 @@ dependencies = [ [[package]] name = "scroll-alloy-hardforks" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-hardforks", "auto_impl", @@ -7434,7 +7569,7 @@ dependencies = [ [[package]] name = "scroll-alloy-network" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-network", @@ -7449,7 +7584,7 @@ dependencies = [ [[package]] name = "scroll-alloy-rpc-types" version = "1.8.2" -source = "git+https://github.com/scroll-tech/reth?branch=scroll#32019bcde9d08524caad5b359b693e8f0c3951b8" +source = "git+https://github.com/scroll-tech/reth?branch=scroll#5edac541f81be7271d6e0b74a8f13f74e9facbb9" dependencies = [ "alloy-consensus", "alloy-eips 1.0.38", @@ -7517,6 +7652,7 @@ name = "scroll-zkvm-chunk-circuit" version = "0.6.0" dependencies = [ "bincode 2.0.1", + "ecies", "k256 0.13.4 (git+https://github.com/openvm-org/openvm.git?tag=v1.4.0)", "openvm", "openvm-algebra-complex-macros", @@ -7527,6 +7663,7 @@ dependencies = [ "openvm-pairing", "openvm-pairing-guest", "openvm-rv32im-guest", + "openvm-sha2", "p256 0.13.2 (git+https://github.com/openvm-org/openvm.git?tag=v1.4.0)", "scroll-zkvm-types-chunk", "scroll-zkvm-types-circuit", @@ -7672,6 +7809,9 @@ version = "0.6.0" dependencies = [ "alloy-consensus", "alloy-primitives", + "alloy-sol-types", + "ecies", + "itertools 0.14.0", "k256 0.13.4 (git+https://github.com/openvm-org/openvm.git?tag=v1.4.0)", "openvm-ecc-guest", "openvm-pairing", @@ -7684,6 +7824,8 @@ dependencies = [ "sbv-trie", "scroll-zkvm-types-base", "serde", + "serde_json", + "thiserror 2.0.16", ] [[package]] @@ -8194,7 +8336,7 @@ dependencies = [ "cfg-if", "libc", "psm", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -8367,7 +8509,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.61.0", + "windows-sys 0.52.0", ] [[package]] @@ -8881,6 +9023,16 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "universal-hash" +version = "0.6.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" +dependencies = [ + "crypto-common 0.2.0-rc.4", + "subtle", +] + [[package]] name = "unroll" version = "0.1.5" diff --git a/Cargo.toml b/Cargo.toml index 5c30db87..9f2f0870 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,6 +86,7 @@ alloy-primitives = { version = "1.3", default-features = false, features = [ "rkyv", ] } alloy-serde = { version = "1.0.13", default-features = false } +alloy-sol-types = { version = "1.3", default-features = false } bitcode = { version = "0.6.5", default-features = false, features = [ "serde", "derive", @@ -97,6 +98,7 @@ clap = "4.5" c-kzg = { version = "2.0" } csv = "1.3.1" derivative = "2.2.0" +ecies = { git = "https://github.com/scroll-tech/ecies-rs" } eyre = "0.6" futures = "0.3" halo2curves-axiom = { version = "0.5.3" } @@ -156,6 +158,23 @@ revm-state = { git = "https://github.com/scroll-tech/revm" } alloy-primitives = { git = "https://github.com/scroll-tech/alloy-core", branch = "feat/rkyv" } +## FIXME: when openvm fixes https://github.com/openvm-org/openvm/pull/1937 +#[patch.'https://github.com/openvm-org/openvm.git'] +#openvm = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-algebra-complex-macros = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-custom-insn = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-sha2 = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-sha256-guest = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-p256 = { git = "https://github.com/lightsing/openvm.git", package = "p256", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-k256 = { git = "https://github.com/lightsing/openvm.git", package = "k256", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-pairing = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-keccak256-guest = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-algebra-guest = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-ecc-guest = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-bigint-guest = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-pairing-guest = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } +#openvm-rv32im-guest = { git = "https://github.com/lightsing/openvm.git", rev = "f834efa186784cfdb0401c8596e1264cc9030f97" } + [profile.maxperf] inherits = "release" lto = "fat" diff --git a/Makefile b/Makefile index c32f6f94..a670e97f 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,18 @@ else CARGO_CONFIG_FLAG = endif +SRS_PARAMS_DIR := $(HOME)/.openvm/params +SRS_PARAMS_URL := https://circuit-release.s3.us-west-2.amazonaws.com/scroll-zkvm/params +SRS_PARAMS := $(SRS_PARAMS_DIR)/kzg_bn254_22.srs $(SRS_PARAMS_DIR)/kzg_bn254_24.srs + +# Download params if missing +$(SRS_PARAMS_DIR)/%.srs: + @mkdir -p $(SRS_PARAMS_DIR) + @if [ ! -f "$@" ]; then \ + echo "Fetching $(@F) from $(SRS_PARAMS_URL)"; \ + wget -q -O "$@" "$(SRS_PARAMS_URL)/$(@F)"; \ + fi + download-release: sh download-release.sh @@ -54,6 +66,9 @@ test-execute-chunk: test-execute-chunk-multi: @cargo test $(CARGO_CONFIG_FLAG) --release -p scroll-zkvm-integration --test chunk_circuit test_execute_multi -- --exact --nocapture +test-execute-validium-chunk: + @cargo test --release -p scroll-zkvm-integration --test chunk_circuit test_execute_validium -- --exact --nocapture + test-cycle: @cargo test $(CARGO_CONFIG_FLAG) --release -p scroll-zkvm-integration --test chunk_circuit test_cycle -- --exact --nocapture @@ -66,6 +81,9 @@ test-execute-batch-fast: test-execute-bundle: @cargo test $(CARGO_CONFIG_FLAG) --release -p scroll-zkvm-integration --test bundle_circuit test_execute -- --exact --nocapture +test-execute-validium-e2e: + @cargo test --release -p scroll-zkvm-integration --test bundle_circuit test_execute_validium -- --exact --nocapture + test-single-chunk: @cargo test $(CARGO_CONFIG_FLAG) --release -p scroll-zkvm-integration --test chunk_circuit setup_prove_verify_single -- --exact --nocapture diff --git a/crates/circuits/batch-circuit/batch_exe_commit.rs b/crates/circuits/batch-circuit/batch_exe_commit.rs index 929d58db..3daf5d0d 100644 --- a/crates/circuits/batch-circuit/batch_exe_commit.rs +++ b/crates/circuits/batch-circuit/batch_exe_commit.rs @@ -1,4 +1,4 @@ #![cfg_attr(rustfmt, rustfmt_skip)] //! Generated by crates/build-guest. DO NOT EDIT! -pub const COMMIT: [u32; 8] = [775328021, 994686220, 311977693, 1767703568, 225895022, 1451295799, 448321152, 1883850545]; +pub const COMMIT: [u32; 8] = [895296330, 1148458384, 132512161, 428973880, 1840310420, 1233162636, 1450429136, 1332854351]; diff --git a/crates/circuits/batch-circuit/src/circuit.rs b/crates/circuits/batch-circuit/src/circuit.rs index 01210d39..66f65baa 100644 --- a/crates/circuits/batch-circuit/src/circuit.rs +++ b/crates/circuits/batch-circuit/src/circuit.rs @@ -4,6 +4,7 @@ use scroll_zkvm_types_circuit::{ AggCircuit, AggregationInput, Circuit, ProgramCommitment, io::read_witnesses, public_inputs::{ + Version, batch::{BatchInfo, VersionedBatchInfo}, chunk::VersionedChunkInfo, }, @@ -42,8 +43,10 @@ impl Circuit for BatchCircuit { } fn validate(witness: Self::Witness) -> Self::PublicInputs { - let fork_name = witness.fork_name; - (BatchInfo::from(&witness), fork_name) + let version = Version::from(witness.version); + assert_eq!(version.fork, witness.fork_name); + + (BatchInfo::from(&witness), version) } } @@ -68,11 +71,12 @@ impl AggCircuit for BatchCircuit { } fn aggregated_public_inputs(witness: &Self::Witness) -> Vec { - let fork_name = witness.fork_name; + let version = Version::from(witness.version); witness .chunk_infos .iter() - .map(|chunk_info| (chunk_info.clone(), fork_name)) + .cloned() + .map(|chunk_info| (chunk_info, version)) .collect() } diff --git a/crates/circuits/bundle-circuit/bundle_exe_commit.rs b/crates/circuits/bundle-circuit/bundle_exe_commit.rs index 3b506b54..8dbaf3f4 100644 --- a/crates/circuits/bundle-circuit/bundle_exe_commit.rs +++ b/crates/circuits/bundle-circuit/bundle_exe_commit.rs @@ -1,4 +1,4 @@ #![cfg_attr(rustfmt, rustfmt_skip)] //! Generated by crates/build-guest. DO NOT EDIT! -pub const COMMIT: [u32; 8] = [999309839, 356817756, 1745788356, 1022091692, 38049001, 1787346163, 1855806929, 1587605488]; +pub const COMMIT: [u32; 8] = [1257908223, 1206458759, 1468660351, 59874919, 689770277, 1592610906, 773480905, 1252681164]; diff --git a/crates/circuits/bundle-circuit/src/circuit.rs b/crates/circuits/bundle-circuit/src/circuit.rs index 1c14fb46..fb78e641 100644 --- a/crates/circuits/bundle-circuit/src/circuit.rs +++ b/crates/circuits/bundle-circuit/src/circuit.rs @@ -4,6 +4,7 @@ use scroll_zkvm_types_circuit::{ AggCircuit, AggregationInput, Circuit, ProgramCommitment, io::read_witnesses, public_inputs::{ + Version, batch::VersionedBatchInfo, bundle::{BundleInfo, VersionedBundleInfo}, }, @@ -35,8 +36,10 @@ impl Circuit for BundleCircuit { } fn validate(witness: Self::Witness) -> Self::PublicInputs { - let fork_name = witness.fork_name; - (BundleInfo::from(&witness), fork_name) + let version = Version::from(witness.version); + assert_eq!(version.fork, witness.fork_name); + + (BundleInfo::from(&witness), version) } } @@ -61,11 +64,12 @@ impl AggCircuit for BundleCircuit { } fn aggregated_public_inputs(witness: &Self::Witness) -> Vec { - let fork_name = witness.fork_name; + let version = Version::from(witness.version); witness .batch_infos .iter() - .map(|batch_info| (batch_info.clone(), fork_name)) + .cloned() + .map(|batch_info| (batch_info, version)) .collect() } diff --git a/crates/circuits/chunk-circuit/Cargo.toml b/crates/circuits/chunk-circuit/Cargo.toml index 246a018e..dc30d343 100644 --- a/crates/circuits/chunk-circuit/Cargo.toml +++ b/crates/circuits/chunk-circuit/Cargo.toml @@ -7,6 +7,7 @@ version = "0.6.0" [dependencies] bincode = { workspace = true } +ecies = { workspace = true } scroll-zkvm-types-circuit = { workspace = true } scroll-zkvm-types-chunk = { workspace = true } @@ -20,6 +21,7 @@ openvm-bigint-guest = { workspace = true } openvm-ecc-guest = { workspace = true } openvm-keccak256-guest= { workspace = true } openvm-pairing-guest = { workspace = true, features = ["bn254"] } +openvm-sha2 = { workspace = true } openvm-rv32im-guest= { workspace = true } diff --git a/crates/circuits/chunk-circuit/chunk_exe_commit.rs b/crates/circuits/chunk-circuit/chunk_exe_commit.rs index 0261dfe5..84cc5287 100644 --- a/crates/circuits/chunk-circuit/chunk_exe_commit.rs +++ b/crates/circuits/chunk-circuit/chunk_exe_commit.rs @@ -1,4 +1,4 @@ #![cfg_attr(rustfmt, rustfmt_skip)] //! Generated by crates/build-guest. DO NOT EDIT! -pub const COMMIT: [u32; 8] = [975311006, 1373163213, 724059054, 1653301253, 267007718, 518639920, 720799142, 310936841]; +pub const COMMIT: [u32; 8] = [988980860, 377520490, 1389793144, 1577198725, 851225072, 192704613, 306102683, 816798173]; diff --git a/crates/circuits/chunk-circuit/src/circuit.rs b/crates/circuits/chunk-circuit/src/circuit.rs index 4fc7dd78..75ddc48d 100644 --- a/crates/circuits/chunk-circuit/src/circuit.rs +++ b/crates/circuits/chunk-circuit/src/circuit.rs @@ -3,7 +3,10 @@ use scroll_zkvm_types_chunk::ChunkWitness; use scroll_zkvm_types_circuit::{ Circuit, io::read_witnesses, - public_inputs::chunk::{ChunkInfo, VersionedChunkInfo}, + public_inputs::{ + Version, + chunk::{ChunkInfo, VersionedChunkInfo}, + }, }; #[allow(unused_imports, clippy::single_component_path_imports)] @@ -38,8 +41,10 @@ impl Circuit for ChunkCircuit { } fn validate(witness: Self::Witness) -> Self::PublicInputs { - let fork_name = witness.fork_name; + let version = Version::from(witness.version); + assert_eq!(version.fork, witness.fork_name); + let chunk_info = ChunkInfo::try_from(witness).expect("failed to execute chunk"); - (chunk_info, fork_name) + (chunk_info, version) } } diff --git a/crates/circuits/chunk-circuit/src/main.rs b/crates/circuits/chunk-circuit/src/main.rs index 737390f8..2e521cd2 100644 --- a/crates/circuits/chunk-circuit/src/main.rs +++ b/crates/circuits/chunk-circuit/src/main.rs @@ -9,6 +9,13 @@ openvm::entry!(main); fn main() { Crypto::install(); + ecies::sha256::set_digest_provider(|| { + Box::new(ecies::sha256::ext::ExtSha256Core::new( + openvm_sha2::set_sha256, + )) + }) + .unwrap(); + let witness_bytes = C::read_witness_bytes(); let witness = C::deserialize_witness(&witness_bytes); diff --git a/crates/integration/src/bin/chunk-scanner.rs b/crates/integration/src/bin/chunk-scanner.rs index 7d7b5763..3135fcc9 100644 --- a/crates/integration/src/bin/chunk-scanner.rs +++ b/crates/integration/src/bin/chunk-scanner.rs @@ -10,7 +10,7 @@ use scroll_zkvm_integration::{ ProverTester, testers::chunk::{ChunkProverTester, exec_chunk}, }; -use scroll_zkvm_types::{chunk::ChunkWitness, public_inputs::ForkName}; +use scroll_zkvm_types::{chunk::ChunkWitness, version}; use std::collections::HashMap; use std::{fs::File, path::PathBuf, slice}; use url::Url; @@ -157,14 +157,24 @@ async fn main() -> eyre::Result<()> { let mut gas_used = 0u64; let mut n_chunks = 0; while let Some(block) = rx.recv().await { + // FIXME: hhq + use scroll_zkvm_types::public_inputs::ForkName::Feynman; let (_, gas) = exec_chunk(&ChunkWitness::new( + version::Version::feynman().as_version_byte(), slice::from_ref(&block), B256::ZERO, - ForkName::Feynman, + Feynman, + None, ))?; if gas + gas_used > cli.chunk_gas_target * 1_000_000 { - let wit = ChunkWitness::new(&blocks, B256::ZERO, ForkName::Feynman); + let wit = ChunkWitness::new( + version::Version::feynman().as_version_byte(), + &blocks, + B256::ZERO, + Feynman, + None, + ); let (exec_result, gas) = exec_chunk(&wit)?; let start_block = blocks[0].header.number; diff --git a/crates/integration/src/lib.rs b/crates/integration/src/lib.rs index 6142816f..bf81beab 100644 --- a/crates/integration/src/lib.rs +++ b/crates/integration/src/lib.rs @@ -8,7 +8,7 @@ use scroll_zkvm_prover::{ }; use scroll_zkvm_types::{ proof::{EvmProof, ProofEnum, StarkProof}, - public_inputs::ForkName, + public_inputs::{ForkName, Version}, types_agg::ProgramCommitment, utils::serialize_vk, }; @@ -42,6 +42,15 @@ pub fn testing_hardfork() -> ForkName { ForkName::Feynman } +/// Test settings (version). +pub fn testing_version() -> Version { + Version::feynman() +} + +pub fn testing_version_validium() -> Version { + Version::validium_v1() +} + /// Read the 'GUEST_VERSION' from the environment variable. /// If not existed, return "dev" as default /// The returned value will be used to locate asset files: $workspace/releases/$guest_version diff --git a/crates/integration/src/testers/batch.rs b/crates/integration/src/testers/batch.rs index e0ddc858..1494f3a9 100644 --- a/crates/integration/src/testers/batch.rs +++ b/crates/integration/src/testers/batch.rs @@ -3,14 +3,14 @@ use scroll_zkvm_types::{ batch::{BatchHeader, BatchInfo, BatchWitness, LegacyBatchWitness, ReferenceHeader}, chunk::ChunkInfo, proof::ProofEnum, - public_inputs::ForkName, + public_inputs::{ForkName, Version}, utils::serialize_vk, }; use crate::{ PartialProvingTask, ProverTester, load_program_commitments, prove_verify, - testers::chunk::{ChunkTaskGenerator, preset_chunk_multiple}, - utils::build_batch_witnesses, + testers::chunk::{ChunkTaskGenerator, preset_chunk_multiple, preset_chunk_validium}, + utils::{build_batch_witnesses, build_batch_witnesses_validium}, }; impl PartialProvingTask for BatchWitness { @@ -19,6 +19,7 @@ impl PartialProvingTask for BatchWitness { ReferenceHeader::V6(h) => h.batch_hash(), ReferenceHeader::V7(h) => h.batch_hash(), ReferenceHeader::V8(h) => h.batch_hash(), + ReferenceHeader::Validium(h) => h.batch_hash(), }; header_hash.to_string() } @@ -57,6 +58,16 @@ pub struct BatchTaskGenerator { } impl BatchTaskGenerator { + pub fn version(&self) -> Version { + if let Some(wit) = self.witness.as_ref() { + return Version::from(wit.version); + } + self.chunk_generators + .first() + .expect("at least 1 chunk in a batch") + .version + } + pub fn get_or_build_witness(&mut self) -> eyre::Result { if self.witness.is_some() { return Ok(self.witness.clone().unwrap()); @@ -65,6 +76,7 @@ impl BatchTaskGenerator { self.witness.replace(witness.clone()); Ok(witness) } + pub fn get_or_build_proof( &mut self, prover: &mut Prover, @@ -105,14 +117,31 @@ impl BatchTaskGenerator { .collect::>>()?; let commitment = load_program_commitments("chunk")?; - let ret_wit = build_batch_witnesses( - &chunks, - &serialize_vk::serialize(&commitment), - self.last_witness - .as_ref() - .map(|wit| (&wit.reference_header).into()) - .unwrap_or_default(), - )?; + + let ret_wit = if chunks + .first() + .expect("at least 1 chunk in batch") + .version() + .is_validium() + { + build_batch_witnesses_validium( + &chunks, + &serialize_vk::serialize(&commitment), + self.last_witness + .as_ref() + .map(|wit| (&wit.reference_header).into()) + .unwrap_or_default(), + )? + } else { + build_batch_witnesses( + &chunks, + &serialize_vk::serialize(&commitment), + self.last_witness + .as_ref() + .map(|wit| (&wit.reference_header).into()) + .unwrap_or_default(), + )? + }; // sanity check for info in &ret_wit.chunk_infos { @@ -175,6 +204,20 @@ pub fn preset_batch() -> BatchTaskGenerator { BatchTaskGenerator::from_chunk_tasks(&preset_chunk_multiple(), None) } +pub fn preset_batch_validium() -> Vec { + let validium_chunks = preset_chunk_validium(); + assert_eq!(validium_chunks.len(), 5); + create_canonical_tasks( + [ + &validium_chunks[0..=1], + &validium_chunks[2..=3], + &validium_chunks[4..=4], + ] + .into_iter(), + ) + .expect("must succeed for preset collection") +} + /// preset examples for multiple task pub fn preset_batch_multiple() -> Vec { static PRESET_RESULT: std::sync::OnceLock> = std::sync::OnceLock::new(); diff --git a/crates/integration/src/testers/bundle.rs b/crates/integration/src/testers/bundle.rs index 409300c1..3f320477 100644 --- a/crates/integration/src/testers/bundle.rs +++ b/crates/integration/src/testers/bundle.rs @@ -1,6 +1,6 @@ use scroll_zkvm_types::{ batch::BatchInfo, - bundle::{BundleInfo, BundleWitness}, + bundle::{BundleInfo, BundleWitness, LegacyBundleWitness}, proof::ProofEnum, public_inputs::ForkName, }; @@ -10,7 +10,7 @@ use scroll_zkvm_prover::Prover; use crate::{ PartialProvingTask, ProverTester, load_program_commitments, prove_verify_single_evm, - testers::batch::BatchTaskGenerator, testing_hardfork, utils::metadata_from_batch_witnesses, + testers::batch::BatchTaskGenerator, utils::metadata_from_batch_witnesses, }; impl PartialProvingTask for BundleWitness { @@ -24,7 +24,9 @@ impl PartialProvingTask for BundleWitness { } fn legacy_rkyv_archive(&self) -> eyre::Result> { - Ok(rkyv::to_bytes::(self)?.to_vec()) + let witness_legacy = LegacyBundleWitness::from(self.clone()); + let bytes = rkyv::to_bytes::(&witness_legacy)?; + Ok(bytes.to_vec()) } fn fork_name(&self) -> ForkName { @@ -77,6 +79,7 @@ impl BundleTaskGenerator { self.proof.replace(proof.clone()); Ok(proof) } + fn get_or_build_child_proofs( &mut self, batch_prover: &mut Prover, @@ -104,7 +107,12 @@ impl BundleTaskGenerator { public_inputs::MultiVersionPublicInputs, types_agg::AggregationInput, }; - let fork_name = testing_hardfork(); + let version = self + .batch_generators + .first() + .expect("at least 1 batch in a bundle") + .version(); + let fork_name = version.fork; let commitment = load_program_commitments("batch")?; let mut batch_proofs = Vec::new(); @@ -120,7 +128,7 @@ impl BundleTaskGenerator { assert_eq!(info.parent_batch_hash, last_info.batch_hash, "batch hash",); } - let pi_hash = info.pi_hash_by_fork(fork_name); + let pi_hash = info.pi_hash_by_version(version); let proof = AggregationInput { public_values: pi_hash .as_slice() @@ -134,6 +142,7 @@ impl BundleTaskGenerator { } Ok(BundleWitness { + version: version.as_version_byte(), batch_infos, batch_proofs, fork_name, diff --git a/crates/integration/src/testers/chunk.rs b/crates/integration/src/testers/chunk.rs index 7f40a082..acf50277 100644 --- a/crates/integration/src/testers/chunk.rs +++ b/crates/integration/src/testers/chunk.rs @@ -1,12 +1,12 @@ use rayon::iter::{IntoParallelIterator, ParallelIterator}; use sbv_core::BlockWitness; -use sbv_primitives::B256; -use scroll_zkvm_prover::Prover; +use sbv_primitives::{B256, types::consensus::TxL1Message}; use scroll_zkvm_prover::utils::vm::ExecutionResult; +use scroll_zkvm_prover::{Prover, utils::read_json}; use scroll_zkvm_types::{ - chunk::{ChunkInfo, ChunkWitness, LegacyChunkWitness}, + chunk::{ChunkInfo, ChunkWitness, LegacyChunkWitness, SecretKey}, proof::ProofEnum, - public_inputs::ForkName, + public_inputs::{ForkName, Version}, }; use std::{ fs::File, @@ -15,7 +15,8 @@ use std::{ use crate::{ PartialProvingTask, ProverTester, prove_verify, testdata_fork_directory, tester_execute, - testers::PATH_TESTDATA, testing_hardfork, utils::metadata_from_chunk_witnesses, + testers::PATH_TESTDATA, testing_hardfork, testing_version, + utils::metadata_from_chunk_witnesses, }; /// Load a file .json in the directory. @@ -61,10 +62,9 @@ impl PartialProvingTask for ChunkWitness { } fn legacy_rkyv_archive(&self) -> eyre::Result> { - Ok( - rkyv::to_bytes::(&LegacyChunkWitness::from(self.clone()))? - .to_vec(), - ) + let witness_legacy = LegacyChunkWitness::from(self.clone()); + let bytes = rkyv::to_bytes::(&witness_legacy)?; + Ok(bytes.to_vec()) } fn fork_name(&self) -> ForkName { @@ -86,6 +86,7 @@ impl ProverTester for ChunkProverTester { /// Generator collect a range of block witnesses from test data #[derive(Clone, Default)] pub struct ChunkTaskGenerator { + pub version: Version, pub block_range: Vec, pub prev_message_hash: Option, pub witness: Option, @@ -102,6 +103,7 @@ impl ChunkTaskGenerator { self.witness = Some(witness.clone()); Ok(witness) } + pub fn get_or_build_proof(&mut self, prover: &mut Prover) -> eyre::Result { if let Some(proof) = &self.proof { return Ok(proof.clone()); @@ -113,12 +115,17 @@ impl ChunkTaskGenerator { } pub fn calculate_witness(&mut self) -> eyre::Result { + let dir_name = if self.version.is_validium() { + "validium" + } else { + self.version.fork.as_str() + }; let paths: Vec = self .block_range .iter() .map(|block_n| { Path::new(PATH_TESTDATA) - .join(testdata_fork_directory()) + .join(dir_name) .join("witnesses") .join(format!("{}.json", block_n)) }) @@ -129,12 +136,33 @@ impl ChunkTaskGenerator { .map(read_block_witness) .collect::>>()?; - let witness = ChunkWitness::new( - &block_witnesses, - self.prev_message_hash - .unwrap_or_else(|| B256::repeat_byte(1u8)), - testing_hardfork(), - ); + let witness = if self.version.is_validium() { + let base_dir = Path::new(PATH_TESTDATA).join("validium").join("witnesses"); + let secret_key = hex::decode(std::env::var("VALIDIUM_KEY")?)?; + let secret_key = SecretKey::try_from_bytes(&secret_key)?; + let validium_txs = self + .block_range + .iter() + .map(|blk| read_json(base_dir.join(format!("{blk}_validium_txs.json")))) + .collect::>, _>>()?; + ChunkWitness::new_validium( + self.version.as_version_byte(), + &block_witnesses, + self.prev_message_hash + .unwrap_or_else(|| B256::repeat_byte(1u8)), + self.version.fork, + validium_txs, + secret_key, + ) + } else { + ChunkWitness::new_scroll( + self.version.as_version_byte(), + &block_witnesses, + self.prev_message_hash + .unwrap_or_else(|| B256::repeat_byte(1u8)), + testing_hardfork(), + ) + }; Ok(witness) } @@ -153,7 +181,11 @@ pub fn get_witness_from_env_or_builder( .iter() .map(read_block_witness) .collect::>>()?; - Ok(ChunkWitness::new( + + let version = testing_version().as_version_byte(); + + Ok(ChunkWitness::new_scroll( + version, &block_witnesses, B256::repeat_byte(1u8), testing_hardfork(), @@ -162,13 +194,14 @@ pub fn get_witness_from_env_or_builder( /// preset examples for single task pub fn preset_chunk() -> ChunkTaskGenerator { - let block_range = match testing_hardfork() { - ForkName::EuclidV1 => 12508460u64..=12508463u64, - ForkName::EuclidV2 => 1u64..=4u64, - ForkName::Feynman => 16525000u64..=16525003u64, + let (version, block_range) = match testing_hardfork() { + ForkName::EuclidV1 => (Version::euclid_v1(), 12508460u64..=12508463u64), + ForkName::EuclidV2 => (Version::euclid_v2(), 1u64..=4u64), + ForkName::Feynman => (Version::feynman(), 16525000u64..=16525003u64), }; ChunkTaskGenerator { + version, block_range: block_range.collect(), ..Default::default() } @@ -176,12 +209,14 @@ pub fn preset_chunk() -> ChunkTaskGenerator { /// create canonical tasks from a series of block range pub fn create_canonical_tasks( + version: Version, ranges: impl Iterator>, ) -> eyre::Result> { let mut ret = Vec::new(); let mut prev_message_hash = None; for r in ranges { let mut canonical_generator = ChunkTaskGenerator { + version, block_range: r.collect(), prev_message_hash, proof: Default::default(), @@ -203,27 +238,40 @@ pub fn preset_chunk_multiple() -> Vec { PRESET_RESULT .get_or_init(|| { - create_canonical_tasks( - match testing_hardfork() { - ForkName::EuclidV1 => vec![ + let (block_range, version) = match testing_hardfork() { + ForkName::EuclidV1 => ( + vec![ 12508460u64..=12508460u64, 12508461u64..=12508461u64, 12508462u64..=12508463u64, ], - ForkName::EuclidV2 => vec![1u64..=1u64, 2u64..=2u64, 3u64..=4u64], - ForkName::Feynman => vec![ + Version::euclid_v1(), + ), + ForkName::EuclidV2 => ( + vec![1u64..=1u64, 2u64..=2u64, 3u64..=4u64], + Version::euclid_v2(), + ), + ForkName::Feynman => ( + vec![ 16525000u64..=16525000u64, 16525001u64..=16525001u64, 16525002u64..=16525003u64, ], - } - .into_iter(), - ) - .expect("must success for preset collections") + Version::feynman(), + ), + }; + create_canonical_tasks(version, block_range.into_iter()) + .expect("must success for preset collections") }) .clone() } +pub fn preset_chunk_validium() -> Vec { + let block_range = vec![347..=355, 356..=360, 361..=370, 371..=375, 376..=397]; + create_canonical_tasks(Version::validium_v1(), block_range.into_iter()) + .expect("must succeed for preset collection") +} + pub fn exec_chunk(wit: &ChunkWitness) -> eyre::Result<(ExecutionResult, u64)> { let blk = wit.blocks[0].header.number; println!( diff --git a/crates/integration/src/utils/mod.rs b/crates/integration/src/utils/mod.rs index 02645214..ecb2a150 100644 --- a/crates/integration/src/utils/mod.rs +++ b/crates/integration/src/utils/mod.rs @@ -1,11 +1,14 @@ -use crate::testing_hardfork; +use crate::{testing_hardfork, testing_version, testing_version_validium}; use bytesize::ByteSize; use sbv_core::BlockWitness; use sbv_primitives::types::consensus::ScrollTransaction; use sbv_primitives::{B256, types::eips::Encodable2718}; use scroll_zkvm_types::batch::build_point_eval_witness; use scroll_zkvm_types::{ - batch::{BatchHeader, BatchHeaderV6, BatchHeaderV7, BatchInfo, BatchWitness, ReferenceHeader}, + batch::{ + BatchHeader, BatchHeaderV6, BatchHeaderV7, BatchHeaderValidium, BatchHeaderValidiumV1, + BatchInfo, BatchWitness, ReferenceHeader, + }, bundle::{BundleInfo, BundleWitness}, chunk::{ChunkInfo, ChunkWitness}, public_inputs::{ForkName, MultiVersionPublicInputs}, @@ -69,6 +72,7 @@ impl From<&ReferenceHeader> for LastHeader { ReferenceHeader::V6(h) => h.into(), ReferenceHeader::V7(h) => h.into(), ReferenceHeader::V8(h) => h.into(), + ReferenceHeader::Validium(h) => h.into(), } } } @@ -95,6 +99,17 @@ impl From<&BatchHeaderV7> for LastHeader { } } +impl From<&BatchHeaderValidium> for LastHeader { + fn from(h: &BatchHeaderValidium) -> Self { + Self { + batch_index: h.index(), + version: h.version(), + batch_hash: h.batch_hash(), + l1_message_index: 0, + } + } +} + pub fn metadata_from_chunk_witnesses(witness: ChunkWitness) -> eyre::Result { witness .try_into() @@ -160,7 +175,9 @@ pub fn build_batch_witnesses( } else { meta_chunk_bytes.clone() }; - if testing_hardfork() >= ForkName::EuclidV2 { + + let version = testing_version(); + if version.fork >= ForkName::EuclidV2 { let num_blocks = chunks.iter().map(|w| w.blocks.len()).sum::() as u16; let prev_msg_queue_hash = chunks[0].prev_msg_queue_hash; let initial_block_number = chunks[0].blocks[0].header.number; @@ -185,8 +202,7 @@ pub fn build_batch_witnesses( // compress ... let compressed_payload = zstd_encode(&payload); - let version = ForkName::Feynman.to_protocol_version() as u32; - let heading = compressed_payload.len() as u32 + (version << 24); + let heading = compressed_payload.len() as u32 + ((version.as_version_byte() as u32) << 24); let blob_bytes = if testing_hardfork() >= ForkName::EuclidV2 { let mut blob_bytes = Vec::from(heading.to_be_bytes()); @@ -204,7 +220,7 @@ pub fn build_batch_witnesses( let kzg_commitment = point_eval::blob_to_kzg_commitment(&kzg_blob); let blob_versioned_hash = point_eval::get_versioned_hash(&kzg_commitment); - // primage = keccak(payload) + blob_versioned_hash + // preimage = keccak(payload) + blob_versioned_hash let challenge_preimage = if testing_hardfork() >= ForkName::EuclidV2 { let mut challenge_preimage = keccak256(&blob_bytes).to_vec(); challenge_preimage.extend(blob_versioned_hash.0); @@ -295,12 +311,11 @@ pub fn build_batch_witnesses( } }; - let fork_name = testing_hardfork(); let commitment = serialize_vk::deserialize(prover_vk); let chunk_proofs = chunk_infos .iter() .map(|chunk_info| { - let pi_hash = chunk_info.pi_hash_by_fork(fork_name); + let pi_hash = chunk_info.pi_hash_by_version(version); AggregationInput { public_values: pi_hash .as_slice() @@ -317,12 +332,82 @@ pub fn build_batch_witnesses( *kzg_proof.to_bytes().as_ref(), ); Ok(BatchWitness { + version: version.as_version_byte(), chunk_proofs, chunk_infos, reference_header, blob_bytes, point_eval_witness: Some(point_eval_witness), - fork_name, + fork_name: version.fork, + }) +} + +pub fn build_batch_witnesses_validium( + chunks: &[ChunkWitness], + prover_vk: &[u8], // notice we supppose all proof is (would be) generated from the same prover + last_header: LastHeader, +) -> eyre::Result { + let chunk_infos = chunks + .iter() + .cloned() + .map(metadata_from_chunk_witnesses) + .collect::>>()?; + + // collect tx bytes from chunk tasks + let (_, chunk_digests, _) = chunks.iter().fold( + (Vec::new(), Vec::new(), Vec::new()), + |(mut meta_chunk_sizes, mut chunk_digests, mut payload_bytes), chunk_wit| { + let tx_bytes = blks_tx_bytes(chunk_wit.blocks.iter()); + meta_chunk_sizes.push(tx_bytes.len()); + chunk_digests.push(keccak256(&tx_bytes)); + payload_bytes.extend(tx_bytes); + (meta_chunk_sizes, chunk_digests, payload_bytes) + }, + ); + + // sanity check, verify the correction of execute + for (digest, chunk_info) in chunk_digests.iter().zip(chunk_infos.as_slice()) { + assert_eq!(digest, &chunk_info.tx_data_digest); + } + + // collect all data together for payload + let version = testing_version_validium(); + + let last_chunk = chunk_infos.last().expect("at least 1 chunk in batch"); + let reference_header = + ReferenceHeader::Validium(BatchHeaderValidium::V1(BatchHeaderValidiumV1 { + version: version.stf_version as u8, + batch_index: last_header.batch_index + 1, + parent_batch_hash: last_header.batch_hash, + post_state_root: last_chunk.post_state_root, + withdraw_root: last_chunk.withdraw_root, + commitment: last_chunk.post_blockhash, + })); + + let commitment = serialize_vk::deserialize(prover_vk); + let chunk_proofs = chunk_infos + .iter() + .map(|chunk_info| { + let pi_hash = chunk_info.pi_hash_by_version(version); + AggregationInput { + public_values: pi_hash + .as_slice() + .iter() + .map(|&b| b as u32) + .collect::>(), + commitment: commitment.clone(), + } + }) + .collect::>(); + + Ok(BatchWitness { + version: version.as_version_byte(), + chunk_proofs, + chunk_infos, + reference_header, + blob_bytes: Vec::default(), + point_eval_witness: None, + fork_name: version.fork, }) } @@ -370,6 +455,9 @@ fn test_build_and_parse_batch_task() -> eyre::Result<()> { let enveloped = batch::EnvelopeV8::from_slice(&task_wit.blob_bytes); ::from_envelope(&enveloped).validate(h, infos); } + ReferenceHeader::Validium(_h) => { + todo!() + } } Ok(()) diff --git a/crates/integration/testdata/validium/witnesses/347_validium_txs.json b/crates/integration/testdata/validium/witnesses/347_validium_txs.json index 8b14b017..34c5502d 100644 --- a/crates/integration/testdata/validium/witnesses/347_validium_txs.json +++ b/crates/integration/testdata/validium/witnesses/347_validium_txs.json @@ -5,8 +5,8 @@ "from": "0xfeea7a92fd46c25a475829f1975876ba48c13ceb", "gas": "0xf4240", "gasPrice": "0x0", - "hash": "0xfe9e8470c8d5840f9f6c25d1105f1e2ef51d31cc9407cfde40d474cbd4d1ab4b", - "input": "0x8ef1332e000000000000000000000000fbe0c68e2241aa4e65c553e558a1f87ae920e562000000000000000000000000694c7feee8bdad3c5d58dcbeb3da08b122ff27760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000344f839517f00000000000000000000000038cb00e044d3cdd3c9f90b7efde61ef62e38fdf3000000000000000000000000928a1909db63ae7813e6318d098fd17439ec0a49000000000000000000000000cf360f1fc8763a38e3e1a19947bceb9f764a7a7c00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000007504702f69ffc4e76bc4edda15f0dad49cfcb80198cd4d171a5b33a286d77cf4a249d3c7e1160b2d5f79268b44cc05431f9de21b0b56478b712727afe647ad9297ec352bfec52d17a9c4ea7ce40737abacb9c841f8fcc5ee8ebfffa58d43047afe2306f3ac2fdf6cf9fa3c4d293714767b4f2709a336000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000045745544800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d577261707065642045746865720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "hash": "0xbbca21975276ee293d2cdd03017f10e924d6b8a9538b24ed6289f7ebb558be31", + "input": "0x8ef1332e000000000000000000000000fbe0c68e2241aa4e65c553e558a1f87ae920e562000000000000000000000000694c7feee8bdad3c5d58dcbeb3da08b122ff27760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002a48431f5c100000000000000000000000038cb00e044d3cdd3c9f90b7efde61ef62e38fdf3000000000000000000000000928a1909db63ae7813e6318d098fd17439ec0a49000000000000000000000000cf360f1fc8763a38e3e1a19947bceb9f764a7a7c000000000000000000000000aaa2a36dc9ae3574cc5bd08b3564867b0b2ed0f3000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000045745544800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d577261707065642045746865720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "nonce": "0x0", "to": "0xdf45f4790e20509959fccc0d09245b216abdaa37", "transactionIndex": "0x0", diff --git a/crates/integration/testdata/validium/witnesses/367_validium_txs.json b/crates/integration/testdata/validium/witnesses/367_validium_txs.json index 84306180..f09c9a3c 100644 --- a/crates/integration/testdata/validium/witnesses/367_validium_txs.json +++ b/crates/integration/testdata/validium/witnesses/367_validium_txs.json @@ -5,8 +5,8 @@ "from": "0xfeea7a92fd46c25a475829f1975876ba48c13ceb", "gas": "0xf4240", "gasPrice": "0x0", - "hash": "0xb9be91cef46b54b88af78f16b5b0305d57b564b7aca4c2f17f00648bc14b5286", - "input": "0x8ef1332e000000000000000000000000fbe0c68e2241aa4e65c553e558a1f87ae920e562000000000000000000000000694c7feee8bdad3c5d58dcbeb3da08b122ff27760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000344f839517f00000000000000000000000038cb00e044d3cdd3c9f90b7efde61ef62e38fdf3000000000000000000000000928a1909db63ae7813e6318d098fd17439ec0a49000000000000000000000000cf360f1fc8763a38e3e1a19947bceb9f764a7a7c00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000007504fc98849efec8cbd82c82f88170e30cfeee13a16814fdbce13b08b3c33fb7a7bbeb6ff6ed96b0f5e773582ef20c9901f952068dbfdd76ad18f47ccd228d0d38dabb6563a8b033af894af4567cbc96ff3c421620319f44a70c4e0563d169c88fec22e90d2ad36694bc6ea06004d27259e346cbb81d000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000045745544800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d577261707065642045746865720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "hash": "0xb3d13d24b87a716f270e24ecb5e6d6fb7b8b49e761d815a06daf4cbf19d63340", + "input": "0x8ef1332e000000000000000000000000fbe0c68e2241aa4e65c553e558a1f87ae920e562000000000000000000000000694c7feee8bdad3c5d58dcbeb3da08b122ff27760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002a48431f5c100000000000000000000000038cb00e044d3cdd3c9f90b7efde61ef62e38fdf3000000000000000000000000928a1909db63ae7813e6318d098fd17439ec0a49000000000000000000000000cf360f1fc8763a38e3e1a19947bceb9f764a7a7c0000000000000000000000003c21c3f27cfed594105e8fccdb8acbae5e7c7a04000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000045745544800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d577261707065642045746865720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "nonce": "0x0", "to": "0xdf45f4790e20509959fccc0d09245b216abdaa37", "transactionIndex": "0x0", diff --git a/crates/integration/testdata/validium/witnesses/397_validium_txs.json b/crates/integration/testdata/validium/witnesses/397_validium_txs.json index 94e1bd81..9c66d726 100644 --- a/crates/integration/testdata/validium/witnesses/397_validium_txs.json +++ b/crates/integration/testdata/validium/witnesses/397_validium_txs.json @@ -5,8 +5,8 @@ "from": "0xfeea7a92fd46c25a475829f1975876ba48c13ceb", "gas": "0xf4240", "gasPrice": "0x0", - "hash": "0x48594f3ac763e40087a762e9e49d2f472fe63b45a08802117e86dfc8293a5e1c", - "input": "0x8ef1332e000000000000000000000000fbe0c68e2241aa4e65c553e558a1f87ae920e562000000000000000000000000694c7feee8bdad3c5d58dcbeb3da08b122ff27760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000344f839517f00000000000000000000000038cb00e044d3cdd3c9f90b7efde61ef62e38fdf3000000000000000000000000928a1909db63ae7813e6318d098fd17439ec0a49000000000000000000000000cf360f1fc8763a38e3e1a19947bceb9f764a7a7c00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000007504a928b626e9f3420e05aa33c24616c6a7389bf9925390caeff341a9613f065788b8efbba5f2424ddb48a0c4f6254a67aa57753116d44905cd5ab6d9ca5a9715cfa11cff5a3047a766e7444ff1bdc786bb5bfe5a91f6ff4dfa59394bca5c2b3e203f98cf6e06ae19790c00b6ee488f980aa6d0f039000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000045745544800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d577261707065642045746865720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "hash": "0xfbc06aac379325a19cb199253cc42b4fcd8cb5971a215636420dcf8ca1652ae8", + "input": "0x8ef1332e000000000000000000000000fbe0c68e2241aa4e65c553e558a1f87ae920e562000000000000000000000000694c7feee8bdad3c5d58dcbeb3da08b122ff27760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002a48431f5c100000000000000000000000038cb00e044d3cdd3c9f90b7efde61ef62e38fdf3000000000000000000000000928a1909db63ae7813e6318d098fd17439ec0a49000000000000000000000000cf360f1fc8763a38e3e1a19947bceb9f764a7a7c00000000000000000000000028d77629c6a8220538c351cc6bab30da0d395e34000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000045745544800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d577261707065642045746865720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "nonce": "0x0", "to": "0xdf45f4790e20509959fccc0d09245b216abdaa37", "transactionIndex": "0x0", diff --git a/crates/integration/tests/batch_circuit.rs b/crates/integration/tests/batch_circuit.rs index c75505ad..1adedcd8 100644 --- a/crates/integration/tests/batch_circuit.rs +++ b/crates/integration/tests/batch_circuit.rs @@ -5,9 +5,10 @@ use scroll_zkvm_integration::{ chunk::{ChunkProverTester, create_canonical_tasks, preset_chunk_multiple}, load_local_task, }, - testing_hardfork, + testing_version, }; use scroll_zkvm_prover::task::ProvingTask; +use scroll_zkvm_types::public_inputs::Version; #[ignore = "need local stuff"] #[test] @@ -74,22 +75,29 @@ fn verify_batch_hash_invariant() -> eyre::Result<()> { BatchProverTester::setup(true)?; let outcome_1 = preset_chunk_multiple(); - let outcome_2 = create_canonical_tasks( - match testing_hardfork() { - ForkName::EuclidV1 => vec![ + let (version, block_range) = match testing_version().fork { + ForkName::EuclidV1 => ( + Version::euclid_v1(), + vec![ 12508460u64..=12508461u64, 12508462u64..=12508462u64, 12508463u64..=12508463u64, ], - ForkName::EuclidV2 => vec![1u64..=2u64, 3u64..=3u64, 4u64..=4u64], - ForkName::Feynman => vec![ + ), + ForkName::EuclidV2 => ( + Version::euclid_v2(), + vec![1u64..=2u64, 3u64..=3u64, 4u64..=4u64], + ), + ForkName::Feynman => ( + Version::feynman(), + vec![ 16525000u64..=16525001u64, 16525002u64..=16525002u64, 16525003u64..=16525003u64, ], - } - .into_iter(), - )?; + ), + }; + let outcome_2 = create_canonical_tasks(version, block_range.into_iter())?; let mut task_1 = BatchTaskGenerator::from_chunk_tasks(&outcome_1, None); let mut task_2 = BatchTaskGenerator::from_chunk_tasks(&outcome_2, None); diff --git a/crates/integration/tests/bundle_circuit.rs b/crates/integration/tests/bundle_circuit.rs index e4f50176..be2c0c7b 100644 --- a/crates/integration/tests/bundle_circuit.rs +++ b/crates/integration/tests/bundle_circuit.rs @@ -1,28 +1,30 @@ use sbv_primitives::B256; use scroll_zkvm_integration::{ - ProverTester, // utils::{LastHeader, build_batch_task, testing_hardfork}, + ProverTester, testers::{ - batch::{BatchProverTester, preset_batch_multiple}, + batch::{BatchProverTester, preset_batch_multiple, preset_batch_validium}, bundle::{BundleProverTester, BundleTaskGenerator}, chunk::ChunkProverTester, load_local_task, }, - testing_hardfork, + testing_hardfork, testing_version_validium, utils::metadata_from_bundle_witnesses, }; -use scroll_zkvm_prover::{ - // AsRootProof, BatchProof, ChunkProof, IntoEvmProof, - // setup::{read_app_config, read_app_exe}, - Prover, - ProverConfig, +use scroll_zkvm_prover::{Prover, ProverConfig}; +use scroll_zkvm_types::{ + proof::OpenVmEvmProof, + public_inputs::{ForkName, MultiVersionPublicInputs}, }; -use scroll_zkvm_types::{proof::OpenVmEvmProof, public_inputs::ForkName}; use std::str::FromStr; fn preset_bundle() -> BundleTaskGenerator { BundleTaskGenerator::from_batch_tasks(&preset_batch_multiple()) } +fn preset_bundle_validium() -> BundleTaskGenerator { + BundleTaskGenerator::from_batch_tasks(&preset_batch_validium()) +} + #[test] fn print_vks() -> eyre::Result<()> { #[derive(Default, Debug, serde::Serialize)] @@ -108,6 +110,7 @@ fn verify_bundle_info_pi() { "0x97f9728ad48ff896b4272abcecd9a6a46577c24fbf2504f5ed2c3178c857263a", ) .unwrap(), + encryption_key: None, }; assert_eq!( @@ -163,3 +166,36 @@ fn e2e() -> eyre::Result<()> { Ok(()) } + +#[test] +fn test_execute_validium() -> eyre::Result<()> { + BundleProverTester::setup(true)?; + + let version = testing_version_validium(); + + let mut chunk_prover = ChunkProverTester::load_prover(false)?; + let mut batch_prover = BatchProverTester::load_prover(false)?; + let mut bundle_prover = BundleProverTester::load_prover(true)?; + + let mut task = preset_bundle_validium(); + let wit = task.get_or_build_witness()?; + let metadata = metadata_from_bundle_witnesses(&wit)?; + let expected_pi_hash = metadata.pi_hash_by_version(version); + + let proof = + task.get_or_build_proof(&mut bundle_prover, &mut batch_prover, &mut chunk_prover)?; + let evm_proof: OpenVmEvmProof = proof.into_evm_proof().unwrap().into(); + let observed_instances = &evm_proof.user_public_values; + for (i, (&expected, &observed)) in expected_pi_hash + .iter() + .zip(observed_instances.iter()) + .enumerate() + { + assert_eq!( + expected, observed, + "pi inconsistent at index {i}: expected={expected}, observed={observed:?}" + ); + } + + Ok(()) +} diff --git a/crates/integration/tests/chunk_circuit.rs b/crates/integration/tests/chunk_circuit.rs index a715c7c7..674857d4 100644 --- a/crates/integration/tests/chunk_circuit.rs +++ b/crates/integration/tests/chunk_circuit.rs @@ -1,4 +1,8 @@ +use alloy_primitives::B256; use eyre::Ok; +use sbv_primitives::types::consensus::TxL1Message; +use scroll_zkvm_integration::testers::PATH_TESTDATA; +use scroll_zkvm_integration::testers::chunk::read_block_witness; use scroll_zkvm_integration::testers::chunk::{exec_chunk, execute_multi}; use scroll_zkvm_integration::utils::get_rayon_threads; use scroll_zkvm_integration::{ @@ -9,7 +13,11 @@ use scroll_zkvm_integration::{ }, utils::metadata_from_chunk_witnesses, }; -use scroll_zkvm_types::chunk::ChunkWitness; +use scroll_zkvm_prover::utils::read_json; +use scroll_zkvm_types::chunk::{ChunkWitness, SecretKey}; +use scroll_zkvm_types::public_inputs::Version; +use std::env; +use std::path::Path; #[ignore = "can only run under eculidv2 hardfork"] #[test] @@ -45,6 +53,35 @@ fn test_execute() -> eyre::Result<()> { Ok(()) } +#[test] +fn test_execute_validium() -> eyre::Result<()> { + ChunkProverTester::setup(true)?; + + let base_dir = Path::new(PATH_TESTDATA).join("validium"); + + let secret_key = hex::decode(env::var("VALIDIUM_KEY")?)?; + let secret_key = SecretKey::try_from_bytes(&secret_key)?; + + for blk in [1019, 1256, 1276, 1141071] { + let block_witness = read_block_witness(base_dir.join(format!("{blk}.json")))?; + let validium_txs: Vec = + read_json(base_dir.join(format!("{blk}_validium_txs.json")))?; + + let version = Version::validium_v1(); + let witness = ChunkWitness::new_validium( + version.as_version_byte(), + &[block_witness], + B256::ZERO, + version.fork, + vec![validium_txs], + secret_key.clone(), + ); + + exec_chunk(&witness)?; + } + Ok(()) +} + #[ignore = "can only run under eculidv2 hardfork"] #[test] fn test_autofill_trie_nodes() -> eyre::Result<()> { @@ -53,7 +90,8 @@ fn test_autofill_trie_nodes() -> eyre::Result<()> { let mut template_wit = get_witness_from_env_or_builder(&mut preset_chunk())?; template_wit.blocks.truncate(1); - let wit = ChunkWitness::new( + let wit = ChunkWitness::new_scroll( + template_wit.version, &template_wit.blocks, template_wit.prev_msg_queue_hash, template_wit.fork_name, diff --git a/crates/types/base/src/lib.rs b/crates/types/base/src/lib.rs index 23727b7d..758b2118 100644 --- a/crates/types/base/src/lib.rs +++ b/crates/types/base/src/lib.rs @@ -1,4 +1,9 @@ pub mod aggregation; + pub mod fork_name; + pub mod public_inputs; + pub mod utils; + +pub mod version; diff --git a/crates/types/base/src/public_inputs.rs b/crates/types/base/src/public_inputs.rs index 5fabb3b5..03a0dda4 100644 --- a/crates/types/base/src/public_inputs.rs +++ b/crates/types/base/src/public_inputs.rs @@ -3,7 +3,8 @@ use alloy_primitives::B256; pub mod batch; pub mod bundle; pub mod chunk; -pub use crate::fork_name::ForkName; + +pub use crate::{fork_name::ForkName, version::Version}; /// Defines behaviour to be implemented by types representing the public-input values of a circuit. pub trait PublicInputs { @@ -18,16 +19,20 @@ pub trait PublicInputs { /// helper trait to extend PublicInputs pub trait MultiVersionPublicInputs { fn pi_hash_by_fork(&self, fork_name: ForkName) -> B256; - fn validate(&self, prev_pi: &Self, fork_name: ForkName); + fn pi_hash_by_version(&self, version: Version) -> B256; + fn validate(&self, prev_pi: &Self, version: Version); } -impl PublicInputs for (T, ForkName) { +impl PublicInputs for (T, Version) { fn pi_hash(&self) -> B256 { - self.0.pi_hash_by_fork(self.1) + self.0.pi_hash_by_version(self.1) } fn validate(&self, prev_pi: &Self) { - assert_eq!(self.1, prev_pi.1); + // version remains unchanged. + assert_eq!(self.1.as_version_byte(), prev_pi.1.as_version_byte()); + + // perform inner validation. self.0.validate(&prev_pi.0, self.1) } } diff --git a/crates/types/base/src/public_inputs/batch.rs b/crates/types/base/src/public_inputs/batch.rs index be93c409..ed1bb31c 100644 --- a/crates/types/base/src/public_inputs/batch.rs +++ b/crates/types/base/src/public_inputs/batch.rs @@ -3,6 +3,7 @@ use alloy_primitives::B256; use crate::{ public_inputs::{ForkName, MultiVersionPublicInputs}, utils::keccak256, + version::{Domain, STFVersion, Version}, }; /// Represents public-input values for a batch. @@ -41,6 +42,9 @@ pub struct BatchInfo { /// The L1 msg queue hash at the end of the current batch. #[rkyv()] pub post_msg_queue_hash: B256, + /// Optional encryption key, used in case of domain=Validium. + #[rkyv()] + pub encryption_key: Option>, } impl BatchInfo { @@ -79,7 +83,7 @@ impl BatchInfo { /// withdraw root || /// prev msg queue hash || /// post msg queue hash - /// ) + /// ) fn pi_hash_euclidv2(&self) -> B256 { keccak256( std::iter::empty() @@ -95,18 +99,66 @@ impl BatchInfo { .collect::>(), ) } + + /// Public input hash for a batch (feynman or da-codec@v8). + /// + /// Unchanged from euclid-v2. + fn pi_hash_feynman(&self) -> B256 { + self.pi_hash_euclidv2() + } + + /// Public input hash for a L3 validium @ v1. + /// + /// keccak( + /// version || + /// parent state root || + /// parent batch hash || + /// state root || + /// batch hash || + /// chain id || + /// withdraw root || + /// prev msg queue hash || + /// post msg queue hash + /// encryption key + /// ) + fn pi_hash_validium(&self, version: Version) -> B256 { + keccak256( + std::iter::empty() + .chain(&[version.as_version_byte()]) + .chain(self.parent_state_root.as_slice()) + .chain(self.parent_batch_hash.as_slice()) + .chain(self.state_root.as_slice()) + .chain(self.batch_hash.as_slice()) + .chain(self.chain_id.to_be_bytes().as_slice()) + .chain(self.withdraw_root.as_slice()) + .chain(self.prev_msg_queue_hash.as_slice()) + .chain(self.post_msg_queue_hash.as_slice()) + .chain(self.encryption_key.as_ref().expect("domain=Validium")) + .cloned() + .collect::>(), + ) + } } -pub type VersionedBatchInfo = (BatchInfo, ForkName); +pub type VersionedBatchInfo = (BatchInfo, Version); impl MultiVersionPublicInputs for BatchInfo { fn pi_hash_by_fork(&self, fork_name: ForkName) -> B256 { match fork_name { ForkName::EuclidV1 => self.pi_hash_euclidv1(), ForkName::EuclidV2 => self.pi_hash_euclidv2(), - ForkName::Feynman => { - // Feynman fork uses the same hash as EuclidV2 - self.pi_hash_euclidv2() + ForkName::Feynman => self.pi_hash_feynman(), + } + } + + fn pi_hash_by_version(&self, version: Version) -> B256 { + match (version.domain, version.stf_version) { + (Domain::Scroll, STFVersion::V6) => self.pi_hash_by_fork(ForkName::EuclidV1), + (Domain::Scroll, STFVersion::V7) => self.pi_hash_by_fork(ForkName::EuclidV2), + (Domain::Scroll, STFVersion::V8) => self.pi_hash_by_fork(ForkName::Feynman), + (Domain::Validium, STFVersion::V1) => self.pi_hash_validium(version), + (domain, stf_version) => { + unreachable!("unsupported version=({domain:?}, {stf_version:?})") } } } @@ -117,17 +169,22 @@ impl MultiVersionPublicInputs for BatchInfo { /// - state roots MUST be chained /// - batch hashes MUST be chained /// - L1 msg queue hashes MUST be chained - fn validate(&self, prev_pi: &Self, fork_name: ForkName) { + fn validate(&self, prev_pi: &Self, version: Version) { assert_eq!(self.chain_id, prev_pi.chain_id); assert_eq!(self.parent_state_root, prev_pi.state_root); assert_eq!(self.parent_batch_hash, prev_pi.batch_hash); assert_eq!(self.prev_msg_queue_hash, prev_pi.post_msg_queue_hash); - if fork_name == ForkName::EuclidV1 { + if version.fork == ForkName::EuclidV1 { assert_eq!(self.prev_msg_queue_hash, B256::ZERO); assert_eq!(prev_pi.prev_msg_queue_hash, B256::ZERO); assert_eq!(self.post_msg_queue_hash, B256::ZERO); assert_eq!(prev_pi.post_msg_queue_hash, B256::ZERO); } + + if version.domain == Domain::Validium { + assert!(self.encryption_key.is_some()); + assert_eq!(self.encryption_key, prev_pi.encryption_key); + } } } diff --git a/crates/types/base/src/public_inputs/bundle.rs b/crates/types/base/src/public_inputs/bundle.rs index 928e08e5..ae0e5594 100644 --- a/crates/types/base/src/public_inputs/bundle.rs +++ b/crates/types/base/src/public_inputs/bundle.rs @@ -3,6 +3,7 @@ use alloy_primitives::B256; use crate::{ public_inputs::{ForkName, MultiVersionPublicInputs}, utils::keccak256, + version::{Domain, STFVersion, Version}, }; /// Represents fields required to compute the public-inputs digest of a bundle. @@ -32,6 +33,8 @@ pub struct BundleInfo { pub batch_hash: B256, /// The withdrawals root at the last block in the last chunk in the last batch in the bundle. pub withdraw_root: B256, + /// Optional encryption key, used in the case of domain=Validium. + pub encryption_key: Option>, } impl BundleInfo { @@ -102,6 +105,25 @@ impl BundleInfo { keccak256(pi) } + pub fn pi_hash_versioned(&self, version: Version, pi: &[u8]) -> B256 { + let version_byte = version.as_version_byte(); + keccak256( + std::iter::empty() + .chain(B256::left_padding_from(&version_byte.to_be_bytes()).as_slice()) + .chain(pi) + .cloned() + .collect::>(), + ) + } + + pub fn pi_validium_v1(&self) -> Vec { + std::iter::empty() + .chain(self.pi_euclidv2().as_slice()) + .chain(self.encryption_key.as_ref().expect("domain=Validium")) + .cloned() + .collect() + } + pub fn pi_hash(&self, fork_name: ForkName) -> B256 { match fork_name { ForkName::EuclidV1 => self.pi_hash_euclidv1(), @@ -111,7 +133,7 @@ impl BundleInfo { } } -pub type VersionedBundleInfo = (BundleInfo, ForkName); +pub type VersionedBundleInfo = (BundleInfo, Version); impl MultiVersionPublicInputs for BundleInfo { fn pi_hash_by_fork(&self, fork_name: ForkName) -> B256 { @@ -122,7 +144,21 @@ impl MultiVersionPublicInputs for BundleInfo { } } - fn validate(&self, _prev_pi: &Self, _fork_name: ForkName) { + fn pi_hash_by_version(&self, version: Version) -> B256 { + match (version.domain, version.stf_version) { + (Domain::Scroll, STFVersion::V6) => self.pi_hash_euclidv1(), + (Domain::Scroll, STFVersion::V7) => self.pi_hash_euclidv2(), + (Domain::Scroll, STFVersion::V8) => self.pi_hash_feynman(), + (Domain::Validium, STFVersion::V1) => { + self.pi_hash_versioned(version, self.pi_validium_v1().as_slice()) + } + (domain, stf_version) => { + unreachable!("unsupported version=({domain:?}, {stf_version:?})") + } + } + } + + fn validate(&self, _prev_pi: &Self, _version: Version) { unreachable!("bundle is the last layer and is not aggregated by any other circuit"); } } diff --git a/crates/types/base/src/public_inputs/chunk.rs b/crates/types/base/src/public_inputs/chunk.rs index fbb3f952..37a43226 100644 --- a/crates/types/base/src/public_inputs/chunk.rs +++ b/crates/types/base/src/public_inputs/chunk.rs @@ -1,6 +1,7 @@ use crate::{ public_inputs::{ForkName, MultiVersionPublicInputs}, utils::keccak256, + version::{Domain, STFVersion, Version}, }; use alloy_primitives::{B256, U256}; @@ -79,6 +80,41 @@ impl BlockContextV2 { } } +/// Represents header-like information for the chunk. +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct ChunkInfo { + /// The EIP-155 chain ID for all txs in the chunk. + pub chain_id: u64, + /// The state root before applying the chunk. + pub prev_state_root: B256, + /// The state root after applying the chunk. + pub post_state_root: B256, + /// The withdrawals root after applying the chunk. + pub withdraw_root: B256, + /// Digest of L1 message txs force included in the chunk. + /// It is a legacy field and can be omitted in new defination + #[serde(default)] + pub data_hash: B256, + /// Digest of L2 tx data flattened over all L2 txs in the chunk. + pub tx_data_digest: B256, + /// The L1 msg queue hash at the end of the previous chunk. + pub prev_msg_queue_hash: B256, + /// The L1 msg queue hash at the end of the current chunk. + pub post_msg_queue_hash: B256, + /// The length of rlp encoded L2 tx bytes flattened over all L2 txs in the chunk. + pub tx_data_length: u64, + /// The block number of the first block in the chunk. + pub initial_block_number: u64, + /// The block contexts of the blocks in the chunk. + pub block_ctxs: Vec, + /// The blockhash of the last block in the previous chunk. + pub prev_blockhash: B256, + /// The blockhash of the last block in the current chunk. + pub post_blockhash: B256, + /// Optional encryption key for encrypted L1 msgs, which is used in case of domain=Validium. + pub encryption_key: Option>, +} + /// Represents header-like information for the chunk. #[derive( Debug, @@ -90,7 +126,7 @@ impl BlockContextV2 { serde::Serialize, )] #[rkyv(derive(Debug))] -pub struct ChunkInfo { +pub struct LegacyChunkInfo { /// The EIP-155 chain ID for all txs in the chunk. #[rkyv()] pub chain_id: u64, @@ -127,6 +163,53 @@ pub struct ChunkInfo { #[rkyv()] pub block_ctxs: Vec, } +impl std::fmt::Display for ChunkInfo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // Create a wrapper struct that implements Debug + struct DisplayWrapper<'a>(&'a ChunkInfo); + + impl<'a> std::fmt::Debug for DisplayWrapper<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ChunkInfo") + .field("chain_id", &self.0.chain_id) + .field("prev_state_root", &self.0.prev_state_root) + .field("post_state_root", &self.0.post_state_root) + .field("withdraw_root", &self.0.withdraw_root) + .field("data_hash", &self.0.data_hash) + .field("tx_data_digest", &self.0.tx_data_digest) + .field("prev_msg_queue_hash", &self.0.prev_msg_queue_hash) + .field("post_msg_queue_hash", &self.0.post_msg_queue_hash) + .field("tx_data_length", &self.0.tx_data_length) + .field("initial_block_number", &self.0.initial_block_number) + .field("prev_blockhash", &self.0.prev_blockhash) + .field("post_blockhash", &self.0.post_blockhash) + .field("block_ctxs", &"") + .finish() + } + } + + // Use the Debug implementation with pretty formatting + write!(f, "{:#?}", DisplayWrapper(self)) + } +} + +impl From for LegacyChunkInfo { + fn from(value: ChunkInfo) -> Self { + Self { + chain_id: value.chain_id, + prev_state_root: value.prev_state_root, + post_state_root: value.post_state_root, + withdraw_root: value.withdraw_root, + data_hash: value.data_hash, + tx_data_digest: value.tx_data_digest, + prev_msg_queue_hash: value.prev_msg_queue_hash, + post_msg_queue_hash: value.post_msg_queue_hash, + tx_data_length: value.tx_data_length, + initial_block_number: value.initial_block_number, + block_ctxs: value.block_ctxs, + } + } +} impl ChunkInfo { /// Public input hash for a given chunk (euclidv1 or da-codec@v6) is defined as @@ -188,9 +271,53 @@ impl ChunkInfo { .collect::>(), ) } + + /// Public input hash for a given chunk for L3 validium @ v1: + /// + /// keccak( + /// version || + /// chain id || + /// prev state root || + /// post state root || + /// withdraw root || + /// tx data digest || + /// prev msg queue hash || + /// post msg queue hash || + /// initial block number || + /// block_ctx for block_ctx in block_ctxs || + /// prev blockhash || + /// post blockhash || + /// encryption key + /// ) + pub fn pi_hash_validium(&self, version: Version) -> B256 { + keccak256( + std::iter::empty() + .chain(&[version.as_version_byte()]) + .chain(&self.chain_id.to_be_bytes()) + .chain(self.prev_state_root.as_slice()) + .chain(self.post_state_root.as_slice()) + .chain(self.withdraw_root.as_slice()) + .chain(self.tx_data_digest.as_slice()) + .chain(self.prev_msg_queue_hash.as_slice()) + .chain(self.post_msg_queue_hash.as_slice()) + .chain(&self.initial_block_number.to_be_bytes()) + .chain( + self.block_ctxs + .iter() + .flat_map(|block_ctx| block_ctx.to_bytes()) + .collect::>() + .as_slice(), + ) + .chain(self.prev_blockhash.as_slice()) + .chain(self.post_blockhash.as_slice()) + .chain(self.encryption_key.as_ref().expect("domain=Validium")) + .cloned() + .collect::>(), + ) + } } -pub type VersionedChunkInfo = (ChunkInfo, ForkName); +pub type VersionedChunkInfo = (ChunkInfo, Version); impl MultiVersionPublicInputs for ChunkInfo { /// Compute the public input hash for the chunk. @@ -208,22 +335,51 @@ impl MultiVersionPublicInputs for ChunkInfo { } } + /// Compute the public input hash for the chunk given the version tuple. + fn pi_hash_by_version(&self, version: Version) -> B256 { + match (version.domain, version.stf_version) { + (Domain::Scroll, STFVersion::V6) => self.pi_hash_by_fork(ForkName::EuclidV1), + (Domain::Scroll, STFVersion::V7) => self.pi_hash_by_fork(ForkName::EuclidV2), + (Domain::Scroll, STFVersion::V8) => self.pi_hash_by_fork(ForkName::Feynman), + (Domain::Validium, STFVersion::V1) => self.pi_hash_validium(version), + (domain, stf_version) => { + unreachable!("unsupported version=({domain:?}, {stf_version:?})") + } + } + } + /// Validate public inputs between 2 contiguous chunks. /// /// - chain id MUST match /// - state roots MUST be chained /// - L1 msg queue hash MUST be chained - fn validate(&self, prev_pi: &Self, fork_name: ForkName) { + /// + /// Furthermore, for validiums we must also chain the blockhashes. + fn validate(&self, prev_pi: &Self, version: Version) { assert_eq!(self.chain_id, prev_pi.chain_id); assert_eq!(self.prev_state_root, prev_pi.post_state_root); assert_eq!(self.prev_msg_queue_hash, prev_pi.post_msg_queue_hash); // message queue hash is used only after euclidv2 (da-codec@v7) - if fork_name == ForkName::EuclidV1 { + if version.fork == ForkName::EuclidV1 { assert_eq!(self.prev_msg_queue_hash, B256::ZERO); assert_eq!(prev_pi.prev_msg_queue_hash, B256::ZERO); assert_eq!(self.post_msg_queue_hash, B256::ZERO); assert_eq!(prev_pi.post_msg_queue_hash, B256::ZERO); } + + // blockhash is unused for scroll domain. + if version.domain == Domain::Scroll { + assert_eq!(self.prev_blockhash, B256::ZERO); + assert_eq!(self.post_blockhash, B256::ZERO); + } + + // - blockhash chaining must be validated for validiums. + // - encryption key must be the same between contiguous chunks in a batch. + if version.domain == Domain::Validium { + assert_eq!(self.prev_blockhash, prev_pi.post_blockhash); + assert!(self.encryption_key.is_some()); + assert_eq!(self.encryption_key, prev_pi.encryption_key); + } } } diff --git a/crates/types/base/src/version.rs b/crates/types/base/src/version.rs new file mode 100644 index 00000000..16f47aee --- /dev/null +++ b/crates/types/base/src/version.rs @@ -0,0 +1,174 @@ +//! Module includes various types and logic pertaining to the versioning system under Scroll's +//! proving system. +//! +//! In order to identify the appropriate EVM fork logic and codec version for the encoded data, we +//! make use of a versioning system specified by the tuple `(domain,stf_version)`. +//! +//! The [`Domain`] indicates the execution of "what" are we proving? +//! +//! The [`STFVersion`] indicates an incremental version used within that domain. +//! +//! The tuple `(domain,stf_version)` maps to a unique tuple `(fork,codec)` that tells us which EVM fork +//! logic and codec logic must be utilised to decode data and execute transactions that are being +//! proven. +//! +//! The version is a single byte that encodes the tuple `(domain,stf_version)` such that: +//! +//! | bit index | purpose | +//! |-----------|-------------| +//! | 0..=1 | domain | +//! | 2..=7 | stf_version | + +use crate::public_inputs::ForkName; + +/// Protocol `domain` in the protocol=(domain,version) tuple. +/// +/// Domain is represented using 2 bits, i.e. we can support at the most 4 domains as per the latest +/// codec. +#[derive(Clone, Copy, Debug, PartialEq, serde::Deserialize, serde::Serialize)] +pub enum Domain { + /// Domain used for Scroll. + Scroll = 0, + /// Domain used for L3 validiums running on L2 Scroll. + Validium = 1, +} + +impl From for Domain { + fn from(value: u8) -> Self { + match value { + 0 => Self::Scroll, + 1 => Self::Validium, + value => unreachable!("unsupported domain={value}"), + } + } +} + +/// The state-transition-function's incremental version. +#[derive(Clone, Copy, Debug, serde::Deserialize, serde::Serialize)] +pub enum STFVersion { + /// Validium@v1. + V1 = 1, + /// Scroll@v6. + V6 = 6, + /// Scroll@v7. + V7 = 7, + /// Scroll@v8. + V8 = 8, +} + +impl From for STFVersion { + fn from(value: u8) -> Self { + match value { + 1 => Self::V1, + 6 => Self::V6, + 7 => Self::V7, + 8 => Self::V8, + value => unreachable!("unsupported stf-version={value}"), + } + } +} + +/// The codec version. +#[derive(Clone, Copy, Debug, serde::Deserialize, serde::Serialize)] +pub enum Codec { + /// da-codec@v6. + V6, + /// da-codec@v7. + V7, + /// da-codec@v8. + V8, + /// da-codec@v9. + V9, +} + +/// The number of bits used for [`STFVersion`]. +const N_BITS_STF_VERSION: u8 = 6; + +/// Mask and get the [`STFVersion`] from the version byte. +const MASK_STF_VERSION: u8 = 0b00111111; + +/// A fully parsed version that includes all necessary identifiers. +#[derive(Clone, Copy, Debug, serde::Deserialize, serde::Serialize)] +pub struct Version { + /// Domain. + pub domain: Domain, + /// STF-version. + pub stf_version: STFVersion, + /// EVM fork name. + pub fork: ForkName, + /// DA-codec version. + pub codec: Codec, +} + +impl Version { + pub const fn as_version_byte(&self) -> u8 { + ((self.domain as u8) << N_BITS_STF_VERSION) + (self.stf_version as u8) + } + + pub const fn euclid_v1() -> Self { + Self { + domain: Domain::Scroll, + stf_version: STFVersion::V6, + fork: ForkName::EuclidV1, + codec: Codec::V6, + } + } + + pub const fn euclid_v2() -> Self { + Self { + domain: Domain::Scroll, + stf_version: STFVersion::V7, + fork: ForkName::EuclidV2, + codec: Codec::V7, + } + } + + pub const fn feynman() -> Self { + Self { + domain: Domain::Scroll, + stf_version: STFVersion::V8, + fork: ForkName::Feynman, + codec: Codec::V8, + } + } + + pub const fn validium_v1() -> Self { + Self { + domain: Domain::Validium, + stf_version: STFVersion::V1, + fork: ForkName::Feynman, + codec: Codec::V9, + } + } + + pub fn is_validium(&self) -> bool { + self.domain == Domain::Validium + } +} + +impl Default for Version { + fn default() -> Self { + Self::feynman() + } +} + +impl From for Version { + fn from(value: u8) -> Self { + let domain = Domain::from(value >> N_BITS_STF_VERSION); + let stf_version = STFVersion::from(value & MASK_STF_VERSION); + + match (domain, stf_version) { + (Domain::Scroll, STFVersion::V6) => Self::euclid_v1(), + (Domain::Scroll, STFVersion::V7) => Self::euclid_v2(), + (Domain::Scroll, STFVersion::V8) => Self::feynman(), + (Domain::Validium, STFVersion::V1) => Self::validium_v1(), + (domain, stf_version) => { + unreachable!("unsupported version=({domain:?}, {stf_version:?})") + } + } + } +} + +/// Version byte for Validium @ v1. +pub const VALIDIUM_V1: u8 = + ((Domain::Validium as u8) << N_BITS_STF_VERSION) + (STFVersion::V1 as u8); diff --git a/crates/types/batch/src/builder/mod.rs b/crates/types/batch/src/builder/mod.rs index 62c96590..591eef27 100644 --- a/crates/types/batch/src/builder/mod.rs +++ b/crates/types/batch/src/builder/mod.rs @@ -7,6 +7,8 @@ pub use v7::BatchInfoBuilderV7; pub mod v8; pub use v8::BatchInfoBuilderV8; +pub mod validium; + use types_base::public_inputs::{batch::BatchInfo, chunk::ChunkInfo}; use crate::{ diff --git a/crates/types/batch/src/builder/v6.rs b/crates/types/batch/src/builder/v6.rs index 7824637e..826aca4e 100644 --- a/crates/types/batch/src/builder/v6.rs +++ b/crates/types/batch/src/builder/v6.rs @@ -52,6 +52,7 @@ impl super::BatchInfoBuilder for BatchInfoBuilderV6 { withdraw_root: last.withdraw_root, prev_msg_queue_hash: Default::default(), post_msg_queue_hash: Default::default(), + encryption_key: Default::default(), } } } diff --git a/crates/types/batch/src/builder/v7.rs b/crates/types/batch/src/builder/v7.rs index d57aec02..2b8d58ff 100644 --- a/crates/types/batch/src/builder/v7.rs +++ b/crates/types/batch/src/builder/v7.rs @@ -109,6 +109,7 @@ impl super::BatchInfoBuilder for GenericBatchInfoBuilderV7

{ withdraw_root: last_chunk.withdraw_root, prev_msg_queue_hash: first_chunk.prev_msg_queue_hash, post_msg_queue_hash: last_chunk.post_msg_queue_hash, + encryption_key: None, } } } diff --git a/crates/types/batch/src/builder/validium.rs b/crates/types/batch/src/builder/validium.rs new file mode 100644 index 00000000..f3de0a48 --- /dev/null +++ b/crates/types/batch/src/builder/validium.rs @@ -0,0 +1,68 @@ +use types_base::{ + public_inputs::{batch::BatchInfo, chunk::ChunkInfo}, + version::Version, +}; + +use crate::header::{BatchHeader, ValidiumBatchHeader, validium::BatchHeaderValidium}; + +pub struct ValidiumBuilderArgs { + pub version: u8, + pub header: BatchHeaderValidium, + pub chunk_infos: Vec, +} + +impl ValidiumBuilderArgs { + pub fn new(version: u8, header: BatchHeaderValidium, chunk_infos: Vec) -> Self { + Self { + version, + header, + chunk_infos, + } + } +} + +pub struct ValidiumBatchInfoBuilder; + +impl ValidiumBatchInfoBuilder { + pub fn build(args: ValidiumBuilderArgs) -> BatchInfo { + // Check that the batch's STF-version is correct. + let version = Version::from(args.version); + assert_eq!(version.stf_version as u8, args.header.version()); + + match &args.header { + BatchHeaderValidium::V1(_) => { + // nothing to do for v1 header since blob data is not included in validium + } + } + + let (first_chunk, last_chunk) = ( + args.chunk_infos + .first() + .expect("at least one chunk in batch"), + args.chunk_infos + .last() + .expect("at least one chunk in batch"), + ); + + // Check that the batch's commitment field is set correctly. + assert_eq!(last_chunk.post_blockhash.to_vec(), args.header.commitment()); + + // Check that the batch's state root is correct. + assert_eq!(last_chunk.post_state_root, args.header.post_state_root()); + + // Check that the batch's withdraw root is correct. + assert_eq!(last_chunk.withdraw_root, args.header.withdraw_root()); + + BatchInfo { + parent_state_root: first_chunk.prev_state_root, + parent_batch_hash: args.header.parent_batch_hash(), + state_root: last_chunk.post_state_root, + batch_hash: args.header.batch_hash(), + chain_id: last_chunk.chain_id, + withdraw_root: last_chunk.withdraw_root, + prev_msg_queue_hash: first_chunk.prev_msg_queue_hash, + post_msg_queue_hash: last_chunk.post_msg_queue_hash, + encryption_key: first_chunk.encryption_key.clone(), + } + } +} diff --git a/crates/types/batch/src/header/mod.rs b/crates/types/batch/src/header/mod.rs index 84c368e0..befec940 100644 --- a/crates/types/batch/src/header/mod.rs +++ b/crates/types/batch/src/header/mod.rs @@ -6,6 +6,8 @@ pub mod v7; pub mod v8; +pub mod validium; + pub trait BatchHeader { /// The DA-codec version for the batch header. fn version(&self) -> u8; @@ -23,6 +25,17 @@ pub trait BatchHeader { fn blob_versioned_hash(&self) -> B256; } +pub trait ValidiumBatchHeader: BatchHeader { + /// The commitment attached to the batch header. + fn commitment(&self) -> Vec; + + /// The state root after applying batch. + fn post_state_root(&self) -> B256; + + /// The withdraw root from the last block in the batch. + fn withdraw_root(&self) -> B256; +} + /// Reference header indicate the version of batch header base on which batch hash /// should be calculated. #[derive( @@ -42,4 +55,6 @@ pub enum ReferenceHeader { V7(v7::BatchHeaderV7), /// Represents DA-codec v8. V8(v8::BatchHeaderV8), + /// Represents batch header utilised in L3 validium. + Validium(validium::BatchHeaderValidium), } diff --git a/crates/types/batch/src/header/validium.rs b/crates/types/batch/src/header/validium.rs new file mode 100644 index 00000000..6c8ded07 --- /dev/null +++ b/crates/types/batch/src/header/validium.rs @@ -0,0 +1,162 @@ +use alloy_primitives::B256; +use types_base::utils::keccak256; + +use super::{BatchHeader, ValidiumBatchHeader}; + +/// Batch header used in L3 validium. +#[derive( + Clone, + Copy, + Debug, + rkyv::Archive, + rkyv::Deserialize, + rkyv::Serialize, + serde::Deserialize, + serde::Serialize, +)] +#[rkyv(derive(Debug))] +pub enum BatchHeaderValidium { + /// L3 validium @ v1 batch header. + V1(BatchHeaderValidiumV1), +} + +/// Represents the batch header summarising a L3 validium batch. +#[derive( + Clone, + Copy, + Debug, + Default, + rkyv::Archive, + rkyv::Deserialize, + rkyv::Serialize, + serde::Deserialize, + serde::Serialize, +)] +#[rkyv(derive(Debug))] +pub struct BatchHeaderValidiumV1 { + /// The DA-codec version for the batch. + #[rkyv()] + pub version: u8, + /// The index of the batch + #[rkyv()] + pub batch_index: u64, + /// The parent batch hash + #[rkyv()] + pub parent_batch_hash: B256, + /// The state root after applying the batch. + #[rkyv()] + pub post_state_root: B256, + /// The withdraw root post the batch. + #[rkyv()] + pub withdraw_root: B256, + /// A commitment that binds the batch to its payload. It also serves provability based on the + /// finalised L2 data. + /// + /// We utilise the last L3 block's blockhash as commitment. + #[rkyv()] + pub commitment: B256, +} + +impl ValidiumBatchHeader for BatchHeaderValidium { + fn commitment(&self) -> Vec { + match self { + Self::V1(header) => header.commitment(), + } + } + fn post_state_root(&self) -> B256 { + match self { + Self::V1(header) => header.post_state_root(), + } + } + fn withdraw_root(&self) -> B256 { + match self { + Self::V1(header) => header.withdraw_root(), + } + } +} + +impl ValidiumBatchHeader for BatchHeaderValidiumV1 { + fn commitment(&self) -> Vec { + self.commitment.to_vec() + } + fn post_state_root(&self) -> B256 { + self.post_state_root + } + fn withdraw_root(&self) -> B256 { + self.withdraw_root + } +} + +impl BatchHeader for BatchHeaderValidium { + fn version(&self) -> u8 { + match self { + Self::V1(header) => header.version(), + } + } + + fn index(&self) -> u64 { + match self { + Self::V1(header) => header.index(), + } + } + + fn parent_batch_hash(&self) -> B256 { + match self { + Self::V1(header) => header.parent_batch_hash(), + } + } + + fn batch_hash(&self) -> B256 { + match self { + Self::V1(header) => header.batch_hash(), + } + } + + fn blob_versioned_hash(&self) -> B256 { + match self { + Self::V1(header) => header.blob_versioned_hash(), + } + } +} + +impl BatchHeader for BatchHeaderValidiumV1 { + fn version(&self) -> u8 { + self.version + } + + fn index(&self) -> u64 { + self.batch_index + } + + fn parent_batch_hash(&self) -> B256 { + self.parent_batch_hash + } + + /// Batch hash for Validium batch header v1: + /// + /// keccak( + /// version || + /// batch index || + /// parent batch hash || + /// post state root || + /// withdraw root || + /// commitment + /// ) + fn batch_hash(&self) -> B256 { + keccak256( + std::iter::empty() + .chain(vec![self.version].as_slice()) + .chain(self.batch_index.to_be_bytes().as_slice()) + .chain(self.parent_batch_hash.as_slice()) + .chain(self.post_state_root.as_slice()) + .chain(self.withdraw_root.as_slice()) + .chain(self.commitment.as_slice()) + .cloned() + .collect::>(), + ) + } + + fn blob_versioned_hash(&self) -> B256 { + B256::default() + } +} diff --git a/crates/types/batch/src/lib.rs b/crates/types/batch/src/lib.rs index 97278250..1e9c38be 100644 --- a/crates/types/batch/src/lib.rs +++ b/crates/types/batch/src/lib.rs @@ -4,6 +4,7 @@ pub use header::{ v6::{ArchivedBatchHeaderV6, BatchHeaderV6}, v7::{ArchivedBatchHeaderV7, BatchHeaderV7}, v8::{ArchivedBatchHeaderV8, BatchHeaderV8}, + validium::{BatchHeaderValidium, BatchHeaderValidiumV1}, }; mod payload; @@ -14,7 +15,7 @@ pub use payload::{ v8::{EnvelopeV8, PayloadV8}, }; -mod blob_consistency; +pub mod blob_consistency; mod builder; mod witness; diff --git a/crates/types/batch/src/payload/mod.rs b/crates/types/batch/src/payload/mod.rs index 11b6e59f..1d3b9d6f 100644 --- a/crates/types/batch/src/payload/mod.rs +++ b/crates/types/batch/src/payload/mod.rs @@ -29,9 +29,9 @@ pub const DA_CODEC_VERSION_V7: u8 = 7; pub const DA_CODEC_VERSION_V8: u8 = 8; pub trait Envelope { - fn from_slice(blob_bytes: &[u8]) -> Self; + fn from_slice(bytes: &[u8]) -> Self; - fn challenge_digest(&self, blob_versioned_hash: B256) -> B256; + fn challenge_digest(&self, versioned_hash: B256) -> B256; } pub trait Payload { diff --git a/crates/types/batch/src/witness.rs b/crates/types/batch/src/witness.rs index dbab5d04..19baa665 100644 --- a/crates/types/batch/src/witness.rs +++ b/crates/types/batch/src/witness.rs @@ -1,13 +1,18 @@ use halo2curves_axiom::CurveAffine; use types_base::{ aggregation::{AggregationInput, ProofCarryingWitness}, - public_inputs::{ForkName, batch::BatchInfo, chunk::ChunkInfo}, + public_inputs::{ + ForkName, + batch::BatchInfo, + chunk::{ChunkInfo, LegacyChunkInfo}, + }, }; use crate::{ builder::{ BatchInfoBuilder, BatchInfoBuilderV6, BatchInfoBuilderV7, BatchInfoBuilderV8, BuilderArgsV6, BuilderArgsV7, BuilderArgsV8, + validium::{ValidiumBatchInfoBuilder, ValidiumBuilderArgs}, }, header::ReferenceHeader, }; @@ -119,6 +124,8 @@ pub fn build_point(x: Bytes48, y: Bytes48) -> Option, /// Chunk infos. @@ -153,7 +160,7 @@ pub struct LegacyBatchWitness { pub chunk_proofs: Vec, /// Chunk infos. #[rkyv()] - pub chunk_infos: Vec, + pub chunk_infos: Vec, /// Blob bytes. #[rkyv()] pub blob_bytes: Vec, @@ -170,10 +177,10 @@ pub struct LegacyBatchWitness { impl From for LegacyBatchWitness { fn from(value: BatchWitness) -> Self { - let point_eval_witness = value.point_eval_witness.as_ref().unwrap(); + let point_eval_witness = value.point_eval_witness.expect("should not be none"); Self { chunk_proofs: value.chunk_proofs, - chunk_infos: value.chunk_infos, + chunk_infos: value.chunk_infos.into_iter().map(|c| c.into()).collect(), blob_bytes: value.blob_bytes, point_eval_witness: point_eval_witness.clone().into(), reference_header: value.reference_header, @@ -228,6 +235,9 @@ impl From<&BatchWitness> for BatchInfo { }; BatchInfoBuilderV8::build(args) } + ReferenceHeader::Validium(header) => ValidiumBatchInfoBuilder::build( + ValidiumBuilderArgs::new(witness.version, *header, chunk_infos), + ), } } } diff --git a/crates/types/bundle/src/lib.rs b/crates/types/bundle/src/lib.rs index 6688df56..622170a7 100644 --- a/crates/types/bundle/src/lib.rs +++ b/crates/types/bundle/src/lib.rs @@ -1,2 +1,2 @@ mod witness; -pub use witness::{ArchivedBundleWitness, BundleWitness}; +pub use witness::{ArchivedLegacyBundleWitness, BundleWitness, LegacyBundleWitness}; diff --git a/crates/types/bundle/src/witness.rs b/crates/types/bundle/src/witness.rs index 0d97f4e5..f601cee7 100644 --- a/crates/types/bundle/src/witness.rs +++ b/crates/types/bundle/src/witness.rs @@ -4,6 +4,19 @@ use types_base::{ public_inputs::{batch::BatchInfo, bundle::BundleInfo}, }; +/// The witness for the bundle circuit. +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub struct BundleWitness { + /// The version byte as per [version][types_base::version]. + pub version: u8, + /// Batch proofs being aggregated in the bundle. + pub batch_proofs: Vec, + /// Public-input values for the corresponding batch proofs. + pub batch_infos: Vec, + /// The code version specify the chain spec + pub fork_name: ForkName, +} + /// The witness for the bundle circuit. #[derive( Clone, @@ -15,7 +28,7 @@ use types_base::{ serde::Serialize, )] #[rkyv(derive(Debug))] -pub struct BundleWitness { +pub struct LegacyBundleWitness { /// Batch proofs being aggregated in the bundle. #[rkyv()] pub batch_proofs: Vec, @@ -27,6 +40,16 @@ pub struct BundleWitness { pub fork_name: ForkName, } +impl From for LegacyBundleWitness { + fn from(value: BundleWitness) -> Self { + Self { + batch_proofs: value.batch_proofs, + batch_infos: value.batch_infos, + fork_name: value.fork_name, + } + } +} + impl ProofCarryingWitness for BundleWitness { fn get_proofs(&self) -> Vec { self.batch_proofs.clone() @@ -69,6 +92,7 @@ impl From<&BundleWitness> for BundleInfo { batch_hash, withdraw_root, msg_queue_hash, + encryption_key: first_batch.encryption_key.clone(), } } } diff --git a/crates/types/chunk/Cargo.toml b/crates/types/chunk/Cargo.toml index c900cc6a..a85c57b5 100644 --- a/crates/types/chunk/Cargo.toml +++ b/crates/types/chunk/Cargo.toml @@ -10,13 +10,17 @@ version.workspace = true [dependencies] alloy-primitives = { workspace = true, features = ["native-keccak"] } alloy-consensus = { workspace = true, features = ["crypto-backend"] } +alloy-sol-types.workspace = true +ecies.workspace = true +itertools.workspace = true +#revm-precompile = { git = "https://github.com/scroll-tech/revm", branch = "feat/reth-v74", default-features=false, features = ["kzg-rs", "libsecp256k1"] } rkyv.workspace = true sbv-helpers.workspace = true sbv-core = { workspace = true, features = ["rkyv"] } sbv-trie = { workspace = true } sbv-primitives = { workspace = true, features = ["hardforks", "evm-types", "revm-types", "reth-evm-types"] } serde.workspace = true - +thiserror.workspace = true openvm-ecc-guest = { workspace = true } openvm-k256 = { workspace = true } openvm-p256 = { workspace = true } @@ -25,9 +29,12 @@ openvm-pairing = { workspace = true, features = ["bn254"] } types-base = { path = "../base", package = "scroll-zkvm-types-base"} +[dev-dependencies] +serde_json.workspace = true + [features] default = [] -host = ["scroll-compress-ratio"] +host = ["scroll-compress-ratio", "alloy-primitives/tiny-keccak"] scroll = [ "sbv-core/scroll", "sbv-primitives/scroll-evm-types", diff --git a/crates/types/chunk/src/lib.rs b/crates/types/chunk/src/lib.rs index c7240a4b..b47e7996 100644 --- a/crates/types/chunk/src/lib.rs +++ b/crates/types/chunk/src/lib.rs @@ -1,5 +1,6 @@ mod crypto; pub use crypto::Crypto; +//pub use witness::{ChunkWitness, LegacyChunkWitness, ValidiumInputs}; #[cfg(feature = "scroll")] mod scroll; diff --git a/crates/types/chunk/src/scroll.rs b/crates/types/chunk/src/scroll.rs index 628fe139..b6f859f7 100644 --- a/crates/types/chunk/src/scroll.rs +++ b/crates/types/chunk/src/scroll.rs @@ -1,7 +1,8 @@ mod types; +pub use types::validium::SecretKey; mod execute; pub use execute::execute; mod witness; -pub use witness::{ChunkWitness, ChunkWitnessWithRspTrie, LegacyChunkWitness}; +pub use witness::{ChunkWitness, ChunkWitnessWithRspTrie, LegacyChunkWitness, ValidiumInputs}; diff --git a/crates/types/chunk/src/scroll/execute.rs b/crates/types/chunk/src/scroll/execute.rs index 85841cd2..b568ff6a 100644 --- a/crates/types/chunk/src/scroll/execute.rs +++ b/crates/types/chunk/src/scroll/execute.rs @@ -1,4 +1,5 @@ use crate::{ChunkWitness, scroll::types::ChunkExt}; +use ecies::SecretKey; use sbv_core::verifier::{self, VerifyResult}; use sbv_helpers::manually_drop_on_zkvm; use sbv_primitives::{ @@ -19,6 +20,13 @@ use types_base::{ /// But in guest mode, it must be provided. pub fn execute(witness: ChunkWitness) -> Result { let chain = Chain::from_id(witness.blocks[0].chain_id); + let prev_blockhash = witness.blocks[0].header.parent_hash(); + let post_blockhash = witness + .blocks + .last() + .expect("witnesses can not be empty") + .header + .hash_slow(); let chain_spec = build_chain_spec_force_hardfork( chain, match witness.fork_name { @@ -44,13 +52,12 @@ pub fn execute(witness: ChunkWitness) -> Result { let data_hash = if witness.fork_name < ForkName::EuclidV2 { blocks.legacy_data_hash() } else { - B256::ZERO + B256::default() }; - let post_msg_queue_hash = if witness.fork_name >= ForkName::EuclidV2 { - blocks.rolling_msg_queue_hash(witness.prev_msg_queue_hash) + blocks.rolling_msg_queue_hash(witness.prev_msg_queue_hash, witness.validium.as_ref()) } else { - B256::ZERO + B256::default() }; let chunk_info = ChunkInfo { @@ -65,9 +72,17 @@ pub fn execute(witness: ChunkWitness) -> Result { prev_msg_queue_hash: witness.prev_msg_queue_hash, post_msg_queue_hash, block_ctxs: blocks.iter().map(block_to_context).collect(), + prev_blockhash, + post_blockhash, + encryption_key: witness.validium.map(|input| { + SecretKey::try_from_bytes(input.secret_key) + .expect("validium key") + .public_key() + .to_bytes(true) + }), }; - // println!("chunk_info = {}", chunk_info); + println!("chunk_info = {}", chunk_info); Ok(chunk_info) } diff --git a/crates/types/chunk/src/scroll/types.rs b/crates/types/chunk/src/scroll/types.rs index 44dae350..63c7853c 100644 --- a/crates/types/chunk/src/scroll/types.rs +++ b/crates/types/chunk/src/scroll/types.rs @@ -1,15 +1,20 @@ -use alloy_consensus::transaction::TxHashRef; +use super::types::validium::SecretKey; +use super::witness::ValidiumInputs; use alloy_primitives::keccak256; +use itertools::Itertools; use sbv_helpers::manually_drop_on_zkvm; use sbv_primitives::{ B256, U256, types::{ + consensus::TxL1Message, eips::Encodable2718, reth::primitives::{Block, RecoveredBlock, TransactionSigned}, }, }; use std::ops::Deref; +pub mod validium; + const LEGACY_DA_HEADER_LEN: usize = size_of::() // block number + size_of::() // timestamp + U256::BYTES // base fee per gas @@ -24,7 +29,11 @@ pub trait ChunkExt { /// Data hash before Euclid V2 fn legacy_data_hash(&self) -> B256; /// Rolling message queue hash after Euclid V2 - fn rolling_msg_queue_hash(&self, rolling_hash: B256) -> B256; + fn rolling_msg_queue_hash( + &self, + rolling_hash: B256, + validium_inputs: Option<&ValidiumInputs>, + ) -> B256; } impl]>> ChunkExt for T { @@ -66,10 +75,28 @@ impl]>> ChunkExt for T { } #[inline] - fn rolling_msg_queue_hash(&self, mut rolling_hash: B256) -> B256 { + fn rolling_msg_queue_hash( + &self, + mut rolling_hash: B256, + validium_inputs: Option<&ValidiumInputs>, + ) -> B256 { let blocks = self.as_ref(); - for block in blocks.iter() { - rolling_hash = block.hash_msg_queue(&rolling_hash); + + if let Some(ValidiumInputs { + validium_txs, + secret_key, + }) = validium_inputs + { + let secret_key = SecretKey::try_from_bytes(secret_key).expect("valid secret key"); + + for (block, validium_txs) in blocks.iter().zip(validium_txs.iter()) { + rolling_hash = block + .hash_msg_queue(&rolling_hash, Some((validium_txs.as_slice(), &secret_key))); + } + } else { + for block in blocks.iter() { + rolling_hash = block.hash_msg_queue(&rolling_hash, None); + } } rolling_hash } @@ -99,16 +126,32 @@ impl<'a, I: Iterator> TxBytesHashExt for I { } /// Chunk related extension methods for Block -trait BlockChunkExt { +trait BlockExt { + /// Get an iterator over L1 message transactions in the block. + fn l1_txs_iter(&self) -> impl Iterator; + /// Hash the header of the block fn encode_legacy_da_header(&self, buffer: &mut Vec); /// Hash the l1 messages of the block fn encode_legacy_l1_msg(&self, buffer: &mut Vec); /// Hash the l1 messages of the block - fn hash_msg_queue(&self, initial_queue_hash: &B256) -> B256; + fn hash_msg_queue( + &self, + initial_queue_hash: &B256, + validium_txs: Option<(&[TxL1Message], &SecretKey)>, + ) -> B256; } -impl BlockChunkExt for RecoveredBlock { +impl BlockExt for RecoveredBlock { + #[inline] + fn l1_txs_iter(&self) -> impl Iterator { + self.body() + .transactions + .iter() + .filter_map(|tx| tx.as_l1_message()) + .map(|tx| tx.inner()) + } + #[inline] fn encode_legacy_da_header(&self, buffer: &mut Vec) { buffer.extend_from_slice(&self.number.to_be_bytes()); @@ -135,20 +178,19 @@ impl BlockChunkExt for RecoveredBlock { } #[inline] - fn hash_msg_queue(&self, initial_queue_hash: &B256) -> B256 { + fn hash_msg_queue( + &self, + initial_queue_hash: &B256, + validium_txs: Option<(&[TxL1Message], &SecretKey)>, + ) -> B256 { let mut rolling_hash = *initial_queue_hash; let mut buffer = [0u8; { size_of::() * 2 }]; buffer[..32].copy_from_slice(rolling_hash.as_ref()); - for tx in self - .body() - .transactions - .iter() - .filter(|tx| tx.is_l1_message()) - { + let mut hash_tx = |tx_hash: B256| { buffer[..size_of::()].copy_from_slice(rolling_hash.as_ref()); - buffer[size_of::()..].copy_from_slice(tx.tx_hash().as_ref()); + buffer[size_of::()..].copy_from_slice(tx_hash.as_ref()); rolling_hash = keccak256(buffer); // clear last 32 bits, i.e. 4 bytes. @@ -158,7 +200,27 @@ impl BlockChunkExt for RecoveredBlock { rolling_hash.0[29] = 0; rolling_hash.0[30] = 0; rolling_hash.0[31] = 0; - } + }; + + if let Some((txs, secret_key)) = validium_txs { + for (validium_tx, tx_in_block) in txs.iter().zip_eq(self.l1_txs_iter()) { + match validium::decrypt(validium_tx, secret_key) { + Ok(decrypted) => { + assert_eq!(decrypted, *tx_in_block); + } + Err(_) => { + // when decryption has failed, the validium_tx is just used for execution with its encrypted bytes + assert_eq!(*validium_tx, *tx_in_block); + } + } + + hash_tx(validium_tx.tx_hash()); + } + } else { + for tx in self.l1_txs_iter() { + hash_tx(tx.tx_hash()); + } + }; rolling_hash } diff --git a/crates/types/chunk/src/scroll/types/validium.rs b/crates/types/chunk/src/scroll/types/validium.rs new file mode 100644 index 00000000..32b4e849 --- /dev/null +++ b/crates/types/chunk/src/scroll/types/validium.rs @@ -0,0 +1,102 @@ +#![allow(non_snake_case)] + +use alloy_primitives::{Address, Bytes}; +use alloy_sol_types::{SolCall, sol}; +use sbv_primitives::types::consensus::TxL1Message; + +pub use ecies::SecretKey; + +sol! { + #[derive(Debug)] + function relayMessage( + address sender, + address target, + uint256 value, + uint256 messageNonce, + bytes message + ); + + #[derive(Debug)] + function finalizeDepositERC20( + address token, + address l2Token, + address from, + address to, + uint256 amount, + bytes l2Data + ); + + #[derive(Debug)] + function finalizeDepositERC20Encrypted( + address token, + address l2Token, + address from, + bytes to, + uint256 amount, + bytes l2Data + ); + +} + +#[derive(Debug, thiserror::Error)] +pub enum ValidiumError { + #[error(transparent)] + Decode(#[from] alloy_sol_types::Error), + #[error(transparent)] + Decrypt(#[from] ecies::DecryptError), + #[error("Invalid target address")] + InvalidTarget, +} + +pub fn decrypt(tx: &TxL1Message, secret_key: &SecretKey) -> Result { + Ok(TxL1Message { + queue_index: tx.queue_index, + gas_limit: tx.gas_limit, + to: tx.to, + value: tx.value, + sender: tx.sender, + input: decrypt_data(&tx.input, secret_key)?, + }) +} + +fn decrypt_data(data: &Bytes, secret_key: &SecretKey) -> Result { + if data.starts_with(&relayMessageCall::SELECTOR) { + let mut msg: relayMessageCall = relayMessageCall::abi_decode(data.as_ref())?; + if msg + .message + .starts_with(&finalizeDepositERC20EncryptedCall::SELECTOR) + { + msg.message = decrypt_message(&msg.message, secret_key)?; + return Ok(Bytes::from(msg.abi_encode())); + } + } + Ok(data.clone()) +} + +fn decrypt_message(message: &Bytes, secret_key: &SecretKey) -> Result { + if message.starts_with(&finalizeDepositERC20EncryptedCall::SELECTOR) { + let finalizeDepositERC20EncryptedCall { + token, + l2Token, + from, + to, + amount, + l2Data, + } = finalizeDepositERC20EncryptedCall::abi_decode(message.as_ref())?; + let to = secret_key.try_decrypt(to.as_ref())?; + let to = Address::try_from(to.as_slice()).map_err(|_| ValidiumError::InvalidTarget)?; + return Ok(Bytes::from( + finalizeDepositERC20Call { + token, + l2Token, + from, + to, + amount, + l2Data, + } + .abi_encode(), + )); + } + + Ok(message.clone()) +} diff --git a/crates/types/chunk/src/scroll/witness.rs b/crates/types/chunk/src/scroll/witness.rs index a64dc4a8..0fa0e25b 100644 --- a/crates/types/chunk/src/scroll/witness.rs +++ b/crates/types/chunk/src/scroll/witness.rs @@ -1,13 +1,18 @@ +use super::types::validium::SecretKey; use alloy_primitives::B256; use sbv_core::{verifier::StateCommitMode, witness::BlockWitness}; use sbv_primitives::U256; +use sbv_primitives::types::consensus::TxL1Message; use sbv_trie::PartialStateTrie; use std::collections::HashSet; +use types_base::version::Version; use types_base::{fork_name::ForkName, public_inputs::chunk::ChunkInfo}; /// The witness type accepted by the chunk-circuit. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct ChunkWitness { + /// Version byte as per [version][types_base::version]. + pub version: u8, /// The block witness for each block in the chunk. pub blocks: Vec, /// The on-chain rolling L1 message queue hash before enqueueing any L1 msg tx from the chunk. @@ -16,11 +21,15 @@ pub struct ChunkWitness { pub fork_name: ForkName, /// The compression ratios for each block in the chunk. pub compression_ratios: Vec>, + /// Validium encrypted txs and secret key if this is a validium chain. + pub validium: Option, } /// The witness type accepted by the chunk-circuit. #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct ChunkWitnessWithRspTrie { + /// Version byte as per [version][types_base::version]. + pub version: u8, /// The block witness for each block in the chunk. pub blocks: Vec, /// The on-chain rolling L1 message queue hash before enqueueing any L1 msg tx from the chunk. @@ -31,6 +40,17 @@ pub struct ChunkWitnessWithRspTrie { pub compression_ratios: Vec>, /// The cached partial state trie for the chunk. pub cached_trie: PartialStateTrie, + /// Validium encrypted txs and secret key if this is a validium chain. + pub validium: Option, +} + +/// The validium inputs for the chunk witness. +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub struct ValidiumInputs { + /// The validium transactions for each block in the chunk. + pub validium_txs: Vec>, + /// The secret key used for decrypting validium transactions. + pub secret_key: Box<[u8]>, } /// The witness type accepted by the chunk-circuit. @@ -65,7 +85,42 @@ pub struct ChunkDetails { } impl ChunkWitness { - pub fn new(blocks: &[BlockWitness], prev_msg_queue_hash: B256, fork_name: ForkName) -> Self { + pub fn new_scroll( + version: u8, + blocks: &[BlockWitness], + prev_msg_queue_hash: B256, + fork_name: ForkName, + ) -> Self { + Self::new(version, blocks, prev_msg_queue_hash, fork_name, None) + } + + pub fn new_validium( + version: u8, + blocks: &[BlockWitness], + prev_msg_queue_hash: B256, + fork_name: ForkName, + validium_txs: Vec>, + secret_key: SecretKey, + ) -> Self { + Self::new( + version, + blocks, + prev_msg_queue_hash, + fork_name, + Some(ValidiumInputs { + validium_txs, + secret_key: secret_key.to_bytes(), + }), + ) + } + + pub fn new( + version: u8, + blocks: &[BlockWitness], + prev_msg_queue_hash: B256, + fork_name: ForkName, + validium: Option, + ) -> Self { let num_codes = blocks.iter().map(|w| w.codes.len()).sum(); let mut codes = HashSet::with_capacity(num_codes); @@ -100,10 +155,12 @@ impl ChunkWitness { .collect(); Self { + version, blocks, prev_msg_queue_hash, fork_name, compression_ratios, + validium, } } @@ -122,6 +179,10 @@ impl ChunkWitness { total_gas_used, } } + + pub fn version(&self) -> Version { + Version::from(self.version) + } } impl TryFrom for ChunkInfo { @@ -166,11 +227,13 @@ impl From for ChunkWitnessWithRspTrie { } ChunkWitnessWithRspTrie { + version: value.version, blocks: value.blocks, prev_msg_queue_hash: value.prev_msg_queue_hash, fork_name: value.fork_name, compression_ratios: value.compression_ratios, cached_trie, + validium: value.validium, } } } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 9bb1023c..51e48648 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -17,7 +17,7 @@ pub mod chunk { pub use types_chunk::*; } -pub use types_base::{aggregation as types_agg, public_inputs}; +pub use types_base::{aggregation as types_agg, public_inputs, version}; pub mod proof; diff --git a/release-fork b/release-fork index e2044e89..a8690d6a 100644 --- a/release-fork +++ b/release-fork @@ -1 +1 @@ -feynman \ No newline at end of file +feynman diff --git a/release.sh b/release.sh index ca68d63c..1cf343e9 100644 --- a/release.sh +++ b/release.sh @@ -1,7 +1,7 @@ -#!/bin/bash +#!/bin/sh set -uex -if [ -z "${SCROLL_ZKVM_VERSION}" ]; then +if [ -z "${SCROLL_ZKVM_VERSION:-}" ]; then echo "SCROLL_ZKVM_VERSION not set" exit 1 else @@ -10,12 +10,12 @@ fi DEV_DIR="releases/dev" # Output sha256 checksums -find $DEV_DIR -type f ! -name sha256sums.txt -exec sha256sum {} \; >$DEV_DIR/sha256sums.txt +find "$DEV_DIR" -type f ! -name sha256sums.txt -exec sha256sum {} \; >"$DEV_DIR/sha256sums.txt" # Read FORKNAME from release-fork file FORKNAME=$(head -n 1 release-fork) -function release_new() { +release_new() { VK_JSON="$DEV_DIR/verifier/openVmVk.json" RELEASES_DIR="releases/$FORKNAME" @@ -35,12 +35,12 @@ function release_new() { mkdir -p "$RELEASES_DIR/batch/$batch_vk" mkdir -p "$RELEASES_DIR/bundle/$bundle_vk" - # Copy files from releases/dev to the new directories - cp -r "$DEV_DIR/chunk"/* "$RELEASES_DIR/chunk/$chunk_vk/" - cp -r "$DEV_DIR/batch"/* "$RELEASES_DIR/batch/$batch_vk/" - cp -r "$DEV_DIR/bundle"/* "$RELEASES_DIR/bundle/$bundle_vk/" - mkdir -p $VERIFIER_RELEASES_DIR - mv $DEV_DIR/* $VERIFIER_RELEASES_DIR + # Copy contents (including hidden files) safely with POSIX cp -R + cp -R "$DEV_DIR/chunk/." "$RELEASES_DIR/chunk/$chunk_vk/" + cp -R "$DEV_DIR/batch/." "$RELEASES_DIR/batch/$batch_vk/" + cp -R "$DEV_DIR/bundle/." "$RELEASES_DIR/bundle/$bundle_vk/" + mkdir -p "$VERIFIER_RELEASES_DIR" + mv "$DEV_DIR"/* "$VERIFIER_RELEASES_DIR" echo "Files organized for release successfully:" echo " chunk files -> $RELEASES_DIR/chunk/$chunk_vk" @@ -52,8 +52,8 @@ function release_new() { #aws --profile default s3 cp releases s3://circuit-release/scroll-zkvm --recursive } -function release_old() { - aws --profile default s3 cp $DEV_DIR s3://circuit-release/scroll-zkvm/$VERIFIER_RELEASES_DIR --recursive +release_old() { + aws --profile default s3 cp "$DEV_DIR" "s3://circuit-release/scroll-zkvm/$VERIFIER_RELEASES_DIR" --recursive } -release_new \ No newline at end of file +release_new diff --git a/releases/dev/verifier/verifier.bin b/releases/dev/verifier/verifier.bin index a5a2680c..b96bbfbc 100644 Binary files a/releases/dev/verifier/verifier.bin and b/releases/dev/verifier/verifier.bin differ diff --git a/releases/dev/verifier/verifier.sol b/releases/dev/verifier/verifier.sol index 1e874311..c439b190 100644 --- a/releases/dev/verifier/verifier.sol +++ b/releases/dev/verifier/verifier.sol @@ -1,3 +1,4 @@ + // SPDX-License-Identifier: MIT pragma solidity 0.8.19; @@ -7,7 +8,9 @@ contract Halo2Verifier { assembly ("memory-safe") { // Enforce that Solidity memory layout is respected let data := mload(0x40) - if iszero(eq(data, 0x80)) { revert(0, 0) } + if iszero(eq(data, 0x80)) { + revert(0, 0) + } let success := true let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 @@ -21,2025 +24,1579 @@ contract Halo2Verifier { { 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 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(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, 9514323097321245931419041477139106601771148851610395955023397192525359125626) - - { - let x := calldataload(0x5c0) - mstore(0x660, x) - let y := calldataload(0x5e0) - mstore(0x680, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0x6a0, keccak256(0x80, 1568)) - { - let hash := mload(0x6a0) - mstore(0x6c0, mod(hash, f_q)) - mstore(0x6e0, hash) - } - - { - 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(0x640) - mstore(0x740, x) - let y := calldataload(0x660) - mstore(0x760, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0x780, keccak256(0x6e0, 160)) - { - let hash := mload(0x780) - mstore(0x7a0, mod(hash, f_q)) - mstore(0x7c0, hash) - } - mstore8(2016, 1) - mstore(0x7e0, keccak256(0x7c0, 33)) - { - let hash := mload(0x7e0) - mstore(0x800, mod(hash, f_q)) - mstore(0x820, hash) - } +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(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, 9514323097321245931419041477139106601771148851610395955023397192525359125626) + + { + let x := calldataload(0x5c0) + mstore(0x660, x) + let y := calldataload(0x5e0) + mstore(0x680, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0x6a0, keccak256(0x80, 1568)) +{ + let hash := mload(0x6a0) + mstore(0x6c0, mod(hash, f_q)) + mstore(0x6e0, hash) + } - { - 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(0x600) + mstore(0x700, x) + let y := calldataload(0x620) + mstore(0x720, y) + success := and(validate_ec_point(x, y), success) + } - { - 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(0x640) + mstore(0x740, x) + let y := calldataload(0x660) + mstore(0x760, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0x780, keccak256(0x6e0, 160)) +{ + let hash := mload(0x780) + mstore(0x7a0, mod(hash, f_q)) + mstore(0x7c0, hash) + } +mstore8(2016, 1) +mstore(0x7e0, keccak256(0x7c0, 33)) +{ + let hash := mload(0x7e0) + mstore(0x800, mod(hash, f_q)) + mstore(0x820, hash) + } - { - let x := calldataload(0x700) - mstore(0x8c0, x) - let y := calldataload(0x720) - mstore(0x8e0, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0x900, keccak256(0x820, 224)) - { - let hash := mload(0x900) - mstore(0x920, mod(hash, f_q)) - mstore(0x940, hash) - } + { + 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(0x740) - mstore(0x960, x) - let y := calldataload(0x760) - mstore(0x980, y) - success := and(validate_ec_point(x, y), success) - } + { + 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(0x780) - mstore(0x9a0, x) - let y := calldataload(0x7a0) - mstore(0x9c0, y) - success := and(validate_ec_point(x, y), success) - } + { + let x := calldataload(0x700) + mstore(0x8c0, x) + let y := calldataload(0x720) + mstore(0x8e0, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0x900, keccak256(0x820, 224)) +{ + let hash := mload(0x900) + mstore(0x920, mod(hash, f_q)) + mstore(0x940, hash) + } - { - 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(0x740) + mstore(0x960, x) + let y := calldataload(0x760) + mstore(0x980, y) + success := and(validate_ec_point(x, y), success) + } - { - let x := calldataload(0x800) - mstore(0xa20, x) - let y := calldataload(0x820) - mstore(0xa40, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0xa60, keccak256(0x940, 288)) - { - let hash := mload(0xa60) - mstore(0xa80, mod(hash, f_q)) - mstore(0xaa0, hash) - } - 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(0xd20) - mstore(0xd40, mod(hash, f_q)) - mstore(0xd60, hash) - } - mstore8(3456, 1) - mstore(0xd80, keccak256(0xd60, 33)) - { - let hash := mload(0xd80) - mstore(0xda0, mod(hash, f_q)) - mstore(0xdc0, hash) - } + { + 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(0xaa0) - mstore(0xde0, x) - let y := calldataload(0xac0) - mstore(0xe00, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0xe20, keccak256(0xdc0, 96)) - { - let hash := mload(0xe20) - mstore(0xe40, mod(hash, f_q)) - mstore(0xe60, hash) - } + { + 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(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(3776, x) - let y := mload(0x100) - y := add(y, shl(88, mload(0x120))) - y := add(y, shl(176, mload(0x140))) - mstore(3808, y) + { + let x := calldataload(0x800) + mstore(0xa20, x) + let y := calldataload(0x820) + mstore(0xa40, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0xa60, keccak256(0x940, 288)) +{ + let hash := mload(0xa60) + mstore(0xa80, mod(hash, f_q)) + mstore(0xaa0, hash) + } +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(0xd20) + mstore(0xd40, mod(hash, f_q)) + mstore(0xd60, hash) + } +mstore8(3456, 1) +mstore(0xd80, keccak256(0xd60, 33)) +{ + let hash := mload(0xd80) + mstore(0xda0, mod(hash, f_q)) + mstore(0xdc0, hash) + } - 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(3840, x) - let y := mload(0x1c0) - y := add(y, shl(88, mload(0x1e0))) - y := add(y, shl(176, mload(0x200))) - mstore(3872, y) + { + let x := calldataload(0xaa0) + mstore(0xde0, x) + let y := calldataload(0xac0) + mstore(0xe00, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0xe20, keccak256(0xdc0, 96)) +{ + let hash := mload(0xe20) + mstore(0xe40, mod(hash, f_q)) + mstore(0xe60, hash) + } - success := and(validate_ec_point(x, y), success) - } - 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, - addmod( - mload(0x11e0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q - ) - ) - mstore( - 0x1220, - mulmod( - mload(0x1200), 21888237653275510688422624196183639687472264873923820041627027729598873448513, f_q - ) - ) - mstore( - 0x1240, - mulmod( - mload(0x1220), 13225785879531581993054172815365636627224369411478295502904397545373139154045, f_q - ) - ) - mstore( - 0x1260, - addmod(mload(0xa80), 8662456992307693229192232929891638461323994988937738840793806641202669341572, f_q) - ) - mstore( - 0x1280, - mulmod( - mload(0x1220), 10939663269433627367777756708678102241564365262857670666700619874077960926249, f_q - ) - ) - mstore( - 0x12a0, - addmod(mload(0xa80), 10948579602405647854468649036579172846983999137558363676997584312497847569368, f_q) - ) - mstore( - 0x12c0, - mulmod( - mload(0x1220), 11016257578652593686382655500910603527869149377564754001549454008164059876499, f_q - ) - ) - mstore( - 0x12e0, - addmod(mload(0xa80), 10871985293186681535863750244346671560679215022851280342148750178411748619118, f_q) - ) - mstore( - 0x1300, - mulmod( - mload(0x1220), 15402826414547299628414612080036060696555554914079673875872749760617770134879, f_q - ) - ) - mstore( - 0x1320, - addmod(mload(0xa80), 6485416457291975593831793665221214391992809486336360467825454425958038360738, f_q) - ) - mstore( - 0x1340, - mulmod( - mload(0x1220), 21710372849001950800533397158415938114909991150039389063546734567764856596059, f_q - ) - ) - mstore( - 0x1360, - addmod(mload(0xa80), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q) - ) - mstore( - 0x1380, - mulmod(mload(0x1220), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q) - ) - mstore( - 0x13a0, - addmod(mload(0xa80), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q) - ) - mstore( - 0x13c0, - mulmod(mload(0x1220), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) - ) - mstore( - 0x13e0, - addmod(mload(0xa80), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q) - ) - mstore(0x1400, mulmod(mload(0x1220), 1, f_q)) - mstore( - 0x1420, - addmod(mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) - ) - mstore( - 0x1440, - mulmod( - mload(0x1220), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q - ) - ) - mstore( - 0x1460, - addmod(mload(0xa80), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q) - ) - mstore( - 0x1480, - mulmod(mload(0x1220), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) - ) - mstore( - 0x14a0, - addmod(mload(0xa80), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q) - ) - mstore( - 0x14c0, - mulmod( - mload(0x1220), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q - ) - ) - mstore( - 0x14e0, - addmod(mload(0xa80), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q) - ) - mstore( - 0x1500, - mulmod( - mload(0x1220), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q - ) - ) - mstore( - 0x1520, - addmod(mload(0xa80), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q) - ) - mstore( - 0x1540, - mulmod(mload(0x1220), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q) - ) - mstore( - 0x1560, - addmod(mload(0xa80), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q) - ) - mstore( - 0x1580, - mulmod(mload(0x1220), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q) - ) - mstore( - 0x15a0, - addmod(mload(0xa80), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q) - ) - mstore( - 0x15c0, - mulmod(mload(0x1220), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q) - ) - mstore( - 0x15e0, - addmod(mload(0xa80), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q) - ) - mstore( - 0x1600, - mulmod(mload(0x1220), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q) - ) - mstore( - 0x1620, - addmod(mload(0xa80), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q) - ) - mstore( - 0x1640, - mulmod(mload(0x1220), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q) - ) - mstore( - 0x1660, - addmod(mload(0xa80), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q) - ) - mstore( - 0x1680, - mulmod( - mload(0x1220), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q - ) - ) - mstore( - 0x16a0, - addmod(mload(0xa80), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q) - ) - mstore( - 0x16c0, - mulmod( - mload(0x1220), 13553911191894110065493137367144919847521088405945523452288398666974237857208, f_q - ) - ) - mstore( - 0x16e0, - addmod(mload(0xa80), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q) - ) - mstore( - 0x1700, - mulmod(mload(0x1220), 9697063347556872083384215826199993067635178715531258559890418744774301211662, f_q) - ) - mstore( - 0x1720, - addmod(mload(0xa80), 12191179524282403138862189919057282020913185684884775783807785441801507283955, f_q) - ) - mstore( - 0x1740, - mulmod( - mload(0x1220), 10807735674816066981985242612061336605021639643453679977988966079770672437131, f_q - ) - ) - mstore( - 0x1760, - addmod(mload(0xa80), 11080507197023208240261163133195938483526724756962354365709238106805136058486, f_q) - ) - mstore( - 0x1780, - mulmod( - mload(0x1220), 12459868075641381822485233712013080087763946065665469821362892189399541605692, f_q - ) - ) - mstore( - 0x17a0, - addmod(mload(0xa80), 9428374796197893399761172033244195000784418334750564522335311997176266889925, f_q) - ) - mstore( - 0x17c0, - mulmod( - mload(0x1220), 16038300751658239075779628684257016433412502747804121525056508685985277092575, f_q - ) - ) - mstore( - 0x17e0, - addmod(mload(0xa80), 5849942120181036146466777061000258655135861652611912818641695500590531403042, f_q) - ) - mstore( - 0x1800, - mulmod(mload(0x1220), 6955697244493336113861667751840378876927906302623587437721024018233754910398, f_q) - ) - mstore( - 0x1820, - addmod(mload(0xa80), 14932545627345939108384737993416896211620458097792446905977180168342053585219, f_q) - ) - mstore( - 0x1840, - mulmod( - mload(0x1220), 13498745591877810872211159461644682954739332524336278910448604883789771736885, f_q - ) - ) - mstore( - 0x1860, - addmod(mload(0xa80), 8389497279961464350035246283612592133809031876079755433249599302786036758732, f_q) - ) - mstore( - 0x1880, - mulmod( - mload(0x1220), 20345677989844117909528750049476969581182118546166966482506114734614108237981, f_q - ) - ) - mstore( - 0x18a0, - addmod(mload(0xa80), 1542564881995157312717655695780305507366245854249067861192089451961700257636, f_q) - ) - mstore( - 0x18c0, - mulmod(mload(0x1220), 790608022292213379425324383664216541739009722347092850716054055768832299157, f_q) - ) - mstore( - 0x18e0, - addmod(mload(0xa80), 21097634849547061842821081361593058546809354678068941492982150130806976196460, f_q) - ) - mstore( - 0x1900, - mulmod(mload(0x1220), 5289443209903185443361862148540090689648485914368835830972895623576469023722, f_q) - ) - mstore( - 0x1920, - addmod(mload(0xa80), 16598799661936089778884543596717184398899878486047198512725308562999339471895, f_q) - ) - mstore( - 0x1940, - mulmod( - mload(0x1220), 15161189183906287273290738379431332336600234154579306802151507052820126345529, f_q - ) - ) - mstore( - 0x1960, - addmod(mload(0xa80), 6727053687932987948955667365825942751948130245836727541546697133755682150088, f_q) - ) - mstore( - 0x1980, - mulmod(mload(0x1220), 557567375339945239933617516585967620814823575807691402619711360028043331811, f_q) - ) - mstore( - 0x19a0, - addmod(mload(0xa80), 21330675496499329982312788228671307467733540824608342941078492826547765163806, f_q) - ) - mstore( - 0x19c0, - mulmod( - mload(0x1220), 16611719114775828483319365659907682366622074960672212059891361227499450055959, f_q - ) - ) - mstore( - 0x19e0, - addmod(mload(0xa80), 5276523757063446738927040085349592721926289439743822283806842959076358439658, f_q) - ) - mstore( - 0x1a00, - mulmod(mload(0x1220), 4509404676247677387317362072810231899718070082381452255950861037254608304934, f_q) - ) - mstore( - 0x1a20, - addmod(mload(0xa80), 17378838195591597834929043672447043188830294318034582087747343149321200190683, f_q) - ) - mstore( - 0x1a40, - mulmod(mload(0x1220), 6866457077948847028333856457654941632900463970069876241424363695212127143359, f_q) - ) - mstore( - 0x1a60, - addmod(mload(0xa80), 15021785793890428193912549287602333455647900430346158102273840491363681352258, f_q) - ) - mstore( - 0x1a80, - mulmod( - mload(0x1220), 20169013865622130318472103510465966222180994822334426398191891983290742724178, f_q - ) - ) - mstore( - 0x1aa0, - addmod(mload(0xa80), 1719229006217144903774302234791308866367369578081607945506312203285065771439, f_q) - ) - mstore( - 0x1ac0, - mulmod( - mload(0x1220), 14874205783542236433261764022044465911656512639684999678853651860683757650009, f_q - ) - ) - mstore( - 0x1ae0, - addmod(mload(0xa80), 7014037088297038788984641723212809176891851760731034664844552325892050845608, f_q) - ) - mstore( - 0x1b00, - mulmod(mload(0x1220), 2579947959091681244170407980400327834520881737801886423874592072501514087543, f_q) - ) - mstore( - 0x1b20, - addmod(mload(0xa80), 19308294912747593978075997764856947254027482662614147919823612114074294408074, f_q) - ) - mstore( - 0x1b40, - mulmod( - mload(0x1220), 17011225028452114973964561549541821925778010085385130152192105634715080939230, f_q - ) - ) - mstore( - 0x1b60, - addmod(mload(0xa80), 4877017843387160248281844195715453162770354315030904191506098551860727556387, f_q) - ) - mstore( - 0x1b80, - mulmod(mload(0x1220), 1881761935718519990121799628252273658786792458106649887437395059872945867717, f_q) - ) - mstore( - 0x1ba0, - addmod(mload(0xa80), 20006480936120755232124606117005001429761571942309384456260809126702862627900, f_q) - ) - mstore( - 0x1bc0, - mulmod( - mload(0x1220), 21662285561588145310352318480822402603888953131447478827940284064946709915517, f_q - ) - ) - mstore( - 0x1be0, - addmod(mload(0xa80), 225957310251129911894087264434872484659411268968555515757920121629098580100, f_q) - ) - mstore( - 0x1c00, - mulmod( - mload(0x1220), 21846745818185811051373434299876022191132089169516983080959277716660228899818, f_q - ) - ) - mstore( - 0x1c20, - addmod(mload(0xa80), 41497053653464170872971445381252897416275230899051262738926469915579595799, f_q) - ) - mstore( - 0x1c40, - mulmod( - mload(0x1220), 11770617947510597378885200406447716404126404817511323735042103519754393416137, f_q - ) - ) - mstore( - 0x1c60, - addmod(mload(0xa80), 10117624924328677843361205338809558684421959582904710608656100666821415079480, f_q) - ) - mstore( - 0x1c80, - mulmod( - mload(0x1220), 13018529307372270489258244406856841315962482733096074798317807775255504614069, f_q - ) - ) - mstore( - 0x1ca0, - addmod(mload(0xa80), 8869713564467004732988161338400433772585881667319959545380396411320303881548, f_q) - ) - mstore( - 0x1cc0, - mulmod(mload(0x1220), 5276270562549512946272803945594037128265390012927669941530122528135796334063, f_q) - ) - mstore( - 0x1ce0, - addmod(mload(0xa80), 16611972309289762275973601799663237960282974387488364402168081658440012161554, f_q) - ) - mstore( - 0x1d00, - mulmod(mload(0x1220), 1459528961030896569807206253631725410868595642414057264270714861278164633285, f_q) - ) - mstore( - 0x1d20, - addmod(mload(0xa80), 20428713910808378652439199491625549677679768758001977079427489325297643862332, f_q) - ) - mstore( - 0x1d40, - mulmod(mload(0x1220), 3194789416964050406424265110350613664596286587119568977604859939037397011192, f_q) - ) - mstore( - 0x1d60, - addmod(mload(0xa80), 18693453454875224815822140634906661423952077813296465366093344247538411484425, f_q) - ) - mstore( - 0x1d80, - mulmod(mload(0x1220), 3090451643741879200285099477849831179472024364989630500355756836624424014697, f_q) - ) - mstore( - 0x1da0, - addmod(mload(0xa80), 18797791228097396021961306267407443909076340035426403843342447349951384480920, f_q) - ) - mstore( - 0x1dc0, - mulmod( - mload(0x1220), 15927748781034921005593027077824543133423706442106451156060388409950986747549, f_q - ) - ) - mstore( - 0x1de0, - addmod(mload(0xa80), 5960494090804354216653378667432731955124657958309583187637815776624821748068, f_q) - ) - mstore( - 0x1e00, - mulmod( - mload(0x1220), 21594472933355353940227302948201802990541640451776958309590170926766063614527, f_q - ) - ) - mstore( - 0x1e20, - addmod(mload(0xa80), 293769938483921282019102797055472098006723948639076034108033259809744881090, f_q) - ) - mstore( - 0x1e40, - mulmod( - mload(0x1220), 18627493688178473377890450102960302362510276568110871848038317193719995024144, f_q - ) - ) - mstore( - 0x1e60, - addmod(mload(0xa80), 3260749183660801844355955642296972726038087832305162495659886992855813471473, f_q) - ) - mstore( - 0x1e80, - mulmod( - mload(0x1220), 15233875724801927436678555222002139405060841628305391430751578735629430475003, f_q - ) - ) - mstore( - 0x1ea0, - addmod(mload(0xa80), 6654367147037347785567850523255135683487522772110642912946625450946378020614, f_q) - ) - mstore( - 0x1ec0, - mulmod( - mload(0x1220), 12662796367122493153085459582914902083443981635312477834616629373139110863873, f_q - ) - ) - mstore( - 0x1ee0, - addmod(mload(0xa80), 9225446504716782069160946162342373005104382765103556509081574813436697631744, f_q) - ) - mstore( - 0x1f00, - mulmod(mload(0x1220), 9228489335593836417731216695316971397516686186585289059470421738439643366942, f_q) - ) - mstore( - 0x1f20, - addmod(mload(0xa80), 12659753536245438804515189049940303691031678213830745284227782448136165128675, f_q) - ) - mstore( - 0x1f40, - mulmod(mload(0x1220), 6904960663187367776878651408524770307710353971752548687936010869699798414796, f_q) - ) - mstore( - 0x1f60, - addmod(mload(0xa80), 14983282208651907445367754336732504780838010428663485655762193316876010080821, f_q) - ) - { - let prod := mload(0x1260) + { + 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(3776, x) +let y := mload(0x100) +y := add(y, shl(88, mload(0x120))) +y := add(y, shl(176, mload(0x140))) +mstore(3808, 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(3840, x) +let y := mload(0x1c0) +y := add(y, shl(88, mload(0x1e0))) +y := add(y, shl(176, mload(0x200))) +mstore(3872, y) + + success := and(validate_ec_point(x, y), success) + } +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, addmod(mload(0x11e0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) +mstore(0x1220, mulmod(mload(0x1200), 21888237653275510688422624196183639687472264873923820041627027729598873448513, f_q)) +mstore(0x1240, mulmod(mload(0x1220), 13225785879531581993054172815365636627224369411478295502904397545373139154045, f_q)) +mstore(0x1260, addmod(mload(0xa80), 8662456992307693229192232929891638461323994988937738840793806641202669341572, f_q)) +mstore(0x1280, mulmod(mload(0x1220), 10939663269433627367777756708678102241564365262857670666700619874077960926249, f_q)) +mstore(0x12a0, addmod(mload(0xa80), 10948579602405647854468649036579172846983999137558363676997584312497847569368, f_q)) +mstore(0x12c0, mulmod(mload(0x1220), 11016257578652593686382655500910603527869149377564754001549454008164059876499, f_q)) +mstore(0x12e0, addmod(mload(0xa80), 10871985293186681535863750244346671560679215022851280342148750178411748619118, f_q)) +mstore(0x1300, mulmod(mload(0x1220), 15402826414547299628414612080036060696555554914079673875872749760617770134879, f_q)) +mstore(0x1320, addmod(mload(0xa80), 6485416457291975593831793665221214391992809486336360467825454425958038360738, f_q)) +mstore(0x1340, mulmod(mload(0x1220), 21710372849001950800533397158415938114909991150039389063546734567764856596059, f_q)) +mstore(0x1360, addmod(mload(0xa80), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q)) +mstore(0x1380, mulmod(mload(0x1220), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q)) +mstore(0x13a0, addmod(mload(0xa80), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q)) +mstore(0x13c0, mulmod(mload(0x1220), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q)) +mstore(0x13e0, addmod(mload(0xa80), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q)) +mstore(0x1400, mulmod(mload(0x1220), 1, f_q)) +mstore(0x1420, addmod(mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) +mstore(0x1440, mulmod(mload(0x1220), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q)) +mstore(0x1460, addmod(mload(0xa80), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q)) +mstore(0x1480, mulmod(mload(0x1220), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +mstore(0x14a0, addmod(mload(0xa80), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q)) +mstore(0x14c0, mulmod(mload(0x1220), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q)) +mstore(0x14e0, addmod(mload(0xa80), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q)) +mstore(0x1500, mulmod(mload(0x1220), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q)) +mstore(0x1520, addmod(mload(0xa80), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q)) +mstore(0x1540, mulmod(mload(0x1220), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q)) +mstore(0x1560, addmod(mload(0xa80), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q)) +mstore(0x1580, mulmod(mload(0x1220), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q)) +mstore(0x15a0, addmod(mload(0xa80), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q)) +mstore(0x15c0, mulmod(mload(0x1220), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q)) +mstore(0x15e0, addmod(mload(0xa80), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q)) +mstore(0x1600, mulmod(mload(0x1220), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q)) +mstore(0x1620, addmod(mload(0xa80), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q)) +mstore(0x1640, mulmod(mload(0x1220), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q)) +mstore(0x1660, addmod(mload(0xa80), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q)) +mstore(0x1680, mulmod(mload(0x1220), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q)) +mstore(0x16a0, addmod(mload(0xa80), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q)) +mstore(0x16c0, mulmod(mload(0x1220), 13553911191894110065493137367144919847521088405945523452288398666974237857208, f_q)) +mstore(0x16e0, addmod(mload(0xa80), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q)) +mstore(0x1700, mulmod(mload(0x1220), 9697063347556872083384215826199993067635178715531258559890418744774301211662, f_q)) +mstore(0x1720, addmod(mload(0xa80), 12191179524282403138862189919057282020913185684884775783807785441801507283955, f_q)) +mstore(0x1740, mulmod(mload(0x1220), 10807735674816066981985242612061336605021639643453679977988966079770672437131, f_q)) +mstore(0x1760, addmod(mload(0xa80), 11080507197023208240261163133195938483526724756962354365709238106805136058486, f_q)) +mstore(0x1780, mulmod(mload(0x1220), 12459868075641381822485233712013080087763946065665469821362892189399541605692, f_q)) +mstore(0x17a0, addmod(mload(0xa80), 9428374796197893399761172033244195000784418334750564522335311997176266889925, f_q)) +mstore(0x17c0, mulmod(mload(0x1220), 16038300751658239075779628684257016433412502747804121525056508685985277092575, f_q)) +mstore(0x17e0, addmod(mload(0xa80), 5849942120181036146466777061000258655135861652611912818641695500590531403042, f_q)) +mstore(0x1800, mulmod(mload(0x1220), 6955697244493336113861667751840378876927906302623587437721024018233754910398, f_q)) +mstore(0x1820, addmod(mload(0xa80), 14932545627345939108384737993416896211620458097792446905977180168342053585219, f_q)) +mstore(0x1840, mulmod(mload(0x1220), 13498745591877810872211159461644682954739332524336278910448604883789771736885, f_q)) +mstore(0x1860, addmod(mload(0xa80), 8389497279961464350035246283612592133809031876079755433249599302786036758732, f_q)) +mstore(0x1880, mulmod(mload(0x1220), 20345677989844117909528750049476969581182118546166966482506114734614108237981, f_q)) +mstore(0x18a0, addmod(mload(0xa80), 1542564881995157312717655695780305507366245854249067861192089451961700257636, f_q)) +mstore(0x18c0, mulmod(mload(0x1220), 790608022292213379425324383664216541739009722347092850716054055768832299157, f_q)) +mstore(0x18e0, addmod(mload(0xa80), 21097634849547061842821081361593058546809354678068941492982150130806976196460, f_q)) +mstore(0x1900, mulmod(mload(0x1220), 5289443209903185443361862148540090689648485914368835830972895623576469023722, f_q)) +mstore(0x1920, addmod(mload(0xa80), 16598799661936089778884543596717184398899878486047198512725308562999339471895, f_q)) +mstore(0x1940, mulmod(mload(0x1220), 15161189183906287273290738379431332336600234154579306802151507052820126345529, f_q)) +mstore(0x1960, addmod(mload(0xa80), 6727053687932987948955667365825942751948130245836727541546697133755682150088, f_q)) +mstore(0x1980, mulmod(mload(0x1220), 557567375339945239933617516585967620814823575807691402619711360028043331811, f_q)) +mstore(0x19a0, addmod(mload(0xa80), 21330675496499329982312788228671307467733540824608342941078492826547765163806, f_q)) +mstore(0x19c0, mulmod(mload(0x1220), 16611719114775828483319365659907682366622074960672212059891361227499450055959, f_q)) +mstore(0x19e0, addmod(mload(0xa80), 5276523757063446738927040085349592721926289439743822283806842959076358439658, f_q)) +mstore(0x1a00, mulmod(mload(0x1220), 4509404676247677387317362072810231899718070082381452255950861037254608304934, f_q)) +mstore(0x1a20, addmod(mload(0xa80), 17378838195591597834929043672447043188830294318034582087747343149321200190683, f_q)) +mstore(0x1a40, mulmod(mload(0x1220), 6866457077948847028333856457654941632900463970069876241424363695212127143359, f_q)) +mstore(0x1a60, addmod(mload(0xa80), 15021785793890428193912549287602333455647900430346158102273840491363681352258, f_q)) +mstore(0x1a80, mulmod(mload(0x1220), 20169013865622130318472103510465966222180994822334426398191891983290742724178, f_q)) +mstore(0x1aa0, addmod(mload(0xa80), 1719229006217144903774302234791308866367369578081607945506312203285065771439, f_q)) +mstore(0x1ac0, mulmod(mload(0x1220), 14874205783542236433261764022044465911656512639684999678853651860683757650009, f_q)) +mstore(0x1ae0, addmod(mload(0xa80), 7014037088297038788984641723212809176891851760731034664844552325892050845608, f_q)) +mstore(0x1b00, mulmod(mload(0x1220), 2579947959091681244170407980400327834520881737801886423874592072501514087543, f_q)) +mstore(0x1b20, addmod(mload(0xa80), 19308294912747593978075997764856947254027482662614147919823612114074294408074, f_q)) +mstore(0x1b40, mulmod(mload(0x1220), 17011225028452114973964561549541821925778010085385130152192105634715080939230, f_q)) +mstore(0x1b60, addmod(mload(0xa80), 4877017843387160248281844195715453162770354315030904191506098551860727556387, f_q)) +mstore(0x1b80, mulmod(mload(0x1220), 1881761935718519990121799628252273658786792458106649887437395059872945867717, f_q)) +mstore(0x1ba0, addmod(mload(0xa80), 20006480936120755232124606117005001429761571942309384456260809126702862627900, f_q)) +mstore(0x1bc0, mulmod(mload(0x1220), 21662285561588145310352318480822402603888953131447478827940284064946709915517, f_q)) +mstore(0x1be0, addmod(mload(0xa80), 225957310251129911894087264434872484659411268968555515757920121629098580100, f_q)) +mstore(0x1c00, mulmod(mload(0x1220), 21846745818185811051373434299876022191132089169516983080959277716660228899818, f_q)) +mstore(0x1c20, addmod(mload(0xa80), 41497053653464170872971445381252897416275230899051262738926469915579595799, f_q)) +mstore(0x1c40, mulmod(mload(0x1220), 11770617947510597378885200406447716404126404817511323735042103519754393416137, f_q)) +mstore(0x1c60, addmod(mload(0xa80), 10117624924328677843361205338809558684421959582904710608656100666821415079480, f_q)) +mstore(0x1c80, mulmod(mload(0x1220), 13018529307372270489258244406856841315962482733096074798317807775255504614069, f_q)) +mstore(0x1ca0, addmod(mload(0xa80), 8869713564467004732988161338400433772585881667319959545380396411320303881548, f_q)) +mstore(0x1cc0, mulmod(mload(0x1220), 5276270562549512946272803945594037128265390012927669941530122528135796334063, f_q)) +mstore(0x1ce0, addmod(mload(0xa80), 16611972309289762275973601799663237960282974387488364402168081658440012161554, f_q)) +mstore(0x1d00, mulmod(mload(0x1220), 1459528961030896569807206253631725410868595642414057264270714861278164633285, f_q)) +mstore(0x1d20, addmod(mload(0xa80), 20428713910808378652439199491625549677679768758001977079427489325297643862332, f_q)) +mstore(0x1d40, mulmod(mload(0x1220), 3194789416964050406424265110350613664596286587119568977604859939037397011192, f_q)) +mstore(0x1d60, addmod(mload(0xa80), 18693453454875224815822140634906661423952077813296465366093344247538411484425, f_q)) +mstore(0x1d80, mulmod(mload(0x1220), 3090451643741879200285099477849831179472024364989630500355756836624424014697, f_q)) +mstore(0x1da0, addmod(mload(0xa80), 18797791228097396021961306267407443909076340035426403843342447349951384480920, f_q)) +mstore(0x1dc0, mulmod(mload(0x1220), 15927748781034921005593027077824543133423706442106451156060388409950986747549, f_q)) +mstore(0x1de0, addmod(mload(0xa80), 5960494090804354216653378667432731955124657958309583187637815776624821748068, f_q)) +mstore(0x1e00, mulmod(mload(0x1220), 21594472933355353940227302948201802990541640451776958309590170926766063614527, f_q)) +mstore(0x1e20, addmod(mload(0xa80), 293769938483921282019102797055472098006723948639076034108033259809744881090, f_q)) +mstore(0x1e40, mulmod(mload(0x1220), 18627493688178473377890450102960302362510276568110871848038317193719995024144, f_q)) +mstore(0x1e60, addmod(mload(0xa80), 3260749183660801844355955642296972726038087832305162495659886992855813471473, f_q)) +mstore(0x1e80, mulmod(mload(0x1220), 15233875724801927436678555222002139405060841628305391430751578735629430475003, f_q)) +mstore(0x1ea0, addmod(mload(0xa80), 6654367147037347785567850523255135683487522772110642912946625450946378020614, f_q)) +mstore(0x1ec0, mulmod(mload(0x1220), 12662796367122493153085459582914902083443981635312477834616629373139110863873, f_q)) +mstore(0x1ee0, addmod(mload(0xa80), 9225446504716782069160946162342373005104382765103556509081574813436697631744, f_q)) +mstore(0x1f00, mulmod(mload(0x1220), 9228489335593836417731216695316971397516686186585289059470421738439643366942, f_q)) +mstore(0x1f20, addmod(mload(0xa80), 12659753536245438804515189049940303691031678213830745284227782448136165128675, f_q)) +mstore(0x1f40, mulmod(mload(0x1220), 6904960663187367776878651408524770307710353971752548687936010869699798414796, f_q)) +mstore(0x1f60, addmod(mload(0xa80), 14983282208651907445367754336732504780838010428663485655762193316876010080821, f_q)) +{ + let prod := mload(0x1260) prod := mulmod(mload(0x12a0), prod, f_q) mstore(0x1f80, prod) - + prod := mulmod(mload(0x12e0), prod, f_q) mstore(0x1fa0, prod) - + prod := mulmod(mload(0x1320), prod, f_q) mstore(0x1fc0, prod) - + prod := mulmod(mload(0x1360), prod, f_q) mstore(0x1fe0, prod) - + prod := mulmod(mload(0x13a0), prod, f_q) mstore(0x2000, prod) - + prod := mulmod(mload(0x13e0), prod, f_q) mstore(0x2020, prod) - + prod := mulmod(mload(0x1420), prod, f_q) mstore(0x2040, prod) - + prod := mulmod(mload(0x1460), prod, f_q) mstore(0x2060, prod) - + prod := mulmod(mload(0x14a0), prod, f_q) mstore(0x2080, prod) - + prod := mulmod(mload(0x14e0), prod, f_q) mstore(0x20a0, prod) - + prod := mulmod(mload(0x1520), prod, f_q) mstore(0x20c0, prod) - + prod := mulmod(mload(0x1560), prod, f_q) mstore(0x20e0, prod) - + prod := mulmod(mload(0x15a0), prod, f_q) mstore(0x2100, prod) - + prod := mulmod(mload(0x15e0), prod, f_q) mstore(0x2120, prod) - + prod := mulmod(mload(0x1620), prod, f_q) mstore(0x2140, prod) - + prod := mulmod(mload(0x1660), prod, f_q) mstore(0x2160, prod) - + prod := mulmod(mload(0x16a0), prod, f_q) mstore(0x2180, prod) - + prod := mulmod(mload(0x16e0), prod, f_q) mstore(0x21a0, prod) - + prod := mulmod(mload(0x1720), prod, f_q) mstore(0x21c0, prod) - + prod := mulmod(mload(0x1760), prod, f_q) mstore(0x21e0, prod) - + prod := mulmod(mload(0x17a0), prod, f_q) mstore(0x2200, prod) - + prod := mulmod(mload(0x17e0), prod, f_q) mstore(0x2220, prod) - + prod := mulmod(mload(0x1820), prod, f_q) mstore(0x2240, prod) - + prod := mulmod(mload(0x1860), prod, f_q) mstore(0x2260, prod) - + prod := mulmod(mload(0x18a0), prod, f_q) mstore(0x2280, prod) - + prod := mulmod(mload(0x18e0), prod, f_q) mstore(0x22a0, prod) - + prod := mulmod(mload(0x1920), prod, f_q) mstore(0x22c0, prod) - + prod := mulmod(mload(0x1960), prod, f_q) mstore(0x22e0, prod) - + prod := mulmod(mload(0x19a0), prod, f_q) mstore(0x2300, prod) - + prod := mulmod(mload(0x19e0), prod, f_q) mstore(0x2320, prod) - + prod := mulmod(mload(0x1a20), prod, f_q) mstore(0x2340, prod) - + prod := mulmod(mload(0x1a60), prod, f_q) mstore(0x2360, prod) - + prod := mulmod(mload(0x1aa0), prod, f_q) mstore(0x2380, prod) - + prod := mulmod(mload(0x1ae0), prod, f_q) mstore(0x23a0, prod) - + prod := mulmod(mload(0x1b20), prod, f_q) mstore(0x23c0, prod) - + prod := mulmod(mload(0x1b60), prod, f_q) mstore(0x23e0, prod) - + prod := mulmod(mload(0x1ba0), prod, f_q) mstore(0x2400, prod) - + prod := mulmod(mload(0x1be0), prod, f_q) mstore(0x2420, prod) - + prod := mulmod(mload(0x1c20), prod, f_q) mstore(0x2440, prod) - + prod := mulmod(mload(0x1c60), prod, f_q) mstore(0x2460, prod) - + prod := mulmod(mload(0x1ca0), prod, f_q) mstore(0x2480, prod) - + prod := mulmod(mload(0x1ce0), prod, f_q) mstore(0x24a0, prod) - + prod := mulmod(mload(0x1d20), prod, f_q) mstore(0x24c0, prod) - + prod := mulmod(mload(0x1d60), prod, f_q) mstore(0x24e0, prod) - + prod := mulmod(mload(0x1da0), prod, f_q) mstore(0x2500, prod) - + prod := mulmod(mload(0x1de0), prod, f_q) mstore(0x2520, prod) - + prod := mulmod(mload(0x1e20), prod, f_q) mstore(0x2540, prod) - + prod := mulmod(mload(0x1e60), prod, f_q) mstore(0x2560, prod) - + prod := mulmod(mload(0x1ea0), prod, f_q) mstore(0x2580, prod) - + prod := mulmod(mload(0x1ee0), prod, f_q) mstore(0x25a0, prod) - + prod := mulmod(mload(0x1f20), prod, f_q) mstore(0x25c0, prod) - + prod := mulmod(mload(0x1f60), prod, f_q) mstore(0x25e0, prod) - + prod := mulmod(mload(0x1200), prod, f_q) mstore(0x2600, prod) - } - mstore(0x2640, 32) - mstore(0x2660, 32) - mstore(0x2680, 32) - mstore(0x26a0, mload(0x2600)) - mstore(0x26c0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x26e0, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x2640, 0xc0, 0x2620, 0x20), 1), success) - { - let inv := mload(0x2620) - let v - - v := mload(0x1200) - mstore(4608, mulmod(mload(0x25e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1f60) - mstore(8032, mulmod(mload(0x25c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1f20) - mstore(7968, mulmod(mload(0x25a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ee0) - mstore(7904, mulmod(mload(0x2580), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ea0) - mstore(7840, mulmod(mload(0x2560), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1e60) - mstore(7776, mulmod(mload(0x2540), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1e20) - mstore(7712, mulmod(mload(0x2520), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1de0) - mstore(7648, mulmod(mload(0x2500), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1da0) - mstore(7584, mulmod(mload(0x24e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1d60) - mstore(7520, mulmod(mload(0x24c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1d20) - mstore(7456, mulmod(mload(0x24a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ce0) - mstore(7392, mulmod(mload(0x2480), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ca0) - mstore(7328, mulmod(mload(0x2460), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1c60) - mstore(7264, mulmod(mload(0x2440), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1c20) - mstore(7200, mulmod(mload(0x2420), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1be0) - mstore(7136, mulmod(mload(0x2400), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ba0) - mstore(7072, mulmod(mload(0x23e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1b60) - mstore(7008, mulmod(mload(0x23c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1b20) - mstore(6944, mulmod(mload(0x23a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ae0) - mstore(6880, mulmod(mload(0x2380), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1aa0) - mstore(6816, mulmod(mload(0x2360), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1a60) - mstore(6752, mulmod(mload(0x2340), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1a20) - mstore(6688, mulmod(mload(0x2320), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x19e0) - mstore(6624, mulmod(mload(0x2300), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x19a0) - mstore(6560, mulmod(mload(0x22e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1960) - mstore(6496, mulmod(mload(0x22c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1920) - mstore(6432, mulmod(mload(0x22a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x18e0) - mstore(6368, mulmod(mload(0x2280), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x18a0) - mstore(6304, mulmod(mload(0x2260), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1860) - mstore(6240, mulmod(mload(0x2240), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1820) - mstore(6176, mulmod(mload(0x2220), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x17e0) - mstore(6112, mulmod(mload(0x2200), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x17a0) - mstore(6048, mulmod(mload(0x21e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1760) - mstore(5984, mulmod(mload(0x21c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1720) - mstore(5920, mulmod(mload(0x21a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x16e0) - mstore(5856, mulmod(mload(0x2180), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x16a0) - mstore(5792, mulmod(mload(0x2160), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1660) - mstore(5728, mulmod(mload(0x2140), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1620) - mstore(5664, mulmod(mload(0x2120), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x15e0) - mstore(5600, mulmod(mload(0x2100), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x15a0) - mstore(5536, mulmod(mload(0x20e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1560) - mstore(5472, mulmod(mload(0x20c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1520) - mstore(5408, mulmod(mload(0x20a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x14e0) - mstore(5344, mulmod(mload(0x2080), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x14a0) - mstore(5280, mulmod(mload(0x2060), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1460) - mstore(5216, mulmod(mload(0x2040), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1420) - mstore(5152, mulmod(mload(0x2020), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x13e0) - mstore(5088, mulmod(mload(0x2000), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x13a0) - mstore(5024, mulmod(mload(0x1fe0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1360) - mstore(4960, mulmod(mload(0x1fc0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1320) - mstore(4896, mulmod(mload(0x1fa0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x12e0) - mstore(4832, mulmod(mload(0x1f80), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x12a0) - mstore(4768, mulmod(mload(0x1260), inv, f_q)) - inv := mulmod(v, inv, f_q) + + } +mstore(0x2640, 32) +mstore(0x2660, 32) +mstore(0x2680, 32) +mstore(0x26a0, mload(0x2600)) +mstore(0x26c0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) +mstore(0x26e0, 21888242871839275222246405745257275088548364400416034343698204186575808495617) +success := and(eq(staticcall(gas(), 0x5, 0x2640, 0xc0, 0x2620, 0x20), 1), success) +{ + + let inv := mload(0x2620) + let v + + v := mload(0x1200) + mstore(4608, mulmod(mload(0x25e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1f60) + mstore(8032, mulmod(mload(0x25c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1f20) + mstore(7968, mulmod(mload(0x25a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ee0) + mstore(7904, mulmod(mload(0x2580), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ea0) + mstore(7840, mulmod(mload(0x2560), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1e60) + mstore(7776, mulmod(mload(0x2540), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1e20) + mstore(7712, mulmod(mload(0x2520), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1de0) + mstore(7648, mulmod(mload(0x2500), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1da0) + mstore(7584, mulmod(mload(0x24e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1d60) + mstore(7520, mulmod(mload(0x24c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1d20) + mstore(7456, mulmod(mload(0x24a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ce0) + mstore(7392, mulmod(mload(0x2480), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ca0) + mstore(7328, mulmod(mload(0x2460), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1c60) + mstore(7264, mulmod(mload(0x2440), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1c20) + mstore(7200, mulmod(mload(0x2420), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1be0) + mstore(7136, mulmod(mload(0x2400), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ba0) + mstore(7072, mulmod(mload(0x23e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1b60) + mstore(7008, mulmod(mload(0x23c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1b20) + mstore(6944, mulmod(mload(0x23a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ae0) + mstore(6880, mulmod(mload(0x2380), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1aa0) + mstore(6816, mulmod(mload(0x2360), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1a60) + mstore(6752, mulmod(mload(0x2340), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1a20) + mstore(6688, mulmod(mload(0x2320), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x19e0) + mstore(6624, mulmod(mload(0x2300), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x19a0) + mstore(6560, mulmod(mload(0x22e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1960) + mstore(6496, mulmod(mload(0x22c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1920) + mstore(6432, mulmod(mload(0x22a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x18e0) + mstore(6368, mulmod(mload(0x2280), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x18a0) + mstore(6304, mulmod(mload(0x2260), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1860) + mstore(6240, mulmod(mload(0x2240), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1820) + mstore(6176, mulmod(mload(0x2220), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x17e0) + mstore(6112, mulmod(mload(0x2200), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x17a0) + mstore(6048, mulmod(mload(0x21e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1760) + mstore(5984, mulmod(mload(0x21c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1720) + mstore(5920, mulmod(mload(0x21a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x16e0) + mstore(5856, mulmod(mload(0x2180), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x16a0) + mstore(5792, mulmod(mload(0x2160), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1660) + mstore(5728, mulmod(mload(0x2140), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1620) + mstore(5664, mulmod(mload(0x2120), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x15e0) + mstore(5600, mulmod(mload(0x2100), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x15a0) + mstore(5536, mulmod(mload(0x20e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1560) + mstore(5472, mulmod(mload(0x20c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1520) + mstore(5408, mulmod(mload(0x20a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x14e0) + mstore(5344, mulmod(mload(0x2080), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x14a0) + mstore(5280, mulmod(mload(0x2060), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1460) + mstore(5216, mulmod(mload(0x2040), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1420) + mstore(5152, mulmod(mload(0x2020), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13e0) + mstore(5088, mulmod(mload(0x2000), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13a0) + mstore(5024, mulmod(mload(0x1fe0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1360) + mstore(4960, mulmod(mload(0x1fc0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1320) + mstore(4896, mulmod(mload(0x1fa0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12e0) + mstore(4832, mulmod(mload(0x1f80), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12a0) + mstore(4768, mulmod(mload(0x1260), inv, f_q)) + inv := mulmod(v, inv, f_q) mstore(0x1260, inv) - } - mstore(0x2700, mulmod(mload(0x1240), mload(0x1260), f_q)) - mstore(0x2720, mulmod(mload(0x1280), mload(0x12a0), f_q)) - mstore(0x2740, mulmod(mload(0x12c0), mload(0x12e0), f_q)) - mstore(0x2760, mulmod(mload(0x1300), mload(0x1320), f_q)) - mstore(0x2780, mulmod(mload(0x1340), mload(0x1360), f_q)) - mstore(0x27a0, mulmod(mload(0x1380), mload(0x13a0), f_q)) - mstore(0x27c0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) - mstore(0x27e0, mulmod(mload(0x1400), mload(0x1420), f_q)) - mstore(0x2800, mulmod(mload(0x1440), mload(0x1460), f_q)) - mstore(0x2820, mulmod(mload(0x1480), mload(0x14a0), f_q)) - mstore(0x2840, mulmod(mload(0x14c0), mload(0x14e0), f_q)) - mstore(0x2860, mulmod(mload(0x1500), mload(0x1520), f_q)) - mstore(0x2880, mulmod(mload(0x1540), mload(0x1560), f_q)) - mstore(0x28a0, mulmod(mload(0x1580), mload(0x15a0), f_q)) - mstore(0x28c0, mulmod(mload(0x15c0), mload(0x15e0), f_q)) - mstore(0x28e0, mulmod(mload(0x1600), mload(0x1620), f_q)) - mstore(0x2900, mulmod(mload(0x1640), mload(0x1660), f_q)) - mstore(0x2920, mulmod(mload(0x1680), mload(0x16a0), f_q)) - mstore(0x2940, mulmod(mload(0x16c0), mload(0x16e0), f_q)) - mstore(0x2960, mulmod(mload(0x1700), mload(0x1720), f_q)) - mstore(0x2980, mulmod(mload(0x1740), mload(0x1760), f_q)) - mstore(0x29a0, mulmod(mload(0x1780), mload(0x17a0), f_q)) - mstore(0x29c0, mulmod(mload(0x17c0), mload(0x17e0), f_q)) - mstore(0x29e0, mulmod(mload(0x1800), mload(0x1820), f_q)) - mstore(0x2a00, mulmod(mload(0x1840), mload(0x1860), f_q)) - mstore(0x2a20, mulmod(mload(0x1880), mload(0x18a0), f_q)) - mstore(0x2a40, mulmod(mload(0x18c0), mload(0x18e0), f_q)) - mstore(0x2a60, mulmod(mload(0x1900), mload(0x1920), f_q)) - mstore(0x2a80, mulmod(mload(0x1940), mload(0x1960), f_q)) - mstore(0x2aa0, mulmod(mload(0x1980), mload(0x19a0), f_q)) - mstore(0x2ac0, mulmod(mload(0x19c0), mload(0x19e0), f_q)) - mstore(0x2ae0, mulmod(mload(0x1a00), mload(0x1a20), f_q)) - mstore(0x2b00, mulmod(mload(0x1a40), mload(0x1a60), f_q)) - mstore(0x2b20, mulmod(mload(0x1a80), mload(0x1aa0), f_q)) - mstore(0x2b40, mulmod(mload(0x1ac0), mload(0x1ae0), f_q)) - mstore(0x2b60, mulmod(mload(0x1b00), mload(0x1b20), f_q)) - mstore(0x2b80, mulmod(mload(0x1b40), mload(0x1b60), f_q)) - mstore(0x2ba0, mulmod(mload(0x1b80), mload(0x1ba0), f_q)) - mstore(0x2bc0, mulmod(mload(0x1bc0), mload(0x1be0), f_q)) - mstore(0x2be0, mulmod(mload(0x1c00), mload(0x1c20), f_q)) - mstore(0x2c00, mulmod(mload(0x1c40), mload(0x1c60), f_q)) - mstore(0x2c20, mulmod(mload(0x1c80), mload(0x1ca0), f_q)) - mstore(0x2c40, mulmod(mload(0x1cc0), mload(0x1ce0), f_q)) - mstore(0x2c60, mulmod(mload(0x1d00), mload(0x1d20), f_q)) - mstore(0x2c80, mulmod(mload(0x1d40), mload(0x1d60), f_q)) - mstore(0x2ca0, mulmod(mload(0x1d80), mload(0x1da0), f_q)) - mstore(0x2cc0, mulmod(mload(0x1dc0), mload(0x1de0), f_q)) - mstore(0x2ce0, mulmod(mload(0x1e00), mload(0x1e20), f_q)) - mstore(0x2d00, mulmod(mload(0x1e40), mload(0x1e60), f_q)) - mstore(0x2d20, mulmod(mload(0x1e80), mload(0x1ea0), f_q)) - mstore(0x2d40, mulmod(mload(0x1ec0), mload(0x1ee0), f_q)) - mstore(0x2d60, mulmod(mload(0x1f00), mload(0x1f20), f_q)) - mstore(0x2d80, mulmod(mload(0x1f40), mload(0x1f60), f_q)) - { - let result := mulmod(mload(0x27e0), mload(0xa0), f_q) - result := addmod(mulmod(mload(0x2800), mload(0xc0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2820), mload(0xe0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2840), mload(0x100), f_q), result, f_q) - result := addmod(mulmod(mload(0x2860), mload(0x120), f_q), result, f_q) - result := addmod(mulmod(mload(0x2880), mload(0x140), f_q), result, f_q) - result := addmod(mulmod(mload(0x28a0), mload(0x160), f_q), result, f_q) - result := addmod(mulmod(mload(0x28c0), mload(0x180), f_q), result, f_q) - result := addmod(mulmod(mload(0x28e0), mload(0x1a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2900), mload(0x1c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2920), mload(0x1e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2940), mload(0x200), f_q), result, f_q) - result := addmod(mulmod(mload(0x2960), mload(0x220), f_q), result, f_q) - result := addmod(mulmod(mload(0x2980), mload(0x240), f_q), result, f_q) - result := addmod(mulmod(mload(0x29a0), mload(0x260), f_q), result, f_q) - result := addmod(mulmod(mload(0x29c0), mload(0x280), f_q), result, f_q) - result := addmod(mulmod(mload(0x29e0), mload(0x2a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2a00), mload(0x2c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2a20), mload(0x2e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2a40), mload(0x300), f_q), result, f_q) - result := addmod(mulmod(mload(0x2a60), mload(0x320), f_q), result, f_q) - result := addmod(mulmod(mload(0x2a80), mload(0x340), f_q), result, f_q) - result := addmod(mulmod(mload(0x2aa0), mload(0x360), f_q), result, f_q) - result := addmod(mulmod(mload(0x2ac0), mload(0x380), f_q), result, f_q) - result := addmod(mulmod(mload(0x2ae0), mload(0x3a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2b00), mload(0x3c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2b20), mload(0x3e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2b40), mload(0x400), f_q), result, f_q) - result := addmod(mulmod(mload(0x2b60), mload(0x420), f_q), result, f_q) - result := addmod(mulmod(mload(0x2b80), mload(0x440), f_q), result, f_q) - result := addmod(mulmod(mload(0x2ba0), mload(0x460), f_q), result, f_q) - result := addmod(mulmod(mload(0x2bc0), mload(0x480), f_q), result, f_q) - result := addmod(mulmod(mload(0x2be0), mload(0x4a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2c00), mload(0x4c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2c20), mload(0x4e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2c40), mload(0x500), f_q), result, f_q) - result := addmod(mulmod(mload(0x2c60), mload(0x520), f_q), result, f_q) - result := addmod(mulmod(mload(0x2c80), mload(0x540), f_q), result, f_q) - result := addmod(mulmod(mload(0x2ca0), mload(0x560), f_q), result, f_q) - result := addmod(mulmod(mload(0x2cc0), mload(0x580), f_q), result, f_q) - result := addmod(mulmod(mload(0x2ce0), mload(0x5a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2d00), mload(0x5c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2d20), mload(0x5e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2d40), mload(0x600), f_q), result, f_q) - result := addmod(mulmod(mload(0x2d60), mload(0x620), f_q), result, f_q) - result := addmod(mulmod(mload(0x2d80), mload(0x640), f_q), result, f_q) - mstore(11680, result) - } - mstore(0x2dc0, mulmod(mload(0xb00), mload(0xae0), f_q)) - mstore(0x2de0, addmod(mload(0xac0), mload(0x2dc0), f_q)) - mstore(0x2e00, addmod(mload(0x2de0), sub(f_q, mload(0xb20)), f_q)) - mstore(0x2e20, mulmod(mload(0x2e00), mload(0xb80), f_q)) - mstore(0x2e40, mulmod(mload(0x920), mload(0x2e20), f_q)) - mstore(0x2e60, addmod(1, sub(f_q, mload(0xc40)), f_q)) - mstore(0x2e80, mulmod(mload(0x2e60), mload(0x27e0), f_q)) - mstore(0x2ea0, addmod(mload(0x2e40), mload(0x2e80), f_q)) - mstore(0x2ec0, mulmod(mload(0x920), mload(0x2ea0), f_q)) - mstore(0x2ee0, mulmod(mload(0xc40), mload(0xc40), f_q)) - mstore(0x2f00, addmod(mload(0x2ee0), sub(f_q, mload(0xc40)), f_q)) - mstore(0x2f20, mulmod(mload(0x2f00), mload(0x2700), f_q)) - mstore(0x2f40, addmod(mload(0x2ec0), mload(0x2f20), f_q)) - mstore(0x2f60, mulmod(mload(0x920), mload(0x2f40), f_q)) - mstore(0x2f80, addmod(1, sub(f_q, mload(0x2700)), f_q)) - mstore(0x2fa0, addmod(mload(0x2720), mload(0x2740), f_q)) - mstore(0x2fc0, addmod(mload(0x2fa0), 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(0x2f80), sub(f_q, mload(0x3020)), f_q)) - mstore(0x3060, mulmod(mload(0xbe0), mload(0x7a0), f_q)) - mstore(0x3080, addmod(mload(0xb40), mload(0x3060), f_q)) - mstore(0x30a0, addmod(mload(0x3080), mload(0x800), f_q)) - mstore(0x30c0, mulmod(mload(0xc00), mload(0x7a0), f_q)) - mstore(0x30e0, addmod(mload(0xac0), mload(0x30c0), f_q)) - mstore(0x3100, addmod(mload(0x30e0), mload(0x800), f_q)) - mstore(0x3120, mulmod(mload(0x3100), mload(0x30a0), f_q)) - mstore(0x3140, mulmod(mload(0xc20), mload(0x7a0), f_q)) - mstore(0x3160, addmod(mload(0x2da0), mload(0x3140), f_q)) - mstore(0x3180, addmod(mload(0x3160), mload(0x800), f_q)) - mstore(0x31a0, mulmod(mload(0x3180), mload(0x3120), f_q)) - mstore(0x31c0, mulmod(mload(0x31a0), mload(0xc60), f_q)) - mstore(0x31e0, mulmod(1, mload(0x7a0), f_q)) - mstore(0x3200, mulmod(mload(0xa80), mload(0x31e0), f_q)) - mstore(0x3220, addmod(mload(0xb40), mload(0x3200), f_q)) - mstore(0x3240, addmod(mload(0x3220), mload(0x800), f_q)) - mstore( - 0x3260, - mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x7a0), f_q) - ) - mstore(0x3280, mulmod(mload(0xa80), mload(0x3260), f_q)) - mstore(0x32a0, addmod(mload(0xac0), mload(0x3280), f_q)) - mstore(0x32c0, addmod(mload(0x32a0), mload(0x800), f_q)) - mstore(0x32e0, mulmod(mload(0x32c0), mload(0x3240), f_q)) - mstore( - 0x3300, - mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x7a0), f_q) - ) - mstore(0x3320, mulmod(mload(0xa80), mload(0x3300), f_q)) - mstore(0x3340, addmod(mload(0x2da0), mload(0x3320), f_q)) - mstore(0x3360, addmod(mload(0x3340), mload(0x800), f_q)) - mstore(0x3380, mulmod(mload(0x3360), mload(0x32e0), f_q)) - mstore(0x33a0, mulmod(mload(0x3380), mload(0xc40), f_q)) - mstore(0x33c0, addmod(mload(0x31c0), sub(f_q, mload(0x33a0)), f_q)) - mstore(0x33e0, mulmod(mload(0x33c0), mload(0x3040), f_q)) - mstore(0x3400, addmod(mload(0x2f60), mload(0x33e0), f_q)) - mstore(0x3420, mulmod(mload(0x920), mload(0x3400), f_q)) - mstore(0x3440, addmod(1, sub(f_q, mload(0xc80)), f_q)) - mstore(0x3460, mulmod(mload(0x3440), mload(0x27e0), f_q)) - mstore(0x3480, addmod(mload(0x3420), mload(0x3460), f_q)) - mstore(0x34a0, mulmod(mload(0x920), mload(0x3480), f_q)) - mstore(0x34c0, mulmod(mload(0xc80), mload(0xc80), f_q)) - mstore(0x34e0, addmod(mload(0x34c0), sub(f_q, mload(0xc80)), f_q)) - mstore(0x3500, mulmod(mload(0x34e0), mload(0x2700), f_q)) - mstore(0x3520, addmod(mload(0x34a0), mload(0x3500), f_q)) - mstore(0x3540, mulmod(mload(0x920), mload(0x3520), f_q)) - mstore(0x3560, addmod(mload(0xcc0), mload(0x7a0), f_q)) - mstore(0x3580, mulmod(mload(0x3560), mload(0xca0), f_q)) - mstore(0x35a0, addmod(mload(0xd00), mload(0x800), f_q)) - mstore(0x35c0, mulmod(mload(0x35a0), mload(0x3580), f_q)) - mstore(0x35e0, mulmod(mload(0xac0), mload(0xba0), f_q)) - mstore(0x3600, addmod(mload(0x35e0), mload(0x7a0), f_q)) - mstore(0x3620, mulmod(mload(0x3600), mload(0xc80), f_q)) - mstore(0x3640, addmod(mload(0xb60), mload(0x800), f_q)) - mstore(0x3660, mulmod(mload(0x3640), mload(0x3620), f_q)) - mstore(0x3680, addmod(mload(0x35c0), sub(f_q, mload(0x3660)), f_q)) - mstore(0x36a0, mulmod(mload(0x3680), mload(0x3040), f_q)) - mstore(0x36c0, addmod(mload(0x3540), mload(0x36a0), f_q)) - mstore(0x36e0, mulmod(mload(0x920), mload(0x36c0), f_q)) - mstore(0x3700, addmod(mload(0xcc0), sub(f_q, mload(0xd00)), f_q)) - mstore(0x3720, mulmod(mload(0x3700), mload(0x27e0), f_q)) - mstore(0x3740, addmod(mload(0x36e0), mload(0x3720), f_q)) - mstore(0x3760, mulmod(mload(0x920), mload(0x3740), f_q)) - mstore(0x3780, mulmod(mload(0x3700), mload(0x3040), f_q)) - mstore(0x37a0, addmod(mload(0xcc0), sub(f_q, mload(0xce0)), f_q)) - mstore(0x37c0, mulmod(mload(0x37a0), mload(0x3780), f_q)) - mstore(0x37e0, addmod(mload(0x3760), mload(0x37c0), f_q)) - mstore(0x3800, mulmod(mload(0x11e0), mload(0x11e0), f_q)) - mstore(0x3820, mulmod(mload(0x3800), mload(0x11e0), f_q)) - mstore(0x3840, mulmod(mload(0x3820), mload(0x11e0), f_q)) - mstore(0x3860, mulmod(1, mload(0x11e0), f_q)) - mstore(0x3880, mulmod(1, mload(0x3800), f_q)) - mstore(0x38a0, mulmod(1, mload(0x3820), f_q)) - mstore(0x38c0, mulmod(mload(0x37e0), mload(0x1200), f_q)) - mstore(0x38e0, mulmod(mload(0xf40), mload(0xa80), f_q)) - mstore(0x3900, mulmod(mload(0x38e0), mload(0xa80), f_q)) - mstore( - 0x3920, - mulmod(mload(0xa80), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) - ) - mstore(0x3940, addmod(mload(0xe40), sub(f_q, mload(0x3920)), f_q)) - mstore(0x3960, mulmod(mload(0xa80), 1, f_q)) - mstore(0x3980, addmod(mload(0xe40), sub(f_q, mload(0x3960)), f_q)) - mstore( - 0x39a0, - mulmod(mload(0xa80), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) - ) - mstore(0x39c0, addmod(mload(0xe40), sub(f_q, mload(0x39a0)), f_q)) - mstore( - 0x39e0, - mulmod(mload(0xa80), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) - ) - mstore(0x3a00, addmod(mload(0xe40), sub(f_q, mload(0x39e0)), f_q)) - mstore( - 0x3a20, - mulmod(mload(0xa80), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q) - ) - mstore(0x3a40, addmod(mload(0xe40), sub(f_q, mload(0x3a20)), f_q)) - mstore( - 0x3a60, - mulmod(3544324119167359571073009690693121464267965232733679586767649244433889388945, mload(0x38e0), f_q) - ) - mstore(0x3a80, mulmod(mload(0x3a60), 1, f_q)) - { - let result := mulmod(mload(0xe40), mload(0x3a60), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3a80)), f_q), result, f_q) - mstore(15008, result) - } - mstore( - 0x3ac0, - mulmod(3860370625838117017501327045244227871206764201116468958063324100051382735289, mload(0x38e0), f_q) - ) - mstore( - 0x3ae0, - mulmod( - mload(0x3ac0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q - ) - ) - { - let result := mulmod(mload(0xe40), mload(0x3ac0), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ae0)), f_q), result, f_q) - mstore(15104, result) - } - mstore( - 0x3b20, - mulmod( - 21616901807277407275624036604424346159916096890712898844034238973395610537327, mload(0x38e0), f_q - ) - ) - mstore( - 0x3b40, - mulmod(mload(0x3b20), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) - ) - { - let result := mulmod(mload(0xe40), mload(0x3b20), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3b40)), f_q), result, f_q) - mstore(15200, result) - } - mstore( - 0x3b80, - mulmod(3209408481237076479025468386201293941554240476766691830436732310949352383503, mload(0x38e0), f_q) - ) - mstore( - 0x3ba0, - mulmod( - mload(0x3b80), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q - ) - ) - { - let result := mulmod(mload(0xe40), mload(0x3b80), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ba0)), f_q), result, f_q) - mstore(15296, result) - } - mstore(0x3be0, mulmod(1, mload(0x3980), f_q)) - mstore(0x3c00, mulmod(mload(0x3be0), mload(0x39c0), f_q)) - mstore(0x3c20, mulmod(mload(0x3c00), mload(0x3a00), f_q)) - mstore(0x3c40, mulmod(mload(0x3c20), mload(0x3a40), f_q)) - mstore( - 0x3c60, - mulmod(10676941854703594198666993839846402519342119846958189386823924046696287912228, mload(0xa80), f_q) - ) - mstore(0x3c80, mulmod(mload(0x3c60), 1, f_q)) - { - let result := mulmod(mload(0xe40), mload(0x3c60), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3c80)), f_q), result, f_q) - mstore(15520, result) - } - mstore( - 0x3cc0, - mulmod(11211301017135681023579411905410872569206244553457844956874280139879520583389, mload(0xa80), f_q) - ) - mstore( - 0x3ce0, - mulmod( - mload(0x3cc0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q - ) - ) - { - let result := mulmod(mload(0xe40), mload(0x3cc0), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ce0)), f_q), result, f_q) - mstore(15616, result) - } - mstore( - 0x3d20, - mulmod(13154116519010929542673167886091370382741775939114889923107781597533678454430, mload(0xa80), f_q) - ) - mstore(0x3d40, mulmod(mload(0x3d20), 1, f_q)) - { - let result := mulmod(mload(0xe40), mload(0x3d20), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3d40)), f_q), result, f_q) - mstore(15712, result) - } - mstore( - 0x3d80, - mulmod(8734126352828345679573237859165904705806588461301144420590422589042130041187, mload(0xa80), f_q) - ) - mstore( - 0x3da0, - mulmod(mload(0x3d80), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) - ) - { - let result := mulmod(mload(0xe40), mload(0x3d80), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3da0)), f_q), result, f_q) - mstore(15808, result) - } - mstore(0x3de0, mulmod(mload(0x3be0), mload(0x3940), f_q)) - { - let result := mulmod(mload(0xe40), 1, f_q) - result := - addmod( - mulmod( - mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q - ), - result, - f_q - ) - mstore(15872, result) - } - { - let prod := mload(0x3aa0) + + } +mstore(0x2700, mulmod(mload(0x1240), mload(0x1260), f_q)) +mstore(0x2720, mulmod(mload(0x1280), mload(0x12a0), f_q)) +mstore(0x2740, mulmod(mload(0x12c0), mload(0x12e0), f_q)) +mstore(0x2760, mulmod(mload(0x1300), mload(0x1320), f_q)) +mstore(0x2780, mulmod(mload(0x1340), mload(0x1360), f_q)) +mstore(0x27a0, mulmod(mload(0x1380), mload(0x13a0), f_q)) +mstore(0x27c0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) +mstore(0x27e0, mulmod(mload(0x1400), mload(0x1420), f_q)) +mstore(0x2800, mulmod(mload(0x1440), mload(0x1460), f_q)) +mstore(0x2820, mulmod(mload(0x1480), mload(0x14a0), f_q)) +mstore(0x2840, mulmod(mload(0x14c0), mload(0x14e0), f_q)) +mstore(0x2860, mulmod(mload(0x1500), mload(0x1520), f_q)) +mstore(0x2880, mulmod(mload(0x1540), mload(0x1560), f_q)) +mstore(0x28a0, mulmod(mload(0x1580), mload(0x15a0), f_q)) +mstore(0x28c0, mulmod(mload(0x15c0), mload(0x15e0), f_q)) +mstore(0x28e0, mulmod(mload(0x1600), mload(0x1620), f_q)) +mstore(0x2900, mulmod(mload(0x1640), mload(0x1660), f_q)) +mstore(0x2920, mulmod(mload(0x1680), mload(0x16a0), f_q)) +mstore(0x2940, mulmod(mload(0x16c0), mload(0x16e0), f_q)) +mstore(0x2960, mulmod(mload(0x1700), mload(0x1720), f_q)) +mstore(0x2980, mulmod(mload(0x1740), mload(0x1760), f_q)) +mstore(0x29a0, mulmod(mload(0x1780), mload(0x17a0), f_q)) +mstore(0x29c0, mulmod(mload(0x17c0), mload(0x17e0), f_q)) +mstore(0x29e0, mulmod(mload(0x1800), mload(0x1820), f_q)) +mstore(0x2a00, mulmod(mload(0x1840), mload(0x1860), f_q)) +mstore(0x2a20, mulmod(mload(0x1880), mload(0x18a0), f_q)) +mstore(0x2a40, mulmod(mload(0x18c0), mload(0x18e0), f_q)) +mstore(0x2a60, mulmod(mload(0x1900), mload(0x1920), f_q)) +mstore(0x2a80, mulmod(mload(0x1940), mload(0x1960), f_q)) +mstore(0x2aa0, mulmod(mload(0x1980), mload(0x19a0), f_q)) +mstore(0x2ac0, mulmod(mload(0x19c0), mload(0x19e0), f_q)) +mstore(0x2ae0, mulmod(mload(0x1a00), mload(0x1a20), f_q)) +mstore(0x2b00, mulmod(mload(0x1a40), mload(0x1a60), f_q)) +mstore(0x2b20, mulmod(mload(0x1a80), mload(0x1aa0), f_q)) +mstore(0x2b40, mulmod(mload(0x1ac0), mload(0x1ae0), f_q)) +mstore(0x2b60, mulmod(mload(0x1b00), mload(0x1b20), f_q)) +mstore(0x2b80, mulmod(mload(0x1b40), mload(0x1b60), f_q)) +mstore(0x2ba0, mulmod(mload(0x1b80), mload(0x1ba0), f_q)) +mstore(0x2bc0, mulmod(mload(0x1bc0), mload(0x1be0), f_q)) +mstore(0x2be0, mulmod(mload(0x1c00), mload(0x1c20), f_q)) +mstore(0x2c00, mulmod(mload(0x1c40), mload(0x1c60), f_q)) +mstore(0x2c20, mulmod(mload(0x1c80), mload(0x1ca0), f_q)) +mstore(0x2c40, mulmod(mload(0x1cc0), mload(0x1ce0), f_q)) +mstore(0x2c60, mulmod(mload(0x1d00), mload(0x1d20), f_q)) +mstore(0x2c80, mulmod(mload(0x1d40), mload(0x1d60), f_q)) +mstore(0x2ca0, mulmod(mload(0x1d80), mload(0x1da0), f_q)) +mstore(0x2cc0, mulmod(mload(0x1dc0), mload(0x1de0), f_q)) +mstore(0x2ce0, mulmod(mload(0x1e00), mload(0x1e20), f_q)) +mstore(0x2d00, mulmod(mload(0x1e40), mload(0x1e60), f_q)) +mstore(0x2d20, mulmod(mload(0x1e80), mload(0x1ea0), f_q)) +mstore(0x2d40, mulmod(mload(0x1ec0), mload(0x1ee0), f_q)) +mstore(0x2d60, mulmod(mload(0x1f00), mload(0x1f20), f_q)) +mstore(0x2d80, mulmod(mload(0x1f40), mload(0x1f60), f_q)) +{ + let result := mulmod(mload(0x27e0), mload(0xa0), f_q) +result := addmod(mulmod(mload(0x2800), mload(0xc0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2820), mload(0xe0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2840), mload(0x100), f_q), result, f_q) +result := addmod(mulmod(mload(0x2860), mload(0x120), f_q), result, f_q) +result := addmod(mulmod(mload(0x2880), mload(0x140), f_q), result, f_q) +result := addmod(mulmod(mload(0x28a0), mload(0x160), f_q), result, f_q) +result := addmod(mulmod(mload(0x28c0), mload(0x180), f_q), result, f_q) +result := addmod(mulmod(mload(0x28e0), mload(0x1a0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2900), mload(0x1c0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2920), mload(0x1e0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2940), mload(0x200), f_q), result, f_q) +result := addmod(mulmod(mload(0x2960), mload(0x220), f_q), result, f_q) +result := addmod(mulmod(mload(0x2980), mload(0x240), f_q), result, f_q) +result := addmod(mulmod(mload(0x29a0), mload(0x260), f_q), result, f_q) +result := addmod(mulmod(mload(0x29c0), mload(0x280), f_q), result, f_q) +result := addmod(mulmod(mload(0x29e0), mload(0x2a0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2a00), mload(0x2c0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2a20), mload(0x2e0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2a40), mload(0x300), f_q), result, f_q) +result := addmod(mulmod(mload(0x2a60), mload(0x320), f_q), result, f_q) +result := addmod(mulmod(mload(0x2a80), mload(0x340), f_q), result, f_q) +result := addmod(mulmod(mload(0x2aa0), mload(0x360), f_q), result, f_q) +result := addmod(mulmod(mload(0x2ac0), mload(0x380), f_q), result, f_q) +result := addmod(mulmod(mload(0x2ae0), mload(0x3a0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2b00), mload(0x3c0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2b20), mload(0x3e0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2b40), mload(0x400), f_q), result, f_q) +result := addmod(mulmod(mload(0x2b60), mload(0x420), f_q), result, f_q) +result := addmod(mulmod(mload(0x2b80), mload(0x440), f_q), result, f_q) +result := addmod(mulmod(mload(0x2ba0), mload(0x460), f_q), result, f_q) +result := addmod(mulmod(mload(0x2bc0), mload(0x480), f_q), result, f_q) +result := addmod(mulmod(mload(0x2be0), mload(0x4a0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2c00), mload(0x4c0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2c20), mload(0x4e0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2c40), mload(0x500), f_q), result, f_q) +result := addmod(mulmod(mload(0x2c60), mload(0x520), f_q), result, f_q) +result := addmod(mulmod(mload(0x2c80), mload(0x540), f_q), result, f_q) +result := addmod(mulmod(mload(0x2ca0), mload(0x560), f_q), result, f_q) +result := addmod(mulmod(mload(0x2cc0), mload(0x580), f_q), result, f_q) +result := addmod(mulmod(mload(0x2ce0), mload(0x5a0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2d00), mload(0x5c0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2d20), mload(0x5e0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2d40), mload(0x600), f_q), result, f_q) +result := addmod(mulmod(mload(0x2d60), mload(0x620), f_q), result, f_q) +result := addmod(mulmod(mload(0x2d80), mload(0x640), f_q), result, f_q) +mstore(11680, result) + } +mstore(0x2dc0, mulmod(mload(0xb00), mload(0xae0), f_q)) +mstore(0x2de0, addmod(mload(0xac0), mload(0x2dc0), f_q)) +mstore(0x2e00, addmod(mload(0x2de0), sub(f_q, mload(0xb20)), f_q)) +mstore(0x2e20, mulmod(mload(0x2e00), mload(0xb80), f_q)) +mstore(0x2e40, mulmod(mload(0x920), mload(0x2e20), f_q)) +mstore(0x2e60, addmod(1, sub(f_q, mload(0xc40)), f_q)) +mstore(0x2e80, mulmod(mload(0x2e60), mload(0x27e0), f_q)) +mstore(0x2ea0, addmod(mload(0x2e40), mload(0x2e80), f_q)) +mstore(0x2ec0, mulmod(mload(0x920), mload(0x2ea0), f_q)) +mstore(0x2ee0, mulmod(mload(0xc40), mload(0xc40), f_q)) +mstore(0x2f00, addmod(mload(0x2ee0), sub(f_q, mload(0xc40)), f_q)) +mstore(0x2f20, mulmod(mload(0x2f00), mload(0x2700), f_q)) +mstore(0x2f40, addmod(mload(0x2ec0), mload(0x2f20), f_q)) +mstore(0x2f60, mulmod(mload(0x920), mload(0x2f40), f_q)) +mstore(0x2f80, addmod(1, sub(f_q, mload(0x2700)), f_q)) +mstore(0x2fa0, addmod(mload(0x2720), mload(0x2740), f_q)) +mstore(0x2fc0, addmod(mload(0x2fa0), 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(0x2f80), sub(f_q, mload(0x3020)), f_q)) +mstore(0x3060, mulmod(mload(0xbe0), mload(0x7a0), f_q)) +mstore(0x3080, addmod(mload(0xb40), mload(0x3060), f_q)) +mstore(0x30a0, addmod(mload(0x3080), mload(0x800), f_q)) +mstore(0x30c0, mulmod(mload(0xc00), mload(0x7a0), f_q)) +mstore(0x30e0, addmod(mload(0xac0), mload(0x30c0), f_q)) +mstore(0x3100, addmod(mload(0x30e0), mload(0x800), f_q)) +mstore(0x3120, mulmod(mload(0x3100), mload(0x30a0), f_q)) +mstore(0x3140, mulmod(mload(0xc20), mload(0x7a0), f_q)) +mstore(0x3160, addmod(mload(0x2da0), mload(0x3140), f_q)) +mstore(0x3180, addmod(mload(0x3160), mload(0x800), f_q)) +mstore(0x31a0, mulmod(mload(0x3180), mload(0x3120), f_q)) +mstore(0x31c0, mulmod(mload(0x31a0), mload(0xc60), f_q)) +mstore(0x31e0, mulmod(1, mload(0x7a0), f_q)) +mstore(0x3200, mulmod(mload(0xa80), mload(0x31e0), f_q)) +mstore(0x3220, addmod(mload(0xb40), mload(0x3200), f_q)) +mstore(0x3240, addmod(mload(0x3220), mload(0x800), f_q)) +mstore(0x3260, mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x7a0), f_q)) +mstore(0x3280, mulmod(mload(0xa80), mload(0x3260), f_q)) +mstore(0x32a0, addmod(mload(0xac0), mload(0x3280), f_q)) +mstore(0x32c0, addmod(mload(0x32a0), mload(0x800), f_q)) +mstore(0x32e0, mulmod(mload(0x32c0), mload(0x3240), f_q)) +mstore(0x3300, mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x7a0), f_q)) +mstore(0x3320, mulmod(mload(0xa80), mload(0x3300), f_q)) +mstore(0x3340, addmod(mload(0x2da0), mload(0x3320), f_q)) +mstore(0x3360, addmod(mload(0x3340), mload(0x800), f_q)) +mstore(0x3380, mulmod(mload(0x3360), mload(0x32e0), f_q)) +mstore(0x33a0, mulmod(mload(0x3380), mload(0xc40), f_q)) +mstore(0x33c0, addmod(mload(0x31c0), sub(f_q, mload(0x33a0)), f_q)) +mstore(0x33e0, mulmod(mload(0x33c0), mload(0x3040), f_q)) +mstore(0x3400, addmod(mload(0x2f60), mload(0x33e0), f_q)) +mstore(0x3420, mulmod(mload(0x920), mload(0x3400), f_q)) +mstore(0x3440, addmod(1, sub(f_q, mload(0xc80)), f_q)) +mstore(0x3460, mulmod(mload(0x3440), mload(0x27e0), f_q)) +mstore(0x3480, addmod(mload(0x3420), mload(0x3460), f_q)) +mstore(0x34a0, mulmod(mload(0x920), mload(0x3480), f_q)) +mstore(0x34c0, mulmod(mload(0xc80), mload(0xc80), f_q)) +mstore(0x34e0, addmod(mload(0x34c0), sub(f_q, mload(0xc80)), f_q)) +mstore(0x3500, mulmod(mload(0x34e0), mload(0x2700), f_q)) +mstore(0x3520, addmod(mload(0x34a0), mload(0x3500), f_q)) +mstore(0x3540, mulmod(mload(0x920), mload(0x3520), f_q)) +mstore(0x3560, addmod(mload(0xcc0), mload(0x7a0), f_q)) +mstore(0x3580, mulmod(mload(0x3560), mload(0xca0), f_q)) +mstore(0x35a0, addmod(mload(0xd00), mload(0x800), f_q)) +mstore(0x35c0, mulmod(mload(0x35a0), mload(0x3580), f_q)) +mstore(0x35e0, mulmod(mload(0xac0), mload(0xba0), f_q)) +mstore(0x3600, addmod(mload(0x35e0), mload(0x7a0), f_q)) +mstore(0x3620, mulmod(mload(0x3600), mload(0xc80), f_q)) +mstore(0x3640, addmod(mload(0xb60), mload(0x800), f_q)) +mstore(0x3660, mulmod(mload(0x3640), mload(0x3620), f_q)) +mstore(0x3680, addmod(mload(0x35c0), sub(f_q, mload(0x3660)), f_q)) +mstore(0x36a0, mulmod(mload(0x3680), mload(0x3040), f_q)) +mstore(0x36c0, addmod(mload(0x3540), mload(0x36a0), f_q)) +mstore(0x36e0, mulmod(mload(0x920), mload(0x36c0), f_q)) +mstore(0x3700, addmod(mload(0xcc0), sub(f_q, mload(0xd00)), f_q)) +mstore(0x3720, mulmod(mload(0x3700), mload(0x27e0), f_q)) +mstore(0x3740, addmod(mload(0x36e0), mload(0x3720), f_q)) +mstore(0x3760, mulmod(mload(0x920), mload(0x3740), f_q)) +mstore(0x3780, mulmod(mload(0x3700), mload(0x3040), f_q)) +mstore(0x37a0, addmod(mload(0xcc0), sub(f_q, mload(0xce0)), f_q)) +mstore(0x37c0, mulmod(mload(0x37a0), mload(0x3780), f_q)) +mstore(0x37e0, addmod(mload(0x3760), mload(0x37c0), f_q)) +mstore(0x3800, mulmod(mload(0x11e0), mload(0x11e0), f_q)) +mstore(0x3820, mulmod(mload(0x3800), mload(0x11e0), f_q)) +mstore(0x3840, mulmod(mload(0x3820), mload(0x11e0), f_q)) +mstore(0x3860, mulmod(1, mload(0x11e0), f_q)) +mstore(0x3880, mulmod(1, mload(0x3800), f_q)) +mstore(0x38a0, mulmod(1, mload(0x3820), f_q)) +mstore(0x38c0, mulmod(mload(0x37e0), mload(0x1200), f_q)) +mstore(0x38e0, mulmod(mload(0xf40), mload(0xa80), f_q)) +mstore(0x3900, mulmod(mload(0x38e0), mload(0xa80), f_q)) +mstore(0x3920, mulmod(mload(0xa80), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q)) +mstore(0x3940, addmod(mload(0xe40), sub(f_q, mload(0x3920)), f_q)) +mstore(0x3960, mulmod(mload(0xa80), 1, f_q)) +mstore(0x3980, addmod(mload(0xe40), sub(f_q, mload(0x3960)), f_q)) +mstore(0x39a0, mulmod(mload(0xa80), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q)) +mstore(0x39c0, addmod(mload(0xe40), sub(f_q, mload(0x39a0)), f_q)) +mstore(0x39e0, mulmod(mload(0xa80), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +mstore(0x3a00, addmod(mload(0xe40), sub(f_q, mload(0x39e0)), f_q)) +mstore(0x3a20, mulmod(mload(0xa80), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q)) +mstore(0x3a40, addmod(mload(0xe40), sub(f_q, mload(0x3a20)), f_q)) +mstore(0x3a60, mulmod(3544324119167359571073009690693121464267965232733679586767649244433889388945, mload(0x38e0), f_q)) +mstore(0x3a80, mulmod(mload(0x3a60), 1, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3a60), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3a80)), f_q), result, f_q) +mstore(15008, result) + } +mstore(0x3ac0, mulmod(3860370625838117017501327045244227871206764201116468958063324100051382735289, mload(0x38e0), f_q)) +mstore(0x3ae0, mulmod(mload(0x3ac0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3ac0), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ae0)), f_q), result, f_q) +mstore(15104, result) + } +mstore(0x3b20, mulmod(21616901807277407275624036604424346159916096890712898844034238973395610537327, mload(0x38e0), f_q)) +mstore(0x3b40, mulmod(mload(0x3b20), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3b20), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3b40)), f_q), result, f_q) +mstore(15200, result) + } +mstore(0x3b80, mulmod(3209408481237076479025468386201293941554240476766691830436732310949352383503, mload(0x38e0), f_q)) +mstore(0x3ba0, mulmod(mload(0x3b80), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3b80), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ba0)), f_q), result, f_q) +mstore(15296, result) + } +mstore(0x3be0, mulmod(1, mload(0x3980), f_q)) +mstore(0x3c00, mulmod(mload(0x3be0), mload(0x39c0), f_q)) +mstore(0x3c20, mulmod(mload(0x3c00), mload(0x3a00), f_q)) +mstore(0x3c40, mulmod(mload(0x3c20), mload(0x3a40), f_q)) +mstore(0x3c60, mulmod(10676941854703594198666993839846402519342119846958189386823924046696287912228, mload(0xa80), f_q)) +mstore(0x3c80, mulmod(mload(0x3c60), 1, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3c60), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3c80)), f_q), result, f_q) +mstore(15520, result) + } +mstore(0x3cc0, mulmod(11211301017135681023579411905410872569206244553457844956874280139879520583389, mload(0xa80), f_q)) +mstore(0x3ce0, mulmod(mload(0x3cc0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3cc0), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ce0)), f_q), result, f_q) +mstore(15616, result) + } +mstore(0x3d20, mulmod(13154116519010929542673167886091370382741775939114889923107781597533678454430, mload(0xa80), f_q)) +mstore(0x3d40, mulmod(mload(0x3d20), 1, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3d20), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3d40)), f_q), result, f_q) +mstore(15712, result) + } +mstore(0x3d80, mulmod(8734126352828345679573237859165904705806588461301144420590422589042130041187, mload(0xa80), f_q)) +mstore(0x3da0, mulmod(mload(0x3d80), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3d80), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3da0)), f_q), result, f_q) +mstore(15808, result) + } +mstore(0x3de0, mulmod(mload(0x3be0), mload(0x3940), f_q)) +{ + let result := mulmod(mload(0xe40), 1, f_q) +result := addmod(mulmod(mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q), result, f_q) +mstore(15872, result) + } +{ + let prod := mload(0x3aa0) prod := mulmod(mload(0x3b00), prod, f_q) mstore(0x3e20, prod) - + prod := mulmod(mload(0x3b60), prod, f_q) mstore(0x3e40, prod) - + prod := mulmod(mload(0x3bc0), prod, f_q) mstore(0x3e60, prod) - + prod := mulmod(mload(0x3ca0), prod, f_q) mstore(0x3e80, prod) - + prod := mulmod(mload(0x3d00), prod, f_q) mstore(0x3ea0, prod) - + prod := mulmod(mload(0x3c00), prod, f_q) mstore(0x3ec0, prod) - + prod := mulmod(mload(0x3d60), prod, f_q) mstore(0x3ee0, prod) - + prod := mulmod(mload(0x3dc0), prod, f_q) mstore(0x3f00, prod) - + prod := mulmod(mload(0x3de0), prod, f_q) mstore(0x3f20, prod) - + prod := mulmod(mload(0x3e00), prod, f_q) mstore(0x3f40, prod) - + prod := mulmod(mload(0x3be0), prod, f_q) mstore(0x3f60, prod) - } - mstore(0x3fa0, 32) - mstore(0x3fc0, 32) - mstore(0x3fe0, 32) - mstore(0x4000, mload(0x3f60)) - mstore(0x4020, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x4040, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x3fa0, 0xc0, 0x3f80, 0x20), 1), success) - { - let inv := mload(0x3f80) - let v - - v := mload(0x3be0) - mstore(15328, mulmod(mload(0x3f40), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3e00) - mstore(15872, mulmod(mload(0x3f20), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3de0) - mstore(15840, mulmod(mload(0x3f00), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3dc0) - mstore(15808, mulmod(mload(0x3ee0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3d60) - mstore(15712, mulmod(mload(0x3ec0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3c00) - mstore(15360, mulmod(mload(0x3ea0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3d00) - mstore(15616, mulmod(mload(0x3e80), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3ca0) - mstore(15520, mulmod(mload(0x3e60), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3bc0) - mstore(15296, mulmod(mload(0x3e40), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3b60) - mstore(15200, mulmod(mload(0x3e20), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3b00) - mstore(15104, mulmod(mload(0x3aa0), inv, f_q)) - inv := mulmod(v, inv, f_q) + + } +mstore(0x3fa0, 32) +mstore(0x3fc0, 32) +mstore(0x3fe0, 32) +mstore(0x4000, mload(0x3f60)) +mstore(0x4020, 21888242871839275222246405745257275088548364400416034343698204186575808495615) +mstore(0x4040, 21888242871839275222246405745257275088548364400416034343698204186575808495617) +success := and(eq(staticcall(gas(), 0x5, 0x3fa0, 0xc0, 0x3f80, 0x20), 1), success) +{ + + let inv := mload(0x3f80) + let v + + v := mload(0x3be0) + mstore(15328, mulmod(mload(0x3f40), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3e00) + mstore(15872, mulmod(mload(0x3f20), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3de0) + mstore(15840, mulmod(mload(0x3f00), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3dc0) + mstore(15808, mulmod(mload(0x3ee0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3d60) + mstore(15712, mulmod(mload(0x3ec0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3c00) + mstore(15360, mulmod(mload(0x3ea0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3d00) + mstore(15616, mulmod(mload(0x3e80), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3ca0) + mstore(15520, mulmod(mload(0x3e60), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3bc0) + mstore(15296, mulmod(mload(0x3e40), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3b60) + mstore(15200, mulmod(mload(0x3e20), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3b00) + mstore(15104, mulmod(mload(0x3aa0), inv, f_q)) + inv := mulmod(v, inv, f_q) mstore(0x3aa0, inv) - } - { - let result := mload(0x3aa0) - result := addmod(mload(0x3b00), result, f_q) - result := addmod(mload(0x3b60), result, f_q) - result := addmod(mload(0x3bc0), result, f_q) - mstore(16480, result) - } - mstore(0x4080, mulmod(mload(0x3c40), mload(0x3c00), f_q)) - { - let result := mload(0x3ca0) - result := addmod(mload(0x3d00), result, f_q) - mstore(16544, result) - } - mstore(0x40c0, mulmod(mload(0x3c40), mload(0x3de0), f_q)) - { - let result := mload(0x3d60) - result := addmod(mload(0x3dc0), result, f_q) - mstore(16608, result) - } - mstore(0x4100, mulmod(mload(0x3c40), mload(0x3be0), f_q)) - { - let result := mload(0x3e00) - mstore(16672, result) - } - { - let prod := mload(0x4060) + + } +{ + let result := mload(0x3aa0) +result := addmod(mload(0x3b00), result, f_q) +result := addmod(mload(0x3b60), result, f_q) +result := addmod(mload(0x3bc0), result, f_q) +mstore(16480, result) + } +mstore(0x4080, mulmod(mload(0x3c40), mload(0x3c00), f_q)) +{ + let result := mload(0x3ca0) +result := addmod(mload(0x3d00), result, f_q) +mstore(16544, result) + } +mstore(0x40c0, mulmod(mload(0x3c40), mload(0x3de0), f_q)) +{ + let result := mload(0x3d60) +result := addmod(mload(0x3dc0), result, f_q) +mstore(16608, result) + } +mstore(0x4100, mulmod(mload(0x3c40), mload(0x3be0), f_q)) +{ + let result := mload(0x3e00) +mstore(16672, result) + } +{ + let prod := mload(0x4060) prod := mulmod(mload(0x40a0), prod, f_q) mstore(0x4140, prod) - + prod := mulmod(mload(0x40e0), prod, f_q) mstore(0x4160, prod) - + prod := mulmod(mload(0x4120), prod, f_q) mstore(0x4180, prod) - } - mstore(0x41c0, 32) - mstore(0x41e0, 32) - mstore(0x4200, 32) - mstore(0x4220, mload(0x4180)) - mstore(0x4240, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x4260, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x41c0, 0xc0, 0x41a0, 0x20), 1), success) - { - let inv := mload(0x41a0) - let v - - v := mload(0x4120) - mstore(16672, mulmod(mload(0x4160), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x40e0) - mstore(16608, mulmod(mload(0x4140), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x40a0) - mstore(16544, mulmod(mload(0x4060), inv, f_q)) - inv := mulmod(v, inv, f_q) + + } +mstore(0x41c0, 32) +mstore(0x41e0, 32) +mstore(0x4200, 32) +mstore(0x4220, mload(0x4180)) +mstore(0x4240, 21888242871839275222246405745257275088548364400416034343698204186575808495615) +mstore(0x4260, 21888242871839275222246405745257275088548364400416034343698204186575808495617) +success := and(eq(staticcall(gas(), 0x5, 0x41c0, 0xc0, 0x41a0, 0x20), 1), success) +{ + + let inv := mload(0x41a0) + let v + + v := mload(0x4120) + mstore(16672, mulmod(mload(0x4160), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x40e0) + mstore(16608, mulmod(mload(0x4140), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x40a0) + mstore(16544, mulmod(mload(0x4060), inv, f_q)) + inv := mulmod(v, inv, f_q) mstore(0x4060, inv) - } - mstore(0x4280, mulmod(mload(0x4080), mload(0x40a0), f_q)) - mstore(0x42a0, mulmod(mload(0x40c0), mload(0x40e0), f_q)) - mstore(0x42c0, mulmod(mload(0x4100), mload(0x4120), f_q)) - mstore(0x42e0, mulmod(mload(0xd40), mload(0xd40), f_q)) - mstore(0x4300, mulmod(mload(0x42e0), 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(0xda0), mload(0xda0), f_q)) - mstore(0x4420, mulmod(mload(0x4400), mload(0xda0), f_q)) - mstore(0x4440, mulmod(mload(0x4420), mload(0xda0), f_q)) - { - let result := mulmod(mload(0xac0), mload(0x3aa0), f_q) - result := addmod(mulmod(mload(0xae0), mload(0x3b00), f_q), result, f_q) - result := addmod(mulmod(mload(0xb00), mload(0x3b60), f_q), result, f_q) - result := addmod(mulmod(mload(0xb20), mload(0x3bc0), f_q), result, f_q) - mstore(17504, result) - } - mstore(0x4480, mulmod(mload(0x4460), mload(0x4060), f_q)) - mstore(0x44a0, mulmod(sub(f_q, mload(0x4480)), 1, f_q)) - mstore(0x44c0, mulmod(mload(0x44a0), 1, f_q)) - mstore(0x44e0, mulmod(1, mload(0x4080), f_q)) - { - let result := mulmod(mload(0xc40), mload(0x3ca0), f_q) - result := addmod(mulmod(mload(0xc60), mload(0x3d00), f_q), result, f_q) - mstore(17664, result) - } - mstore(0x4520, mulmod(mload(0x4500), mload(0x4280), f_q)) - mstore(0x4540, mulmod(sub(f_q, mload(0x4520)), 1, f_q)) - mstore(0x4560, mulmod(mload(0x44e0), 1, f_q)) - { - let result := mulmod(mload(0xc80), mload(0x3ca0), f_q) - result := addmod(mulmod(mload(0xca0), mload(0x3d00), f_q), result, f_q) - mstore(17792, result) - } - mstore(0x45a0, mulmod(mload(0x4580), mload(0x4280), f_q)) - mstore(0x45c0, mulmod(sub(f_q, mload(0x45a0)), mload(0xd40), f_q)) - mstore(0x45e0, mulmod(mload(0x44e0), mload(0xd40), f_q)) - mstore(0x4600, addmod(mload(0x4540), mload(0x45c0), f_q)) - mstore(0x4620, mulmod(mload(0x4600), mload(0xda0), f_q)) - mstore(0x4640, mulmod(mload(0x4560), mload(0xda0), f_q)) - mstore(0x4660, mulmod(mload(0x45e0), mload(0xda0), f_q)) - mstore(0x4680, addmod(mload(0x44c0), mload(0x4620), f_q)) - mstore(0x46a0, mulmod(1, mload(0x40c0), f_q)) - { - let result := mulmod(mload(0xcc0), mload(0x3d60), f_q) - result := addmod(mulmod(mload(0xce0), mload(0x3dc0), f_q), result, f_q) - mstore(18112, result) - } - mstore(0x46e0, mulmod(mload(0x46c0), mload(0x42a0), f_q)) - mstore(0x4700, mulmod(sub(f_q, mload(0x46e0)), 1, f_q)) - mstore(0x4720, mulmod(mload(0x46a0), 1, f_q)) - mstore(0x4740, mulmod(mload(0x4700), mload(0x4400), f_q)) - mstore(0x4760, mulmod(mload(0x4720), mload(0x4400), f_q)) - mstore(0x4780, addmod(mload(0x4680), mload(0x4740), f_q)) - mstore(0x47a0, mulmod(1, mload(0x4100), f_q)) - { - let result := mulmod(mload(0xd00), mload(0x3e00), f_q) - mstore(18368, result) - } - mstore(0x47e0, mulmod(mload(0x47c0), mload(0x42c0), f_q)) - mstore(0x4800, mulmod(sub(f_q, mload(0x47e0)), 1, f_q)) - mstore(0x4820, mulmod(mload(0x47a0), 1, f_q)) - { - let result := mulmod(mload(0xb40), mload(0x3e00), f_q) - mstore(18496, result) - } - mstore(0x4860, mulmod(mload(0x4840), mload(0x42c0), f_q)) - mstore(0x4880, mulmod(sub(f_q, mload(0x4860)), mload(0xd40), f_q)) - mstore(0x48a0, mulmod(mload(0x47a0), mload(0xd40), f_q)) - mstore(0x48c0, addmod(mload(0x4800), mload(0x4880), f_q)) - { - let result := mulmod(mload(0xb60), mload(0x3e00), f_q) - mstore(18656, result) - } - mstore(0x4900, mulmod(mload(0x48e0), mload(0x42c0), f_q)) - mstore(0x4920, mulmod(sub(f_q, mload(0x4900)), mload(0x42e0), f_q)) - mstore(0x4940, mulmod(mload(0x47a0), mload(0x42e0), f_q)) - mstore(0x4960, addmod(mload(0x48c0), mload(0x4920), f_q)) - { - let result := mulmod(mload(0xb80), mload(0x3e00), f_q) - mstore(18816, result) - } - mstore(0x49a0, mulmod(mload(0x4980), mload(0x42c0), f_q)) - mstore(0x49c0, mulmod(sub(f_q, mload(0x49a0)), mload(0x4300), f_q)) - mstore(0x49e0, mulmod(mload(0x47a0), mload(0x4300), f_q)) - mstore(0x4a00, addmod(mload(0x4960), mload(0x49c0), f_q)) - { - let result := mulmod(mload(0xba0), mload(0x3e00), f_q) - mstore(18976, result) - } - mstore(0x4a40, mulmod(mload(0x4a20), mload(0x42c0), f_q)) - mstore(0x4a60, mulmod(sub(f_q, mload(0x4a40)), mload(0x4320), f_q)) - mstore(0x4a80, mulmod(mload(0x47a0), mload(0x4320), f_q)) - mstore(0x4aa0, addmod(mload(0x4a00), mload(0x4a60), f_q)) - { - let result := mulmod(mload(0xbe0), mload(0x3e00), f_q) - mstore(19136, result) - } - mstore(0x4ae0, mulmod(mload(0x4ac0), mload(0x42c0), f_q)) - mstore(0x4b00, mulmod(sub(f_q, mload(0x4ae0)), mload(0x4340), f_q)) - mstore(0x4b20, mulmod(mload(0x47a0), mload(0x4340), f_q)) - mstore(0x4b40, addmod(mload(0x4aa0), mload(0x4b00), f_q)) - { - let result := mulmod(mload(0xc00), mload(0x3e00), f_q) - mstore(19296, result) - } - mstore(0x4b80, mulmod(mload(0x4b60), mload(0x42c0), f_q)) - mstore(0x4ba0, mulmod(sub(f_q, mload(0x4b80)), mload(0x4360), f_q)) - mstore(0x4bc0, mulmod(mload(0x47a0), mload(0x4360), f_q)) - mstore(0x4be0, addmod(mload(0x4b40), mload(0x4ba0), f_q)) - { - let result := mulmod(mload(0xc20), mload(0x3e00), f_q) - mstore(19456, result) - } - mstore(0x4c20, mulmod(mload(0x4c00), mload(0x42c0), f_q)) - mstore(0x4c40, mulmod(sub(f_q, mload(0x4c20)), mload(0x4380), f_q)) - mstore(0x4c60, mulmod(mload(0x47a0), mload(0x4380), f_q)) - mstore(0x4c80, addmod(mload(0x4be0), mload(0x4c40), f_q)) - mstore(0x4ca0, mulmod(mload(0x3860), mload(0x4100), f_q)) - mstore(0x4cc0, mulmod(mload(0x3880), mload(0x4100), f_q)) - mstore(0x4ce0, mulmod(mload(0x38a0), mload(0x4100), f_q)) - { - let result := mulmod(mload(0x38c0), mload(0x3e00), f_q) - mstore(19712, result) - } - mstore(0x4d20, mulmod(mload(0x4d00), mload(0x42c0), f_q)) - mstore(0x4d40, mulmod(sub(f_q, mload(0x4d20)), mload(0x43a0), f_q)) - mstore(0x4d60, mulmod(mload(0x47a0), mload(0x43a0), f_q)) - mstore(0x4d80, mulmod(mload(0x4ca0), mload(0x43a0), f_q)) - mstore(0x4da0, mulmod(mload(0x4cc0), mload(0x43a0), f_q)) - mstore(0x4dc0, mulmod(mload(0x4ce0), mload(0x43a0), f_q)) - mstore(0x4de0, addmod(mload(0x4c80), mload(0x4d40), f_q)) - { - let result := mulmod(mload(0xbc0), mload(0x3e00), f_q) - mstore(19968, result) - } - mstore(0x4e20, mulmod(mload(0x4e00), mload(0x42c0), f_q)) - mstore(0x4e40, mulmod(sub(f_q, mload(0x4e20)), mload(0x43c0), f_q)) - mstore(0x4e60, mulmod(mload(0x47a0), mload(0x43c0), f_q)) - mstore(0x4e80, addmod(mload(0x4de0), mload(0x4e40), f_q)) - mstore(0x4ea0, mulmod(mload(0x4e80), mload(0x4420), f_q)) - mstore(0x4ec0, mulmod(mload(0x4820), mload(0x4420), f_q)) - mstore(0x4ee0, mulmod(mload(0x48a0), mload(0x4420), f_q)) - mstore(0x4f00, mulmod(mload(0x4940), mload(0x4420), f_q)) - mstore(0x4f20, mulmod(mload(0x49e0), mload(0x4420), f_q)) - mstore(0x4f40, mulmod(mload(0x4a80), mload(0x4420), f_q)) - mstore(0x4f60, mulmod(mload(0x4b20), mload(0x4420), f_q)) - mstore(0x4f80, mulmod(mload(0x4bc0), mload(0x4420), f_q)) - mstore(0x4fa0, mulmod(mload(0x4c60), mload(0x4420), f_q)) - mstore(0x4fc0, mulmod(mload(0x4d60), mload(0x4420), f_q)) - mstore(0x4fe0, mulmod(mload(0x4d80), mload(0x4420), f_q)) - mstore(0x5000, mulmod(mload(0x4da0), mload(0x4420), f_q)) - mstore(0x5020, mulmod(mload(0x4dc0), mload(0x4420), f_q)) - mstore(0x5040, mulmod(mload(0x4e60), mload(0x4420), f_q)) - mstore(0x5060, addmod(mload(0x4780), mload(0x4ea0), f_q)) - mstore(0x5080, mulmod(1, mload(0x3c40), f_q)) - mstore(0x50a0, mulmod(1, mload(0xe40), f_q)) - mstore(0x50c0, 0x0000000000000000000000000000000000000000000000000000000000000001) - mstore(0x50e0, 0x0000000000000000000000000000000000000000000000000000000000000002) - mstore(0x5100, mload(0x5060)) - success := and(eq(staticcall(gas(), 0x7, 0x50c0, 0x60, 0x50c0, 0x40), 1), success) - mstore(0x5120, mload(0x50c0)) - mstore(0x5140, mload(0x50e0)) - mstore(0x5160, mload(0x660)) - mstore(0x5180, mload(0x680)) - success := and(eq(staticcall(gas(), 0x6, 0x5120, 0x80, 0x5120, 0x40), 1), success) - mstore(0x51a0, mload(0x840)) - mstore(0x51c0, mload(0x860)) - mstore(0x51e0, mload(0x4640)) - success := and(eq(staticcall(gas(), 0x7, 0x51a0, 0x60, 0x51a0, 0x40), 1), success) - mstore(0x5200, mload(0x5120)) - mstore(0x5220, mload(0x5140)) - mstore(0x5240, mload(0x51a0)) - mstore(0x5260, mload(0x51c0)) - success := and(eq(staticcall(gas(), 0x6, 0x5200, 0x80, 0x5200, 0x40), 1), success) - mstore(0x5280, mload(0x880)) - mstore(0x52a0, mload(0x8a0)) - mstore(0x52c0, mload(0x4660)) - success := and(eq(staticcall(gas(), 0x7, 0x5280, 0x60, 0x5280, 0x40), 1), success) - mstore(0x52e0, mload(0x5200)) - mstore(0x5300, mload(0x5220)) - mstore(0x5320, mload(0x5280)) - mstore(0x5340, mload(0x52a0)) - success := and(eq(staticcall(gas(), 0x6, 0x52e0, 0x80, 0x52e0, 0x40), 1), success) - mstore(0x5360, mload(0x700)) - mstore(0x5380, mload(0x720)) - mstore(0x53a0, mload(0x4760)) - success := and(eq(staticcall(gas(), 0x7, 0x5360, 0x60, 0x5360, 0x40), 1), success) - mstore(0x53c0, mload(0x52e0)) - mstore(0x53e0, mload(0x5300)) - mstore(0x5400, mload(0x5360)) - mstore(0x5420, mload(0x5380)) - success := and(eq(staticcall(gas(), 0x6, 0x53c0, 0x80, 0x53c0, 0x40), 1), success) - mstore(0x5440, mload(0x740)) - mstore(0x5460, mload(0x760)) - mstore(0x5480, mload(0x4ec0)) - success := and(eq(staticcall(gas(), 0x7, 0x5440, 0x60, 0x5440, 0x40), 1), success) - mstore(0x54a0, mload(0x53c0)) - mstore(0x54c0, mload(0x53e0)) - mstore(0x54e0, mload(0x5440)) - mstore(0x5500, mload(0x5460)) - success := and(eq(staticcall(gas(), 0x6, 0x54a0, 0x80, 0x54a0, 0x40), 1), success) - mstore(0x5520, 0x215365efc7b867c1204aab35fb060db538521b93b08872e3a9700c7ee4a285c2) - mstore(0x5540, 0x26da76077e618e9351d4e53058afcb50f9ecb808ef537ffed4c95f1e964a8c58) - mstore(0x5560, mload(0x4ee0)) - success := and(eq(staticcall(gas(), 0x7, 0x5520, 0x60, 0x5520, 0x40), 1), success) - mstore(0x5580, mload(0x54a0)) - mstore(0x55a0, mload(0x54c0)) - mstore(0x55c0, mload(0x5520)) - mstore(0x55e0, mload(0x5540)) - success := and(eq(staticcall(gas(), 0x6, 0x5580, 0x80, 0x5580, 0x40), 1), success) - mstore(0x5600, 0x21c6ea7d6dbcd767ffb9d9beeb4f9c2f8243bc65290f2d75a59aea4f65ba8f3d) - mstore(0x5620, 0x24d0a0acb031c9a5687da08cdaf96650aae5c60435739bda8bbd574eb962622c) - mstore(0x5640, mload(0x4f00)) - success := and(eq(staticcall(gas(), 0x7, 0x5600, 0x60, 0x5600, 0x40), 1), success) - mstore(0x5660, mload(0x5580)) - mstore(0x5680, mload(0x55a0)) - mstore(0x56a0, mload(0x5600)) - mstore(0x56c0, mload(0x5620)) - success := and(eq(staticcall(gas(), 0x6, 0x5660, 0x80, 0x5660, 0x40), 1), success) - mstore(0x56e0, 0x289feda4952fe4464c9716d071e291bbecdcd5432356042dc79b76ed38cbbb0d) - mstore(0x5700, 0x07f3ca14a8801fa413462ad72ea448da5d7cf8c5218534cdc39bb23779b70bb9) - mstore(0x5720, mload(0x4f20)) - success := and(eq(staticcall(gas(), 0x7, 0x56e0, 0x60, 0x56e0, 0x40), 1), success) - mstore(0x5740, mload(0x5660)) - mstore(0x5760, mload(0x5680)) - mstore(0x5780, mload(0x56e0)) - mstore(0x57a0, mload(0x5700)) - success := and(eq(staticcall(gas(), 0x6, 0x5740, 0x80, 0x5740, 0x40), 1), success) - mstore(0x57c0, 0x259670bd2f2f6fce3b18100f92a2e59874da3b66a9ddd61e163eb4b071e24a97) - mstore(0x57e0, 0x097f07272f7ca89070ad9c06d9a3da1bb6e91d0e69bf7872f44cc5d332291eb5) - mstore(0x5800, mload(0x4f40)) - success := and(eq(staticcall(gas(), 0x7, 0x57c0, 0x60, 0x57c0, 0x40), 1), success) - mstore(0x5820, mload(0x5740)) - mstore(0x5840, mload(0x5760)) - mstore(0x5860, mload(0x57c0)) - mstore(0x5880, mload(0x57e0)) - success := and(eq(staticcall(gas(), 0x6, 0x5820, 0x80, 0x5820, 0x40), 1), success) - mstore(0x58a0, 0x1e9efbe537998d8260c28c8e2ca8d83118f378f1e83daed033c2ae772806280a) - mstore(0x58c0, 0x15e04128b5f6b9bb6c758886eda92c27e8414c25809bd547e4987c332c38a430) - mstore(0x58e0, mload(0x4f60)) - success := and(eq(staticcall(gas(), 0x7, 0x58a0, 0x60, 0x58a0, 0x40), 1), success) - mstore(0x5900, mload(0x5820)) - mstore(0x5920, mload(0x5840)) - mstore(0x5940, mload(0x58a0)) - mstore(0x5960, mload(0x58c0)) - success := and(eq(staticcall(gas(), 0x6, 0x5900, 0x80, 0x5900, 0x40), 1), success) - mstore(0x5980, 0x2db56ede49a6f38ee215d1fa9557ac54cb085bbb6170e9a2cda8db3c996c496e) - mstore(0x59a0, 0x017bd7af014917e84cda777f32c3b586cf6de90f0d649cbbce320ee837513cb8) - mstore(0x59c0, mload(0x4f80)) - success := and(eq(staticcall(gas(), 0x7, 0x5980, 0x60, 0x5980, 0x40), 1), success) - mstore(0x59e0, mload(0x5900)) - mstore(0x5a00, mload(0x5920)) - mstore(0x5a20, mload(0x5980)) - mstore(0x5a40, mload(0x59a0)) - success := and(eq(staticcall(gas(), 0x6, 0x59e0, 0x80, 0x59e0, 0x40), 1), success) - mstore(0x5a60, 0x0f76818adad3c635f139fde306f33aba7249952bdbbf72cf477a51f9d84f3ccc) - mstore(0x5a80, 0x23f89f9896b1cc39de92659098ea839186ff2e997ffa3413c1a7af4f31abe4ce) - mstore(0x5aa0, mload(0x4fa0)) - success := and(eq(staticcall(gas(), 0x7, 0x5a60, 0x60, 0x5a60, 0x40), 1), success) - mstore(0x5ac0, mload(0x59e0)) - mstore(0x5ae0, mload(0x5a00)) - mstore(0x5b00, mload(0x5a60)) - mstore(0x5b20, mload(0x5a80)) - success := and(eq(staticcall(gas(), 0x6, 0x5ac0, 0x80, 0x5ac0, 0x40), 1), success) - mstore(0x5b40, mload(0x960)) - mstore(0x5b60, mload(0x980)) - mstore(0x5b80, mload(0x4fc0)) - success := and(eq(staticcall(gas(), 0x7, 0x5b40, 0x60, 0x5b40, 0x40), 1), success) - mstore(0x5ba0, mload(0x5ac0)) - mstore(0x5bc0, mload(0x5ae0)) - mstore(0x5be0, mload(0x5b40)) - mstore(0x5c00, mload(0x5b60)) - success := and(eq(staticcall(gas(), 0x6, 0x5ba0, 0x80, 0x5ba0, 0x40), 1), success) - mstore(0x5c20, mload(0x9a0)) - mstore(0x5c40, mload(0x9c0)) - mstore(0x5c60, mload(0x4fe0)) - success := and(eq(staticcall(gas(), 0x7, 0x5c20, 0x60, 0x5c20, 0x40), 1), success) - mstore(0x5c80, mload(0x5ba0)) - mstore(0x5ca0, mload(0x5bc0)) - mstore(0x5cc0, mload(0x5c20)) - mstore(0x5ce0, mload(0x5c40)) - success := and(eq(staticcall(gas(), 0x6, 0x5c80, 0x80, 0x5c80, 0x40), 1), success) - mstore(0x5d00, mload(0x9e0)) - mstore(0x5d20, mload(0xa00)) - mstore(0x5d40, mload(0x5000)) - success := and(eq(staticcall(gas(), 0x7, 0x5d00, 0x60, 0x5d00, 0x40), 1), success) - mstore(0x5d60, mload(0x5c80)) - mstore(0x5d80, mload(0x5ca0)) - mstore(0x5da0, mload(0x5d00)) - mstore(0x5dc0, mload(0x5d20)) - success := and(eq(staticcall(gas(), 0x6, 0x5d60, 0x80, 0x5d60, 0x40), 1), success) - mstore(0x5de0, mload(0xa20)) - mstore(0x5e00, mload(0xa40)) - mstore(0x5e20, mload(0x5020)) - success := and(eq(staticcall(gas(), 0x7, 0x5de0, 0x60, 0x5de0, 0x40), 1), success) - mstore(0x5e40, mload(0x5d60)) - mstore(0x5e60, mload(0x5d80)) - mstore(0x5e80, mload(0x5de0)) - mstore(0x5ea0, mload(0x5e00)) - success := and(eq(staticcall(gas(), 0x6, 0x5e40, 0x80, 0x5e40, 0x40), 1), success) - mstore(0x5ec0, mload(0x8c0)) - mstore(0x5ee0, mload(0x8e0)) - mstore(0x5f00, mload(0x5040)) - success := and(eq(staticcall(gas(), 0x7, 0x5ec0, 0x60, 0x5ec0, 0x40), 1), success) - mstore(0x5f20, mload(0x5e40)) - mstore(0x5f40, mload(0x5e60)) - mstore(0x5f60, mload(0x5ec0)) - mstore(0x5f80, mload(0x5ee0)) - success := and(eq(staticcall(gas(), 0x6, 0x5f20, 0x80, 0x5f20, 0x40), 1), success) - mstore(0x5fa0, mload(0xde0)) - mstore(0x5fc0, mload(0xe00)) - mstore(0x5fe0, sub(f_q, mload(0x5080))) - success := and(eq(staticcall(gas(), 0x7, 0x5fa0, 0x60, 0x5fa0, 0x40), 1), success) - mstore(0x6000, mload(0x5f20)) - mstore(0x6020, mload(0x5f40)) - mstore(0x6040, mload(0x5fa0)) - mstore(0x6060, mload(0x5fc0)) - success := and(eq(staticcall(gas(), 0x6, 0x6000, 0x80, 0x6000, 0x40), 1), success) - mstore(0x6080, mload(0xe80)) - mstore(0x60a0, mload(0xea0)) - mstore(0x60c0, mload(0x50a0)) - success := and(eq(staticcall(gas(), 0x7, 0x6080, 0x60, 0x6080, 0x40), 1), success) - mstore(0x60e0, mload(0x6000)) - mstore(0x6100, mload(0x6020)) - mstore(0x6120, mload(0x6080)) - mstore(0x6140, mload(0x60a0)) - success := and(eq(staticcall(gas(), 0x6, 0x60e0, 0x80, 0x60e0, 0x40), 1), success) - mstore(0x6160, mload(0x60e0)) - mstore(0x6180, mload(0x6100)) - mstore(0x61a0, mload(0xe80)) - mstore(0x61c0, mload(0xea0)) - mstore(0x61e0, mload(0xec0)) - mstore(0x6200, mload(0xee0)) - mstore(0x6220, mload(0xf00)) - mstore(0x6240, mload(0xf20)) - mstore(0x6260, keccak256(0x6160, 256)) - mstore(25216, mod(mload(25184), f_q)) - mstore(0x62a0, mulmod(mload(0x6280), mload(0x6280), f_q)) - mstore(0x62c0, mulmod(1, mload(0x6280), f_q)) - mstore(0x62e0, mload(0x61e0)) - mstore(0x6300, mload(0x6200)) - mstore(0x6320, mload(0x62c0)) - success := and(eq(staticcall(gas(), 0x7, 0x62e0, 0x60, 0x62e0, 0x40), 1), success) - mstore(0x6340, mload(0x6160)) - mstore(0x6360, mload(0x6180)) - mstore(0x6380, mload(0x62e0)) - mstore(0x63a0, mload(0x6300)) - success := and(eq(staticcall(gas(), 0x6, 0x6340, 0x80, 0x6340, 0x40), 1), success) - mstore(0x63c0, mload(0x6220)) - mstore(0x63e0, mload(0x6240)) - mstore(0x6400, mload(0x62c0)) - success := and(eq(staticcall(gas(), 0x7, 0x63c0, 0x60, 0x63c0, 0x40), 1), success) - mstore(0x6420, mload(0x61a0)) - mstore(0x6440, mload(0x61c0)) - mstore(0x6460, mload(0x63c0)) - mstore(0x6480, mload(0x63e0)) - success := and(eq(staticcall(gas(), 0x6, 0x6420, 0x80, 0x6420, 0x40), 1), success) - mstore(0x64a0, mload(0x6340)) - mstore(0x64c0, mload(0x6360)) - mstore(0x64e0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) + + } +mstore(0x4280, mulmod(mload(0x4080), mload(0x40a0), f_q)) +mstore(0x42a0, mulmod(mload(0x40c0), mload(0x40e0), f_q)) +mstore(0x42c0, mulmod(mload(0x4100), mload(0x4120), f_q)) +mstore(0x42e0, mulmod(mload(0xd40), mload(0xd40), f_q)) +mstore(0x4300, mulmod(mload(0x42e0), 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(0xda0), mload(0xda0), f_q)) +mstore(0x4420, mulmod(mload(0x4400), mload(0xda0), f_q)) +mstore(0x4440, mulmod(mload(0x4420), mload(0xda0), f_q)) +{ + let result := mulmod(mload(0xac0), mload(0x3aa0), f_q) +result := addmod(mulmod(mload(0xae0), mload(0x3b00), f_q), result, f_q) +result := addmod(mulmod(mload(0xb00), mload(0x3b60), f_q), result, f_q) +result := addmod(mulmod(mload(0xb20), mload(0x3bc0), f_q), result, f_q) +mstore(17504, result) + } +mstore(0x4480, mulmod(mload(0x4460), mload(0x4060), f_q)) +mstore(0x44a0, mulmod(sub(f_q, mload(0x4480)), 1, f_q)) +mstore(0x44c0, mulmod(mload(0x44a0), 1, f_q)) +mstore(0x44e0, mulmod(1, mload(0x4080), f_q)) +{ + let result := mulmod(mload(0xc40), mload(0x3ca0), f_q) +result := addmod(mulmod(mload(0xc60), mload(0x3d00), f_q), result, f_q) +mstore(17664, result) + } +mstore(0x4520, mulmod(mload(0x4500), mload(0x4280), f_q)) +mstore(0x4540, mulmod(sub(f_q, mload(0x4520)), 1, f_q)) +mstore(0x4560, mulmod(mload(0x44e0), 1, f_q)) +{ + let result := mulmod(mload(0xc80), mload(0x3ca0), f_q) +result := addmod(mulmod(mload(0xca0), mload(0x3d00), f_q), result, f_q) +mstore(17792, result) + } +mstore(0x45a0, mulmod(mload(0x4580), mload(0x4280), f_q)) +mstore(0x45c0, mulmod(sub(f_q, mload(0x45a0)), mload(0xd40), f_q)) +mstore(0x45e0, mulmod(mload(0x44e0), mload(0xd40), f_q)) +mstore(0x4600, addmod(mload(0x4540), mload(0x45c0), f_q)) +mstore(0x4620, mulmod(mload(0x4600), mload(0xda0), f_q)) +mstore(0x4640, mulmod(mload(0x4560), mload(0xda0), f_q)) +mstore(0x4660, mulmod(mload(0x45e0), mload(0xda0), f_q)) +mstore(0x4680, addmod(mload(0x44c0), mload(0x4620), f_q)) +mstore(0x46a0, mulmod(1, mload(0x40c0), f_q)) +{ + let result := mulmod(mload(0xcc0), mload(0x3d60), f_q) +result := addmod(mulmod(mload(0xce0), mload(0x3dc0), f_q), result, f_q) +mstore(18112, result) + } +mstore(0x46e0, mulmod(mload(0x46c0), mload(0x42a0), f_q)) +mstore(0x4700, mulmod(sub(f_q, mload(0x46e0)), 1, f_q)) +mstore(0x4720, mulmod(mload(0x46a0), 1, f_q)) +mstore(0x4740, mulmod(mload(0x4700), mload(0x4400), f_q)) +mstore(0x4760, mulmod(mload(0x4720), mload(0x4400), f_q)) +mstore(0x4780, addmod(mload(0x4680), mload(0x4740), f_q)) +mstore(0x47a0, mulmod(1, mload(0x4100), f_q)) +{ + let result := mulmod(mload(0xd00), mload(0x3e00), f_q) +mstore(18368, result) + } +mstore(0x47e0, mulmod(mload(0x47c0), mload(0x42c0), f_q)) +mstore(0x4800, mulmod(sub(f_q, mload(0x47e0)), 1, f_q)) +mstore(0x4820, mulmod(mload(0x47a0), 1, f_q)) +{ + let result := mulmod(mload(0xb40), mload(0x3e00), f_q) +mstore(18496, result) + } +mstore(0x4860, mulmod(mload(0x4840), mload(0x42c0), f_q)) +mstore(0x4880, mulmod(sub(f_q, mload(0x4860)), mload(0xd40), f_q)) +mstore(0x48a0, mulmod(mload(0x47a0), mload(0xd40), f_q)) +mstore(0x48c0, addmod(mload(0x4800), mload(0x4880), f_q)) +{ + let result := mulmod(mload(0xb60), mload(0x3e00), f_q) +mstore(18656, result) + } +mstore(0x4900, mulmod(mload(0x48e0), mload(0x42c0), f_q)) +mstore(0x4920, mulmod(sub(f_q, mload(0x4900)), mload(0x42e0), f_q)) +mstore(0x4940, mulmod(mload(0x47a0), mload(0x42e0), f_q)) +mstore(0x4960, addmod(mload(0x48c0), mload(0x4920), f_q)) +{ + let result := mulmod(mload(0xb80), mload(0x3e00), f_q) +mstore(18816, result) + } +mstore(0x49a0, mulmod(mload(0x4980), mload(0x42c0), f_q)) +mstore(0x49c0, mulmod(sub(f_q, mload(0x49a0)), mload(0x4300), f_q)) +mstore(0x49e0, mulmod(mload(0x47a0), mload(0x4300), f_q)) +mstore(0x4a00, addmod(mload(0x4960), mload(0x49c0), f_q)) +{ + let result := mulmod(mload(0xba0), mload(0x3e00), f_q) +mstore(18976, result) + } +mstore(0x4a40, mulmod(mload(0x4a20), mload(0x42c0), f_q)) +mstore(0x4a60, mulmod(sub(f_q, mload(0x4a40)), mload(0x4320), f_q)) +mstore(0x4a80, mulmod(mload(0x47a0), mload(0x4320), f_q)) +mstore(0x4aa0, addmod(mload(0x4a00), mload(0x4a60), f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x3e00), f_q) +mstore(19136, result) + } +mstore(0x4ae0, mulmod(mload(0x4ac0), mload(0x42c0), f_q)) +mstore(0x4b00, mulmod(sub(f_q, mload(0x4ae0)), mload(0x4340), f_q)) +mstore(0x4b20, mulmod(mload(0x47a0), mload(0x4340), f_q)) +mstore(0x4b40, addmod(mload(0x4aa0), mload(0x4b00), f_q)) +{ + let result := mulmod(mload(0xc00), mload(0x3e00), f_q) +mstore(19296, result) + } +mstore(0x4b80, mulmod(mload(0x4b60), mload(0x42c0), f_q)) +mstore(0x4ba0, mulmod(sub(f_q, mload(0x4b80)), mload(0x4360), f_q)) +mstore(0x4bc0, mulmod(mload(0x47a0), mload(0x4360), f_q)) +mstore(0x4be0, addmod(mload(0x4b40), mload(0x4ba0), f_q)) +{ + let result := mulmod(mload(0xc20), mload(0x3e00), f_q) +mstore(19456, result) + } +mstore(0x4c20, mulmod(mload(0x4c00), mload(0x42c0), f_q)) +mstore(0x4c40, mulmod(sub(f_q, mload(0x4c20)), mload(0x4380), f_q)) +mstore(0x4c60, mulmod(mload(0x47a0), mload(0x4380), f_q)) +mstore(0x4c80, addmod(mload(0x4be0), mload(0x4c40), f_q)) +mstore(0x4ca0, mulmod(mload(0x3860), mload(0x4100), f_q)) +mstore(0x4cc0, mulmod(mload(0x3880), mload(0x4100), f_q)) +mstore(0x4ce0, mulmod(mload(0x38a0), mload(0x4100), f_q)) +{ + let result := mulmod(mload(0x38c0), mload(0x3e00), f_q) +mstore(19712, result) + } +mstore(0x4d20, mulmod(mload(0x4d00), mload(0x42c0), f_q)) +mstore(0x4d40, mulmod(sub(f_q, mload(0x4d20)), mload(0x43a0), f_q)) +mstore(0x4d60, mulmod(mload(0x47a0), mload(0x43a0), f_q)) +mstore(0x4d80, mulmod(mload(0x4ca0), mload(0x43a0), f_q)) +mstore(0x4da0, mulmod(mload(0x4cc0), mload(0x43a0), f_q)) +mstore(0x4dc0, mulmod(mload(0x4ce0), mload(0x43a0), f_q)) +mstore(0x4de0, addmod(mload(0x4c80), mload(0x4d40), f_q)) +{ + let result := mulmod(mload(0xbc0), mload(0x3e00), f_q) +mstore(19968, result) + } +mstore(0x4e20, mulmod(mload(0x4e00), mload(0x42c0), f_q)) +mstore(0x4e40, mulmod(sub(f_q, mload(0x4e20)), mload(0x43c0), f_q)) +mstore(0x4e60, mulmod(mload(0x47a0), mload(0x43c0), f_q)) +mstore(0x4e80, addmod(mload(0x4de0), mload(0x4e40), f_q)) +mstore(0x4ea0, mulmod(mload(0x4e80), mload(0x4420), f_q)) +mstore(0x4ec0, mulmod(mload(0x4820), mload(0x4420), f_q)) +mstore(0x4ee0, mulmod(mload(0x48a0), mload(0x4420), f_q)) +mstore(0x4f00, mulmod(mload(0x4940), mload(0x4420), f_q)) +mstore(0x4f20, mulmod(mload(0x49e0), mload(0x4420), f_q)) +mstore(0x4f40, mulmod(mload(0x4a80), mload(0x4420), f_q)) +mstore(0x4f60, mulmod(mload(0x4b20), mload(0x4420), f_q)) +mstore(0x4f80, mulmod(mload(0x4bc0), mload(0x4420), f_q)) +mstore(0x4fa0, mulmod(mload(0x4c60), mload(0x4420), f_q)) +mstore(0x4fc0, mulmod(mload(0x4d60), mload(0x4420), f_q)) +mstore(0x4fe0, mulmod(mload(0x4d80), mload(0x4420), f_q)) +mstore(0x5000, mulmod(mload(0x4da0), mload(0x4420), f_q)) +mstore(0x5020, mulmod(mload(0x4dc0), mload(0x4420), f_q)) +mstore(0x5040, mulmod(mload(0x4e60), mload(0x4420), f_q)) +mstore(0x5060, addmod(mload(0x4780), mload(0x4ea0), f_q)) +mstore(0x5080, mulmod(1, mload(0x3c40), f_q)) +mstore(0x50a0, mulmod(1, mload(0xe40), f_q)) +mstore(0x50c0, 0x0000000000000000000000000000000000000000000000000000000000000001) + mstore(0x50e0, 0x0000000000000000000000000000000000000000000000000000000000000002) +mstore(0x5100, mload(0x5060)) +success := and(eq(staticcall(gas(), 0x7, 0x50c0, 0x60, 0x50c0, 0x40), 1), success) +mstore(0x5120, mload(0x50c0)) + mstore(0x5140, mload(0x50e0)) +mstore(0x5160, mload(0x660)) + mstore(0x5180, mload(0x680)) +success := and(eq(staticcall(gas(), 0x6, 0x5120, 0x80, 0x5120, 0x40), 1), success) +mstore(0x51a0, mload(0x840)) + mstore(0x51c0, mload(0x860)) +mstore(0x51e0, mload(0x4640)) +success := and(eq(staticcall(gas(), 0x7, 0x51a0, 0x60, 0x51a0, 0x40), 1), success) +mstore(0x5200, mload(0x5120)) + mstore(0x5220, mload(0x5140)) +mstore(0x5240, mload(0x51a0)) + mstore(0x5260, mload(0x51c0)) +success := and(eq(staticcall(gas(), 0x6, 0x5200, 0x80, 0x5200, 0x40), 1), success) +mstore(0x5280, mload(0x880)) + mstore(0x52a0, mload(0x8a0)) +mstore(0x52c0, mload(0x4660)) +success := and(eq(staticcall(gas(), 0x7, 0x5280, 0x60, 0x5280, 0x40), 1), success) +mstore(0x52e0, mload(0x5200)) + mstore(0x5300, mload(0x5220)) +mstore(0x5320, mload(0x5280)) + mstore(0x5340, mload(0x52a0)) +success := and(eq(staticcall(gas(), 0x6, 0x52e0, 0x80, 0x52e0, 0x40), 1), success) +mstore(0x5360, mload(0x700)) + mstore(0x5380, mload(0x720)) +mstore(0x53a0, mload(0x4760)) +success := and(eq(staticcall(gas(), 0x7, 0x5360, 0x60, 0x5360, 0x40), 1), success) +mstore(0x53c0, mload(0x52e0)) + mstore(0x53e0, mload(0x5300)) +mstore(0x5400, mload(0x5360)) + mstore(0x5420, mload(0x5380)) +success := and(eq(staticcall(gas(), 0x6, 0x53c0, 0x80, 0x53c0, 0x40), 1), success) +mstore(0x5440, mload(0x740)) + mstore(0x5460, mload(0x760)) +mstore(0x5480, mload(0x4ec0)) +success := and(eq(staticcall(gas(), 0x7, 0x5440, 0x60, 0x5440, 0x40), 1), success) +mstore(0x54a0, mload(0x53c0)) + mstore(0x54c0, mload(0x53e0)) +mstore(0x54e0, mload(0x5440)) + mstore(0x5500, mload(0x5460)) +success := and(eq(staticcall(gas(), 0x6, 0x54a0, 0x80, 0x54a0, 0x40), 1), success) +mstore(0x5520, 0x215365efc7b867c1204aab35fb060db538521b93b08872e3a9700c7ee4a285c2) + mstore(0x5540, 0x26da76077e618e9351d4e53058afcb50f9ecb808ef537ffed4c95f1e964a8c58) +mstore(0x5560, mload(0x4ee0)) +success := and(eq(staticcall(gas(), 0x7, 0x5520, 0x60, 0x5520, 0x40), 1), success) +mstore(0x5580, mload(0x54a0)) + mstore(0x55a0, mload(0x54c0)) +mstore(0x55c0, mload(0x5520)) + mstore(0x55e0, mload(0x5540)) +success := and(eq(staticcall(gas(), 0x6, 0x5580, 0x80, 0x5580, 0x40), 1), success) +mstore(0x5600, 0x21c6ea7d6dbcd767ffb9d9beeb4f9c2f8243bc65290f2d75a59aea4f65ba8f3d) + mstore(0x5620, 0x24d0a0acb031c9a5687da08cdaf96650aae5c60435739bda8bbd574eb962622c) +mstore(0x5640, mload(0x4f00)) +success := and(eq(staticcall(gas(), 0x7, 0x5600, 0x60, 0x5600, 0x40), 1), success) +mstore(0x5660, mload(0x5580)) + mstore(0x5680, mload(0x55a0)) +mstore(0x56a0, mload(0x5600)) + mstore(0x56c0, mload(0x5620)) +success := and(eq(staticcall(gas(), 0x6, 0x5660, 0x80, 0x5660, 0x40), 1), success) +mstore(0x56e0, 0x289feda4952fe4464c9716d071e291bbecdcd5432356042dc79b76ed38cbbb0d) + mstore(0x5700, 0x07f3ca14a8801fa413462ad72ea448da5d7cf8c5218534cdc39bb23779b70bb9) +mstore(0x5720, mload(0x4f20)) +success := and(eq(staticcall(gas(), 0x7, 0x56e0, 0x60, 0x56e0, 0x40), 1), success) +mstore(0x5740, mload(0x5660)) + mstore(0x5760, mload(0x5680)) +mstore(0x5780, mload(0x56e0)) + mstore(0x57a0, mload(0x5700)) +success := and(eq(staticcall(gas(), 0x6, 0x5740, 0x80, 0x5740, 0x40), 1), success) +mstore(0x57c0, 0x259670bd2f2f6fce3b18100f92a2e59874da3b66a9ddd61e163eb4b071e24a97) + mstore(0x57e0, 0x097f07272f7ca89070ad9c06d9a3da1bb6e91d0e69bf7872f44cc5d332291eb5) +mstore(0x5800, mload(0x4f40)) +success := and(eq(staticcall(gas(), 0x7, 0x57c0, 0x60, 0x57c0, 0x40), 1), success) +mstore(0x5820, mload(0x5740)) + mstore(0x5840, mload(0x5760)) +mstore(0x5860, mload(0x57c0)) + mstore(0x5880, mload(0x57e0)) +success := and(eq(staticcall(gas(), 0x6, 0x5820, 0x80, 0x5820, 0x40), 1), success) +mstore(0x58a0, 0x1e9efbe537998d8260c28c8e2ca8d83118f378f1e83daed033c2ae772806280a) + mstore(0x58c0, 0x15e04128b5f6b9bb6c758886eda92c27e8414c25809bd547e4987c332c38a430) +mstore(0x58e0, mload(0x4f60)) +success := and(eq(staticcall(gas(), 0x7, 0x58a0, 0x60, 0x58a0, 0x40), 1), success) +mstore(0x5900, mload(0x5820)) + mstore(0x5920, mload(0x5840)) +mstore(0x5940, mload(0x58a0)) + mstore(0x5960, mload(0x58c0)) +success := and(eq(staticcall(gas(), 0x6, 0x5900, 0x80, 0x5900, 0x40), 1), success) +mstore(0x5980, 0x2db56ede49a6f38ee215d1fa9557ac54cb085bbb6170e9a2cda8db3c996c496e) + mstore(0x59a0, 0x017bd7af014917e84cda777f32c3b586cf6de90f0d649cbbce320ee837513cb8) +mstore(0x59c0, mload(0x4f80)) +success := and(eq(staticcall(gas(), 0x7, 0x5980, 0x60, 0x5980, 0x40), 1), success) +mstore(0x59e0, mload(0x5900)) + mstore(0x5a00, mload(0x5920)) +mstore(0x5a20, mload(0x5980)) + mstore(0x5a40, mload(0x59a0)) +success := and(eq(staticcall(gas(), 0x6, 0x59e0, 0x80, 0x59e0, 0x40), 1), success) +mstore(0x5a60, 0x0f76818adad3c635f139fde306f33aba7249952bdbbf72cf477a51f9d84f3ccc) + mstore(0x5a80, 0x23f89f9896b1cc39de92659098ea839186ff2e997ffa3413c1a7af4f31abe4ce) +mstore(0x5aa0, mload(0x4fa0)) +success := and(eq(staticcall(gas(), 0x7, 0x5a60, 0x60, 0x5a60, 0x40), 1), success) +mstore(0x5ac0, mload(0x59e0)) + mstore(0x5ae0, mload(0x5a00)) +mstore(0x5b00, mload(0x5a60)) + mstore(0x5b20, mload(0x5a80)) +success := and(eq(staticcall(gas(), 0x6, 0x5ac0, 0x80, 0x5ac0, 0x40), 1), success) +mstore(0x5b40, mload(0x960)) + mstore(0x5b60, mload(0x980)) +mstore(0x5b80, mload(0x4fc0)) +success := and(eq(staticcall(gas(), 0x7, 0x5b40, 0x60, 0x5b40, 0x40), 1), success) +mstore(0x5ba0, mload(0x5ac0)) + mstore(0x5bc0, mload(0x5ae0)) +mstore(0x5be0, mload(0x5b40)) + mstore(0x5c00, mload(0x5b60)) +success := and(eq(staticcall(gas(), 0x6, 0x5ba0, 0x80, 0x5ba0, 0x40), 1), success) +mstore(0x5c20, mload(0x9a0)) + mstore(0x5c40, mload(0x9c0)) +mstore(0x5c60, mload(0x4fe0)) +success := and(eq(staticcall(gas(), 0x7, 0x5c20, 0x60, 0x5c20, 0x40), 1), success) +mstore(0x5c80, mload(0x5ba0)) + mstore(0x5ca0, mload(0x5bc0)) +mstore(0x5cc0, mload(0x5c20)) + mstore(0x5ce0, mload(0x5c40)) +success := and(eq(staticcall(gas(), 0x6, 0x5c80, 0x80, 0x5c80, 0x40), 1), success) +mstore(0x5d00, mload(0x9e0)) + mstore(0x5d20, mload(0xa00)) +mstore(0x5d40, mload(0x5000)) +success := and(eq(staticcall(gas(), 0x7, 0x5d00, 0x60, 0x5d00, 0x40), 1), success) +mstore(0x5d60, mload(0x5c80)) + mstore(0x5d80, mload(0x5ca0)) +mstore(0x5da0, mload(0x5d00)) + mstore(0x5dc0, mload(0x5d20)) +success := and(eq(staticcall(gas(), 0x6, 0x5d60, 0x80, 0x5d60, 0x40), 1), success) +mstore(0x5de0, mload(0xa20)) + mstore(0x5e00, mload(0xa40)) +mstore(0x5e20, mload(0x5020)) +success := and(eq(staticcall(gas(), 0x7, 0x5de0, 0x60, 0x5de0, 0x40), 1), success) +mstore(0x5e40, mload(0x5d60)) + mstore(0x5e60, mload(0x5d80)) +mstore(0x5e80, mload(0x5de0)) + mstore(0x5ea0, mload(0x5e00)) +success := and(eq(staticcall(gas(), 0x6, 0x5e40, 0x80, 0x5e40, 0x40), 1), success) +mstore(0x5ec0, mload(0x8c0)) + mstore(0x5ee0, mload(0x8e0)) +mstore(0x5f00, mload(0x5040)) +success := and(eq(staticcall(gas(), 0x7, 0x5ec0, 0x60, 0x5ec0, 0x40), 1), success) +mstore(0x5f20, mload(0x5e40)) + mstore(0x5f40, mload(0x5e60)) +mstore(0x5f60, mload(0x5ec0)) + mstore(0x5f80, mload(0x5ee0)) +success := and(eq(staticcall(gas(), 0x6, 0x5f20, 0x80, 0x5f20, 0x40), 1), success) +mstore(0x5fa0, mload(0xde0)) + mstore(0x5fc0, mload(0xe00)) +mstore(0x5fe0, sub(f_q, mload(0x5080))) +success := and(eq(staticcall(gas(), 0x7, 0x5fa0, 0x60, 0x5fa0, 0x40), 1), success) +mstore(0x6000, mload(0x5f20)) + mstore(0x6020, mload(0x5f40)) +mstore(0x6040, mload(0x5fa0)) + mstore(0x6060, mload(0x5fc0)) +success := and(eq(staticcall(gas(), 0x6, 0x6000, 0x80, 0x6000, 0x40), 1), success) +mstore(0x6080, mload(0xe80)) + mstore(0x60a0, mload(0xea0)) +mstore(0x60c0, mload(0x50a0)) +success := and(eq(staticcall(gas(), 0x7, 0x6080, 0x60, 0x6080, 0x40), 1), success) +mstore(0x60e0, mload(0x6000)) + mstore(0x6100, mload(0x6020)) +mstore(0x6120, mload(0x6080)) + mstore(0x6140, mload(0x60a0)) +success := and(eq(staticcall(gas(), 0x6, 0x60e0, 0x80, 0x60e0, 0x40), 1), success) +mstore(0x6160, mload(0x60e0)) + mstore(0x6180, mload(0x6100)) +mstore(0x61a0, mload(0xe80)) + mstore(0x61c0, mload(0xea0)) +mstore(0x61e0, mload(0xec0)) + mstore(0x6200, mload(0xee0)) +mstore(0x6220, mload(0xf00)) + mstore(0x6240, mload(0xf20)) +mstore(0x6260, keccak256(0x6160, 256)) +mstore(25216, mod(mload(25184), f_q)) +mstore(0x62a0, mulmod(mload(0x6280), mload(0x6280), f_q)) +mstore(0x62c0, mulmod(1, mload(0x6280), f_q)) +mstore(0x62e0, mload(0x61e0)) + mstore(0x6300, mload(0x6200)) +mstore(0x6320, mload(0x62c0)) +success := and(eq(staticcall(gas(), 0x7, 0x62e0, 0x60, 0x62e0, 0x40), 1), success) +mstore(0x6340, mload(0x6160)) + mstore(0x6360, mload(0x6180)) +mstore(0x6380, mload(0x62e0)) + mstore(0x63a0, mload(0x6300)) +success := and(eq(staticcall(gas(), 0x6, 0x6340, 0x80, 0x6340, 0x40), 1), success) +mstore(0x63c0, mload(0x6220)) + mstore(0x63e0, mload(0x6240)) +mstore(0x6400, mload(0x62c0)) +success := and(eq(staticcall(gas(), 0x7, 0x63c0, 0x60, 0x63c0, 0x40), 1), success) +mstore(0x6420, mload(0x61a0)) + mstore(0x6440, mload(0x61c0)) +mstore(0x6460, mload(0x63c0)) + mstore(0x6480, mload(0x63e0)) +success := and(eq(staticcall(gas(), 0x6, 0x6420, 0x80, 0x6420, 0x40), 1), success) +mstore(0x64a0, mload(0x6340)) + mstore(0x64c0, mload(0x6360)) +mstore(0x64e0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) mstore(0x6500, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) mstore(0x6520, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) mstore(0x6540, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - mstore(0x6560, mload(0x6420)) - mstore(0x6580, mload(0x6440)) - mstore(0x65a0, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) +mstore(0x6560, mload(0x6420)) + mstore(0x6580, mload(0x6440)) +mstore(0x65a0, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) mstore(0x65c0, 0x2ae0c8c3a090f7200ff398ee9845bbae8f8c1445ae7b632212775f60a0e21600) mstore(0x65e0, 0x190fa476a5b352809ed41d7a0d7fe12b8f685e3c12a6d83855dba27aaf469643) mstore(0x6600, 0x1c0a500618907df9e4273d5181e31088deb1f05132de037cbfe73888f97f77c9) - success := and(eq(staticcall(gas(), 0x8, 0x64a0, 0x180, 0x64a0, 0x20), 1), success) - success := and(eq(mload(0x64a0), 1), success) +success := and(eq(staticcall(gas(), 0x8, 0x64a0, 0x180, 0x64a0, 0x20), 1), success) +success := and(eq(mload(0x64a0), 1), success) // Revert if anything fails if iszero(success) { revert(0, 0) } // Return empty bytes on success return(0, 0) + } } } + \ No newline at end of file