diff --git a/Cargo.lock b/Cargo.lock index 733681e..46b19bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,9 +24,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aes" @@ -215,7 +215,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -241,7 +241,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -291,7 +291,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -390,7 +390,7 @@ checksum = "42b6b4cb608b8282dc3b53d0f4c9ab404655d562674c682db7e6c0458cc83c23" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -508,14 +508,14 @@ checksum = "efb7846e0cb180355c2dec69e721edafa36919850f1a9f52ffba4ebc0393cb71" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] name = "bytemuck" -version = "1.23.1" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" [[package]] name = "byteorder" @@ -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#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "glob", ] @@ -589,13 +589,14 @@ dependencies = [ "serde", "serde_json", "sumcheck", + "tracing", "transcript", ] [[package]] name = "ceno_emul" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "anyhow", "ceno_rt", @@ -616,7 +617,7 @@ dependencies = [ [[package]] name = "ceno_host" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "anyhow", "ceno_emul", @@ -629,7 +630,7 @@ dependencies = [ [[package]] name = "ceno_rt" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "getrandom 0.2.16", "rkyv", @@ -638,7 +639,7 @@ dependencies = [ [[package]] name = "ceno_zkvm" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "base64", "bincode", @@ -679,9 +680,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "ciborium" @@ -722,9 +723,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.40" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" dependencies = [ "clap_builder", "clap_derive", @@ -732,9 +733,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.40" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" dependencies = [ "anstream", "anstyle", @@ -744,21 +745,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.40" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" @@ -922,7 +923,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -933,7 +934,7 @@ checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -946,7 +947,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -966,7 +967,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", "unicode-xid", ] @@ -1017,7 +1018,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -1061,7 +1062,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -1073,7 +1074,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -1150,7 +1151,7 @@ dependencies = [ [[package]] name = "ff_ext" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "p3", "rand_core", @@ -1209,7 +1210,7 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -1233,7 +1234,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -1412,9 +1413,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" [[package]] name = "hex" @@ -1611,9 +1612,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memuse" @@ -1669,9 +1670,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.9" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] @@ -1679,7 +1680,7 @@ dependencies = [ [[package]] name = "mpcs" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "aes", "bincode", @@ -1709,7 +1710,7 @@ dependencies = [ [[package]] name = "multilinear_extensions" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "ff_ext", "itertools 0.13.0", @@ -1737,7 +1738,7 @@ checksum = "0ac7d860b767c6398e88fe93db73ce53eb496057aa6895ffa4d60cb02e1d1c6b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -1818,7 +1819,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -1960,7 +1961,7 @@ source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_mul dependencies = [ "itertools 0.14.0", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -1985,7 +1986,7 @@ source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_mul dependencies = [ "itertools 0.14.0", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -1995,7 +1996,7 @@ source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_mul dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -2021,7 +2022,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.102", + "syn 2.0.101", ] [[package]] @@ -2079,7 +2080,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.102", + "syn 2.0.101", ] [[package]] @@ -2274,7 +2275,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p3" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "p3-baby-bear 0.1.0 (git+https://github.com/scroll-tech/plonky3?rev=20c3cb9)", "p3-challenger 0.1.0 (git+https://github.com/scroll-tech/plonky3?rev=20c3cb9)", @@ -3065,7 +3066,7 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "poseidon" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "criterion", "ff_ext", @@ -3126,7 +3127,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -3155,20 +3156,20 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] name = "quanta" -version = "0.12.6" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" +checksum = "3bd1fe6824cea6538803de3ff1bc0cf3949024db3d43c9643024bfb33a807c0e" dependencies = [ "crossbeam-utils", "libc", "once_cell", "raw-cpuid", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", "web-sys", "winapi", ] @@ -3364,7 +3365,7 @@ checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -3390,9 +3391,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -3522,7 +3523,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -3643,7 +3644,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -3668,7 +3669,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "sumcheck" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "crossbeam-channel", "ff_ext", @@ -3685,14 +3686,14 @@ dependencies = [ [[package]] name = "sumcheck_macro" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "itertools 0.13.0", "p3", "proc-macro2", "quote", "rand", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -3708,9 +3709,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.102" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -3764,7 +3765,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -3874,7 +3875,7 @@ dependencies = [ "serde_spanned", "toml_datetime", "toml_write", - "winnow 0.7.11", + "winnow 0.7.10", ] [[package]] @@ -3902,7 +3903,7 @@ checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -3960,7 +3961,7 @@ dependencies = [ [[package]] name = "transcript" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "crossbeam-channel", "ff_ext", @@ -4054,9 +4055,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" @@ -4089,7 +4090,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", "wasm-bindgen-shared", ] @@ -4111,7 +4112,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4138,7 +4139,7 @@ dependencies = [ [[package]] name = "whir" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "bincode", "blake2", @@ -4284,9 +4285,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.11" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] @@ -4303,7 +4304,7 @@ dependencies = [ [[package]] name = "witness" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#ea8fd863f96f6bbc6bb0e7f4cc8de5b127a37e56" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "ff_ext", "multilinear_extensions", @@ -4339,7 +4340,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] @@ -4359,7 +4360,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.101", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6c8b600..48f5fc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", ta rand = { version = "0.8.5", default-features = false } itertools = { version = "0.13.0", default-features = false } bincode = "1" +tracing = "0.1.40" # Plonky3 p3-air = { git = "https://github.com/Plonky3/Plonky3.git", rev = "1ba4e5c" } diff --git a/src/arithmetics/mod.rs b/src/arithmetics/mod.rs index e262d9f..8548ccc 100644 --- a/src/arithmetics/mod.rs +++ b/src/arithmetics/mod.rs @@ -36,6 +36,7 @@ pub fn _print_usize_arr(builder: &mut Builder, arr: &Array(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 @@ -103,20 +104,19 @@ pub fn dot_product( acc } -pub fn dot_product_pt_n_eval( +pub fn fixed_dot_product( builder: &mut Builder, - pt_and_eval: &Array>, + a: &[Ext], b: &Array>, + zero: Ext, ) -> Ext<::F, ::EF> { - 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); - }); + // 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 } @@ -175,16 +175,18 @@ pub fn eq_eval( builder: &mut Builder, x: &Array>, y: &Array>, + one: Ext, + zero: Ext, ) -> Ext { - let acc: Ext = builder.constant(C::EF::ONE); + let acc: Ext = builder.eval(zero + one); // simple trick to use AddE iter_zip!(builder, x, y).for_each(|idx_vec, builder| { let ptr_x = idx_vec[0]; let ptr_y = idx_vec[1]; let v_x = builder.iter_ptr_get(&x, ptr_x); let v_y = builder.iter_ptr_get(&y, ptr_y); + // x*y + (1-x)*(1-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); }); @@ -220,29 +222,21 @@ pub fn sum( acc } -// Join two arrays -pub fn join( +// Extend an array by one element +pub fn extend( builder: &mut Builder, - a: &Array>, - b: &Array>, + arr: &Array>, + elem: &Ext, ) -> Array> { - 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); + let new_len: Var = builder.eval(arr.len() + C::N::ONE); + let out = builder.dyn_array(new_len); - builder.range(0, a_len.clone()).for_each(|i_vec, builder| { + builder.range(0, arr.len()).for_each(|i_vec, builder| { let i = i_vec[0]; - 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); + let val = builder.get(arr, i); + builder.set_value(&out, i, val); }); + builder.set_value(&out, arr.len(), elem.clone()); out } @@ -730,7 +724,7 @@ impl UniPolyExtrapolator { } pub fn extrapolate_uni_poly(&mut self, builder: &mut Builder, p_i: &Array>, eval_at: Ext) -> Ext { - let res: Ext = builder.constant(C::EF::ZERO); + let res: Ext = builder.eval(self.constants[0] + self.constants[0]); builder.if_eq(p_i.len(), Usize::from(4)).then_or_else(|builder| { let ext = self.extrapolate_uni_poly_deg_3(builder, p_i, eval_at); @@ -767,8 +761,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.inverse()); - let t1: Ext = builder.eval(self.constants[1] * p_i_1 * d1.inverse()); + let t0: Ext = builder.eval(self.constants[5] * p_i_0 / d0); + let t1: Ext = builder.eval(self.constants[1] * p_i_1 / d1); builder.eval(l * (t0 + t1)) } @@ -787,9 +781,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.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()); + 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); builder.eval(l * (t0 + t1 + t2)) } @@ -811,10 +805,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.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()); + 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); builder.eval(l * (t0 + t1 + t2 + t3)) } @@ -839,12 +833,12 @@ 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.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()); + 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); builder.eval(l * (t0 + t1 + t2 + t3 + t4)) } -} \ No newline at end of file +} diff --git a/src/e2e/mod.rs b/src/e2e/mod.rs index f69d9ed..d54ecb2 100644 --- a/src/e2e/mod.rs +++ b/src/e2e/mod.rs @@ -17,6 +17,7 @@ use openvm_native_compiler::{ }; use openvm_native_recursion::hints::Hintable; use openvm_stark_backend::config::StarkGenericConfig; +use openvm_stark_sdk::config::setup_tracing_with_log_level; use openvm_stark_sdk::{ config::baby_bear_poseidon2::BabyBearPoseidon2Config, p3_baby_bear::BabyBear, }; @@ -415,6 +416,7 @@ pub fn parse_zkvm_proof_import( #[test] pub fn test_zkvm_proof_verifier_from_bincode_exports() { + setup_tracing_with_log_level(tracing::Level::WARN); let proof_path = "./src/e2e/encoded/proof.bin"; let vk_path = "./src/e2e/encoded/vk.bin"; @@ -483,4 +485,4 @@ pub fn test_zkvm_proof_verifier_from_bincode_exports() { for (i, seg) in res.iter().enumerate() { println!("=> segment {:?} metrics: {:?}", i, seg.metrics); } -} \ No newline at end of file +} diff --git a/src/tower_verifier/program.rs b/src/tower_verifier/program.rs index 019ae19..815decb 100644 --- a/src/tower_verifier/program.rs +++ b/src/tower_verifier/program.rs @@ -2,9 +2,8 @@ use super::binding::{ IOPProverMessageVariable, PointAndEvalVariable, PointVariable, TowerVerifierInputVariable, }; use crate::arithmetics::{ - challenger_multi_observe, dot_product, dot_product_pt_n_eval, eq_eval, evaluate_at_point, - exts_to_felts, gen_alpha_pows, is_smaller_than, join, product, reverse, - UniPolyExtrapolator, + challenger_multi_observe, dot_product, eq_eval, evaluate_at_point, extend, exts_to_felts, + fixed_dot_product, gen_alpha_pows, is_smaller_than, reverse, UniPolyExtrapolator, }; use crate::transcript::transcript_observe_label; use openvm_native_compiler::prelude::*; @@ -20,77 +19,6 @@ use p3_field::FieldAlgebra; // // \sum_{i=0}^len p_i * (\prod_{j!=i} (eval_at - j)/(i-j) ) // -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 -} - pub(crate) fn interpolate_uni_poly_with_weights( builder: &mut Builder, p_i: &Array>, @@ -143,23 +71,27 @@ pub fn iop_verifier_state_verify( Array::F, ::EF>>, Ext<::F, ::EF>, ) { + // TODO: either store it in a global cache or pass them as parameters + let zero: Ext = builder.constant(C::EF::ZERO); + let max_num_variables_usize: Usize = Usize::from(builder.cast_felt_to_var(max_num_variables.clone())); challenger.observe(builder, max_num_variables); challenger.observe(builder, max_degree); - let one: Ext = builder.constant(C::EF::ONE); - let round: Ext = builder.constant(C::EF::ONE); + builder.assert_var_eq(max_num_variables_usize.get_var(), prover_messages.len()); + let challenges: Array> = builder.dyn_array(max_num_variables_usize.clone()); + let expected: Ext = builder.eval(out_claim.clone() + zero); + builder.cycle_tracker_start("IOPVerifierState::verify_round_and_update_state"); builder .range(0, max_num_variables_usize.clone()) .for_each(|i_vec, builder| { let i = i_vec[0]; + // TODO: this takes 7 cycles, can we optimize it? let prover_msg = builder.get(&prover_messages, i); - builder.cycle_tracker_start("IOPVerifierState::verify_round_and_update_state"); - unsafe { let prover_msg_felts = exts_to_felts(builder, &prover_msg.evaluations); challenger_multi_observe(builder, challenger, &prover_msg_felts); @@ -168,50 +100,21 @@ pub fn iop_verifier_state_verify( transcript_observe_label(builder, challenger, b"Internal round"); let challenge = challenger.sample_ext(builder); - builder.set(&challenges, i, challenge); - builder.assign(&round, round + one); - builder.cycle_tracker_end("IOPVerifierState::verify_round_and_update_state"); - }); - - builder.cycle_tracker_start("IOPVerifierState::check_and_generate_subclaim"); - // set `expected` to P(r)` - let expected_len: RVar<_> = builder.eval_expr(max_num_variables_usize.clone() + RVar::from(1)); - let expected_vec: Array> = builder.dyn_array(expected_len.clone()); - builder.set(&expected_vec, 0, out_claim.clone()); + let e1 = builder.get(&prover_msg.evaluations, 0); + let e2 = builder.get(&prover_msg.evaluations, 1); + let target: Ext<::F, ::EF> = builder.eval(e1 + e2); + builder.assert_ext_eq(expected, target); - let truncated_expected_vec = expected_vec.slice(builder, 1, expected_len); - iter_zip!(builder, prover_messages, challenges, truncated_expected_vec).for_each( - |idx_vec, builder| { - let poly_ptr = idx_vec[0]; - let c_ptr = idx_vec[1]; - - let msg = builder.iter_ptr_get(&prover_messages, poly_ptr); - let c = builder.iter_ptr_get(&challenges, c_ptr); - - let expected_ptr = idx_vec[2]; - let expected = unipoly_extrapolator.extrapolate_uni_poly( + let p_r = unipoly_extrapolator.extrapolate_uni_poly( builder, - &msg.evaluations, - c, + &prover_msg.evaluations, + challenge, ); - builder.iter_ptr_set(&truncated_expected_vec, expected_ptr, expected); - }, - ); - // l-append asserted_sum to the first position of the expected vector - iter_zip!(builder, prover_messages, expected_vec).for_each(|idx_vec, builder| { - let msg = builder.iter_ptr_get(&prover_messages, idx_vec[0]); - let expected = builder.iter_ptr_get(&expected_vec, idx_vec[1]); - - let e1 = builder.get(&msg.evaluations, 0); - let e2 = builder.get(&msg.evaluations, 1); - let target: Ext<::F, ::EF> = builder.eval(e1 + e2); - - builder.assert_ext_eq(expected, target); - }); - - let expected = builder.get(&expected_vec, max_num_variables_usize); - builder.cycle_tracker_end("IOPVerifierState::check_and_generate_subclaim"); + builder.assign(&expected, p_r + zero); + builder.set_value(&challenges, i, challenge); + }); + builder.cycle_tracker_end("IOPVerifierState::verify_round_and_update_state"); (challenges, expected) } @@ -232,6 +135,9 @@ pub fn verify_tower_proof( let num_prod_spec = tower_verifier_input.prod_out_evals.len(); let num_logup_spec = tower_verifier_input.logup_out_evals.len(); + let one: Ext = builder.constant(C::EF::ONE); + let zero: Ext = builder.constant(C::EF::ZERO); + builder.assert_usize_eq( tower_verifier_input.prod_specs_eval.len(), num_prod_spec.clone(), @@ -256,17 +162,28 @@ pub fn verify_tower_proof( builder.assert_usize_eq(evals.len(), RVar::from(4)); }); - let alpha_len: Usize = - builder.eval(num_prod_spec.clone() + num_logup_spec.clone() + num_logup_spec.clone()); + let num_specs: Var = builder.eval(num_prod_spec.get_var() + num_logup_spec.get_var()); + let var_zero: Var = builder.constant(C::N::ZERO); + let var_one: Var = builder.constant(C::N::ONE); + + let should_skip: Array> = builder.dyn_array(num_specs); + builder.range(0, num_specs).for_each(|i_vec, builder| { + let i = i_vec[0]; + + // all specs should not be skipped initially + builder.set_value(&should_skip, i, var_zero.clone()); + }); transcript_observe_label(builder, challenger, b"combine subset evals"); - let alpha_pows = gen_alpha_pows(builder, challenger, alpha_len.clone()); + let alpha = challenger.sample_ext(builder); + let alpha_acc: Ext = builder.eval(zero + one); // initial_claim = \sum_j alpha^j * out_j[rt] // out_j[rt] := (record_{j}[rt]) // out_j[rt] := (logup_p{j}[rt]) // out_j[rt] := (logup_q{j}[rt]) let log2_num_fanin = 1usize; + builder.cycle_tracker_start("initial sum"); let initial_rt: Array> = builder.dyn_array(RVar::from(log2_num_fanin)); transcript_observe_label(builder, challenger, b"product_sum"); builder @@ -274,7 +191,7 @@ pub fn verify_tower_proof( .for_each(|idx_vec, builder| { let idx = idx_vec[0]; let c = challenger.sample_ext(builder); - builder.set(&initial_rt, idx, c); + builder.set_value(&initial_rt, idx, c); }); let prod_spec_point_n_eval: Array> = @@ -363,13 +280,23 @@ pub fn verify_tower_proof( builder.set(&interleaved_point_n_eval, q_i, q); }); - let alpha_prod_slice = alpha_pows.slice(builder, 0, num_prod_spec.clone()); - let prod_sub_sum = dot_product_pt_n_eval(builder, &prod_spec_point_n_eval, &alpha_prod_slice); - let alpha_logup_slice = alpha_pows.slice(builder, num_prod_spec.clone(), alpha_len.clone()); - let logup_sub_sum = - dot_product_pt_n_eval(builder, &interleaved_point_n_eval, &alpha_logup_slice); - let initial_claim: Ext = builder.constant(C::EF::ZERO); - builder.assign(&initial_claim, prod_sub_sum + logup_sub_sum); + let mut initial_claim: Ext = builder.eval(zero + zero); + + iter_zip!(builder, prod_spec_point_n_eval).for_each(|ptr_vec, builder| { + let ptr = ptr_vec[0]; + let prod_eval = builder.iter_ptr_get(&prod_spec_point_n_eval, ptr); + builder.assign(&initial_claim, initial_claim + prod_eval.eval * alpha_acc); + builder.assign(&alpha_acc, alpha_acc * alpha); + }); + + iter_zip!(builder, interleaved_point_n_eval).for_each(|ptr_vec, builder| { + let ptr = ptr_vec[0]; + let logup_eval = builder.iter_ptr_get(&interleaved_point_n_eval, ptr); + builder.assign(&initial_claim, initial_claim + logup_eval.eval * alpha_acc); + builder.assign(&alpha_acc, alpha_acc * alpha); + }); + + builder.cycle_tracker_end("initial sum"); let curr_pt = initial_rt.clone(); let curr_eval = initial_claim.clone(); @@ -399,6 +326,7 @@ pub fn verify_tower_proof( let max_degree = builder.constant(C::F::from_canonical_usize(3)); + builder.cycle_tracker_start("sumcheck verify"); let (sub_rt, sub_e) = iop_verifier_state_verify( builder, challenger, @@ -408,37 +336,53 @@ pub fn verify_tower_proof( max_degree, unipoly_extrapolator, ); + builder.cycle_tracker_end("sumcheck verify"); + + builder.cycle_tracker_start("check expected evaluation"); + let eq_e = eq_eval(builder, &out_rt, &sub_rt, one, zero); + + let expected_evaluation: Ext = builder.eval(zero + zero); + let alpha_acc: Ext = builder.eval(zero + one); - let expected_evaluation: Ext = builder.constant(C::EF::ZERO); builder .range(0, num_prod_spec.clone()) .for_each(|i_vec, builder| { + builder.cycle_tracker_start("accumulate expected eval for prod specs"); let spec_index = i_vec[0]; - let eq_e = eq_eval(builder, &out_rt, &sub_rt); - let alpha = builder.get(&alpha_pows, spec_index.clone()); + let skip = builder.get(&should_skip, spec_index.clone()); let max_round = builder.get(&tower_verifier_input.num_variables, spec_index); let round_limit: RVar = builder.eval_expr(max_round - RVar::from(1)); - let prod: Ext = builder.constant(C::EF::ZERO); - - let is_smaller = is_smaller_than(builder, round_var, round_limit); - builder.if_eq(is_smaller, RVar::from(1)).then(|builder| { - let prod_slice = - builder.get(&tower_verifier_input.prod_specs_eval, spec_index); - let prod_round_slice = builder.get(&prod_slice, round_var); - let pdt = product(builder, &prod_round_slice); - builder.assign(&prod, pdt); + let prod: Ext = builder.eval(zero + zero); + + // invariant: skip == 0 implies previous round_var is smaller than round_limit. + // + // if skip == 0 and current round_var is also not equal to round_limit, + // then we know round_var is also smaller than round_limit. + builder.if_eq(skip, var_zero.clone()).then(|builder| { + builder.if_ne(round_var, round_limit).then_or_else( + |builder| { + let prod_slice = + builder.get(&tower_verifier_input.prod_specs_eval, spec_index); + let prod_round_slice = builder.get(&prod_slice, round_var); + builder.assign(&prod, one * one); + for j in 0..num_fanin { + let prod_j = builder.get(&prod_round_slice, j); + builder.assign(&prod, prod * prod_j); + } + }, + |builder| { + builder.set_value(&should_skip, spec_index, var_one.clone()); + }, + ); }); - builder.assign( - &expected_evaluation, - expected_evaluation + eq_e * alpha * prod, - ); + builder.assign(&expected_evaluation, expected_evaluation + alpha_acc * prod); + builder.assign(&alpha_acc, alpha_acc * alpha.clone()); + builder.cycle_tracker_end("accumulate expected eval for prod specs"); }); let num_variables_len = tower_verifier_input.num_variables.len(); - let logup_alpha_pows_slice = - alpha_pows.slice(builder, num_prod_spec.clone(), alpha_len.clone()); let logup_num_variables_slice = tower_verifier_input.num_variables.slice( builder, num_prod_spec.clone(), @@ -448,115 +392,127 @@ pub fn verify_tower_proof( builder .range(0, num_logup_spec.clone()) .for_each(|i_vec, builder| { + builder.cycle_tracker_start("accumulate expected eval for logup specs"); let spec_index = i_vec[0]; - let alpha_numerator_idx = builder.eval_expr(spec_index * RVar::from(2)); - let alpha_denominator_idx = - builder.eval_expr(spec_index * RVar::from(2) + RVar::from(1)); let alpha_numerator: Ext<::F, ::EF> = - builder.get(&logup_alpha_pows_slice, alpha_numerator_idx); - let alpha_denominator = - builder.get(&logup_alpha_pows_slice, alpha_denominator_idx); - + builder.eval(alpha_acc * one); + builder.assign(&alpha_acc, alpha_acc * alpha); + let alpha_denominator: Ext = builder.eval(alpha_acc * one); + builder.assign(&alpha_acc, alpha_acc * alpha); + + let idx: Var = + builder.eval(spec_index.variable() + num_prod_spec.get_var()); + let skip = builder.get(&should_skip, idx); let max_round = builder.get(&logup_num_variables_slice, spec_index); let round_limit: RVar = builder.eval_expr(max_round - RVar::from(1)); - let eq_e = eq_eval(builder, &out_rt, &sub_rt); - let prod: Ext = builder.constant(C::EF::ZERO); + let prod: Ext = builder.eval(zero + zero); - let is_smaller = is_smaller_than(builder, round_var, round_limit); - builder.if_eq(is_smaller, RVar::from(1)).then(|builder| { - let prod_slice = - builder.get(&tower_verifier_input.logup_specs_eval, spec_index); - let prod_round_slice = builder.get(&prod_slice, round_var); - - let p1 = builder.get(&prod_round_slice, 0); - let p2 = builder.get(&prod_round_slice, 1); - let q1 = builder.get(&prod_round_slice, 2); - let q2 = builder.get(&prod_round_slice, 3); + builder.if_eq(skip, var_zero).then(|builder| { + builder.if_ne(round_var, round_limit).then_or_else( + |builder| { + let prod_slice = + builder.get(&tower_verifier_input.logup_specs_eval, spec_index); + let prod_round_slice = builder.get(&prod_slice, round_var); - builder.assign( - &prod, - alpha_numerator * (p1 * q2 + p2 * q1) + alpha_denominator * (q1 * q2), + let p1 = builder.get(&prod_round_slice, 0); + let p2 = builder.get(&prod_round_slice, 1); + let q1 = builder.get(&prod_round_slice, 2); + let q2 = builder.get(&prod_round_slice, 3); + builder.assign( + &prod, + alpha_numerator * (p1 * q2 + p2 * q1) + + alpha_denominator * (q1 * q2), + ); + }, + |builder| { + builder.set_value(&should_skip, idx, var_one.clone()); + }, ); }); - builder.assign(&expected_evaluation, expected_evaluation + eq_e * prod); + builder.assign(&expected_evaluation, expected_evaluation + prod); + builder.cycle_tracker_end("accumulate expected eval for logup specs"); }); + builder.assign(&expected_evaluation, expected_evaluation * eq_e); builder.assert_ext_eq(expected_evaluation, sub_e); + builder.cycle_tracker_end("check expected evaluation"); + builder.cycle_tracker_start("derive next layer's expected sum"); // derive single eval // rt' = r_merge || rt // r_merge.len() == ceil_log2(num_product_fanin) transcript_observe_label(builder, challenger, b"merge"); + + builder.cycle_tracker_start("derive rt_prime"); let r_merge = challenger.sample_ext(builder); - let coeffs: Array> = builder.dyn_array(num_fanin); - let one: Ext<::F, ::EF> = builder.constant(C::EF::ONE); let c1: Ext<::F, ::EF> = builder.eval(one - r_merge.clone()); let c2: Ext<::F, ::EF> = builder.eval(r_merge.clone()); - builder.set(&coeffs, 0, c1); - builder.set(&coeffs, 1, c2); + let coeffs = vec![c1, c2]; - let r_merge_arr = builder.dyn_array(RVar::from(1)); - builder.set(&r_merge_arr, 0, r_merge); - let rt_prime = join(builder, &sub_rt, &r_merge_arr); + let rt_prime = extend(builder, &sub_rt, &r_merge); + builder.cycle_tracker_end("derive rt_prime"); // generate next round challenge - let next_alpha_len: Usize = builder - .eval(num_prod_spec.clone() + num_logup_spec.clone() + num_logup_spec.clone()); transcript_observe_label(builder, challenger, b"combine subset evals"); - let next_alpha_pows = gen_alpha_pows(builder, challenger, next_alpha_len.clone()); + let new_alpha = challenger.sample_ext(builder); + builder.assign(&alpha, new_alpha); + builder.assign(&alpha_acc, zero + one); + let next_round = builder.eval_expr(round_var + RVar::from(1)); let next_prod_spec_evals: Ext<::F, ::EF> = - builder.constant(C::EF::ZERO); + builder.eval(zero + zero); // simple trick to avoid AddEI builder .range(0, num_prod_spec.clone()) .for_each(|i_vec, builder| { + builder.cycle_tracker_start("derive next layer for prod specs"); let spec_index = i_vec[0]; - let alpha = builder.get(&next_alpha_pows, spec_index.clone()); - + let skip = builder.get(&should_skip, spec_index.clone()); let max_round = builder.get(&tower_verifier_input.num_variables, spec_index.clone()); let round_limit: RVar = builder.eval_expr(max_round - RVar::from(1)); - let is_smaller = is_smaller_than(builder, round_var, round_limit.clone()); - builder.if_eq(is_smaller, RVar::from(1)).then(|builder| { + // now skip is 0 if and only if current round_var is smaller than round_limit. + builder.if_eq(skip, var_zero.clone()).then(|builder| { let prod_slice = builder.get(&tower_verifier_input.prod_specs_eval, spec_index); let prod_round_slice = builder.get(&prod_slice, round_var); - let evals = dot_product(builder, &prod_round_slice, &coeffs); - - builder.set( - &prod_spec_point_n_eval, - spec_index, - PointAndEvalVariable { - point: PointVariable { - fs: rt_prime.clone(), - }, - eval: evals, - }, - ); + let evals = fixed_dot_product(builder, &coeffs, &prod_round_slice, zero); - let is_next_smaller = is_smaller_than(builder, next_round, round_limit); - builder - .if_eq(is_next_smaller, RVar::from(1)) - .then(|builder| { - let new_subsum: Ext = builder.eval(evals * alpha); + builder.if_ne(next_round, round_limit).then_or_else( + |builder| { + let new_subsum: Ext = builder.eval(evals * alpha_acc); builder.assign( &next_prod_spec_evals, next_prod_spec_evals + new_subsum, ); - }); + }, + // update point and eval only for last layer + |builder| { + builder.set( + &prod_spec_point_n_eval, + spec_index, + PointAndEvalVariable { + point: PointVariable { + fs: rt_prime.clone(), + }, + eval: evals, + }, + ); + }, + ); }); + + builder.assign(&alpha_acc, alpha_acc * alpha.clone()); + builder.cycle_tracker_end("derive next layer for prod specs"); }); let next_logup_spec_evals: Ext<::F, ::EF> = - builder.constant(C::EF::ZERO); - let logup_next_alpha_pows_slice = - next_alpha_pows.slice(builder, num_prod_spec.clone(), next_alpha_len.clone()); + builder.eval(zero + zero); let logup_num_variables_slice = tower_verifier_input.num_variables.slice( builder, num_prod_spec.clone(), @@ -566,20 +522,21 @@ pub fn verify_tower_proof( builder .range(0, num_logup_spec.clone()) .for_each(|i_vec, builder| { + builder.cycle_tracker_start("derive next layer for logup specs"); let spec_index = i_vec[0]; let max_round = builder.get(&logup_num_variables_slice, spec_index); let round_limit: RVar = builder.eval_expr(max_round - RVar::from(1)); + let idx: Var = + builder.eval(spec_index.variable() + num_prod_spec.get_var()); + let skip = builder.get(&should_skip, idx); - let is_smaller = is_smaller_than(builder, round_var, round_limit); - builder.if_eq(is_smaller, RVar::from(1)).then(|builder| { - let alpha_numerator_idx = builder.eval_expr(spec_index * RVar::from(2)); - let alpha_denominator_idx = - builder.eval_expr(spec_index * RVar::from(2) + RVar::from(1)); - let alpha_numerator = - builder.get(&logup_next_alpha_pows_slice, alpha_numerator_idx); - let alpha_denominator = - builder.get(&logup_next_alpha_pows_slice, alpha_denominator_idx); + let alpha_numerator: Ext = builder.eval(alpha_acc * one); + builder.assign(&alpha_acc, alpha_acc * alpha.clone()); + let alpha_denominator: Ext = builder.eval(alpha_acc * one); + builder.assign(&alpha_acc, alpha_acc * alpha.clone()); + // now skip is 0 if and only if current round_var is smaller than round_limit. + builder.if_eq(skip, var_zero).then(|builder| { let prod_slice = builder.get(&tower_verifier_input.logup_specs_eval, spec_index); let prod_round_slice = builder.get(&prod_slice, round_var); @@ -587,60 +544,57 @@ pub fn verify_tower_proof( let p2 = builder.get(&prod_round_slice, 1); let q1 = builder.get(&prod_round_slice, 2); let q2 = builder.get(&prod_round_slice, 3); - let c1 = builder.get(&coeffs, 0); - let c2 = builder.get(&coeffs, 1); let p_eval: Ext<::F, ::EF> = - builder.constant(C::EF::ZERO); + builder.eval(zero + zero); let q_eval: Ext<::F, ::EF> = - builder.constant(C::EF::ZERO); - builder.assign(&p_eval, p1 * c1 + p2 * c2); - builder.assign(&q_eval, q1 * c1 + q2 * c2); - - builder.set( - &logup_spec_p_point_n_eval, - spec_index, - PointAndEvalVariable { - point: PointVariable { - fs: rt_prime.clone(), - }, - eval: p_eval, - }, - ); - builder.set( - &logup_spec_q_point_n_eval, - spec_index, - PointAndEvalVariable { - point: PointVariable { - fs: rt_prime.clone(), - }, - eval: q_eval, - }, - ); + builder.eval(zero + zero); + builder.assign(&p_eval, p1 * coeffs[0] + p2 * coeffs[1]); + builder.assign(&q_eval, q1 * coeffs[0] + q2 * coeffs[1]); - let is_next_smaller = is_smaller_than(builder, next_round, round_limit); - builder - .if_eq(is_next_smaller, RVar::from(1)) - .then(|builder| { + builder.if_ne(next_round, round_limit).then_or_else( + |builder| { builder.assign( &next_logup_spec_evals, next_logup_spec_evals + alpha_numerator * p_eval + alpha_denominator * q_eval, ); - }); - }) + }, + // update point and eval only for last layer + |builder| { + builder.set( + &logup_spec_p_point_n_eval, + spec_index, + PointAndEvalVariable { + point: PointVariable { + fs: rt_prime.clone(), + }, + eval: p_eval, + }, + ); + builder.set( + &logup_spec_q_point_n_eval, + spec_index, + PointAndEvalVariable { + point: PointVariable { + fs: rt_prime.clone(), + }, + eval: q_eval, + }, + ); + }, + ); + }); + builder.cycle_tracker_end("derive next layer for logup specs"); }); - iter_zip!(builder, alpha_pows, next_alpha_pows).for_each(|ptr_vec, builder| { - let new_alpha = builder.iter_ptr_get(&next_alpha_pows, ptr_vec[1]); - builder.iter_ptr_set(&alpha_pows, ptr_vec[0], new_alpha); - }); - builder.assign(&curr_pt, rt_prime.clone()); builder.assign(&curr_eval, next_prod_spec_evals + next_logup_spec_evals); builder.assign(&round, round + C::F::ONE); + builder.cycle_tracker_end("derive next layer's expected sum"); + next_rt = PointAndEvalVariable { point: PointVariable { fs: rt_prime.clone(), @@ -661,14 +615,21 @@ pub fn verify_tower_proof( mod tests { use crate::arithmetics::UniPolyExtrapolator; use crate::tower_verifier::binding::IOPProverMessage; + use crate::tower_verifier::binding::TowerVerifierInput; use crate::tower_verifier::program::iop_verifier_state_verify; - use ceno_mle::mle::DenseMultilinearExtension; + use crate::tower_verifier::program::verify_tower_proof; + use ceno_mle::mle::{DenseMultilinearExtension, IntoMLE, MultilinearExtension}; use ceno_mle::virtual_poly::ArcMultilinearExtension; use ceno_mle::virtual_polys::VirtualPolynomials; use ceno_sumcheck::structs::IOPProverState; use ceno_transcript::BasicTranscript; + use ceno_zkvm::scheme::constants::NUM_FANIN; + use ceno_zkvm::scheme::utils::infer_tower_logup_witness; + use ceno_zkvm::scheme::utils::infer_tower_product_witness; + use ceno_zkvm::structs::TowerProver; use ff_ext::BabyBearExt4; use ff_ext::FieldFrom; + use ff_ext::FromUniformBytes; use itertools::Itertools; use openvm_circuit::arch::SystemConfig; use openvm_circuit::arch::VmExecutor; @@ -682,19 +643,22 @@ mod tests { use openvm_native_compiler::ir::Ext; use openvm_native_compiler::prelude::Felt; use openvm_native_recursion::challenger::duplex::DuplexChallengerVariable; + use openvm_native_recursion::hints::Hintable; + use openvm_stark_sdk::config::setup_tracing_with_log_level; use p3_baby_bear::BabyBear; - use p3_field::Field; use p3_field::extension::BinomialExtensionField; + use p3_field::Field; use p3_field::FieldAlgebra; - use openvm_native_recursion::hints::Hintable; use rand::thread_rng; + type F = BabyBear; + type E = BabyBearExt4; + type EF = BinomialExtensionField; + type C = AsmConfig; + #[test] fn test_simple_sumcheck() { - type F = BabyBear; - type E = BabyBearExt4; - type EF = BinomialExtensionField; - type C = AsmConfig; + setup_tracing_with_log_level(tracing::Level::WARN); let nv = 5; let degree = 3; @@ -710,38 +674,9 @@ mod tests { let mut challenger: DuplexChallengerVariable = DuplexChallengerVariable::new(&mut builder); - let interpolation_weights: Array>> = builder.dyn_array(4); - for deg in 1..=4usize { - let points: Vec = (0..=deg) - .into_iter() - .map(|i| EF::from_canonical_u32(i as u32)) - .collect(); - let weights = points - .iter() - .enumerate() - .map(|(j, point_j)| { - points - .iter() - .enumerate() - .filter(|&(i, _)| (i != j)) - .map(|(_, point_i)| *point_j - *point_i) - .reduce(|acc, value| acc * value) - .unwrap_or(EF::ONE) - .inverse() - }) - .collect::>(); - - let weight_array: Array> = builder.dyn_array(4); - weights.into_iter().enumerate().for_each(|(i, w)| { - let w: Ext = builder.constant(w); - builder.set(&weight_array, i, w); - }); - - builder.set(&interpolation_weights, deg - 1, weight_array); - } - - let mut unipoly_extrapolator = UniPolyExtrapolator::new(&mut builder); + let mut uni_p = UniPolyExtrapolator::new(&mut builder); + builder.cycle_tracker_start("sumcheck verify"); iop_verifier_state_verify( &mut builder, &mut challenger, @@ -749,13 +684,14 @@ mod tests { &prover_msgs, max_num_variables, max_degree, - &mut unipoly_extrapolator, + &mut uni_p, ); + builder.cycle_tracker_end("sumcheck verify"); builder.halt(); // get the assembly code - let options = CompilerOptions::default(); + let options = CompilerOptions::default().with_cycle_tracker(); let mut compiler = AsmCompiler::new(options.word_size); compiler.build(builder.operations); let asm_code = compiler.code(); @@ -827,6 +763,173 @@ mod tests { } } + #[test] + fn test_prod_tower() { + let nv = 5; + let num_prod_specs = 2; + let num_logup_specs = 1; + let mut rng = thread_rng(); + + setup_tracing_with_log_level(tracing::Level::WARN); + + let records: Vec> = (0..num_prod_specs) + .map(|_| { + DenseMultilinearExtension::from_evaluations_ext_vec( + nv - 1, + E::random_vec(1 << (nv - 1), &mut rng), + ) + }) + .collect_vec(); + let denom_records = (0..num_logup_specs) + .map(|_| { + DenseMultilinearExtension::from_evaluations_ext_vec( + nv, + E::random_vec(1 << nv, &mut rng), + ) + }) + .collect_vec(); + + let prod_specs = records + .into_iter() + .map(|record| { + let (first, second) = record + .get_ext_field_vec() + .split_at(record.evaluations().len() / 2); + let last_layer: Vec> = vec![ + first.to_vec().into_mle().into(), + second.to_vec().into_mle().into(), + ]; + assert_eq!(last_layer.len(), NUM_FANIN); + ceno_zkvm::structs::TowerProverSpec { + witness: infer_tower_product_witness(nv - 1, last_layer, NUM_FANIN), + } + }) + .collect_vec(); + + let prod_out_evals = prod_specs + .iter() + .map(|spec| { + spec.witness[0] + .iter() + .map(|mle| cast_vec(mle.get_ext_field_vec().to_vec())[0]) + .collect_vec() + }) + .collect_vec(); + + let logup_specs = denom_records + .into_iter() + .map(|record| { + let (first, second) = record + .get_ext_field_vec() + .split_at(record.evaluations().len() / 2); + let last_layer: Vec> = vec![ + first.to_vec().into_mle().into(), + second.to_vec().into_mle().into(), + ]; + ceno_zkvm::structs::TowerProverSpec { + witness: infer_tower_logup_witness(None, last_layer), + } + }) + .collect_vec(); + + let logup_out_evals = logup_specs + .iter() + .map(|spec| { + spec.witness[0] + .iter() + .map(|mle| cast_vec(mle.get_ext_field_vec().to_vec())[0]) + .collect_vec() + }) + .collect_vec(); + + let num_variables = prod_specs + .iter() + .chain(logup_specs.iter()) + .map(|spec| spec.witness.len()) + .collect_vec(); + + let mut transcript = BasicTranscript::new(&[]); + let (_, tower_proof) = + TowerProver::create_proof(prod_specs, logup_specs, NUM_FANIN, &mut transcript); + + // build program + let mut builder = AsmBuilder::::default(); + + let mut challenger: DuplexChallengerVariable = + DuplexChallengerVariable::new(&mut builder); + + // construct extrapolation weights + let mut uni_p = UniPolyExtrapolator::new(&mut builder); + + assert_eq!(tower_proof.proofs.len(), nv - 1); + let tower_verifier_input_var = TowerVerifierInput::read(&mut builder); + let tower_verifier_input = TowerVerifierInput { + prod_out_evals, + logup_out_evals, + num_variables, + num_fanin: NUM_FANIN, + num_proofs: nv - 1, + num_prod_specs, + num_logup_specs, + _max_num_variables: nv, + proofs: tower_proof + .proofs + .iter() + .map(|layer| { + layer + .iter() + .map(|round| IOPProverMessage { + evaluations: cast_vec(round.evaluations.clone()), + }) + .collect_vec() + }) + .collect_vec(), + prod_specs_eval: tower_proof + .prod_specs_eval + .iter() + .map(|spec| { + spec.iter() + .map(|layer| cast_vec(layer.clone())) + .collect_vec() + }) + .collect_vec(), + logup_specs_eval: tower_proof + .logup_specs_eval + .iter() + .map(|spec| { + spec.iter() + .map(|layer| cast_vec(layer.clone())) + .collect_vec() + }) + .collect_vec(), + }; + verify_tower_proof( + &mut builder, + &mut challenger, + tower_verifier_input_var, + &mut uni_p, + ); + + builder.halt(); + + // prepare input + let mut input_stream = Vec::new(); + input_stream.extend(tower_verifier_input.write()); + + // get the assembly code + let options = CompilerOptions::default().with_cycle_tracker(); + let program = builder.compile_isa_with_options(options); + let system_config = SystemConfig::default() + .with_public_values(4) + .with_max_segment_len((1 << 25) - 100) + .with_profiling(); + let config = NativeConfig::new(system_config, Native); + let executor = VmExecutor::::new(config); + executor + .execute_and_then(program, input_stream, |_, seg| Ok(seg), |err| err) + .unwrap(); + } + fn cast_vec(mut vec: Vec) -> Vec { let length = vec.len(); let capacity = vec.capacity(); diff --git a/src/zkvm_verifier/verifier.rs b/src/zkvm_verifier/verifier.rs index ac477ed..10e768d 100644 --- a/src/zkvm_verifier/verifier.rs +++ b/src/zkvm_verifier/verifier.rs @@ -355,6 +355,7 @@ pub fn verify_opcode_proof( builder.set(&logup_inner_evals, 3, opcode_proof.lk_q2_out_eval); builder.set(&logup_out_evals, 0, logup_inner_evals); + builder.cycle_tracker_start("verify tower proof for opcode"); let (rt_tower, record_evals, logup_p_evals, logup_q_evals) = verify_tower_proof( builder, challenger, @@ -373,6 +374,7 @@ pub fn verify_opcode_proof( }, unipoly_extrapolator, ); + builder.cycle_tracker_end("verify tower proof for opcode"); let rt_non_lc_sumcheck: Array> = rt_tower @@ -429,6 +431,7 @@ pub fn verify_opcode_proof( SEL_DEGREE.max(max_non_lc_degree + 1) as u32, )); + builder.cycle_tracker_start("main sumcheck"); let main_sel_subclaim = iop_verifier_state_verify( builder, challenger, @@ -438,6 +441,7 @@ pub fn verify_opcode_proof( main_sel_subclaim_max_degree, unipoly_extrapolator, ); + builder.cycle_tracker_end("main sumcheck"); let input_opening_point = PointVariable { fs: main_sel_subclaim.0, @@ -755,6 +759,7 @@ pub fn verify_table_proof( let num_logup_specs: Usize = tower_proof.logup_specs_eval.len(); let max_num_variables: Usize = Usize::from(max_expected_rounds); + builder.cycle_tracker_start("verify tower proof"); let (rt_tower, prod_point_and_eval, logup_p_point_and_eval, logup_q_point_and_eval) = verify_tower_proof( builder, @@ -774,6 +779,7 @@ pub fn verify_table_proof( }, unipoly_extrapolator, ); + builder.cycle_tracker_end("verify tower proof"); builder.assert_usize_eq( logup_q_point_and_eval.len(),