From 25c7bc6357d2e28106713264e1a2515f0a58a97b Mon Sep 17 00:00:00 2001 From: nikkolasg Date: Tue, 21 Nov 2023 16:46:20 +0100 Subject: [PATCH 1/7] rlp + tests --- Cargo.lock | 973 +++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 10 + src/lib.rs | 16 +- src/rlp.rs | 768 ++++++++++++++++++++++++++++++++++++++++ src/utils.rs | 354 +++++++++++++++++++ 5 files changed, 2107 insertions(+), 14 deletions(-) create mode 100644 Cargo.lock create mode 100644 src/rlp.rs create mode 100644 src/utils.rs diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..facf89616 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,973 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +dependencies = [ + "cfg-if", + "const-random", + "once_cell", + "version_check", + "zerocopy", +] + +[[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 = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[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.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + +[[package]] +name = "const-random" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.39", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "fixed-hash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +dependencies = [ + "ahash", + "rayon", + "serde", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +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 = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2bd4c29270e724d3eaadf7bdc8700af4221fc0ed771b855eadcd1b98d52851" +dependencies = [ + "primitive-types", + "tiny-keccak", +] + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "mapreduce-plonky2" +version = "0.1.0" +dependencies = [ + "anyhow", + "itertools 0.12.0", + "plonky2", + "plonky2_crypto", + "rlp", + "serde", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", + "rand", +] + +[[package]] +name = "num-complex" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "plonky2" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c7acc7871fdaf000d3533116eab95d89ada3dfb82b7bb0231da981323c27d6" +dependencies = [ + "ahash", + "anyhow", + "getrandom", + "hashbrown 0.14.2", + "itertools 0.11.0", + "keccak-hash", + "log", + "num", + "plonky2_field", + "plonky2_maybe_rayon", + "plonky2_util", + "rand", + "rand_chacha", + "serde", + "serde_json", + "static_assertions", + "unroll", +] + +[[package]] +name = "plonky2_crypto" +version = "0.1.0" +source = "git+https://github.com/nikkolasg/plonky2-crypto#011183a3cf5e5b67e5e47c88954f629cdb8b7d2a" +dependencies = [ + "anyhow", + "hex", + "itertools 0.10.5", + "num", + "plonky2", + "plonky2_maybe_rayon", + "rand", + "rayon", + "serde", + "serde_with", +] + +[[package]] +name = "plonky2_field" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d33a655ab5d274f763c292fe7e14577f25e40d9d8607b70ef10b39f8619e60b4" +dependencies = [ + "anyhow", + "itertools 0.11.0", + "num", + "plonky2_util", + "rand", + "serde", + "static_assertions", + "unroll", +] + +[[package]] +name = "plonky2_maybe_rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194db0cbdd974e92d897cd92b74adb3968dc1b967315eb280357c49a7637994e" +dependencies = [ + "rayon", +] + +[[package]] +name = "plonky2_util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5696e2e2a6bb5c48a6e33fb0dd4d20d0a9472784b709964f337f224e99bd6d06" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "primitive-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" +dependencies = [ + "fixed-hash", + "uint", +] + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[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.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "time" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +dependencies = [ + "deranged", + "itoa", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unroll" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad948c1cb799b1a70f836077721a92a35ac177d4daddf4c20a633786d4cf618" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.39", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +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", +] + +[[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_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[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_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[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_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "zerocopy" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] diff --git a/Cargo.toml b/Cargo.toml index 6e82a7adc..90684ab19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +itertools = "0.12.0" +plonky2 = "0.1.4" + +# supporting latest plonky2 +plonky2_crypto = { git = "https://github.com/nikkolasg/plonky2-crypto" } +serde = "1.0.193" + +[dev-dependencies] +anyhow = "1.0.75" +rlp = "0.5.2" diff --git a/src/lib.rs b/src/lib.rs index 7d12d9af8..5c953234e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,2 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +mod rlp; +mod utils; diff --git a/src/rlp.rs b/src/rlp.rs new file mode 100644 index 000000000..f57cad9fa --- /dev/null +++ b/src/rlp.rs @@ -0,0 +1,768 @@ +use crate::utils::{greater_than_or_equal_to, less_than, less_than_or_equal_to}; +use plonky2::field::extension::Extendable; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::target::Target; +use plonky2::plonk::circuit_builder::CircuitBuilder; + +// nikko: Seems like this constant means the maximum number of bytes the length of data +// can take. However, this is set arbitrarily because there can be up 7 bytes +// expressing the length of the data according to RLP specs for long lists +// size = prefix - 248 (where prefix is a single byte so can go up to 255) +pub const MAX_LEN_BYTES: usize = 2; + +// nikko: I assume this is a practical consideration that tx and storage and receipts +// don't have more than 17 fields and each items list don't have more than 17? +pub const MAX_FIELDS: usize = 17; + +/// Whether the data represents a list or a string. +pub const STRING: usize = 0; +/// Whether the data represents a list or a string. +pub const LIST: usize = 1; + +#[derive(Clone, Copy, Debug)] +pub struct RlpHeader { + // Length of the actual data + pub len: Target, + // offset from which to read the data from the array + pub offset: Target, + // whether it's a string or a list + pub data_type: Target, +} + +/// Contains the header information for all the elements in a list. +#[derive(Clone, Copy, Debug)] +pub struct RlpList { + pub offset: [Target; N], + pub len: [Target; N], + pub data_type: [Target; N], + pub num_fields: Target, +} + +// Returns the length from the RLP prefix in case of long string or long list +// data is the full data starting from the "type" byte of RLP encoding +// data length needs to be a power of 2 +// non power of 2 lengths are padded leading zeros +pub fn data_len, const D: usize>( + b: &mut CircuitBuilder, + data: &[Target], + len_of_len: Target, +) -> Target { + let mut res = b.zero(); + let const_256 = b.constant(F::from_canonical_u64(256)); + let arr_len = data.len(); + + for i in 0..MAX_LEN_BYTES { + // this makes sure we don't read outside of the data length: it can happen + // because we call this function in circuit regardless of the actual + // type of rlp data. If it's a single short value, then reading after 1st byte + // might just fail. + let arr_len_pred: usize = if i + 1 < arr_len { 1 } else { 0 }; + + let i_target = b.constant(F::from_canonical_usize(i)); + let len_of_len_pred = less_than(b, i_target, len_of_len, 8); + + // i+1 because first byte is the RLP type + let arr_access = data[(i + 1) * arr_len_pred]; + // shift result by one byte + let multiplicand = b.mul(const_256, res); + // res += 2^i * arr[i+1] only if we're in right range + let sum = b.add(multiplicand, arr_access); + let multiplicand_2 = b.mul(sum, len_of_len_pred.target); + + let not_len_of_len_pred_target = b.not(len_of_len_pred); + let multiplicand_3 = b.mul(not_len_of_len_pred_target.target, res); + // res = (2^i * arr[i+1]) * (i < len_len) + res * (i >= len_len) + res = b.add(multiplicand_2, multiplicand_3); + } + + res +} + +/// Returns the header of this RLP encoded data. +pub fn decode_header, const D: usize>( + b: &mut CircuitBuilder, + data: &[Target], +) -> RlpHeader { + let one = b.one(); + let zero = b.zero(); + + let prefix = data[0]; + + let byte_80 = b.constant(F::from_canonical_usize(128)); + let byte_b7 = b.constant(F::from_canonical_usize(183)); + let byte_b8 = b.constant(F::from_canonical_usize(184)); + let byte_c0 = b.constant(F::from_canonical_usize(192)); + let byte_f7 = b.constant(F::from_canonical_usize(247)); + let byte_f8 = b.constant(F::from_canonical_usize(248)); + + let prefix_less_0x80 = less_than(b, prefix, byte_80, 8); + let prefix_less_0xb8 = less_than(b, prefix, byte_b8, 8); + let prefix_less_0xc0 = less_than(b, prefix, byte_c0, 8); + let prefix_less_0xf8 = less_than(b, prefix, byte_f8, 8); + + // This part determines at which offset should we read the data + let prefix_plus_one = b.add(prefix, one); + // if it's in [0xf8,0xff] -> long list, offset to read the data from arr[prefix-0xf7+1:] + let prefix_plus_one_minus_f7 = b.sub(prefix_plus_one, byte_f7); + // select1 = if prefix < 0xf8 { 1 } else { prefix + 1 - 0xf7 } + // i.e. if it's in [0xc0,0xf7] -> short list, offset of 1 cause length already encoded in first byte + // nikko XXX TODO: We should handle the case of an empty list, 0xc0 + let select_1 = b._if(prefix_less_0xf8, one, prefix_plus_one_minus_f7); + let prefix_plus_one_minus_b7 = b.sub(prefix_plus_one, byte_b7); + // select2 = if prefix < 0xc0 { prefix + 1 - 0xb7 } else { select1 } + // i.e. if it's in [0xb8,0xbf] -> long string, and we read data from arr[prefix-0xb7+1:] + let select_2 = b._if(prefix_less_0xc0, prefix_plus_one_minus_b7, select_1); + // select3 = if prefix < 0xb8 { 1 } else { select2 } + // i.e. if it's in [0x80,0xb8] -> short string, 1 offset because length already encoded in first byte + let select_3 = b._if(prefix_less_0xb8, one, select_2); + // offset = if prefix < 0x80 { 0 } else { select3 } + // i.e. if it's a single byte value, no offset we directly read value + let offset = b._if(prefix_less_0x80, zero, select_3); + + // read the lenght encoded depending on the type + let prefix_minus_f7 = b.sub(prefix, byte_f7); + let long_list_len = data_len(b, data, prefix_minus_f7); + let short_list_len = b.sub(prefix, byte_c0); + let select_1 = b._if(prefix_less_0xf8, short_list_len, long_list_len); + let prefix_minus_b7 = b.sub(prefix, byte_b7); + let long_str_len = data_len(b, data, prefix_minus_b7); + let select_2 = b._if(prefix_less_0xc0, long_str_len, select_1); + let short_str_len = b.sub(prefix, byte_80); + let select_3 = b._if(prefix_less_0xb8, short_str_len, select_2); + let len = b._if(prefix_less_0x80, one, select_3); + + let data_type = greater_than_or_equal_to(b, prefix, byte_c0, 8).target; + + RlpHeader { + len, + offset, + data_type, + } +} + +/// RLP String decoder : returns the offset in the array where string starts and +/// the length of the string. +/// It checks that the type is correctly a string and the length is within correct +/// range. +/// nikko: I dont think we need these extra checks - we should remove. +pub(crate) fn decode_str, const D: usize>( + b: &mut CircuitBuilder, + data: &[Target], +) -> (Target, Target) { + let rlp_header: RlpHeader = decode_header(b, data); + + let is_string = b.constant(F::from_canonical_usize(STRING)); + b.connect(rlp_header.data_type, is_string); + + let data_len = data.len(); + let total_len = b.add(rlp_header.len, rlp_header.offset); + let data_len_target = b.constant(F::from_canonical_usize(data_len)); + let is_lt = less_than(b, total_len, data_len_target, 63); + let true_pred = b._true(); + b.connect(is_lt.target, true_pred.target); + + (rlp_header.offset, rlp_header.len) +} + +/// Decodes a list of two elements. +pub(crate) fn decode_tuple, const D: usize>( + b: &mut CircuitBuilder, + data: &[Target], +) -> RlpList<2> { + decode_fixed_list::(b, data) +} + +/// Decodes a list of fixed number of items +pub fn decode_fixed_list, const D: usize, const N: usize>( + b: &mut CircuitBuilder, + data: &[Target], +) -> RlpList { + let zero = b.zero(); + let one = b.one(); + + let mut num_fields = zero; + let mut dec_off = [zero; N]; + let mut dec_len = [zero; N]; + let mut dec_type = [zero; N]; + + let RlpHeader { + len: payload_len, + offset: header_len, + data_type, + } = decode_header(b, data); + + // total_len includes the header byte + potential len_len bytes + payload len + let total_len = b.add(header_len, payload_len); + + let is_list = b.constant(F::from_canonical_usize(LIST)); + b.connect(is_list, data_type); + + let mut offset = header_len; + // decode each headers of each items ofthe list + // remember in a list each item of the list is RLP encoded + for i in 0..N { + // stop when you've looked at the whole expected length + let mut loop_p = b.is_equal(offset, total_len); + loop_p = b.not(loop_p); + + // read the header starting from the offset - + // nikko: this is assuming the header will take at least 1 bytes and less than 1 + MAX_LEN_BYTES + let header = take_dot_drop::(b, data, offset); + let RlpHeader { + len: field_len, + offset: field_offset, + data_type: field_type, + } = decode_header(b, &header); + let total_field_len = b.add(field_offset, field_len); + + let one_sub_field_type = b.sub(one, field_type); + // d_off_i = ((1-field_type) * field_offset + offset) * (offset != total_len) + // - if type is 0, str, then d_off_i basically = field_offset + offset + // - if type is 1, list, then d_off_i basically = offset because it's a list so we + // again need to decode the rlp header + let mut d_off_i = b.mul(one_sub_field_type, field_offset); + d_off_i = b.add(d_off_i, offset); + d_off_i = b.mul(loop_p.target, d_off_i); + + // d_len_i = ((field_type * field_offset) + field_len) * (offset != total_len) + // - if type is 0, str, then d_len_i = field_len + // - if type is 1, list, then d_len_i = field_offset + field_len + // index where to find the data within the item array + let mut d_len_i = b.mul(field_type, field_offset); + d_len_i = b.add(d_len_i, field_len); + d_len_i = b.mul(loop_p.target, d_len_i); + let d_type_i = b.mul(loop_p.target, field_type); + + dec_off[i] = d_off_i; + dec_len[i] = d_len_i; + dec_type[i] = d_type_i; + + // move offset to the next field in the list + offset = b.mul_add(loop_p.target, total_field_len, offset); + num_fields = b.add(num_fields, loop_p.target); + } + + // make sure the total length is equal to the added length of all items + // otherwise attacker could specify an inconsistent length in the first header + b.connect(total_len, offset); + + RlpList { + offset: dec_off, + len: dec_len, + data_type: dec_type, + num_fields, + } +} +/// RLP List decoder : returns the offsetS in the array where elementS start and +/// their respective lengthS +pub fn decode_list, const D: usize>( + b: &mut CircuitBuilder, + data: &[Target], +) -> RlpList { + let zero = b.zero(); + let one = b.one(); + + let mut num_fields = zero; + let mut dec_off = [zero; MAX_FIELDS]; + let mut dec_len = [zero; MAX_FIELDS]; + let mut dec_type = [zero; MAX_FIELDS]; + + let RlpHeader { + len: payload_len, + mut offset, + data_type, + } = decode_header(b, data); + + // total_len includes the header byte + potential len_len bytes + payload len + let total_len = b.add(offset, payload_len); + + let is_list = b.constant(F::from_canonical_usize(LIST)); + b.connect(is_list, data_type); + + for i in 0..MAX_FIELDS { + let mut loop_p = b.is_equal(offset, total_len); + loop_p = b.not(loop_p); + + // read the header starting from the offset - the header will at most 1 bytes + MAX_LEN_BYTES + // remember in a list each item of the list is RLP encoded + let header = take_dot_drop::(b, data, offset); + let RlpHeader { + len: field_len, + offset: field_offset, + data_type: field_type, + } = decode_header(b, &header); + let total_field_len = b.add(field_offset, field_len); + + let one_sub_field_type = b.sub(one, field_type); + // d_off_i = ((1-field_type) * field_offset + offset) * (offset != total_len) + // - if type is 0, str, then d_off_i basically = field_offset + offset + // -> value starts at offset + field_offset from the beginning of the given array + // - if type is 1, list, then d_off_i basically = offset because it's a list so we + // again need to decode the rlp header right at the offset? + let mut d_off_i = b.mul(one_sub_field_type, field_offset); + d_off_i = b.add(d_off_i, offset); + d_off_i = b.mul(loop_p.target, d_off_i); + + // d_len_i = ((field_type * field_offset) + field_len) * (offset != total_len) + // - if type is 0, str, then d_len_i = field_len + // - if type is 1, list, then d_len_i = field_offset + field_len + // index where to find the data within the item array + let mut d_len_i = b.mul(field_type, field_offset); + d_len_i = b.add(d_len_i, field_len); + d_len_i = b.mul(loop_p.target, d_len_i); + let d_type_i = b.mul(loop_p.target, field_type); + + dec_off[i] = d_off_i; + dec_len[i] = d_len_i; + dec_type[i] = d_type_i; + + // move offset to the next field in the list + offset = b.mul_add(loop_p.target, total_field_len, offset); + num_fields = b.add(num_fields, loop_p.target); + } + + // nikko: I think we can remove this - no need to check RLP is correct ! + b.connect(total_len, offset); + + RlpList { + offset: dec_off, + len: dec_len, + data_type: dec_type, + num_fields, + } +} + +/// decode a list whose length (= sum of its items) are less than 55 bytes +/// and all its items must be a string (no sub-list) +pub fn decode_short_list, const D: usize>( + b: &mut CircuitBuilder, + data: &[Target], +) -> RlpList { + let zero = b.zero(); + + let mut num_fields = zero; + let mut dec_off = [zero; MAX_FIELDS]; + let mut dec_len = [zero; MAX_FIELDS]; + let mut dec_type = [zero; MAX_FIELDS]; + + let RlpHeader { + len: payload_len, + mut offset, + data_type, + } = decode_header(b, data); + let total_len = b.add(offset, payload_len); + let true_pred = b._true(); + let is_list = b.constant(F::from_canonical_usize(LIST)); + b.connect(is_list, data_type); + + for i in 0..MAX_FIELDS { + let mut loop_p = b.is_equal(offset, total_len); + loop_p = b.not(loop_p); + + // let header = b.random_access(offset, data.to_vec()); + let header = quin_selector(b, data, offset); + + // assert(header < 0xb8); // Header must represent a string of length < 56 bytes. + let bytes_0xb8 = b.constant(F::from_canonical_usize(0xb8)); + let is_lt = less_than(b, header, bytes_0xb8, 63); + b.connect(is_lt.target, true_pred.target); + + let field_type = b.constant(F::from_canonical_usize(STRING)); + + let bytes_0x80 = b.constant(F::from_canonical_usize(0x80)); + let single_bytes_p = less_than(b, header, bytes_0x80, 63); + let field_off = b.not(single_bytes_p); + + let mut field_len = b.sub(header, bytes_0x80); + field_len = b.mul(field_len, field_off.target); + field_len = b.add(single_bytes_p.target, field_len); + + let total_field_len = b.add(field_off.target, field_len); + + let mut d_off_i = b.add(offset, field_off.target); + d_off_i = b.mul(loop_p.target, d_off_i); + let d_len_i = b.mul(loop_p.target, field_len); + let d_type_i = b.mul(loop_p.target, field_type); + + dec_off[i] = d_off_i; + dec_len[i] = d_len_i; + dec_type[i] = d_type_i; + + let offset_add = b.mul(loop_p.target, total_field_len); + offset = b.add(offset, offset_add); + num_fields = b.add(num_fields, loop_p.target); + } + + b.connect(total_len, offset); + + RlpList { + offset: dec_off, + len: dec_len, + data_type: dec_type, + num_fields, + } +} + +/// Returns an array of length `len` containing the elements of `array` starting at `offset`. +// nikko TODO: this is my own to hack around, and avoid take dot drop which is +// super expensive, but we should remove the call to quin_selector +// and directly make the constraints inside the loop, will remove the N^2 complexity +// into just linear ? +// TODO: remove and only use take_dot_drop if possible (and rename it to extract_array) +pub fn extract_array, const D: usize>( + b: &mut CircuitBuilder, + array: &[Target], + offset: Target, + len: usize, +) -> Vec { + (0..len) + .map(|i| { + let i_target = b.constant(F::from_canonical_usize(i)); + let offset_plus_i = b.add(offset, i_target); + quin_selector(b, array, offset_plus_i) + }) + .collect() +} + +/// Similar to extract_array but for a constant size. +/// nikko: Make it such other circuits only use this one. +pub fn take_dot_drop, const D: usize, const M: usize>( + b: &mut CircuitBuilder, + arr: &[Target], + offset: Target, +) -> [Target; M] { + let mut out: [Target; M] = [arr[0]; M]; + + let m = b.constant(F::from_canonical_usize(M)); + let upper_bound = b.add(offset, m); + for (i, out_val) in out.iter_mut().enumerate().take(M) { + let i_target = b.constant(F::from_canonical_usize(i)); + let i_plus_n_target = b.add(offset, i_target); + + // nikko: ((i + offset) <= n + M) + let lt = less_than_or_equal_to(b, i_plus_n_target, upper_bound, 63); + // ((i+n) <= n+M) * (i+n) + let j = b.mul(lt.target, i_plus_n_target); + + // out_val = arr[((i+n)<=n+M) * (i+n)] + *out_val = quin_selector(b, arr, j); + } + + out +} + +/// Returns an element of the array at index n +/// TODO: replace with random_access from plonky2 and compare constraints +pub fn quin_selector, const D: usize>( + b: &mut CircuitBuilder, + arr: &[Target], + n: Target, +) -> Target { + let mut nums: Vec = vec![]; + + for (i, el) in arr.iter().enumerate() { + let i_target = b.constant(F::from_canonical_usize(i)); + let is_eq = b.is_equal(i_target, n); + // (i == n (idx) ) * element + let product = b.mul(is_eq.target, *el); + nums.push(product); + } + // SUM_i (i == n (idx) ) * element + // -> sum = element + calculate_total(b, &nums) +} + +fn calculate_total, const D: usize>( + b: &mut CircuitBuilder, + arr: &[Target], +) -> Target { + b.add_many(arr) +} + +#[cfg(test)] +mod tests { + + use anyhow::Result; + + use plonky2::field::types::Field; + use plonky2::iop::target::Target; + use plonky2::iop::witness::{PartialWitness, WitnessWrite}; + use plonky2::plonk::circuit_builder::CircuitBuilder; + use plonky2::plonk::circuit_data::CircuitConfig; + use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + + use crate::rlp::{RlpHeader,MAX_LEN_BYTES }; + + #[test] + fn test_data_len() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let data: Vec = [185, 4, 0] + .iter() + .map(|x| builder.constant(F::from_canonical_u64(*x))) + .collect(); + let ret_target = builder.constant(F::from_canonical_u64(1024)); + + let len_of_len = builder.constant(F::from_canonical_u64(2)); + let res = super::data_len(&mut builder, &data, len_of_len); + builder.connect(res, ret_target); + + builder.register_public_inputs(&data); + builder.register_public_input(ret_target); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + #[test] + fn test_decode_len() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let zero = builder.zero(); + + let data1: Vec = [130, 4, 0] + .iter() + .map(|x| builder.constant(F::from_canonical_u64(*x))) + .collect(); + + let rlp_header1 = RlpHeader { + offset: builder.constant(F::from_canonical_usize(1)), + len: builder.constant(F::from_canonical_usize(2)), + data_type: builder.constant(F::from_canonical_usize(0)), + }; + + let res_rlp_header1 = super::decode_header(&mut builder, &data1); + + // builder.connect(rlp_header.len, res_rlp_header.len); + builder.connect(rlp_header1.offset, res_rlp_header1.offset); + builder.connect(rlp_header1.data_type, res_rlp_header1.data_type); + + builder.register_public_inputs(&data1); + builder.register_public_input(rlp_header1.offset); + builder.register_public_input(rlp_header1.len); + builder.register_public_input(rlp_header1.data_type); + + let data2: Vec = [ + 185, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 0, + ] + .iter() + .map(|x| builder.constant(F::from_canonical_u64(*x))) + .collect(); + + let rlp_header2 = RlpHeader { + offset: builder.constant(F::from_canonical_usize(3)), + len: builder.constant(F::from_canonical_usize(1024)), + data_type: builder.constant(F::from_canonical_usize(0)), + }; + + let res_rlp_header2 = super::decode_header(&mut builder, &data2); + + // builder.connect(rlp_header.len, res_rlp_header.len); + builder.connect(rlp_header2.offset, res_rlp_header2.offset); + builder.connect(rlp_header2.data_type, res_rlp_header2.data_type); + + builder.register_public_inputs(&data2); + builder.register_public_input(rlp_header2.offset); + builder.register_public_input(rlp_header2.len); + builder.register_public_input(rlp_header2.data_type); + + let data3: Vec = [199, 192, 193, 192, 195, 192, 193, 192] + .iter() + .map(|x| builder.constant(F::from_canonical_u64(*x))) + .collect(); + + let rlp_header3 = RlpHeader { + offset: builder.constant(F::from_canonical_usize(1)), + len: builder.constant(F::from_canonical_usize(7)), + data_type: builder.constant(F::from_canonical_usize(1)), + }; + + let res_dot_drop = + super::take_dot_drop::(&mut builder, &data3, zero); + let res_rlp_header3 = super::decode_header(&mut builder, &res_dot_drop); + + // builder.connect(rlp_header.len, res_rlp_header.len); + builder.connect(rlp_header3.offset, res_rlp_header3.offset); + builder.connect(rlp_header3.data_type, res_rlp_header3.data_type); + + builder.register_public_inputs(&data3); + builder.register_public_input(rlp_header3.offset); + builder.register_public_input(rlp_header3.len); + builder.register_public_input(rlp_header3.data_type); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + #[test] + fn test_rlp_decode_empty_list() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let zero = builder.zero(); + + let data: Vec = [0xc0] + .iter() + .map(|x| builder.constant(F::from_canonical_u64(*x))) + .collect(); + + let empty_list = super::decode_list(&mut builder, &data); + builder.connect(empty_list.num_fields, zero); + + builder.register_public_inputs(&data); + builder.register_public_input(empty_list.num_fields); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + #[test] + fn test_rlp_decode() -> Result<()> { + let data: [u64; 532] = [ + 249, 2, 17, 160, 10, 210, 58, 71, 229, 91, 254, 185, 245, 139, 35, 127, 191, 50, 125, + 165, 19, 165, 59, 86, 127, 77, 226, 197, 94, 143, 9, 69, 104, 149, 113, 39, 160, 164, + 115, 165, 166, 228, 180, 44, 203, 222, 52, 48, 157, 214, 190, 69, 130, 116, 84, 133, + 170, 215, 193, 212, 152, 106, 149, 100, 253, 145, 220, 246, 94, 160, 69, 11, 1, 238, + 164, 195, 225, 91, 51, 198, 134, 50, 21, 34, 253, 120, 157, 26, 173, 81, 148, 24, 94, + 179, 165, 5, 99, 85, 90, 78, 104, 180, 160, 82, 128, 145, 254, 48, 73, 106, 165, 234, + 223, 46, 5, 168, 79, 141, 218, 64, 98, 200, 87, 199, 28, 213, 222, 164, 182, 145, 219, + 253, 186, 121, 39, 160, 167, 139, 46, 219, 193, 195, 174, 240, 47, 40, 188, 121, 97, + 50, 227, 220, 35, 99, 122, 36, 94, 78, 156, 78, 197, 54, 232, 163, 249, 213, 16, 58, + 160, 111, 180, 73, 26, 200, 238, 6, 49, 66, 159, 230, 23, 226, 13, 10, 230, 7, 51, 103, + 45, 139, 187, 57, 125, 86, 1, 146, 77, 200, 196, 223, 158, 160, 55, 41, 196, 37, 89, + 112, 4, 6, 183, 246, 239, 121, 175, 146, 171, 71, 19, 99, 239, 56, 75, 116, 235, 20, + 239, 208, 243, 25, 211, 222, 248, 120, 160, 203, 87, 65, 73, 168, 197, 46, 86, 209, + 173, 204, 46, 232, 157, 204, 145, 75, 151, 105, 166, 72, 142, 173, 255, 186, 120, 43, + 121, 104, 228, 130, 134, 160, 150, 115, 130, 186, 247, 99, 108, 21, 244, 243, 60, 208, + 96, 34, 93, 32, 175, 77, 181, 18, 59, 49, 192, 153, 255, 123, 231, 108, 251, 75, 134, + 92, 160, 78, 107, 27, 31, 43, 92, 213, 101, 63, 87, 83, 248, 163, 19, 104, 103, 84, + 248, 119, 180, 32, 209, 82, 52, 250, 148, 101, 219, 76, 194, 160, 125, 160, 83, 37, + 183, 243, 189, 9, 79, 122, 28, 120, 150, 139, 190, 225, 222, 184, 206, 225, 117, 233, + 244, 162, 244, 212, 38, 220, 37, 129, 215, 25, 93, 53, 160, 229, 6, 255, 207, 78, 120, + 107, 238, 212, 128, 106, 189, 84, 39, 136, 172, 149, 67, 89, 238, 163, 122, 88, 90, + 149, 80, 59, 121, 249, 7, 238, 1, 160, 81, 214, 156, 64, 149, 165, 65, 36, 216, 223, + 167, 73, 213, 180, 230, 230, 32, 106, 193, 147, 176, 40, 93, 119, 210, 13, 1, 159, 16, + 112, 114, 103, 160, 211, 15, 4, 49, 74, 86, 24, 146, 109, 246, 80, 207, 194, 97, 226, + 153, 241, 94, 43, 233, 192, 2, 152, 171, 150, 86, 26, 250, 234, 179, 74, 156, 160, 175, + 157, 156, 73, 109, 26, 48, 12, 182, 175, 211, 173, 181, 241, 131, 247, 105, 98, 255, + 101, 7, 227, 21, 63, 78, 41, 155, 58, 231, 222, 15, 141, 160, 219, 213, 163, 116, 191, + 119, 232, 215, 182, 77, 130, 102, 90, 48, 66, 197, 228, 202, 43, 169, 232, 246, 11, 23, + 100, 50, 211, 205, 202, 115, 60, 49, 128, + ]; + + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let data: Vec = data + .iter() + .map(|x| builder.constant(F::from_canonical_u64(*x))) + .collect(); + + let decoded = super::decode_list(&mut builder, &data); + + let num_fields = builder.constant(F::from_canonical_u64(17)); + let offset: Vec = [ + 4, 37, 70, 103, 136, 169, 202, 235, 268, 301, 334, 367, 400, 433, 466, 499, 532, + ] + .iter() + .map(|x| builder.constant(F::from_canonical_u64(*x))) + .collect(); + let len: Vec = [ + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, + ] + .iter() + .map(|x| builder.constant(F::from_canonical_u64(*x))) + .collect(); + let data_type: Vec = [0; 17] + .iter() + .map(|x| builder.constant(F::from_canonical_u64(*x))) + .collect(); + + builder.connect(decoded.num_fields, num_fields); + for i in 0..17 { + builder.connect(decoded.offset[i], offset[i]); + builder.connect(decoded.len[i], len[i]); + builder.connect(decoded.data_type[i], data_type[i]); + } + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } +} diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 000000000..c566a1f93 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,354 @@ +use plonky2::field::extension::Extendable; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::target::{BoolTarget, Target}; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2_crypto::hash::HashOutputTarget; +use plonky2_crypto::u32::arithmetic_u32::U32Target; +use itertools::Itertools; + +pub(crate) const TWO_POWER_8: usize = 256; +pub(crate) const TWO_POWER_16: usize = 65536; +pub(crate) const TWO_POWER_24: usize = 16777216; + +/// Useful to convert between u32 representation and u8 representation in circuit. +/// For example hash output is using u32 representations. +pub fn array_u8_to_u32, const D: usize>( + b: &mut CircuitBuilder, + arr: &[Target; 32], // each target represents a single byte +) -> [U32Target; 8] { + // constants to convert [u8; 4] to u32 + // u32 = u8[0] + u8[1] * 2^8 + u8[2] * 2^16 + u8[3] * 2^24 + let two_power_8: Target = b.constant(F::from_canonical_usize(TWO_POWER_8)); + let two_power_16: Target = b.constant(F::from_canonical_usize(TWO_POWER_16)); + let two_power_24: Target = b.constant(F::from_canonical_usize(TWO_POWER_24)); + + let mut u32_array = [U32Target(b.zero()); 8]; + (0..arr.len()).step_by(4).for_each(|i| { + // u8[0] + let mut x = arr[i]; + + // u8[1] + let mut y = arr[i + 1]; + // u8[1] * 2^8 + y = b.mul(y, two_power_8); + + // u8[0] + u8[1] * 2^8 + x = b.add(x, y); + + // u8[2] + y = arr[i + 2]; + // u8[2] * 2^16 + y = b.mul(y, two_power_16); + + // u8[0] + u8[1] * 2^8 + u8[2] * 2^16 + x = b.add(x, y); + + // u8[3] + y = arr[i + 3]; + // u8[3] * 2^24 + y = b.mul(y, two_power_24); + + // u8[0] + u8[1] * 2^8 + u8[2] * 2^16 + u8[3] * 2^24 + x = b.add(x, y); + + u32_array[i / 4] = U32Target(x); + }); + u32_array +} + +pub fn num_to_bits, const D: usize>( + builder: &mut CircuitBuilder, + n: usize, + x: Target, +) -> Vec { + builder.range_check(x, n); + builder.split_le(x, n) +} + +pub fn bits_to_num, const D: usize>( + builder: &mut CircuitBuilder, + bits: &[BoolTarget], +) -> Target { + let mut res = builder.zero(); + let mut e2 = builder.one(); + for bit in bits { + res = builder.mul_add(e2, bit.target, res); + e2 = builder.add(e2, e2); + } + res +} + +pub fn less_than, const D: usize>( + builder: &mut CircuitBuilder, + a: Target, + b: Target, + n: usize, +) -> BoolTarget { + assert!(n < 64); + + let power_of_two = builder.constant(F::from_canonical_u64(1 << n)); + let mut lin_pol = builder.add(a, power_of_two); + // 2^n + a - b + lin_pol = builder.sub(lin_pol, b); + + let binary = num_to_bits(builder, n + 1, lin_pol); + // bin(2^n + a - b)[n] == false is correct only when a < b otherwise + // 2^n + a - b > 2^n so binary[n] will be set + builder.not(binary[n]) +} + +pub fn greater_than, const D: usize>( + builder: &mut CircuitBuilder, + a: Target, + b: Target, + n: usize, +) -> BoolTarget { + less_than(builder, b, a, n) +} + +pub fn less_than_or_equal_to, const D: usize>( + builder: &mut CircuitBuilder, + a: Target, + b: Target, + n: usize, +) -> BoolTarget { + let one = builder.one(); + let b_plus_1 = builder.add(b, one); + less_than(builder, a, b_plus_1, n) +} + +pub fn greater_than_or_equal_to, const D: usize>( + builder: &mut CircuitBuilder, + a: Target, + b: Target, + n: usize, +) -> BoolTarget { + let one = builder.one(); + let a_plus_1 = builder.add(a, one); + less_than(builder, b, a_plus_1, n) +} + +// Returns the shifted bits as a num +pub fn right_shift, const D: usize>( + builder: &mut CircuitBuilder, + n: usize, + x: Target, + shift: usize, +) -> Target { + // nikko: Is this legit ? an IF depending on the witness seems + // wrong, because then the circuit is not the same depending + // on the value of the witness... + let bits = num_to_bits(builder, n, x); + if bits.is_empty() || shift >= bits.len() { + return builder.zero(); + } + // Remove the least significant bits according to the shift value + let shifted_bits = &bits[shift..]; + + // Convert the shifted bits back to a number + + // builder.connect(res, x); + bits_to_num(builder, shifted_bits) +} + +#[cfg(test)] +mod test { + use crate::utils::{ + bits_to_num, greater_than, greater_than_or_equal_to, less_than, less_than_or_equal_to, + num_to_bits, right_shift, + }; + use anyhow::Result; + use plonky2::field::types::Field; + use plonky2::iop::target::Target; + use plonky2::iop::witness::PartialWitness; + use plonky2::plonk::circuit_builder::CircuitBuilder; + use plonky2::plonk::circuit_data::CircuitConfig; + use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + + #[test] + fn test_right_shift() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let a = builder.constant(F::from_canonical_u64(121u64)); + let b = builder.constant(F::from_canonical_u64(15u64)); + let res = right_shift(&mut builder, 64, a, 3); + + builder.connect(res, b); + + builder.register_public_input(a); + builder.register_public_input(b); + builder.register_public_input(res); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + #[test] + fn test_bits_to_num() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + let number = builder.constant(F::from_canonical_usize(1986)); + let t = builder._true(); + let f = builder._false(); + + let bits_array = [f, t, f, f, f, f, t, t, t, t, t]; + let one = builder.one(); + let zero = builder.zero(); + + let public_input_array = [zero, one, zero, zero, zero, zero, one, one, one, one, one]; + + let nums = bits_to_num(&mut builder, &bits_array); + + builder.connect(number, nums); + builder.register_public_input(number); + builder.register_public_inputs(&public_input_array); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + #[test] + fn test_num_to_bits_valid() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + let x = F::from_canonical_usize(0b110100000); // 416 = 1532 in base 6. + let xt = builder.constant(x); + + let mut bits = [1, 1, 0, 1, 0, 0, 0, 0, 0]; + bits.reverse(); + let mut bits_target_input: Vec = vec![]; + + let bits_target = num_to_bits(&mut builder, 9, xt); + + for i in 0..bits_target.len() { + bits_target_input.push(builder.constant(F::from_canonical_u64(bits[i]))); + builder.connect(bits_target_input[i], bits_target[i].target); + } + + builder.register_public_input(xt); + builder.register_public_inputs(&bits_target_input); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + #[test] + fn test_less_than() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let a = builder.constant(F::from_canonical_u64(5u64)); + let b = builder.constant(F::from_canonical_u64(10u64)); + let n = 4; + + let result = less_than(&mut builder, a, b, n); + let one = builder.one(); + builder.connect(result.target, one); + + builder.register_public_input(a); + builder.register_public_input(b); + builder.register_public_input(result.target); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + #[test] + fn test_greater_than() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let a = builder.constant(F::from_canonical_u64(10u64)); + let b = builder.constant(F::from_canonical_u64(5u64)); + let n = 4; + + let result = greater_than(&mut builder, a, b, n); + let one = builder.one(); + builder.connect(result.target, one); + + builder.register_public_input(a); + builder.register_public_input(b); + builder.register_public_input(result.target); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + #[test] + fn test_less_than_or_equal_to() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let a = builder.constant(F::from_canonical_u64(10u64)); + let b = builder.constant(F::from_canonical_u64(10u64)); + let n = 4; + + let result = less_than_or_equal_to(&mut builder, a, b, n); + let one = builder.one(); + builder.connect(result.target, one); + + builder.register_public_input(a); + builder.register_public_input(b); + builder.register_public_input(result.target); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } + + #[test] + fn test_greater_than_or_equal_to() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let config = CircuitConfig::standard_recursion_config(); + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let a = builder.constant(F::from_canonical_u64(10u64)); + let b = builder.constant(F::from_canonical_u64(10u64)); + let n = 4; + + let result = greater_than_or_equal_to(&mut builder, a, b, n); + let one = builder.one(); + builder.connect(result.target, one); + + builder.register_public_input(a); + builder.register_public_input(b); + builder.register_public_input(result.target); + + let data = builder.build::(); + let proof = data.prove(pw)?; + data.verify(proof) + } +} From 9ec305ee43c88ca7edc7ffc3d605104233ee96e9 Mon Sep 17 00:00:00 2001 From: nikkolasg Date: Tue, 21 Nov 2023 17:07:15 +0100 Subject: [PATCH 2/7] fmt --- src/utils.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index c566a1f93..92c76cbf6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -146,8 +146,6 @@ pub fn right_shift, const D: usize>( let shifted_bits = &bits[shift..]; // Convert the shifted bits back to a number - - // builder.connect(res, x); bits_to_num(builder, shifted_bits) } From ba33d0e2a9f4bbc1d897b77bef6d27df52b6f99a Mon Sep 17 00:00:00 2001 From: nikkolasg Date: Tue, 21 Nov 2023 17:07:26 +0100 Subject: [PATCH 3/7] cargo fmt --- src/rlp.rs | 2 +- src/utils.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index f57cad9fa..63ada1de9 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -491,7 +491,7 @@ mod tests { use plonky2::plonk::circuit_data::CircuitConfig; use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - use crate::rlp::{RlpHeader,MAX_LEN_BYTES }; + use crate::rlp::{RlpHeader, MAX_LEN_BYTES}; #[test] fn test_data_len() -> Result<()> { diff --git a/src/utils.rs b/src/utils.rs index 92c76cbf6..556e12321 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,16 +1,16 @@ +use itertools::Itertools; use plonky2::field::extension::Extendable; use plonky2::hash::hash_types::RichField; use plonky2::iop::target::{BoolTarget, Target}; use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2_crypto::hash::HashOutputTarget; use plonky2_crypto::u32::arithmetic_u32::U32Target; -use itertools::Itertools; pub(crate) const TWO_POWER_8: usize = 256; pub(crate) const TWO_POWER_16: usize = 65536; pub(crate) const TWO_POWER_24: usize = 16777216; -/// Useful to convert between u32 representation and u8 representation in circuit. +/// Useful to convert between u32 representation and u8 representation in circuit. /// For example hash output is using u32 representations. pub fn array_u8_to_u32, const D: usize>( b: &mut CircuitBuilder, From 51755b47a7ec50882757db26625e410d9059b141 Mon Sep 17 00:00:00 2001 From: nikkolasg Date: Tue, 21 Nov 2023 17:28:32 +0100 Subject: [PATCH 4/7] making nightly work? --- .github/workflows/rust.yml | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0b5a8c7ac..94d98e570 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -15,22 +15,24 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - - uses: actions/cache@v3 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - name: Build - run: cargo build --verbose - - name: Check fmt - run: cargo fmt --check - - name: Run tests - run: cargo test --verbose + - name: Stable with rustfmt and clippy + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + components: rustfmt, clippy + - uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - name: Build + run: cargo build --verbose + - name: Check fmt + run: cargo fmt --check + - name: Run tests + run: cargo test --verbose From 1d815e1495eba7e66c2235433138994099e74983 Mon Sep 17 00:00:00 2001 From: nikkolasg Date: Tue, 21 Nov 2023 17:34:28 +0100 Subject: [PATCH 5/7] trying again --- .github/workflows/rust.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 94d98e570..7c52b926d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -11,11 +11,10 @@ env: jobs: build: - runs-on: ubuntu-latest - steps: - - name: Stable with rustfmt and clippy + - uses: actions/checkout@v2 + - name: nightly with rustfmt and clippy uses: actions-rs/toolchain@v1 with: profile: minimal From 105a50598e6a402ba1c6c58a2f198fd6dcc33e4e Mon Sep 17 00:00:00 2001 From: nikkolasg Date: Tue, 21 Nov 2023 17:38:13 +0100 Subject: [PATCH 6/7] trying again --- .github/workflows/rust.yml | 50 ++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7c52b926d..90fac5c8c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,25 +1,23 @@ -name: mapreduce CI - on: pull_request: push: branches: - main -env: - CARGO_TERM_COLOR: always + +name: Check and Lint jobs: - build: + check: + name: Check runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: nightly with rustfmt and clippy - uses: actions-rs/toolchain@v1 + - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly - components: rustfmt, clippy + toolchain: stable + override: true - uses: actions/cache@v3 with: path: | @@ -29,9 +27,31 @@ jobs: ~/.cargo/git/db/ target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - name: Build - run: cargo build --verbose - - name: Check fmt - run: cargo fmt --check - - name: Run tests - run: cargo test --verbose + - uses: actions-rs/cargo@v1 + with: + command: check + + fmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - run: rustup component add rustfmt + - uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check \ No newline at end of file From e7df84916c65e00d66b15f3272ddb01f6c58c719 Mon Sep 17 00:00:00 2001 From: nikkolasg Date: Tue, 21 Nov 2023 17:56:12 +0100 Subject: [PATCH 7/7] nightly everywhere --- .github/workflows/rust.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 90fac5c8c..b75f60a3c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -16,7 +16,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: stable + toolchain: nightly override: true - uses: actions/cache@v3 with: @@ -39,7 +39,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: stable + toolchain: nightly override: true - uses: actions/cache@v3 with: