diff --git a/Cargo.lock b/Cargo.lock index 4606d00..bf573cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,9 +24,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aes" @@ -117,7 +117,7 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -128,7 +128,7 @@ checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -215,7 +215,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -241,7 +241,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -291,7 +291,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -328,9 +328,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" @@ -345,7 +345,7 @@ dependencies = [ "object", "rustc-demangle", "serde", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -390,7 +390,7 @@ checksum = "42b6b4cb608b8282dc3b53d0f4c9ab404655d562674c682db7e6c0458cc83c23" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -484,9 +484,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytecheck" @@ -508,14 +508,14 @@ checksum = "efb7846e0cb180355c2dec69e721edafa36919850f1a9f52ffba4ebc0393cb71" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] name = "bytemuck" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" [[package]] name = "byteorder" @@ -537,9 +537,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.26" +version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ "shlex", ] @@ -547,7 +547,7 @@ dependencies = [ [[package]] name = "ceno-examples" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "glob", ] @@ -580,6 +580,7 @@ dependencies = [ "p3-challenger", "p3-commit", "p3-field", + "p3-fri", "p3-goldilocks", "p3-matrix", "p3-monty-31", @@ -596,7 +597,7 @@ dependencies = [ [[package]] name = "ceno_emul" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "anyhow", "ceno_rt", @@ -617,7 +618,7 @@ dependencies = [ [[package]] name = "ceno_host" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "anyhow", "ceno_emul", @@ -630,7 +631,7 @@ dependencies = [ [[package]] name = "ceno_rt" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "getrandom 0.2.16", "rkyv", @@ -639,7 +640,7 @@ dependencies = [ [[package]] name = "ceno_zkvm" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "base64", "bincode", @@ -680,9 +681,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "ciborium" @@ -723,9 +724,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.39" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", "clap_derive", @@ -733,9 +734,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.39" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstream", "anstyle", @@ -745,21 +746,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "colorchoice" @@ -860,9 +861,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" @@ -923,7 +924,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -934,7 +935,7 @@ checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -947,7 +948,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -967,7 +968,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", "unicode-xid", ] @@ -1018,7 +1019,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -1062,7 +1063,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -1074,7 +1075,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -1085,12 +1086,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.60.2", ] [[package]] @@ -1151,7 +1152,7 @@ dependencies = [ [[package]] name = "ff_ext" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "p3", "rand_core", @@ -1204,7 +1205,7 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] @@ -1221,14 +1222,14 @@ dependencies = [ [[package]] name = "getset" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3586f256131df87204eb733da72e3d3eb4f343c639f4b7be279ac7c48baeafe" +checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -1239,9 +1240,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glam" -version = "0.30.3" +version = "0.30.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b46b9ca4690308844c644e7c634d68792467260e051c8543e0c7871662b3ba7" +checksum = "50a99dbe56b72736564cfa4b85bf9a33079f16ae8b74983ab06af3b1a3696b11" [[package]] name = "glob" @@ -1407,9 +1408,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -1462,7 +1463,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", "libc", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1557,9 +1558,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.172" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libm" @@ -1569,9 +1570,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" dependencies = [ "bitflags", "libc", @@ -1606,9 +1607,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memuse" @@ -1664,9 +1665,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] @@ -1674,7 +1675,7 @@ dependencies = [ [[package]] name = "mpcs" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "aes", "bincode", @@ -1704,7 +1705,7 @@ dependencies = [ [[package]] name = "multilinear_extensions" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "ff_ext", "itertools 0.13.0", @@ -1717,22 +1718,22 @@ dependencies = [ [[package]] name = "munge" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e22e7961c873e8b305b176d2a4e1d41ce7ba31bc1c52d2a107a89568ec74c55" +checksum = "9cce144fab80fbb74ec5b89d1ca9d41ddf6b644ab7e986f7d3ed0aab31625cb1" dependencies = [ "munge_macro", ] [[package]] name = "munge_macro" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ac7d860b767c6398e88fe93db73ce53eb496057aa6895ffa4d60cb02e1d1c6b" +checksum = "574af9cd5b9971cbfdf535d6a8d533778481b241c447826d976101e0149392a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -1813,7 +1814,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -1955,7 +1956,7 @@ source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_mul dependencies = [ "itertools 0.14.0", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -1980,7 +1981,7 @@ source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_mul dependencies = [ "itertools 0.14.0", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -1990,7 +1991,7 @@ source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_mul dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -2016,7 +2017,7 @@ version = "1.1.0" source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#0a8b3571c5e123ba47c224afc02df08afc79784a" dependencies = [ "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -2074,7 +2075,7 @@ version = "1.1.0" source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#0a8b3571c5e123ba47c224afc02df08afc79784a" dependencies = [ "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -2269,7 +2270,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p3" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "p3-baby-bear", "p3-challenger", @@ -2704,7 +2705,7 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "poseidon" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "criterion", "ff_ext", @@ -2765,7 +2766,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -2794,20 +2795,20 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] name = "quanta" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bd1fe6824cea6538803de3ff1bc0cf3949024db3d43c9643024bfb33a807c0e" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" dependencies = [ "crossbeam-utils", "libc", "once_cell", "raw-cpuid", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "web-sys", "winapi", ] @@ -2823,9 +2824,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "radium" @@ -3003,7 +3004,7 @@ checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -3029,9 +3030,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc-hash" @@ -3064,7 +3065,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -3161,7 +3162,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -3282,7 +3283,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -3307,7 +3308,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "sumcheck" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "crossbeam-channel", "ff_ext", @@ -3324,14 +3325,14 @@ dependencies = [ [[package]] name = "sumcheck_macro" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "itertools 0.13.0", "p3", "proc-macro2", "quote", "rand", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -3347,9 +3348,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.101" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -3372,7 +3373,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -3403,17 +3404,16 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -3513,7 +3513,7 @@ dependencies = [ "serde_spanned", "toml_datetime", "toml_write", - "winnow 0.7.10", + "winnow 0.7.11", ] [[package]] @@ -3535,13 +3535,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -3599,7 +3599,7 @@ dependencies = [ [[package]] name = "transcript" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "crossbeam-channel", "ff_ext", @@ -3693,9 +3693,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" @@ -3728,7 +3728,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", "wasm-bindgen-shared", ] @@ -3750,7 +3750,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3777,7 +3777,7 @@ dependencies = [ [[package]] name = "whir" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "bincode", "blake2", @@ -3830,7 +3830,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -3845,7 +3845,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", ] [[package]] @@ -3854,14 +3863,30 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -3870,48 +3895,96 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.5.40" @@ -3923,9 +3996,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] @@ -3942,7 +4015,7 @@ dependencies = [ [[package]] name = "witness" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#f2346a942b630d9af4cc4f88e875fefaf5e9f6d0" +source = "git+https://github.com/scroll-tech/ceno.git?branch=cyte%2Fgenerate-basefold-verifier-query-phase-test-data#e9d59e268818cd2d26668a2fac014fde25cb07dd" dependencies = [ "ff_ext", "multilinear_extensions", @@ -3963,22 +4036,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] @@ -3998,7 +4071,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.104", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1ed81e5..42e186d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ bincode = "1" tracing = "0.1.40" # Plonky3 +p3-fri = { git = "https://github.com/Plonky3/Plonky3.git", rev = "1ba4e5c" } p3-air = { git = "https://github.com/Plonky3/Plonky3.git", rev = "1ba4e5c" } p3-baby-bear = { git = "https://github.com/Plonky3/Plonky3.git", rev = "1ba4e5c" } p3-field = { git = "https://github.com/Plonky3/Plonky3.git", rev = "1ba4e5c" } @@ -38,13 +39,13 @@ ark-poly = "0.5" ark-serialize = "0.5" # Ceno -ceno_mle = { git = "https://github.com/scroll-tech/ceno.git", branch = "feat/export_ff_ext", package = "multilinear_extensions" } -ceno_sumcheck = { git = "https://github.com/scroll-tech/ceno.git", branch = "feat/export_ff_ext", package = "sumcheck" } -ceno_transcript = { git = "https://github.com/scroll-tech/ceno.git", branch = "feat/export_ff_ext", package = "transcript" } -ceno_zkvm = { git = "https://github.com/scroll-tech/ceno.git", branch = "feat/export_ff_ext" } -ceno_emul = { git = "https://github.com/scroll-tech/ceno.git", branch = "feat/export_ff_ext" } -mpcs = { git = "https://github.com/scroll-tech/ceno.git", branch = "feat/export_ff_ext" } -ff_ext = { git = "https://github.com/scroll-tech/ceno.git", branch = "feat/export_ff_ext" } +ceno_mle = { git = "https://github.com/scroll-tech/ceno.git", branch = "cyte/generate-basefold-verifier-query-phase-test-data", package = "multilinear_extensions" } +ceno_sumcheck = { git = "https://github.com/scroll-tech/ceno.git", branch = "cyte/generate-basefold-verifier-query-phase-test-data", package = "sumcheck" } +ceno_transcript = { git = "https://github.com/scroll-tech/ceno.git", branch = "cyte/generate-basefold-verifier-query-phase-test-data", package = "transcript" } +ceno_zkvm = { git = "https://github.com/scroll-tech/ceno.git", branch = "cyte/generate-basefold-verifier-query-phase-test-data" } +ceno_emul = { git = "https://github.com/scroll-tech/ceno.git", branch = "cyte/generate-basefold-verifier-query-phase-test-data" } +mpcs = { git = "https://github.com/scroll-tech/ceno.git", branch = "cyte/generate-basefold-verifier-query-phase-test-data" } +ff_ext = { git = "https://github.com/scroll-tech/ceno.git", branch = "cyte/generate-basefold-verifier-query-phase-test-data" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/src/arithmetics/mod.rs b/src/arithmetics/mod.rs index 776aeb0..0d63942 100644 --- a/src/arithmetics/mod.rs +++ b/src/arithmetics/mod.rs @@ -39,10 +39,6 @@ pub unsafe fn exts_to_felts( builder: &mut Builder, exts: &Array>, ) -> Array> { - assert!( - matches!(exts, Array::Dyn(_, _)), - "Expected dynamic array of Exts" - ); let f_len: Usize = builder.eval(exts.len() * Usize::from(C::EF::D)); let f_arr: Array> = Array::Dyn(exts.ptr(), f_len); f_arr @@ -101,6 +97,23 @@ pub fn evaluate_at_point( builder.eval(r * (right - left) + left) } +pub fn fixed_dot_product( + builder: &mut Builder, + a: &[Ext], + b: &Array>, + zero: Ext, +) -> Ext<::F, ::EF> { + // simple trick to prefer AddE(1 cycle) than AddEI(4 cycles) + let acc: Ext = builder.eval(zero + zero); + + for (i, va) in a.iter().enumerate() { + let vb = builder.get(b, i); + builder.assign(&acc, acc + *va * vb); + } + + acc +} + pub fn dot_product( builder: &mut Builder, a: &Array>, @@ -117,19 +130,20 @@ pub fn dot_product( acc } -pub fn fixed_dot_product( +pub fn dot_product_pt_n_eval( builder: &mut Builder, - a: &[Ext], + pt_and_eval: &Array>, b: &Array>, - zero: Ext, ) -> Ext<::F, ::EF> { - // simple trick to prefer AddE(1 cycle) than AddEI(4 cycles) - let acc: Ext = builder.eval(zero + zero); - - for (i, va) in a.iter().enumerate() { - let vb = builder.get(b, i); - builder.assign(&acc, acc + *va * vb); - } + let acc: Ext = builder.eval(C::F::ZERO); + + iter_zip!(builder, pt_and_eval, b).for_each(|idx_vec, builder| { + let ptr_a = idx_vec[0]; + let ptr_b = idx_vec[1]; + let v_a = builder.iter_ptr_get(&pt_and_eval, ptr_a); + let v_b = builder.iter_ptr_get(&b, ptr_b); + builder.assign(&acc, acc + v_a.eval * v_b); + }); acc } @@ -207,6 +221,32 @@ pub fn eq_eval( acc } +// Evaluate eq polynomial. +pub fn eq_eval_with_index( + builder: &mut Builder, + x: &Array>, + y: &Array>, + xlo: Usize, + ylo: Usize, + len: Usize, +) -> Ext { + let acc: Ext = builder.constant(C::EF::ONE); + + builder.range(0, len).for_each(|i_vec, builder| { + let i = i_vec[0]; + let ptr_x: Var = builder.eval(xlo.clone() + i); + let ptr_y: Var = builder.eval(ylo.clone() + i); + let v_x = builder.get(&x, ptr_x); + let v_y = builder.get(&y, ptr_y); + let xi_yi: Ext = builder.eval(v_x * v_y); + let one: Ext = builder.constant(C::EF::ONE); + let new_acc: Ext = builder.eval(acc * (xi_yi + xi_yi - v_x - v_y + one)); + builder.assign(&acc, new_acc); + }); + + acc +} + // Multiply all elements in the Array pub fn product( builder: &mut Builder, @@ -235,21 +275,29 @@ pub fn sum( acc } -// Extend an array by one element -pub fn extend( +// Join two arrays +pub fn join( builder: &mut Builder, - arr: &Array>, - elem: &Ext, + a: &Array>, + b: &Array>, ) -> Array> { - let new_len: Var = builder.eval(arr.len() + C::N::ONE); - let out = builder.dyn_array(new_len); + let a_len = a.len(); + let b_len = b.len(); + let out_len = builder.eval_expr(a_len.clone() + b_len.clone()); + let out = builder.dyn_array(out_len); - builder.range(0, arr.len()).for_each(|i_vec, builder| { + builder.range(0, a_len.clone()).for_each(|i_vec, builder| { let i = i_vec[0]; - let val = builder.get(arr, i); - builder.set_value(&out, i, val); + let a_val = builder.get(a, i); + builder.set(&out, i, a_val); + }); + + builder.range(0, b_len).for_each(|i_vec, builder| { + let b_i = i_vec[0]; + let i = builder.eval_expr(b_i + a_len.clone()); + let b_val = builder.get(b, b_i); + builder.set(&out, i, b_val); }); - builder.set_value(&out, arr.len(), elem.clone()); out } @@ -392,6 +440,34 @@ pub fn build_eq_x_r_vec_sequential( evals } +pub fn build_eq_x_r_vec_sequential_with_offset( + builder: &mut Builder, + r: &Array>, + offset: Usize, +) -> Array> { + // we build eq(x,r) from its evaluations + // we want to evaluate eq(x,r) over x \in {0, 1}^num_vars + // for example, with num_vars = 4, x is a binary vector of 4, then + // 0 0 0 0 -> (1-r0) * (1-r1) * (1-r2) * (1-r3) + // 1 0 0 0 -> r0 * (1-r1) * (1-r2) * (1-r3) + // 0 1 0 0 -> (1-r0) * r1 * (1-r2) * (1-r3) + // 1 1 0 0 -> r0 * r1 * (1-r2) * (1-r3) + // .... + // 1 1 1 1 -> r0 * r1 * r2 * r3 + // we will need 2^num_var evaluations + + let r_len: Var = builder.eval(r.len() - offset); + let evals_len: Felt = builder.constant(C::F::ONE); + let evals_len = builder.exp_power_of_2_v::>(evals_len, r_len); + let evals_len = builder.cast_felt_to_var(evals_len); + + let evals: Array> = builder.dyn_array(evals_len); + // _debug + // build_eq_x_r_helper_sequential_offset(r, &mut evals, E::ONE); + // unsafe { std::mem::transmute(evals) } + evals +} + pub fn ceil_log2(x: usize) -> usize { assert!(x > 0, "ceil_log2: x must be positive"); // Calculate the number of bits in usize @@ -742,7 +818,7 @@ impl UniPolyExtrapolator { p_i: &Array>, eval_at: Ext, ) -> Ext { - let res: Ext = builder.eval(self.constants[0] + self.constants[0]); + let res: Ext = builder.constant(C::EF::ZERO); builder.if_eq(p_i.len(), Usize::from(4)).then_or_else( |builder| { @@ -797,8 +873,8 @@ impl UniPolyExtrapolator { let p_i_0 = builder.get(p_i, 0); let p_i_1 = builder.get(p_i, 1); - let t0: Ext = builder.eval(self.constants[5] * p_i_0 / d0); - let t1: Ext = builder.eval(self.constants[1] * p_i_1 / d1); + let t0: Ext = builder.eval(self.constants[5] * p_i_0 * d0.inverse()); + let t1: Ext = builder.eval(self.constants[1] * p_i_1 * d1.inverse()); builder.eval(l * (t0 + t1)) } @@ -822,9 +898,9 @@ impl UniPolyExtrapolator { let p_i_1: Ext = builder.get(p_i, 1); let p_i_2: Ext = builder.get(p_i, 2); - let t0: Ext = builder.eval(self.constants[6] * p_i_0 / d0); - let t1: Ext = builder.eval(self.constants[5] * p_i_1 / d1); - let t2: Ext = builder.eval(self.constants[6] * p_i_2 / d2); + let t0: Ext = builder.eval(self.constants[6] * p_i_0 * d0.inverse()); + let t1: Ext = builder.eval(self.constants[5] * p_i_1 * d1.inverse()); + let t2: Ext = builder.eval(self.constants[6] * p_i_2 * d2.inverse()); builder.eval(l * (t0 + t1 + t2)) } @@ -851,10 +927,10 @@ impl UniPolyExtrapolator { let p_i_2: Ext = builder.get(p_i, 2); let p_i_3: Ext = builder.get(p_i, 3); - let t0: Ext = builder.eval(self.constants[9] * p_i_0 / d0); - let t1: Ext = builder.eval(self.constants[6] * p_i_1 / d1); - let t2: Ext = builder.eval(self.constants[7] * p_i_2 / d2); - let t3: Ext = builder.eval(self.constants[8] * p_i_3 / d3); + let t0: Ext = builder.eval(self.constants[9] * p_i_0 * d0.inverse()); + let t1: Ext = builder.eval(self.constants[6] * p_i_1 * d1.inverse()); + let t2: Ext = builder.eval(self.constants[7] * p_i_2 * d2.inverse()); + let t3: Ext = builder.eval(self.constants[8] * p_i_3 * d3.inverse()); builder.eval(l * (t0 + t1 + t2 + t3)) } @@ -884,12 +960,30 @@ impl UniPolyExtrapolator { let p_i_3: Ext = builder.get(p_i, 3); let p_i_4: Ext = builder.get(p_i, 4); - let t0: Ext = builder.eval(self.constants[11] * p_i_0 / d0); - let t1: Ext = builder.eval(self.constants[9] * p_i_1 / d1); - let t2: Ext = builder.eval(self.constants[10] * p_i_2 / d2); - let t3: Ext = builder.eval(self.constants[9] * p_i_3 / d3); - let t4: Ext = builder.eval(self.constants[11] * p_i_4 / d4); + let t0: Ext = builder.eval(self.constants[11] * p_i_0 * d0.inverse()); + let t1: Ext = builder.eval(self.constants[9] * p_i_1 * d1.inverse()); + let t2: Ext = builder.eval(self.constants[10] * p_i_2 * d2.inverse()); + let t3: Ext = builder.eval(self.constants[9] * p_i_3 * d3.inverse()); + let t4: Ext = builder.eval(self.constants[11] * p_i_4 * d4.inverse()); builder.eval(l * (t0 + t1 + t2 + t3 + t4)) } } + +pub fn extend( + builder: &mut Builder, + arr: &Array>, + elem: &Ext, +) -> Array> { + let new_len: Var = builder.eval(arr.len() + C::N::ONE); + let out = builder.dyn_array(new_len); + + builder.range(0, arr.len()).for_each(|i_vec, builder| { + let i = i_vec[0]; + let val = builder.get(arr, i); + builder.set_value(&out, i, val); + }); + builder.set_value(&out, arr.len(), elem.clone()); + + out +} diff --git a/src/basefold_verifier/basefold.rs b/src/basefold_verifier/basefold.rs new file mode 100644 index 0000000..4bb8d77 --- /dev/null +++ b/src/basefold_verifier/basefold.rs @@ -0,0 +1,68 @@ +use openvm_native_compiler::{asm::AsmConfig, prelude::*}; +use openvm_native_recursion::hints::Hintable; +use openvm_stark_sdk::p3_baby_bear::BabyBear; +use p3_field::extension::BinomialExtensionField; +use serde::Deserialize; + +use crate::basefold_verifier::hash::Hash; + +use super::{mmcs::*, structs::DIMENSIONS}; + +pub type F = BabyBear; +pub type E = BinomialExtensionField; +pub type InnerConfig = AsmConfig; + +pub type HashDigest = MmcsCommitment; +#[derive(Deserialize)] +pub struct BasefoldCommitment { + pub commit: HashDigest, + pub log2_max_codeword_size: usize, + // pub trivial_commits: Vec, +} + +use mpcs::BasefoldCommitment as InnerBasefoldCommitment; + +impl From> for BasefoldCommitment { + fn from(value: InnerBasefoldCommitment) -> Self { + Self { + commit: Hash { + value: value.commit().into(), + }, + log2_max_codeword_size: value.log2_max_codeword_size, + } + } +} + +impl Hintable for BasefoldCommitment { + type HintVariable = BasefoldCommitmentVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let commit = HashDigest::read(builder); + let log2_max_codeword_size = Usize::Var(usize::read(builder)); + // let trivial_commits = Vec::::read(builder); + + BasefoldCommitmentVariable { + commit, + log2_max_codeword_size, + // trivial_commits, + } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(self.commit.write()); + stream.extend(>::write( + &self.log2_max_codeword_size, + )); + // stream.extend(self.trivial_commits.write()); + stream + } +} + +pub type HashDigestVariable = MmcsCommitmentVariable; +#[derive(DslVariable, Clone)] +pub struct BasefoldCommitmentVariable { + pub commit: HashDigestVariable, + pub log2_max_codeword_size: Usize, + // pub trivial_commits: Array>, +} diff --git a/src/basefold_verifier/extension_mmcs.rs b/src/basefold_verifier/extension_mmcs.rs new file mode 100644 index 0000000..cf4f7e0 --- /dev/null +++ b/src/basefold_verifier/extension_mmcs.rs @@ -0,0 +1,89 @@ +use openvm_native_compiler::{asm::AsmConfig, prelude::*}; +use openvm_native_recursion::{hints::Hintable, vars::HintSlice}; +use openvm_stark_sdk::p3_baby_bear::BabyBear; +use p3_field::extension::BinomialExtensionField; + +use super::{mmcs::*, structs::*}; + +pub type F = BabyBear; +pub type E = BinomialExtensionField; +pub type InnerConfig = AsmConfig; + +pub struct ExtMmcsVerifierInput { + pub commit: MmcsCommitment, + pub dimensions: Vec, + pub index: usize, + pub opened_values: Vec>, + pub proof: MmcsProof, +} + +impl Hintable for ExtMmcsVerifierInput { + type HintVariable = ExtMmcsVerifierInputVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let commit = MmcsCommitment::read(builder); + let dimensions = Vec::::read(builder); + let index_bits = Vec::::read(builder); + let opened_values = Vec::>::read(builder); + let length = Usize::from(builder.hint_var()); + let id = Usize::from(builder.hint_load()); + let proof = HintSlice { length, id }; + + ExtMmcsVerifierInputVariable { + commit, + dimensions, + index_bits, + opened_values, + proof, + } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(self.commit.write()); + stream.extend(self.dimensions.write()); + let mut index_bits = Vec::new(); + let mut index = self.index; + while index > 0 { + index_bits.push(index % 2); + index /= 2; + } + stream.extend( as Hintable>::write(&index_bits)); + stream.extend(self.opened_values.write()); + stream.extend( + self.proof + .iter() + .map(|p| p.to_vec()) + .collect::>() + .write(), + ); + stream + } +} + +#[derive(DslVariable, Clone)] +pub struct ExtMmcsVerifierInputVariable { + pub commit: MmcsCommitmentVariable, + pub dimensions: Array>, + pub index_bits: Array>, + pub opened_values: Array>>, + pub proof: HintSlice, +} + +pub(crate) fn ext_mmcs_verify_batch( + builder: &mut Builder, + input: ExtMmcsVerifierInputVariable, +) { + let dimensions = match input.dimensions { + Array::Dyn(ptr, len) => Array::Dyn(ptr, len.clone()), + _ => panic!("Expected a dynamic array of felts"), + }; + + builder.verify_batch_ext( + &dimensions, + &input.opened_values, + input.proof.id.get_var(), + &input.index_bits, + &input.commit.value, + ); +} diff --git a/src/basefold_verifier/field.rs b/src/basefold_verifier/field.rs new file mode 100644 index 0000000..64eea03 --- /dev/null +++ b/src/basefold_verifier/field.rs @@ -0,0 +1,54 @@ +const TWO_ADICITY: usize = 32; +const TWO_ADIC_GENERATORS: [usize; 33] = [ + 0x0000000000000001, + 0xffffffff00000000, + 0x0001000000000000, + 0xfffffffeff000001, + 0xefffffff00000001, + 0x00003fffffffc000, + 0x0000008000000000, + 0xf80007ff08000001, + 0xbf79143ce60ca966, + 0x1905d02a5c411f4e, + 0x9d8f2ad78bfed972, + 0x0653b4801da1c8cf, + 0xf2c35199959dfcb6, + 0x1544ef2335d17997, + 0xe0ee099310bba1e2, + 0xf6b2cffe2306baac, + 0x54df9630bf79450e, + 0xabd0a6e8aa3d8a0e, + 0x81281a7b05f9beac, + 0xfbd41c6b8caa3302, + 0x30ba2ecd5e93e76d, + 0xf502aef532322654, + 0x4b2a18ade67246b5, + 0xea9d5a1336fbc98b, + 0x86cdcc31c307e171, + 0x4bbaf5976ecfefd8, + 0xed41d05b78d6e286, + 0x10d78dd8915a171d, + 0x59049500004a4485, + 0xdfa8c93ba46d2666, + 0x7e9bd009b86a0845, + 0x400a7f755588e659, + 0x185629dcda58878c, +]; + +use openvm_native_compiler::prelude::*; +use p3_field::FieldAlgebra; + +fn two_adic_generator( + builder: &mut Builder, + bits: Var, +) -> Var { + let bits_limit = builder.eval(Usize::from(TWO_ADICITY) + Usize::from(1)); + builder.assert_less_than_slow_small_rhs(bits, bits_limit); + + let two_adic_generator: Array::F>> = builder.dyn_array(TWO_ADICITY + 1); + builder.range(0, TWO_ADICITY + 1).for_each(|i_vec, builder| { + let i = i_vec[0]; + builder.set_value(&two_adic_generator, i, C::F::from_canonical_usize(TWO_ADIC_GENERATORS[i.value()])); + }); + builder.get(&two_adic_generator, bits) +} \ No newline at end of file diff --git a/src/basefold_verifier/hash.rs b/src/basefold_verifier/hash.rs new file mode 100644 index 0000000..d7b7813 --- /dev/null +++ b/src/basefold_verifier/hash.rs @@ -0,0 +1,98 @@ +use openvm_native_compiler::{asm::AsmConfig, prelude::*}; +use openvm_native_recursion::hints::{Hintable, VecAutoHintable}; +use openvm_stark_sdk::p3_baby_bear::BabyBear; +use p3_field::extension::BinomialExtensionField; +use p3_field::FieldAlgebra; +use serde::Deserialize; + +use super::structs::DIMENSIONS; + +pub const DIGEST_ELEMS: usize = 8; + +pub type F = BabyBear; +pub type E = BinomialExtensionField; +pub type InnerConfig = AsmConfig; + +#[derive(Deserialize)] +pub struct Hash { + pub value: [F; DIGEST_ELEMS], +} + +impl Default for Hash { + fn default() -> Self { + Hash { + value: [F::ZERO; DIGEST_ELEMS], + } + } +} + +impl Hintable for Hash { + type HintVariable = HashVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let value = builder.dyn_array(DIGEST_ELEMS); + for i in 0..DIGEST_ELEMS { + let tmp = F::read(builder); + builder.set(&value, i, tmp); + } + + HashVariable { value } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + // Write out each entries + for i in 0..DIGEST_ELEMS { + stream.extend(self.value[i].write()); + } + stream + } +} +impl VecAutoHintable for Hash {} + +#[derive(DslVariable, Clone)] +pub struct HashVariable { + pub value: Array>, +} + +pub fn hash_iter_slices( + builder: &mut Builder, + // _hash: HashVariable, + _values: Array>>, +) -> Array> { + // XXX: verify hash + builder.hint_felts_fixed(DIGEST_ELEMS) +} + +pub fn compress( + builder: &mut Builder, + // _hash: HashVariable, + _values: Array>>, +) -> Array> { + // XXX: verify hash + builder.hint_felts_fixed(DIGEST_ELEMS) +} + +#[cfg(test)] +mod tests { + use openvm_native_compiler::asm::AsmBuilder; + use openvm_native_compiler_derive::iter_zip; + use openvm_stark_backend::config::StarkGenericConfig; + use openvm_stark_sdk::config::baby_bear_poseidon2::BabyBearPoseidon2Config; + type SC = BabyBearPoseidon2Config; + type F = BabyBear; + type E = BinomialExtensionField; + type EF = ::Challenge; + + use crate::basefold_verifier::basefold::HashDigest; + + use super::*; + #[test] + fn test_read_to_hash_variable() { + let mut builder = AsmBuilder::::default(); + + let hint = HashDigest::read(&mut builder); + let dst: HashVariable<_> = builder.uninit(); + builder.assign(&dst, hint); + } +} diff --git a/src/basefold_verifier/mmcs.rs b/src/basefold_verifier/mmcs.rs new file mode 100644 index 0000000..d419e46 --- /dev/null +++ b/src/basefold_verifier/mmcs.rs @@ -0,0 +1,291 @@ +// Note: check all XXX comments! + +use std::marker::PhantomData; + +use openvm_native_compiler::{asm::AsmConfig, prelude::*}; +use openvm_native_recursion::{hints::Hintable, vars::HintSlice}; +use openvm_stark_sdk::p3_baby_bear::BabyBear; +use p3_field::extension::BinomialExtensionField; + +use super::{hash::*, structs::*}; + +pub type F = BabyBear; +pub type E = BinomialExtensionField; +pub type InnerConfig = AsmConfig; + +pub type MmcsCommitment = Hash; +pub type MmcsProof = Vec<[F; DIGEST_ELEMS]>; +pub struct MmcsVerifierInput { + pub commit: MmcsCommitment, + pub dimensions: Vec, + pub index: usize, + pub opened_values: Vec>, + pub proof: MmcsProof, +} + +impl Hintable for MmcsVerifierInput { + type HintVariable = MmcsVerifierInputVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let commit = MmcsCommitment::read(builder); + let dimensions = Vec::::read(builder); + let index_bits = Vec::::read(builder); + let opened_values = Vec::>::read(builder); + let length = Usize::from(builder.hint_var()); + let id = Usize::from(builder.hint_load()); + let proof = HintSlice { length, id }; + + MmcsVerifierInputVariable { + commit, + dimensions, + index_bits, + opened_values, + proof, + } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + // Split index into bits + stream.extend(self.commit.write()); + stream.extend(self.dimensions.write()); + let mut index_bits = Vec::new(); + let mut index = self.index; + for _ in 0..self.proof.len() { + index_bits.push(index % 2); + index /= 2; + } + // index_bits.reverse(); // Index bits is big endian ? + stream.extend( as Hintable>::write(&index_bits)); + stream.extend(self.opened_values.write()); + stream.extend(>::write(&(self.proof.len()))); // According to openvm extensions/native/recursion/src/fri/hints.rs + stream.extend( + self.proof + .iter() + .flat_map(|p| p.iter().copied()) + .collect::>() + .write(), + ); // According to openvm extensions/native/recursion/src/fri/hints.rs + stream + } +} + +pub type MmcsCommitmentVariable = HashVariable; + +#[derive(DslVariable, Clone)] +pub struct MmcsVerifierInputVariable { + pub commit: MmcsCommitmentVariable, + pub dimensions: Array>, + pub index_bits: Array>, + pub opened_values: Array>>, + pub proof: HintSlice, +} + +pub(crate) fn mmcs_verify_batch( + builder: &mut Builder, + input: MmcsVerifierInputVariable, +) { + let dimensions = match input.dimensions { + Array::Dyn(ptr, len) => Array::Dyn(ptr, len.clone()), + _ => panic!("Expected a dynamic array of felts"), + }; + builder.verify_batch_felt( + &dimensions, + &input.opened_values, + input.proof.id.get_var(), + &input.index_bits, + &input.commit.value, + ); +} + +pub mod tests { + use openvm_circuit::arch::{instructions::program::Program, SystemConfig, VmExecutor}; + use openvm_native_circuit::{Native, NativeConfig}; + use openvm_native_compiler::asm::AsmBuilder; + use openvm_native_recursion::hints::Hintable; + use openvm_stark_backend::config::StarkGenericConfig; + use openvm_stark_sdk::{ + config::baby_bear_poseidon2::BabyBearPoseidon2Config, p3_baby_bear::BabyBear, + }; + use p3_field::{extension::BinomialExtensionField, FieldAlgebra}; + type SC = BabyBearPoseidon2Config; + + type F = BabyBear; + type E = BinomialExtensionField; + type EF = ::Challenge; + use crate::basefold_verifier::structs::Dimensions; + + use super::{mmcs_verify_batch, InnerConfig, MmcsCommitment, MmcsVerifierInput}; + + /// The witness in this test is produced by: + /// https://github.com/Jiangkm3/Plonky3 branch cyte/mmcs-poseidon2-constants + /// cargo test --package p3-merkle-tree --lib -- mmcs::tests::size_gaps --exact --show-output + #[allow(dead_code)] + pub fn build_mmcs_verify_batch() -> (Program, Vec>) { + // OpenVM DSL + let mut builder = AsmBuilder::::default(); + + // Witness inputs + let mmcs_input = MmcsVerifierInput::read(&mut builder); + mmcs_verify_batch(&mut builder, mmcs_input); + builder.halt(); + + // Pass in witness stream + let f = |n: usize| F::from_canonical_usize(n); + let mut witness_stream: Vec< + Vec>, + > = Vec::new(); + let commit = MmcsCommitment { + value: [ + f(414821839), + f(366064801), + f(76927727), + f(1054874897), + f(522043147), + f(638338172), + f(1583746438), + f(941156703), + ], + }; + let dimensions = vec![7, 0, 0]; + let index = 6; + let opened_values = vec![ + vec![ + f(783379538), + f(1083745632), + f(1297755122), + f(739705382), + f(1249630435), + f(1794480926), + f(706129135), + f(51286871), + ], + vec![ + f(1782820525), + f(487690259), + f(1939320991), + f(1236615939), + f(1149125220), + f(1681169264), + f(418636771), + f(1198975790), + ], + vec![ + f(1782820525), + f(487690259), + f(1939320991), + f(1236615939), + f(1149125220), + f(1681169264), + f(418636771), + f(1198975790), + ], + ]; + let proof = vec![ + [ + f(709175359), + f(862600965), + f(21724453), + f(1644204827), + f(1122851899), + f(902491334), + f(187250228), + f(766400688), + ], + [ + f(1500388444), + f(788589576), + f(699109303), + f(1804289606), + f(295155621), + f(328080503), + f(198482491), + f(1942550078), + ], + [ + f(132120813), + f(362247724), + f(635527855), + f(709381234), + f(1331884835), + f(1016275827), + f(962247980), + f(1772849136), + ], + [ + f(1707124288), + f(1917010688), + f(261076785), + f(346295418), + f(1637246858), + f(1607442625), + f(777235843), + f(194556598), + ], + [ + f(1410853257), + f(1598063795), + f(1111574219), + f(1465562989), + f(1102456901), + f(1433687377), + f(1376477958), + f(1087266135), + ], + [ + f(278709284), + f(1823086849), + f(1969802325), + f(633552560), + f(1780238760), + f(297873878), + f(421105965), + f(1357131680), + ], + [ + f(883611536), + f(685305811), + f(56966874), + f(170904280), + f(1353579462), + f(1357636937), + f(1565241058), + f(209109553), + ], + ]; + let mmcs_input = MmcsVerifierInput { + commit, + dimensions, + index, + opened_values, + proof, + }; + witness_stream.extend(mmcs_input.write()); + + // PROGRAM + let program: Program< + p3_monty_31::MontyField31, + > = builder.compile_isa(); + + (program, witness_stream) + } + + #[test] + fn test_mmcs_verify_batch() { + let (program, witness) = build_mmcs_verify_batch(); + + let system_config = SystemConfig::default() + .with_public_values(4) + .with_max_segment_len((1 << 25) - 100); + let config = NativeConfig::new(system_config, Native); + + let executor = VmExecutor::::new(config); + executor.execute(program, witness).unwrap(); + + // _debug + // let results = executor.execute_segments(program, witness).unwrap(); + // for seg in results { + // println!("=> cycle count: {:?}", seg.metrics.cycle_count); + // } + } +} diff --git a/src/basefold_verifier/mod.rs b/src/basefold_verifier/mod.rs new file mode 100644 index 0000000..01ea914 --- /dev/null +++ b/src/basefold_verifier/mod.rs @@ -0,0 +1,9 @@ +pub(crate) mod structs; +pub(crate) mod basefold; +pub(crate) mod query_phase; +pub(crate) mod rs; +pub(crate) mod extension_mmcs; +pub(crate) mod mmcs; +pub(crate) mod hash; +// pub(crate) mod field; +pub(crate) mod utils; \ No newline at end of file diff --git a/src/basefold_verifier/query_phase.rs b/src/basefold_verifier/query_phase.rs new file mode 100644 index 0000000..e533bb5 --- /dev/null +++ b/src/basefold_verifier/query_phase.rs @@ -0,0 +1,954 @@ +// Note: check all XXX comments! + +use std::fmt::Debug; + +use ff_ext::{ExtensionField, PoseidonField}; +use mpcs::QueryPhaseVerifierInput as InnerQueryPhaseVerifierInput; +use openvm_native_compiler::{asm::AsmConfig, prelude::*}; +use openvm_native_recursion::{ + hints::{Hintable, VecAutoHintable}, + vars::HintSlice, +}; +use openvm_stark_sdk::p3_baby_bear::BabyBear; +use p3_commit::ExtensionMmcs; +use p3_field::extension::BinomialExtensionField; +use p3_field::FieldAlgebra; +use serde::Deserialize; + +use super::{basefold::*, extension_mmcs::*, mmcs::*, rs::*, structs::*, utils::*}; +use crate::{ + arithmetics::{ + build_eq_x_r_vec_sequential, build_eq_x_r_vec_sequential_with_offset, eq_eval_with_index, + }, + tower_verifier::{binding::*, program::interpolate_uni_poly}, +}; + +pub type F = BabyBear; +pub type E = BinomialExtensionField; +pub type InnerConfig = AsmConfig; + +use p3_fri::BatchOpening as InnerBatchOpening; +#[derive(Deserialize)] +pub struct BatchOpening { + pub opened_values: Vec>, + pub opening_proof: MmcsProof, +} + +impl + From< + InnerBatchOpening< + ::BaseField, + <::BaseField as PoseidonField>::MMCS, + >, + > for BatchOpening +{ + fn from( + inner: InnerBatchOpening< + ::BaseField, + <::BaseField as PoseidonField>::MMCS, + >, + ) -> Self { + Self { + opened_values: inner.opened_values, + opening_proof: inner.opening_proof.into(), + } + } +} + +impl Hintable for BatchOpening { + type HintVariable = BatchOpeningVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let opened_values = Vec::>::read(builder); + let length = Usize::from(builder.hint_var()); + let id = Usize::from(builder.hint_load()); + let opening_proof = HintSlice { length, id }; + + BatchOpeningVariable { + opened_values, + opening_proof, + } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(self.opened_values.write()); + stream.extend(vec![ + vec![::N::from_canonical_usize( + self.opening_proof.len(), + )], + self.opening_proof.iter().flatten().copied().collect(), + ]); + stream + } +} + +#[derive(DslVariable, Clone)] +pub struct BatchOpeningVariable { + pub opened_values: Array>>, + pub opening_proof: HintSlice, +} + +use p3_fri::CommitPhaseProofStep as InnerCommitPhaseProofStep; +#[derive(Deserialize)] +pub struct CommitPhaseProofStep { + pub sibling_value: E, + pub opening_proof: MmcsProof, +} + +pub type ExtMmcs = ExtensionMmcs< + ::BaseField, + E, + <::BaseField as PoseidonField>::MMCS, +>; +impl From>> for CommitPhaseProofStep { + fn from(inner: InnerCommitPhaseProofStep>) -> Self { + Self { + sibling_value: inner.sibling_value, + opening_proof: inner.opening_proof.into(), + } + } +} + +impl Hintable for CommitPhaseProofStep { + type HintVariable = CommitPhaseProofStepVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let sibling_value = E::read(builder); + let length = Usize::from(builder.hint_var()); + let id = Usize::from(builder.hint_load()); + let opening_proof = HintSlice { length, id }; + + CommitPhaseProofStepVariable { + sibling_value, + opening_proof, + } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(self.sibling_value.write()); + stream.extend(vec![ + vec![::N::from_canonical_usize( + self.opening_proof.len(), + )], + self.opening_proof.iter().flatten().copied().collect(), + ]); + stream + } +} +impl VecAutoHintable for CommitPhaseProofStep {} + +#[derive(DslVariable, Clone)] +pub struct CommitPhaseProofStepVariable { + pub sibling_value: Ext, + pub opening_proof: HintSlice, +} + +#[derive(Deserialize)] +pub struct QueryOpeningProof { + pub witin_base_proof: BatchOpening, + pub fixed_base_proof: Option, + pub commit_phase_openings: Vec, +} +type QueryOpeningProofs = Vec; + +use mpcs::QueryOpeningProof as InnerQueryOpeningProof; +impl From> for QueryOpeningProof { + fn from(proof: InnerQueryOpeningProof) -> Self { + QueryOpeningProof { + witin_base_proof: proof.witin_base_proof.into(), + fixed_base_proof: proof.fixed_base_proof.map(|p| p.into()), + commit_phase_openings: proof + .commit_phase_openings + .into_iter() + .map(|p| p.into()) + .collect(), + } + } +} + +impl Hintable for QueryOpeningProof { + type HintVariable = QueryOpeningProofVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let witin_base_proof = BatchOpening::read(builder); + let fixed_is_some = Usize::Var(usize::read(builder)); + let fixed_base_proof = BatchOpening::read(builder); + let commit_phase_openings = Vec::::read(builder); + QueryOpeningProofVariable { + witin_base_proof, + fixed_is_some, + fixed_base_proof, + commit_phase_openings, + } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(self.witin_base_proof.write()); + if let Some(fixed_base_proof) = &self.fixed_base_proof { + stream.extend(>::write(&1)); + stream.extend(fixed_base_proof.write()); + } else { + stream.extend(>::write(&0)); + let tmp_proof = BatchOpening { + opened_values: Vec::new(), + opening_proof: Vec::new(), + }; + stream.extend(tmp_proof.write()); + } + stream.extend(self.commit_phase_openings.write()); + stream + } +} +impl VecAutoHintable for QueryOpeningProof {} + +#[derive(DslVariable, Clone)] +pub struct QueryOpeningProofVariable { + pub witin_base_proof: BatchOpeningVariable, + pub fixed_is_some: Usize, // 0 <==> false + pub fixed_base_proof: BatchOpeningVariable, + pub commit_phase_openings: Array>, +} +type QueryOpeningProofsVariable = Array>; + +// NOTE: Different from PointAndEval in tower_verifier! +pub struct PointAndEvals { + pub point: Point, + pub evals: Vec, +} +impl Hintable for PointAndEvals { + type HintVariable = PointAndEvalsVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let point = Point::read(builder); + let evals = Vec::::read(builder); + PointAndEvalsVariable { point, evals } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(self.point.write()); + stream.extend(self.evals.write()); + stream + } +} +impl VecAutoHintable for PointAndEvals {} + +#[derive(DslVariable, Clone)] +pub struct PointAndEvalsVariable { + pub point: PointVariable, + pub evals: Array>, +} + +#[derive(Deserialize)] +pub struct QueryPhaseVerifierInput { + pub max_num_var: usize, + pub indices: Vec, + pub final_message: Vec>, + pub batch_coeffs: Vec, + pub queries: QueryOpeningProofs, + pub fixed_comm: Option, + pub witin_comm: BasefoldCommitment, + pub circuit_meta: Vec, + pub commits: Vec, + pub fold_challenges: Vec, + pub sumcheck_messages: Vec, + pub point_evals: Vec<(Point, Vec)>, +} + +impl From> for QueryPhaseVerifierInput { + fn from(input: InnerQueryPhaseVerifierInput) -> Self { + QueryPhaseVerifierInput { + max_num_var: input.max_num_var, + indices: input.indices, + final_message: input.final_message, + batch_coeffs: input.batch_coeffs, + queries: input.queries.into_iter().map(|q| q.into()).collect(), + fixed_comm: input.fixed_comm.map(|comm| comm.into()), + witin_comm: input.witin_comm.into(), + circuit_meta: input.circuit_meta.into_iter().map(|q| q.into()).collect(), + commits: input + .commits + .into_iter() + .map(|q| super::hash::Hash { value: q.into() }) + .collect(), + fold_challenges: input.fold_challenges, + sumcheck_messages: input + .sumcheck_messages + .into_iter() + .map(|q| q.into()) + .collect(), + point_evals: input + .point_evals + .into_iter() + .map(|q| (Point { fs: q.0 }, q.1)) + .collect(), + } + } +} + +impl Hintable for QueryPhaseVerifierInput { + type HintVariable = QueryPhaseVerifierInputVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let max_num_var = Usize::Var(usize::read(builder)); + let indices = Vec::::read(builder); + let final_message = Vec::>::read(builder); + let batch_coeffs = Vec::::read(builder); + let queries = QueryOpeningProofs::read(builder); + let fixed_is_some = Usize::Var(usize::read(builder)); + let fixed_comm = BasefoldCommitment::read(builder); + let witin_comm = BasefoldCommitment::read(builder); + let circuit_meta = Vec::::read(builder); + let commits = Vec::::read(builder); + let fold_challenges = Vec::::read(builder); + let sumcheck_messages = Vec::::read(builder); + let point_evals = Vec::::read(builder); + + QueryPhaseVerifierInputVariable { + max_num_var, + indices, + final_message, + batch_coeffs, + queries, + fixed_is_some, + fixed_comm, + witin_comm, + circuit_meta, + commits, + fold_challenges, + sumcheck_messages, + point_evals, + } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(>::write(&self.max_num_var)); + stream.extend(self.indices.write()); + stream.extend(self.final_message.write()); + stream.extend(self.batch_coeffs.write()); + stream.extend(self.queries.write()); + if let Some(fixed_comm) = &self.fixed_comm { + stream.extend(>::write(&1)); + stream.extend(fixed_comm.write()); + } else { + stream.extend(>::write(&0)); + let tmp_comm = BasefoldCommitment { + commit: Default::default(), + log2_max_codeword_size: 0, + // trivial_commits: Vec::new(), + }; + stream.extend(tmp_comm.write()); + } + stream.extend(self.witin_comm.write()); + stream.extend(self.circuit_meta.write()); + stream.extend(self.commits.write()); + stream.extend(self.fold_challenges.write()); + stream.extend(self.sumcheck_messages.write()); + stream.extend( + self.point_evals + .iter() + .map(|(p, e)| PointAndEvals { + point: p.clone(), + evals: e.clone(), + }) + .collect::>() + .write(), + ); + stream + } +} + +#[derive(DslVariable, Clone)] +pub struct QueryPhaseVerifierInputVariable { + pub max_num_var: Usize, + pub indices: Array>, + pub final_message: Array>>, + pub batch_coeffs: Array>, + pub queries: QueryOpeningProofsVariable, + pub fixed_is_some: Usize, // 0 <==> false + pub fixed_comm: BasefoldCommitmentVariable, + pub witin_comm: BasefoldCommitmentVariable, + pub circuit_meta: Array>, + pub commits: Array>, + pub fold_challenges: Array>, + pub sumcheck_messages: Array>, + pub point_evals: Array>, +} + +pub(crate) fn batch_verifier_query_phase( + builder: &mut Builder, + input: QueryPhaseVerifierInputVariable, +) { + // Nondeterministically supply inv_2 + let inv_2 = builder.hint_felt(); + builder.assert_eq::>( + inv_2 * C::F::from_canonical_usize(2), + C::F::from_canonical_usize(1), + ); + let two_adic_generators: Array> = builder.dyn_array(28); + for (index, val) in [ + 0x1usize, 0x78000000, 0x67055c21, 0x5ee99486, 0xbb4c4e4, 0x2d4cc4da, 0x669d6090, + 0x17b56c64, 0x67456167, 0x688442f9, 0x145e952d, 0x4fe61226, 0x4c734715, 0x11c33e2a, + 0x62c3d2b1, 0x77cad399, 0x54c131f4, 0x4cabd6a6, 0x5cf5713f, 0x3e9430e8, 0xba067a3, + 0x18adc27d, 0x21fd55bc, 0x4b859b3d, 0x3bd57996, 0x4483d85a, 0x3a26eef8, 0x1a427a41, + ] + .iter() + .enumerate() + { + let generator = builder.constant(C::F::from_canonical_usize(*val)); + builder.set_value(&two_adic_generators, index, generator); + } + + // encode_small + let final_rmm_values_len = builder.get(&input.final_message, 0).len(); + let final_rmm_values = builder.dyn_array(final_rmm_values_len.clone()); + + builder + .range(0, final_rmm_values_len.clone()) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + let row_len = input.final_message.len(); + let sum = builder.constant(C::EF::ZERO); + builder.range(0, row_len).for_each(|j_vec, builder| { + let j = j_vec[0]; + let row = builder.get(&input.final_message, j); + let row_j = builder.get(&row, i); + builder.assign(&sum, sum + row_j); + }); + builder.set_value(&final_rmm_values, i, sum); + }); + + let final_rmm = RowMajorMatrixVariable { + values: final_rmm_values, + width: builder.eval(Usize::from(1)), + }; + let final_codeword = encode_small(builder, final_rmm); + // can't use witin_comm.log2_max_codeword_size since it's untrusted + let log2_witin_max_codeword_size: Var = + builder.eval(input.max_num_var.clone() + get_rate_log::()); + + // Nondeterministically supply the index folding_sorted_order + // Check that: + // 1. It has the same length as input.circuit_meta (checked by requesting folding_len hints) + // 2. It does not contain the same index twice (checked via a correspondence array) + // 3. Indexed witin_num_vars are sorted in decreasing order + // Infer witin_num_vars through index + let folding_len = input.circuit_meta.len(); + let zero: Ext = builder.constant(C::EF::ZERO); + let folding_sort_surjective: Array> = + builder.dyn_array(folding_len.clone()); + builder + .range(0, folding_len.clone()) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + builder.set(&folding_sort_surjective, i, zero.clone()); + }); + + // an vector with same length as circuit_meta, which is sorted by num_var in descending order and keep its index + // for reverse lookup when retrieving next base codeword to involve into batching + // Sort input.dimensions by height, returns + // 1. height_order: after sorting by decreasing height, the original index of each entry + // 2. num_unique_height: number of different heights + // 3. count_per_unique_height: for each unique height, number of dimensions of that height + // builder.assert_nonzero(&Usize::from(0)); + let (folding_sorted_order_index, _num_unique_num_vars, count_per_unique_num_var) = + sort_with_count( + builder, + &input.circuit_meta, + |m: CircuitIndexMetaVariable| m.witin_num_vars, + ); + + builder + .range(0, input.indices.len()) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + let idx = builder.get(&input.indices, i); + let query = builder.get(&input.queries, i); + let witin_opened_values = query.witin_base_proof.opened_values; + + let witin_opening_proof = query.witin_base_proof.opening_proof; + let fixed_is_some = query.fixed_is_some; + let fixed_commit = query.fixed_base_proof; + let opening_ext = query.commit_phase_openings; + + // verify base oracle query proof + // refer to prover documentation for the reason of right shift by 1 + // Nondeterministically supply the bits of idx in BIG ENDIAN + // These are not only used by the right shift here but also later on idx_shift + let idx_len = builder.hint_var(); + let idx_bits: Array> = builder.dyn_array(idx_len); + builder.range(0, idx_len).for_each(|j_vec, builder| { + let j = j_vec[0]; + let next_bit = builder.hint_var(); + // Assert that it is a bit + builder.assert_eq::>(next_bit * next_bit, next_bit); + builder.set_value(&idx_bits, j, next_bit); + }); + // Right shift + let idx_len_minus_one: Var = builder.eval(idx_len - Usize::from(1)); + builder.assign(&idx_len, idx_len_minus_one); + let new_idx = bin_to_dec(builder, &idx_bits, idx_len); + let last_bit = builder.get(&idx_bits, idx_len); + builder.assert_eq::>(Usize::from(2) * new_idx + last_bit, idx); + builder.assign(&idx, new_idx); + + let (witin_dimensions, fixed_dimensions) = + get_base_codeword_dimensions(builder, input.circuit_meta.clone()); + // verify witness + let mmcs_verifier_input = MmcsVerifierInputVariable { + commit: input.witin_comm.commit.clone(), + dimensions: witin_dimensions, + index_bits: idx_bits.clone(), // TODO: double check, should be new idx bits here ? + opened_values: witin_opened_values.clone(), + proof: witin_opening_proof, + }; + mmcs_verify_batch(builder, mmcs_verifier_input); + + // verify fixed + let fixed_commit_leafs = builder.dyn_array(0); + builder + .if_eq(fixed_is_some.clone(), Usize::from(1)) + .then(|builder| { + let fixed_opened_values = fixed_commit.opened_values.clone(); + + let fixed_opening_proof = fixed_commit.opening_proof.clone(); + // new_idx used by mmcs proof + let new_idx: Var = builder.eval(idx); + // Nondeterministically supply a hint: + // 0: input.fixed_comm.log2_max_codeword_size < log2_witin_max_codeword_size + // 1: >= + let branch_le = builder.hint_var(); + builder.if_eq(branch_le, Usize::from(0)).then(|builder| { + // input.fixed_comm.log2_max_codeword_size < log2_witin_max_codeword_size + builder.assert_less_than_slow_small_rhs( + input.fixed_comm.log2_max_codeword_size.clone(), + log2_witin_max_codeword_size, + ); + // idx >> idx_shift + let idx_shift_remain: Var = builder.eval( + idx_len + - (log2_witin_max_codeword_size + - input.fixed_comm.log2_max_codeword_size.clone()), + ); + let tmp_idx = bin_to_dec(builder, &idx_bits, idx_shift_remain); + builder.assign(&new_idx, tmp_idx); + }); + builder.if_ne(branch_le, Usize::from(0)).then(|builder| { + // input.fixed_comm.log2_max_codeword_size >= log2_witin_max_codeword_size + let input_codeword_size_plus_one: Var = builder + .eval(input.fixed_comm.log2_max_codeword_size.clone() + Usize::from(1)); + builder.assert_less_than_slow_small_rhs( + log2_witin_max_codeword_size, + input_codeword_size_plus_one, + ); + // idx << -idx_shift + let idx_shift = builder.eval( + input.fixed_comm.log2_max_codeword_size.clone() + - log2_witin_max_codeword_size, + ); + let idx_factor = pow_2(builder, idx_shift); + builder.assign(&new_idx, new_idx * idx_factor); + }); + // verify witness + let mmcs_verifier_input = MmcsVerifierInputVariable { + commit: input.fixed_comm.commit.clone(), + dimensions: fixed_dimensions.clone(), + index_bits: idx_bits.clone(), // TODO: should be new idx_bits + opened_values: fixed_opened_values.clone(), + proof: fixed_opening_proof, + }; + mmcs_verify_batch(builder, mmcs_verifier_input); + builder.assign(&fixed_commit_leafs, fixed_opened_values); + }); + + // base_codeword_lo_hi + let base_codeword_lo = builder.dyn_array(folding_len.clone()); + let base_codeword_hi = builder.dyn_array(folding_len.clone()); + builder + .range(0, folding_len.clone()) + .for_each(|j_vec, builder| { + let j = j_vec[0]; + let circuit_meta = builder.get(&input.circuit_meta, j); + let witin_num_polys = circuit_meta.witin_num_polys; + let fixed_num_vars = circuit_meta.fixed_num_vars; + let fixed_num_polys = circuit_meta.fixed_num_polys; + let witin_leafs = builder.get(&witin_opened_values, j); + // lo_wit, hi_wit + let leafs_len_div_2 = builder.hint_var(); + let two: Var = builder.eval(Usize::from(2)); + builder.assert_eq::>(leafs_len_div_2 * two, witin_leafs.len()); // Can we assume that leafs.len() is even? + // Actual dot_product only computes the first num_polys terms (can we assume leafs_len_div_2 == num_polys?) + let lo_wit = dot_product(builder, &input.batch_coeffs, &witin_leafs); + let hi_wit = dot_product_with_index( + builder, + &input.batch_coeffs, + &witin_leafs, + Usize::from(0), + Usize::Var(leafs_len_div_2), + witin_num_polys.clone(), + ); + // lo_fixed, hi_fixed + let lo_fixed: Ext = + builder.constant(C::EF::from_canonical_usize(0)); + let hi_fixed: Ext = + builder.constant(C::EF::from_canonical_usize(0)); + builder + .if_ne(fixed_num_vars, Usize::from(0)) + .then(|builder| { + let fixed_leafs = builder.get(&fixed_commit_leafs, j); + let leafs_len_div_2 = builder.hint_var(); + let two: Var = builder.eval(Usize::from(2)); + builder + .assert_eq::>(leafs_len_div_2 * two, fixed_leafs.len()); // Can we assume that leafs.len() is even? + // Actual dot_product only computes the first num_polys terms (can we assume leafs_len_div_2 == num_polys?) + let tmp_lo_fixed = + dot_product(builder, &input.batch_coeffs, &fixed_leafs); + let tmp_hi_fixed = dot_product_with_index( + builder, + &input.batch_coeffs, + &fixed_leafs, + Usize::from(0), + Usize::Var(leafs_len_div_2), + fixed_num_polys.clone(), + ); + builder.assign(&lo_fixed, tmp_lo_fixed); + builder.assign(&hi_fixed, tmp_hi_fixed); + }); + let lo: Ext = builder.eval(lo_wit + lo_fixed); + let hi: Ext = builder.eval(hi_wit + hi_fixed); + builder.set_value(&base_codeword_lo, j, lo); + builder.set_value(&base_codeword_hi, j, hi); + }); + + // fold and query + let cur_num_var: Var = builder.eval(input.max_num_var.clone()); + // let rounds: Var = builder.eval(cur_num_var - get_basecode_msg_size_log::() - Usize::from(1)); + let n_d_next_log: Var = + builder.eval(cur_num_var - get_rate_log::() - Usize::from(1)); + // let n_d_next = pow_2(builder, n_d_next_log); + + // first folding challenge + let r = builder.get(&input.fold_challenges, 0); + let next_unique_num_vars_count: Var = builder.get(&count_per_unique_num_var, 0); + let folded: Ext = builder.constant(C::EF::ZERO); + builder + .range(0, next_unique_num_vars_count) + .for_each(|j_vec, builder| { + let j = j_vec[0]; + let index = builder.get(&folding_sorted_order_index, j); + let lo = builder.get(&base_codeword_lo, index.clone()); + let hi = builder.get(&base_codeword_hi, index.clone()); + let level: Var = + builder.eval(cur_num_var + get_rate_log::() - Usize::from(1)); + let coeff = verifier_folding_coeffs_level( + builder, + &two_adic_generators, + level, + &idx_bits, + inv_2, + ); + let fold = codeword_fold_with_challenge::(builder, lo, hi, r, coeff, inv_2); + builder.assign(&folded, folded + fold); + }); + let next_unique_num_vars_index: Var = builder.eval(Usize::from(1)); + let cumul_num_vars_count: Var = builder.eval(next_unique_num_vars_count); + let n_d_i_log: Var = builder.eval(n_d_next_log); + // let n_d_i: Var = builder.eval(n_d_next); + // zip_eq + builder.assert_eq::>( + input.commits.len() + Usize::from(1), + input.fold_challenges.len(), + ); + builder.assert_eq::>(input.commits.len(), opening_ext.len()); + builder + .range(0, input.commits.len()) + .for_each(|j_vec, builder| { + let j = j_vec[0]; + let pi_comm = builder.get(&input.commits, j); + let j_plus_one = builder.eval_expr(j + RVar::from(1)); + let r = builder.get(&input.fold_challenges, j_plus_one); + let leaf = builder.get(&opening_ext, j).sibling_value; + let proof = builder.get(&opening_ext, j).opening_proof; + builder.assign(&cur_num_var, cur_num_var - Usize::from(1)); + + // next folding challenges + let idx_len_minus_one: Var = builder.eval(idx_len - Usize::from(1)); + let is_interpolate_to_right_index = builder.get(&idx_bits, idx_len_minus_one); + let new_involved_codewords: Ext = builder.constant(C::EF::ZERO); + let next_unique_num_vars_count: Var = + builder.get(&count_per_unique_num_var, next_unique_num_vars_index); + builder + .range(0, next_unique_num_vars_count) + .for_each(|k_vec, builder| { + let k = builder.eval_expr(k_vec[0] + cumul_num_vars_count); + let index = builder.get(&folding_sorted_order_index, k); + let lo = builder.get(&base_codeword_lo, index.clone()); + let hi = builder.get(&base_codeword_hi, index.clone()); + builder + .if_eq(is_interpolate_to_right_index, Usize::from(1)) + .then(|builder| { + builder.assign( + &new_involved_codewords, + new_involved_codewords + hi, + ); + }); + builder + .if_ne(is_interpolate_to_right_index, Usize::from(1)) + .then(|builder| { + builder.assign( + &new_involved_codewords, + new_involved_codewords + lo, + ); + }); + }); + builder.assign( + &cumul_num_vars_count, + cumul_num_vars_count + next_unique_num_vars_count, + ); + builder.assign( + &next_unique_num_vars_index, + next_unique_num_vars_index + Usize::from(1), + ); + + // leafs + let leafs = builder.dyn_array(2); + let new_leaf = builder.eval(folded + new_involved_codewords); + builder + .if_eq(is_interpolate_to_right_index, Usize::from(1)) + .then(|builder| { + builder.set_value(&leafs, 0, leaf); + builder.set_value(&leafs, 1, new_leaf); + }); + builder + .if_ne(is_interpolate_to_right_index, Usize::from(1)) + .then(|builder| { + builder.set_value(&leafs, 0, new_leaf); + builder.set_value(&leafs, 1, leaf); + }); + // idx >>= 1 + let idx_len_minus_one: Var = builder.eval(idx_len - Usize::from(1)); + builder.assign(&idx_len, idx_len_minus_one); + let new_idx = bin_to_dec(builder, &idx_bits, idx_len); + let last_bit = builder.get(&idx_bits, idx_len); + builder.assert_eq::>(Usize::from(2) * new_idx + last_bit, idx); + builder.assign(&idx, new_idx); + // n_d_i >> 1 + builder.assign(&n_d_i_log, n_d_i_log - Usize::from(1)); + let n_d_i = pow_2(builder, n_d_i_log); + // mmcs_ext.verify_batch + let dimensions = builder.dyn_array(1); + // let two: Var<_> = builder.eval(Usize::from(2)); + builder.set_value(&dimensions, 0, n_d_i.clone()); + let opened_values = builder.dyn_array(1); + builder.set_value(&opened_values, 0, leafs.clone()); + let ext_mmcs_verifier_input = ExtMmcsVerifierInputVariable { + commit: pi_comm.clone(), + dimensions, + index_bits: idx_bits.clone(), // TODO: new idx bits? + opened_values, + proof, + }; + ext_mmcs_verify_batch::(builder, ext_mmcs_verifier_input); + + let coeff = verifier_folding_coeffs_level( + builder, + &two_adic_generators, + n_d_i_log.clone(), + &idx_bits, + inv_2, + ); + let left = builder.get(&leafs, 0); + let right = builder.get(&leafs, 1); + let new_folded = + codeword_fold_with_challenge(builder, left, right, r.clone(), coeff, inv_2); + builder.assign(&folded, new_folded); + }); + let final_value = builder.get(&final_codeword.values, idx.clone()); + builder.assert_eq::>(final_value, folded); + }); + + // 1. check initial claim match with first round sumcheck value + let points = builder.dyn_array(input.batch_coeffs.len()); + let next_point_index: Var = builder.eval(Usize::from(0)); + builder + .range(0, input.point_evals.len()) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + let evals = builder.get(&input.point_evals, i).evals; + let witin_num_vars = builder.get(&input.circuit_meta, i).witin_num_vars; + // we need to scale up with scalar for witin_num_vars < max_num_var + let scale_log = builder.eval(input.max_num_var.clone() - witin_num_vars); + let scale = pow_2(builder, scale_log); + // Transform scale into a field element + let scale = builder.unsafe_cast_var_to_felt(scale); + builder.range(0, evals.len()).for_each(|j_vec, builder| { + let j = j_vec[0]; + let eval = builder.get(&evals, j); + let scaled_eval: Ext = builder.eval(eval * scale); + builder.set_value(&points, next_point_index, scaled_eval); + builder.assign(&next_point_index, next_point_index + Usize::from(1)); + }); + }); + let left = dot_product(builder, &input.batch_coeffs, &points); + let next_sumcheck_evals = builder.get(&input.sumcheck_messages, 0).evaluations; + let eval0 = builder.get(&next_sumcheck_evals, 0); + let eval1 = builder.get(&next_sumcheck_evals, 1); + let right: Ext = builder.eval(eval0 + eval1); + builder.assert_eq::>(left, right); + + // 2. check every round of sumcheck match with prev claims + let fold_len_minus_one: Var = builder.eval(input.fold_challenges.len() - Usize::from(1)); + builder + .range(0, fold_len_minus_one) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + let evals = builder.get(&input.sumcheck_messages, i).evaluations; + let challenge = builder.get(&input.fold_challenges, i); + let left = interpolate_uni_poly(builder, &evals, challenge); + let i_plus_one = builder.eval_expr(i + Usize::from(1)); + let next_evals = builder + .get(&input.sumcheck_messages, i_plus_one) + .evaluations; + let eval0 = builder.get(&next_evals, 0); + let eval1 = builder.get(&next_evals, 1); + let right: Ext = builder.eval(eval0 + eval1); + builder.assert_eq::>(left, right); + }); + + // 3. check final evaluation are correct + let final_evals = builder + .get(&input.sumcheck_messages, fold_len_minus_one.clone()) + .evaluations; + let final_challenge = builder.get(&input.fold_challenges, fold_len_minus_one.clone()); + let left = interpolate_uni_poly(builder, &final_evals, final_challenge); + let right: Ext = builder.constant(C::EF::ZERO); + builder + .range(0, input.final_message.len()) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + let final_message = builder.get(&input.final_message, i); + let point = builder.get(&input.point_evals, i).point; + // coeff is the eq polynomial evaluated at the first challenge.len() variables + let num_vars_evaluated: Var = + builder.eval(point.fs.len() - get_basecode_msg_size_log::()); + let ylo = builder.eval(input.fold_challenges.len() - num_vars_evaluated); + let coeff = eq_eval_with_index( + builder, + &point.fs, + &input.fold_challenges, + Usize::from(0), + Usize::Var(ylo), + Usize::Var(num_vars_evaluated), + ); + let eq = build_eq_x_r_vec_sequential_with_offset::( + builder, + &point.fs, + Usize::Var(num_vars_evaluated), + ); + let eq_coeff = builder.dyn_array(eq.len()); + builder.range(0, eq.len()).for_each(|j_vec, builder| { + let j = j_vec[0]; + let next_eq = builder.get(&eq, j); + let next_eq_coeff: Ext = builder.eval(next_eq * coeff); + builder.set_value(&eq_coeff, j, next_eq_coeff); + }); + let dot_prod = dot_product(builder, &final_message, &eq_coeff); + builder.assign(&right, right + dot_prod); + }); + builder.assert_eq::>(left, right); +} + +pub mod tests { + use std::{fs::File, io::Read}; + + use mpcs::{QueryPhaseAdditionalHint, QueryPhaseVerifierInput as InnerQueryPhaseVerifierInput}; + use openvm_circuit::arch::{instructions::program::Program, SystemConfig, VmExecutor}; + use openvm_native_circuit::{Native, NativeConfig}; + use openvm_native_compiler::asm::AsmBuilder; + use openvm_native_recursion::hints::Hintable; + use openvm_stark_backend::config::StarkGenericConfig; + use openvm_stark_sdk::{ + config::baby_bear_poseidon2::BabyBearPoseidon2Config, p3_baby_bear::BabyBear, + }; + use p3_field::{extension::BinomialExtensionField, Field, FieldAlgebra}; + type SC = BabyBearPoseidon2Config; + + type F = BabyBear; + type E = BinomialExtensionField; + type EF = ::Challenge; + + use super::{batch_verifier_query_phase, QueryPhaseVerifierInput}; + + #[allow(dead_code)] + pub fn build_batch_verifier_query_phase() -> (Program, Vec>) { + // OpenVM DSL + let mut builder = AsmBuilder::::default(); + + // Witness inputs + let query_phase_input = QueryPhaseVerifierInput::read(&mut builder); + batch_verifier_query_phase(&mut builder, query_phase_input); + builder.halt(); + + // Pass in witness stream + let f = |n: usize| F::from_canonical_usize(n); + let mut witness_stream: Vec< + Vec>, + > = Vec::new(); + + // INPUT + let mut f = File::open("query_phase_verifier_input.bin".to_string()).unwrap(); + let mut content: Vec = Vec::new(); + f.read_to_end(&mut content).unwrap(); + let input: InnerQueryPhaseVerifierInput = bincode::deserialize(&content).unwrap(); + let input: QueryPhaseVerifierInput = input.into(); + + witness_stream.extend(input.write()); + + // the builder reads some additional hints after reading the query + // phase verifier input. Need to feed them into the stream + let mut f = File::open("query_phase_additional_hint.bin".to_string()).unwrap(); + let mut content: Vec = Vec::new(); + f.read_to_end(&mut content).unwrap(); + let input: QueryPhaseAdditionalHint = bincode::deserialize(&content).unwrap(); + + witness_stream.extend(vec![vec![input.two_inv]]); + witness_stream.extend(vec![vec![F::from_canonical_usize( + input.num_unique_entries, + )]]); + witness_stream.extend(vec![input + .sorting_orders + .iter() + .map(|x| F::from_canonical_usize(*x)) + .collect()]); + + // PROGRAM + let program: Program< + p3_monty_31::MontyField31, + > = builder.compile_isa(); + + (program, witness_stream) + } + + #[test] + fn test_verify_query_phase_batch() { + let (program, witness) = build_batch_verifier_query_phase(); + + let system_config = SystemConfig::default() + .with_public_values(4) + .with_max_segment_len((1 << 25) - 100); + let config = NativeConfig::new(system_config, Native); + + let executor = VmExecutor::::new(config); + executor.execute(program, witness).unwrap(); + + // _debug + // let results = executor.execute_segments(program, witness).unwrap(); + // for seg in results { + // println!("=> cycle count: {:?}", seg.metrics.cycle_count); + // } + } +} diff --git a/src/basefold_verifier/rs.rs b/src/basefold_verifier/rs.rs new file mode 100644 index 0000000..93e676a --- /dev/null +++ b/src/basefold_verifier/rs.rs @@ -0,0 +1,301 @@ +// Note: check all XXX comments! + +use std::{cell::RefCell, collections::BTreeMap}; + +use openvm_native_compiler::{asm::AsmConfig, prelude::*}; +use openvm_native_recursion::hints::Hintable; +use openvm_stark_sdk::p3_baby_bear::BabyBear; +use p3_field::extension::BinomialExtensionField; +use p3_field::FieldAlgebra; +use serde::Deserialize; + +use super::structs::*; +use super::utils::{pow_felt, pow_felt_bits}; + +pub type F = BabyBear; +pub type E = BinomialExtensionField; +pub type InnerConfig = AsmConfig; + +pub struct DenseMatrix { + pub values: Vec, + pub width: usize, +} + +impl Hintable for DenseMatrix { + type HintVariable = DenseMatrixVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let values = Vec::::read(builder); + let width = usize::read(builder); + + DenseMatrixVariable { values, width } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(self.values.write()); + stream.extend(>::write(&self.width)); + stream + } +} + +#[derive(DslVariable, Clone)] +pub struct DenseMatrixVariable { + pub values: Array>, + pub width: Var, +} +pub type RowMajorMatrixVariable = DenseMatrixVariable; + +impl DenseMatrixVariable { + pub fn height(&self, builder: &mut Builder) -> Var { + // Supply height as hint + let height = builder.hint_var(); + builder + .if_eq(self.width.clone(), Usize::from(0)) + .then(|builder| { + builder.assert_usize_eq(height, Usize::from(0)); + }); + builder + .if_ne(self.width.clone(), Usize::from(0)) + .then(|builder| { + // XXX: check that width * height is not a field multiplication + builder.assert_usize_eq(self.width.clone() * height, self.values.len()); + }); + height + } + + // XXX: Find better ways to handle this without cloning + pub fn pad_to_height( + &self, + builder: &mut Builder, + new_height: Var, + fill: Ext, + ) { + // XXX: Not necessary, only for testing purpose + let old_height = self.height(builder); + builder.assert_less_than_slow_small_rhs(old_height, new_height + RVar::from(1)); + let new_size = builder.eval_expr(self.width.clone() * new_height.clone()); + let evals: Array> = builder.dyn_array(new_size); + builder + .range(0, self.values.len()) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + let tmp: Ext = builder.get(&self.values, i); + builder.set(&evals, i, tmp); + }); + builder + .range(self.values.len(), evals.len()) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + builder.set(&evals, i, fill); + }); + builder.assign(&self.values, evals); + } +} + +pub fn get_rate_log() -> Usize { + Usize::from(1) +} + +pub fn get_basecode_msg_size_log() -> Usize { + Usize::from(7) +} + +pub fn verifier_folding_coeffs_level( + builder: &mut Builder, + two_adic_generators: &Array>, + level: Var, + index_bits: &Array>, // In big endian + two_inv: Felt, +) -> Felt { + let level_plus_one = builder.eval::, _>(level + C::N::ONE); + let g = builder.get(two_adic_generators, level_plus_one); + let g_inv = builder.hint_felt(); + builder.assert_eq::>(g_inv * g, C::F::from_canonical_usize(1)); + + let g_inv_index = pow_felt_bits(builder, g_inv, index_bits, level.into()); + + builder.eval(g_inv_index * two_inv) +} + +/// The DIT FFT algorithm. +#[derive(Deserialize)] +pub struct Radix2Dit { + pub twiddles: RefCell>>, +} + +impl Hintable for Radix2Dit { + type HintVariable = Radix2DitVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let twiddles = Vec::::read(builder); + + Radix2DitVariable { twiddles } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + // XXX: process BTreeMap + let twiddles_vec: Vec = Vec::new(); + stream.extend(twiddles_vec.write()); + stream + } +} + +#[derive(DslVariable, Clone)] +pub struct Radix2DitVariable { + /// Memoized twiddle factors for each length log_n. + /// Precise definition is a map from usize to E + pub twiddles: Array>, +} + +/* +impl Radix2DitVariable { + fn dft_batch( + &self, + builder: &mut Builder, + mat: RowMajorMatrixVariable + ) -> RowMajorMatrixVariable { + let h = mat.height(builder); + let log_h = builder.hint_var(); + let log_h_minus_1: Var = builder.eval(log_h - Usize::from(1)); + let purported_h_lower_bound = pow_2(builder, log_h_minus_1); + let purported_h_upper_bound = pow_2(builder, log_h); + builder.assert_less_than_slow_small_rhs(purported_h_lower_bound, h); + builder.assert_less_than_slow_small_rhs(h, purported_h_upper_bound); + + // TODO: support memoization + // Compute twiddle factors, or take memoized ones if already available. + let twiddles = { + let root = F::two_adic_generator(log_h); + root.powers().take(1 << log_h).collect() + }; + + // DIT butterfly + reverse_matrix_index_bits(&mut mat); + for layer in 0..log_h { + dit_layer(&mut mat.as_view_mut(), layer, twiddles); + } + mat + } +} +*/ + +#[derive(Deserialize)] +pub struct RSCodeVerifierParameters { + pub full_message_size_log: usize, +} + +#[derive(DslVariable, Clone)] +pub struct RSCodeVerifierParametersVariable { + pub full_message_size_log: Usize, +} + +/* +pub(crate) fn encode_small( + builder: &mut Builder, + vp: RSCodeVerifierParametersVariable, + rmm: RowMajorMatrixVariable, +) -> RowMajorMatrixVariable { + let m = rmm; + // Add current setup this is unnecessary + let old_height = m.height(builder); + let new_height = builder.eval_expr( + old_height * Usize::from(1 << get_rate_log()) + ); + m.pad_to_height(builder, new_height, Ext::new(0)); + m +} +*/ + +/// Encode the last message sent from the prover to the verifier +/// in the commit phase. Currently, for simplicity, we drop the +/// early stopping strategy so the last message has just one +/// element, and the encoding is simply repeating this element +/// by the expansion rate. +pub(crate) fn encode_small( + builder: &mut Builder, + rmm: RowMajorMatrixVariable, // Assumed to have only one row and one column +) -> RowMajorMatrixVariable { + // XXX: nondeterministically supply the results for now + let result = builder.array(2); // Assume the expansion rate is fixed to 2 by now + let value = builder.get(&rmm.values, 0); + builder.range(0, 2).for_each(|i_vec, builder| { + let i = i_vec[0]; + builder.set_value(&result, i, value); + }); + DenseMatrixVariable { + values: result, + width: builder.eval(Usize::from(1)), + } +} + +pub mod tests { + use openvm_circuit::arch::{instructions::program::Program, SystemConfig, VmExecutor}; + use openvm_native_circuit::{Native, NativeConfig}; + use openvm_native_compiler::asm::AsmBuilder; + use openvm_native_compiler::prelude::*; + use openvm_native_recursion::hints::Hintable; + use openvm_stark_backend::config::StarkGenericConfig; + use openvm_stark_sdk::{ + config::baby_bear_poseidon2::BabyBearPoseidon2Config, p3_baby_bear::BabyBear, + }; + use p3_field::{extension::BinomialExtensionField, FieldAlgebra}; + type SC = BabyBearPoseidon2Config; + + type F = BabyBear; + type E = BinomialExtensionField; + type EF = ::Challenge; + use super::{DenseMatrix, InnerConfig}; + + #[allow(dead_code)] + pub fn build_test_dense_matrix_pad() -> (Program, Vec>) { + // OpenVM DSL + let mut builder = AsmBuilder::::default(); + + // Witness inputs + let dense_matrix_variable = DenseMatrix::read(&mut builder); + let new_height = builder.eval(Usize::from(8)); + let fill = Ext::new(0); + dense_matrix_variable.pad_to_height(&mut builder, new_height, fill); + builder.halt(); + + // Pass in witness stream + let mut witness_stream: Vec< + Vec>, + > = Vec::new(); + + let verifier_input = DenseMatrix { + values: vec![E::ONE; 25], + width: 5, + }; + witness_stream.extend(verifier_input.write()); + // Hint for height + witness_stream.extend(>::write(&5)); + + let program: Program< + p3_monty_31::MontyField31, + > = builder.compile_isa(); + + (program, witness_stream) + } + + #[test] + fn test_dense_matrix_pad() { + let (program, witness) = build_test_dense_matrix_pad(); + + let system_config = SystemConfig::default() + .with_public_values(4) + .with_max_segment_len((1 << 25) - 100); + let config = NativeConfig::new(system_config, Native); + + let executor = VmExecutor::::new(config); + executor.execute(program, witness).unwrap(); + + // _debug + // let results = executor.execute_segments(program, witness).unwrap(); + // for seg in results { + // println!("=> cycle count: {:?}", seg.metrics.cycle_count); + // } + } +} diff --git a/src/basefold_verifier/structs.rs b/src/basefold_verifier/structs.rs new file mode 100644 index 0000000..a933c5c --- /dev/null +++ b/src/basefold_verifier/structs.rs @@ -0,0 +1,250 @@ +use openvm_native_compiler::{asm::AsmConfig, ir::*}; +use openvm_native_compiler_derive::DslVariable; +use openvm_native_recursion::hints::{Hintable, VecAutoHintable}; +use openvm_stark_sdk::p3_baby_bear::BabyBear; +use p3_field::extension::BinomialExtensionField; +use serde::Deserialize; + +pub const DIMENSIONS: usize = 4; + +pub type F = BabyBear; +pub type E = BinomialExtensionField; +pub type InnerConfig = AsmConfig; + +use super::rs::get_rate_log; +use super::utils::pow_2; + +#[derive(DslVariable, Clone)] +pub struct CircuitIndexMetaVariable { + pub witin_num_vars: Usize, + pub witin_num_polys: Usize, + pub fixed_num_vars: Usize, + pub fixed_num_polys: Usize, +} + +#[derive(Deserialize)] +pub struct CircuitIndexMeta { + pub witin_num_vars: usize, + pub witin_num_polys: usize, + pub fixed_num_vars: usize, + pub fixed_num_polys: usize, +} + +use mpcs::CircuitIndexMeta as InnerCircuitIndexMeta; +impl From for CircuitIndexMeta { + fn from(inner: InnerCircuitIndexMeta) -> Self { + Self { + witin_num_vars: inner.witin_num_vars, + witin_num_polys: inner.witin_num_polys, + fixed_num_vars: inner.fixed_num_vars, + fixed_num_polys: inner.fixed_num_polys, + } + } +} + +impl Hintable for CircuitIndexMeta { + type HintVariable = CircuitIndexMetaVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let witin_num_vars = Usize::Var(usize::read(builder)); + let witin_num_polys = Usize::Var(usize::read(builder)); + let fixed_num_vars = Usize::Var(usize::read(builder)); + let fixed_num_polys = Usize::Var(usize::read(builder)); + + CircuitIndexMetaVariable { + witin_num_vars, + witin_num_polys, + fixed_num_vars, + fixed_num_polys, + } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(>::write( + &self.witin_num_vars, + )); + stream.extend(>::write( + &self.witin_num_polys, + )); + stream.extend(>::write( + &self.fixed_num_vars, + )); + stream.extend(>::write( + &self.fixed_num_polys, + )); + stream + } +} +impl VecAutoHintable for CircuitIndexMeta {} + +#[derive(DslVariable, Clone)] +pub struct DimensionsVariable { + pub width: Var, + pub height: Var, +} + +pub struct Dimensions { + pub width: usize, + pub height: usize, +} + +impl Hintable for Dimensions { + type HintVariable = DimensionsVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let width = usize::read(builder); + let height = usize::read(builder); + + DimensionsVariable { width, height } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(>::write(&self.width)); + stream.extend(>::write(&self.height)); + stream + } +} +impl VecAutoHintable for Dimensions {} + +pub fn get_base_codeword_dimensions( + builder: &mut Builder, + circuit_meta_map: Array>, +) -> (Array>, Array>) { + let dim_len = circuit_meta_map.len(); + let wit_dim: Array> = builder.dyn_array(dim_len.clone()); + let fixed_dim: Array> = builder.dyn_array(dim_len.clone()); + + builder.range(0, dim_len).for_each(|i_vec, builder| { + let i = i_vec[0]; + let tmp = builder.get(&circuit_meta_map, i); + let witin_num_vars = tmp.witin_num_vars; + let witin_num_polys = tmp.witin_num_polys; + let fixed_num_vars = tmp.fixed_num_vars; + let fixed_num_polys = tmp.fixed_num_polys; + // wit_dim + // let width = builder.eval(witin_num_polys * Usize::from(2)); + let height_exp = builder.eval(witin_num_vars + get_rate_log::() - Usize::from(1)); + let height = pow_2(builder, height_exp); + // let next_wit: DimensionsVariable = DimensionsVariable { width, height }; + // Only keep the height because the width is not needed in the mmcs batch + // verify instruction + builder.set_value(&wit_dim, i, height); + + // fixed_dim + // XXX: since fixed_num_vars is usize, fixed_num_vars > 0 is equivalent to fixed_num_vars != 0 + builder + .if_ne(fixed_num_vars.clone(), Usize::from(0)) + .then(|builder| { + // let width = builder.eval(fixed_num_polys.clone() * Usize::from(2)); + let height_exp = + builder.eval(fixed_num_vars.clone() + get_rate_log::() - Usize::from(1)); + // XXX: more efficient pow implementation + let height = pow_2(builder, height_exp); + // let next_fixed: DimensionsVariable = DimensionsVariable { width, height }; + builder.set_value(&fixed_dim, i, height); + }); + }); + (wit_dim, fixed_dim) +} + +pub mod tests { + use openvm_circuit::arch::{instructions::program::Program, SystemConfig, VmExecutor}; + use openvm_native_circuit::{Native, NativeConfig}; + use openvm_native_compiler::asm::AsmBuilder; + use openvm_native_compiler::prelude::*; + use openvm_native_recursion::hints::Hintable; + use openvm_stark_backend::config::StarkGenericConfig; + use openvm_stark_sdk::{ + config::baby_bear_poseidon2::BabyBearPoseidon2Config, p3_baby_bear::BabyBear, + }; + use p3_field::extension::BinomialExtensionField; + type SC = BabyBearPoseidon2Config; + + type F = BabyBear; + type E = BinomialExtensionField; + type EF = ::Challenge; + use crate::basefold_verifier::structs::*; + + use super::{get_base_codeword_dimensions, InnerConfig}; + + #[allow(dead_code)] + pub fn build_test_get_base_codeword_dimensions() -> (Program, Vec>) { + // OpenVM DSL + let mut builder = AsmBuilder::::default(); + + // Witness inputs + let map_len = Usize::Var(usize::read(&mut builder)); + let circuit_meta_map = builder.dyn_array(map_len.clone()); + builder + .range(0, map_len.clone()) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + let next_meta = CircuitIndexMeta::read(builder); + builder.set(&circuit_meta_map, i, next_meta); + }); + + let (wit_dim, fixed_dim) = get_base_codeword_dimensions(&mut builder, circuit_meta_map); + builder.range(0, map_len).for_each(|i_vec, builder| { + let i = i_vec[0]; + let wit = builder.get(&wit_dim, i); + let fixed = builder.get(&fixed_dim, i); + let i_val: Var<_> = builder.eval(i); + builder.print_v(i_val); + // let ww_val: Var<_> = builder.eval(wit.width); + // let wh_val: Var<_> = builder.eval(wit.height); + // let fw_val: Var<_> = builder.eval(fixed.width); + // let fh_val: Var<_> = builder.eval(fixed.height); + // builder.print_v(ww_val); + builder.print_v(wit); + // builder.print_v(fw_val); + builder.print_v(fixed); + }); + builder.halt(); + + // Pass in witness stream + let mut witness_stream: Vec< + Vec>, + > = Vec::new(); + + // Map length + let map_len = 5; + witness_stream.extend(>::write(&map_len)); + for i in 0..map_len { + // Individual metas + let circuit_meta = CircuitIndexMeta { + witin_num_vars: i, + witin_num_polys: i, + fixed_num_vars: i, + fixed_num_polys: i, + }; + witness_stream.extend(circuit_meta.write()); + } + + let program: Program< + p3_monty_31::MontyField31, + > = builder.compile_isa(); + + (program, witness_stream) + } + + #[test] + fn test_dense_matrix_pad() { + let (program, witness) = build_test_get_base_codeword_dimensions(); + + let system_config = SystemConfig::default() + .with_public_values(4) + .with_max_segment_len((1 << 25) - 100); + let config = NativeConfig::new(system_config, Native); + + let executor = VmExecutor::::new(config); + executor.execute(program, witness).unwrap(); + + // _debug + // let results = executor.execute_segments(program, witness).unwrap(); + // for seg in results { + // println!("=> cycle count: {:?}", seg.metrics.cycle_count); + // } + } +} diff --git a/src/basefold_verifier/utils.rs b/src/basefold_verifier/utils.rs new file mode 100644 index 0000000..49dc5a2 --- /dev/null +++ b/src/basefold_verifier/utils.rs @@ -0,0 +1,246 @@ +use openvm_native_compiler::ir::*; +use p3_field::FieldAlgebra; + +// XXX: more efficient pow implementation +pub fn pow(builder: &mut Builder, base: Var, exponent: Var) -> Var { + let value: Var = builder.constant(C::N::ONE); + builder.range(0, exponent).for_each(|_, builder| { + builder.assign(&value, value * base); + }); + value +} + +// XXX: more efficient pow implementation +pub fn pow_felt( + builder: &mut Builder, + base: Felt, + exponent: Var, +) -> Felt { + let value: Felt = builder.constant(C::F::ONE); + builder.range(0, exponent).for_each(|_, builder| { + builder.assign(&value, value * base); + }); + value +} + +// XXX: more efficient pow implementation +pub fn pow_felt_bits( + builder: &mut Builder, + base: Felt, + exponent_bits: &Array>, // In small endian + exponent_len: Usize, +) -> Felt { + let value: Felt = builder.constant(C::F::ONE); + let repeated_squared: Felt = base; + builder.range(0, exponent_len).for_each(|ptr, builder| { + let ptr = ptr[0]; + let bit = builder.get(exponent_bits, ptr); + builder.if_eq(bit, C::N::ONE).then(|builder| { + builder.assign(&value, value * repeated_squared); + }); + builder.assign(&repeated_squared, repeated_squared * repeated_squared); + }); + value +} + +pub fn pow_2(builder: &mut Builder, exponent: Var) -> Var { + let two: Var = builder.constant(C::N::from_canonical_usize(2)); + pow(builder, two, exponent) +} + +// XXX: Equally outrageously inefficient +pub fn next_power_of_two(builder: &mut Builder, value: Var) -> Var { + // Non-deterministically supply the exponent n such that + // 2^n < v <= 2^{n+1} + // Ignore if v == 1 + let n: Var = builder.hint_var(); + let ret = pow_2(builder, n); + builder.if_eq(value, Usize::from(1)).then(|builder| { + builder.assign(&ret, Usize::from(1)); + }); + builder.if_ne(value, Usize::from(1)).then(|builder| { + builder.assert_less_than_slow_bit_decomp(ret, value); + let two: Var = builder.constant(C::N::from_canonical_usize(2)); + builder.assign(&ret, ret * two); + let ret_plus_one = builder.eval(ret.clone() + Usize::from(1)); + builder.assert_less_than_slow_bit_decomp(value, ret_plus_one); + }); + ret +} + +// Dot product: li * ri +pub fn dot_product( + builder: &mut Builder, + li: &Array>, + ri: &Array, +) -> Ext +where + F: openvm_native_compiler::ir::MemVariable + 'static, +{ + dot_product_with_index::(builder, li, ri, Usize::from(0), Usize::from(0), li.len()) +} + +// Generic dot product of li[llo..llo+len] * ri[rlo..rlo+len] +pub fn dot_product_with_index( + builder: &mut Builder, + li: &Array>, + ri: &Array, + llo: Usize, + rlo: Usize, + len: Usize, +) -> Ext +where + F: openvm_native_compiler::ir::MemVariable + 'static, +{ + let ret: Ext = builder.constant(C::EF::ZERO); + + builder.range(0, len).for_each(|i_vec, builder| { + let i = i_vec[0]; + let lidx: Var = builder.eval(llo.clone() + i); + let ridx: Var = builder.eval(rlo.clone() + i); + let l = builder.get(li, lidx); + let r = builder.get(ri, ridx); + builder.assign(&ret, ret + l * r); + }); + ret +} + +// Convert the first len entries of binary to decimal +// BIN is in big endian +pub fn bin_to_dec( + builder: &mut Builder, + bin: &Array>, + len: Var, +) -> Var { + let value: Var = builder.constant(C::N::ZERO); + let two: Var = builder.constant(C::N::TWO); + builder.range(0, len).for_each(|i_vec, builder| { + let i = i_vec[0]; + builder.assign(&value, value * two); + let next_bit = builder.get(bin, i); + builder.assign(&value, value + next_bit); + }); + value +} + +// Sort a list in decreasing order, returns: +// 1. The original index of each sorted entry +// 2. Number of unique entries +// 3. Number of counts of each unique entry +pub fn sort_with_count( + builder: &mut Builder, + list: &Array, + ind: Ind, // Convert loaded out entries into comparable ones +) -> (Array>, Var, Array>) +where + E: openvm_native_compiler::ir::MemVariable, + N: Into::N>> + + openvm_native_compiler::ir::Variable, + Ind: Fn(E) -> N, +{ + let len = list.len(); + // Nondeterministically supplies: + // 1. num_unique_entries: number of different entries + // 2. entry_order: after sorting by decreasing order, the original index of each entry + // To ensure that entry_order represents sorted index, assert that + // 1. It has the same length as list (checked by requesting list.len() hints) + // 2. It does not contain the same index twice (checked via a correspondence array) + // 3. Sorted entries are in decreasing order + // While checking, record: + // 1. count_per_unique_entry: for each unique entry value, count of entries of that value + let num_unique_entries = builder.hint_var(); + let count_per_unique_entry = builder.dyn_array(num_unique_entries); + let zero: Ext = builder.constant(C::EF::ZERO); + let one: Ext = builder.constant(C::EF::ONE); + let entries_sort_surjective: Array> = builder.dyn_array(len.clone()); + builder.range(0, len.clone()).for_each(|i_vec, builder| { + let i = i_vec[0]; + builder.set(&entries_sort_surjective, i, zero.clone()); + }); + + let entries_order = builder.dyn_array(len.clone()); + let next_order = builder.hint_var(); + // Check surjection + let surjective = builder.get(&entries_sort_surjective, next_order); + builder.assert_ext_eq(surjective, zero.clone()); + builder.set(&entries_sort_surjective, next_order, one.clone()); + builder.set_value(&entries_order, 0, next_order); + let last_entry = ind(builder.get(&list, next_order)); + + let last_unique_entry_index: Var = builder.eval(Usize::from(0)); + let last_count_per_unique_entry: Var = builder.eval(Usize::from(1)); + builder.range(1, len).for_each(|i_vec, builder| { + let i = i_vec[0]; + let next_order = builder.hint_var(); + // Check surjection + let surjective = builder.get(&entries_sort_surjective, next_order); + builder.assert_ext_eq(surjective, zero.clone()); + builder.set(&entries_sort_surjective, next_order, one.clone()); + // Check entries + let next_entry = ind(builder.get(&list, next_order)); + builder + .if_eq(last_entry.clone(), next_entry.clone()) + .then(|builder| { + // next_entry == last_entry + builder.assign( + &last_count_per_unique_entry, + last_count_per_unique_entry + Usize::from(1), + ); + }); + builder + .if_ne(last_entry.clone(), next_entry.clone()) + .then(|builder| { + // next_entry < last_entry + builder.assert_less_than_slow_small_rhs(next_entry.clone(), last_entry.clone()); + + // Update count_per_unique_entry + builder.set( + &count_per_unique_entry, + last_unique_entry_index, + last_count_per_unique_entry, + ); + builder.assign(&last_entry, next_entry.clone()); + builder.assign( + &last_unique_entry_index, + last_unique_entry_index + Usize::from(1), + ); + builder.assign(&last_count_per_unique_entry, Usize::from(1)); + }); + + builder.set_value(&entries_order, i, next_order); + }); + + // Final check on num_unique_entries and count_per_unique_entry + builder.set( + &count_per_unique_entry, + last_unique_entry_index, + last_count_per_unique_entry, + ); + builder.assign( + &last_unique_entry_index, + last_unique_entry_index + Usize::from(1), + ); + builder.assert_var_eq(last_unique_entry_index, num_unique_entries); + + (entries_order, num_unique_entries, count_per_unique_entry) +} + +pub fn codeword_fold_with_challenge( + builder: &mut Builder, + left: Ext, + right: Ext, + challenge: Ext, + coeff: Felt, + inv_2: Felt, +) -> Ext { + // original (left, right) = (lo + hi*x, lo - hi*x), lo, hi are codeword, but after times x it's not codeword + // recover left & right codeword via (lo, hi) = ((left + right) / 2, (left - right) / 2x) + let lo: Ext = builder.eval((left + right) * inv_2); + let hi: Ext = builder.eval((left - right) * coeff); + // e.g. coeff = (2 * dit_butterfly)^(-1) in rs code + // we do fold on (lo, hi) to get folded = (1-r) * lo + r * hi + // (with lo, hi are two codewords), as it match perfectly with raw message in + // lagrange domain fixed variable + let ret: Ext = builder.eval(lo + challenge * (hi - lo)); + ret +} diff --git a/src/e2e/mod.rs b/src/e2e/mod.rs index 101eacc..505c217 100644 --- a/src/e2e/mod.rs +++ b/src/e2e/mod.rs @@ -400,6 +400,23 @@ pub fn parse_zkvm_proof_import( serde_json::from_value(serde_json::to_value(zkvm_proof.witin_commit).unwrap()).unwrap(); let fixed_commit = verifier.vk.fixed_commit.clone(); + let pcs_proof = zkvm_proof.fixed_witin_opening_proof; + + // let query_phase_verifier_input = QueryPhaseVerifierInput { + // max_num_var, + // indices, + // final_message, + // batch_coeffs, + // queries, + // fixed_comm, + // witin_comm, + // circuit_meta, + // commits: pcs_proof.commits, + // fold_challenges, + // sumcheck_messages: pcs_proof.sumcheck_proof.unwrap(), + // point_evals, + // }; + ( ZKVMProofInput { raw_pi, @@ -409,6 +426,7 @@ pub fn parse_zkvm_proof_import( witin_commit, fixed_commit, num_instances: zkvm_proof.num_instances.clone(), + // query_phase_verifier_input, }, proving_sequence, ) diff --git a/src/lib.rs b/src/lib.rs index a48c288..04165c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ mod arithmetics; +mod basefold_verifier; pub mod constants; mod tower_verifier; mod transcript; diff --git a/src/tower_verifier/binding.rs b/src/tower_verifier/binding.rs index 9f96304..5fd52bd 100644 --- a/src/tower_verifier/binding.rs +++ b/src/tower_verifier/binding.rs @@ -11,6 +11,7 @@ pub type InnerConfig = AsmConfig; use openvm_stark_sdk::p3_baby_bear::BabyBear; use p3_field::extension::BinomialExtensionField; +use serde::Deserialize; #[derive(DslVariable, Clone)] pub struct PointVariable { @@ -46,8 +47,9 @@ pub struct TowerVerifierInputVariable { pub logup_specs_eval: Array>>>, } +#[derive(Clone, Deserialize)] pub struct Point { - pub fs: Vec, + pub fs: Vec, } impl Hintable for Point { type HintVariable = PointVariable; @@ -66,10 +68,42 @@ impl Hintable for Point { } impl VecAutoHintable for Point {} -#[derive(Debug)] +pub struct PointAndEval { + pub point: Point, + pub eval: E, +} +impl Hintable for PointAndEval { + type HintVariable = PointAndEvalVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let point = Point::read(builder); + let eval = E::read(builder); + PointAndEvalVariable { point, eval } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(self.point.write()); + stream.extend(self.eval.write()); + stream + } +} +impl VecAutoHintable for PointAndEval {} + +#[derive(Debug, Deserialize)] pub struct IOPProverMessage { pub evaluations: Vec, } + +use ceno_sumcheck::structs::IOPProverMessage as InnerIOPProverMessage; +impl From> for IOPProverMessage { + fn from(value: InnerIOPProverMessage) -> Self { + IOPProverMessage { + evaluations: value.evaluations, + } + } +} + impl Hintable for IOPProverMessage { type HintVariable = IOPProverMessageVariable; diff --git a/src/tower_verifier/program.rs b/src/tower_verifier/program.rs index 815decb..f8e6e3c 100644 --- a/src/tower_verifier/program.rs +++ b/src/tower_verifier/program.rs @@ -14,6 +14,77 @@ use openvm_native_recursion::challenger::{ }; use p3_field::FieldAlgebra; +pub(crate) fn interpolate_uni_poly( + builder: &mut Builder, + p_i: &Array>, + eval_at: Ext, +) -> Ext { + let len = p_i.len(); + let evals: Array> = builder.dyn_array(len.clone()); + let prod: Ext = builder.eval(eval_at); + + builder.set(&evals, 0, eval_at); + + // `prod = \prod_{j} (eval_at - j)` + let e: Ext = builder.constant(C::EF::ONE); + let one: Ext = builder.constant(C::EF::ONE); + builder.range(1, len.clone()).for_each(|i_vec, builder| { + let i = i_vec[0]; + let tmp: Ext = builder.constant(C::EF::ONE); + builder.assign(&tmp, eval_at - e); + builder.set(&evals, i, tmp); + builder.assign(&prod, prod * tmp); + builder.assign(&e, e + one); + }); + + let denom_up: Ext = builder.constant(C::EF::ONE); + let i: Ext = builder.constant(C::EF::ONE); + builder.assign(&i, i + one); + builder.range(2, len.clone()).for_each(|_i_vec, builder| { + builder.assign(&denom_up, denom_up * i); + builder.assign(&i, i + one); + }); + let denom_down: Ext = builder.constant(C::EF::ONE); + + let idx_vec_len: RVar = builder.eval_expr(len.clone() - RVar::from(1)); + let idx_vec: Array> = builder.dyn_array(idx_vec_len); + let idx_val: Ext = builder.constant(C::EF::ONE); + builder.range(0, idx_vec.len()).for_each(|i_vec, builder| { + builder.set(&idx_vec, i_vec[0], idx_val); + builder.assign(&idx_val, idx_val + one); + }); + let idx_rev = reverse(builder, &idx_vec); + let res = builder.constant(C::EF::ZERO); + + let len_f = idx_val.clone(); + let neg_one: Ext = builder.constant(C::EF::NEG_ONE); + let evals_rev = reverse(builder, &evals); + let p_i_rev = reverse(builder, &p_i); + + let mut idx_pos: RVar = builder.eval_expr(len.clone() - RVar::from(1)); + iter_zip!(builder, idx_rev, evals_rev, p_i_rev).for_each(|ptr_vec, builder| { + let idx = builder.iter_ptr_get(&idx_rev, ptr_vec[0]); + let eval = builder.iter_ptr_get(&evals_rev, ptr_vec[1]); + let up_eval_inv: Ext = builder.eval(denom_up * eval); + builder.assign(&up_eval_inv, up_eval_inv.inverse()); + let p = builder.iter_ptr_get(&p_i_rev, ptr_vec[2]); + + builder.assign(&res, res + p * prod * denom_down * up_eval_inv); + builder.assign(&denom_up, denom_up * (len_f - idx) * neg_one); + builder.assign(&denom_down, denom_down * idx); + + idx_pos = builder.eval_expr(idx_pos - RVar::from(1)); + }); + + let p_i_0 = builder.get(&p_i, 0); + let eval_0 = builder.get(&evals, 0); + let up_eval_inv: Ext = builder.eval(denom_up * eval_0); + builder.assign(&up_eval_inv, up_eval_inv.inverse()); + builder.assign(&res, res + p_i_0 * prod * denom_down * up_eval_inv); + + res +} + // Interpolate a uni-variate degree-`p_i.len()-1` polynomial and evaluate this // polynomial at `eval_at`: // diff --git a/src/zkvm_verifier/binding.rs b/src/zkvm_verifier/binding.rs index e0e3725..21cdee2 100644 --- a/src/zkvm_verifier/binding.rs +++ b/src/zkvm_verifier/binding.rs @@ -1,4 +1,7 @@ use crate::arithmetics::next_pow2_instance_padding; +use crate::basefold_verifier::query_phase::{ + QueryPhaseVerifierInput, QueryPhaseVerifierInputVariable, +}; use crate::{ arithmetics::ceil_log2, tower_verifier::binding::{IOPProverMessage, IOPProverMessageVariable}, @@ -37,6 +40,8 @@ pub struct ZKVMProofInputVariable { pub fixed_commit_trivial_commits: Array>>, pub fixed_commit_log2_max_codeword_size: Felt, pub num_instances: Array>>, + + pub query_phase_verifier_input: QueryPhaseVerifierInputVariable, } #[derive(DslVariable, Clone)] @@ -106,6 +111,7 @@ pub(crate) struct ZKVMProofInput { pub witin_commit: BasefoldCommitment, pub fixed_commit: Option>, pub num_instances: Vec<(usize, usize)>, + // pub query_phase_verifier_input: QueryPhaseVerifierInput, } impl Hintable for ZKVMProofInput { type HintVariable = ZKVMProofInputVariable; @@ -128,6 +134,8 @@ impl Hintable for ZKVMProofInput { let num_instances = Vec::>::read(builder); + let query_phase_verifier_input = QueryPhaseVerifierInput::read(builder); + ZKVMProofInputVariable { raw_pi, raw_pi_num_variables, @@ -142,6 +150,7 @@ impl Hintable for ZKVMProofInput { fixed_commit_trivial_commits, fixed_commit_log2_max_codeword_size, num_instances, + query_phase_verifier_input, } } @@ -226,6 +235,8 @@ impl Hintable for ZKVMProofInput { } stream.extend(num_instances_vec.write()); + // stream.extend(self.query_phase_verifier_input.write()); + stream } }