diff --git a/Cargo.lock b/Cargo.lock index a7653414..81874cce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anes" version = "0.1.6" @@ -52,7 +67,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -62,7 +77,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -71,6 +86,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -98,12 +128,31 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "cc" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.4", +] + [[package]] name = "ciborium" version = "0.2.2" @@ -177,6 +226,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + [[package]] name = "cpufeatures" version = "0.2.12" @@ -222,6 +277,28 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -241,12 +318,47 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.5.0", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "serde", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -285,6 +397,27 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fd-lock" +version = "3.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -328,6 +461,29 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "is-terminal" version = "0.4.12" @@ -336,7 +492,7 @@ checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ "hermit-abi", "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -378,6 +534,22 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.21" @@ -390,6 +562,27 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2800e1520bdc966782168a627aa5d1ad92e33b984bf7c7615d31280c83ff14" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "num-traits" version = "0.2.18" @@ -633,6 +826,29 @@ dependencies = [ "serde", ] +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + [[package]] name = "pest" version = "2.7.8" @@ -804,6 +1020,51 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "reedline" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413a9fa6a5d8c937d3ae1e975bfb6a918bb0b6cdfae6a10416218c837a31b8fc" +dependencies = [ + "chrono", + "crossbeam", + "crossterm", + "fd-lock", + "itertools 0.12.1", + "nu-ansi-term", + "serde", + "strip-ansi-escapes", + "strum", + "strum_macros", + "thiserror", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "reedline-repl-rs" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28f19046a23d5c9f988b6677868024009a60e82676d5cd3b4c52d7557db680eb" +dependencies = [ + "clap", + "crossterm", + "nu-ansi-term", + "reedline", + "regex", + "winapi-util", + "yansi", +] + [[package]] name = "regex" version = "1.10.3" @@ -833,6 +1094,25 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rustix" +version = "0.38.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" + [[package]] name = "ryu" version = "1.0.17" @@ -848,6 +1128,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.197" @@ -890,12 +1176,76 @@ dependencies = [ "digest", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "strip-ansi-escapes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.52", +] + [[package]] name = "syn" version = "1.0.109" @@ -1006,6 +1356,18 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + [[package]] name = "utf8parse" version = "0.2.1" @@ -1073,6 +1435,7 @@ dependencies = [ "rand", "rand_pcg", "rand_seeder", + "reedline-repl-rs", "tracing", "valida-alu-u32", "valida-assembler", @@ -1089,6 +1452,48 @@ dependencies = [ "valida-static-data", ] +[[package]] +name = "valida-basic-macro" +version = "0.1.0" +dependencies = [ + "byteorder", + "ciborium", + "clap", + "p3-air", + "p3-baby-bear", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-fri", + "p3-goldilocks", + "p3-keccak", + "p3-matrix", + "p3-maybe-rayon", + "p3-mds", + "p3-merkle-tree", + "p3-poseidon", + "p3-symmetric", + "p3-uni-stark", + "p3-util", + "rand", + "rand_pcg", + "rand_seeder", + "tracing", + "valida-alu-u32", + "valida-assembler", + "valida-bus", + "valida-cpu", + "valida-derive", + "valida-machine", + "valida-memory", + "valida-opcodes", + "valida-output", + "valida-program", + "valida-range", + "valida-static-data", +] + [[package]] name = "valida-bus" version = "0.1.0" @@ -1282,6 +1687,26 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -1393,13 +1818,46 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1408,53 +1866,101 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" diff --git a/Cargo.toml b/Cargo.toml index 3a2fefd7..ff8210b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "assembler", "alu_u32", "basic", + "basic_macro", "bus", "cpu", "derive", diff --git a/basic/src/bin/valida.rs b/basic/src/bin/valida.rs index b8e770d7..5e4eff84 100644 --- a/basic/src/bin/valida.rs +++ b/basic/src/bin/valida.rs @@ -9,7 +9,7 @@ use p3_baby_bear::BabyBear; use p3_fri::{FriConfig, TwoAdicFriPcs, TwoAdicFriPcsConfig}; use valida_cpu::MachineWithCpuChip; -use valida_machine::{Machine, MachineProof, ProgramROM, StdinAdviceProvider}; +use valida_machine::{Machine, MachineProof, ProgramROM, StdinAdviceProvider, StoppingFlag}; use valida_memory::MachineWithMemoryChip; use valida_elf::{load_executable_file, Program}; @@ -34,7 +34,7 @@ use valida_output::MachineWithOutputChip; use reedline_repl_rs::clap::{Arg, ArgMatches, Command}; use reedline_repl_rs::{Repl, Result}; -#[derive(Parser)] +#[derive(Parser, Clone)] struct Args { /// Command option either "run" or "prove" or "verify" or "interactive" #[arg(name = "Action Option")] @@ -53,23 +53,23 @@ struct Args { stack_height: u32, } -struct Context<'a> { +struct Context { machine_: BasicMachine, - args_: &'a Args, + args_: Args, breakpoints_: Vec, - stopped_: bool, + stopped_: StoppingFlag, last_fp_: u32, recorded_current_fp_: u32, last_fp_size_: u32, } -impl Context<'_> { +impl Context { fn new(args: &Args) -> Context { let mut context = Context { machine_: BasicMachine::::default(), - args_: args.clone(), + args_: (*args).clone(), breakpoints_: Vec::new(), - stopped_: false, + stopped_: StoppingFlag::DidNotStop, last_fp_: args.stack_height, recorded_current_fp_: args.stack_height, last_fp_size_: 0, @@ -88,10 +88,10 @@ impl Context<'_> { context } - fn step(&mut self) -> (bool, u32) { + fn step(&mut self) -> (StoppingFlag, u32) { // do not execute if already stopped - if self.stopped_ { - return (true, 0); + if self.stopped_ == StoppingFlag::DidStop { + return (StoppingFlag::DidStop, 0); } let state = self.machine_.step(&mut StdinAdviceProvider); let pc = self.machine_.cpu().pc; @@ -113,21 +113,20 @@ impl Context<'_> { } } -fn init_context(args: ArgMatches, context: &mut Context) -> Result> { +fn init_context(_args: ArgMatches, _context: &mut Context) -> Result> { Ok(Some(String::from("created machine"))) } -fn status(args: ArgMatches, context: &mut Context) -> Result> { +fn status(_args: ArgMatches, context: &mut Context) -> Result> { // construct machine status let mut status = String::new(); status.push_str("FP: "); status.push_str(&context.machine_.cpu().fp.to_string()); status.push_str(", PC: "); status.push_str(&context.machine_.cpu().pc.to_string()); - status.push_str(if context.stopped_ { - ", Stopped" - } else { - ", Running" + status.push_str(match context.stopped_ { + StoppingFlag::DidStop => ", Stopped", + StoppingFlag::DidNotStop => ", Running", }); Ok(Some(status)) } @@ -233,11 +232,11 @@ fn show_memory(args: ArgMatches, context: &mut Context) -> Result Ok(Some(memory)) } -fn run_until(_: ArgMatches, context: &mut Context) -> Result> { +fn run_until(_args: ArgMatches, context: &mut Context) -> Result> { let mut message = String::new(); loop { let (stop, pc) = context.step(); - if stop { + if stop == StoppingFlag::DidStop { message.push_str("Execution stopped"); break; } @@ -250,10 +249,10 @@ fn run_until(_: ArgMatches, context: &mut Context) -> Result> { Ok(Some(message)) } -fn step(_: ArgMatches, context: &mut Context) -> Result> { +fn step(_args: ArgMatches, context: &mut Context) -> Result> { let (stop, _) = context.step(); - if stop { - context.stopped_ = true; + if stop == StoppingFlag::DidStop { + context.stopped_ = StoppingFlag::DidStop; Ok(Some(String::from("Execution stopped"))) } else { Ok(None) diff --git a/basic/src/lib.rs b/basic/src/lib.rs index e7522e00..35168eab 100644 --- a/basic/src/lib.rs +++ b/basic/src/lib.rs @@ -2,15 +2,19 @@ extern crate alloc; +use alloc::boxed::Box; +use alloc::format; +use alloc::vec; use alloc::vec::Vec; use core::marker::PhantomData; use p3_air::Air; use p3_commit::{Pcs, UnivariatePcs, UnivariatePcsWithLde}; -use p3_field::PrimeField32; use p3_field::{extension::BinomialExtensionField, TwoAdicField}; +use p3_field::{AbstractExtensionField, AbstractField, PrimeField32}; use p3_matrix::dense::RowMajorMatrix; +use p3_matrix::{Dimensions, Matrix, MatrixRowSlices}; use p3_maybe_rayon::*; -use p3_util::log2_ceil_usize; +use p3_util::{log2_ceil_usize, log2_strict_usize}; use valida_alu_u32::{ add::{Add32Chip, Add32Instruction, MachineWithAdd32Chip}, bitwise::{ @@ -37,9 +41,13 @@ use valida_cpu::{ Store32Instruction, }; use valida_cpu::{CpuChip, MachineWithCpuChip}; -use valida_derive::Machine; +use valida_machine::__internal::p3_challenger::{CanObserve, FieldChallenger}; +use valida_machine::__internal::{ + check_constraints, check_cumulative_sums, get_log_quotient_degree, quotient, +}; use valida_machine::{ - AdviceProvider, BusArgument, Chip, ChipProof, Instruction, Machine, MachineProof, ProgramROM, + generate_permutation_trace, verify_constraints, AdviceProvider, BusArgument, Chip, ChipProof, + Commitments, Instruction, Machine, MachineProof, OpenedValues, ProgramROM, StoppingFlag, ValidaAirBuilder, }; use valida_memory::{MachineWithMemoryChip, MemoryChip}; @@ -51,142 +59,1109 @@ use valida_static_data::{MachineWithStaticDataChip, StaticDataChip}; use p3_maybe_rayon::prelude::*; use valida_machine::StarkConfig; -#[derive(Machine, Default)] -#[machine_fields(F)] +#[derive(Default)] pub struct BasicMachine { // Core instructions - #[instruction] load32: Load32Instruction, - - #[instruction] store32: Store32Instruction, - - #[instruction] jal: JalInstruction, - - #[instruction] jalv: JalvInstruction, - - #[instruction] beq: BeqInstruction, - - #[instruction] bne: BneInstruction, - - #[instruction] imm32: Imm32Instruction, - - #[instruction] stop: StopInstruction, - - #[instruction] loadfp: LoadFpInstruction, // ALU instructions - #[instruction(add_u32)] add32: Add32Instruction, - - #[instruction(sub_u32)] sub32: Sub32Instruction, - - #[instruction(mul_u32)] mul32: Mul32Instruction, - - #[instruction(mul_u32)] mulhs32: Mulhs32Instruction, - - #[instruction(mul_u32)] mulhu32: Mulhu32Instruction, - - #[instruction(div_u32)] div32: Div32Instruction, - - #[instruction(div_u32)] sdiv32: SDiv32Instruction, - - #[instruction(shift_u32)] shl32: Shl32Instruction, - - #[instruction(shift_u32)] shr32: Shr32Instruction, - - #[instruction(shift_u32)] sra32: Sra32Instruction, - - #[instruction(lt_u32)] lt32: Lt32Instruction, - - #[instruction(lt_u32)] lte32: Lte32Instruction, - - #[instruction(bitwise_u32)] and32: And32Instruction, - - #[instruction(bitwise_u32)] or32: Or32Instruction, - - #[instruction(bitwise_u32)] xor32: Xor32Instruction, - - #[instruction(com_u32)] ne32: Ne32Instruction, - - #[instruction(com_u32)] eq32: Eq32Instruction, // Input/output instructions - #[instruction] read: ReadAdviceInstruction, - - #[instruction(output)] write: WriteInstruction, - #[chip] + // Chips cpu: CpuChip, - - #[chip] program: ProgramChip, - - #[chip] mem: MemoryChip, - - #[chip] add_u32: Add32Chip, - - #[chip] sub_u32: Sub32Chip, - - #[chip] mul_u32: Mul32Chip, - - #[chip] div_u32: Div32Chip, - - #[chip] shift_u32: Shift32Chip, - - #[chip] lt_u32: Lt32Chip, - - #[chip] com_u32: Com32Chip, - - #[chip] bitwise_u32: Bitwise32Chip, - - #[chip] output: OutputChip, - - #[chip] range: RangeCheckerChip<256>, - - #[chip] - #[static_data_chip] static_data: StaticDataChip, _phantom_sc: PhantomData F>, } +const NUM_CHIPS: usize = 14; + +impl Machine for BasicMachine { + fn run(&mut self, program: &ProgramROM, advice: &mut Adv) + where + Adv: AdviceProvider, + { + self.initialize_memory(); + + loop { + let step_did_stop = self.step(advice); + if step_did_stop == StoppingFlag::DidStop { + break; + } + } + + // Record padded STOP instructions + let n = self.cpu().clock.next_power_of_two() - self.cpu().clock; + for _ in 0..n { + self.read_word(self.cpu().pc as usize); + } + } + + fn prove(&self, config: &SC) -> MachineProof + where + SC: StarkConfig, + { + let mut chips: [Box<&dyn Chip>; NUM_CHIPS] = [ + Box::new(self.cpu()), + Box::new(self.program()), + Box::new(self.mem()), + Box::new(self.add_u32()), + Box::new(self.sub_u32()), + Box::new(self.mul_u32()), + Box::new(self.div_u32()), + Box::new(self.shift_u32()), + Box::new(self.lt_u32()), + Box::new(self.com_u32()), + Box::new(self.bitwise_u32()), + Box::new(self.output()), + Box::new(self.range()), + Box::new(self.static_data()), + ]; + + let log_quotient_degrees: [usize; NUM_CHIPS] = [ + get_log_quotient_degree::(self, self.cpu()), + get_log_quotient_degree::(self, self.program()), + get_log_quotient_degree::(self, self.mem()), + get_log_quotient_degree::(self, self.add_u32()), + get_log_quotient_degree::(self, self.sub_u32()), + get_log_quotient_degree::(self, self.mul_u32()), + get_log_quotient_degree::(self, self.div_u32()), + get_log_quotient_degree::(self, self.shift_u32()), + get_log_quotient_degree::(self, self.lt_u32()), + get_log_quotient_degree::(self, self.com_u32()), + get_log_quotient_degree::(self, self.bitwise_u32()), + get_log_quotient_degree::(self, self.output()), + get_log_quotient_degree::(self, self.range()), + get_log_quotient_degree::(self, self.static_data()), + ]; + + let mut challenger = config.challenger(); + // TODO: Seed challenger with digest of all constraints & trace lengths. + let pcs = config.pcs(); + + let preprocessed_traces: Vec> = + tracing::info_span!("generate preprocessed traces").in_scope(|| { + chips + .par_iter() + .flat_map(|chip| chip.preprocessed_trace()) + .collect::>() + }); + + let (preprocessed_commit, preprocessed_data) = + tracing::info_span!("commit to preprocessed traces") + .in_scope(|| pcs.commit_batches(preprocessed_traces.to_vec())); + challenger.observe(preprocessed_commit.clone()); + let mut preprocessed_trace_ldes = pcs.get_ldes(&preprocessed_data); + + let main_traces: [RowMajorMatrix; NUM_CHIPS] = + tracing::info_span!("generate main trace").in_scope(|| { + chips + .par_iter() + .map(|chip| chip.generate_trace(self)) + .collect::>() + .try_into() + .unwrap() + }); + + let degrees: [usize; NUM_CHIPS] = main_traces + .iter() + .map(|trace| trace.height()) + .collect::>() + .try_into() + .unwrap(); + let log_degrees = degrees.map(|d| log2_strict_usize(d)); + let g_subgroups = log_degrees.map(|log_deg| SC::Val::two_adic_generator(log_deg)); + + let (main_commit, main_data) = tracing::info_span!("commit to main traces") + .in_scope(|| pcs.commit_batches(main_traces.to_vec())); + challenger.observe(main_commit.clone()); + let mut main_trace_ldes = pcs.get_ldes(&main_data); + + let mut perm_challenges = Vec::new(); + for _ in 0..3 { + perm_challenges.push(challenger.sample_ext_element()); + } + + let perm_traces = tracing::info_span!("generate permutation traces").in_scope(|| { + chips + .into_par_iter() + .enumerate() + .map(|(i, chip)| { + generate_permutation_trace( + self, + *chip, + &main_traces[i], + perm_challenges.clone(), + ) + }) + .collect::>() + }); + + let cumulative_sums = perm_traces + .iter() + .map(|trace| trace.row_slice(trace.height() - 1).last().unwrap().clone()) + .collect::>(); + + let (perm_commit, perm_data) = tracing::info_span!("commit to permutation traces") + .in_scope(|| { + let flattened_perm_traces = perm_traces + .iter() + .map(|trace| trace.flatten_to_base()) + .collect::>(); + pcs.commit_batches(flattened_perm_traces) + }); + challenger.observe(perm_commit.clone()); + let mut perm_trace_ldes = pcs.get_ldes(&perm_data); + + let alpha: SC::Challenge = challenger.sample_ext_element(); + + let mut quotients: Vec> = vec![]; + + let mut i: usize = 0; + + let chip = self.cpu(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.program(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + Some(preprocessed_trace_ldes.remove(0)), + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.mem(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.add_u32(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.sub_u32(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.mul_u32(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.div_u32(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.shift_u32(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.lt_u32(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.com_u32(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.bitwise_u32(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.output(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.range(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + Some(preprocessed_trace_ldes.remove(0)), + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + let chip = self.static_data(); + #[cfg(debug_assertions)] + check_constraints::( + self, + chip, + &main_traces[i], + &perm_traces[i], + &perm_challenges, + ); + quotients.push(quotient( + self, + config, + chip, + log_degrees[i], + None::>, + main_trace_ldes.remove(0), + perm_trace_ldes.remove(0), + cumulative_sums[i], + &perm_challenges, + alpha, + )); + i += 1; + + assert_eq!(quotients.len(), NUM_CHIPS); + assert_eq!(log_quotient_degrees.len(), NUM_CHIPS); + let coset_shifts = tracing::debug_span!("coset shift").in_scope(|| { + let pcs_coset_shift = pcs.coset_shift(); + log_quotient_degrees.map(|log_d| pcs_coset_shift.exp_power_of_2(log_d)) + }); + assert_eq!(coset_shifts.len(), NUM_CHIPS); + let (quotient_commit, quotient_data) = tracing::info_span!("commit to quotient chunks") + .in_scope(|| pcs.commit_shifted_batches(quotients.to_vec(), &coset_shifts)); + + challenger.observe(quotient_commit.clone()); + + #[cfg(debug_assertions)] + check_cumulative_sums(&perm_traces[..]); + + let zeta: SC::Challenge = challenger.sample_ext_element(); + let zeta_and_next: [Vec; NUM_CHIPS] = + g_subgroups.map(|g| vec![zeta, zeta * g]); + let zeta_exp_quotient_degree: [Vec; NUM_CHIPS] = + log_quotient_degrees.map(|log_deg| vec![zeta.exp_power_of_2(log_deg)]); + let prover_data_and_points = [ + // TODO: Causes some errors, probably related to the fact that not all chips have preprocessed traces? + // (&preprocessed_data, zeta_and_next.as_slice()), + (&main_data, zeta_and_next.as_slice()), + (&perm_data, zeta_and_next.as_slice()), + ("ient_data, zeta_exp_quotient_degree.as_slice()), + ]; + let (openings, opening_proof) = + pcs.open_multi_batches(&prover_data_and_points, &mut challenger); + + // TODO: add preprocessed openings + let [main_openings, perm_openings, quotient_openings] = openings + .try_into() + .expect("Should have 3 rounds of openings"); + + let commitments = Commitments { + main_trace: main_commit, + perm_trace: perm_commit, + quotient_chunks: quotient_commit, + }; + + // TODO: add preprocessed openings + let chip_proofs = log_degrees + .iter() + .zip(main_openings) + .zip(perm_openings) + .zip(quotient_openings) + .zip(perm_traces) + .map(|((((log_degree, main), perm), quotient), perm_trace)| { + // TODO: add preprocessed openings + let [preprocessed_local, preprocessed_next] = [vec![], vec![]]; + + let [main_local, main_next] = main.try_into().expect("Should have 2 openings"); + let [perm_local, perm_next] = perm.try_into().expect("Should have 2 openings"); + let [quotient_chunks] = quotient.try_into().expect("Should have 1 opening"); + + let opened_values = OpenedValues { + preprocessed_local, + preprocessed_next, + trace_local: main_local, + trace_next: main_next, + permutation_local: perm_local, + permutation_next: perm_next, + quotient_chunks, + }; + + let cumulative_sum = perm_trace + .row_slice(perm_trace.height() - 1) + .last() + .unwrap() + .clone(); + ChipProof { + log_degree: *log_degree, + opened_values, + cumulative_sum, + } + }) + .collect::>(); + + MachineProof { + commitments, + opening_proof, + chip_proofs, + } + } + + fn verify(&self, config: &SC, proof: &MachineProof) -> Result<(), ()> + where + SC: StarkConfig, + { + let mut chips: [Box<&dyn Chip>; NUM_CHIPS] = [ + Box::new(self.cpu()), + Box::new(self.program()), + Box::new(self.mem()), + Box::new(self.add_u32()), + Box::new(self.sub_u32()), + Box::new(self.mul_u32()), + Box::new(self.div_u32()), + Box::new(self.shift_u32()), + Box::new(self.lt_u32()), + Box::new(self.com_u32()), + Box::new(self.bitwise_u32()), + Box::new(self.output()), + Box::new(self.range()), + Box::new(self.static_data()), + ]; + + let log_quotient_degrees: [usize; NUM_CHIPS] = [ + get_log_quotient_degree::(self, self.cpu()), + get_log_quotient_degree::(self, self.program()), + get_log_quotient_degree::(self, self.mem()), + get_log_quotient_degree::(self, self.add_u32()), + get_log_quotient_degree::(self, self.sub_u32()), + get_log_quotient_degree::(self, self.mul_u32()), + get_log_quotient_degree::(self, self.div_u32()), + get_log_quotient_degree::(self, self.shift_u32()), + get_log_quotient_degree::(self, self.lt_u32()), + get_log_quotient_degree::(self, self.com_u32()), + get_log_quotient_degree::(self, self.bitwise_u32()), + get_log_quotient_degree::(self, self.output()), + get_log_quotient_degree::(self, self.range()), + get_log_quotient_degree::(self, self.static_data()), + ]; + + let mut challenger = config.challenger(); + // TODO: Seed challenger with digest of all constraints & trace lengths. + let pcs = config.pcs(); + + let chips_interactions = chips + .iter() + .map(|chip| chip.all_interactions(self)) + .collect::>(); + + let dims = &[ + chips + .iter() + .zip(proof.chip_proofs.iter()) + .map(|(chip, chip_proof)| Dimensions { + width: chip.trace_width(), + height: 1 << chip_proof.log_degree, + }) + .collect::>(), + chips_interactions + .iter() + .zip(proof.chip_proofs.iter()) + .map(|(interactions, chip_proof)| Dimensions { + width: (interactions.len() + 1) * SC::Challenge::D, + height: 1 << chip_proof.log_degree, + }) + .collect::>(), + proof + .chip_proofs + .iter() + .zip(log_quotient_degrees) + .map(|(chip_proof, log_quotient_deg)| Dimensions { + width: log_quotient_deg << SC::Challenge::D, + height: 1 << chip_proof.log_degree, + }) + .collect::>(), + ]; + + // Get the generators of the trace subgroups for each chip. + let g_subgroups: [SC::Val; NUM_CHIPS] = proof + .chip_proofs + .iter() + .map(|chip_proof| SC::Val::two_adic_generator(chip_proof.log_degree)) + .collect::>() + .try_into() + .unwrap(); + + // TODO: maybe avoid cloning opened values (not sure if possible) + let mut main_values = vec![]; + let mut perm_values = vec![]; + let mut quotient_values = vec![]; + + for chip_proof in proof.chip_proofs.iter() { + let OpenedValues { + preprocessed_local, + preprocessed_next, + trace_local, + trace_next, + permutation_local, + permutation_next, + quotient_chunks, + } = &chip_proof.opened_values; + + main_values.push(vec![trace_local.clone(), trace_next.clone()]); + perm_values.push(vec![permutation_local.clone(), permutation_next.clone()]); + quotient_values.push(vec![quotient_chunks.clone()]); + } + + let chips_opening_values = vec![main_values, perm_values, quotient_values]; + + // Observe commitments and get challenges. + let Commitments { + main_trace, + perm_trace, + quotient_chunks, + } = &proof.commitments; + + // Compute the commitments to preprocessed traces (TODO: avoid in the future) + let preprocessed_traces: Vec> = + tracing::info_span!("generate preprocessed traces").in_scope(|| { + chips + .par_iter() + .flat_map(|chip| chip.preprocessed_trace()) + .collect::>() + }); + + let (preprocessed_commit, preprocessed_data) = + tracing::info_span!("commit to preprocessed traces") + .in_scope(|| pcs.commit_batches(preprocessed_traces.to_vec())); + + challenger.observe(preprocessed_commit.clone()); + + challenger.observe(main_trace.clone()); + + let mut perm_challenges = Vec::new(); + for _ in 0..3 { + perm_challenges.push(challenger.sample_ext_element::()); + } + + challenger.observe(perm_trace.clone()); + + let alpha = challenger.sample_ext_element::(); + + challenger.observe(quotient_chunks.clone()); + + // Verify the opening proof. + let zeta: SC::Challenge = challenger.sample_ext_element(); + let zeta_and_next: [Vec; NUM_CHIPS] = + g_subgroups.map(|g| vec![zeta, zeta * g]); + let zeta_exp_quotient_degree: [Vec; NUM_CHIPS] = + log_quotient_degrees.map(|log_deg| vec![zeta.exp_power_of_2(log_deg)]); + pcs.verify_multi_batches( + &[ + // TODO: add preprocessed trace + (main_trace.clone(), zeta_and_next.as_slice()), + (perm_trace.clone(), zeta_and_next.as_slice()), + (quotient_chunks.clone(), zeta_exp_quotient_degree.as_slice()), + ], + dims, + chips_opening_values, + &proof.opening_proof, + &mut challenger, + ) + .map_err(|_| ())?; + + // Verify the constraints. + let mut i = 0; + + let chip = self.cpu(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.program(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.mem(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.add_u32(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.sub_u32(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.mul_u32(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.div_u32(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.shift_u32(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.lt_u32(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.com_u32(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.bitwise_u32(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.output(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.range(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + let chip = self.static_data(); + verify_constraints::( + self, + chip, + &proof.chip_proofs[i].opened_values, + proof.chip_proofs[i].cumulative_sum, + proof.chip_proofs[i].log_degree, + g_subgroups[i], + zeta, + alpha, + &perm_challenges, + ) + .expect(&format!("Failed to verify constraints on chip {}", i)); + i += 1; + + // Verify that the cumulative_sum sums add up to zero. + let sum: SC::Challenge = proof + .chip_proofs + .iter() + .map(|chip_proof| chip_proof.cumulative_sum) + .sum(); + + if sum != SC::Challenge::zero() { + return Err(()); + } + + Ok(()) + } + + fn step(&mut self, advice: &mut Adv) -> StoppingFlag + where + Adv: AdviceProvider, + { + // Fetch + let pc = self.cpu().pc; + let instruction = self.program.program_rom.get_instruction(pc); + let opcode = instruction.opcode; + let ops = instruction.operands; + + // Execute + match opcode { + >::OPCODE => { + Load32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Store32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + JalInstruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + JalvInstruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + BeqInstruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + BneInstruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Imm32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + StopInstruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + LoadFpInstruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Add32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Sub32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Mul32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Mulhs32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Mulhu32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Div32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + SDiv32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Shl32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Shr32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Lt32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Lte32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + And32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Or32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Xor32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Ne32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + Eq32Instruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + ReadAdviceInstruction::execute_with_advice::(self, ops, advice) + } + >::OPCODE => { + WriteInstruction::execute_with_advice::(self, ops, advice) + } + _ => panic!("Unrecognized opcode: {}", opcode), + }; + self.read_word(pc as usize); + + // A STOP instruction signals the end of the program + if opcode == >::OPCODE { + StoppingFlag::DidStop + } else { + StoppingFlag::DidNotStop + } + } +} + impl MachineWithGeneralBus for BasicMachine { fn general_bus(&self) -> BusArgument { BusArgument::Global(0) diff --git a/basic_macro/Cargo.toml b/basic_macro/Cargo.toml new file mode 100644 index 00000000..3b2e0951 --- /dev/null +++ b/basic_macro/Cargo.toml @@ -0,0 +1,63 @@ +[package] +name = "valida-basic-macro" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" + +[[bin]] +name = "valida_macro" +path = "src/bin/valida.rs" + +[[bin]] +name = "test_prover_macro" +path = "src/bin/test_prover.rs" + +[dependencies] +byteorder = "1.4.3" +ciborium = "0.2.2" +clap = { version = "4.3.19", features = ["derive"] } +rand = "0.8.5" +rand_pcg = "0.3.1" +rand_seeder = "0.2.3" +tracing = "0.1.37" +valida-alu-u32 = { path = "../alu_u32" } +valida-assembler = { path = "../assembler" } +valida-bus = { path = "../bus" } +valida-cpu = { path = "../cpu" } +valida-derive = { path = "../derive" } +valida-machine = { path = "../machine" } +valida-memory = { path = "../memory" } +valida-opcodes = { path = "../opcodes" } +valida-output = { path = "../output" } +valida-program = { path = "../program" } +valida-range = { path = "../range" } +valida-static-data = { path = "../static_data" } +p3-baby-bear = { workspace = true } +p3-field = { workspace = true } +p3-maybe-rayon = { workspace = true } +p3-util = { workspace = true } +p3-goldilocks = { workspace = true } +p3-uni-stark = { workspace = true } +p3-commit = { workspace = true } +p3-air = { workspace = true } +p3-matrix = { workspace = true } +p3-challenger = { workspace = true } +p3-dft = { workspace = true } +p3-fri = { workspace = true } +p3-keccak = { workspace = true } +p3-mds = { workspace = true } +p3-merkle-tree = { workspace = true } +p3-poseidon = { workspace = true } +p3-symmetric = { workspace = true } + +[dev-dependencies] +ciborium = "0.2.2" +p3-challenger = { workspace = true } +p3-dft = { workspace = true } +p3-field = { workspace = true } +p3-fri = { workspace = true } +p3-keccak = { workspace = true } +p3-mds = { workspace = true } +p3-merkle-tree = { workspace = true } +p3-poseidon = { workspace = true } +p3-symmetric = { workspace = true } diff --git a/basic_macro/src/bin/test_prover.rs b/basic_macro/src/bin/test_prover.rs new file mode 100644 index 00000000..27116fb1 --- /dev/null +++ b/basic_macro/src/bin/test_prover.rs @@ -0,0 +1,263 @@ +extern crate core; + +use p3_baby_bear::BabyBear; +use p3_fri::{TwoAdicFriPcs, TwoAdicFriPcsConfig}; +use valida_alu_u32::add::Add32Instruction; +use valida_basic_macro::BasicMachine; +use valida_cpu::{ + BeqInstruction, BneInstruction, Imm32Instruction, JalInstruction, JalvInstruction, + MachineWithCpuChip, StopInstruction, +}; +use valida_machine::{ + FixedAdviceProvider, Instruction, InstructionWord, Machine, MachineProof, Operands, ProgramROM, +}; + +use valida_opcodes::BYTES_PER_INSTR; +use valida_program::MachineWithProgramChip; + +use p3_challenger::DuplexChallenger; +use p3_dft::Radix2Bowers; +use p3_field::extension::BinomialExtensionField; +use p3_field::Field; +use p3_fri::FriConfig; +use p3_keccak::Keccak256Hash; +use p3_mds::coset_mds::CosetMds; +use p3_merkle_tree::FieldMerkleTreeMmcs; +use p3_poseidon::Poseidon; +use p3_symmetric::{CompressionFunctionFromHasher, SerializingHasher32}; +use rand::thread_rng; +use valida_machine::StarkConfigImpl; +use valida_machine::__internal::p3_commit::ExtensionMmcs; + +fn main() { + prove_fibonacci() +} + +fn prove_fibonacci() { + let mut program = vec![]; + + // Label locations + let bytes_per_instr = BYTES_PER_INSTR as i32; + let fib_bb0 = 8 * bytes_per_instr; + let fib_bb0_1 = 13 * bytes_per_instr; + let fib_bb0_2 = 15 * bytes_per_instr; + let fib_bb0_3 = 19 * bytes_per_instr; + let fib_bb0_4 = 21 * bytes_per_instr; + + //main: ; @main + //; %bb.0: + // imm32 -4(fp), 0, 0, 0, 0 + // imm32 -8(fp), 0, 0, 0, 100 + // addi -16(fp), -8(fp), 0 + // imm32 -20(fp), 0, 0, 0, 28 + // jal -28(fp), fib, -28 + // addi -12(fp), -24(fp), 0 + // addi 4(fp), -12(fp), 0 + // exit + //... + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-4, 0, 0, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-8, 0, 0, 0, 100]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-16, -8, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-20, 0, 0, 0, 28]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-28, fib_bb0, -28, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-12, -24, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([4, -12, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands::default(), + }, + ]); + + //fib: ; @fib + //; %bb.0: + // addi -4(fp), 12(fp), 0 + // imm32 -8(fp), 0, 0, 0, 0 + // imm32 -12(fp), 0, 0, 0, 1 + // imm32 -16(fp), 0, 0, 0, 0 + // beq .LBB0_1, 0(fp), 0(fp) + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-4, 12, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-8, 0, 0, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-12, 0, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-16, 0, 0, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([fib_bb0_1, 0, 0, 0, 0]), + }, + ]); + + //.LBB0_1: + // bne .LBB0_2, -16(fp), -4(fp) + // beq .LBB0_4, 0(fp), 0(fp) + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([fib_bb0_2, -16, -4, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([fib_bb0_4, 0, 0, 0, 0]), + }, + ]); + + //; %bb.2: + // add -20(fp), -8(fp), -12(fp) + // addi -8(fp), -12(fp), 0 + // addi -12(fp), -20(fp), 0 + // beq .LBB0_3, 0(fp), 0(fp) + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-20, -8, -12, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-8, -12, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-12, -20, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([fib_bb0_3, 0, 0, 0, 0]), + }, + ]); + + //; %bb.3: + // addi -16(fp), -16(fp), 1 + // beq .LBB0_1, 0(fp), 0(fp) + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-16, -16, 1, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([fib_bb0_1, 0, 0, 0, 0]), + }, + ]); + + //.LBB0_4: + // addi 4(fp), -8(fp), 0 + // jalv -4(fp), 0(fp), 8(fp) + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([4, -8, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-4, 0, 8, 0, 0]), + }, + ]); + + let mut machine = BasicMachine::::default(); + let rom = ProgramROM::new(program); + machine.program_mut().set_program_rom(&rom); + machine.cpu_mut().fp = 0x1000; + machine.cpu_mut().save_register_state(); // TODO: Initial register state should be saved + // automatically by the machine, not manually here + machine.run(&rom, &mut FixedAdviceProvider::empty()); + + type Val = BabyBear; + type Challenge = BinomialExtensionField; + type PackedChallenge = BinomialExtensionField<::Packing, 5>; + + type Mds16 = CosetMds; + let mds16 = Mds16::default(); + + type Perm16 = Poseidon; + let perm16 = Perm16::new_from_rng(4, 22, mds16, &mut thread_rng()); // TODO: Use deterministic RNG + + type MyHash = SerializingHasher32; + let hash = MyHash::new(Keccak256Hash {}); + + type MyCompress = CompressionFunctionFromHasher; + let compress = MyCompress::new(hash); + + type ValMmcs = FieldMerkleTreeMmcs; + let val_mmcs = ValMmcs::new(hash, compress); + + type ChallengeMmcs = ExtensionMmcs; + let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone()); + + type Dft = Radix2Bowers; + let dft = Dft::default(); + + type Challenger = DuplexChallenger; + + type MyFriConfig = TwoAdicFriPcsConfig; + let fri_config = FriConfig { + log_blowup: 1, + num_queries: 40, + proof_of_work_bits: 8, + mmcs: challenge_mmcs, + }; + + type Pcs = TwoAdicFriPcs; + type MyConfig = StarkConfigImpl; + + let pcs = Pcs::new(fri_config, dft, val_mmcs); + + let challenger = Challenger::new(perm16); + let config = MyConfig::new(pcs, challenger); + let proof = machine.prove(&config); + + let mut bytes = vec![]; + ciborium::into_writer(&proof, &mut bytes).expect("serialization failed"); + println!("Proof size: {} bytes", bytes.len()); + let deserialized_proof: MachineProof = + ciborium::from_reader(bytes.as_slice()).expect("deserialization failed"); + + machine + .verify(&config, &proof) + .expect("verification failed"); + machine + .verify(&config, &deserialized_proof) + .expect("verification failed"); + + // assert_eq!(machine.cpu().clock, 192); + // assert_eq!(machine.cpu().operations.len(), 192); + // assert_eq!(machine.mem().operations.values().flatten().count(), 401); + // assert_eq!(machine.add_u32().operations.len(), 105); + + // assert_eq!( + // *machine.mem().cells.get(&(0x1000 + 4)).unwrap(), // Return value + // Word([0, 1, 37, 17,]) // 25th fibonacci number (75025) + // ); +} diff --git a/basic_macro/src/bin/valida.rs b/basic_macro/src/bin/valida.rs new file mode 100644 index 00000000..a7b2eb27 --- /dev/null +++ b/basic_macro/src/bin/valida.rs @@ -0,0 +1,157 @@ +use clap::Parser; +use std::fs::File; +use std::io::{stdout, Write}; + +use valida_basic_macro::BasicMachine; + +use p3_baby_bear::BabyBear; + +use p3_fri::{FriConfig, TwoAdicFriPcs, TwoAdicFriPcsConfig}; +use valida_cpu::MachineWithCpuChip; +use valida_machine::{Machine, MachineProof, ProgramROM, StdinAdviceProvider}; + +use valida_program::MachineWithProgramChip; + +use p3_challenger::DuplexChallenger; +use p3_dft::Radix2DitParallel; +use p3_field::extension::BinomialExtensionField; +use p3_field::Field; +use p3_keccak::Keccak256Hash; +use p3_mds::coset_mds::CosetMds; +use p3_merkle_tree::FieldMerkleTreeMmcs; +use p3_poseidon::Poseidon; +use p3_symmetric::{CompressionFunctionFromHasher, SerializingHasher32}; +use rand_pcg::Pcg64; +use rand_seeder::Seeder; +use valida_machine::StarkConfigImpl; +use valida_machine::__internal::p3_commit::ExtensionMmcs; +use valida_output::MachineWithOutputChip; + +#[derive(Parser)] +struct Args { + /// Command option either "run" or "prove" or "verify" + #[arg(name = "Action Option")] + action: String, + + /// Program binary file + #[arg(name = "PROGRAM FILE")] + program: String, + + /// The output file for run or prove, or the input file for verify + #[arg(name = "ACTION FILE")] + action_file: String, + + /// Stack height (which is also the initial frame pointer value) + #[arg(long, default_value = "16777216")] + stack_height: u32, +} + +fn main() { + let args = Args::parse(); + + let mut machine = BasicMachine::::default(); + let rom = match ProgramROM::from_file(&args.program) { + Ok(contents) => contents, + Err(e) => panic!("Failure to load file: {}. {}", &args.program, e), + }; + machine.program_mut().set_program_rom(&rom); + machine.cpu_mut().fp = args.stack_height; + machine.cpu_mut().save_register_state(); + + // Run the program + machine.run(&rom, &mut StdinAdviceProvider); + + type Val = BabyBear; + type Challenge = BinomialExtensionField; + type PackedChallenge = BinomialExtensionField<::Packing, 5>; + + type Mds16 = CosetMds; + let mds16 = Mds16::default(); + + type Perm16 = Poseidon; + let mut rng: Pcg64 = Seeder::from("validia seed").make_rng(); + let perm16 = Perm16::new_from_rng(4, 22, mds16, &mut rng); + + type MyHash = SerializingHasher32; + let hash = MyHash::new(Keccak256Hash {}); + + type MyCompress = CompressionFunctionFromHasher; + let compress = MyCompress::new(hash); + + type ValMmcs = FieldMerkleTreeMmcs; + let val_mmcs = ValMmcs::new(hash, compress); + + type ChallengeMmcs = ExtensionMmcs; + let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone()); + + type Dft = Radix2DitParallel; + let dft = Dft::default(); + + type Challenger = DuplexChallenger; + + type MyFriConfig = TwoAdicFriPcsConfig; + let fri_config = FriConfig { + log_blowup: 1, + num_queries: 40, + proof_of_work_bits: 8, + mmcs: challenge_mmcs, + }; + + type Pcs = TwoAdicFriPcs; + type MyConfig = StarkConfigImpl; + + let pcs = Pcs::new(fri_config, dft, val_mmcs); + + let challenger = Challenger::new(perm16); + let config = MyConfig::new(pcs, challenger); + + if args.action == "run" { + let mut action_file; + match File::create(args.action_file) { + Ok(file) => { + action_file = file; + } + Err(e) => { + stdout().write(e.to_string().as_bytes()).unwrap(); + return (); + } + } + action_file.write_all(&machine.output().bytes()).unwrap(); + } else if args.action == "prove" { + let mut action_file; + match File::create(args.action_file) { + Ok(file) => { + action_file = file; + } + Err(e) => { + stdout().write(e.to_string().as_bytes()).unwrap(); + return (); + } + } + let proof = machine.prove(&config); + debug_assert!(machine.verify(&config, &proof).is_ok()); + let mut bytes = vec![]; + ciborium::into_writer(&proof, &mut bytes).expect("Proof serialization failed"); + action_file.write(&bytes).expect("Writing proof failed"); + stdout().write("Proof successful\n".as_bytes()).unwrap(); + } else if args.action == "verify" { + let bytes = std::fs::read(args.action_file).expect("File reading failed"); + let proof: MachineProof = + ciborium::from_reader(bytes.as_slice()).expect("Proof deserialization failed"); + let verification_result = machine.verify(&config, &proof); + match verification_result { + Ok(_) => { + stdout().write("Proof verified\n".as_bytes()).unwrap(); + } + Err(_) => { + stdout() + .write("Proof verification failed\n".as_bytes()) + .unwrap(); + } + } + } else { + stdout() + .write("Action name unrecognized".as_bytes()) + .unwrap(); + } +} diff --git a/basic_macro/src/lib.rs b/basic_macro/src/lib.rs new file mode 100644 index 00000000..8d2b44ed --- /dev/null +++ b/basic_macro/src/lib.rs @@ -0,0 +1,351 @@ +#![allow(unused)] + +extern crate alloc; + +use alloc::vec::Vec; +use core::marker::PhantomData; +use p3_air::Air; +use p3_commit::{Pcs, UnivariatePcs, UnivariatePcsWithLde}; +use p3_field::PrimeField32; +use p3_field::{extension::BinomialExtensionField, TwoAdicField}; +use p3_matrix::dense::RowMajorMatrix; +use p3_maybe_rayon::*; +use p3_util::log2_ceil_usize; +use valida_alu_u32::{ + add::{Add32Chip, Add32Instruction, MachineWithAdd32Chip}, + bitwise::{ + And32Instruction, Bitwise32Chip, MachineWithBitwise32Chip, Or32Instruction, + Xor32Instruction, + }, + com::{Com32Chip, Eq32Instruction, MachineWithCom32Chip, Ne32Instruction}, + div::{Div32Chip, Div32Instruction, MachineWithDiv32Chip, SDiv32Instruction}, + lt::{Lt32Chip, Lt32Instruction, Lte32Instruction, MachineWithLt32Chip}, + mul::{ + MachineWithMul32Chip, Mul32Chip, Mul32Instruction, Mulhs32Instruction, Mulhu32Instruction, + }, + shift::{ + MachineWithShift32Chip, Shift32Chip, Shl32Instruction, Shr32Instruction, Sra32Instruction, + }, + sub::{MachineWithSub32Chip, Sub32Chip, Sub32Instruction}, +}; +use valida_bus::{ + MachineWithGeneralBus, MachineWithMemBus, MachineWithProgramBus, MachineWithRangeBus8, +}; +use valida_cpu::{ + BeqInstruction, BneInstruction, Imm32Instruction, JalInstruction, JalvInstruction, + Load32Instruction, LoadFpInstruction, ReadAdviceInstruction, StopInstruction, + Store32Instruction, +}; +use valida_cpu::{CpuChip, MachineWithCpuChip}; +use valida_derive::Machine; +use valida_machine::{ + AdviceProvider, BusArgument, Chip, ChipProof, Instruction, Machine, MachineProof, ProgramROM, + StoppingFlag, ValidaAirBuilder, +}; +use valida_memory::{MachineWithMemoryChip, MemoryChip}; +use valida_output::{MachineWithOutputChip, OutputChip, WriteInstruction}; +use valida_program::{MachineWithProgramChip, ProgramChip}; +use valida_range::{MachineWithRangeChip, RangeCheckerChip}; +use valida_static_data::{MachineWithStaticDataChip, StaticDataChip}; + +use p3_maybe_rayon::prelude::*; +use valida_machine::StarkConfig; + +#[derive(Machine, Default)] +#[machine_fields(F)] +pub struct BasicMachine { + // Core instructions + #[instruction] + load32: Load32Instruction, + + #[instruction] + store32: Store32Instruction, + + #[instruction] + jal: JalInstruction, + + #[instruction] + jalv: JalvInstruction, + + #[instruction] + beq: BeqInstruction, + + #[instruction] + bne: BneInstruction, + + #[instruction] + imm32: Imm32Instruction, + + #[instruction] + stop: StopInstruction, + + #[instruction] + loadfp: LoadFpInstruction, + + // ALU instructions + #[instruction(add_u32)] + add32: Add32Instruction, + + #[instruction(sub_u32)] + sub32: Sub32Instruction, + + #[instruction(mul_u32)] + mul32: Mul32Instruction, + + #[instruction(mul_u32)] + mulhs32: Mulhs32Instruction, + + #[instruction(mul_u32)] + mulhu32: Mulhu32Instruction, + + #[instruction(div_u32)] + div32: Div32Instruction, + + #[instruction(div_u32)] + sdiv32: SDiv32Instruction, + + #[instruction(shift_u32)] + shl32: Shl32Instruction, + + #[instruction(shift_u32)] + shr32: Shr32Instruction, + + #[instruction(shift_u32)] + sra32: Sra32Instruction, + + #[instruction(lt_u32)] + lt32: Lt32Instruction, + + #[instruction(lt_u32)] + lte32: Lte32Instruction, + + #[instruction(bitwise_u32)] + and32: And32Instruction, + + #[instruction(bitwise_u32)] + or32: Or32Instruction, + + #[instruction(bitwise_u32)] + xor32: Xor32Instruction, + + #[instruction(com_u32)] + ne32: Ne32Instruction, + + #[instruction(com_u32)] + eq32: Eq32Instruction, + + // Input/output instructions + #[instruction] + read: ReadAdviceInstruction, + + #[instruction(output)] + write: WriteInstruction, + + #[chip] + cpu: CpuChip, + + #[chip] + program: ProgramChip, + + #[chip] + mem: MemoryChip, + + #[chip] + add_u32: Add32Chip, + + #[chip] + sub_u32: Sub32Chip, + + #[chip] + mul_u32: Mul32Chip, + + #[chip] + div_u32: Div32Chip, + + #[chip] + shift_u32: Shift32Chip, + + #[chip] + lt_u32: Lt32Chip, + + #[chip] + com_u32: Com32Chip, + + #[chip] + bitwise_u32: Bitwise32Chip, + + #[chip] + output: OutputChip, + + #[chip] + range: RangeCheckerChip<256>, + + #[chip] + #[static_data_chip] + static_data: StaticDataChip, + + _phantom_sc: PhantomData F>, +} + +impl MachineWithGeneralBus for BasicMachine { + fn general_bus(&self) -> BusArgument { + BusArgument::Global(0) + } +} + +impl MachineWithProgramBus for BasicMachine { + fn program_bus(&self) -> BusArgument { + BusArgument::Global(1) + } +} + +impl MachineWithMemBus for BasicMachine { + fn mem_bus(&self) -> BusArgument { + BusArgument::Global(2) + } +} + +impl MachineWithRangeBus8 for BasicMachine { + fn range_bus(&self) -> BusArgument { + BusArgument::Global(3) + } +} + +impl MachineWithCpuChip for BasicMachine { + fn cpu(&self) -> &CpuChip { + &self.cpu + } + + fn cpu_mut(&mut self) -> &mut CpuChip { + &mut self.cpu + } +} + +impl MachineWithProgramChip for BasicMachine { + fn program(&self) -> &ProgramChip { + &self.program + } + + fn program_mut(&mut self) -> &mut ProgramChip { + &mut self.program + } +} + +impl MachineWithMemoryChip for BasicMachine { + fn mem(&self) -> &MemoryChip { + &self.mem + } + + fn mem_mut(&mut self) -> &mut MemoryChip { + &mut self.mem + } +} + +impl MachineWithAdd32Chip for BasicMachine { + fn add_u32(&self) -> &Add32Chip { + &self.add_u32 + } + + fn add_u32_mut(&mut self) -> &mut Add32Chip { + &mut self.add_u32 + } +} + +impl MachineWithSub32Chip for BasicMachine { + fn sub_u32(&self) -> &Sub32Chip { + &self.sub_u32 + } + + fn sub_u32_mut(&mut self) -> &mut Sub32Chip { + &mut self.sub_u32 + } +} + +impl MachineWithMul32Chip for BasicMachine { + fn mul_u32(&self) -> &Mul32Chip { + &self.mul_u32 + } + + fn mul_u32_mut(&mut self) -> &mut Mul32Chip { + &mut self.mul_u32 + } +} + +impl MachineWithDiv32Chip for BasicMachine { + fn div_u32(&self) -> &Div32Chip { + &self.div_u32 + } + + fn div_u32_mut(&mut self) -> &mut Div32Chip { + &mut self.div_u32 + } +} + +impl MachineWithBitwise32Chip for BasicMachine { + fn bitwise_u32(&self) -> &Bitwise32Chip { + &self.bitwise_u32 + } + + fn bitwise_u32_mut(&mut self) -> &mut Bitwise32Chip { + &mut self.bitwise_u32 + } +} + +impl MachineWithLt32Chip for BasicMachine { + fn lt_u32(&self) -> &Lt32Chip { + &self.lt_u32 + } + + fn lt_u32_mut(&mut self) -> &mut Lt32Chip { + &mut self.lt_u32 + } +} +impl MachineWithCom32Chip for BasicMachine { + fn com_u32(&self) -> &Com32Chip { + &self.com_u32 + } + + fn com_u32_mut(&mut self) -> &mut Com32Chip { + &mut self.com_u32 + } +} + +impl MachineWithShift32Chip for BasicMachine { + fn shift_u32(&self) -> &Shift32Chip { + &self.shift_u32 + } + + fn shift_u32_mut(&mut self) -> &mut Shift32Chip { + &mut self.shift_u32 + } +} + +impl MachineWithOutputChip for BasicMachine { + fn output(&self) -> &OutputChip { + &self.output + } + + fn output_mut(&mut self) -> &mut OutputChip { + &mut self.output + } +} + +impl MachineWithRangeChip for BasicMachine { + fn range(&self) -> &RangeCheckerChip<256> { + &self.range + } + + fn range_mut(&mut self) -> &mut RangeCheckerChip<256> { + &mut self.range + } +} + +impl MachineWithStaticDataChip for BasicMachine { + fn static_data(&self) -> &StaticDataChip { + &self.static_data + } + + fn static_data_mut(&mut self) -> &mut StaticDataChip { + &mut self.static_data + } +} diff --git a/basic_macro/tests/programs/assembly/fibonacci.val b/basic_macro/tests/programs/assembly/fibonacci.val new file mode 100644 index 00000000..7caf9384 --- /dev/null +++ b/basic_macro/tests/programs/assembly/fibonacci.val @@ -0,0 +1,38 @@ +main: + imm32 -4(fp), 0, 0, 0, 0 + ; Read the fibonacci number count from input + advread -8 + addi -16(fp), -8(fp), 0 + imm32 -20(fp), 0, 0, 0, 28 + jal -28(fp), fib, -28 + addi -12(fp), -24(fp), 0 + addi 4(fp), -12(fp), 0 + ; Write the result to output + write 0, 4, 0, 0, 1 + divi 4, 4, 256 + write 0, 4, 0, 0, 1 + divi 4, 4, 256 + write 0, 4, 0, 0, 1 + divi 4, 4, 256 + write 0, 4, 0, 0, 1 + stop +fib: + addi -4(fp), 12(fp), 0 + imm32 -8(fp), 0, 0, 0, 0 + imm32 -12(fp), 0, 0, 0, 1 + imm32 -16(fp), 0, 0, 0, 0 + beq .LBB0_1, 0(fp), 0(fp) +.LBB0_1: + bne .LBB0_2, -16(fp), -4(fp) + beq .LBB0_4, 0(fp), 0(fp) +.LBB0_2: + add -20(fp), -8(fp), -12(fp) + addi -8(fp), -12(fp), 0 + addi -12(fp), -20(fp), 0 + beq .LBB0_3, 0(fp), 0(fp) +.LBB0_3: + addi -16(fp), -16(fp), 1 + beq .LBB0_1, 0(fp), 0(fp) +.LBB0_4: + addi 4(fp), -8(fp), 0 + jalv -4(fp), 0(fp), 8(fp) diff --git a/basic_macro/tests/programs/assembly/subtraction.val b/basic_macro/tests/programs/assembly/subtraction.val new file mode 100644 index 00000000..7a57c107 --- /dev/null +++ b/basic_macro/tests/programs/assembly/subtraction.val @@ -0,0 +1,7 @@ +main: + ; TODO: Test different classes of input + imm32 0(fp), 0, 0, 0, 12 + imm32 -4(fp), 0, 0, 0, 5 + sub 4(fp), 0(fp), -4(fp) + write 0, 4(fp), 0, 0, 1 + stop diff --git a/basic_macro/tests/programs/binary/fibonacci.bin b/basic_macro/tests/programs/binary/fibonacci.bin new file mode 100644 index 00000000..36ef4ce1 Binary files /dev/null and b/basic_macro/tests/programs/binary/fibonacci.bin differ diff --git a/basic_macro/tests/programs/binary/subtraction.bin b/basic_macro/tests/programs/binary/subtraction.bin new file mode 100644 index 00000000..be5cf6e0 Binary files /dev/null and b/basic_macro/tests/programs/binary/subtraction.bin differ diff --git a/basic_macro/tests/test_interpreter.rs b/basic_macro/tests/test_interpreter.rs new file mode 100644 index 00000000..12af4a9b --- /dev/null +++ b/basic_macro/tests/test_interpreter.rs @@ -0,0 +1,43 @@ +use p3_baby_bear::BabyBear; +use std::fs::read_to_string; +use valida_assembler::assemble; +use valida_basic_macro::BasicMachine; +use valida_cpu::MachineWithCpuChip; +use valida_machine::{FixedAdviceProvider, Machine, ProgramROM}; +use valida_output::MachineWithOutputChip; +use valida_program::MachineWithProgramChip; + +#[test] +fn run_fibonacci() { + let mut machine = BasicMachine::::default(); + let asm_path = "tests/programs/assembly/fibonacci.val"; + let asm = read_to_string(asm_path).expect("Failed to read asm"); + let rom = ProgramROM::from_machine_code(&assemble(&asm).unwrap()); + machine.program_mut().set_program_rom(&rom); + machine.cpu_mut().fp = 16777216; // default stack height + machine.cpu_mut().save_register_state(); + + let fib_number = 25; + // Put the desired fib number in the advice tape. + let mut advice = FixedAdviceProvider::new(vec![fib_number]); + + // Run the program + machine.run(&rom, &mut advice); + let output = machine.output().bytes(); + assert_eq!(output.len(), 4); + let actual_result = u32::from_le_bytes(output.try_into().unwrap()); + + let expected_result = fibonacci(fib_number); + assert_eq!(actual_result, expected_result); +} + +fn fibonacci(n: u8) -> u32 { + let mut a = 0u32; + let mut b = 1u32; + for _ in 0..n { + let temp = a; + a = b; + (b, _) = temp.overflowing_add(b); + } + a +} diff --git a/basic_macro/tests/test_prover.rs b/basic_macro/tests/test_prover.rs new file mode 100644 index 00000000..0a1a0cad --- /dev/null +++ b/basic_macro/tests/test_prover.rs @@ -0,0 +1,262 @@ +extern crate core; + +use p3_baby_bear::BabyBear; +use p3_fri::{TwoAdicFriPcs, TwoAdicFriPcsConfig}; +use valida_alu_u32::add::{Add32Instruction, MachineWithAdd32Chip}; +use valida_basic_macro::BasicMachine; +use valida_cpu::{ + BeqInstruction, BneInstruction, Imm32Instruction, JalInstruction, JalvInstruction, + MachineWithCpuChip, StopInstruction, +}; +use valida_machine::{ + FixedAdviceProvider, Instruction, InstructionWord, Machine, MachineProof, Operands, ProgramROM, + Word, +}; + +use valida_memory::MachineWithMemoryChip; +use valida_opcodes::BYTES_PER_INSTR; +use valida_program::MachineWithProgramChip; + +use p3_challenger::DuplexChallenger; +use p3_dft::Radix2Bowers; +use p3_field::extension::BinomialExtensionField; +use p3_field::Field; +use p3_fri::FriConfig; +use p3_keccak::Keccak256Hash; +use p3_mds::coset_mds::CosetMds; +use p3_merkle_tree::FieldMerkleTreeMmcs; +use p3_poseidon::Poseidon; +use p3_symmetric::{CompressionFunctionFromHasher, SerializingHasher32}; +use rand::thread_rng; +use valida_machine::StarkConfigImpl; +use valida_machine::__internal::p3_commit::ExtensionMmcs; + +#[test] +fn prove_fibonacci() { + let mut program = vec![]; + + // Label locations + let bytes_per_instr = BYTES_PER_INSTR as i32; + let fib_bb0 = 8 * bytes_per_instr; + let fib_bb0_1 = 13 * bytes_per_instr; + let fib_bb0_2 = 15 * bytes_per_instr; + let fib_bb0_3 = 19 * bytes_per_instr; + let fib_bb0_4 = 21 * bytes_per_instr; + + //main: ; @main + //; %bb.0: + // imm32 -4(fp), 0, 0, 0, 0 + // imm32 -8(fp), 0, 0, 0, 10 + // addi -16(fp), -8(fp), 0 + // imm32 -20(fp), 0, 0, 0, 28 + // jal -28(fp), fib, -28 + // addi -12(fp), -24(fp), 0 + // addi 4(fp), -12(fp), 0 + // exit + //... + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-4, 0, 0, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-8, 0, 0, 0, 25]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-16, -8, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-20, 0, 0, 0, 28]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-28, fib_bb0, -28, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-12, -24, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([4, -12, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands::default(), + }, + ]); + + //fib: ; @fib + //; %bb.0: + // addi -4(fp), 12(fp), 0 + // imm32 -8(fp), 0, 0, 0, 0 + // imm32 -12(fp), 0, 0, 0, 1 + // imm32 -16(fp), 0, 0, 0, 0 + // beq .LBB0_1, 0(fp), 0(fp) + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-4, 12, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-8, 0, 0, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-12, 0, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-16, 0, 0, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([fib_bb0_1, 0, 0, 0, 0]), + }, + ]); + + //.LBB0_1: + // bne .LBB0_2, -16(fp), -4(fp) + // beq .LBB0_4, 0(fp), 0(fp) + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([fib_bb0_2, -16, -4, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([fib_bb0_4, 0, 0, 0, 0]), + }, + ]); + + //; %bb.2: + // add -20(fp), -8(fp), -12(fp) + // addi -8(fp), -12(fp), 0 + // addi -12(fp), -20(fp), 0 + // beq .LBB0_3, 0(fp), 0(fp) + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-20, -8, -12, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-8, -12, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-12, -20, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([fib_bb0_3, 0, 0, 0, 0]), + }, + ]); + + //; %bb.3: + // addi -16(fp), -16(fp), 1 + // beq .LBB0_1, 0(fp), 0(fp) + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-16, -16, 1, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([fib_bb0_1, 0, 0, 0, 0]), + }, + ]); + + //.LBB0_4: + // addi 4(fp), -8(fp), 0 + // jalv -4(fp), 0(fp), 8(fp) + program.extend([ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([4, -8, 0, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-4, 0, 8, 0, 0]), + }, + ]); + + let mut machine = BasicMachine::::default(); + let rom = ProgramROM::new(program); + machine.program_mut().set_program_rom(&rom); + machine.cpu_mut().fp = 0x1000; + machine.cpu_mut().save_register_state(); // TODO: Initial register state should be saved + // automatically by the machine, not manually here + machine.run(&rom, &mut FixedAdviceProvider::empty()); + + type Val = BabyBear; + type Challenge = BinomialExtensionField; + type PackedChallenge = BinomialExtensionField<::Packing, 5>; + + type Mds16 = CosetMds; + let mds16 = Mds16::default(); + + type Perm16 = Poseidon; + let perm16 = Perm16::new_from_rng(4, 22, mds16, &mut thread_rng()); // TODO: Use deterministic RNG + + type MyHash = SerializingHasher32; + let hash = MyHash::new(Keccak256Hash {}); + + type MyCompress = CompressionFunctionFromHasher; + let compress = MyCompress::new(hash); + + type ValMmcs = FieldMerkleTreeMmcs; + let val_mmcs = ValMmcs::new(hash, compress); + + type ChallengeMmcs = ExtensionMmcs; + let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone()); + + type Dft = Radix2Bowers; + let dft = Dft::default(); + + type Challenger = DuplexChallenger; + + type MyFriConfig = TwoAdicFriPcsConfig; + let fri_config = FriConfig { + log_blowup: 1, + num_queries: 40, + proof_of_work_bits: 8, + mmcs: challenge_mmcs, + }; + + type Pcs = TwoAdicFriPcs; + type MyConfig = StarkConfigImpl; + + let pcs = Pcs::new(fri_config, dft, val_mmcs); + + let challenger = Challenger::new(perm16); + let config = MyConfig::new(pcs, challenger); + let proof = machine.prove(&config); + + let mut bytes = vec![]; + ciborium::into_writer(&proof, &mut bytes).expect("serialization failed"); + println!("Proof size: {} bytes", bytes.len()); + let deserialized_proof: MachineProof = + ciborium::from_reader(bytes.as_slice()).expect("deserialization failed"); + + machine + .verify(&config, &proof) + .expect("verification failed"); + machine + .verify(&config, &deserialized_proof) + .expect("verification failed"); + + assert_eq!(machine.cpu().clock, 192); + assert_eq!(machine.cpu().operations.len(), 192); + assert_eq!(machine.mem().operations.values().flatten().count(), 401); + assert_eq!(machine.add_u32().operations.len(), 105); + + assert_eq!( + *machine.mem().cells.get(&(0x1000 + 4)).unwrap(), // Return value + Word([0, 1, 37, 17,]) // 25th fibonacci number (75025) + ); +} diff --git a/basic_macro/tests/test_static_data.rs b/basic_macro/tests/test_static_data.rs new file mode 100644 index 00000000..6d63046e --- /dev/null +++ b/basic_macro/tests/test_static_data.rs @@ -0,0 +1,113 @@ +extern crate core; + +use p3_baby_bear::BabyBear; +use p3_fri::{TwoAdicFriPcs, TwoAdicFriPcsConfig}; +use valida_basic_macro::BasicMachine; +use valida_cpu::{ + BneInstruction, Imm32Instruction, Load32Instruction, MachineWithCpuChip, StopInstruction, +}; +use valida_machine::{ + FixedAdviceProvider, Instruction, InstructionWord, Machine, Operands, ProgramROM, Word, +}; + +use valida_program::MachineWithProgramChip; +use valida_static_data::MachineWithStaticDataChip; + +use p3_challenger::DuplexChallenger; +use p3_dft::Radix2Bowers; +use p3_field::extension::BinomialExtensionField; +use p3_field::Field; +use p3_fri::FriConfig; +use p3_keccak::Keccak256Hash; +use p3_mds::coset_mds::CosetMds; +use p3_merkle_tree::FieldMerkleTreeMmcs; +use p3_poseidon::Poseidon; +use p3_symmetric::{CompressionFunctionFromHasher, SerializingHasher32}; +use rand::thread_rng; +use valida_machine::StarkConfigImpl; +use valida_machine::__internal::p3_commit::ExtensionMmcs; + +#[test] +fn prove_static_data() { + // _start: + // imm32 0(fp), 0, 0, 0, 0x10 + // load32 -4(fp), 0(fp), 0, 0, 0 + // bnei _start, 0(fp), 0x25, 0, 1 // infinite loop unless static value is loaded + // stop + let program = vec![ + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([0, 0, 0, 0, 0x10]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([-4, 0, 0, 0, 0]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands([0, -4, 0x25, 0, 1]), + }, + InstructionWord { + opcode: , Val>>::OPCODE, + operands: Operands::default(), + }, + ]; + + let mut machine = BasicMachine::::default(); + let rom = ProgramROM::new(program); + machine.static_data_mut().write(0x10, Word([0, 0, 0, 0x25])); + machine.static_data_mut().write(0x14, Word([0, 0, 0, 0x32])); + machine.program_mut().set_program_rom(&rom); + machine.cpu_mut().fp = 0x1000; + machine.cpu_mut().save_register_state(); // TODO: Initial register state should be saved + // automatically by the machine, not manually here + + machine.run(&rom, &mut FixedAdviceProvider::empty()); + + type Val = BabyBear; + type Challenge = BinomialExtensionField; + type PackedChallenge = BinomialExtensionField<::Packing, 5>; + + type Mds16 = CosetMds; + let mds16 = Mds16::default(); + + type Perm16 = Poseidon; + let perm16 = Perm16::new_from_rng(4, 22, mds16, &mut thread_rng()); // TODO: Use deterministic RNG + + type MyHash = SerializingHasher32; + let hash = MyHash::new(Keccak256Hash {}); + + type MyCompress = CompressionFunctionFromHasher; + let compress = MyCompress::new(hash); + + type ValMmcs = FieldMerkleTreeMmcs; + let val_mmcs = ValMmcs::new(hash, compress); + + type ChallengeMmcs = ExtensionMmcs; + let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone()); + + type Dft = Radix2Bowers; + let dft = Dft::default(); + + type Challenger = DuplexChallenger; + + type MyFriConfig = TwoAdicFriPcsConfig; + let fri_config = FriConfig { + log_blowup: 1, + num_queries: 40, + proof_of_work_bits: 8, + mmcs: challenge_mmcs, + }; + + type Pcs = TwoAdicFriPcs; + type MyConfig = StarkConfigImpl; + + let pcs = Pcs::new(fri_config, dft, val_mmcs); + + let challenger = Challenger::new(perm16); + let config = MyConfig::new(pcs, challenger); + let proof = machine.prove(&config); + machine + .verify(&config, &proof) + .expect("verification failed"); +} diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 65c4b138..34ec4f8e 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -149,18 +149,6 @@ fn run_method( let name = &machine.ident; let (_, ty_generics, _) = machine.generics.split_for_impl(); - let opcode_arms = instructions - .iter() - .map(|inst| { - let ty = &inst.ty; - quote! { - // TODO: Self instead of #name #ty_generics? - <#ty as Instruction<#name #ty_generics, #val>>::OPCODE => - #ty::execute_with_advice::(self, ops, advice), - } - }) - .collect::(); - let init_static_data: TokenStream2 = match static_data_chip { Some(_static_data_chip) => quote! { self.initialize_memory(); @@ -173,25 +161,10 @@ fn run_method( #init_static_data loop { - // Fetch - let pc = self.cpu().pc; - let instruction = program.get_instruction(pc); - let opcode = instruction.opcode; - let ops = instruction.operands; - - // Execute - std::println!("trace: pc = {:?}, instruction = {:?}, ops = {:?}", pc, instruction, ops); - match opcode { - #opcode_arms - _ => panic!("Unrecognized opcode: {}", opcode), - }; - self.read_word(pc as usize); - - //let stop = self.step(&program, &mut advice); - // A STOP instruction signals the end of the program - if opcode == >::OPCODE { - break; - } + let step_did_stop = self.step(advice); + if step_did_stop == StoppingFlag::DidStop { + break; + } } // Record padded STOP instructions @@ -221,7 +194,7 @@ fn step_method(machine: &syn::DeriveInput, instructions: &[&Field], val: &Ident) .collect::(); quote! { - fn step(&mut self, advice: &mut Adv) -> bool { + fn step(&mut self, advice: &mut Adv) -> StoppingFlag { let pc = self.cpu().pc; let instruction = self.program.program_rom.get_instruction(pc); let opcode = instruction.opcode; @@ -233,7 +206,11 @@ fn step_method(machine: &syn::DeriveInput, instructions: &[&Field], val: &Ident) }; self.read_word(pc as usize); - opcode == >::OPCODE + if opcode == >::OPCODE { + StoppingFlag::DidStop + } else { + StoppingFlag::DidNotStop + } } } } @@ -287,7 +264,7 @@ fn prove_method(chips: &[&Field]) -> TokenStream2 { preprocessed_trace_lde, main_trace_ldes.remove(0), perm_trace_ldes.remove(0), - cummulative_sums[#i], + cumulative_sums[#i], &perm_challenges, alpha, )); @@ -366,7 +343,7 @@ fn prove_method(chips: &[&Field]) -> TokenStream2 { }).collect::>() ); - let cummulative_sums = perm_traces.iter() + let cumulative_sums = perm_traces.iter() .map(|trace| trace.row_slice(trace.height() - 1).last().unwrap().clone()) .collect::>(); @@ -571,7 +548,7 @@ fn verify_method(chips: &[&Field]) -> TokenStream2 { ]; // Get the generators of the trace subgroups for each chip. - let g_subgroups :[SC::Val ; #num_chips] = proof.chip_proofs + let g_subgroups: [SC::Val; #num_chips] = proof.chip_proofs .iter() .map(|chip_proof| SC::Val::two_adic_generator(chip_proof.log_degree)) .collect::>().try_into().unwrap(); @@ -599,7 +576,6 @@ fn verify_method(chips: &[&Field]) -> TokenStream2 { let chips_opening_values = vec![main_values, perm_values, quotient_values]; - // Observe commitments and get challenges. let Commitments { main_trace, @@ -607,7 +583,6 @@ fn verify_method(chips: &[&Field]) -> TokenStream2 { quotient_chunks, } = &proof.commitments; - // Compute the commitments to preprocessed traces (TODO: avoid in the future) let preprocessed_traces: Vec> = tracing::info_span!("generate preprocessed traces") @@ -623,7 +598,6 @@ fn verify_method(chips: &[&Field]) -> TokenStream2 { challenger.observe(preprocessed_commit.clone()); - // challenger.observe(preprocessed_commit.clone()); challenger.observe(main_trace.clone()); let mut perm_challenges = Vec::new(); @@ -637,15 +611,16 @@ fn verify_method(chips: &[&Field]) -> TokenStream2 { challenger.observe(quotient_chunks.clone()); - // Verify the openning proof. - let zeta: SC::Challenge = challenger.sample_ext_element(); - let zeta_and_next: [Vec; #num_chips] = - g_subgroups.map(|g| vec![zeta, zeta * g]); - let zeta_exp_quotient_degree: [Vec; #num_chips] = - log_quotient_degrees.map(|log_deg| vec![zeta.exp_power_of_2(log_deg)]); + // Verify the opening proof. + let zeta: SC::Challenge = challenger.sample_ext_element(); + let zeta_and_next: [Vec; #num_chips] = + g_subgroups.map(|g| vec![zeta, zeta * g]); + let zeta_exp_quotient_degree: [Vec; #num_chips] = + log_quotient_degrees.map(|log_deg| vec![zeta.exp_power_of_2(log_deg)]); pcs .verify_multi_batches( &[ + // TODO: add preprocessed trace (main_trace.clone(), zeta_and_next.as_slice()), (perm_trace.clone(), zeta_and_next.as_slice()), (quotient_chunks.clone(), zeta_exp_quotient_degree.as_slice()), diff --git a/machine/src/machine.rs b/machine/src/machine.rs index 70d64126..8122dbf0 100644 --- a/machine/src/machine.rs +++ b/machine/src/machine.rs @@ -4,12 +4,18 @@ use crate::proof::MachineProof; use crate::AdviceProvider; use p3_field::Field; +#[derive(PartialEq, Eq)] +pub enum StoppingFlag { + DidStop, + DidNotStop, +} + pub trait Machine: Sync { fn run(&mut self, program: &ProgramROM, advice: &mut Adv) where Adv: AdviceProvider; - fn step(&mut self, advice: &mut Adv) -> bool + fn step(&mut self, advice: &mut Adv) -> StoppingFlag where Adv: AdviceProvider;