diff --git a/.gitignore b/.gitignore index 06e25a0..4e0d6e4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ Cargo.lock vm_run_output.log *.bin -.DS_Store \ No newline at end of file +.DS_Store +*.log \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 150ad14..e0ca1cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,14 +41,14 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", "once_cell", "version_check", - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -98,36 +98,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys", ] @@ -150,7 +150,7 @@ dependencies = [ "ark-std 0.5.0", "educe", "fnv", - "hashbrown 0.15.3", + "hashbrown 0.15.4", "itertools 0.13.0", "num-bigint 0.4.6", "num-integer", @@ -256,7 +256,7 @@ dependencies = [ "ark-std 0.5.0", "educe", "fnv", - "hashbrown 0.15.3", + "hashbrown 0.15.4", ] [[package]] @@ -334,9 +334,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -411,9 +411,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bitvec" @@ -484,9 +484,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "bytecheck" @@ -537,9 +537,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.21" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" 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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "glob", ] @@ -566,6 +566,7 @@ dependencies = [ "ff_ext", "itertools 0.13.0", "mpcs", + "multilinear_extensions", "openvm", "openvm-circuit", "openvm-native-circuit", @@ -575,6 +576,7 @@ dependencies = [ "openvm-stark-backend", "openvm-stark-sdk", "p3-air", + "p3-baby-bear 0.1.0 (git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c)", "p3-challenger 0.1.0 (git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c)", "p3-commit 0.1.0 (git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c)", "p3-field 0.1.0 (git+https://github.com/Plonky3/Plonky3.git?rev=1ba4e5c)", @@ -586,12 +588,15 @@ dependencies = [ "rand", "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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "anyhow", "ceno_rt", @@ -612,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "anyhow", "ceno_emul", @@ -625,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "getrandom 0.2.16", "rkyv", @@ -634,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "base64", "bincode", @@ -718,9 +723,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.37" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" dependencies = [ "clap_builder", "clap_derive", @@ -728,9 +733,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" dependencies = [ "anstream", "anstyle", @@ -758,9 +763,9 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "constant_time_eq" @@ -1080,9 +1085,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys", @@ -1146,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "p3", "rand_core", @@ -1210,9 +1215,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", @@ -1393,9 +1398,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ "allocator-api2", ] @@ -1408,15 +1413,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" [[package]] name = "hex" @@ -1449,7 +1448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.3", + "hashbrown 0.15.4", ] [[package]] @@ -1467,7 +1466,7 @@ version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.5.0", + "hermit-abi", "libc", "windows-sys", ] @@ -1570,9 +1569,9 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libm" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" @@ -1681,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "aes", "bincode", @@ -1711,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "ff_ext", "itertools 0.13.0", @@ -1843,11 +1842,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", ] @@ -1899,6 +1898,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "oorandom" version = "11.1.5" @@ -1907,8 +1912,8 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "openvm" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "bytemuck", "num-bigint 0.4.6", @@ -1920,8 +1925,8 @@ dependencies = [ [[package]] name = "openvm-circuit" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "backtrace", "cfg-if", @@ -1951,8 +1956,8 @@ dependencies = [ [[package]] name = "openvm-circuit-derive" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "itertools 0.14.0", "quote", @@ -1961,8 +1966,8 @@ dependencies = [ [[package]] name = "openvm-circuit-primitives" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "derive-new 0.6.0", "itertools 0.14.0", @@ -1976,8 +1981,8 @@ dependencies = [ [[package]] name = "openvm-circuit-primitives-derive" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "itertools 0.14.0", "quote", @@ -1987,7 +1992,7 @@ dependencies = [ [[package]] name = "openvm-custom-insn" version = "0.1.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "proc-macro2", "quote", @@ -1996,8 +2001,8 @@ dependencies = [ [[package]] name = "openvm-instructions" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "backtrace", "derive-new 0.6.0", @@ -2013,8 +2018,8 @@ dependencies = [ [[package]] name = "openvm-instructions-derive" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "quote", "syn 2.0.101", @@ -2022,8 +2027,8 @@ dependencies = [ [[package]] name = "openvm-native-circuit" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "derive-new 0.6.0", "derive_more 1.0.0", @@ -2049,8 +2054,8 @@ dependencies = [ [[package]] name = "openvm-native-compiler" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "backtrace", "itertools 0.14.0", @@ -2071,8 +2076,8 @@ dependencies = [ [[package]] name = "openvm-native-compiler-derive" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "quote", "syn 2.0.101", @@ -2080,8 +2085,8 @@ dependencies = [ [[package]] name = "openvm-native-recursion" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "cfg-if", "itertools 0.14.0", @@ -2104,8 +2109,8 @@ dependencies = [ [[package]] name = "openvm-platform" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "getrandom 0.2.16", "libm", @@ -2115,8 +2120,8 @@ dependencies = [ [[package]] name = "openvm-poseidon2-air" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "derivative", "lazy_static", @@ -2132,8 +2137,8 @@ dependencies = [ [[package]] name = "openvm-rv32im-circuit" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "derive-new 0.6.0", "derive_more 1.0.0", @@ -2155,8 +2160,8 @@ dependencies = [ [[package]] name = "openvm-rv32im-guest" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "openvm-custom-insn", "strum_macros", @@ -2164,8 +2169,8 @@ dependencies = [ [[package]] name = "openvm-rv32im-transpiler" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "openvm-instructions", "openvm-instructions-derive", @@ -2240,8 +2245,8 @@ dependencies = [ [[package]] name = "openvm-transpiler" -version = "1.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v1.0.0#f41640c37bc5468a0775a38098053fe37ea3538a" +version = "1.1.0" +source = "git+https://github.com/scroll-tech/openvm.git?branch=feat%2Fnative_multi_observe#ead0b2bea4e5a25083162a40ecde2bfa9ba576f2" dependencies = [ "elf", "eyre", @@ -2270,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +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)", @@ -3054,14 +3059,14 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "poseidon" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "criterion", "ff_ext", @@ -3076,7 +3081,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.25", + "zerocopy", ] [[package]] @@ -3341,7 +3346,7 @@ checksum = "1e147371c75553e1e2fcdb483944a8540b8438c31426279553b9a8182a9b7b65" dependencies = [ "bytecheck", "bytes", - "hashbrown 0.15.3", + "hashbrown 0.15.4", "indexmap", "munge", "ptr_meta", @@ -3426,9 +3431,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -3535,9 +3540,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -3592,9 +3597,9 @@ checksum = "85636c14b73d81f541e525f585c0a2109e6744e1565b5c1668e31c70c10ed65c" [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "spin" @@ -3664,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "crossbeam-channel", "ff_ext", @@ -3681,7 +3686,7 @@ dependencies = [ [[package]] name = "sumcheck_macro" version = "0.1.0" -source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "itertools 0.13.0", "p3", @@ -3721,12 +3726,12 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.19.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", - "getrandom 0.3.2", + "getrandom 0.3.3", "once_cell", "rustix", "windows-sys", @@ -3829,21 +3834,21 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.26", + "toml_edit 0.22.27", ] [[package]] name = "toml_datetime" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] @@ -3861,23 +3866,23 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.26" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", "toml_write", - "winnow 0.7.9", + "winnow 0.7.10", ] [[package]] name = "toml_write" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tracing" @@ -3892,9 +3897,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", @@ -3903,9 +3908,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -3956,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "crossbeam-channel", "ff_ext", @@ -4018,9 +4023,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "valuable" @@ -4130,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "bincode", "blake2", @@ -4276,9 +4285,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] @@ -4295,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#1e677ecf64d5d54f3d93b5ee167ce7811b2dbf36" +source = "git+https://github.com/scroll-tech/ceno.git?branch=feat%2Fexport_ff_ext#5aa4bfe5a4f52871cdabd866668250734f985363" dependencies = [ "ff_ext", "multilinear_extensions", @@ -4314,33 +4323,13 @@ dependencies = [ "tap", ] -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "zerocopy-derive 0.7.35", -] - [[package]] name = "zerocopy" version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ - "zerocopy-derive 0.8.25", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", + "zerocopy-derive", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6735c2d..48f5fc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,21 +4,24 @@ version = "0.1.0" edition = "2021" [dependencies] -openvm = { git = "https://github.com/openvm-org/openvm.git", default-features = false, tag = "v1.0.0" } -openvm-circuit = { git = "https://github.com/openvm-org/openvm.git", default-features = false, tag = "v1.0.0", features = ["bench-metrics"] } -openvm-native-circuit = { git = "https://github.com/openvm-org/openvm.git", default-features = false, tag = "v1.0.0" } -openvm-native-compiler = { git = "https://github.com/openvm-org/openvm.git", default-features = false, tag = "v1.0.0" } -openvm-native-compiler-derive = { git = "https://github.com/openvm-org/openvm.git", default-features = false, tag = "v1.0.0" } -openvm-native-recursion = { git = "https://github.com/openvm-org/openvm.git", default-features = false, tag = "v1.0.0" } +openvm = { git = "https://github.com/scroll-tech/openvm.git", branch = "feat/native_multi_observe", default-features = false } +openvm-circuit = { git = "https://github.com/scroll-tech/openvm.git", branch = "feat/native_multi_observe", default-features = false, features = ["bench-metrics"] } +openvm-native-circuit = { git = "https://github.com/scroll-tech/openvm.git", branch = "feat/native_multi_observe", default-features = false } +openvm-native-compiler = { git = "https://github.com/scroll-tech/openvm.git", branch = "feat/native_multi_observe", default-features = false } +openvm-native-compiler-derive = { git = "https://github.com/scroll-tech/openvm.git", branch = "feat/native_multi_observe", default-features = false } +openvm-native-recursion = { git = "https://github.com/scroll-tech/openvm.git", branch = "feat/native_multi_observe", default-features = false } + openvm-stark-backend = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v1.0.0", default-features = false } openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v1.0.0", default-features = false } 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" } +p3-baby-bear = { git = "https://github.com/Plonky3/Plonky3.git", rev = "1ba4e5c" } p3-field = { git = "https://github.com/Plonky3/Plonky3.git", rev = "1ba4e5c" } p3-commit = { git = "https://github.com/Plonky3/Plonky3.git", rev = "1ba4e5c" } p3-matrix = { git = "https://github.com/Plonky3/Plonky3.git", rev = "1ba4e5c" } @@ -35,9 +38,15 @@ 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" } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" \ No newline at end of file +serde_json = "1.0" + +[features] +bench-metrics = ["openvm-circuit/bench-metrics"] diff --git a/src/arithmetics/mod.rs b/src/arithmetics/mod.rs index f4445e0..ce50fe8 100644 --- a/src/arithmetics/mod.rs +++ b/src/arithmetics/mod.rs @@ -8,7 +8,11 @@ use openvm_native_compiler::prelude::*; use openvm_native_compiler_derive::iter_zip; use openvm_native_recursion::challenger::ChallengerVariable; use p3_field::{FieldAlgebra, FieldExtensionAlgebra}; +use openvm_native_recursion::challenger::{ + duplex::DuplexChallengerVariable, CanObserveVariable, FeltChallenger, +}; type E = BabyBearExt4; +const HASH_RATE: usize = 8; pub fn _print_ext_arr(builder: &mut Builder, arr: &Array>) { iter_zip!(builder, arr).for_each(|ptr_vec, builder| { @@ -17,7 +21,7 @@ pub fn _print_ext_arr(builder: &mut Builder, arr: &Array(builder: &mut Builder, arr: &Array>) { +pub fn print_felt_arr(builder: &mut Builder, arr: &Array>) { iter_zip!(builder, arr).for_each(|ptr_vec, builder| { let f = builder.iter_ptr_get(arr, ptr_vec[0]); builder.print_f(f); @@ -31,6 +35,27 @@ 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 +} + +pub fn challenger_multi_observe( + builder: &mut Builder, + challenger: &mut DuplexChallengerVariable, + arr: &Array> +) { + let input_ptr = builder.poseidon2_multi_observe(&challenger.sponge_state, challenger.input_ptr, challenger.io_full_ptr, &arr); + builder.assign(&challenger.input_ptr, challenger.io_empty_ptr + input_ptr.clone()); + builder.if_ne(input_ptr, Usize::from(0)).then_or_else(|builder| { + builder.assign(&challenger.output_ptr, challenger.io_empty_ptr); + }, |builder| { + builder.assign(&challenger.output_ptr, challenger.io_full_ptr); + }); +} + pub fn is_smaller_than( builder: &mut Builder, left: RVar, @@ -79,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 } @@ -151,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); }); @@ -196,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 } @@ -226,7 +244,7 @@ pub fn join( // Generate alpha power challenges pub fn gen_alpha_pows( builder: &mut Builder, - challenger: &mut impl ChallengerVariable, + challenger: &mut DuplexChallengerVariable, alpha_len: Usize<::N>, ) -> Array> { let alpha = challenger.sample_ext(builder); @@ -250,7 +268,7 @@ pub fn gen_alpha_pows( /// = \sum_{\mathbf{b}=0}^{max_idx} \prod_{i=0}^{n-1} (x_i y_i b_i + (1 - x_i)(1 - y_i)(1 - b_i)) pub fn eq_eval_less_or_equal_than( builder: &mut Builder, - _challenger: &mut impl ChallengerVariable, + _challenger: &mut DuplexChallengerVariable, opcode_proof: &ZKVMOpcodeProofInputVariable, a: &Array>, b: &Array>, diff --git a/src/e2e/mod.rs b/src/e2e/mod.rs index 9af4bc0..f69d9ed 100644 --- a/src/e2e/mod.rs +++ b/src/e2e/mod.rs @@ -10,7 +10,11 @@ use mpcs::BasefoldCommitment; use mpcs::{Basefold, BasefoldRSParams}; use openvm_circuit::arch::{instructions::program::Program, SystemConfig, VmExecutor}; use openvm_native_circuit::{Native, NativeConfig}; -use openvm_native_compiler::{asm::AsmBuilder, conversion::CompilerOptions}; +use openvm_native_compiler::{ + asm::AsmBuilder, + conversion::{CompilerOptions, convert_program}, + prelude::AsmCompiler +}; use openvm_native_recursion::hints::Hintable; use openvm_stark_backend::config::StarkGenericConfig; use openvm_stark_sdk::{ @@ -446,10 +450,19 @@ pub fn test_zkvm_proof_verifier_from_bincode_exports() { witness_stream.extend(zkvm_proof_input.write()); // Compile program - let program: Program< - p3_monty_31::MontyField31, - > =builder.compile_isa_with_options(CompilerOptions::default().with_cycle_tracker()); - + let options = CompilerOptions::default().with_cycle_tracker(); + let mut compiler = AsmCompiler::new(options.word_size); + compiler.build(builder.operations); + let asm_code = compiler.code(); + + // _debug: print out assembly + /* + println!("=> AssemblyCode:"); + println!("{asm_code}"); + return (); + */ + + let program: Program,> = convert_program(asm_code, options); let mut system_config = SystemConfig::default() .with_public_values(4) .with_max_segment_len((1 << 25) - 100); @@ -457,9 +470,6 @@ pub fn test_zkvm_proof_verifier_from_bincode_exports() { let config = NativeConfig::new(system_config, Native); let executor = VmExecutor::::new(config); - - // Alternative execution - // executor.execute(program, witness_stream).unwrap(); let res = executor.execute_and_then( program, @@ -473,4 +483,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/extensions/mod.rs b/src/extensions/mod.rs new file mode 100644 index 0000000..77984e2 --- /dev/null +++ b/src/extensions/mod.rs @@ -0,0 +1,137 @@ +use crate::arithmetics::{challenger_multi_observe, exts_to_felts, print_felt_arr}; +use crate::tower_verifier::binding::IOPProverMessage; +use crate::zkvm_verifier::binding::ZKVMProofInput; +use crate::zkvm_verifier::binding::{ + TowerProofInput, ZKVMOpcodeProofInput, ZKVMTableProofInput, E, F, +}; +use crate::zkvm_verifier::verifier::verify_zkvm_proof; +use ff_ext::BabyBearExt4; +use itertools::Itertools; +use mpcs::BasefoldCommitment; +use mpcs::{Basefold, BasefoldRSParams}; +use openvm_circuit::arch::{instructions::program::Program, SystemConfig, VmExecutor}; +use openvm_native_circuit::{Native, NativeConfig}; +use openvm_native_compiler::{asm::AsmBuilder, conversion::CompilerOptions}; +use openvm_native_recursion::challenger::{self, CanSampleVariable}; +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 openvm_native_compiler::conversion::convert_program; +use std::collections::HashMap; +use std::fs::File; +use std::marker::PhantomData; +use crate::e2e::SubcircuitParams; +use crate::tower_verifier::program::verify_tower_proof; +use crate::transcript::transcript_observe_label; +use crate::{ + arithmetics::{ + build_eq_x_r_vec_sequential, ceil_log2, concat, dot_product as ext_dot_product, + eq_eval_less_or_equal_than, eval_ceno_expr_with_instance, eval_wellform_address_vec, + gen_alpha_pows, max_usize_arr, max_usize_vec, next_pow2_instance_padding, product, + sum as ext_sum, + }, + tower_verifier::{ + binding::{PointVariable, TowerVerifierInputVariable}, + program::iop_verifier_state_verify, + }, +}; +use ceno_zkvm::circuit_builder::SetTableSpec; +use ceno_zkvm::{expression::StructuralWitIn, scheme::verifier::ZKVMVerifier}; +use itertools::interleave; +use itertools::max; +use openvm_native_compiler::prelude::*; +use openvm_native_compiler_derive::iter_zip; +use openvm_native_recursion::challenger::{ + duplex::DuplexChallengerVariable, CanObserveVariable, FeltChallenger, +}; +use p3_field::{Field, FieldAlgebra, FieldExtensionAlgebra}; + +type Pcs = Basefold; +const NUM_FANIN: usize = 2; +const MAINCONSTRAIN_SUMCHECK_BATCH_SIZE: usize = 3; // read/write/lookup +const SEL_DEGREE: usize = 2; + +type SC = BabyBearPoseidon2Config; +type EF = ::Challenge; + +#[test] +pub fn test_native_multi_observe() { + // OpenVM DSL + let mut builder = AsmBuilder::::default(); + + vm_program(&mut builder); + + builder.halt(); + + // Pass in witness stream + let witness_stream: Vec< + Vec>, + > = Vec::new(); + + // Compile program + let options = CompilerOptions::default().with_cycle_tracker(); + let mut compiler = AsmCompiler::new(options.word_size); + compiler.build(builder.operations); + let asm_code = compiler.code(); + let program = convert_program(asm_code, options); + + let mut system_config = SystemConfig::default() + .with_public_values(4) + .with_max_segment_len((1 << 25) - 100); + system_config.profiling = true; + let config = NativeConfig::new(system_config, Native); + + let executor = VmExecutor::::new(config); + + // Alternative execution + // executor.execute(program, witness_stream).unwrap(); + + let res = executor.execute_and_then( + program, + witness_stream, + |_, seg| { + Ok(seg) + }, + |err| err, + ).unwrap(); + + for (i, seg) in res.iter().enumerate() { + println!("=> segment {:?} metrics: {:?}", i, seg.metrics); + } +} + +fn vm_program( + builder: &mut Builder, +) { + let e1: Ext = builder.constant(C::EF::GENERATOR.exp_power_of_2(16)); + let e2: Ext = builder.constant(C::EF::GENERATOR.exp_power_of_2(32)); + let e3: Ext = builder.constant(C::EF::GENERATOR.exp_power_of_2(64)); + let e4: Ext = builder.constant(C::EF::GENERATOR.exp_power_of_2(128)); + let e5: Ext = builder.constant(C::EF::GENERATOR.exp_power_of_2(256)); + let len: usize = 5; + + let e_arr: Array> = builder.dyn_array(len); + builder.set(&e_arr, 0, e1); + builder.set(&e_arr, 1, e2); + builder.set(&e_arr, 2, e3); + builder.set(&e_arr, 3, e4); + builder.set(&e_arr, 4, e5); + + unsafe { + let mut c1 = DuplexChallengerVariable::new(builder); + let mut c2 = DuplexChallengerVariable::new(builder); + + let f_arr1 = exts_to_felts(builder, &e_arr); + let f_arr2 = f_arr1.clone(); + + challenger_multi_observe(builder, &mut c1, &f_arr1); + let test_e1 = c1.sample(builder); + + c2.observe_slice(builder, f_arr2); + let test_e2 = c2.sample(builder); + + builder.assert_felt_eq(test_e1, test_e2); + } +} diff --git a/src/lib.rs b/src/lib.rs index ba742fc..a48c288 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,3 +6,4 @@ pub mod zkvm_verifier; #[allow(dead_code)] mod e2e; +mod extensions; diff --git a/src/tower_verifier/program.rs b/src/tower_verifier/program.rs index 0e271f6..0a140ff 100644 --- a/src/tower_verifier/program.rs +++ b/src/tower_verifier/program.rs @@ -2,13 +2,15 @@ use super::binding::{ IOPProverMessageVariable, PointAndEvalVariable, PointVariable, TowerVerifierInputVariable, }; use crate::arithmetics::{ - dot_product, dot_product_pt_n_eval, eq_eval, evaluate_at_point, gen_alpha_pows, - is_smaller_than, join, product, reverse, + challenger_multi_observe, eq_eval, evaluate_at_point, + extend, exts_to_felts, fixed_dot_product, is_smaller_than, product, reverse, }; use crate::transcript::transcript_observe_label; use openvm_native_compiler::prelude::*; use openvm_native_compiler_derive::iter_zip; -use openvm_native_recursion::challenger::ChallengerVariable; +use openvm_native_recursion::challenger::{ + duplex::DuplexChallengerVariable, CanObserveVariable, FeltChallenger, +}; use p3_field::FieldAlgebra; // Interpolate a uni-variate degree-`p_i.len()-1` polynomial and evaluate this @@ -16,77 +18,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>, @@ -129,7 +60,7 @@ pub(crate) fn interpolate_uni_poly_with_weights( pub fn iop_verifier_state_verify( builder: &mut Builder, - challenger: &mut impl ChallengerVariable, + challenger: &mut DuplexChallengerVariable, out_claim: &Ext, prover_messages: &Array>, max_num_variables: Felt, @@ -146,67 +77,71 @@ pub fn iop_verifier_state_verify( let one: Ext = builder.constant(C::EF::ONE); let round: Ext = builder.constant(C::EF::ONE); - let polynomials_received: Array>> = - builder.dyn_array(max_num_variables_usize.clone()); let challenges: Array> = builder.dyn_array(max_num_variables_usize.clone()); + 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]; let prover_msg = builder.get(&prover_messages, i); - builder.cycle_tracker_start("IOPVerifierState::verify_round_and_update_state"); - iter_zip!(builder, prover_msg.evaluations).for_each(|ptr_vec, builder| { - let e = builder.iter_ptr_get(&prover_msg.evaluations, ptr_vec[0]); - let e_felts = builder.ext2felt(e); - challenger.observe_slice(builder, e_felts); - }); + builder.cycle_tracker_start("multi_observe"); + unsafe { + let prover_msg_felts = exts_to_felts(builder, &prover_msg.evaluations); + challenger_multi_observe(builder, challenger, &prover_msg_felts); + } + builder.cycle_tracker_end("multi_observe"); + builder.cycle_tracker_start("observe round"); transcript_observe_label(builder, challenger, b"Internal round"); + builder.cycle_tracker_end("observe round"); + + builder.cycle_tracker_start("sample_ext"); let challenge = challenger.sample_ext(builder); + builder.cycle_tracker_end("sample_ext"); - builder.set(&challenges, i, challenge); - builder.set(&polynomials_received, i, prover_msg.evaluations); + builder.set_value(&challenges, i, challenge); builder.assign(&round, round + one); - builder.cycle_tracker_end("IOPVerifierState::verify_round_and_update_state"); }); - + 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(polynomials_received.len() + RVar::from(1)); + 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 truncated_expected_vec = expected_vec.slice(builder, 1, expected_len); - iter_zip!( - builder, - polynomials_received, - challenges, - truncated_expected_vec - ) - .for_each(|idx_vec, builder| { - let poly_ptr = idx_vec[0]; - let c_ptr = idx_vec[1]; + 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 evaluations = builder.iter_ptr_get(&polynomials_received, poly_ptr); - let c = builder.iter_ptr_get(&challenges, c_ptr); + 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]; - // _debug - // let expected = interpolate_uni_poly(builder, &evaluations, c); - let expected = interpolate_uni_poly_with_weights(builder, &evaluations, c, interpolation_weights); + let expected_ptr = idx_vec[2]; + builder.cycle_tracker_start("extrapolate_uni_poly"); + let expected = interpolate_uni_poly_with_weights( + builder, + &msg.evaluations, + c, + interpolation_weights, + ); + builder.cycle_tracker_end("extrapolate_uni_poly"); - builder.iter_ptr_set(&truncated_expected_vec, expected_ptr, expected); - }); + 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, polynomials_received, expected_vec).for_each(|idx_vec, builder| { - let evaluations = builder.iter_ptr_get(&polynomials_received, idx_vec[0]); + 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(&evaluations, 0); - let e2 = builder.get(&evaluations, 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); @@ -220,7 +155,7 @@ pub fn iop_verifier_state_verify( pub fn verify_tower_proof( builder: &mut Builder, - challenger: &mut impl ChallengerVariable, + challenger: &mut DuplexChallengerVariable, tower_verifier_input: TowerVerifierInputVariable, interpolation_weights: &Array>>, ) -> ( @@ -234,6 +169,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(), @@ -262,13 +200,15 @@ pub fn verify_tower_proof( builder.eval(num_prod_spec.clone() + num_logup_spec.clone() + num_logup_spec.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 @@ -365,13 +305,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(); @@ -401,6 +351,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, @@ -410,18 +361,25 @@ pub fn verify_tower_proof( max_degree, interpolation_weights, ); + builder.cycle_tracker_end("sumcheck verify"); + + builder.cycle_tracker_start("check expected evaluation"); + builder.cycle_tracker_start("eq_eval"); + let eq_e = eq_eval(builder, &out_rt, &sub_rt, one, zero); + builder.cycle_tracker_end("eq_eval"); + + 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 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 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| { @@ -434,13 +392,13 @@ pub fn verify_tower_proof( builder.assign( &expected_evaluation, - expected_evaluation + eq_e * alpha * prod, + expected_evaluation + eq_e * 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(), @@ -452,19 +410,16 @@ pub fn verify_tower_proof( .for_each(|i_vec, builder| { 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 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| { @@ -487,49 +442,50 @@ pub fn verify_tower_proof( }); 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| { let spec_index = i_vec[0]; - let alpha = builder.get(&next_alpha_pows, 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| { 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); + let evals = fixed_dot_product(builder, &coeffs, &prod_round_slice, zero); builder.set( &prod_spec_point_n_eval, @@ -546,19 +502,19 @@ pub fn verify_tower_proof( builder .if_eq(is_next_smaller, RVar::from(1)) .then(|builder| { - let new_subsum: Ext = builder.eval(evals * alpha); + let new_subsum: Ext = builder.eval(evals * alpha_acc); builder.assign( &next_prod_spec_evals, next_prod_spec_evals + new_subsum, ); }); }); + + builder.assign(&alpha_acc, alpha_acc * alpha.clone()); }); 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(), @@ -574,13 +530,10 @@ pub fn verify_tower_proof( 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()); let prod_slice = builder.get(&tower_verifier_input.logup_specs_eval, spec_index); @@ -589,15 +542,13 @@ 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); 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.assign(&p_eval, p1 * coeffs[0] + p2 * coeffs[1]); + builder.assign(&q_eval, q1 * coeffs[0] + q2 * coeffs[1]); builder.set( &logup_spec_p_point_n_eval, @@ -634,15 +585,12 @@ pub fn verify_tower_proof( }) }); - 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(), @@ -658,3 +606,339 @@ pub fn verify_tower_proof( logup_spec_q_point_n_eval, ) } + +#[cfg(test)] +mod tests { + use crate::tower_verifier::binding::IOPProverMessage; + use crate::tower_verifier::binding::TowerVerifierInput; + use crate::tower_verifier::program::iop_verifier_state_verify; + 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_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; + use openvm_native_circuit::Native; + use openvm_native_circuit::NativeConfig; + use openvm_native_compiler::asm::AsmCompiler; + use openvm_native_compiler::asm::{AsmBuilder, AsmConfig}; + use openvm_native_compiler::conversion::convert_program; + use openvm_native_compiler::conversion::CompilerOptions; + use openvm_native_compiler::ir::Array; + 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::extension::BinomialExtensionField; + use p3_field::Field; + use p3_field::FieldAlgebra; + use rand::thread_rng; + + type F = BabyBear; + type E = BabyBearExt4; + type EF = BinomialExtensionField; + type C = AsmConfig; + + #[test] + fn test_simple_sumcheck() { + setup_tracing_with_log_level(tracing::Level::WARN); + + let nv = 4; + let degree = 3; + + let mut builder = AsmBuilder::::default(); + + let out_claim = EF::read(&mut builder); + let prover_msgs = Vec::::read(&mut builder); + + let max_num_variables: Felt = builder.constant(F::from_canonical_u32(nv as u32)); + let max_degree: Felt = builder.constant(F::from_canonical_u32(degree as u32)); + + 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); + } + + iop_verifier_state_verify( + &mut builder, + &mut challenger, + &out_claim, + &prover_msgs, + max_num_variables, + max_degree, + &interpolation_weights, + ); + + builder.halt(); + + // get the assembly code + let options = CompilerOptions::default().with_cycle_tracker(); + let mut compiler = AsmCompiler::new(options.word_size); + compiler.build(builder.operations); + let asm_code = compiler.code(); + println!("asm code"); + println!("{asm_code}"); + + // run sumcheck prover to get sumcheck proof + let mut rng = thread_rng(); + let (mles, expected_sum) = + DenseMultilinearExtension::::random_mle_list(nv, degree, &mut rng); + let mles: Vec> = + mles.into_iter().map(|mle| mle as _).collect_vec(); + let mut virtual_poly: VirtualPolynomials<'_, E> = VirtualPolynomials::new(1, nv); + virtual_poly.add_mle_list(mles.iter().collect_vec(), E::from_v(1)); + + let mut transcript = BasicTranscript::new(&[]); + let (sumcheck_proof, _) = IOPProverState::prove(virtual_poly, &mut transcript); + let mut input_stream = Vec::new(); + + // hacky way: convert E to EF but actually they are the same + let expected_sum: EF = cast_vec(vec![expected_sum])[0]; + input_stream.extend(expected_sum.write()); + input_stream.extend( + sumcheck_proof + .proofs + .into_iter() + .map(|msg| { + let evaluations: Vec = cast_vec(msg.evaluations); + IOPProverMessage { evaluations } + }) + .collect_vec() + .write(), + ); + + // get execution result + let program = convert_program(asm_code, 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); + + let res = executor + .execute_and_then(program, input_stream, |_, seg| Ok(seg), |err| err) + .unwrap(); + + for (i, seg) in res.iter().enumerate() { + #[cfg(feature = "bench-metrics")] + { + println!( + "=> segment {} metrics.cycle_count: {:?}", + i, seg.metrics.cycle_count + ); + for (insn, count) in seg.metrics.counts.iter() { + println!("insn: {:?}, count: {:?}", insn, count); + } + println!( + "=> segment {} #(insns): {}", + i, + seg.metrics + .counts + .values() + .copied() + .into_iter() + .sum::() + ); + } + } + } + + #[test] + fn test_prod_tower() { + let nv = 5; + let num_prod_records = 2; + let mut rng = thread_rng(); + + setup_tracing_with_log_level(tracing::Level::WARN); + + let records: Vec> = (0..num_prod_records) + .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, 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 mut transcript = BasicTranscript::new(&[]); + let (_, tower_proof) = + TowerProver::create_proof(prod_specs, vec![], NUM_FANIN, &mut transcript); + + // build program + let mut builder = AsmBuilder::::default(); + + let mut challenger: DuplexChallengerVariable = + DuplexChallengerVariable::new(&mut builder); + + // construct extrapolation weights + 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); + } + + 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: vec![], + num_variables: vec![nv; num_prod_records], + num_fanin: NUM_FANIN, + num_proofs: nv - 1, + num_prod_specs: num_prod_records, + num_logup_specs: 0, + _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: vec![], + }; + verify_tower_proof( + &mut builder, + &mut challenger, + tower_verifier_input_var, + &interpolation_weights, + ); + + 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(); + let ptr = vec.as_mut_ptr(); + // Prevent `vec` from dropping its contents + std::mem::forget(vec); + + // Convert the pointer to the new type + let new_ptr = ptr as *mut B; + + // Create a new vector with the same length and capacity, but different type + unsafe { Vec::from_raw_parts(new_ptr, length, capacity) } + } +} diff --git a/src/transcript/mod.rs b/src/transcript/mod.rs index ec1facc..05fd418 100644 --- a/src/transcript/mod.rs +++ b/src/transcript/mod.rs @@ -2,10 +2,13 @@ use ff_ext::{BabyBearExt4, ExtensionField as CenoExtensionField, SmallField}; use openvm_native_compiler::prelude::*; use openvm_native_recursion::challenger::ChallengerVariable; use p3_field::FieldAlgebra; +use openvm_native_recursion::challenger::{ + duplex::DuplexChallengerVariable, CanObserveVariable, FeltChallenger, +}; pub fn transcript_observe_label( builder: &mut Builder, - challenger: &mut impl ChallengerVariable, + challenger: &mut DuplexChallengerVariable, label: &[u8], ) { let label_f = ::BaseField::bytes_to_field_elements(label); diff --git a/src/zkvm_verifier/verifier.rs b/src/zkvm_verifier/verifier.rs index 633645e..88d1305 100644 --- a/src/zkvm_verifier/verifier.rs +++ b/src/zkvm_verifier/verifier.rs @@ -1,6 +1,7 @@ use super::binding::{ ZKVMOpcodeProofInputVariable, ZKVMProofInputVariable, ZKVMTableProofInputVariable, }; +use crate::arithmetics::challenger_multi_observe; use crate::e2e::SubcircuitParams; use crate::tower_verifier::program::verify_tower_proof; use crate::transcript::transcript_observe_label; @@ -83,10 +84,8 @@ pub fn verify_zkvm_proof( iter_zip!(builder, zkvm_proof_input.raw_pi).for_each(|ptr_vec, builder| { let v = builder.iter_ptr_get(&zkvm_proof_input.raw_pi, ptr_vec[0]); - iter_zip!(builder, v).for_each(|inner_ptr_vec, builder| { - let f = builder.iter_ptr_get(&v, inner_ptr_vec[0]); - challenger.observe(builder, f); - }) + + challenger_multi_observe(builder, &mut challenger, &v); }); iter_zip!(builder, zkvm_proof_input.raw_pi, zkvm_proof_input.pi_evals).for_each( @@ -102,18 +101,13 @@ pub fn verify_zkvm_proof( }, ); - iter_zip!(builder, zkvm_proof_input.fixed_commit).for_each(|ptr_vec, builder| { - let f = builder.iter_ptr_get(&zkvm_proof_input.fixed_commit, ptr_vec[0]); - challenger.observe(builder, f); - }); + challenger_multi_observe(builder, &mut challenger, &zkvm_proof_input.fixed_commit); + iter_zip!(builder, zkvm_proof_input.fixed_commit_trivial_commits).for_each( |ptr_vec, builder| { let trivial_cmt = builder.iter_ptr_get(&zkvm_proof_input.fixed_commit_trivial_commits, ptr_vec[0]); - iter_zip!(builder, trivial_cmt).for_each(|t_ptr_vec, builder| { - let f = builder.iter_ptr_get(&trivial_cmt, t_ptr_vec[0]); - challenger.observe(builder, f); - }); + challenger_multi_observe(builder, &mut challenger, &trivial_cmt); }, ); challenger.observe( @@ -129,18 +123,13 @@ pub fn verify_zkvm_proof( challenger.observe(builder, num_var); }); - iter_zip!(builder, zkvm_proof_input.witin_commit).for_each(|ptr_vec, builder| { - let f = builder.iter_ptr_get(&zkvm_proof_input.witin_commit, ptr_vec[0]); - challenger.observe(builder, f); - }); + challenger_multi_observe(builder, &mut challenger, &zkvm_proof_input.witin_commit); + iter_zip!(builder, zkvm_proof_input.witin_commit_trivial_commits).for_each( |ptr_vec, builder| { let trivial_cmt = builder.iter_ptr_get(&zkvm_proof_input.witin_commit_trivial_commits, ptr_vec[0]); - iter_zip!(builder, trivial_cmt).for_each(|t_ptr_vec, builder| { - let f = builder.iter_ptr_get(&trivial_cmt, t_ptr_vec[0]); - challenger.observe(builder, f); - }); + challenger_multi_observe(builder, &mut challenger, &trivial_cmt); }, ); challenger.observe(