From 99613aa7a7e030424fd8a4d3801491d79cfec154 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Fri, 7 Apr 2023 10:51:08 +0000 Subject: [PATCH 01/21] upgrade ethers lib --- Cargo.lock | 1325 +++++++++++++------------ bus-mapping/Cargo.toml | 4 +- circuit-benchmarks/Cargo.toml | 2 +- eth-types/Cargo.toml | 4 +- eth-types/src/geth_types.rs | 4 +- integration-tests/Cargo.toml | 2 +- mock/Cargo.toml | 4 +- mock/src/transaction.rs | 3 +- rust-toolchain | 2 +- testool/Cargo.toml | 4 +- testool/src/statetest/executor.rs | 4 +- testool/src/statetest/json.rs | 2 +- testool/src/statetest/spec.rs | 2 +- testool/src/statetest/yaml.rs | 2 +- zkevm-circuits/Cargo.toml | 5 +- zkevm-circuits/src/lib.rs | 3 +- zkevm-circuits/src/mpt_circuit/lib.rs | 1 + 17 files changed, 723 insertions(+), 650 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7dc3f0d4b2..7558dfabe8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,16 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "adler" version = "1.0.2" @@ -10,36 +20,13 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aes" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" dependencies = [ "cfg-if", "cipher", "cpufeatures", - "opaque-debug 0.3.0", -] - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", ] [[package]] @@ -106,13 +93,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.64" +version = "0.1.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] @@ -146,7 +133,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -157,31 +144,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base58" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" - -[[package]] -name = "base58check" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee2fe4c9a0c84515f136aaae2466744a721af6d63339c18689d9e995d74d99b" -dependencies = [ - "base58", - "sha2 0.8.2", -] - -[[package]] -name = "base64" -version = "0.12.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" @@ -259,15 +224,6 @@ dependencies = [ "wyz", ] -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest 0.10.6", -] - [[package]] name = "blake2b_simd" version = "1.0.0" @@ -286,19 +242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" dependencies = [ "arrayref", - "byte-tools 0.2.0", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding 0.1.5", - "byte-tools 0.3.1", - "byteorder", - "generic-array 0.12.4", + "byte-tools", ] [[package]] @@ -307,7 +251,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding 0.2.1", + "block-padding", "generic-array 0.14.6", ] @@ -320,71 +264,20 @@ dependencies = [ "generic-array 0.14.6", ] -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools 0.3.1", -] - [[package]] name = "block-padding" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" -[[package]] -name = "borsh" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "822462c1e7b17b31961798a6874b36daea6818e99e0cb7d3b7b0fa3c477751c3" -dependencies = [ - "borsh-derive", - "hashbrown 0.13.2", -] - -[[package]] -name = "borsh-derive" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37626c9e941a687ee9abef6065b44c379478ae563b7483c613dd705ef1dff59e" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61820b4c5693eafb998b1e67485423c923db4a75f72585c247bdee32bad81e7b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c76cdbfa13def20d1f8af3ae7b3c6771f06352a74221d8851262ac384c122b8e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "bs58" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +dependencies = [ + "sha2 0.9.9", +] [[package]] name = "bstr" @@ -442,51 +335,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" [[package]] -name = "byte-tools" -version = "0.3.1" +name = "bytemuck" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" [[package]] -name = "bytecheck" -version = "0.6.9" +name = "byteorder" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11cac2c12b5adc6570dad2ee1b87eff4955dac476fe12d81e5fdd352e52406f" -dependencies = [ - "bytecheck_derive", - "ptr_meta", -] +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] -name = "bytecheck_derive" -version = "0.6.9" +name = "bytes" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" dependencies = [ - "proc-macro2", - "quote", - "syn", + "serde", ] [[package]] -name = "bytemuck" -version = "1.13.0" +name = "camino" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" +checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +dependencies = [ + "serde", +] [[package]] -name = "byteorder" -version = "1.4.3" +name = "cargo-platform" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] [[package]] -name = "bytes" -version = "1.4.0" +name = "cargo_metadata" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.16", "serde", + "serde_json", + "thiserror", ] [[package]] @@ -524,11 +422,12 @@ dependencies = [ [[package]] name = "cipher" -version = "0.3.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "generic-array 0.14.6", + "crypto-common", + "inout", ] [[package]] @@ -588,7 +487,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -620,7 +519,7 @@ checksum = "2af3bfb9da627b0a6c467624fb7963921433774ed435493b5c08a3053e829ad4" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -644,9 +543,9 @@ dependencies = [ [[package]] name = "coins-bip32" -version = "0.7.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634c509653de24b439672164bbf56f5f582a2ab0e313d3b0f6af0b7345cf2560" +checksum = "b30a84aab436fcb256a2ab3c80663d8aec686e6bae12827bb05fef3e1e439c9f" dependencies = [ "bincode", "bs58", @@ -663,31 +562,32 @@ dependencies = [ [[package]] name = "coins-bip39" -version = "0.7.0" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a11892bcac83b4c6e95ab84b5b06c76d9d70ad73548dd07418269c5c7977171" +checksum = "ad2a68a46b9d8cc90484f0689adc0e4c890eb215bf698ae52e5235bb88f40be7" dependencies = [ "bitvec 0.17.4", "coins-bip32", "getrandom", "hex", "hmac 0.12.1", - "pbkdf2 0.11.0", + "once_cell", + "pbkdf2 0.12.1", "rand", "sha2 0.10.6", "thiserror", + "tracing", ] [[package]] name = "coins-core" -version = "0.7.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94090a6663f224feae66ab01e41a2555a8296ee07b5f20dab8888bdefc9f617" +checksum = "9b949a1c63fb7eb591eb7ba438746326aedf0ae843e51ec92ba6bec5bb382c4f" dependencies = [ - "base58check", - "base64 0.12.3", + "base64 0.21.0", "bech32", - "blake2", + "bs58", "digest 0.10.6", "generic-array 0.14.6", "hex", @@ -724,9 +624,9 @@ checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6" [[package]] name = "const-oid" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" [[package]] name = "constant_time_eq" @@ -736,9 +636,12 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "convert_case" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "core-foundation" @@ -898,9 +801,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.4.9" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +checksum = "7c2538c4e68e52548bacb3e83ac549f903d44f011ac9d5abb5e132e67d0808f7" dependencies = [ "generic-array 0.14.6", "rand_core", @@ -957,14 +860,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.107", ] [[package]] name = "ctr" -version = "0.8.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ "cipher", ] @@ -993,7 +896,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.107", ] [[package]] @@ -1010,7 +913,7 @@ checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -1044,7 +947,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.9.3", - "syn", + "syn 1.0.107", ] [[package]] @@ -1058,7 +961,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn", + "syn 1.0.107", ] [[package]] @@ -1069,7 +972,7 @@ checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ "darling_core 0.10.2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -1080,14 +983,14 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core 0.13.4", "quote", - "syn", + "syn 1.0.107", ] [[package]] name = "der" -version = "0.6.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +checksum = "82b10af9f9f9f2134a42d3f8aa74658660f2e0234b0eb81bd171df8aa32779ed" dependencies = [ "const-oid", "zeroize", @@ -1103,7 +1006,7 @@ dependencies = [ "derive_builder_core", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -1115,7 +1018,18 @@ dependencies = [ "darling 0.10.2", "proc-macro2", "quote", - "syn", + "syn 1.0.107", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", ] [[package]] @@ -1133,15 +1047,6 @@ dependencies = [ "generic-array 0.9.1", ] -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - [[package]] name = "digest" version = "0.9.0" @@ -1158,6 +1063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", + "const-oid", "crypto-common", "subtle", ] @@ -1215,7 +1121,7 @@ name = "ecc" version = "0.1.0" source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" dependencies = [ - "group", + "group 0.12.1", "integer", "num-bigint", "num-integer", @@ -1230,7 +1136,7 @@ version = "0.1.0" source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" dependencies = [ "ecc", - "group", + "group 0.12.1", "num-bigint", "num-integer", "num-traits", @@ -1240,11 +1146,12 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.14.8" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +checksum = "106401dadc137d05cb0d4ab4d42be089746aefdfe8992df4d0edcf351c16ddca" dependencies = [ "der", + "digest 0.10.6", "elliptic-curve", "rfc6979", "signature", @@ -1258,17 +1165,16 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "elliptic-curve" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +checksum = "22cdacd4d6ed3f9b98680b679c0e52a823b8a2c7a97358d508fe247f2180c282" dependencies = [ "base16ct", "crypto-bigint", - "der", "digest 0.10.6", - "ff", + "ff 0.13.0", "generic-array 0.14.6", - "group", + "group 0.13.0", "pkcs8", "rand_core", "sec1", @@ -1300,6 +1206,24 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb4d5fbf6f56acecd38f5988eb2e4ae412008a2a30268c748c701ec6322f39d4" +dependencies = [ + "base64 0.13.1", + "bytes", + "hex", + "k256", + "log", + "rand", + "rlp", + "serde", + "sha3 0.10.6", + "zeroize", +] + [[package]] name = "env_logger" version = "0.9.3" @@ -1324,6 +1248,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "errno" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "errno-dragonfly" version = "0.1.2" @@ -1336,9 +1271,9 @@ dependencies = [ [[package]] name = "eth-keystore" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f65b750ac950f2f825b36d08bef4cda4112e19a7b1a68f6e2bb499413e12440" +checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" dependencies = [ "aes", "ctr", @@ -1382,9 +1317,9 @@ dependencies = [ [[package]] name = "ethabi" -version = "17.2.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" dependencies = [ "ethereum-types", "hex", @@ -1399,36 +1334,40 @@ dependencies = [ [[package]] name = "ethbloom" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "tiny-keccak", ] [[package]] name = "ethereum-types" -version = "0.13.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", "primitive-types", + "scale-info", "uint", ] [[package]] name = "ethers" -version = "0.17.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16142eeb3155cfa5aec6be3f828a28513a28bd995534f945fa70e7d608f16c10" +checksum = "839a392641e746a1ff365ef7c901238410b5c6285d240cf2409ffaaa7df9a78a" dependencies = [ "ethers-addressbook", "ethers-contract", @@ -1442,9 +1381,9 @@ dependencies = [ [[package]] name = "ethers-addressbook" -version = "0.17.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e23f8992ecf45ea9dd2983696aabc566c108723585f07f5dc8c9efb24e52d3db" +checksum = "c0b603812e5e4d63521c691cbc1f34743879e96a1ee96c6594639d7fa0cf6fbc" dependencies = [ "ethers-core", "once_cell", @@ -1454,10 +1393,12 @@ dependencies = [ [[package]] name = "ethers-contract" -version = "0.17.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e0010fffc97c5abcf75a30fd75676b1ed917b2b82beb8270391333618e2847d" +checksum = "b4e8ed7c2b2a22e07b65ae0eb426c948a7448f1be15c66e4813e02c423751fc9" dependencies = [ + "ethers-contract-abigen", + "ethers-contract-derive", "ethers-core", "ethers-providers", "futures-util", @@ -1469,31 +1410,75 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ethers-contract-abigen" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf0984f4ec4e267fd27b7c9fa2f73e72c5c98491a73f777290654154d104f723" +dependencies = [ + "Inflector", + "dunce", + "ethers-core", + "ethers-etherscan", + "eyre", + "getrandom", + "hex", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "reqwest", + "serde", + "serde_json", + "syn 1.0.107", + "tokio", + "toml 0.7.3", + "url", + "walkdir", +] + +[[package]] +name = "ethers-contract-derive" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914e9211077a1b590af1ee6b8dfbd54515c808119546c95da69479908dc3d4de" +dependencies = [ + "ethers-contract-abigen", + "ethers-core", + "hex", + "proc-macro2", + "quote", + "syn 1.0.107", +] + [[package]] name = "ethers-core" -version = "0.17.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ebdd63c828f58aa067f40f9adcbea5e114fb1f90144b3a1e2858e0c9b1ff4e8" +checksum = "40bf114f1017ace0f622f1652f59c2c5e1abfe7d88891cca0c43da979b351de0" dependencies = [ "arrayvec", "bytes", + "cargo_metadata", "chrono", "convert_case", "elliptic-curve", "ethabi", - "fastrlp", "generic-array 0.14.6", + "getrandom", "hex", "k256", + "num_enum", + "once_cell", + "open-fastrlp", "proc-macro2", "rand", "rlp", - "rlp-derive", - "rust_decimal", "serde", "serde_json", "strum", - "syn", + "syn 1.0.107", + "tempfile", "thiserror", "tiny-keccak", "unicode-xid", @@ -1501,16 +1486,16 @@ dependencies = [ [[package]] name = "ethers-etherscan" -version = "0.17.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b279a3d00bd219caa2f9a34451b4accbfa9a1eaafc26dcda9d572591528435f0" +checksum = "8920b59cf81e357df2c8102d6a9dc81c2d68f7409543ff3b6868851ecf007807" dependencies = [ "ethers-core", + "ethers-solc", "getrandom", "reqwest", "semver 1.0.16", "serde", - "serde-aux", "serde_json", "thiserror", "tracing", @@ -1518,11 +1503,12 @@ dependencies = [ [[package]] name = "ethers-middleware" -version = "0.17.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e7e8632d28175352b9454bbcb604643b6ca1de4d36dc99b3f86860d75c132b" +checksum = "a7dd311b76eab9d15209e4fd16bb419e25543709cbdf33079e8923dfa597517c" dependencies = [ "async-trait", + "auto_impl", "ethers-contract", "ethers-core", "ethers-etherscan", @@ -1543,13 +1529,15 @@ dependencies = [ [[package]] name = "ethers-providers" -version = "0.17.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46482e4d1e79b20c338fd9db9e166184eb387f0a4e7c05c5b5c0aa2e8c8900c" +checksum = "c2fa0857eaad0c1678f982a2f4cfbe33ebd51d273cc93de0182b7c693f2a84a1" dependencies = [ "async-trait", "auto_impl", - "base64 0.13.1", + "base64 0.21.0", + "bytes", + "enr", "ethers-core", "futures-channel", "futures-core", @@ -1559,8 +1547,8 @@ dependencies = [ "hashers", "hex", "http", + "instant", "once_cell", - "parking_lot 0.11.2", "pin-project", "reqwest", "serde", @@ -1573,16 +1561,15 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-timer", "web-sys", "ws_stream_wasm", ] [[package]] name = "ethers-signers" -version = "0.17.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73a72ecad124e8ccd18d6a43624208cab0199e59621b1f0fa6b776b2e0529107" +checksum = "5caa7cad4f444931d0ed45818e609847781582399eff0be5c089e8666475c7fb" dependencies = [ "async-trait", "coins-bip32", @@ -1594,16 +1581,16 @@ dependencies = [ "rand", "sha2 0.10.6", "thiserror", + "tracing", ] [[package]] name = "ethers-solc" -version = "0.17.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebe5db405d0e584aa8dae154ffebb90f2305cae588fd11d9f6b857ebe3a79294" +checksum = "139542f51f4c405d0dd7e97c34232140a14e8744d1cf121777355567187259e4" dependencies = [ "cfg-if", - "colored", "dunce", "ethers-core", "getrandom", @@ -1625,6 +1612,7 @@ dependencies = [ "tokio", "tracing", "walkdir", + "yansi", ] [[package]] @@ -1638,34 +1626,22 @@ dependencies = [ ] [[package]] -name = "fake-simd" -version = "0.1.2" +name = "eyre" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - -[[package]] -name = "fastrlp" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "089263294bb1c38ac73649a6ad563dd9a5142c8dc0482be15b8b9acb22a1611e" +checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "ethereum-types", - "fastrlp-derive", + "indenter", + "once_cell", ] [[package]] -name = "fastrlp-derive" -version = "0.1.5" +name = "fastrand" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0f9d074ab623d1b388c12544bfeed759c7df36dc5c300cda053df9ba1232075" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn", + "instant", ] [[package]] @@ -1679,11 +1655,21 @@ dependencies = [ "subtle", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "fixed-hash" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", "rand", @@ -1812,9 +1798,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -1822,9 +1808,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" @@ -1839,9 +1825,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-locks" @@ -1851,43 +1837,46 @@ checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" dependencies = [ "futures-channel", "futures-task", - "tokio", ] [[package]] name = "futures-macro" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] name = "futures-sink" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-timer" version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +dependencies = [ + "gloo-timers", + "send_wrapper 0.4.0", +] [[package]] name = "futures-util" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -1932,15 +1921,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - [[package]] name = "generic-array" version = "0.14.6" @@ -1949,6 +1929,7 @@ checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1989,6 +1970,18 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "gobuild" version = "0.1.0-alpha.2" @@ -2004,7 +1997,18 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ - "ff", + "ff 0.12.1", + "rand_core", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", "rand_core", "subtle", ] @@ -2041,8 +2045,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e925780549adee8364c7f2b685c753f6f3df23bde520c67416e93bf615933760" dependencies = [ "blake2b_simd", - "ff", - "group", + "ff 0.12.1", + "group 0.12.1", "pasta_curves", "plotters", "rand_core", @@ -2056,8 +2060,8 @@ version = "0.2.0" source = "git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2023_02_02#0a8646b78286a13d320759b1c585262d6536dce4" dependencies = [ "blake2b_simd", - "ff", - "group", + "ff 0.12.1", + "group 0.12.1", "halo2curves 0.3.1", "rand_core", "rayon", @@ -2070,8 +2074,8 @@ name = "halo2curves" version = "0.2.1" source = "git+https://github.com/privacy-scaling-explorations/halo2curves?tag=0.3.0#83c72d49762343ffc9576ca11a2aa615efe1029b" dependencies = [ - "ff", - "group", + "ff 0.12.1", + "group 0.12.1", "lazy_static", "num-bigint", "num-traits", @@ -2087,8 +2091,8 @@ name = "halo2curves" version = "0.3.1" source = "git+https://github.com/privacy-scaling-explorations/halo2curves.git?tag=0.3.1#9b67e19bca30a35208b0c1b41c1723771e2c9f49" dependencies = [ - "ff", - "group", + "ff 0.12.1", + "group 0.12.1", "lazy_static", "num-bigint", "num-traits", @@ -2104,7 +2108,7 @@ name = "halo2wrong" version = "0.1.0" source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" dependencies = [ - "group", + "group 0.12.1", "halo2_proofs 0.2.0", "num-bigint", "num-integer", @@ -2130,18 +2134,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash 0.8.3", -] [[package]] name = "hashers" @@ -2379,9 +2371,9 @@ dependencies = [ [[package]] name = "impl-serde" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" dependencies = [ "serde", ] @@ -2394,9 +2386,15 @@ checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" version = "1.9.2" @@ -2404,7 +2402,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown 0.12.3", + "hashbrown", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array 0.14.6", ] [[package]] @@ -2414,9 +2421,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", ] [[package]] @@ -2424,7 +2428,7 @@ name = "integer" version = "0.1.0" source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" dependencies = [ - "group", + "group 0.12.1", "maingate", "num-bigint", "num-integer", @@ -2459,12 +2463,13 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.5" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" dependencies = [ + "hermit-abi 0.3.1", "libc", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -2481,7 +2486,7 @@ checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix", + "rustix 0.36.8", "windows-sys 0.45.0", ] @@ -2523,15 +2528,16 @@ dependencies = [ [[package]] name = "k256" -version = "0.11.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +checksum = "955890845095ccf31ef83ad41a05aabb4d8cc23dc3cac5a9f5c89cf26dd0da75" dependencies = [ "cfg-if", - "ecdsa 0.14.8", + "ecdsa 0.16.4", "elliptic-curve", + "once_cell", "sha2 0.10.6", - "sha3 0.10.6", + "signature", ] [[package]] @@ -2600,9 +2606,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] name = "libloading" @@ -2683,6 +2689,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +[[package]] +name = "linux-raw-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" + [[package]] name = "lock_api" version = "0.4.9" @@ -2707,7 +2719,7 @@ name = "maingate" version = "0.1.0" source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" dependencies = [ - "group", + "group 0.12.1", "halo2wrong", "num-bigint", "num-integer", @@ -2898,17 +2910,17 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ - "proc-macro-crate 1.3.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "oorandom" @@ -2918,15 +2930,34 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opaque-debug" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] -name = "opaque-debug" -version = "0.3.0" +name = "open-fastrlp" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2", + "quote", + "syn 1.0.107", +] [[package]] name = "os_str_bytes" @@ -2963,21 +2994,10 @@ version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" dependencies = [ - "proc-macro-crate 1.3.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", + "syn 1.0.107", ] [[package]] @@ -2987,21 +3007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.7", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -3012,33 +3018,11 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "windows-sys 0.45.0", ] -[[package]] -name = "password-hash" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - [[package]] name = "pasta_curves" version = "0.4.1" @@ -3046,8 +3030,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cc65faf8e7313b4b1fbaa9f7ca917a0eed499a9663be71477f87993604341d8" dependencies = [ "blake2b_simd", - "ff", - "group", + "ff 0.12.1", + "group 0.12.1", "lazy_static", "rand", "static_assertions", @@ -3087,23 +3071,21 @@ dependencies = [ [[package]] name = "pbkdf2" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ "digest 0.10.6", ] [[package]] name = "pbkdf2" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +checksum = "f0ca0b5a68607598bf3bad68f32227a8164f6254833f84eafaac409cd6746c31" dependencies = [ "digest 0.10.6", "hmac 0.12.1", - "password-hash 0.4.2", - "sha2 0.10.6", ] [[package]] @@ -3142,7 +3124,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -3178,44 +3160,51 @@ dependencies = [ [[package]] name = "phf" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" dependencies = [ "phf_macros", - "phf_shared", - "proc-macro-hack", + "phf_shared 0.11.1", ] [[package]] name = "phf_generator" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" dependencies = [ - "phf_shared", + "phf_shared 0.11.1", "rand", ] [[package]] name = "phf_macros" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" dependencies = [ "phf_generator", - "phf_shared", - "proc-macro-hack", + "phf_shared 0.11.1", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] name = "phf_shared" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" dependencies = [ "siphasher", ] @@ -3243,7 +3232,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -3260,9 +3249,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs8" -version = "0.9.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", "spki", @@ -3337,7 +3326,7 @@ name = "poseidon" version = "0.2.0" source = "git+https://github.com/privacy-scaling-explorations/poseidon.git?tag=v2022_10_22#5d29df01a95e3df6334080d28e983407f56b5da3" dependencies = [ - "group", + "group 0.12.1", "halo2curves 0.2.1", "subtle", ] @@ -3366,6 +3355,16 @@ dependencies = [ "yansi", ] +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.107", +] + [[package]] name = "prettytable-rs" version = "0.10.0" @@ -3382,26 +3381,18 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.11.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" dependencies = [ "fixed-hash", "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "uint", ] -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - [[package]] name = "proc-macro-crate" version = "1.3.0" @@ -3409,7 +3400,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.18.1", ] [[package]] @@ -3421,7 +3412,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.107", "version_check", ] @@ -3436,46 +3427,20 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "quote" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -3533,9 +3498,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ "either", "rayon-core", @@ -3543,9 +3508,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.2" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -3562,6 +3527,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + [[package]] name = "redox_users" version = "0.4.3" @@ -3569,7 +3543,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "redox_syscall", + "redox_syscall 0.2.16", "thiserror", ] @@ -3596,15 +3570,6 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" -[[package]] -name = "rend" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" -dependencies = [ - "bytecheck", -] - [[package]] name = "reqwest" version = "0.11.14" @@ -3646,13 +3611,12 @@ dependencies = [ [[package]] name = "rfc6979" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "crypto-bigint", "hmac 0.12.1", - "zeroize", + "subtle", ] [[package]] @@ -3679,31 +3643,6 @@ dependencies = [ "digest 0.10.6", ] -[[package]] -name = "rkyv" -version = "0.7.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" -dependencies = [ - "bytecheck", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "rlp" version = "0.5.2" @@ -3711,6 +3650,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", + "rlp-derive", "rustc-hex", ] @@ -3722,25 +3662,7 @@ checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" dependencies = [ "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "rust_decimal" -version = "1.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13cf35f7140155d02ba4ec3294373d513a3c7baa8364c162b030e33c61520a8" -dependencies = [ - "arrayvec", - "borsh", - "bytecheck", - "byteorder", - "bytes", - "num-traits", - "rand", - "rkyv", - "serde", - "serde_json", + "syn 1.0.107", ] [[package]] @@ -3774,13 +3696,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" dependencies = [ "bitflags", - "errno", + "errno 0.2.8", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.1.4", "windows-sys 0.45.0", ] +[[package]] +name = "rustix" +version = "0.37.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aef160324be24d31a62147fae491c14d2204a3865c7ca8c3b0d7f7bcb3ea635" +dependencies = [ + "bitflags", + "errno 0.3.0", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.1", + "windows-sys 0.48.0", +] + [[package]] name = "rustls" version = "0.20.8" @@ -3816,9 +3752,9 @@ checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "salsa20" -version = "0.9.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" dependencies = [ "cipher", ] @@ -3832,6 +3768,30 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cfdffd972d76b22f3d7f81c8be34b2296afd3a25e0a547bd9abe340a4dbbe97" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61fa974aea2d63dd18a4ec3a49d59af9f34178c73a4f56d2f18205628d00681e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.107", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -3846,13 +3806,12 @@ checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "scrypt" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e73d6d7c6311ebdbd9184ad6c4447b2f36337e327bda107d3ba9e3c374f9d325" +checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" dependencies = [ "hmac 0.12.1", - "password-hash 0.3.2", - "pbkdf2 0.10.1", + "pbkdf2 0.11.0", "salsa20", "sha2 0.10.6", ] @@ -3867,17 +3826,11 @@ dependencies = [ "untrusted", ] -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - [[package]] name = "sec1" -version = "0.3.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e" dependencies = [ "base16ct", "der", @@ -3914,6 +3867,12 @@ dependencies = [ "pest", ] +[[package]] +name = "send_wrapper" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" + [[package]] name = "send_wrapper" version = "0.6.0" @@ -3929,16 +3888,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-aux" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a77223b653fa95f3f9864f3eb25b93e4ed170687eb42d85b6b98af21d5e1de" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "serde_cbor" version = "0.11.2" @@ -3957,7 +3906,7 @@ checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -3971,6 +3920,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4002,32 +3960,20 @@ dependencies = [ "darling 0.13.4", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] -name = "sha-1" -version = "0.10.1" +name = "sha1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", "digest 0.10.6", ] -[[package]] -name = "sha2" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - [[package]] name = "sha2" version = "0.9.9" @@ -4038,7 +3984,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -4059,7 +4005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b64dcef59ed4290b9fb562b53df07f564690d6539e8ecdd4728cf392477530bc" dependencies = [ "block-buffer 0.3.3", - "byte-tools 0.2.0", + "byte-tools", "digest 0.7.6", "keccak", ] @@ -4073,7 +4019,7 @@ dependencies = [ "block-buffer 0.9.0", "digest 0.9.0", "keccak", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -4088,9 +4034,9 @@ dependencies = [ [[package]] name = "signature" -version = "1.6.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ "digest 0.10.6", "rand_core", @@ -4137,9 +4083,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", "winapi", @@ -4147,9 +4093,9 @@ dependencies = [ [[package]] name = "solang-parser" -version = "0.1.16" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f68b8280e3f354d5646218319bcee4febe42833cef5ebf653cfc49d0a94409" +checksum = "ff87dae6cdccacdbf3b19e99b271083556e808de0f59c74a01482f64fdbc61fc" dependencies = [ "itertools", "lalrpop", @@ -4166,9 +4112,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spki" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e" dependencies = [ "base64ct", "der", @@ -4188,8 +4134,8 @@ checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" dependencies = [ "new_debug_unreachable", "once_cell", - "parking_lot 0.12.1", - "phf_shared", + "parking_lot", + "phf_shared 0.10.0", "precomputed-hash", ] @@ -4224,7 +4170,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 1.0.107", ] [[package]] @@ -4244,6 +4190,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tabbycat" version = "0.1.2" @@ -4261,6 +4218,19 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tempfile" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall 0.3.5", + "rustix 0.37.8", + "windows-sys 0.45.0", +] + [[package]] name = "term" version = "0.7.0" @@ -4311,7 +4281,7 @@ dependencies = [ "strum", "strum_macros", "thiserror", - "toml", + "toml 0.5.11", "urlencoding", "yaml-rust", "zkevm-circuits", @@ -4349,7 +4319,7 @@ checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -4399,31 +4369,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.25.0" +version = "1.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" dependencies = [ "autocfg", "bytes", "libc", - "memchr", "mio", "num_cpus", "pin-project-lite", "socket2", "tokio-macros", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] @@ -4439,9 +4408,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.17.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" +checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" dependencies = [ "futures-util", "log", @@ -4476,12 +4445,33 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.1", + "toml_edit 0.19.8", +] + [[package]] name = "toml_datetime" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde", +] + [[package]] name = "toml_edit" version = "0.18.1" @@ -4490,7 +4480,20 @@ checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" dependencies = [ "indexmap", "nom8", - "toml_datetime", + "toml_datetime 0.5.1", +] + +[[package]] +name = "toml_edit" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.1", + "winnow", ] [[package]] @@ -4519,7 +4522,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -4555,9 +4558,9 @@ checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd" [[package]] name = "tungstenite" -version = "0.17.3" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" +checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" dependencies = [ "base64 0.13.1", "byteorder", @@ -4567,7 +4570,7 @@ dependencies = [ "log", "rand", "rustls", - "sha-1", + "sha1", "thiserror", "url", "utf-8", @@ -4619,6 +4622,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.10" @@ -4730,7 +4739,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.107", "wasm-bindgen-shared", ] @@ -4764,7 +4773,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4775,21 +4784,6 @@ version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" -[[package]] -name = "wasm-timer" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.11.2", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "web-sys" version = "0.3.61" @@ -4862,13 +4856,13 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 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.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", ] [[package]] @@ -4877,7 +4871,16 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.1", +] + +[[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.0", ] [[package]] @@ -4886,13 +4889,28 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" 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.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] [[package]] @@ -4901,42 +4919,93 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + [[package]] name = "windows_aarch64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + [[package]] name = "windows_i686_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + [[package]] name = "windows_i686_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + [[package]] name = "windows_x86_64_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + [[package]] name = "windows_x86_64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.10.1" @@ -4967,7 +5036,7 @@ dependencies = [ "log", "pharos", "rustc_version 0.4.0", - "send_wrapper", + "send_wrapper 0.6.0", "thiserror", "wasm-bindgen", "wasm-bindgen-futures", diff --git a/bus-mapping/Cargo.toml b/bus-mapping/Cargo.toml index 65b0b411da..6dd72ddd1b 100644 --- a/bus-mapping/Cargo.toml +++ b/bus-mapping/Cargo.toml @@ -11,8 +11,8 @@ gadgets = { path = "../gadgets" } keccak256 = { path = "../keccak256" } mock = { path = "../mock", optional = true } -ethers-core = "0.17.0" -ethers-providers = "0.17.0" +ethers-core = "2.0.0" +ethers-providers = "2.0.0" halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2023_02_02" } itertools = "0.10" lazy_static = "1.4" diff --git a/circuit-benchmarks/Cargo.toml b/circuit-benchmarks/Cargo.toml index 3646c329a5..2fe7f48aaf 100644 --- a/circuit-benchmarks/Cargo.toml +++ b/circuit-benchmarks/Cargo.toml @@ -17,7 +17,7 @@ rand = "0.8" itertools = "0.10" eth-types = { path = "../eth-types" } env_logger = "0.9" -ethers-signers = "0.17.0" +ethers-signers = "2.0.2" mock = { path="../mock" } rand_chacha = "0.3" diff --git a/eth-types/Cargo.toml b/eth-types/Cargo.toml index 078c1fee99..b8f6637bb2 100644 --- a/eth-types/Cargo.toml +++ b/eth-types/Cargo.toml @@ -6,8 +6,8 @@ authors = ["The appliedzkp team"] license = "MIT OR Apache-2.0" [dependencies] -ethers-core = "0.17.0" -ethers-signers = "0.17.0" +ethers-core = "2.0.2" +ethers-signers = "2.0.2" hex = "0.4" lazy_static = "1.4" halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2023_02_02" } diff --git a/eth-types/src/geth_types.rs b/eth-types/src/geth_types.rs index 818c544163..f3f29adb4a 100644 --- a/eth-types/src/geth_types.rs +++ b/eth-types/src/geth_types.rs @@ -263,7 +263,9 @@ impl GethData { assert_eq!(Word::from(wallet.chain_id()), self.chain_id); let geth_tx: Transaction = (&*tx).into(); let req: TransactionRequest = (&geth_tx).into(); - let sig = wallet.sign_transaction_sync(&req.chain_id(self.chain_id.as_u64()).into()); + let sig = wallet + .sign_transaction_sync(&req.chain_id(self.chain_id.as_u64()).into()) + .unwrap(); tx.v = U64::from(sig.v); tx.r = sig.r; tx.s = sig.s; diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index a95848d960..e29fdacbaa 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] lazy_static = "1.4" -ethers = { version = "0.17.0", features = ["ethers-solc"] } +ethers = { version = "2.0.0", features = ["ethers-solc"] } serde_json = "1.0.66" serde = { version = "1.0.130", features = ["derive"] } bus-mapping = { path = "../bus-mapping" } diff --git a/mock/Cargo.toml b/mock/Cargo.toml index 406341ab7d..0da906f1b1 100644 --- a/mock/Cargo.toml +++ b/mock/Cargo.toml @@ -10,7 +10,7 @@ eth-types = { path = "../eth-types" } external-tracer = { path = "../external-tracer" } lazy_static = "1.4" itertools = "0.10.3" -ethers-signers = "0.17.0" -ethers-core = "0.17.0" +ethers-signers = "2.0.2" +ethers-core = "2.0.2" rand_chacha = "0.3" rand = "0.8" diff --git a/mock/src/transaction.rs b/mock/src/transaction.rs index 9bb9b00291..3210c131da 100644 --- a/mock/src/transaction.rs +++ b/mock/src/transaction.rs @@ -325,7 +325,8 @@ impl MockTransaction { .from .as_wallet() .with_chain_id(self.chain_id.low_u64()) - .sign_transaction_sync(&tx.into()); + .sign_transaction_sync(&tx.into()) + .unwrap(); // Set sig parameters self.sig_data((sig.v, sig.r, sig.s)); } diff --git a/rust-toolchain b/rust-toolchain index 24b6d11f20..75fa63e38e 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2022-08-23 +nightly-2023-03-28 diff --git a/testool/Cargo.toml b/testool/Cargo.toml index a55df16161..c0bd2cc62c 100644 --- a/testool/Cargo.toml +++ b/testool/Cargo.toml @@ -10,8 +10,8 @@ bus-mapping = { path = "../bus-mapping" } clap = { version = "3.1", features = ["derive"] } env_logger = "0.9" eth-types = { path="../eth-types" } -ethers-core = "0.17.0" -ethers-signers = "0.17.0" +ethers-core = "2.0.2" +ethers-signers = "2.0.2" external-tracer = { path="../external-tracer" } glob = "0.3" handlebars = "4.3" diff --git a/testool/src/statetest/executor.rs b/testool/src/statetest/executor.rs index 1b110f6062..fcd8cc273b 100644 --- a/testool/src/statetest/executor.rs +++ b/testool/src/statetest/executor.rs @@ -123,7 +123,7 @@ fn into_traceconfig(st: StateTest) -> (String, TraceConfig, StateTestResult) { } let tx: TypedTransaction = tx.into(); - let sig = wallet.sign_transaction_sync(&tx); + let sig = wallet.sign_transaction_sync(&tx).unwrap(); ( st.id, @@ -242,7 +242,7 @@ pub fn run_test( ..eth_types::Block::default() }; - let wallet: LocalWallet = SigningKey::from_bytes(&st.secret_key).unwrap().into(); + let wallet: LocalWallet = SigningKey::from_slice(&st.secret_key).unwrap().into(); let mut wallets = HashMap::new(); wallets.insert( wallet.address(), diff --git a/testool/src/statetest/json.rs b/testool/src/statetest/json.rs index a083077a8f..7d24676064 100644 --- a/testool/src/statetest/json.rs +++ b/testool/src/statetest/json.rs @@ -111,7 +111,7 @@ impl<'a> JsonStateTestBuilder<'a> { let to = parse::parse_to_address(&test.transaction.to)?; let secret_key = parse::parse_bytes(&test.transaction.secret_key)?; - let from = secret_key_to_address(&SigningKey::from_bytes(&secret_key.to_vec())?); + let from = secret_key_to_address(&SigningKey::from_slice(&secret_key)?); let nonce = parse::parse_u256(&test.transaction.nonce)?; let gas_price = parse::parse_u256(&test.transaction.gas_price)?; diff --git a/testool/src/statetest/spec.rs b/testool/src/statetest/spec.rs index b2d224a73f..5528655f87 100644 --- a/testool/src/statetest/spec.rs +++ b/testool/src/statetest/spec.rs @@ -196,7 +196,7 @@ impl StateTest { let value = parse_u256(tx.next().unwrap_or("0"))?; let gas_limit = u64::from_str(tx.next().unwrap_or("10000000"))?; let secret_key = Bytes::from(&[1u8; 32]); - let from = secret_key_to_address(&SigningKey::from_bytes(&secret_key.to_vec())?); + let from = secret_key_to_address(&SigningKey::from_slice(&secret_key)?); let mut pre = HashMap::::new(); diff --git a/testool/src/statetest/yaml.rs b/testool/src/statetest/yaml.rs index a6ae70ef68..8f3cf7def1 100644 --- a/testool/src/statetest/yaml.rs +++ b/testool/src/statetest/yaml.rs @@ -107,7 +107,7 @@ impl<'a> YamlStateTestBuilder<'a> { let nonce = Self::parse_u256(&yaml_transaction["nonce"])?; let to = Self::parse_to_address(&yaml_transaction["to"])?; let secret_key = Self::parse_bytes(&yaml_transaction["secretKey"])?; - let from = secret_key_to_address(&SigningKey::from_bytes(&secret_key.to_vec())?); + let from = secret_key_to_address(&SigningKey::from_slice(&secret_key)?); // parse expects (account states before executing the transaction) let mut expects = Vec::new(); diff --git a/zkevm-circuits/Cargo.toml b/zkevm-circuits/Cargo.toml index c84f32ad7d..b6b5fc9707 100644 --- a/zkevm-circuits/Cargo.toml +++ b/zkevm-circuits/Cargo.toml @@ -15,8 +15,8 @@ array-init = "2.0.0" bus-mapping = { path = "../bus-mapping" } eth-types = { path = "../eth-types" } gadgets = { path = "../gadgets" } -ethers-core = "0.17.0" -ethers-signers = { version = "0.17.0", optional = true } +ethers-core = "2.0.2" +ethers-signers = { version = "2.0.2", optional = true } mock = { path = "../mock", optional = true } strum = "0.24" strum_macros = "0.24" @@ -42,7 +42,6 @@ num_enum = "0.5.7" bus-mapping = { path = "../bus-mapping", features = ["test"] } criterion = "0.3" ctor = "0.1.22" -ethers-signers = "0.17.0" hex = "0.4.3" itertools = "0.10.1" mock = { path = "../mock" } diff --git a/zkevm-circuits/src/lib.rs b/zkevm-circuits/src/lib.rs index db5ded8922..f6b08b8079 100644 --- a/zkevm-circuits/src/lib.rs +++ b/zkevm-circuits/src/lib.rs @@ -18,6 +18,7 @@ #![deny(clippy::debug_assert_with_mut_call)] pub mod bytecode_circuit; +pub mod circuit_tools; pub mod copy_circuit; pub mod evm_circuit; pub mod exp_circuit; @@ -28,7 +29,6 @@ pub mod root_circuit; pub mod state_circuit; pub mod super_circuit; pub mod table; -pub mod circuit_tools; #[cfg(any(feature = "test", test))] pub mod test_util; @@ -40,4 +40,5 @@ pub mod tx_circuit; pub mod util; pub mod witness; +// extern crate gadgets; pub use gadgets::impl_expr; diff --git a/zkevm-circuits/src/mpt_circuit/lib.rs b/zkevm-circuits/src/mpt_circuit/lib.rs index b4c0247823..39dae97eeb 100644 --- a/zkevm-circuits/src/mpt_circuit/lib.rs +++ b/zkevm-circuits/src/mpt_circuit/lib.rs @@ -8,3 +8,4 @@ pub mod mpt; pub mod param; pub mod storage_leaf; pub mod witness_row; +extern crate gadgets; From ea3bcb48fd9176e7476d830f8c61e50bd895a3e1 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Sat, 6 May 2023 09:09:59 +0000 Subject: [PATCH 02/21] init ver, no lookup and 33 bytes columns --- Cargo.lock | 1 + zkevm-circuits/Cargo.toml | 3 +- zkevm-circuits/src/lib.rs | 3 +- zkevm-circuits/src/rlp_decoder.rs | 1288 +++++++++++++++++++++++++++++ 4 files changed, 1293 insertions(+), 2 deletions(-) create mode 100644 zkevm-circuits/src/rlp_decoder.rs diff --git a/Cargo.lock b/Cargo.lock index 7558dfabe8..6dc34cfe93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5089,6 +5089,7 @@ checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" name = "zkevm-circuits" version = "0.1.0" dependencies = [ + "ark-std", "array-init", "bus-mapping", "cli-table", diff --git a/zkevm-circuits/Cargo.toml b/zkevm-circuits/Cargo.toml index b6b5fc9707..30f3f08cb0 100644 --- a/zkevm-circuits/Cargo.toml +++ b/zkevm-circuits/Cargo.toml @@ -37,6 +37,7 @@ subtle = "2.4" rand_chacha = "0.3" snark-verifier = { git = "https://github.com/privacy-scaling-explorations/snark-verifier", tag = "v2023_02_02", default-features = false, features = ["loader_halo2", "system_halo2"] } num_enum = "0.5.7" +ark-std = { version = "0.3", features = ["print-trace"] } [dev-dependencies] bus-mapping = { path = "../bus-mapping", features = ["test"] } @@ -51,7 +52,7 @@ serde = { version = "1.0.130", features = ["derive"] } serde_json = "1.0.78" [features] -default = [] +default = ["test"] test = ["ethers-signers", "mock"] test-circuits = [] warn-unimplemented = ["eth-types/warn-unimplemented"] diff --git a/zkevm-circuits/src/lib.rs b/zkevm-circuits/src/lib.rs index f6b08b8079..33671b196f 100644 --- a/zkevm-circuits/src/lib.rs +++ b/zkevm-circuits/src/lib.rs @@ -25,6 +25,7 @@ pub mod exp_circuit; pub mod keccak_circuit; pub mod mpt_circuit; pub mod pi_circuit; +pub mod rlp_decoder; pub mod root_circuit; pub mod state_circuit; pub mod super_circuit; @@ -40,5 +41,5 @@ pub mod tx_circuit; pub mod util; pub mod witness; -// extern crate gadgets; +extern crate gadgets; pub use gadgets::impl_expr; diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs new file mode 100644 index 0000000000..9e36d0886d --- /dev/null +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -0,0 +1,1288 @@ +//! The rlp decoding transaction list circuit implementation. + +// Naming notes: +// - *_be: Big-Endian bytes +// - *_le: Little-Endian bytes + +use crate::{ + evm_circuit::util::{constraint_builder::BaseConstraintBuilder, rlc}, + impl_expr, + table::{KeccakTable, TxFieldTag, TxTable}, + util::{Challenges, SubCircuit, SubCircuitConfig}, + witness, +}; +use eth_types::{ + sign_types::SignData, Address, Field, Signature, ToBigEndian, ToLittleEndian, ToScalar, ToWord, + Transaction, Word, +}; +use ethers_core::{types::TransactionRequest, utils::rlp}; +use gadgets::{evm_word::r, util::not}; +use halo2_proofs::{ + circuit::{AssignedCell, Layouter, Region, SimpleFloorPlanner, Value}, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Expression, Fixed, Selector}, + poly::Rotation, +}; +// use itertools::Itertools; +// use log::error; +// use sign_verify::{AssignedSignatureVerify, SignVerifyChip, SignVerifyConfig}; +// use std::marker::PhantomData; + +pub use halo2_proofs::halo2curves::{ + group::{ + ff::{Field as GroupField, PrimeField}, + prime::PrimeCurveAffine, + Curve, Group, GroupEncoding, + }, + secp256k1::{self, Secp256k1Affine, Secp256k1Compressed}, +}; +use mock::MockTransaction; + +use crate::util::Expr; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum RlpDecodeTypeTag { + SingleByte, // 0x00 - 0x7f + NullValue, // 0x80 + ShortString, // 0x81~0x88 should be enough + EmptyList, // 0xc0 + LongList1, // 0xc1 ~ 0xf7 + LongList2, // 0xf8 + LongList3, // 0xf9, 0xFFFF upto (64K) + // LongList4, // 0xfa, 0xFFFFFF upto (16M) + PartialRlp, // for those rlp that is not complete + RlpDecodeTypeNum, +} +impl_expr!(RlpDecodeTypeTag); + +impl std::ops::Index for [T; N] { + type Output = T; + + fn index(&self, index: RlpDecodeTypeTag) -> &Self::Output { + &self[index as usize] + } +} + +impl std::ops::Index for Vec { + type Output = T; + + fn index(&self, index: RlpDecodeTypeTag) -> &Self::Output { + &self[index as usize] + } +} + +// single, null, short, long1, long2, long3, long4, partial, length, r_mult +// 1, 0, 0, 0, 0, 0, 0, 0, 1~3, r^(0~2) +// 0, 1, 0, 0, 0, 0, 0, 0, 1, r^0 +// 0, 0, 1, 0, 0, 0, 0, 0, 1~33, r^(0~32) +// 0, 0, 1, 0, 0, 0, 0, 0, 2, r^1 +// . +// 0, 0, 0, 1, 0, 0, 0, 0, 1~33, r^(0~32) +// 0, 0, 0, 0, 1, 0, 0, 0, 1~33, r^(0~32) +// 0, 0, 0, 0, 0, 1, 0, 0, 1~33, r^(0~32) +// 0, 0, 0, 0, 0, 0, 1, 0, 1~33, r^(0~32) +// 0, 0, 0, 0, 0, 0, 0, 1, 1~33, r^(0~32) +#[derive(Clone, Debug)] +struct RlpDecodeTable { + rlp_type: [Column; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], + bytes_length: Column, // max 33 bytes + r_mult: Column, +} + +// TODO: combine with TxFieldTag in table.rs +/// Marker that defines whether an Operation performs a `READ` or a `WRITE`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum RlpTxFieldTag { + // for legacy tx + Nonce, + GasPrice, + Gas, + To, + Value, + Data, + SignV, + SignR, + SignS, + Padding, + // 1559 extra field + ChainID, + GasTipCap, + GasFeeCap, + AccessList, +} +impl_expr!(RlpTxFieldTag); + +impl std::ops::Index for [T; N] { + type Output = T; + + fn index(&self, index: RlpTxFieldTag) -> &Self::Output { + &self[index as usize] + } +} + +impl std::ops::Index for Vec { + type Output = T; + + fn index(&self, index: RlpTxFieldTag) -> &Self::Output { + &self[index as usize] + } +} + +const LegacyTxFieldNum: usize = RlpTxFieldTag::Padding as usize + 1 as usize; +const Tx1559TxFieldNum: usize = RlpTxFieldTag::AccessList as usize + 1 as usize; + +// TODO: combine with TxFieldTag in table.rs +/// Marker that defines whether an Operation performs a `READ` or a `WRITE`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum RlpTxTypeTag { + TxLegacyType, + Tx1559Type, +} +impl_expr!(RlpTxTypeTag); + +const MAX_BYTE_COLUMN: usize = 33; + +/// Config for RlpDecoderCircuit +#[derive(Clone, Debug)] +pub struct RlpDecoderCircuitConfig { + /// tx_id column + pub tx_id: Column, + /// tx_type column + pub tx_type: Column, + /// tag column + pub tag: Column, + /// complete column + pub complete: Column, + /// rlp types: [single, short, long, very_long, fixed(33)] + pub rlp_types: [Column; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], + /// rlp_tag_length, the length of this rlp field + pub rlp_tag_length: Column, + /// remained rows, for n < 33 fields, it is n, for m > 33 fields, it is 33 and next row is + /// partial, next_length = m - 33 + pub tag_bytes_in_row: Column, + /// r_mult column, (length, r_mult) => @fixed + pub r_mult: Column, + /// remain_length + pub rlp_remain_length: Column, + /// value + pub value: Column, + /// acc_rlc_value + pub acc_rlc_value: Column, + /// bytes + pub bytes: [Column; MAX_BYTE_COLUMN], + /// decodable, 0 for decode failed, 1 for success + pub decodable: Column, + /// valid, 0 for invalid, 1 for valid, should be == decodable at the end of the circuit + pub valid: Column, + /// dynamic selector for fields + pub q_fields: [Column; LegacyTxFieldNum as usize], + /// full chip enable + pub q_enable: Selector, + /// the begining + pub q_first: Column, + /// the end + pub q_last: Column, + /// args + pub args: RlpDecoderCircuitConfigArgs, +} + +#[derive(Clone, Debug)] +/// Circuit configuration arguments +pub struct RlpDecoderCircuitConfigArgs { + /// TxTable + pub tx_table: TxTable, + /// KeccakTable + pub keccak_table: KeccakTable, + /// Challenges + pub challenges: Challenges>, +} + +impl SubCircuitConfig for RlpDecoderCircuitConfig { + type ConfigArgs = RlpDecoderCircuitConfigArgs; + + /// Return a new RlpDecoderCircuitConfig + fn new(meta: &mut ConstraintSystem, args: Self::ConfigArgs) -> Self { + let tx_id = meta.advice_column(); + let tx_type = meta.advice_column(); + let tag = meta.advice_column(); + let complete = meta.advice_column(); + let rlp_types = [meta.advice_column(); RlpDecodeTypeTag::RlpDecodeTypeNum as usize]; + let rlp_tag_length = meta.advice_column(); + let tag_bytes_in_row = meta.advice_column(); + let rlp_remain_length = meta.advice_column(); + let r_mult = meta.advice_column(); + let value = meta.advice_column(); + let acc_rlc_value = meta.advice_column(); + let bytes = [meta.advice_column(); 33]; + let decodable = meta.advice_column(); + let valid = meta.advice_column(); + let q_fields = [meta.advice_column(); LegacyTxFieldNum]; + let q_enable = meta.selector(); + let q_first = meta.fixed_column(); + let q_last = meta.fixed_column(); + + // common logic + meta.create_gate("common", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tx_id = meta.query_advice(tx_id, Rotation::cur()); + let tx_type = meta.query_advice(tx_type, Rotation::cur()); + let tag = meta.query_advice(tag, Rotation::cur()); + let complete_cur = meta.query_advice(complete, Rotation::cur()); + let rlp_types_cur: [Expression; RlpDecodeTypeTag::RlpDecodeTypeNum as usize] = + rlp_types + .iter() + .map(|rlp_type| meta.query_advice(*rlp_type, Rotation::cur())) + .collect::>() + .try_into() + .unwrap(); + let rlp_tag_length_cur = meta.query_advice(rlp_tag_length, Rotation::cur()); + let r_mult = meta.query_advice(r_mult, Rotation::cur()); + let tag_bytes_in_row_cur = meta.query_advice(tag_bytes_in_row, Rotation::cur()); + let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); + let value = meta.query_advice(value, Rotation::cur()); + let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let valid = meta.query_advice(valid, Rotation::cur()); + let q_fields: Vec> = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + let q_enable = meta.query_selector(q_enable); + + // cb.require_boolean("q_enable boolean", q_enable); + cb.require_boolean("field complete boolean", complete_cur.expr()); + q_fields.iter().for_each(|q_col| { + cb.require_boolean("q_fields boolean", q_col.expr()); + }); + cb.require_boolean("decodable", decodable); + cb.require_boolean("valid", valid); + + rlp_types_cur.iter().for_each(|rlp_type_cur| { + cb.require_boolean("rlp_type boolean", rlp_type_cur.expr()); + }); + + // length without leading bytes + cb.condition(rlp_types_cur[RlpDecodeTypeTag::SingleByte].expr(), |cb| { + cb.require_equal("single length", rlp_tag_length_cur.clone(), 1.expr()) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::NullValue].expr(), |cb| { + cb.require_equal("empty length", rlp_tag_length_cur.clone(), 0.expr()) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::ShortString].expr(), |cb| { + cb.require_equal( + "single string length", + rlp_tag_length_cur.clone(), + bytes[0].expr() - 0x80.expr(), + ) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::EmptyList].expr(), |cb| { + cb.require_equal("empty list length", rlp_tag_length_cur.clone(), 0.expr()) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList1].expr(), |cb| { + cb.require_equal( + "short length", + rlp_tag_length_cur.clone(), + bytes[0].expr() - 0xc0.expr(), + ) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList2].expr(), |cb| { + cb.require_equal("long length", rlp_tag_length_cur.clone(), bytes[1].expr()) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList3].expr(), |cb| { + cb.require_equal( + "long length", + rlp_tag_length_cur.clone(), + bytes[1].expr() * 256.expr() + bytes[2].expr(), + ) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::PartialRlp].expr(), |cb| { + cb.require_equal( + "length = prev_length - prev_bytes_in_row", + rlp_tag_length_cur.clone(), + meta.query_advice(rlp_tag_length, Rotation::prev()) + - tag_bytes_in_row_cur.expr(), + ); + + cb.require_zero( + "above row is incomplete", + meta.query_advice(complete, Rotation::prev()), + ); + }); + + cb.condition(complete_cur.expr(), |cb| { + cb.require_equal( + "complete = 1 => remain_length = bytes_in_row", + tag_bytes_in_row_cur.expr(), + remain_length.expr(), + ); + + cb.require_equal( + "rlp_remain_length = rlp_remain_length.prev - length", + remain_length.expr(), + meta.query_advice(rlp_remain_length, Rotation::prev()) + - tag_bytes_in_row_cur.expr(), + ); + }); + + cb.require_equal( + "rlc = r_mult_cur * rlc_next + rlc(bytes_cur)", + acc_rlc_cur, + r_mult * meta.query_advice(acc_rlc_value, Rotation::next()) + + rlc::expr( + bytes.iter().rev().collect::>().as_ref(), + &args.challenges.keccak_input(), + ), + ); + + // TODO: lookup rlp_types table + // TODO: lookup r_mult table + // TODO: lookup bytes range table + cb.gate(q_enable) + }); + + // TxListHeader in the first row + meta.create_gate("txListHeader", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tx_id = meta.query_advice(tx_id, Rotation::cur()); + let tx_type_cur = meta.query_advice(tx_type, Rotation::cur()); + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let tag_next = meta.query_advice(tag, Rotation::next()); + let complete = meta.query_advice(complete, Rotation::cur()); + let length = meta.query_advice(rlp_tag_length, Rotation::cur()); + let r_mult = meta.query_advice(r_mult, Rotation::cur()); + let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); + let value = meta.query_advice(value, Rotation::cur()); + let acc_rlc_value = meta.query_advice(acc_rlc_value, Rotation::cur()); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let valid = meta.query_advice(valid, Rotation::cur()); + let q_first = meta.query_fixed(q_first, Rotation::cur()); + + cb.require_zero("0 tx_id", tx_id); + cb.require_zero("0 tx_type", tx_type_cur.expr()); + cb.require_zero("0 tx_tag", tag_cur); + cb.require_equal("field completed", complete.expr(), 1.expr()); + + // next should be nonce if legacy(0) or chain_id if 1559 + cb.condition(not::expr(tx_type_cur.expr()), |cb| { + let tx_type_next = meta.query_advice(tx_type, Rotation::next()); + cb.require_equal( + "next tx is legacy", + tx_type_next, + RlpTxTypeTag::TxLegacyType.expr(), + ); + cb.require_equal("next field is nonce", tag_next, RlpTxFieldTag::Nonce.expr()); + }); + + // TODO: enable 1559 + // cb.condition("tx 1559", |cb| { + // let next_tx_type = meta.query_advice(tx_type, Rotation::next()); + // cb.require_equal( + // "next tx is 1559", + // next_tx_type, + // RlpTxTypeTag::Tx1559Type.expr(), + // ); + // cb.require_equal( + // "next field is nonce", + // next_tag, + // RlpTxFieldTag::ChainID.expr(), + // ); + // }); + + cb.condition(decodable, |cb| { + // TODO: use look up?? + cb.require_in_set( + "list header in [0xf8,0xf9,0xfa]", + bytes[0].expr(), + vec![248.expr(), 249.expr(), 250.expr()], + ) + }); + + cb.gate(q_first) + }); + + // Nonce + meta.create_gate("Nonce", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let rlp_types = rlp_types + .iter() + .map(|rlp_type| meta.query_advice(*rlp_type, Rotation::cur())) + .collect::>(); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal("nonce tag", tag_cur, RlpTxFieldTag::Nonce.expr()); + cb.require_equal("field completed", complete.expr(), 1.expr()); + // next is gas_price + cb.require_equal( + "next field is gas_price", + meta.query_advice(tag, Rotation::next()), + RlpTxFieldTag::GasPrice.expr(), + ); + + cb.require_equal( + "decodable if not null", + decodable, + not::expr(rlp_types[RlpDecodeTypeTag::NullValue].expr()), + ); + + // TODO: lookup nonce rlp_type table, should be single or short + cb.gate(q_fields[RlpTxFieldTag::Nonce].expr() * meta.query_selector(q_enable)) + }); + + // gas price + meta.create_gate("Gas price", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let rlp_types = rlp_types + .iter() + .map(|rlp_type| meta.query_advice(*rlp_type, Rotation::cur())) + .collect::>(); + + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal("gas price tag", tag_cur, RlpTxFieldTag::GasPrice.expr()); + // next is gas_price + cb.require_equal( + "next field is gas_limit", + meta.query_advice(tag, Rotation::next()), + RlpTxFieldTag::Gas.expr(), + ); + + cb.require_equal( + "decodable if not null", + decodable, + not::expr(rlp_types[RlpDecodeTypeTag::NullValue].expr()), + ); + + cb.gate(q_fields[RlpTxFieldTag::GasPrice].expr() * meta.query_selector(q_enable)) + }); + + // Gas + meta.create_gate("Gas", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let rlp_types = rlp_types + .iter() + .map(|rlp_type| meta.query_advice(*rlp_type, Rotation::cur())) + .collect::>(); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal("tag", tag_cur, RlpTxFieldTag::Gas.expr()); + cb.require_equal("field completed", complete.expr(), 1.expr()); + cb.require_equal( + "next field is To", + meta.query_advice(tag, Rotation::next()), + RlpTxFieldTag::To.expr(), + ); + + cb.require_equal( + "decodable if not null", + decodable, + not::expr(rlp_types[RlpDecodeTypeTag::NullValue].expr()), + ); + + cb.gate(q_fields[RlpTxFieldTag::Gas].expr() * meta.query_selector(q_enable)) + }); + + // To + meta.create_gate("To", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal("tag", tag_cur, RlpTxFieldTag::To.expr()); + cb.require_equal("field completed", complete.expr(), 1.expr()); + cb.require_equal( + "next field is Value", + meta.query_advice(tag, Rotation::next()), + RlpTxFieldTag::Value.expr(), + ); + + // TODO: Lookup fix length 0xa0/0x80 + cb.require_in_set( + "0xa0 or 0x80", + bytes[0].expr(), + vec![160.expr(), 128.expr()], + ); + + cb.gate(q_fields[RlpTxFieldTag::To].expr() * meta.query_selector(q_enable)) + }); + + // Value + meta.create_gate("Value", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal("tag", tag_cur, RlpTxFieldTag::Value.expr()); + cb.require_equal("field completed", complete.expr(), 1.expr()); + cb.require_equal( + "next field is Data", + meta.query_advice(tag, Rotation::next()), + RlpTxFieldTag::Data.expr(), + ); + + cb.gate(q_fields[RlpTxFieldTag::Value].expr() * meta.query_selector(q_enable)) + }); + + // Data + meta.create_gate("Data", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal("tag", tag_cur, RlpTxFieldTag::Data.expr()); + cb.require_equal("field completed", complete.expr(), 1.expr()); + cb.require_equal( + "next field is SignV", + meta.query_advice(tag, Rotation::next()), + RlpTxFieldTag::SignV.expr(), + ); + + cb.gate(q_fields[RlpTxFieldTag::Data].expr() * meta.query_selector(q_enable)) + }); + + // V + meta.create_gate("SignV", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal("tag", tag_cur, RlpTxFieldTag::SignV.expr()); + cb.require_equal("field completed", complete.expr(), 1.expr()); + cb.require_equal( + "next field is SignR", + meta.query_advice(tag, Rotation::next()), + RlpTxFieldTag::SignR.expr(), + ); + + cb.gate(q_fields[RlpTxFieldTag::SignV].expr() * meta.query_selector(q_enable)) + }); + + // R + meta.create_gate("SignR", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal("tag", tag_cur, RlpTxFieldTag::SignR.expr()); + cb.require_equal("field completed", complete.expr(), 1.expr()); + + cb.require_equal( + "decodable if valid rlp header", + not::expr(decodable), + bytes[0].expr() - 0xa0.expr(), + ); + + // next is signS + cb.require_equal( + "next field is SignR", + meta.query_advice(tag, Rotation::next()), + RlpTxFieldTag::SignS.expr(), + ); + + cb.gate(q_fields[RlpTxFieldTag::SignR].expr() * meta.query_selector(q_enable)) + }); + + // S + meta.create_gate("SignS", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal("tag", tag_cur, RlpTxFieldTag::SignS.expr()); + cb.require_equal("field completed", complete.expr(), 1.expr()); + // next is a new tx or padding + cb.require_in_set( + "next field is Nonce or Padding", + meta.query_advice(tag, Rotation::next()), + vec![RlpTxFieldTag::Nonce.expr(), RlpTxFieldTag::Padding.expr()], + ); + + cb.gate(q_fields[RlpTxFieldTag::SignS].expr() * meta.query_selector(q_enable)) + }); + + // padding + meta.create_gate("Padding", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let length = meta.query_advice(rlp_tag_length, Rotation::cur()); + let r_mult = meta.query_advice(r_mult, Rotation::cur()); + let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); + let value = meta.query_advice(value, Rotation::cur()); + let acc_rlc_value = meta.query_advice(acc_rlc_value, Rotation::cur()); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_last = meta.query_fixed(q_last, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal("tag", tag_cur, RlpTxFieldTag::Padding.expr()); + cb.require_equal("field completed", complete.expr(), 1.expr()); + // next is a new tx or padding + cb.require_in_set( + "next field is Padding or next tx nonce", + meta.query_advice(tag, Rotation::next()), + vec![RlpTxFieldTag::Nonce.expr(), RlpTxFieldTag::Padding.expr()], + ); + cb.require_equal("padding has no r_mult", r_mult, 0.expr()); + cb.require_equal("padding has no length", length, 0.expr()); + cb.require_equal("padding has no remain length", remain_length, 0.expr()); + cb.require_equal("padding has no rlc (all 0)", acc_rlc_value, 0.expr()); + + cb.gate( + q_fields[RlpTxFieldTag::Padding].expr() + * not::expr(q_last) + * meta.query_selector(q_enable), + ) + }); + + meta.create_gate("end logic", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let complete = meta.query_advice(complete, Rotation::cur()); + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let length = meta.query_advice(rlp_tag_length, Rotation::cur()); + let r_mult = meta.query_advice(r_mult, Rotation::cur()); + let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); + let value = meta.query_advice(value, Rotation::cur()); + let acc_rlc_value = meta.query_advice(acc_rlc_value, Rotation::cur()); + let bytes = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let valid = meta.query_advice(valid, Rotation::cur()); + let q_enable = meta.query_selector(q_enable); + let q_last = meta.query_fixed(q_last, Rotation::cur()); + + cb.require_equal("padding at last", tag_cur, RlpTxFieldTag::Padding.expr()); + cb.require_equal("padding has no r_mult", r_mult, 0.expr()); + cb.require_equal("padding has no length", length, 0.expr()); + cb.require_equal("padding has no remain length", remain_length, 0.expr()); + cb.require_equal("padding has no rlc (all 0)", acc_rlc_value, 0.expr()); + cb.require_equal("valid == decodable", valid, decodable); + + cb.gate(q_last) + }); + + Self { + tx_id, + tx_type, + tag, + complete, + rlp_types, + rlp_tag_length, + tag_bytes_in_row, + r_mult, + rlp_remain_length, + value, + acc_rlc_value, + bytes, + decodable, + valid, + q_fields, + q_enable, + q_first, + q_last, + args, + } + } +} + +impl RlpDecoderCircuitConfig { + fn assign_row( + &self, + region: &mut Region<'_, F>, + offset: usize, + value: u8, + ) -> Result, Error> { + todo!() + } + + /// Get number of rows required. + pub fn get_num_rows_required(num_tx: usize) -> usize { + return 0; + } +} + +/// rlp decode Circuit for verifying transaction signatures +#[derive(Clone, Default, Debug)] +pub struct RlpDecoderCircuit { + /// Max number of supported transactions + pub max_txs: usize, + /// Max number of supported calldata bytes + pub max_calldata: usize, + /// input bytes + pub bytes: Vec, + /// phantom + pub _marker: std::marker::PhantomData, +} + +impl RlpDecoderCircuit { + /// Return a new RlpDecoderCircuit + pub fn new(max_txs: usize, max_calldata: usize, bytes: Vec) -> Self { + RlpDecoderCircuit:: { + max_txs, + max_calldata, + bytes, + _marker: std::marker::PhantomData, + } + } + + /// Return the minimum number of rows required to prove an input of a + /// particular size. + pub fn min_num_rows(txs_len: usize, call_data_len: usize) -> usize { + 0 + } +} + +impl SubCircuit for RlpDecoderCircuit { + type Config = RlpDecoderCircuitConfig; + + fn new_from_block(block: &witness::Block) -> Self { + Self::new( + block.circuits_params.max_txs, + block.circuits_params.max_calldata, + Vec::::new(), + ) + } + + /// Return the minimum number of rows required to prove the block + fn min_num_rows_block(block: &witness::Block) -> (usize, usize) { + ( + Self::min_num_rows( + block.txs.len(), + block.txs.iter().map(|tx| tx.call_data.len()).sum(), + ), + Self::min_num_rows( + block.circuits_params.max_txs, + block.circuits_params.max_calldata, + ), + ) + } + + /// Make the assignments to the RlpDecodeCircuit + fn synthesize_sub( + &self, + config: &Self::Config, + challenges: &Challenges>, + layouter: &mut impl Layouter, + ) -> Result<(), Error> { + Ok(()) + } + + fn instance(&self) -> Vec> { + // The maingate expects an instance column, but we don't use it, so we return an + // "empty" instance column + vec![vec![]] + } +} + +#[cfg(any(feature = "test", test, feature = "test-circuits"))] +impl Circuit for RlpDecoderCircuit { + type Config = (RlpDecoderCircuitConfig, Challenges); + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let tx_table = TxTable::construct(meta); + let keccak_table = KeccakTable::construct(meta); + let challenges = Challenges::construct(meta); + + let config = { + let challenges = challenges.exprs(meta); + RlpDecoderCircuitConfig::new( + meta, + RlpDecoderCircuitConfigArgs { + tx_table, + keccak_table, + challenges, + }, + ) + }; + + (config, challenges) + } + + fn synthesize( + &self, + (config, challenges): Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + Ok(()) + } +} + +trait RlpWitness { + fn generate_rlp_decoded_witness(&self) -> Vec; +} + +impl RlpWitness for Transaction { + fn generate_rlp_decoded_witness(&self) -> Vec { + // TODO: use offset to split the input bytes + let mut bytes = Vec::new(); + bytes.extend_from_slice(rlp::encode(&self.nonce).as_ref()); + bytes.extend_from_slice(rlp::encode(&self.gas_price).as_ref()); + bytes.extend_from_slice(rlp::encode(&self.gas).as_ref()); + bytes.extend_from_slice(rlp::encode(&self.to).as_ref()); + bytes.extend_from_slice(rlp::encode(&self.value).as_ref()); + bytes.extend_from_slice(rlp::encode(&self.input.as_ref()).as_ref()); + bytes.extend_from_slice(rlp::encode(&self.v).as_ref()); + bytes.extend_from_slice(rlp::encode(&self.r).as_ref()); + bytes.extend_from_slice(rlp::encode(&self.s).as_ref()); + bytes + } +} + +fn rlp_decode(bytes: Vec) -> Result, Error> { + match rlp::Rlp::new(&bytes).as_list::() { + Ok(txlist) => { + // TODO: check txs.len() <= max_txs + let mut bytes = Vec::new(); + for tx in txlist { + let witness = tx.generate_rlp_decoded_witness(); + bytes.extend_from_slice(&witness) + } + Ok(bytes) + } + Err(e) => rlp_decode_tx_list_manually(&bytes), + } +} + +fn rlp_decode_tx_list_manually(bytes: &Vec) -> Result, Error> { + let mut bytes = Vec::new(); + bytes.push(0xc8); // empty [] + + Ok(bytes) +} + +/// Signed transaction in a witness block +#[derive(Debug, Clone)] +pub struct SignedTransaction { + /// Transaction data. + pub tx: Transaction, + /// ECDSA signature on the transaction. + pub signature: ethers_core::types::Signature, +} + +use rlp::{Encodable, RlpStream}; + +impl Encodable for SignedTransaction { + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(9); + s.append(&Word::from(self.tx.nonce)); + s.append(&self.tx.gas_price.unwrap()); + s.append(&Word::from(self.tx.gas)); + if let Some(addr) = self.tx.to { + s.append(&addr); + } else { + s.append(&""); + } + s.append(&self.tx.value); + s.append(&self.tx.input.to_vec()); + s.append(&self.signature.v); + s.append(&self.signature.r); + s.append(&self.signature.s); + } +} + +impl From<&Transaction> for SignedTransaction { + fn from(tx: &Transaction) -> Self { + Self { + tx: tx.clone(), + signature: ethers_core::types::Signature { + v: tx.v.as_u64(), + r: tx.r, + s: tx.s, + }, + } + } +} + +impl From for SignedTransaction { + fn from(mock_tx: MockTransaction) -> Self { + let tx = { + let is_create = mock_tx.to.is_none(); + let sig = Signature { + r: mock_tx.r.expect("tx expected to be signed"), + s: mock_tx.s.expect("tx expected to be signed"), + v: mock_tx.v.expect("tx expected to be signed").as_u64(), + }; + let (rlp_unsigned, rlp_signed) = { + let mut legacy_tx = TransactionRequest::new() + .from(mock_tx.from.address()) + .nonce(mock_tx.nonce) + .gas_price(mock_tx.gas_price) + .gas(mock_tx.gas) + .value(mock_tx.value) + .data(mock_tx.input.clone()) + .chain_id(mock_tx.chain_id.as_u64()); + if !is_create { + legacy_tx = legacy_tx.to(mock_tx.to.as_ref().map(|to| to.address()).unwrap()); + } + + let unsigned = legacy_tx.rlp().to_vec(); + + let signed = legacy_tx.rlp_signed(&sig).to_vec(); + + (unsigned, signed) + }; + Transaction { + hash: mock_tx.hash.unwrap(), + nonce: mock_tx.nonce, + gas_price: Some(mock_tx.gas_price), + gas: mock_tx.gas, + to: mock_tx.to.map(|to| to.address()), + value: mock_tx.value, + input: mock_tx.input, + v: mock_tx.v.unwrap(), + r: mock_tx.r.unwrap(), + s: mock_tx.s.unwrap(), + ..Default::default() + } + }; + SignedTransaction::from(&tx) + } +} + +#[cfg(test)] +mod rlp_test { + use super::SignedTransaction; + use ethers_core::utils::rlp; + use hex; + use rand::SeedableRng; + use rand_chacha::ChaCha20Rng; + + #[test] + fn test_decode() { + let tx: SignedTransaction = mock::CORRECT_MOCK_TXS[1].clone().into(); + let rlp_tx = rlp::encode(&tx); + println!("{:?}", hex::encode(rlp_tx)); + + let txs: Vec = vec![ + mock::CORRECT_MOCK_TXS[0].clone().into(), + mock::CORRECT_MOCK_TXS[1].clone().into(), + // mock::CORRECT_MOCK_TXS[2].clone().into(), + ]; + let rlp_txs = rlp::encode_list(&txs); + println!("{:?}", hex::encode(rlp_txs.clone())); + + let dec_txs = rlp::Rlp::new(rlp_txs.to_vec().as_slice()) + .as_list::() + .unwrap(); + println!("{:?}", dec_txs); + } + + #[test] + fn test_encode() { + let mut rng = ChaCha20Rng::seed_from_u64(2u64); + let tx: SignedTransaction = mock::MockTransaction::default() + .from(mock::AddrOrWallet::random(&mut rng)) + .to(mock::AddrOrWallet::random(&mut rng)) + .nonce(eth_types::word!("0x106")) + .value(eth_types::word!("0x3e8")) + .gas_price(eth_types::word!("0x4d2")) + .input(eth_types::Bytes::from( + b"hellohellohellohellohellohellohellohellohellohellohellohello", + )) + .build() + .into(); + let rlp_tx = rlp::encode(&tx); + println!("{:?}", hex::encode(rlp_tx)); + } +} + +#[cfg(test)] +mod rlp_decode_circuit_tests { + use super::*; + use crate::util::log2_ceil; + use eth_types::address; + use halo2_proofs::{ + dev::{MockProver, VerifyFailure}, + halo2curves::bn256::Fr, + }; + use mock::AddrOrWallet; + use pretty_assertions::assert_eq; + + const NUM_BLINDING_ROWS: usize = 64; + + fn run( + txs: Vec, + chain_id: u64, + max_txs: usize, + max_calldata: usize, + ) -> Result<(), Vec> { + let k = log2_ceil( + NUM_BLINDING_ROWS + RlpDecoderCircuit::::min_num_rows(max_txs, max_calldata), + ); + // SignVerifyChip -> ECDSAChip -> MainGate instance column + let circuit = RlpDecoderCircuit::::new(max_txs, max_calldata, vec![]); + + let prover = match MockProver::run(k, &circuit, vec![]) { + Ok(prover) => prover, + Err(e) => panic!("{:#?}", e), + }; + prover.verify() + } + + #[test] + fn tx_circuit_1tx_1max_tx() { + const MAX_TXS: usize = 1; + const MAX_CALLDATA: usize = 32; + + let chain_id: u64 = mock::MOCK_CHAIN_ID.as_u64(); + + let tx: Transaction = mock::CORRECT_MOCK_TXS[0].clone().into(); + + assert_eq!(run::(vec![tx], chain_id, MAX_TXS, MAX_CALLDATA), Ok(())); + } + + #[test] + fn tx_circuit_1tx_2max_tx() { + const MAX_TXS: usize = 2; + const MAX_CALLDATA: usize = 32; + + let chain_id: u64 = mock::MOCK_CHAIN_ID.as_u64(); + + let tx: Transaction = mock::CORRECT_MOCK_TXS[0].clone().into(); + + assert_eq!(run::(vec![tx], chain_id, MAX_TXS, MAX_CALLDATA), Ok(())); + } + + #[test] + fn tx_circuit_bad_address() { + const MAX_TXS: usize = 1; + const MAX_CALLDATA: usize = 32; + + let mut tx = mock::CORRECT_MOCK_TXS[0].clone(); + // This address doesn't correspond to the account that signed this tx. + tx.from = AddrOrWallet::from(address!("0x1230000000000000000000000000000000000456")); + + assert!(run::( + vec![tx.into()], + mock::MOCK_CHAIN_ID.as_u64(), + MAX_TXS, + MAX_CALLDATA + ) + .is_err(),); + } +} + +mod bench { + use ark_std::{end_timer, start_timer}; + use halo2_proofs::{ + halo2curves::bn256::{Bn256, Fr, G1Affine}, + plonk::{create_proof, keygen_pk, keygen_vk, verify_proof}, + poly::{ + commitment::ParamsProver, + kzg::{ + commitment::{KZGCommitmentScheme, ParamsKZG, ParamsVerifierKZG}, + multiopen::{ProverSHPLONK, VerifierSHPLONK}, + strategy::SingleStrategy, + }, + }, + transcript::{ + Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, + }, + }; + use std::env::var; + + use rand::SeedableRng; + + use rand_chacha::ChaChaRng; + + use super::*; + use crate::util::log2_ceil; + + #[test] + fn bench_super_circuit_prover() { + let setup_prfx = "crate::constants::SETUP"; + let proof_gen_prfx = "crate::constants::PROOFGEN_PREFIX"; + let proof_ver_prfx = "crate::constants::PROOFVER_PREFIX"; + // Unique string used by bench results module for parsing the result + const BENCHMARK_ID: &str = "Rlp decode Circuit"; + + let degree: u32 = var("DEGREE") + .unwrap_or_else(|_| "18".to_string()) + .parse() + .expect("Cannot parse DEGREE env var as u32"); + + let mut rng = ChaChaRng::seed_from_u64(2); + + let (circuit, instance) = { + let mut circuit = RlpDecoderCircuit::::new(10, 16384, vec![]); + let instance = vec![vec![]]; + (circuit, instance) + }; + let instance_refs: Vec<&[Fr]> = instance.iter().map(|v| &v[..]).collect(); + + // Bench setup generation + let setup_message = format!("{} {} with degree = {}", BENCHMARK_ID, setup_prfx, degree); + let start1 = start_timer!(|| setup_message); + let general_params = ParamsKZG::::setup(degree, &mut rng); + let verifier_params: ParamsVerifierKZG = general_params.verifier_params().clone(); + end_timer!(start1); + + // Initialize the proving key + let vk = keygen_vk(&general_params, &circuit).expect("keygen_vk should not fail"); + let pk = keygen_pk(&general_params, vk, &circuit).expect("keygen_pk should not fail"); + // Create a proof + let mut transcript = Blake2bWrite::<_, G1Affine, Challenge255<_>>::init(vec![]); + + // Bench proof generation time + let proof_message = format!( + "{} {} with degree = {}", + BENCHMARK_ID, proof_gen_prfx, degree + ); + let start2 = start_timer!(|| proof_message); + create_proof::< + KZGCommitmentScheme, + ProverSHPLONK<'_, Bn256>, + Challenge255, + ChaChaRng, + Blake2bWrite, G1Affine, Challenge255>, + RlpDecoderCircuit, + >( + &general_params, + &pk, + &[circuit], + &[&[]], + rng, + &mut transcript, + ) + .expect("proof generation should not fail"); + let proof = transcript.finalize(); + end_timer!(start2); + + // Bench verification time + let start3 = start_timer!(|| format!("{} {}", BENCHMARK_ID, proof_ver_prfx)); + let mut verifier_transcript = Blake2bRead::<_, G1Affine, Challenge255<_>>::init(&proof[..]); + let strategy = SingleStrategy::new(&general_params); + + verify_proof::< + KZGCommitmentScheme, + VerifierSHPLONK<'_, Bn256>, + Challenge255, + Blake2bRead<&[u8], G1Affine, Challenge255>, + SingleStrategy<'_, Bn256>, + >( + &verifier_params, + pk.get_vk(), + strategy, + &[&[]], + &mut verifier_transcript, + ) + .expect("failed to verify bench circuit"); + end_timer!(start3); + } +} From a2c4e16d779d0e8fa6a58bdf29a8c1e764a2cddf Mon Sep 17 00:00:00 2001 From: smtmfft Date: Thu, 11 May 2023 06:25:53 +0000 Subject: [PATCH 03/21] make constraints work for happy path --- Cargo.lock | 1 - Cargo.toml | 4 +- zkevm-circuits/src/rlp_decoder.rs | 1436 ++++++++++++++++++++++++----- 3 files changed, 1219 insertions(+), 222 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6dc34cfe93..96b50ff1e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2057,7 +2057,6 @@ dependencies = [ [[package]] name = "halo2_proofs" version = "0.2.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2023_02_02#0a8646b78286a13d320759b1c585262d6536dce4" dependencies = [ "blake2b_simd", "ff 0.12.1", diff --git a/Cargo.toml b/Cargo.toml index 100836d5ce..ea98d00f1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,8 +13,8 @@ members = [ "testool" ] -[patch.crates-io] -halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2023_02_02" } +[patch."https://github.com/privacy-scaling-explorations/halo2.git"] +halo2_proofs = { path = "../halo2/halo2_proofs" } # Definition of benchmarks profile to use. [profile.bench] diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 9e36d0886d..2dfc7ba9f3 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -1,25 +1,25 @@ //! The rlp decoding transaction list circuit implementation. -// Naming notes: -// - *_be: Big-Endian bytes -// - *_le: Little-Endian bytes +use std::marker::PhantomData; use crate::{ evm_circuit::util::{constraint_builder::BaseConstraintBuilder, rlc}, impl_expr, - table::{KeccakTable, TxFieldTag, TxTable}, - util::{Challenges, SubCircuit, SubCircuitConfig}, + table::{KeccakTable, TxTable}, + util::{log2_ceil, Challenges, SubCircuit, SubCircuitConfig}, witness, }; -use eth_types::{ - sign_types::SignData, Address, Field, Signature, ToBigEndian, ToLittleEndian, ToScalar, ToWord, - Transaction, Word, +use eth_types::{Field, Signature, Transaction, Word}; +use ethers_core::{ + types::TransactionRequest, + utils::rlp::{self, PayloadInfo}, }; -use ethers_core::{types::TransactionRequest, utils::rlp}; -use gadgets::{evm_word::r, util::not}; +use gadgets::util::{and, not}; use halo2_proofs::{ - circuit::{AssignedCell, Layouter, Region, SimpleFloorPlanner, Value}, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Expression, Fixed, Selector}, + circuit::{Layouter, Region, SimpleFloorPlanner, Value}, + plonk::{ + Advice, Circuit, Column, ConstraintSystem, Error, Expression, Fixed, SecondPhase, Selector, + }, poly::Rotation, }; // use itertools::Itertools; @@ -27,6 +27,7 @@ use halo2_proofs::{ // use sign_verify::{AssignedSignatureVerify, SignVerifyChip, SignVerifyConfig}; // use std::marker::PhantomData; +use crate::util::Expr; pub use halo2_proofs::halo2curves::{ group::{ ff::{Field as GroupField, PrimeField}, @@ -37,19 +38,37 @@ pub use halo2_proofs::halo2curves::{ }; use mock::MockTransaction; -use crate::util::Expr; +const NUM_BLINDING_ROWS: usize = 64; -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +/// RlpDecodeTypeTag is used to index the flag of rlp decoding type +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] pub enum RlpDecodeTypeTag { - SingleByte, // 0x00 - 0x7f - NullValue, // 0x80 - ShortString, // 0x81~0x88 should be enough - EmptyList, // 0xc0 - LongList1, // 0xc1 ~ 0xf7 - LongList2, // 0xf8 - LongList3, // 0xf9, 0xFFFF upto (64K) - // LongList4, // 0xfa, 0xFFFFFF upto (16M) - PartialRlp, // for those rlp that is not complete + #[default] + /// SingleByte: 0x00 - 0x7f + SingleByte, + /// NullValue: 0x80 + NullValue, + /// ShortString: 0x81~0xb7 + ShortString, + /// LongString: 0xb8 + LongString1, + /// LongString: 0xb9 + LongString2, + /// LongString: 0xba + LongString3, + /// EmptyList: 0xc0 + EmptyList, + /// ShortList: 0xc1 ~ 0xf7 + ShortList, + /// LongList1: 0xf8 + LongList1, + /// LongList2: 0xf9, 0xFFFF upto (64K) + LongList2, + /// LongList3: 0xfa, 0xFFFFFF upto (16M) + LongList3, + /// PartialRlp: for those rlp that is not complete + PartialRlp, + /// RlpDecodeTypeNum, RlpDecodeTypeNum, } impl_expr!(RlpDecodeTypeTag); @@ -89,24 +108,43 @@ struct RlpDecodeTable { } // TODO: combine with TxFieldTag in table.rs -/// Marker that defines whether an Operation performs a `READ` or a `WRITE`. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +// Marker that defines whether an Operation performs a `READ` or a `WRITE`. +/// RlpTxFieldTag is used to tell the field of tx, used as state in the circuit +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] pub enum RlpTxFieldTag { - // for legacy tx + #[default] + /// for tx list rlp header + TxListRlpHeader, + /// for rlp header + TxRlpHeader, + /// for tx nonce Nonce, + /// gas price GasPrice, + /// Gas Gas, + /// To To, + /// Value Value, + /// Data Data, + /// SignV SignV, + /// SignR SignR, + /// SignS SignS, + /// Padding Padding, // 1559 extra field + /// ChainID ChainID, + /// GasTipCap GasTipCap, + /// GasFeeCap GasFeeCap, + /// AccessList AccessList, } impl_expr!(RlpTxFieldTag); @@ -127,19 +165,65 @@ impl std::ops::Index for Vec { } } -const LegacyTxFieldNum: usize = RlpTxFieldTag::Padding as usize + 1 as usize; -const Tx1559TxFieldNum: usize = RlpTxFieldTag::AccessList as usize + 1 as usize; +const LEGACY_TX_FIELD_NUM: usize = RlpTxFieldTag::Padding as usize + 1; +const TX1559_TX_FIELD_NUM: usize = RlpTxFieldTag::AccessList as usize + 1; // TODO: combine with TxFieldTag in table.rs -/// Marker that defines whether an Operation performs a `READ` or a `WRITE`. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +// Marker that defines whether an Operation performs a `READ` or a `WRITE`. +/// RlpTxTypeTag is used to tell the type of tx +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] pub enum RlpTxTypeTag { + #[default] + /// legacy tx TxLegacyType, + /// 1559 tx Tx1559Type, } impl_expr!(RlpTxTypeTag); -const MAX_BYTE_COLUMN: usize = 33; +const MAX_BYTE_COLUMN_NUM: usize = 33; + +/// Witness for RlpDecoderCircuit +#[derive(Clone, Debug, Default)] +pub struct RlpDecoderCircuitConfigWitness { + /// tx_id column + pub tx_id: u64, + /// tx_type column + pub tx_type: RlpTxTypeTag, + /// tag column + pub tag: RlpTxFieldTag, + /// complete column + pub complete: bool, + /// rlp types: [single, short, long, very_long, fixed(33)] + pub rlp_types: [bool; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], + /// rlp_tag_length, the length of this rlp field + pub rlp_tag_length: u64, + /// remained rows, for n < 33 fields, it is n, for m > 33 fields, it is 33 and next row is + /// partial, next_length = m - 33 + pub tag_bytes_in_row: u8, + /// r_mult column, (length, r_mult) => @fixed + pub r_mult: F, + /// remain_length + pub rlp_remain_length: usize, + /// value + pub value: F, + /// acc_rlc_value + pub acc_rlc_value: F, + /// bytes + pub bytes: Vec, //[u8; MAX_BYTE_COLUMN], + /// decodable, 0 for decode failed, 1 for success + pub decodable: bool, + /// valid, 0 for invalid, 1 for valid, should be == decodable at the end of the circuit + pub valid: bool, + /// dynamic selector for fields + pub q_fields: [bool; LEGACY_TX_FIELD_NUM as usize], + /// full chip enable + pub q_enable: bool, + /// the begining + pub q_first: bool, + /// the end + pub q_last: bool, +} /// Config for RlpDecoderCircuit #[derive(Clone, Debug)] @@ -168,13 +252,13 @@ pub struct RlpDecoderCircuitConfig { /// acc_rlc_value pub acc_rlc_value: Column, /// bytes - pub bytes: [Column; MAX_BYTE_COLUMN], + pub bytes: [Column; MAX_BYTE_COLUMN_NUM], /// decodable, 0 for decode failed, 1 for success pub decodable: Column, /// valid, 0 for invalid, 1 for valid, should be == decodable at the end of the circuit pub valid: Column, /// dynamic selector for fields - pub q_fields: [Column; LegacyTxFieldNum as usize], + pub q_fields: [Column; LEGACY_TX_FIELD_NUM as usize], /// full chip enable pub q_enable: Selector, /// the begining @@ -205,23 +289,55 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tx_type = meta.advice_column(); let tag = meta.advice_column(); let complete = meta.advice_column(); - let rlp_types = [meta.advice_column(); RlpDecodeTypeTag::RlpDecodeTypeNum as usize]; + let rlp_types: [Column; RlpDecodeTypeTag::RlpDecodeTypeNum as usize] = (0 + ..RlpDecodeTypeTag::RlpDecodeTypeNum as usize) + .map(|_| meta.advice_column()) + .collect::>>() + .try_into() + .unwrap(); let rlp_tag_length = meta.advice_column(); let tag_bytes_in_row = meta.advice_column(); let rlp_remain_length = meta.advice_column(); let r_mult = meta.advice_column(); let value = meta.advice_column(); - let acc_rlc_value = meta.advice_column(); - let bytes = [meta.advice_column(); 33]; + let acc_rlc_value = meta.advice_column_in(SecondPhase); + let bytes: [Column; MAX_BYTE_COLUMN_NUM] = (0..MAX_BYTE_COLUMN_NUM as usize) + .map(|_| meta.advice_column()) + .collect::>>() + .try_into() + .unwrap(); let decodable = meta.advice_column(); let valid = meta.advice_column(); - let q_fields = [meta.advice_column(); LegacyTxFieldNum]; + let q_fields: [Column; LEGACY_TX_FIELD_NUM as usize] = (0..LEGACY_TX_FIELD_NUM) + .map(|_| meta.advice_column()) + .collect::>>() + .try_into() + .unwrap(); let q_enable = meta.selector(); let q_first = meta.fixed_column(); let q_last = meta.fixed_column(); - // common logic - meta.create_gate("common", |meta| { + // TODO: lookup rlp_types table, which may also include bytes[1] as prefix of len + // also need to be constrainted + // TODO: lookup r_mult table with length, also as r_mult is adv, add constraint for pow + // TODO: lookup bytes range table + // TODO: lookup q_fields table + + meta.create_gate("common constraints for all rows", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let valid_cur = meta.query_advice(valid, Rotation::cur()); + let valid_next = meta.query_advice(valid, Rotation::next()); + cb.require_equal("valid should be consistent", valid_cur, valid_next); + + cb.gate(and::expr([ + meta.query_selector(q_enable), + not::expr(meta.query_fixed(q_last, Rotation::cur())), + ])) + }); + + // common logic for tx fields + meta.create_gate("tx fields common constraints", |meta| { let mut cb = BaseConstraintBuilder::default(); let tx_id = meta.query_advice(tx_id, Rotation::cur()); @@ -241,7 +357,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); let value = meta.query_advice(value, Rotation::cur()); let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); - let bytes = bytes + let byte_cells_cur = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); @@ -252,6 +368,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) .collect::>(); let q_enable = meta.query_selector(q_enable); + let q_first = meta.query_fixed(q_first, Rotation::cur()); // cb.require_boolean("q_enable boolean", q_enable); cb.require_boolean("field complete boolean", complete_cur.expr()); @@ -265,38 +382,76 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_boolean("rlp_type boolean", rlp_type_cur.expr()); }); - // length without leading bytes + // length with leading bytes cb.condition(rlp_types_cur[RlpDecodeTypeTag::SingleByte].expr(), |cb| { cb.require_equal("single length", rlp_tag_length_cur.clone(), 1.expr()) }); cb.condition(rlp_types_cur[RlpDecodeTypeTag::NullValue].expr(), |cb| { - cb.require_equal("empty length", rlp_tag_length_cur.clone(), 0.expr()) + cb.require_equal("empty length", rlp_tag_length_cur.clone(), 1.expr()) }); cb.condition(rlp_types_cur[RlpDecodeTypeTag::ShortString].expr(), |cb| { cb.require_equal( - "single string length", + "ShortString length", rlp_tag_length_cur.clone(), - bytes[0].expr() - 0x80.expr(), + byte_cells_cur[0].expr() - 0x80.expr() + 1.expr(), + ) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongString1].expr(), |cb| { + cb.require_equal( + "Long String 0xb8 length", + rlp_tag_length_cur.clone(), + byte_cells_cur[1].expr() + 2.expr(), + ) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongString2].expr(), |cb| { + cb.require_equal( + "Long String 0xb9 length", + rlp_tag_length_cur.clone(), + byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr() + 3.expr(), + ) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongString3].expr(), |cb| { + cb.require_equal( + "Long String 0xba length", + rlp_tag_length_cur.clone(), + byte_cells_cur[1].expr() * 65536.expr() + + byte_cells_cur[2].expr() * 256.expr() + + byte_cells_cur[3].expr() + + 4.expr(), ) }); cb.condition(rlp_types_cur[RlpDecodeTypeTag::EmptyList].expr(), |cb| { - cb.require_equal("empty list length", rlp_tag_length_cur.clone(), 0.expr()) + cb.require_equal("empty list length", rlp_tag_length_cur.clone(), 1.expr()) }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList1].expr(), |cb| { + cb.condition(rlp_types_cur[RlpDecodeTypeTag::ShortList].expr(), |cb| { cb.require_equal( "short length", rlp_tag_length_cur.clone(), - bytes[0].expr() - 0xc0.expr(), + byte_cells_cur[0].expr() - 0xc0.expr() + 1.expr(), + ) + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList1].expr(), |cb| { + cb.require_equal( + "long length: f8 + 1", + rlp_tag_length_cur.clone(), + byte_cells_cur[1].expr() + 2.expr(), ) }); cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList2].expr(), |cb| { - cb.require_equal("long length", rlp_tag_length_cur.clone(), bytes[1].expr()) + cb.require_equal( + "long length: f9 + 2", + rlp_tag_length_cur.clone(), + byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr() + 3.expr(), + ) }); cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList3].expr(), |cb| { cb.require_equal( - "long length", + "long length: fa + 3", rlp_tag_length_cur.clone(), - bytes[1].expr() * 256.expr() + bytes[2].expr(), + byte_cells_cur[1].expr() * 65536.expr() + + byte_cells_cur[2].expr() * 256.expr() + + byte_cells_cur[3].expr() + + 4.expr(), ) }); cb.condition(rlp_types_cur[RlpDecodeTypeTag::PartialRlp].expr(), |cb| { @@ -304,7 +459,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { "length = prev_length - prev_bytes_in_row", rlp_tag_length_cur.clone(), meta.query_advice(rlp_tag_length, Rotation::prev()) - - tag_bytes_in_row_cur.expr(), + - meta.query_advice(tag_bytes_in_row, Rotation::prev()), ); cb.require_zero( @@ -315,9 +470,9 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.condition(complete_cur.expr(), |cb| { cb.require_equal( - "complete = 1 => remain_length = bytes_in_row", + "complete = 1 => rlp_tag_length = bytes_in_row", tag_bytes_in_row_cur.expr(), - remain_length.expr(), + rlp_tag_length_cur.expr(), ); cb.require_equal( @@ -328,20 +483,26 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ); }); + cb.condition(not::expr(complete_cur.expr()), |cb| { + cb.require_equal( + "!complete => MAX_BYTES_COL == bytes_in_row", + tag_bytes_in_row_cur.expr(), + MAX_BYTE_COLUMN_NUM.expr(), + ); + }); + cb.require_equal( "rlc = r_mult_cur * rlc_next + rlc(bytes_cur)", acc_rlc_cur, r_mult * meta.query_advice(acc_rlc_value, Rotation::next()) - + rlc::expr( - bytes.iter().rev().collect::>().as_ref(), - &args.challenges.keccak_input(), - ), + + rlc::expr(&byte_cells_cur, args.challenges.keccak_input()), ); - // TODO: lookup rlp_types table - // TODO: lookup r_mult table - // TODO: lookup bytes range table - cb.gate(q_enable) + cb.gate(and::expr([ + q_enable, + not::expr(q_first), + not::expr(q_fields[RlpTxFieldTag::TxRlpHeader].expr()), + ])) }); // TxListHeader in the first row @@ -353,12 +514,20 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tag_cur = meta.query_advice(tag, Rotation::cur()); let tag_next = meta.query_advice(tag, Rotation::next()); let complete = meta.query_advice(complete, Rotation::cur()); - let length = meta.query_advice(rlp_tag_length, Rotation::cur()); + let rlp_types_cur: [Expression; RlpDecodeTypeTag::RlpDecodeTypeNum as usize] = + rlp_types + .iter() + .map(|rlp_type| meta.query_advice(*rlp_type, Rotation::cur())) + .collect::>() + .try_into() + .unwrap(); + + let rlp_tag_length_cur = meta.query_advice(rlp_tag_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); let value = meta.query_advice(value, Rotation::cur()); - let acc_rlc_value = meta.query_advice(acc_rlc_value, Rotation::cur()); - let bytes = bytes + let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); + let byte_cells_cur = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); @@ -379,7 +548,14 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { tx_type_next, RlpTxTypeTag::TxLegacyType.expr(), ); - cb.require_equal("next field is nonce", tag_next, RlpTxFieldTag::Nonce.expr()); + cb.require_in_set( + "next field is txRlpHeader or Padding", + tag_next, + vec![ + RlpTxFieldTag::TxRlpHeader.expr(), + RlpTxFieldTag::Padding.expr(), + ], + ); }); // TODO: enable 1559 @@ -397,16 +573,131 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { // ); // }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList1].expr(), |cb| { + cb.require_equal( + "long length: f8 + 1", + remain_length.expr(), + byte_cells_cur[1].expr(), + ) + // TODO: byte_cells_cur[1] in (0, 55] + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList2].expr(), |cb| { + cb.require_equal( + "long length: f9 + 2", + remain_length.expr(), + byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr(), + ) + + // TODO: byte_cells_cur[1] != 0 + }); + cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList3].expr(), |cb| { + cb.require_equal( + "long length: fa + 3", + remain_length.expr(), + byte_cells_cur[1].expr() * 65536.expr() + + byte_cells_cur[2].expr() * 256.expr() + + byte_cells_cur[3].expr(), + ) + // TODO: byte_cells_cur[1] != 0 + }); + + cb.condition(decodable, |cb| { + // TODO: use look up?? + cb.require_in_set( + "txlist header in [0xf8,0xf9,0xfa]", + byte_cells_cur[0].expr(), + vec![192.expr(), 248.expr(), 249.expr(), 250.expr()], + ); + + cb.require_equal( + "rlp_tag_length = rlp_header length", + rlp_tag_length_cur.expr(), + byte_cells_cur[0].expr() - 247.expr() + 1.expr(), + ); + }); + + cb.require_equal( + "rlc = r_mult_cur * rlc_next + rlc(bytes_cur)", + acc_rlc_cur, + r_mult * meta.query_advice(acc_rlc_value, Rotation::next()) + + rlc::expr(&byte_cells_cur, args.challenges.keccak_input()), + ); + + cb.gate(q_first) + }); + + meta.create_gate("txHeader", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tx_id_cur = meta.query_advice(tx_id, Rotation::cur()); + let tx_id_prev = meta.query_advice(tx_id, Rotation::prev()); + let tx_type_cur = meta.query_advice(tx_type, Rotation::cur()); + let tag_cur = meta.query_advice(tag, Rotation::cur()); + let tag_next = meta.query_advice(tag, Rotation::next()); + let complete = meta.query_advice(complete, Rotation::cur()); + let rlp_tag_length_cur = meta.query_advice(rlp_tag_length, Rotation::cur()); + let r_mult = meta.query_advice(r_mult, Rotation::cur()); + let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); + let value = meta.query_advice(value, Rotation::cur()); + let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); + let byte_cells_cur = bytes + .iter() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let valid = meta.query_advice(valid, Rotation::cur()); + let q_fields = q_fields + .iter() + .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) + .collect::>(); + + cb.require_equal( + "tx_id == tx_id_prev + 1", + tx_id_cur.expr(), + tx_id_prev.expr() + 1.expr(), + ); + cb.require_zero("legacy tx_type", tx_type_cur.expr()); + cb.require_equal( + "tag is tx header", + tag_cur, + RlpTxFieldTag::TxRlpHeader.expr(), + ); + cb.require_equal("field completed", complete.expr(), 1.expr()); + + // next should be nonce if legacy(0) or chain_id if 1559 + cb.condition(not::expr(tx_type_cur.expr()), |cb| { + let tx_type_next = meta.query_advice(tx_type, Rotation::next()); + cb.require_equal( + "next tx is legacy", + tx_type_next, + RlpTxTypeTag::TxLegacyType.expr(), + ); + cb.require_equal("next field is nonce", tag_next, RlpTxFieldTag::Nonce.expr()); + }); + cb.condition(decodable, |cb| { // TODO: use look up?? cb.require_in_set( "list header in [0xf8,0xf9,0xfa]", - bytes[0].expr(), + byte_cells_cur[0].expr(), vec![248.expr(), 249.expr(), 250.expr()], - ) + ); + + cb.require_equal( + "rlp_tag_length = rlp_header length", + rlp_tag_length_cur.expr(), + byte_cells_cur[0].expr() - 247.expr() + 1.expr(), + ); }); - cb.gate(q_first) + cb.require_equal( + "rlc = r_mult_cur * rlc_next + rlc(bytes_cur)", + acc_rlc_cur, + r_mult * meta.query_advice(acc_rlc_value, Rotation::next()) + + rlc::expr(&byte_cells_cur, args.challenges.keccak_input()), + ); + + cb.gate(q_fields[RlpTxFieldTag::TxRlpHeader].expr() * meta.query_selector(q_enable)) }); // Nonce @@ -438,13 +729,9 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { RlpTxFieldTag::GasPrice.expr(), ); - cb.require_equal( - "decodable if not null", - decodable, - not::expr(rlp_types[RlpDecodeTypeTag::NullValue].expr()), - ); + // TODO: decodable == 0 < bytes[0] <= 0x88, using lookup?? + // i.e., lookup nonce rlp_type table, should be single or short - // TODO: lookup nonce rlp_type table, should be single or short cb.gate(q_fields[RlpTxFieldTag::Nonce].expr() * meta.query_selector(q_enable)) }); @@ -548,11 +835,13 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ); // TODO: Lookup fix length 0xa0/0x80 - cb.require_in_set( - "0xa0 or 0x80", - bytes[0].expr(), - vec![160.expr(), 128.expr()], - ); + cb.condition(decodable.expr(), |cb| { + cb.require_in_set( + "0x94 or 0x80", + bytes[0].expr(), + vec![148.expr(), 128.expr()], + ); + }); cb.gate(q_fields[RlpTxFieldTag::To].expr() * meta.query_selector(q_enable)) }); @@ -601,12 +890,13 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .collect::>(); cb.require_equal("tag", tag_cur, RlpTxFieldTag::Data.expr()); - cb.require_equal("field completed", complete.expr(), 1.expr()); - cb.require_equal( - "next field is SignV", - meta.query_advice(tag, Rotation::next()), - RlpTxFieldTag::SignV.expr(), - ); + cb.condition(complete, |cb| { + cb.require_equal( + "next field is SignV", + meta.query_advice(tag, Rotation::next()), + RlpTxFieldTag::SignV.expr(), + ); + }); cb.gate(q_fields[RlpTxFieldTag::Data].expr() * meta.query_selector(q_enable)) }); @@ -657,11 +947,13 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_equal("tag", tag_cur, RlpTxFieldTag::SignR.expr()); cb.require_equal("field completed", complete.expr(), 1.expr()); - cb.require_equal( - "decodable if valid rlp header", - not::expr(decodable), - bytes[0].expr() - 0xa0.expr(), - ); + cb.condition(decodable.expr(), |cb| { + cb.require_equal( + "decodable if valid rlp header", + bytes[0].expr(), + 0xa0.expr(), + ) + }); // next is signS cb.require_equal( @@ -695,7 +987,10 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_in_set( "next field is Nonce or Padding", meta.query_advice(tag, Rotation::next()), - vec![RlpTxFieldTag::Nonce.expr(), RlpTxFieldTag::Padding.expr()], + vec![ + RlpTxFieldTag::TxRlpHeader.expr(), + RlpTxFieldTag::Padding.expr(), + ], ); cb.gate(q_fields[RlpTxFieldTag::SignS].expr() * meta.query_selector(q_enable)) @@ -726,14 +1021,18 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_equal("tag", tag_cur, RlpTxFieldTag::Padding.expr()); cb.require_equal("field completed", complete.expr(), 1.expr()); // next is a new tx or padding - cb.require_in_set( - "next field is Padding or next tx nonce", + cb.require_equal( + "next field is Padding", meta.query_advice(tag, Rotation::next()), - vec![RlpTxFieldTag::Nonce.expr(), RlpTxFieldTag::Padding.expr()], + RlpTxFieldTag::Padding.expr(), + ); + cb.require_zero("padding has no r_mult", r_mult); + cb.require_zero("padding has no length", length); + cb.require_zero("padding has no remain length", remain_length); + cb.require_zero( + "last row above padding has no remain length", + meta.query_advice(rlp_remain_length, Rotation::prev()), ); - cb.require_equal("padding has no r_mult", r_mult, 0.expr()); - cb.require_equal("padding has no length", length, 0.expr()); - cb.require_equal("padding has no remain length", remain_length, 0.expr()); cb.require_equal("padding has no rlc (all 0)", acc_rlc_value, 0.expr()); cb.gate( @@ -797,13 +1096,166 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { } impl RlpDecoderCircuitConfig { + fn assign_rows( + &self, + region: &mut Region<'_, F>, + offset: usize, + wits: &[RlpDecoderCircuitConfigWitness], + ) -> Result<(), Error> { + let mut offset = offset; + self.name_row_members(region); + for wit in wits { + self.assign_row(region, offset, wit)?; + offset += 1; + } + Ok(()) + } + + fn name_row_members(&self, region: &mut Region<'_, F>) { + region.name_column(|| "config.tx_id", self.tx_id); + region.name_column(|| "config.tx_type", self.tx_type); + region.name_column(|| "config.tag", self.tag); + region.name_column(|| "config.complete", self.complete); + for (i, rlp_type) in self.rlp_types.iter().enumerate() { + region.name_column(|| format!("config.rlp_types[{}]", i), *rlp_type); + } + region.name_column(|| "config.rlp_tag_length", self.rlp_tag_length); + region.name_column(|| "config.rlp_remain_length", self.rlp_remain_length); + region.name_column(|| "config.r_mult", self.r_mult); + region.name_column(|| "config.value", self.value); + region.name_column(|| "config.acc_rlc_value", self.acc_rlc_value); + for (i, byte) in self.bytes.iter().enumerate() { + region.name_column(|| format!("config.bytes-[{}]", i), *byte); + } + region.name_column(|| "config.decodable", self.decodable); + region.name_column(|| "config.valid", self.valid); + } + fn assign_row( &self, region: &mut Region<'_, F>, offset: usize, - value: u8, - ) -> Result, Error> { - todo!() + w: &RlpDecoderCircuitConfigWitness, + ) -> Result<(), Error> { + region.assign_advice( + || "config.tx_id", + self.tx_id, + offset, + || Value::known(F::from(w.tx_id)), + )?; + region.assign_advice( + || "config.tx_type", + self.tx_type, + offset, + || Value::known(F::from(w.tx_type as u64)), + )?; + region.assign_advice( + || "config.tag", + self.tag, + offset, + || Value::known(F::from(w.tag as u64)), + )?; + region.assign_advice( + || "config.complete", + self.complete, + offset, + || Value::known(F::from(w.complete)), + )?; + for (i, rlp_type) in self.rlp_types.iter().enumerate() { + region.assign_advice( + || format!("config.rlp_types[{}]", i), + *rlp_type, + offset, + || Value::known(F::from(w.rlp_types[i])), + )?; + } + region.assign_advice( + || "config.rlp_tag_length", + self.rlp_tag_length, + offset, + || Value::known(F::from(w.rlp_tag_length)), + )?; + region.assign_advice( + || "config.tag_bytes_in_row", + self.tag_bytes_in_row, + offset, + || Value::known(F::from(w.tag_bytes_in_row as u64)), + )?; + region.assign_advice( + || "config.r_mult", + self.r_mult, + offset, + || Value::known(F::from(w.r_mult)), + )?; + region.assign_advice( + || "config.rlp_remain_length", + self.rlp_remain_length, + offset, + || Value::known(F::from(w.rlp_remain_length as u64)), + )?; + region.assign_advice( + || "config.value", + self.value, + offset, + || Value::known(F::from(w.value)), + )?; + region.assign_advice( + || "config.acc_rlc_value", + self.acc_rlc_value, + offset, + || Value::known(F::from(w.acc_rlc_value)), + )?; + for (i, byte) in self.bytes.iter().enumerate() { + region.assign_advice( + || format!("config.bytes[{}]", i), + *byte, + offset, + || { + if i < w.bytes.len() { + Value::known(F::from(w.bytes[i] as u64)) + } else { + Value::known(F::zero()) + } + }, + )?; + } + region.assign_advice( + || "config.decodable", + self.decodable, + offset, + || Value::known(F::from(w.decodable)), + )?; + region.assign_advice( + || "config.valid", + self.valid, + offset, + || Value::known(F::from(w.valid)), + )?; + for (i, q_field) in self.q_fields.iter().enumerate() { + region.assign_advice( + || format!("config.q_fields[{}]", i), + *q_field, + offset, + || Value::known(F::from(w.q_fields[i])), + )?; + } + region.assign_fixed( + || "config.q_first", + self.q_first, + offset, + || Value::known(F::from(w.q_first)), + )?; + region.assign_fixed( + || "config.q_last", + self.q_last, + offset, + || Value::known(F::from(w.q_last)), + )?; + if w.q_enable { + self.q_enable.enable(region, offset)?; + } + + Ok(()) } /// Get number of rows required. @@ -815,31 +1267,51 @@ impl RlpDecoderCircuitConfig { /// rlp decode Circuit for verifying transaction signatures #[derive(Clone, Default, Debug)] pub struct RlpDecoderCircuit { - /// Max number of supported transactions - pub max_txs: usize, - /// Max number of supported calldata bytes - pub max_calldata: usize, /// input bytes pub bytes: Vec, + /// Size of the circuit + pub size: usize, /// phantom - pub _marker: std::marker::PhantomData, + pub _marker: PhantomData, } impl RlpDecoderCircuit { /// Return a new RlpDecoderCircuit - pub fn new(max_txs: usize, max_calldata: usize, bytes: Vec) -> Self { + pub fn new(bytes: Vec, degree: usize) -> Self { RlpDecoderCircuit:: { - max_txs, - max_calldata, bytes, - _marker: std::marker::PhantomData, + size: 1 << degree, + _marker: PhantomData, } } /// Return the minimum number of rows required to prove an input of a /// particular size. - pub fn min_num_rows(txs_len: usize, call_data_len: usize) -> usize { - 0 + pub fn min_num_rows(block: &witness::Block) -> (usize, usize) { + let txs_len = block.txs.len(); + let call_data_rows = block.txs.iter().fold(0, |acc, tx| { + acc + tx.call_data.len() / MAX_BYTE_COLUMN_NUM + 1 + }); + + let min_num_rows = Self::calc_min_num_rows(txs_len, call_data_rows); + (min_num_rows, min_num_rows) + } + + /// Return the minimum number of rows required to prove an input of a + /// particular size. + pub fn min_num_rows_from_tx(txs: &Vec) -> (usize, usize) { + let txs_len = txs.len(); + let call_data_rows = txs + .iter() + .fold(0, |acc, tx| acc + tx.input.len() / MAX_BYTE_COLUMN_NUM + 1); + + let min_num_rows = Self::calc_min_num_rows(txs_len, call_data_rows); + (min_num_rows, min_num_rows) + } + + fn calc_min_num_rows(txs_len: usize, call_data_rows: usize) -> usize { + // add 2 for prev and next rotations. + txs_len * LEGACY_TX_FIELD_NUM + call_data_rows + NUM_BLINDING_ROWS + 2 } } @@ -847,25 +1319,24 @@ impl SubCircuit for RlpDecoderCircuit { type Config = RlpDecoderCircuitConfig; fn new_from_block(block: &witness::Block) -> Self { - Self::new( - block.circuits_params.max_txs, - block.circuits_params.max_calldata, - Vec::::new(), - ) + let txs: Vec = block + .eth_block + .transactions + .iter() + .map(|tx| tx.into()) + .collect::>(); + let bytes = rlp::encode_list(&txs).to_vec(); + let degree = log2_ceil(Self::min_num_rows(block).0); + RlpDecoderCircuit:: { + bytes, + size: 1 << degree, + _marker: PhantomData, + } } /// Return the minimum number of rows required to prove the block fn min_num_rows_block(block: &witness::Block) -> (usize, usize) { - ( - Self::min_num_rows( - block.txs.len(), - block.txs.iter().map(|tx| tx.call_data.len()).sum(), - ), - Self::min_num_rows( - block.circuits_params.max_txs, - block.circuits_params.max_calldata, - ), - ) + RlpDecoderCircuit::::min_num_rows(block) } /// Make the assignments to the RlpDecodeCircuit @@ -875,12 +1346,27 @@ impl SubCircuit for RlpDecoderCircuit { challenges: &Challenges>, layouter: &mut impl Layouter, ) -> Result<(), Error> { - Ok(()) + let mut randomness = F::zero(); + challenges.keccak_input().map(|r| randomness = r); + let witness: Vec> = + rlp_decode_tx_list_manually(&self.bytes, randomness, self.size as u32); + + // for iw in witness.iter().take(100).enumerate() { + // println!("witness[{}] {:?}", iw.0, iw.1); + // } + + layouter.assign_region( + || "rlp witness region", + |mut region| { + let offset = 0; + config.assign_rows(&mut region, offset, &witness)?; + Ok(()) + }, + ) } fn instance(&self) -> Vec> { - // The maingate expects an instance column, but we don't use it, so we return an - // "empty" instance column + // empty instance now vec![vec![]] } } @@ -900,13 +1386,15 @@ impl Circuit for RlpDecoderCircuit { let challenges = Challenges::construct(meta); let config = { - let challenges = challenges.exprs(meta); + // let challenges_expr = challenges.exprs(meta); + let r = 11u64; + let challenges_expr = Challenges::mock(r.expr(), r.expr(), r.expr()); RlpDecoderCircuitConfig::new( meta, RlpDecoderCircuitConfigArgs { tx_table, keccak_table, - challenges, + challenges: challenges_expr, }, ) }; @@ -916,54 +1404,461 @@ impl Circuit for RlpDecoderCircuit { fn synthesize( &self, - (config, challenges): Self::Config, + (config, _challenges): Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - Ok(()) + // let challenges = challenges.values(&mut layouter); + let r = F::from(11u64); + let challenges = Challenges::mock(Value::known(r), Value::known(r), Value::known(r)); + + self.synthesize_sub(&config, &challenges, &mut layouter) + } +} + +fn generate_rlp_type_witness( + header_byte: u8, +) -> ([bool; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], bool) { + let mut rlp_types = [false; RlpDecodeTypeTag::RlpDecodeTypeNum as usize]; + let mut decodable = true; + match header_byte { + 0x00..=0x7f => { + rlp_types[RlpDecodeTypeTag::SingleByte as usize] = true; + } + 0x80 => { + rlp_types[RlpDecodeTypeTag::NullValue as usize] = true; + } + 0x81..=0xb7 => { + rlp_types[RlpDecodeTypeTag::ShortString as usize] = true; + } + 0xb8 => { + rlp_types[RlpDecodeTypeTag::LongString1 as usize] = true; + } + 0xb9 => { + rlp_types[RlpDecodeTypeTag::LongString2 as usize] = true; + } + 0xba => { + rlp_types[RlpDecodeTypeTag::LongString3 as usize] = true; + } + 0xc0 => { + rlp_types[RlpDecodeTypeTag::EmptyList as usize] = true; + } + 0xc1..=0xf7 => { + rlp_types[RlpDecodeTypeTag::ShortList as usize] = true; + } + 0xf8 => { + rlp_types[RlpDecodeTypeTag::LongList1 as usize] = true; + } + 0xf9 => { + rlp_types[RlpDecodeTypeTag::LongList2 as usize] = true; + } + 0xfa => { + rlp_types[RlpDecodeTypeTag::LongList3 as usize] = true; + } + _ => { + decodable = false; + } } + (rlp_types, decodable) } -trait RlpWitness { - fn generate_rlp_decoded_witness(&self) -> Vec; +fn generate_q_fields_witness(tag: &RlpTxFieldTag) -> [bool; LEGACY_TX_FIELD_NUM as usize] { + let mut q_fields = [false; LEGACY_TX_FIELD_NUM as usize]; + q_fields[*tag as usize] = true; + if tag > &RlpTxFieldTag::Padding { + unreachable!("1559 not support now") + } + q_fields } -impl RlpWitness for Transaction { - fn generate_rlp_decoded_witness(&self) -> Vec { - // TODO: use offset to split the input bytes - let mut bytes = Vec::new(); - bytes.extend_from_slice(rlp::encode(&self.nonce).as_ref()); - bytes.extend_from_slice(rlp::encode(&self.gas_price).as_ref()); - bytes.extend_from_slice(rlp::encode(&self.gas).as_ref()); - bytes.extend_from_slice(rlp::encode(&self.to).as_ref()); - bytes.extend_from_slice(rlp::encode(&self.value).as_ref()); - bytes.extend_from_slice(rlp::encode(&self.input.as_ref()).as_ref()); - bytes.extend_from_slice(rlp::encode(&self.v).as_ref()); - bytes.extend_from_slice(rlp::encode(&self.r).as_ref()); - bytes.extend_from_slice(rlp::encode(&self.s).as_ref()); - bytes +fn generate_fields_witness_len(tag: &RlpTxFieldTag, payload: &PayloadInfo) -> usize { + match tag { + RlpTxFieldTag::TxListRlpHeader => payload.header_len, + RlpTxFieldTag::TxRlpHeader => payload.header_len, + _ => payload.total(), } } -fn rlp_decode(bytes: Vec) -> Result, Error> { - match rlp::Rlp::new(&bytes).as_list::() { - Ok(txlist) => { - // TODO: check txs.len() <= max_txs - let mut bytes = Vec::new(); - for tx in txlist { - let witness = tx.generate_rlp_decoded_witness(); - bytes.extend_from_slice(&witness) +fn generate_rlp_row_witness( + tx_id: u64, + tag: &RlpTxFieldTag, + raw_bytes: &[u8], + r: F, + rlp_remain_length: usize, +) -> Vec> { + let mut witness = vec![]; + let (mut rlp_types, decodable) = generate_rlp_type_witness(raw_bytes[0]); + let partial_rlp_types = { + let mut tmp = [false; RlpDecodeTypeTag::RlpDecodeTypeNum as usize]; + tmp[RlpDecodeTypeTag::PartialRlp as usize] = true; + tmp + }; + let q_fields = generate_q_fields_witness(tag); + let rlp_tag_len = raw_bytes.len(); + let mut prev_rlp_remain_length = rlp_remain_length; + + macro_rules! generate_witness { + () => {{ + let mut temp_witness_vec = Vec::new(); + let mut tag_remain_length = rlp_tag_len; + let mut raw_bytes_offset = 0; + while tag_remain_length > MAX_BYTE_COLUMN_NUM { + temp_witness_vec.push(RlpDecoderCircuitConfigWitness:: { + tx_id: tx_id, + tx_type: RlpTxTypeTag::TxLegacyType, + tag: tag.clone(), + complete: false, + rlp_types: rlp_types, + rlp_tag_length: tag_remain_length as u64, + tag_bytes_in_row: MAX_BYTE_COLUMN_NUM as u8, + r_mult: r.pow(&[MAX_BYTE_COLUMN_NUM as u64, 0, 0, 0]), + rlp_remain_length: prev_rlp_remain_length - MAX_BYTE_COLUMN_NUM, + value: F::zero(), + acc_rlc_value: F::zero(), + bytes: raw_bytes[..MAX_BYTE_COLUMN_NUM].to_vec(), + decodable: decodable, + valid: true, + q_fields: q_fields, + q_enable: true, + q_first: false, + q_last: false, + }); + raw_bytes_offset += MAX_BYTE_COLUMN_NUM; + tag_remain_length -= MAX_BYTE_COLUMN_NUM; + prev_rlp_remain_length -= MAX_BYTE_COLUMN_NUM; + rlp_types = partial_rlp_types; } - Ok(bytes) + temp_witness_vec.push(RlpDecoderCircuitConfigWitness:: { + tx_id: tx_id, + tx_type: RlpTxTypeTag::TxLegacyType, + tag: tag.clone(), + complete: true, + rlp_types: rlp_types, + rlp_tag_length: tag_remain_length as u64, + tag_bytes_in_row: tag_remain_length as u8, + r_mult: r.pow(&[tag_remain_length as u64, 0, 0, 0]), + rlp_remain_length: prev_rlp_remain_length - tag_remain_length, + value: F::zero(), + acc_rlc_value: F::zero(), + bytes: raw_bytes[raw_bytes_offset..].to_vec(), + decodable: decodable, + valid: true, + q_fields: q_fields, + q_enable: true, + q_first: false, + q_last: false, + }); + temp_witness_vec + }}; + } + + // TODO: reorganize the match + match tag { + RlpTxFieldTag::TxListRlpHeader => witness.append(&mut generate_witness!()), + RlpTxFieldTag::TxRlpHeader => witness.append(&mut generate_witness!()), + RlpTxFieldTag::Nonce => witness.append(&mut generate_witness!()), + RlpTxFieldTag::GasPrice => witness.append(&mut generate_witness!()), + RlpTxFieldTag::Gas => witness.append(&mut generate_witness!()), + RlpTxFieldTag::To => witness.append(&mut generate_witness!()), + RlpTxFieldTag::Value => witness.append(&mut generate_witness!()), + RlpTxFieldTag::Data => witness.append(&mut generate_witness!()), + RlpTxFieldTag::SignV => witness.append(&mut generate_witness!()), + RlpTxFieldTag::SignR => witness.append(&mut generate_witness!()), + RlpTxFieldTag::SignS => witness.append(&mut generate_witness!()), + RlpTxFieldTag::Padding => { + unreachable!("Padding should not be here") + } + _ => { + unreachable!("1559 not support now") + } + } + witness +} + +fn generate_rlp_txfield_witness( + tx_id: u64, + tag: &RlpTxFieldTag, + bytes: &[u8], + r: F, + witness: &mut Vec>, +) -> Option { + let offset = 0; + let decode_result = PayloadInfo::from(&bytes[offset..]); + + match decode_result { + Ok(payload_info) => { + let bytes_num = generate_fields_witness_len(tag, &payload_info); + let rlp_remain_length = witness + .last() + .map_or(payload_info.total(), |w| w.rlp_remain_length); + + witness.append(&mut generate_rlp_row_witness( + tx_id, + tag, + &bytes[offset..offset + bytes_num], + r, + rlp_remain_length, + )); + Some(payload_info) + } + // TODO: error case + Err(decoder_err) => match decoder_err { + rlp::DecoderError::RlpIsTooShort => todo!(), + rlp::DecoderError::RlpDataLenWithZeroPrefix => todo!(), + rlp::DecoderError::RlpInvalidIndirection => todo!(), + _ => unimplemented!("Unsupport payload decode error: {:?}", decoder_err), + }, + } +} + +// trait RlpTxFieldWittnessGenerator { +// fn generate_rlp_txfield_witness( +// &self, +// tx_id: u64, +// bytes: &[u8], +// r: F, +// witness: &mut Vec>, +// ) -> Option; +// } + +// impl RlpTxFieldWittnessGenerator for RlpTxFieldTag { +// fn generate_rlp_txfield_witness( +// &self, +// tx_id: u64, +// bytes: &[u8], +// r: F, +// witness: &mut Vec>, +// ) -> Option { +// let offset = 0; +// let decode_result = PayloadInfo::from(&bytes[offset..]); +// match self { +// RlpTxFieldTag::TxListRlpHeader => todo!(), +// RlpTxFieldTag::TxRlpHeader => todo!(), +// RlpTxFieldTag::Nonce => todo!(), +// RlpTxFieldTag::GasPrice => todo!(), +// RlpTxFieldTag::Gas => todo!(), +// RlpTxFieldTag::To => todo!(), +// RlpTxFieldTag::Value => todo!(), +// RlpTxFieldTag::Data => todo!(), +// RlpTxFieldTag::SignV => todo!(), +// RlpTxFieldTag::SignR => todo!(), +// RlpTxFieldTag::SignS => todo!(), +// RlpTxFieldTag::Padding => todo!(), +// RlpTxFieldTag::ChainID => todo!(), +// RlpTxFieldTag::GasTipCap => todo!(), +// RlpTxFieldTag::GasFeeCap => todo!(), +// RlpTxFieldTag::AccessList => todo!(), +// } +// } +// } + +// TODO: use a state machine to decode the tx list as above +fn rlp_decode_tx_list_manually( + bytes: &[u8], + r: F, + k: u32, +) -> Vec> { + let mut witness = vec![]; + let mut tx_id: u64 = 0; + + let mut offset = 0; + let tx_list_header = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::TxListRlpHeader, + &bytes[offset..], + r, + &mut witness, + ); + if tx_list_header.is_none() { + return witness; + } + let tx_list_rlp_header = tx_list_header.unwrap(); + offset += tx_list_rlp_header.header_len; + + let total_list_len = tx_list_rlp_header.total(); + tx_id = 1; // tx_id started from 1 as we have a Anchor tx + while offset < total_list_len { + let tx_rlp_header = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::TxRlpHeader, + &bytes[offset..], + r, + &mut witness, + ); + if tx_rlp_header.is_none() { + return witness; + } + offset += tx_rlp_header.unwrap().header_len; + + let tx_rlp_nonce = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::Nonce, + &bytes[offset..], + r, + &mut witness, + ); + if tx_rlp_nonce.is_none() { + return witness; + } + offset += tx_rlp_nonce.unwrap().total(); + + let tx_rlp_gas_price = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::GasPrice, + &bytes[offset..], + r, + &mut witness, + ); + if tx_rlp_gas_price.is_none() { + return witness; + } + offset += tx_rlp_gas_price.unwrap().total(); + + let tx_rlp_gas = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::Gas, + &bytes[offset..], + r, + &mut witness, + ); + if tx_rlp_gas.is_none() { + return witness; + } + offset += tx_rlp_gas.unwrap().total(); + + let tx_rlp_to_addr = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::To, + &bytes[offset..], + r, + &mut witness, + ); + if tx_rlp_to_addr.is_none() { + return witness; + } + offset += tx_rlp_to_addr.unwrap().total(); + + let tx_rlp_value = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::Value, + &bytes[offset..], + r, + &mut witness, + ); + if tx_rlp_value.is_none() { + return witness; + } + offset += tx_rlp_value.unwrap().total(); + + let tx_rlp_data = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::Data, + &bytes[offset..], + r, + &mut witness, + ); + if tx_rlp_data.is_none() { + return witness; + } + offset += tx_rlp_data.unwrap().total(); + + let tx_rlp_v = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::SignV, + &bytes[offset..], + r, + &mut witness, + ); + if tx_rlp_v.is_none() { + return witness; } - Err(e) => rlp_decode_tx_list_manually(&bytes), + offset += tx_rlp_v.unwrap().total(); + + let tx_rlp_r = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::SignR, + &bytes[offset..], + r, + &mut witness, + ); + if tx_rlp_r.is_none() { + return witness; + } + offset += tx_rlp_r.unwrap().total(); + + let tx_rlp_s = generate_rlp_txfield_witness( + tx_id, + &RlpTxFieldTag::SignS, + &bytes[offset..], + r, + &mut witness, + ); + if tx_rlp_s.is_none() { + return witness; + } + offset += tx_rlp_s.unwrap().total(); + tx_id += 1; } + + assert!(offset == total_list_len); + fixup_acc_rlc(&mut witness, r); + + let witness_len = witness.len(); + assert!(k > (witness_len + 2 + NUM_BLINDING_ROWS) as u32); + complete_paddings( + &mut witness, + k as usize - witness_len - 2 - NUM_BLINDING_ROWS, + ) } -fn rlp_decode_tx_list_manually(bytes: &Vec) -> Result, Error> { - let mut bytes = Vec::new(); - bytes.push(0xc8); // empty [] +fn fixup_acc_rlc(witness: &mut Vec>, randomness: F) { + let mut rev_iter = witness.iter_mut().rev(); + let mut prev: Option<&mut RlpDecoderCircuitConfigWitness> = None; + while let Some(current_witness) = rev_iter.next() { + let prev_acc_rlc_value = + prev.map_or(F::zero(), |w| w.acc_rlc_value * current_witness.r_mult); + current_witness.acc_rlc_value = + prev_acc_rlc_value + rlc::value(¤t_witness.bytes, randomness); - Ok(bytes) + prev = Some(current_witness); + } +} +fn complete_paddings( + witness: &mut Vec>, + num_padding_to_last_row: usize, +) -> Vec> { + let mut complete_witness = vec![]; + let mut pre_padding = RlpDecoderCircuitConfigWitness::::default(); + pre_padding.rlp_remain_length = + witness[0].rlp_remain_length + witness[0].tag_bytes_in_row as usize; + + complete_witness.push(pre_padding); + witness[0].q_first = true; + complete_witness.append(witness); + + for i in 0..num_padding_to_last_row { + complete_witness.push(RlpDecoderCircuitConfigWitness:: { + tx_id: 0, + tx_type: RlpTxTypeTag::TxLegacyType, + tag: RlpTxFieldTag::Padding, + complete: true, + rlp_types: [false; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], + rlp_tag_length: 0, + tag_bytes_in_row: 0, + r_mult: F::zero(), + rlp_remain_length: 0, + value: F::zero(), + acc_rlc_value: F::zero(), + bytes: [0; MAX_BYTE_COLUMN_NUM].to_vec(), + decodable: true, + valid: true, + q_fields: [false; LEGACY_TX_FIELD_NUM as usize], + q_enable: true, + q_first: false, + q_last: i == num_padding_to_last_row - 1, + }); + } + complete_witness.push(RlpDecoderCircuitConfigWitness::::default()); + complete_witness } /// Signed transaction in a witness block @@ -1057,12 +1952,32 @@ impl From for SignedTransaction { #[cfg(test)] mod rlp_test { - use super::SignedTransaction; + use super::{rlp_decode_tx_list_manually, SignedTransaction}; use ethers_core::utils::rlp; + use halo2_proofs::halo2curves::bn256::Fr; use hex; + use mock::AddrOrWallet; use rand::SeedableRng; use rand_chacha::ChaCha20Rng; + fn prepare_legacy_txlist_rlp_bytes(txs_num: usize) -> Vec { + // let tx: SignedTransaction = mock::CORRECT_MOCK_TXS[1].clone().into(); + // let rlp_tx = rlp::encode(&tx); + // println!("{:?}", hex::encode(rlp_tx)); + + let txs: Vec = vec![mock::CORRECT_MOCK_TXS[0].clone().into(); txs_num]; + let rlp_txs = rlp::encode_list(&txs); + println!("rlp_txs = {:?}", hex::encode(rlp_txs.clone())); + + let rlp_bytes = rlp_txs.to_vec(); + println!("rlp_bytes = {:?}", hex::encode(&rlp_bytes)); + rlp_bytes + } + + fn prepare_eip1559_txlist_rlp_bytes() -> Vec { + todo!() + } + #[test] fn test_decode() { let tx: SignedTransaction = mock::CORRECT_MOCK_TXS[1].clone().into(); @@ -1100,34 +2015,93 @@ mod rlp_test { let rlp_tx = rlp::encode(&tx); println!("{:?}", hex::encode(rlp_tx)); } + + #[test] + fn test_correct_witness_generation_empty_list() { + let rlp_bytes = prepare_legacy_txlist_rlp_bytes(0); + let randomness = Fr::from(100); + let k = 128; + + let witness = rlp_decode_tx_list_manually::(&rlp_bytes, randomness, k); + for (i, w) in witness.iter().enumerate() { + print!("witness[{}] = {:?}\n", i, w); + } + } + + #[test] + fn test_correct_witness_generation_1tx() { + let rlp_bytes = prepare_legacy_txlist_rlp_bytes(1); + let randomness = Fr::from(100); + let k = 128; + + let witness = rlp_decode_tx_list_manually::(&rlp_bytes, randomness, k); + for (i, w) in witness.iter().enumerate() { + print!("witness[{}] = {:?}\n", i, w); + } + } + + #[test] + fn test_correct_witness_generation_11tx() { + let rlp_bytes = prepare_legacy_txlist_rlp_bytes(11); + let randomness = Fr::from(100); + let k = 256; + + let witness = rlp_decode_tx_list_manually::(&rlp_bytes, randomness, k); + for (i, w) in witness.iter().enumerate() { + print!("witness[{}] = {:?}\n", i, w); + } + } + + #[test] + fn test_correct_witness_generation_big_data() { + let mut rng = ChaCha20Rng::seed_from_u64(2u64); + let tx: SignedTransaction = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from( + (0..55).map(|v| v as u8).collect::>(), + )) + .build() + .into(); + + let rlp_txs = rlp::encode_list(&[tx]); + println!("rlp_txs = {:?}", hex::encode(rlp_txs.clone())); + let randomness = Fr::from(100); + let k = 256; + + let witness = rlp_decode_tx_list_manually::(&rlp_txs.to_vec(), randomness, k); + for (i, w) in witness.iter().enumerate() { + print!("witness[{}] = {:?}\n", i, w); + } + } + + #[test] + fn test_wrong_witness_generation() { + todo!() + } } #[cfg(test)] mod rlp_decode_circuit_tests { use super::*; use crate::util::log2_ceil; - use eth_types::address; use halo2_proofs::{ dev::{MockProver, VerifyFailure}, halo2curves::bn256::Fr, }; use mock::AddrOrWallet; use pretty_assertions::assert_eq; + use rand::SeedableRng; + use rand_chacha::ChaCha20Rng; - const NUM_BLINDING_ROWS: usize = 64; + fn run(txs: Vec) -> Result<(), Vec> { + let k = log2_ceil(RlpDecoderCircuit::::min_num_rows_from_tx(&txs).0); - fn run( - txs: Vec, - chain_id: u64, - max_txs: usize, - max_calldata: usize, - ) -> Result<(), Vec> { - let k = log2_ceil( - NUM_BLINDING_ROWS + RlpDecoderCircuit::::min_num_rows(max_txs, max_calldata), - ); - // SignVerifyChip -> ECDSAChip -> MainGate instance column - let circuit = RlpDecoderCircuit::::new(max_txs, max_calldata, vec![]); + let encodable_txs: Vec = + txs.iter().map(|tx| tx.into()).collect::>(); + let rlp_bytes = rlp::encode_list(&encodable_txs); + println!("input rlp_bytes = {:?}", hex::encode(&rlp_bytes)); + let circuit = RlpDecoderCircuit::::new(rlp_bytes.to_vec(), k as usize); let prover = match MockProver::run(k, &circuit, vec![]) { Ok(prover) => prover, Err(e) => panic!("{:#?}", e), @@ -1136,50 +2110,84 @@ mod rlp_decode_circuit_tests { } #[test] - fn tx_circuit_1tx_1max_tx() { - const MAX_TXS: usize = 1; - const MAX_CALLDATA: usize = 32; - - let chain_id: u64 = mock::MOCK_CHAIN_ID.as_u64(); + fn tx_circuit_0tx() { + assert_eq!(run::(vec![]), Ok(())); + } + #[test] + fn tx_circuit_1tx() { let tx: Transaction = mock::CORRECT_MOCK_TXS[0].clone().into(); + assert_eq!(run::(vec![tx]), Ok(())); + } - assert_eq!(run::(vec![tx], chain_id, MAX_TXS, MAX_CALLDATA), Ok(())); + #[test] + fn tx_circuit_2tx() { + let tx1: Transaction = mock::CORRECT_MOCK_TXS[0].clone().into(); + let tx2: Transaction = mock::CORRECT_MOCK_TXS[1].clone().into(); + assert_eq!(run::(vec![tx1, tx2]), Ok(())); } #[test] - fn tx_circuit_1tx_2max_tx() { - const MAX_TXS: usize = 2; - const MAX_CALLDATA: usize = 32; + fn tx_circuit_1tx_non_to() { + let mut rng = ChaCha20Rng::seed_from_u64(2u64); + let tx = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .build() + .into(); + assert_eq!(run::(vec![tx]), Ok(())); + } - let chain_id: u64 = mock::MOCK_CHAIN_ID.as_u64(); + #[test] + fn tx_circuit_tx_with_various_input() { + let mut rng = ChaCha20Rng::seed_from_u64(2u64); + let mut tx = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from(b"0")) + .build() + .into(); + assert_eq!(run::(vec![tx]), Ok(())); - let tx: Transaction = mock::CORRECT_MOCK_TXS[0].clone().into(); + tx = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from(b"1")) + .build() + .into(); + assert_eq!(run::(vec![tx]), Ok(())); - assert_eq!(run::(vec![tx], chain_id, MAX_TXS, MAX_CALLDATA), Ok(())); - } + tx = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from( + (0..55).map(|v| v % 255).collect::>(), + )) + .build() + .into(); + assert_eq!(run::(vec![tx]), Ok(())); - #[test] - fn tx_circuit_bad_address() { - const MAX_TXS: usize = 1; - const MAX_CALLDATA: usize = 32; - - let mut tx = mock::CORRECT_MOCK_TXS[0].clone(); - // This address doesn't correspond to the account that signed this tx. - tx.from = AddrOrWallet::from(address!("0x1230000000000000000000000000000000000456")); - - assert!(run::( - vec![tx.into()], - mock::MOCK_CHAIN_ID.as_u64(), - MAX_TXS, - MAX_CALLDATA - ) - .is_err(),); + tx = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from( + (0..65536).map(|v| v as u8).collect::>(), + )) + .build() + .into(); + assert_eq!(run::(vec![tx]), Ok(())); + + tx = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from( + (0..65536 * 2).map(|v| v as u8).collect::>(), + )) + .build() + .into(); + assert_eq!(run::(vec![tx.clone(), tx.clone()]), Ok(())); } } +#[cfg(test)] mod bench { + use super::*; use ark_std::{end_timer, start_timer}; + use eth_types::Bytes; use halo2_proofs::{ halo2curves::bn256::{Bn256, Fr, G1Affine}, plonk::{create_proof, keygen_pk, keygen_vk, verify_proof}, @@ -1195,14 +2203,9 @@ mod bench { Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, }, }; - use std::env::var; - use rand::SeedableRng; - use rand_chacha::ChaChaRng; - - use super::*; - use crate::util::log2_ceil; + use std::env::var; #[test] fn bench_super_circuit_prover() { @@ -1218,13 +2221,8 @@ mod bench { .expect("Cannot parse DEGREE env var as u32"); let mut rng = ChaChaRng::seed_from_u64(2); - - let (circuit, instance) = { - let mut circuit = RlpDecoderCircuit::::new(10, 16384, vec![]); - let instance = vec![vec![]]; - (circuit, instance) - }; - let instance_refs: Vec<&[Fr]> = instance.iter().map(|v| &v[..]).collect(); + let input_bytes = hex::decode("f850f84e8001830f4240808080820a97a0805d3057e9b74379d814e2c4d264be888a9b560ea2256781af8a6ea83af41208a07168d2b6d3aa47cbc5020c8a9b120926a197e1135b3aaa13ef0b292663345c15").unwrap(); + let circuit = RlpDecoderCircuit::::new(input_bytes, degree as usize); // Bench setup generation let setup_message = format!("{} {} with degree = {}", BENCHMARK_ID, setup_prfx, degree); From ecc63a744ddbedc039670e6282d3b10581ed7b7f Mon Sep 17 00:00:00 2001 From: smtmfft Date: Mon, 22 May 2023 10:59:04 +0000 Subject: [PATCH 04/21] add lookups --- zkevm-circuits/src/lib.rs | 1 + zkevm-circuits/src/rlp_decoder.rs | 137 ++++++--- zkevm-circuits/src/rlp_decoder_tables.rs | 352 +++++++++++++++++++++++ 3 files changed, 451 insertions(+), 39 deletions(-) create mode 100644 zkevm-circuits/src/rlp_decoder_tables.rs diff --git a/zkevm-circuits/src/lib.rs b/zkevm-circuits/src/lib.rs index 33671b196f..8f2625a4ad 100644 --- a/zkevm-circuits/src/lib.rs +++ b/zkevm-circuits/src/lib.rs @@ -26,6 +26,7 @@ pub mod keccak_circuit; pub mod mpt_circuit; pub mod pi_circuit; pub mod rlp_decoder; +pub mod rlp_decoder_tables; pub mod root_circuit; pub mod state_circuit; pub mod super_circuit; diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 2dfc7ba9f3..057f8199f4 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -5,7 +5,8 @@ use std::marker::PhantomData; use crate::{ evm_circuit::util::{constraint_builder::BaseConstraintBuilder, rlc}, impl_expr, - table::{KeccakTable, TxTable}, + rlp_decoder_tables::{RMultPowTable, RlpDecoderTable, TxFieldSwitchTable}, + table::KeccakTable, util::{log2_ceil, Challenges, SubCircuit, SubCircuitConfig}, witness, }; @@ -22,10 +23,6 @@ use halo2_proofs::{ }, poly::Rotation, }; -// use itertools::Itertools; -// use log::error; -// use sign_verify::{AssignedSignatureVerify, SignVerifyChip, SignVerifyConfig}; -// use std::marker::PhantomData; use crate::util::Expr; pub use halo2_proofs::halo2curves::{ @@ -89,24 +86,6 @@ impl std::ops::Index for Vec { } } -// single, null, short, long1, long2, long3, long4, partial, length, r_mult -// 1, 0, 0, 0, 0, 0, 0, 0, 1~3, r^(0~2) -// 0, 1, 0, 0, 0, 0, 0, 0, 1, r^0 -// 0, 0, 1, 0, 0, 0, 0, 0, 1~33, r^(0~32) -// 0, 0, 1, 0, 0, 0, 0, 0, 2, r^1 -// . -// 0, 0, 0, 1, 0, 0, 0, 0, 1~33, r^(0~32) -// 0, 0, 0, 0, 1, 0, 0, 0, 1~33, r^(0~32) -// 0, 0, 0, 0, 0, 1, 0, 0, 1~33, r^(0~32) -// 0, 0, 0, 0, 0, 0, 1, 0, 1~33, r^(0~32) -// 0, 0, 0, 0, 0, 0, 0, 1, 1~33, r^(0~32) -#[derive(Clone, Debug)] -struct RlpDecodeTable { - rlp_type: [Column; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], - bytes_length: Column, // max 33 bytes - r_mult: Column, -} - // TODO: combine with TxFieldTag in table.rs // Marker that defines whether an Operation performs a `READ` or a `WRITE`. /// RlpTxFieldTag is used to tell the field of tx, used as state in the circuit @@ -181,7 +160,8 @@ pub enum RlpTxTypeTag { } impl_expr!(RlpTxTypeTag); -const MAX_BYTE_COLUMN_NUM: usize = 33; +/// max byte column num which is used to store the rlp raw bytes +pub const MAX_BYTE_COLUMN_NUM: usize = 33; /// Witness for RlpDecoderCircuit #[derive(Clone, Debug, Default)] @@ -272,8 +252,12 @@ pub struct RlpDecoderCircuitConfig { #[derive(Clone, Debug)] /// Circuit configuration arguments pub struct RlpDecoderCircuitConfigArgs { - /// TxTable - pub tx_table: TxTable, + /// RlpDecoderTable + pub rlp_decoder_table: RlpDecoderTable, + /// state transition table + pub tx_field_switch_table: TxFieldSwitchTable, + /// r_mult pow table + pub r_mult_pow_table: RMultPowTable, /// KeccakTable pub keccak_table: KeccakTable, /// Challenges @@ -313,16 +297,68 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .collect::>>() .try_into() .unwrap(); - let q_enable = meta.selector(); + let q_enable = meta.complex_selector(); let q_first = meta.fixed_column(); let q_last = meta.fixed_column(); - // TODO: lookup rlp_types table, which may also include bytes[1] as prefix of len - // also need to be constrainted - // TODO: lookup r_mult table with length, also as r_mult is adv, add constraint for pow // TODO: lookup bytes range table // TODO: lookup q_fields table + // lookup rlp_types table + // TODO: bytes[1] as prefix of len also need to be constrainted + meta.lookup_any("rlp decodable check", |meta| { + let tag = meta.query_advice(tag, Rotation::cur()); + let byte0 = meta.query_advice(bytes[0], Rotation::cur()); + let decodable = meta.query_advice(decodable, Rotation::cur()); + let q_enable = meta.query_selector(q_enable); + + let tag_in_table = + meta.query_fixed(args.rlp_decoder_table.tx_field_tag, Rotation::cur()); + let byte0_in_table = meta.query_fixed(args.rlp_decoder_table.byte_0, Rotation::cur()); + let decodable_in_table = + meta.query_fixed(args.rlp_decoder_table.decodable, Rotation::cur()); + vec![ + (q_enable.expr() * tag, tag_in_table), + (q_enable.expr() * byte0, byte0_in_table), + (q_enable.expr() * decodable, decodable_in_table), + ] + }); + + // // lookup tx_field_switch table + meta.lookup_any("rlp tx field transition", |meta| { + let current_field = meta.query_advice(tag, Rotation::cur()); + let next_filed = meta.query_advice(tag, Rotation::next()); + let current_field_in_table = + meta.query_fixed(args.tx_field_switch_table.current_tx_field, Rotation::cur()); + let next_field_in_table = + meta.query_fixed(args.tx_field_switch_table.next_tx_field, Rotation::cur()); + let q_enable = meta.query_selector(q_enable); + let is_last = meta.query_fixed(q_last, Rotation::cur()); + + vec![ + ( + and::expr([not::expr(is_last.expr()), q_enable.expr()]) * current_field, + current_field_in_table, + ), + ( + and::expr([not::expr(is_last.expr()), q_enable.expr()]) * next_filed, + next_field_in_table, + ), + ] + }); + + // // lookup r_mult table with length, + // // TODO: r_mult is adv, add constraint for pow + // meta.lookup_any("rlp r_mult check", |meta| { + // let r_mult = meta.query_advice(r_mult, Rotation::cur()); + // let pow = meta.query_advice(tag_bytes_in_row, Rotation::cur()); + // let r_mult_in_table = meta.query_fixed(args.r_mult_pow_table.r_mult, + // Rotation::cur()); let r_pow_in_table = + // meta.query_fixed(args.r_mult_pow_table.length, Rotation::cur()); + + // vec![(r_mult, r_mult_in_table), (pow, r_pow_in_table)] + // }); + meta.create_gate("common constraints for all rows", |meta| { let mut cb = BaseConstraintBuilder::default(); @@ -1311,7 +1347,10 @@ impl RlpDecoderCircuit { fn calc_min_num_rows(txs_len: usize, call_data_rows: usize) -> usize { // add 2 for prev and next rotations. - txs_len * LEGACY_TX_FIELD_NUM + call_data_rows + NUM_BLINDING_ROWS + 2 + let constraint_size = txs_len * LEGACY_TX_FIELD_NUM + call_data_rows + 2; + let tables_size = + RlpDecoderTable::table_size() + TxFieldSwitchTable::table_size() + MAX_BYTE_COLUMN_NUM; + constraint_size + tables_size + NUM_BLINDING_ROWS } } @@ -1351,9 +1390,16 @@ impl SubCircuit for RlpDecoderCircuit { let witness: Vec> = rlp_decode_tx_list_manually(&self.bytes, randomness, self.size as u32); - // for iw in witness.iter().take(100).enumerate() { - // println!("witness[{}] {:?}", iw.0, iw.1); - // } + config.args.rlp_decoder_table.load(layouter, challenges)?; + config + .args + .tx_field_switch_table + .load(layouter, challenges)?; + config.args.r_mult_pow_table.load(layouter, challenges)?; + config + .args + .keccak_table + .dev_load(layouter, vec![&self.bytes], challenges)?; layouter.assign_region( || "rlp witness region", @@ -1381,7 +1427,9 @@ impl Circuit for RlpDecoderCircuit { } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let tx_table = TxTable::construct(meta); + let rlp_decoder_table = RlpDecoderTable::construct(meta); + let tx_field_switch_table = TxFieldSwitchTable::construct(meta); + let r_mult_pow_table = RMultPowTable::construct(meta); let keccak_table = KeccakTable::construct(meta); let challenges = Challenges::construct(meta); @@ -1392,7 +1440,9 @@ impl Circuit for RlpDecoderCircuit { RlpDecoderCircuitConfig::new( meta, RlpDecoderCircuitConfigArgs { - tx_table, + rlp_decoder_table, + tx_field_switch_table, + r_mult_pow_table, keccak_table, challenges: challenges_expr, }, @@ -1804,10 +1854,15 @@ fn rlp_decode_tx_list_manually( let witness_len = witness.len(); assert!(k > (witness_len + 2 + NUM_BLINDING_ROWS) as u32); - complete_paddings( + let complete_witness = complete_paddings( &mut witness, k as usize - witness_len - 2 - NUM_BLINDING_ROWS, - ) + ); + + // for iw in complete_witness.iter().enumerate() { + // println!("witness[{}] {:?}", iw.0, iw.1); + // } + complete_witness } fn fixup_acc_rlc(witness: &mut Vec>, randomness: F) { @@ -2099,7 +2154,11 @@ mod rlp_decode_circuit_tests { let encodable_txs: Vec = txs.iter().map(|tx| tx.into()).collect::>(); let rlp_bytes = rlp::encode_list(&encodable_txs); - println!("input rlp_bytes = {:?}", hex::encode(&rlp_bytes)); + println!( + "input rlp_bytes = {:?}, k = {}.", + hex::encode(&rlp_bytes), + k + ); let circuit = RlpDecoderCircuit::::new(rlp_bytes.to_vec(), k as usize); let prover = match MockProver::run(k, &circuit, vec![]) { diff --git a/zkevm-circuits/src/rlp_decoder_tables.rs b/zkevm-circuits/src/rlp_decoder_tables.rs new file mode 100644 index 0000000000..d38cdd3fbc --- /dev/null +++ b/zkevm-circuits/src/rlp_decoder_tables.rs @@ -0,0 +1,352 @@ +//! The rlp decoding tables implementation. + +use std::marker::PhantomData; + +use crate::{ + evm_circuit::util::{constraint_builder::BaseConstraintBuilder, rlc}, + impl_expr, + rlp_decoder::{RlpDecodeTypeTag, RlpTxFieldTag, MAX_BYTE_COLUMN_NUM}, + table::{KeccakTable, TxTable}, + util::{log2_ceil, Challenges, Expr, SubCircuit, SubCircuitConfig}, + witness, +}; +use eth_types::{Field, Signature, Transaction, Word}; +use ethers_core::{ + types::TransactionRequest, + utils::rlp::{self, PayloadInfo}, +}; +use gadgets::util::{and, not}; +pub use halo2_proofs::halo2curves::{ + group::{ + ff::{Field as GroupField, PrimeField}, + prime::PrimeCurveAffine, + Curve, Group, GroupEncoding, + }, + secp256k1::{self, Secp256k1Affine, Secp256k1Compressed}, +}; +use halo2_proofs::{ + circuit::{Layouter, Region, SimpleFloorPlanner, Value}, + plonk::{ + Advice, Circuit, Column, ConstraintSystem, Error, Expression, Fixed, SecondPhase, Selector, + }, + poly::Rotation, +}; + +/// Rlp encoding types +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum RlpDecodeRule { + /// The Padding RLP encoding type is a single byte 0x00 + Padding, + /// The RLP encoding type is a empty string, i.e., 0x80 + Empty, + /// The RLP encoding type is a uint96 + Uint64, + /// The RLP encoding type is a uint96 + Uint96, + /// The RLP encoding type is a address 20bytes i.e., 0x94xxxx + Address, + /// The RLP encoding type is a hash string 32bytes, i.e., 0xa0xxx + Bytes32, + /// The RLP encoding type is a string which is upto 48k bytes + Bytes48K, + /// The RLP encoding empty list type + EmptyList, + /// The RLP encoding empty long list type, upto 16M, i.e., 0xF9FFFFFF + LongList, +} + +impl RlpDecodeRule { + /// Get the length of the RLP encoding type + pub fn load( + &self, + tx_field_tag: &RlpTxFieldTag, + table: &RlpDecoderTable, + region: &mut Region<'_, F>, + offset: usize, + ) -> Result<(), Error> { + let rule_table_rows = { + (0..256u64) + .map(|i| { + let (rlp_type, decodable, length) = match self { + RlpDecodeRule::Padding => (RlpDecodeTypeTag::SingleByte, true, 0u64), + RlpDecodeRule::Empty => match i { + 0x80 => (RlpDecodeTypeTag::SingleByte, true, 1u64), + _ => (RlpDecodeTypeTag::ShortString, false, 0u64), + }, + RlpDecodeRule::Uint64 => match i { + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true, 1u64), + 0x81..=0x88 => (RlpDecodeTypeTag::ShortString, true, i - 0x80 + 1), + _ => (RlpDecodeTypeTag::ShortString, false, 0u64), + }, + RlpDecodeRule::Uint96 => match i { + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true, 1), + 0x81..=0x8c => (RlpDecodeTypeTag::ShortString, true, i - 0x80 + 1), + _ => (RlpDecodeTypeTag::ShortString, false, 0), + }, + RlpDecodeRule::Address => match i { + 0x94 => (RlpDecodeTypeTag::ShortString, true, 20 + 1), + _ => (RlpDecodeTypeTag::ShortString, false, 0), + }, + RlpDecodeRule::Bytes32 => match i { + 0xa0 => (RlpDecodeTypeTag::ShortString, true, 20 + 1), + _ => (RlpDecodeTypeTag::ShortString, false, 0), + }, + RlpDecodeRule::Bytes48K => match i { + 0 => (RlpDecodeTypeTag::SingleByte, false, 1), + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true, 1), + 0x81..=0xbf => (RlpDecodeTypeTag::ShortString, true, i - 0x80 + 1), + _ => (RlpDecodeTypeTag::ShortString, false, 0), + }, + RlpDecodeRule::EmptyList => match i { + 0xc0 => (RlpDecodeTypeTag::ShortString, false, 0), + _ => (RlpDecodeTypeTag::ShortString, false, 0), + }, + RlpDecodeRule::LongList => match i { + 0xf8 => (RlpDecodeTypeTag::LongList1, true, 2), + 0xf9 => (RlpDecodeTypeTag::LongList2, true, 3), + 0xfa => (RlpDecodeTypeTag::LongList3, true, 4), + _ => (RlpDecodeTypeTag::LongList1, false, 0), + }, + }; + [ + *tx_field_tag as u64, + rlp_type as u64, + i, + decodable as u64, + length, + ] + }) + .collect::>() + }; + + let mut offset = offset; + for rule_table_row in rule_table_rows.iter() { + // println!("rule_table_row: {:?} @ offset {}.", rule_table_row, offset); + rule_table_row + .iter() + .zip([ + table.tx_field_tag, + table.rlp_type, + table.byte_0, + table.decodable, + table.length, + ]) + .try_for_each(|(value, col)| { + region + .assign_fixed( + || "load rlp decoder table", + col, + offset, + || Value::known(F::from(*value)), + ) + .map(|_| ()) + })?; + offset += 1; + } + Ok(()) + } +} + +/// Table that contains the fields of all possible RLP decodable fields +#[derive(Clone, Debug)] +pub struct RlpDecoderTable { + /// The tx field tag + pub tx_field_tag: Column, + /// The RLP type + pub rlp_type: Column, + /// The first byte of the RLP encoded field + pub byte_0: Column, + /// Whether the field is decodable + pub decodable: Column, + /// The length of the field + pub length: Column, +} + +impl RlpDecoderTable { + /// Construct a new RlpDecoderTable + pub fn construct(meta: &mut ConstraintSystem) -> Self { + Self { + tx_field_tag: meta.fixed_column(), + rlp_type: meta.fixed_column(), + byte_0: meta.fixed_column(), + decodable: meta.fixed_column(), + length: meta.fixed_column(), + } + } + + /// Get the row num of the RLP decoding table + pub fn table_size() -> usize { + (RlpDecodeRule::LongList as usize + 1) * 256 + } + + /// Assign the values of the table to the circuit + pub fn load( + &self, + layouter: &mut impl Layouter, + challenges: &Challenges>, + ) -> Result<(), Error> { + // make a list with all member of rlpTxFieldTag literally + let rlp_tx_field_tag_list: Vec<(RlpTxFieldTag, RlpDecodeRule)> = vec![ + (RlpTxFieldTag::TxListRlpHeader, RlpDecodeRule::LongList), + (RlpTxFieldTag::TxRlpHeader, RlpDecodeRule::LongList), + (RlpTxFieldTag::Nonce, RlpDecodeRule::Uint96), + (RlpTxFieldTag::GasPrice, RlpDecodeRule::Uint96), + (RlpTxFieldTag::Gas, RlpDecodeRule::Uint96), + (RlpTxFieldTag::To, RlpDecodeRule::Address), + (RlpTxFieldTag::To, RlpDecodeRule::Empty), + (RlpTxFieldTag::Value, RlpDecodeRule::Uint96), + (RlpTxFieldTag::Data, RlpDecodeRule::Bytes48K), + (RlpTxFieldTag::SignV, RlpDecodeRule::Uint96), + (RlpTxFieldTag::SignR, RlpDecodeRule::Bytes32), + (RlpTxFieldTag::SignS, RlpDecodeRule::Bytes48K), + (RlpTxFieldTag::Padding, RlpDecodeRule::Padding), + ]; + + layouter.assign_region( + || "load rlp decoder table", + |mut region| { + let mut offset = 0; + for (tx_field_tag, decode_rule) in rlp_tx_field_tag_list.iter() { + decode_rule.load(tx_field_tag, self, &mut region, offset)?; + offset += 256; + } + Ok(()) + }, + )?; + + Ok(()) + } +} + +/// Table that contains the fields of possible state transitions +#[derive(Clone, Debug)] +pub struct TxFieldSwitchTable { + /// The current tx field + pub current_tx_field: Column, + /// The next tx field + pub next_tx_field: Column, +} + +static TX_FIELD_TRANSITION_TABLE: [(RlpTxFieldTag, RlpTxFieldTag); 14] = [ + (RlpTxFieldTag::TxListRlpHeader, RlpTxFieldTag::TxRlpHeader), + (RlpTxFieldTag::TxRlpHeader, RlpTxFieldTag::Nonce), + (RlpTxFieldTag::Nonce, RlpTxFieldTag::GasPrice), + (RlpTxFieldTag::GasPrice, RlpTxFieldTag::Gas), + (RlpTxFieldTag::Gas, RlpTxFieldTag::To), + (RlpTxFieldTag::To, RlpTxFieldTag::Value), + (RlpTxFieldTag::Value, RlpTxFieldTag::Data), + (RlpTxFieldTag::Data, RlpTxFieldTag::Data), + (RlpTxFieldTag::Data, RlpTxFieldTag::SignV), + (RlpTxFieldTag::SignV, RlpTxFieldTag::SignR), + (RlpTxFieldTag::SignR, RlpTxFieldTag::SignS), + (RlpTxFieldTag::SignS, RlpTxFieldTag::TxRlpHeader), + (RlpTxFieldTag::SignS, RlpTxFieldTag::Padding), + (RlpTxFieldTag::Padding, RlpTxFieldTag::Padding), + // TODO: add 1559 fields +]; + +impl TxFieldSwitchTable { + /// Construct a new RlpDecoderTable + pub fn construct(meta: &mut ConstraintSystem) -> Self { + Self { + current_tx_field: meta.fixed_column(), + next_tx_field: meta.fixed_column(), + } + } + + /// Get the row num of the table + pub fn table_size() -> usize { + TX_FIELD_TRANSITION_TABLE.len() + } + + /// Assign the values of the table to the circuit + pub fn load( + &self, + layouter: &mut impl Layouter, + challenges: &Challenges>, + ) -> Result<(), Error> { + // make a list with all member of rlpTxFieldTag literally + let tx_field_trans_table = &TX_FIELD_TRANSITION_TABLE; + + layouter.assign_region( + || "load rlp decoder table", + |mut region| { + let mut offset = 0; + tx_field_trans_table + .iter() + .try_for_each(|(current_tx_field, next_tx_field)| { + region.assign_fixed( + || "current tx field", + self.current_tx_field, + offset, + || Value::known(F::from(*current_tx_field as u64)), + )?; + region.assign_fixed( + || "next tx field", + self.next_tx_field, + offset, + || Value::known(F::from(*next_tx_field as u64)), + )?; + offset += 1; + Ok(()) + }) + }, + ) + } +} + +/// Table that contains the pow of randomness +#[derive(Clone, Debug)] +pub struct RMultPowTable { + /// pow number + pub length: Column, + /// pow of randomness + pub r_mult: Column, +} + +impl RMultPowTable { + /// Construct a new RlpDecoderTable + pub fn construct(meta: &mut ConstraintSystem) -> Self { + Self { + length: meta.fixed_column(), + r_mult: meta.fixed_column(), + } + } + + /// Get the row num of the table + pub fn table_size() -> usize { + MAX_BYTE_COLUMN_NUM + } + + /// Assign the values of the table to the circuit + pub fn load( + &self, + layouter: &mut impl Layouter, + challenges: &Challenges>, + ) -> Result<(), Error> { + let mut randomness = F::zero(); + challenges.keccak_input().map(|r| randomness = r); + + (0..MAX_BYTE_COLUMN_NUM).try_for_each(|i| { + layouter.assign_region( + || "load rlp r_mult table", + |mut region| { + region.assign_fixed( + || "pow", + self.length, + i, + || Value::known(F::from(i as u64)), + )?; + region.assign_fixed( + || "r_mult", + self.r_mult, + i, + || Value::known(randomness.pow(&[i as u64, 0, 0, 0])), + )?; + Ok(()) + }, + ) + })?; + Ok(()) + } +} From b996966a6f56c2230fe1c100159a24606aa3d9ab Mon Sep 17 00:00:00 2001 From: smtmfft Date: Tue, 23 May 2023 07:40:25 +0000 Subject: [PATCH 05/21] refine logic based on lookup --- gadgets/src/is_equal.rs | 257 ++++++++ gadgets/src/is_zero.rs | 1 + gadgets/src/lib.rs | 1 + zkevm-circuits/src/rlp_decoder.rs | 717 ++++++----------------- zkevm-circuits/src/rlp_decoder_tables.rs | 143 +++-- 5 files changed, 528 insertions(+), 591 deletions(-) create mode 100644 gadgets/src/is_equal.rs diff --git a/gadgets/src/is_equal.rs b/gadgets/src/is_equal.rs new file mode 100644 index 0000000000..4bc13247b7 --- /dev/null +++ b/gadgets/src/is_equal.rs @@ -0,0 +1,257 @@ +//! IsEqual chip can be used to check equality of two expressions. + +use eth_types::Field; +use halo2_proofs::{ + arithmetic::FieldExt, + circuit::{Chip, Region, Value}, + plonk::{ConstraintSystem, Error, Expression, VirtualCells}, +}; + +use crate::util::Expr; + +use super::is_zero::{IsZeroChip, IsZeroInstruction}; + +/// Instruction that the IsEqual chip needs to implement. +pub trait IsEqualInstruction { + /// Assign lhs and rhs witnesses to the IsEqual chip's region. + fn assign( + &self, + region: &mut Region<'_, F>, + offset: usize, + lhs: Value, + rhs: Value, + ) -> Result<(), Error>; +} + +/// Config for the IsEqual chip. +#[derive(Clone, Debug)] +pub struct IsEqualConfig { + /// Stores an IsZero chip. + pub is_zero_chip: IsZeroChip, + /// Expression that denotes whether the chip evaluated to equal or not. + pub is_equal_expression: Expression, +} + +impl IsEqualConfig { + /// Returns the expression that denotes whether the chip evaluated to equal or not. + pub fn is_equal(&self) -> Expression { + self.is_equal_expression.expr() + } +} + +/// Chip that compares equality between two expressions. +#[derive(Clone, Debug)] +pub struct IsEqualChip { + /// Config for the IsEqual chip. + pub(crate) config: IsEqualConfig, +} + +impl IsEqualChip { + /// Configure the IsEqual chip. + pub fn configure( + meta: &mut ConstraintSystem, + q_enable: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression, + lhs: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression, + rhs: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression, + ) -> IsEqualConfig { + let value = |meta: &mut VirtualCells| lhs(meta) - rhs(meta); + let value_inv = meta.advice_column(); + + let is_zero_config = IsZeroChip::configure(meta, q_enable, value, value_inv); + let is_equal_expression = is_zero_config.is_zero_expression.clone(); + + IsEqualConfig { + is_zero_chip: IsZeroChip::construct(is_zero_config), + is_equal_expression, + } + } + + /// Construct an IsEqual chip given a config. + pub fn construct(config: IsEqualConfig) -> Self { + Self { config } + } +} + +impl IsEqualInstruction for IsEqualChip { + fn assign( + &self, + region: &mut Region<'_, F>, + offset: usize, + lhs: Value, + rhs: Value, + ) -> Result<(), Error> { + self.config.is_zero_chip.assign(region, offset, lhs - rhs)?; + + Ok(()) + } +} + +impl Chip for IsEqualChip { + type Config = IsEqualConfig; + type Loaded = (); + + fn config(&self) -> &Self::Config { + &self.config + } + + fn loaded(&self) -> &Self::Loaded { + &() + } +} + +#[cfg(test)] +mod tests { + use std::marker::PhantomData; + + use eth_types::Field; + use halo2_proofs::{ + arithmetic::FieldExt, + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + halo2curves::bn256::Fr as Fp, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Selector, VirtualCells}, + poly::Rotation, + }; + use rand::Rng; + + use super::{IsEqualChip, IsEqualConfig, IsEqualInstruction}; + use crate::util::Expr; + + #[derive(Clone, Debug)] + struct TestCircuitConfig { + q_enable: Selector, + value: Column, + check: Column, + is_equal: IsEqualConfig, + } + + #[derive(Default)] + struct TestCircuit { + values: Vec, + checks: Vec, + _marker: PhantomData, + } + + impl Circuit for TestCircuit { + type Config = TestCircuitConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let q_enable = meta.complex_selector(); + let value = meta.advice_column(); + let check = meta.advice_column(); + + let lhs = |meta: &mut VirtualCells| meta.query_advice(value, Rotation::cur()); + let rhs = |_meta: &mut VirtualCells| RHS.expr(); + + let is_equal = + IsEqualChip::configure(meta, |meta| meta.query_selector(q_enable), lhs, rhs); + + let config = Self::Config { + q_enable, + value, + check, + is_equal, + }; + + meta.create_gate("check is_equal", |meta| { + let q_enable = meta.query_selector(q_enable); + + let check = meta.query_advice(check, Rotation::cur()); + + vec![q_enable * (config.is_equal.is_equal_expression.clone() - check)] + }); + + config + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = IsEqualChip::construct(config.is_equal.clone()); + + layouter.assign_region( + || "witness", + |mut region| { + let checks = self.checks.clone(); + + for (idx, (value, check)) in self.values.iter().cloned().zip(checks).enumerate() + { + region.assign_advice( + || "value", + config.value, + idx + 1, + || Value::known(F::from(value)), + )?; + region.assign_advice( + || "check", + config.check, + idx + 1, + || Value::known(F::from(check as u64)), + )?; + config.q_enable.enable(&mut region, idx + 1)?; + chip.assign( + &mut region, + idx + 1, + Value::known(F::from(value)), + Value::known(F::from(RHS)), + )?; + } + + Ok(()) + }, + ) + } + } + + macro_rules! try_test { + ($values:expr, $checks:expr, $rhs:expr, $is_ok_or_err:ident) => { + let k = usize::BITS - $values.len().leading_zeros() + 2; + let circuit = TestCircuit:: { + values: $values, + checks: $checks, + _marker: PhantomData, + }; + let prover = MockProver::::run(k, &circuit, vec![]).unwrap(); + assert!(prover.verify().$is_ok_or_err()); + }; + } + + fn random() -> u64 { + rand::thread_rng().gen::() + } + + #[test] + fn is_equal_gadget() { + try_test!( + vec![random(), 123, random(), 123, 123, random()], + vec![false, true, false, true, true, false], + 123, + is_ok + ); + try_test!( + vec![random(), 321321, 321321, random()], + vec![false, true, true, false], + 321321, + is_ok + ); + try_test!( + vec![random(), random(), random(), 1846123], + vec![false, false, false, true], + 1846123, + is_ok + ); + try_test!( + vec![123, 234, 345, 456], + vec![true, true, false, false], + 234, + is_err + ); + } +} diff --git a/gadgets/src/is_zero.rs b/gadgets/src/is_zero.rs index 0f0d9fe721..32d47158b7 100644 --- a/gadgets/src/is_zero.rs +++ b/gadgets/src/is_zero.rs @@ -51,6 +51,7 @@ impl IsZeroConfig { } } +#[derive(Clone, Debug)] /// Wrapper arround [`IsZeroConfig`] for which [`Chip`] is implemented. pub struct IsZeroChip { config: IsZeroConfig, diff --git a/gadgets/src/lib.rs b/gadgets/src/lib.rs index 3ef7fae9a1..718199f1c1 100644 --- a/gadgets/src/lib.rs +++ b/gadgets/src/lib.rs @@ -14,6 +14,7 @@ pub mod batched_is_zero; pub mod binary_number; pub mod evm_word; +pub mod is_equal; pub mod is_zero; pub mod less_than; pub mod monotone; diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 057f8199f4..58727dc8e5 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -15,7 +15,10 @@ use ethers_core::{ types::TransactionRequest, utils::rlp::{self, PayloadInfo}, }; -use gadgets::util::{and, not}; +use gadgets::{ + is_equal::{IsEqualChip, IsEqualConfig, IsEqualInstruction}, + util::{and, not}, +}; use halo2_proofs::{ circuit::{Layouter, Region, SimpleFloorPlanner, Value}, plonk::{ @@ -41,6 +44,8 @@ const NUM_BLINDING_ROWS: usize = 64; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] pub enum RlpDecodeTypeTag { #[default] + /// Nothing for no rlp decoding + DoNothing, /// SingleByte: 0x00 - 0x7f SingleByte, /// NullValue: 0x80 @@ -175,7 +180,7 @@ pub struct RlpDecoderCircuitConfigWitness { /// complete column pub complete: bool, /// rlp types: [single, short, long, very_long, fixed(33)] - pub rlp_types: [bool; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], + pub rlp_type: RlpDecodeTypeTag, /// rlp_tag_length, the length of this rlp field pub rlp_tag_length: u64, /// remained rows, for n < 33 fields, it is n, for m > 33 fields, it is 33 and next row is @@ -217,7 +222,9 @@ pub struct RlpDecoderCircuitConfig { /// complete column pub complete: Column, /// rlp types: [single, short, long, very_long, fixed(33)] - pub rlp_types: [Column; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], + pub rlp_type: Column, + /// rlp_type checking gadget + pub is_rlp_type: [IsEqualConfig; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], /// rlp_tag_length, the length of this rlp field pub rlp_tag_length: Column, /// remained rows, for n < 33 fields, it is n, for m > 33 fields, it is 33 and next row is @@ -273,12 +280,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tx_type = meta.advice_column(); let tag = meta.advice_column(); let complete = meta.advice_column(); - let rlp_types: [Column; RlpDecodeTypeTag::RlpDecodeTypeNum as usize] = (0 - ..RlpDecodeTypeTag::RlpDecodeTypeNum as usize) - .map(|_| meta.advice_column()) - .collect::>>() - .try_into() - .unwrap(); + let rlp_type = meta.advice_column(); let rlp_tag_length = meta.advice_column(); let tag_bytes_in_row = meta.advice_column(); let rlp_remain_length = meta.advice_column(); @@ -301,26 +303,57 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let q_first = meta.fixed_column(); let q_last = meta.fixed_column(); + // type checking + let is_rlp_type: [IsEqualConfig; RlpDecodeTypeTag::RlpDecodeTypeNum as usize] = (0 + ..RlpDecodeTypeTag::RlpDecodeTypeNum as usize) + .map(|t| { + IsEqualChip::configure( + meta, + |meta| meta.query_selector(q_enable), + |meta| meta.query_advice(rlp_type, Rotation::cur()), + |_| t.expr(), + ) + }) + .collect::>>() + .try_into() + .unwrap(); + // TODO: lookup bytes range table // TODO: lookup q_fields table // lookup rlp_types table // TODO: bytes[1] as prefix of len also need to be constrainted meta.lookup_any("rlp decodable check", |meta| { + let tx_type = meta.query_advice(tx_type, Rotation::cur()); let tag = meta.query_advice(tag, Rotation::cur()); let byte0 = meta.query_advice(bytes[0], Rotation::cur()); let decodable = meta.query_advice(decodable, Rotation::cur()); let q_enable = meta.query_selector(q_enable); + let is_not_partial = + not::expr(is_rlp_type[RlpDecodeTypeTag::PartialRlp as usize].is_equal()); + + let tx_type_in_table = + meta.query_fixed(args.rlp_decoder_table.tx_type, Rotation::cur()); let tag_in_table = meta.query_fixed(args.rlp_decoder_table.tx_field_tag, Rotation::cur()); let byte0_in_table = meta.query_fixed(args.rlp_decoder_table.byte_0, Rotation::cur()); let decodable_in_table = meta.query_fixed(args.rlp_decoder_table.decodable, Rotation::cur()); vec![ - (q_enable.expr() * tag, tag_in_table), - (q_enable.expr() * byte0, byte0_in_table), - (q_enable.expr() * decodable, decodable_in_table), + ( + q_enable.expr() * is_not_partial.expr() * tx_type, + tx_type_in_table, + ), + (q_enable.expr() * is_not_partial.expr() * tag, tag_in_table), + ( + q_enable.expr() * is_not_partial.expr() * byte0, + byte0_in_table, + ), + ( + q_enable.expr() * is_not_partial.expr() * decodable, + decodable_in_table, + ), ] }); @@ -347,24 +380,33 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ] }); - // // lookup r_mult table with length, - // // TODO: r_mult is adv, add constraint for pow - // meta.lookup_any("rlp r_mult check", |meta| { - // let r_mult = meta.query_advice(r_mult, Rotation::cur()); - // let pow = meta.query_advice(tag_bytes_in_row, Rotation::cur()); - // let r_mult_in_table = meta.query_fixed(args.r_mult_pow_table.r_mult, - // Rotation::cur()); let r_pow_in_table = - // meta.query_fixed(args.r_mult_pow_table.length, Rotation::cur()); + // lookup r_mult table with length, + // TODO: r_mult is adv, add constraint for pow + meta.lookup_any("rlp r_mult check", |meta| { + let r_mult = meta.query_advice(r_mult, Rotation::cur()); + let pow = meta.query_advice(tag_bytes_in_row, Rotation::cur()); + let r_mult_in_table = meta.query_fixed(args.r_mult_pow_table.r_mult, Rotation::cur()); + let r_pow_in_table = meta.query_fixed(args.r_mult_pow_table.length, Rotation::cur()); - // vec![(r_mult, r_mult_in_table), (pow, r_pow_in_table)] - // }); + vec![(r_mult, r_mult_in_table), (pow, r_pow_in_table)] + }); meta.create_gate("common constraints for all rows", |meta| { let mut cb = BaseConstraintBuilder::default(); let valid_cur = meta.query_advice(valid, Rotation::cur()); let valid_next = meta.query_advice(valid, Rotation::next()); - cb.require_equal("valid should be consistent", valid_cur, valid_next); + cb.require_equal( + "valid should be consistent", + valid_cur.expr(), + valid_next.expr(), + ); + + let decodable = meta.query_advice(decodable, Rotation::cur()); + cb.require_zero( + "if decode == 0 then valid must 0", + not::expr(decodable.expr()) * valid_cur.expr(), + ); cb.gate(and::expr([ meta.query_selector(q_enable), @@ -376,22 +418,12 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { meta.create_gate("tx fields common constraints", |meta| { let mut cb = BaseConstraintBuilder::default(); - let tx_id = meta.query_advice(tx_id, Rotation::cur()); - let tx_type = meta.query_advice(tx_type, Rotation::cur()); let tag = meta.query_advice(tag, Rotation::cur()); let complete_cur = meta.query_advice(complete, Rotation::cur()); - let rlp_types_cur: [Expression; RlpDecodeTypeTag::RlpDecodeTypeNum as usize] = - rlp_types - .iter() - .map(|rlp_type| meta.query_advice(*rlp_type, Rotation::cur())) - .collect::>() - .try_into() - .unwrap(); let rlp_tag_length_cur = meta.query_advice(rlp_tag_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); let tag_bytes_in_row_cur = meta.query_advice(tag_bytes_in_row, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); - let value = meta.query_advice(value, Rotation::cur()); let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); let byte_cells_cur = bytes .iter() @@ -414,83 +446,70 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_boolean("decodable", decodable); cb.require_boolean("valid", valid); - rlp_types_cur.iter().for_each(|rlp_type_cur| { - cb.require_boolean("rlp_type boolean", rlp_type_cur.expr()); - }); - // length with leading bytes - cb.condition(rlp_types_cur[RlpDecodeTypeTag::SingleByte].expr(), |cb| { + cb.condition(is_rlp_type[RlpDecodeTypeTag::DoNothing].is_equal(), |cb| { + cb.require_equal("0 length", rlp_tag_length_cur.clone(), 0.expr()) + }); + cb.condition(is_rlp_type[RlpDecodeTypeTag::SingleByte].is_equal(), |cb| { cb.require_equal("single length", rlp_tag_length_cur.clone(), 1.expr()) }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::NullValue].expr(), |cb| { + cb.condition(is_rlp_type[RlpDecodeTypeTag::NullValue].is_equal(), |cb| { cb.require_equal("empty length", rlp_tag_length_cur.clone(), 1.expr()) }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::ShortString].expr(), |cb| { - cb.require_equal( - "ShortString length", - rlp_tag_length_cur.clone(), - byte_cells_cur[0].expr() - 0x80.expr() + 1.expr(), - ) - }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongString1].expr(), |cb| { - cb.require_equal( - "Long String 0xb8 length", - rlp_tag_length_cur.clone(), - byte_cells_cur[1].expr() + 2.expr(), - ) - }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongString2].expr(), |cb| { - cb.require_equal( - "Long String 0xb9 length", - rlp_tag_length_cur.clone(), - byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr() + 3.expr(), - ) - }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongString3].expr(), |cb| { - cb.require_equal( - "Long String 0xba length", - rlp_tag_length_cur.clone(), - byte_cells_cur[1].expr() * 65536.expr() - + byte_cells_cur[2].expr() * 256.expr() - + byte_cells_cur[3].expr() - + 4.expr(), - ) - }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::EmptyList].expr(), |cb| { + cb.condition( + is_rlp_type[RlpDecodeTypeTag::ShortString].is_equal(), + |cb| { + cb.require_equal( + "ShortString length", + rlp_tag_length_cur.clone(), + byte_cells_cur[0].expr() - 0x80.expr() + 1.expr(), + ) + }, + ); + cb.condition( + is_rlp_type[RlpDecodeTypeTag::LongString1].is_equal(), + |cb| { + cb.require_equal( + "Long String 0xb8 length", + rlp_tag_length_cur.clone(), + byte_cells_cur[1].expr() + 2.expr(), + ) + }, + ); + cb.condition( + is_rlp_type[RlpDecodeTypeTag::LongString2].is_equal(), + |cb| { + cb.require_equal( + "Long String 0xb9 length", + rlp_tag_length_cur.clone(), + byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr() + 3.expr(), + ) + }, + ); + cb.condition( + is_rlp_type[RlpDecodeTypeTag::LongString3].is_equal(), + |cb| { + cb.require_equal( + "Long String 0xba length", + rlp_tag_length_cur.clone(), + byte_cells_cur[1].expr() * 65536.expr() + + byte_cells_cur[2].expr() * 256.expr() + + byte_cells_cur[3].expr() + + 4.expr(), + ) + }, + ); + cb.condition(is_rlp_type[RlpDecodeTypeTag::EmptyList].is_equal(), |cb| { cb.require_equal("empty list length", rlp_tag_length_cur.clone(), 1.expr()) }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::ShortList].expr(), |cb| { + cb.condition(is_rlp_type[RlpDecodeTypeTag::ShortList].is_equal(), |cb| { cb.require_equal( "short length", rlp_tag_length_cur.clone(), byte_cells_cur[0].expr() - 0xc0.expr() + 1.expr(), ) }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList1].expr(), |cb| { - cb.require_equal( - "long length: f8 + 1", - rlp_tag_length_cur.clone(), - byte_cells_cur[1].expr() + 2.expr(), - ) - }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList2].expr(), |cb| { - cb.require_equal( - "long length: f9 + 2", - rlp_tag_length_cur.clone(), - byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr() + 3.expr(), - ) - }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList3].expr(), |cb| { - cb.require_equal( - "long length: fa + 3", - rlp_tag_length_cur.clone(), - byte_cells_cur[1].expr() * 65536.expr() - + byte_cells_cur[2].expr() * 256.expr() - + byte_cells_cur[3].expr() - + 4.expr(), - ) - }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::PartialRlp].expr(), |cb| { + cb.condition(is_rlp_type[RlpDecodeTypeTag::PartialRlp].is_equal(), |cb| { cb.require_equal( "length = prev_length - prev_bytes_in_row", rlp_tag_length_cur.clone(), @@ -502,6 +521,8 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { "above row is incomplete", meta.query_advice(complete, Rotation::prev()), ); + + cb.require_equal("only data has partial rlp", tag, RlpTxFieldTag::Data.expr()); }); cb.condition(complete_cur.expr(), |cb| { @@ -542,33 +563,22 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }); // TxListHeader in the first row - meta.create_gate("txListHeader", |meta| { + meta.create_gate("txListHeader in first row", |meta| { let mut cb = BaseConstraintBuilder::default(); let tx_id = meta.query_advice(tx_id, Rotation::cur()); let tx_type_cur = meta.query_advice(tx_type, Rotation::cur()); let tag_cur = meta.query_advice(tag, Rotation::cur()); - let tag_next = meta.query_advice(tag, Rotation::next()); let complete = meta.query_advice(complete, Rotation::cur()); - let rlp_types_cur: [Expression; RlpDecodeTypeTag::RlpDecodeTypeNum as usize] = - rlp_types - .iter() - .map(|rlp_type| meta.query_advice(*rlp_type, Rotation::cur())) - .collect::>() - .try_into() - .unwrap(); - let rlp_tag_length_cur = meta.query_advice(rlp_tag_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); - let value = meta.query_advice(value, Rotation::cur()); let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); let byte_cells_cur = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); let decodable = meta.query_advice(decodable, Rotation::cur()); - let valid = meta.query_advice(valid, Rotation::cur()); let q_first = meta.query_fixed(q_first, Rotation::cur()); cb.require_zero("0 tx_id", tx_id); @@ -576,48 +586,15 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_zero("0 tx_tag", tag_cur); cb.require_equal("field completed", complete.expr(), 1.expr()); - // next should be nonce if legacy(0) or chain_id if 1559 - cb.condition(not::expr(tx_type_cur.expr()), |cb| { - let tx_type_next = meta.query_advice(tx_type, Rotation::next()); - cb.require_equal( - "next tx is legacy", - tx_type_next, - RlpTxTypeTag::TxLegacyType.expr(), - ); - cb.require_in_set( - "next field is txRlpHeader or Padding", - tag_next, - vec![ - RlpTxFieldTag::TxRlpHeader.expr(), - RlpTxFieldTag::Padding.expr(), - ], - ); - }); - - // TODO: enable 1559 - // cb.condition("tx 1559", |cb| { - // let next_tx_type = meta.query_advice(tx_type, Rotation::next()); - // cb.require_equal( - // "next tx is 1559", - // next_tx_type, - // RlpTxTypeTag::Tx1559Type.expr(), - // ); - // cb.require_equal( - // "next field is nonce", - // next_tag, - // RlpTxFieldTag::ChainID.expr(), - // ); - // }); - - cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList1].expr(), |cb| { + cb.condition(is_rlp_type[RlpDecodeTypeTag::LongList1].is_equal(), |cb| { cb.require_equal( "long length: f8 + 1", remain_length.expr(), byte_cells_cur[1].expr(), ) - // TODO: byte_cells_cur[1] in (0, 55] + // TODO: byte_cells_cur[1] > 55 }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList2].expr(), |cb| { + cb.condition(is_rlp_type[RlpDecodeTypeTag::LongList2].is_equal(), |cb| { cb.require_equal( "long length: f9 + 2", remain_length.expr(), @@ -626,7 +603,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { // TODO: byte_cells_cur[1] != 0 }); - cb.condition(rlp_types_cur[RlpDecodeTypeTag::LongList3].expr(), |cb| { + cb.condition(is_rlp_type[RlpDecodeTypeTag::LongList3].is_equal(), |cb| { cb.require_equal( "long length: fa + 3", remain_length.expr(), @@ -638,13 +615,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }); cb.condition(decodable, |cb| { - // TODO: use look up?? - cb.require_in_set( - "txlist header in [0xf8,0xf9,0xfa]", - byte_cells_cur[0].expr(), - vec![192.expr(), 248.expr(), 249.expr(), 250.expr()], - ); - cb.require_equal( "rlp_tag_length = rlp_header length", rlp_tag_length_cur.expr(), @@ -662,7 +632,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.gate(q_first) }); - meta.create_gate("txHeader", |meta| { + meta.create_gate("txHeader of legacy tx", |meta| { let mut cb = BaseConstraintBuilder::default(); let tx_id_cur = meta.query_advice(tx_id, Rotation::cur()); @@ -673,15 +643,12 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let complete = meta.query_advice(complete, Rotation::cur()); let rlp_tag_length_cur = meta.query_advice(rlp_tag_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); - let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); - let value = meta.query_advice(value, Rotation::cur()); let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); let byte_cells_cur = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); let decodable = meta.query_advice(decodable, Rotation::cur()); - let valid = meta.query_advice(valid, Rotation::cur()); let q_fields = q_fields .iter() .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) @@ -712,13 +679,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }); cb.condition(decodable, |cb| { - // TODO: use look up?? - cb.require_in_set( - "list header in [0xf8,0xf9,0xfa]", - byte_cells_cur[0].expr(), - vec![248.expr(), 249.expr(), 250.expr()], - ); - cb.require_equal( "rlp_tag_length = rlp_header length", rlp_tag_length_cur.expr(), @@ -736,302 +696,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.gate(q_fields[RlpTxFieldTag::TxRlpHeader].expr() * meta.query_selector(q_enable)) }); - // Nonce - meta.create_gate("Nonce", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let complete = meta.query_advice(complete, Rotation::cur()); - let rlp_types = rlp_types - .iter() - .map(|rlp_type| meta.query_advice(*rlp_type, Rotation::cur())) - .collect::>(); - let bytes = bytes - .iter() - .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) - .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); - - cb.require_equal("nonce tag", tag_cur, RlpTxFieldTag::Nonce.expr()); - cb.require_equal("field completed", complete.expr(), 1.expr()); - // next is gas_price - cb.require_equal( - "next field is gas_price", - meta.query_advice(tag, Rotation::next()), - RlpTxFieldTag::GasPrice.expr(), - ); - - // TODO: decodable == 0 < bytes[0] <= 0x88, using lookup?? - // i.e., lookup nonce rlp_type table, should be single or short - - cb.gate(q_fields[RlpTxFieldTag::Nonce].expr() * meta.query_selector(q_enable)) - }); - - // gas price - meta.create_gate("Gas price", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let complete = meta.query_advice(complete, Rotation::cur()); - let rlp_types = rlp_types - .iter() - .map(|rlp_type| meta.query_advice(*rlp_type, Rotation::cur())) - .collect::>(); - - let bytes = bytes - .iter() - .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) - .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); - - cb.require_equal("gas price tag", tag_cur, RlpTxFieldTag::GasPrice.expr()); - // next is gas_price - cb.require_equal( - "next field is gas_limit", - meta.query_advice(tag, Rotation::next()), - RlpTxFieldTag::Gas.expr(), - ); - - cb.require_equal( - "decodable if not null", - decodable, - not::expr(rlp_types[RlpDecodeTypeTag::NullValue].expr()), - ); - - cb.gate(q_fields[RlpTxFieldTag::GasPrice].expr() * meta.query_selector(q_enable)) - }); - - // Gas - meta.create_gate("Gas", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let complete = meta.query_advice(complete, Rotation::cur()); - let rlp_types = rlp_types - .iter() - .map(|rlp_type| meta.query_advice(*rlp_type, Rotation::cur())) - .collect::>(); - let bytes = bytes - .iter() - .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) - .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); - - cb.require_equal("tag", tag_cur, RlpTxFieldTag::Gas.expr()); - cb.require_equal("field completed", complete.expr(), 1.expr()); - cb.require_equal( - "next field is To", - meta.query_advice(tag, Rotation::next()), - RlpTxFieldTag::To.expr(), - ); - - cb.require_equal( - "decodable if not null", - decodable, - not::expr(rlp_types[RlpDecodeTypeTag::NullValue].expr()), - ); - - cb.gate(q_fields[RlpTxFieldTag::Gas].expr() * meta.query_selector(q_enable)) - }); - - // To - meta.create_gate("To", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let complete = meta.query_advice(complete, Rotation::cur()); - let bytes = bytes - .iter() - .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) - .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); - - cb.require_equal("tag", tag_cur, RlpTxFieldTag::To.expr()); - cb.require_equal("field completed", complete.expr(), 1.expr()); - cb.require_equal( - "next field is Value", - meta.query_advice(tag, Rotation::next()), - RlpTxFieldTag::Value.expr(), - ); - - // TODO: Lookup fix length 0xa0/0x80 - cb.condition(decodable.expr(), |cb| { - cb.require_in_set( - "0x94 or 0x80", - bytes[0].expr(), - vec![148.expr(), 128.expr()], - ); - }); - - cb.gate(q_fields[RlpTxFieldTag::To].expr() * meta.query_selector(q_enable)) - }); - - // Value - meta.create_gate("Value", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let complete = meta.query_advice(complete, Rotation::cur()); - let bytes = bytes - .iter() - .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) - .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); - - cb.require_equal("tag", tag_cur, RlpTxFieldTag::Value.expr()); - cb.require_equal("field completed", complete.expr(), 1.expr()); - cb.require_equal( - "next field is Data", - meta.query_advice(tag, Rotation::next()), - RlpTxFieldTag::Data.expr(), - ); - - cb.gate(q_fields[RlpTxFieldTag::Value].expr() * meta.query_selector(q_enable)) - }); - - // Data - meta.create_gate("Data", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let complete = meta.query_advice(complete, Rotation::cur()); - let bytes = bytes - .iter() - .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) - .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); - - cb.require_equal("tag", tag_cur, RlpTxFieldTag::Data.expr()); - cb.condition(complete, |cb| { - cb.require_equal( - "next field is SignV", - meta.query_advice(tag, Rotation::next()), - RlpTxFieldTag::SignV.expr(), - ); - }); - - cb.gate(q_fields[RlpTxFieldTag::Data].expr() * meta.query_selector(q_enable)) - }); - - // V - meta.create_gate("SignV", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let complete = meta.query_advice(complete, Rotation::cur()); - let bytes = bytes - .iter() - .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) - .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); - - cb.require_equal("tag", tag_cur, RlpTxFieldTag::SignV.expr()); - cb.require_equal("field completed", complete.expr(), 1.expr()); - cb.require_equal( - "next field is SignR", - meta.query_advice(tag, Rotation::next()), - RlpTxFieldTag::SignR.expr(), - ); - - cb.gate(q_fields[RlpTxFieldTag::SignV].expr() * meta.query_selector(q_enable)) - }); - - // R - meta.create_gate("SignR", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let complete = meta.query_advice(complete, Rotation::cur()); - let bytes = bytes - .iter() - .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) - .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); - - cb.require_equal("tag", tag_cur, RlpTxFieldTag::SignR.expr()); - cb.require_equal("field completed", complete.expr(), 1.expr()); - - cb.condition(decodable.expr(), |cb| { - cb.require_equal( - "decodable if valid rlp header", - bytes[0].expr(), - 0xa0.expr(), - ) - }); - - // next is signS - cb.require_equal( - "next field is SignR", - meta.query_advice(tag, Rotation::next()), - RlpTxFieldTag::SignS.expr(), - ); - - cb.gate(q_fields[RlpTxFieldTag::SignR].expr() * meta.query_selector(q_enable)) - }); - - // S - meta.create_gate("SignS", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let complete = meta.query_advice(complete, Rotation::cur()); - let bytes = bytes - .iter() - .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) - .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); - - cb.require_equal("tag", tag_cur, RlpTxFieldTag::SignS.expr()); - cb.require_equal("field completed", complete.expr(), 1.expr()); - // next is a new tx or padding - cb.require_in_set( - "next field is Nonce or Padding", - meta.query_advice(tag, Rotation::next()), - vec![ - RlpTxFieldTag::TxRlpHeader.expr(), - RlpTxFieldTag::Padding.expr(), - ], - ); - - cb.gate(q_fields[RlpTxFieldTag::SignS].expr() * meta.query_selector(q_enable)) - }); - // padding meta.create_gate("Padding", |meta| { let mut cb = BaseConstraintBuilder::default(); @@ -1041,13 +705,11 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let length = meta.query_advice(rlp_tag_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); - let value = meta.query_advice(value, Rotation::cur()); let acc_rlc_value = meta.query_advice(acc_rlc_value, Rotation::cur()); - let bytes = bytes + let bytes_values = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); let q_last = meta.query_fixed(q_last, Rotation::cur()); let q_fields = q_fields .iter() @@ -1056,12 +718,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_equal("tag", tag_cur, RlpTxFieldTag::Padding.expr()); cb.require_equal("field completed", complete.expr(), 1.expr()); - // next is a new tx or padding - cb.require_equal( - "next field is Padding", - meta.query_advice(tag, Rotation::next()), - RlpTxFieldTag::Padding.expr(), - ); cb.require_zero("padding has no r_mult", r_mult); cb.require_zero("padding has no length", length); cb.require_zero("padding has no remain length", remain_length); @@ -1070,6 +726,9 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { meta.query_advice(rlp_remain_length, Rotation::prev()), ); cb.require_equal("padding has no rlc (all 0)", acc_rlc_value, 0.expr()); + bytes_values.iter().for_each(|byte| { + cb.require_zero("padding has no bytes", byte.expr()); + }); cb.gate( q_fields[RlpTxFieldTag::Padding].expr() @@ -1086,17 +745,13 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let length = meta.query_advice(rlp_tag_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); - let value = meta.query_advice(value, Rotation::cur()); let acc_rlc_value = meta.query_advice(acc_rlc_value, Rotation::cur()); - let bytes = bytes - .iter() - .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) - .collect::>(); let decodable = meta.query_advice(decodable, Rotation::cur()); let valid = meta.query_advice(valid, Rotation::cur()); let q_enable = meta.query_selector(q_enable); let q_last = meta.query_fixed(q_last, Rotation::cur()); + cb.require_equal("completed at last", complete, 1.expr()); cb.require_equal("padding at last", tag_cur, RlpTxFieldTag::Padding.expr()); cb.require_equal("padding has no r_mult", r_mult, 0.expr()); cb.require_equal("padding has no length", length, 0.expr()); @@ -1104,7 +759,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_equal("padding has no rlc (all 0)", acc_rlc_value, 0.expr()); cb.require_equal("valid == decodable", valid, decodable); - cb.gate(q_last) + cb.gate(q_last * q_enable) }); Self { @@ -1112,7 +767,8 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { tx_type, tag, complete, - rlp_types, + rlp_type, + is_rlp_type, rlp_tag_length, tag_bytes_in_row, r_mult, @@ -1142,6 +798,19 @@ impl RlpDecoderCircuitConfig { self.name_row_members(region); for wit in wits { self.assign_row(region, offset, wit)?; + + self.is_rlp_type + .iter() + .enumerate() + .try_for_each(|(idx, config)| { + let chip = IsEqualChip::construct(config.clone()); + chip.assign( + region, + offset, + Value::known(F::from(wit.rlp_type as u64)), + Value::known(F::from(idx as u64)), + ) + })?; offset += 1; } Ok(()) @@ -1152,9 +821,7 @@ impl RlpDecoderCircuitConfig { region.name_column(|| "config.tx_type", self.tx_type); region.name_column(|| "config.tag", self.tag); region.name_column(|| "config.complete", self.complete); - for (i, rlp_type) in self.rlp_types.iter().enumerate() { - region.name_column(|| format!("config.rlp_types[{}]", i), *rlp_type); - } + region.name_column(|| "config.rlp_types", self.rlp_type); region.name_column(|| "config.rlp_tag_length", self.rlp_tag_length); region.name_column(|| "config.rlp_remain_length", self.rlp_remain_length); region.name_column(|| "config.r_mult", self.r_mult); @@ -1197,14 +864,12 @@ impl RlpDecoderCircuitConfig { offset, || Value::known(F::from(w.complete)), )?; - for (i, rlp_type) in self.rlp_types.iter().enumerate() { - region.assign_advice( - || format!("config.rlp_types[{}]", i), - *rlp_type, - offset, - || Value::known(F::from(w.rlp_types[i])), - )?; - } + region.assign_advice( + || "config.rlp_types", + self.rlp_type, + offset, + || Value::known(F::from(w.rlp_type as u64)), + )?; region.assign_advice( || "config.rlp_tag_length", self.rlp_tag_length, @@ -1293,11 +958,6 @@ impl RlpDecoderCircuitConfig { Ok(()) } - - /// Get number of rows required. - pub fn get_num_rows_required(num_tx: usize) -> usize { - return 0; - } } /// rlp decode Circuit for verifying transaction signatures @@ -1465,50 +1125,26 @@ impl Circuit for RlpDecoderCircuit { } } -fn generate_rlp_type_witness( - header_byte: u8, -) -> ([bool; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], bool) { - let mut rlp_types = [false; RlpDecodeTypeTag::RlpDecodeTypeNum as usize]; +fn generate_rlp_type_witness(header_byte: u8) -> (RlpDecodeTypeTag, bool) { let mut decodable = true; - match header_byte { - 0x00..=0x7f => { - rlp_types[RlpDecodeTypeTag::SingleByte as usize] = true; - } - 0x80 => { - rlp_types[RlpDecodeTypeTag::NullValue as usize] = true; - } - 0x81..=0xb7 => { - rlp_types[RlpDecodeTypeTag::ShortString as usize] = true; - } - 0xb8 => { - rlp_types[RlpDecodeTypeTag::LongString1 as usize] = true; - } - 0xb9 => { - rlp_types[RlpDecodeTypeTag::LongString2 as usize] = true; - } - 0xba => { - rlp_types[RlpDecodeTypeTag::LongString3 as usize] = true; - } - 0xc0 => { - rlp_types[RlpDecodeTypeTag::EmptyList as usize] = true; - } - 0xc1..=0xf7 => { - rlp_types[RlpDecodeTypeTag::ShortList as usize] = true; - } - 0xf8 => { - rlp_types[RlpDecodeTypeTag::LongList1 as usize] = true; - } - 0xf9 => { - rlp_types[RlpDecodeTypeTag::LongList2 as usize] = true; - } - 0xfa => { - rlp_types[RlpDecodeTypeTag::LongList3 as usize] = true; - } + let rlp_type = match header_byte { + 0x00..=0x7f => RlpDecodeTypeTag::SingleByte, + 0x80 => RlpDecodeTypeTag::NullValue, + 0x81..=0xb7 => RlpDecodeTypeTag::ShortString, + 0xb8 => RlpDecodeTypeTag::LongString1, + 0xb9 => RlpDecodeTypeTag::LongString2, + 0xba => RlpDecodeTypeTag::LongString3, + 0xc0 => RlpDecodeTypeTag::EmptyList, + 0xc1..=0xf7 => RlpDecodeTypeTag::ShortList, + 0xf8 => RlpDecodeTypeTag::LongList1, + 0xf9 => RlpDecodeTypeTag::LongList2, + 0xfa => RlpDecodeTypeTag::LongList3, _ => { decodable = false; + RlpDecodeTypeTag::NullValue } - } - (rlp_types, decodable) + }; + (rlp_type, decodable) } fn generate_q_fields_witness(tag: &RlpTxFieldTag) -> [bool; LEGACY_TX_FIELD_NUM as usize] { @@ -1536,12 +1172,8 @@ fn generate_rlp_row_witness( rlp_remain_length: usize, ) -> Vec> { let mut witness = vec![]; - let (mut rlp_types, decodable) = generate_rlp_type_witness(raw_bytes[0]); - let partial_rlp_types = { - let mut tmp = [false; RlpDecodeTypeTag::RlpDecodeTypeNum as usize]; - tmp[RlpDecodeTypeTag::PartialRlp as usize] = true; - tmp - }; + let (mut rlp_type, decodable) = generate_rlp_type_witness(raw_bytes[0]); + let partial_rlp_type = RlpDecodeTypeTag::PartialRlp; let q_fields = generate_q_fields_witness(tag); let rlp_tag_len = raw_bytes.len(); let mut prev_rlp_remain_length = rlp_remain_length; @@ -1557,7 +1189,7 @@ fn generate_rlp_row_witness( tx_type: RlpTxTypeTag::TxLegacyType, tag: tag.clone(), complete: false, - rlp_types: rlp_types, + rlp_type: rlp_type, rlp_tag_length: tag_remain_length as u64, tag_bytes_in_row: MAX_BYTE_COLUMN_NUM as u8, r_mult: r.pow(&[MAX_BYTE_COLUMN_NUM as u64, 0, 0, 0]), @@ -1575,14 +1207,14 @@ fn generate_rlp_row_witness( raw_bytes_offset += MAX_BYTE_COLUMN_NUM; tag_remain_length -= MAX_BYTE_COLUMN_NUM; prev_rlp_remain_length -= MAX_BYTE_COLUMN_NUM; - rlp_types = partial_rlp_types; + rlp_type = partial_rlp_type; } temp_witness_vec.push(RlpDecoderCircuitConfigWitness:: { tx_id: tx_id, tx_type: RlpTxTypeTag::TxLegacyType, tag: tag.clone(), complete: true, - rlp_types: rlp_types, + rlp_type: rlp_type, rlp_tag_length: tag_remain_length as u64, tag_bytes_in_row: tag_remain_length as u8, r_mult: r.pow(&[tag_remain_length as u64, 0, 0, 0]), @@ -1896,7 +1528,7 @@ fn complete_paddings( tx_type: RlpTxTypeTag::TxLegacyType, tag: RlpTxFieldTag::Padding, complete: true, - rlp_types: [false; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], + rlp_type: RlpDecodeTypeTag::DoNothing, rlp_tag_length: 0, tag_bytes_in_row: 0, r_mult: F::zero(), @@ -2246,7 +1878,6 @@ mod rlp_decode_circuit_tests { mod bench { use super::*; use ark_std::{end_timer, start_timer}; - use eth_types::Bytes; use halo2_proofs::{ halo2curves::bn256::{Bn256, Fr, G1Affine}, plonk::{create_proof, keygen_pk, keygen_vk, verify_proof}, diff --git a/zkevm-circuits/src/rlp_decoder_tables.rs b/zkevm-circuits/src/rlp_decoder_tables.rs index d38cdd3fbc..3bc3e0b7d1 100644 --- a/zkevm-circuits/src/rlp_decoder_tables.rs +++ b/zkevm-circuits/src/rlp_decoder_tables.rs @@ -1,21 +1,10 @@ //! The rlp decoding tables implementation. -use std::marker::PhantomData; - use crate::{ - evm_circuit::util::{constraint_builder::BaseConstraintBuilder, rlc}, - impl_expr, - rlp_decoder::{RlpDecodeTypeTag, RlpTxFieldTag, MAX_BYTE_COLUMN_NUM}, - table::{KeccakTable, TxTable}, - util::{log2_ceil, Challenges, Expr, SubCircuit, SubCircuitConfig}, - witness, -}; -use eth_types::{Field, Signature, Transaction, Word}; -use ethers_core::{ - types::TransactionRequest, - utils::rlp::{self, PayloadInfo}, + rlp_decoder::{RlpDecodeTypeTag, RlpTxFieldTag, RlpTxTypeTag, MAX_BYTE_COLUMN_NUM}, + util::Challenges, }; -use gadgets::util::{and, not}; +use eth_types::Field; pub use halo2_proofs::halo2curves::{ group::{ ff::{Field as GroupField, PrimeField}, @@ -25,11 +14,8 @@ pub use halo2_proofs::halo2curves::{ secp256k1::{self, Secp256k1Affine, Secp256k1Compressed}, }; use halo2_proofs::{ - circuit::{Layouter, Region, SimpleFloorPlanner, Value}, - plonk::{ - Advice, Circuit, Column, ConstraintSystem, Error, Expression, Fixed, SecondPhase, Selector, - }, - poly::Rotation, + circuit::{Layouter, Region, Value}, + plonk::{Column, ConstraintSystem, Error, Fixed}, }; /// Rlp encoding types @@ -59,6 +45,7 @@ impl RlpDecodeRule { /// Get the length of the RLP encoding type pub fn load( &self, + tx_type: &RlpTxTypeTag, tx_field_tag: &RlpTxFieldTag, table: &RlpDecoderTable, region: &mut Region<'_, F>, @@ -68,47 +55,51 @@ impl RlpDecodeRule { (0..256u64) .map(|i| { let (rlp_type, decodable, length) = match self { - RlpDecodeRule::Padding => (RlpDecodeTypeTag::SingleByte, true, 0u64), + RlpDecodeRule::Padding => (RlpDecodeTypeTag::DoNothing, true, 0u64), RlpDecodeRule::Empty => match i { 0x80 => (RlpDecodeTypeTag::SingleByte, true, 1u64), - _ => (RlpDecodeTypeTag::ShortString, false, 0u64), + _ => (RlpDecodeTypeTag::DoNothing, false, 0u64), }, RlpDecodeRule::Uint64 => match i { + // 0 is error: non-canonical integer (leading zero bytes) for uint64 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true, 1u64), 0x81..=0x88 => (RlpDecodeTypeTag::ShortString, true, i - 0x80 + 1), - _ => (RlpDecodeTypeTag::ShortString, false, 0u64), + _ => (RlpDecodeTypeTag::DoNothing, false, 0u64), }, RlpDecodeRule::Uint96 => match i { + // 0 is error: non-canonical integer (leading zero bytes) for uint96 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true, 1), 0x81..=0x8c => (RlpDecodeTypeTag::ShortString, true, i - 0x80 + 1), - _ => (RlpDecodeTypeTag::ShortString, false, 0), + _ => (RlpDecodeTypeTag::DoNothing, false, 0), }, RlpDecodeRule::Address => match i { 0x94 => (RlpDecodeTypeTag::ShortString, true, 20 + 1), - _ => (RlpDecodeTypeTag::ShortString, false, 0), + _ => (RlpDecodeTypeTag::DoNothing, false, 0), }, RlpDecodeRule::Bytes32 => match i { + // TODO: what if sig is less then 32 bytes? 0xa0 => (RlpDecodeTypeTag::ShortString, true, 20 + 1), - _ => (RlpDecodeTypeTag::ShortString, false, 0), + _ => (RlpDecodeTypeTag::DoNothing, false, 0), }, RlpDecodeRule::Bytes48K => match i { - 0 => (RlpDecodeTypeTag::SingleByte, false, 1), - 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true, 1), + 0 => (RlpDecodeTypeTag::SingleByte, true, 1), // 0x00 + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true, 1), // 0x01..=0x80 0x81..=0xbf => (RlpDecodeTypeTag::ShortString, true, i - 0x80 + 1), - _ => (RlpDecodeTypeTag::ShortString, false, 0), + _ => (RlpDecodeTypeTag::DoNothing, false, 0), }, RlpDecodeRule::EmptyList => match i { 0xc0 => (RlpDecodeTypeTag::ShortString, false, 0), - _ => (RlpDecodeTypeTag::ShortString, false, 0), + _ => (RlpDecodeTypeTag::DoNothing, false, 0), }, RlpDecodeRule::LongList => match i { 0xf8 => (RlpDecodeTypeTag::LongList1, true, 2), 0xf9 => (RlpDecodeTypeTag::LongList2, true, 3), 0xfa => (RlpDecodeTypeTag::LongList3, true, 4), - _ => (RlpDecodeTypeTag::LongList1, false, 0), + _ => (RlpDecodeTypeTag::DoNothing, false, 0), }, }; [ + *tx_type as u64, *tx_field_tag as u64, rlp_type as u64, i, @@ -116,7 +107,7 @@ impl RlpDecodeRule { length, ] }) - .collect::>() + .collect::>() }; let mut offset = offset; @@ -125,6 +116,7 @@ impl RlpDecodeRule { rule_table_row .iter() .zip([ + table.tx_type, table.tx_field_tag, table.rlp_type, table.byte_0, @@ -150,6 +142,8 @@ impl RlpDecodeRule { /// Table that contains the fields of all possible RLP decodable fields #[derive(Clone, Debug)] pub struct RlpDecoderTable { + /// The tx type tag + pub tx_type: Column, /// The tx field tag pub tx_field_tag: Column, /// The RLP type @@ -166,6 +160,7 @@ impl RlpDecoderTable { /// Construct a new RlpDecoderTable pub fn construct(meta: &mut ConstraintSystem) -> Self { Self { + tx_type: meta.fixed_column(), tx_field_tag: meta.fixed_column(), rlp_type: meta.fixed_column(), byte_0: meta.fixed_column(), @@ -186,28 +181,80 @@ impl RlpDecoderTable { challenges: &Challenges>, ) -> Result<(), Error> { // make a list with all member of rlpTxFieldTag literally - let rlp_tx_field_tag_list: Vec<(RlpTxFieldTag, RlpDecodeRule)> = vec![ - (RlpTxFieldTag::TxListRlpHeader, RlpDecodeRule::LongList), - (RlpTxFieldTag::TxRlpHeader, RlpDecodeRule::LongList), - (RlpTxFieldTag::Nonce, RlpDecodeRule::Uint96), - (RlpTxFieldTag::GasPrice, RlpDecodeRule::Uint96), - (RlpTxFieldTag::Gas, RlpDecodeRule::Uint96), - (RlpTxFieldTag::To, RlpDecodeRule::Address), - (RlpTxFieldTag::To, RlpDecodeRule::Empty), - (RlpTxFieldTag::Value, RlpDecodeRule::Uint96), - (RlpTxFieldTag::Data, RlpDecodeRule::Bytes48K), - (RlpTxFieldTag::SignV, RlpDecodeRule::Uint96), - (RlpTxFieldTag::SignR, RlpDecodeRule::Bytes32), - (RlpTxFieldTag::SignS, RlpDecodeRule::Bytes48K), - (RlpTxFieldTag::Padding, RlpDecodeRule::Padding), + let rlp_tx_field_tag_list: Vec<(RlpTxTypeTag, RlpTxFieldTag, RlpDecodeRule)> = vec![ + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::TxListRlpHeader, + RlpDecodeRule::LongList, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::TxRlpHeader, + RlpDecodeRule::LongList, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::Nonce, + RlpDecodeRule::Uint96, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::GasPrice, + RlpDecodeRule::Uint96, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::Gas, + RlpDecodeRule::Uint96, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::To, + RlpDecodeRule::Address, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::To, + RlpDecodeRule::Empty, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::Value, + RlpDecodeRule::Uint96, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::Data, + RlpDecodeRule::Bytes48K, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::SignV, + RlpDecodeRule::Uint96, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::SignR, + RlpDecodeRule::Bytes32, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::SignS, + RlpDecodeRule::Bytes48K, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::Padding, + RlpDecodeRule::Padding, + ), ]; layouter.assign_region( || "load rlp decoder table", |mut region| { let mut offset = 0; - for (tx_field_tag, decode_rule) in rlp_tx_field_tag_list.iter() { - decode_rule.load(tx_field_tag, self, &mut region, offset)?; + for (tx_type, tx_field_tag, decode_rule) in rlp_tx_field_tag_list.iter() { + decode_rule.load(tx_type, tx_field_tag, self, &mut region, offset)?; offset += 256; } Ok(()) @@ -327,7 +374,7 @@ impl RMultPowTable { let mut randomness = F::zero(); challenges.keccak_input().map(|r| randomness = r); - (0..MAX_BYTE_COLUMN_NUM).try_for_each(|i| { + (0..=MAX_BYTE_COLUMN_NUM).try_for_each(|i| { layouter.assign_region( || "load rlp r_mult table", |mut region| { From e3617d39638234534fbc3d30d8f458fb6b8e2a0f Mon Sep 17 00:00:00 2001 From: smtmfft Date: Wed, 24 May 2023 04:01:47 +0000 Subject: [PATCH 06/21] revert back to conditional cells, due to bad perf of is_equal gadget --- zkevm-circuits/src/rlp_decoder.rs | 205 ++++++++++++++++++------------ 1 file changed, 121 insertions(+), 84 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 58727dc8e5..b6ef8ccda5 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -15,10 +15,7 @@ use ethers_core::{ types::TransactionRequest, utils::rlp::{self, PayloadInfo}, }; -use gadgets::{ - is_equal::{IsEqualChip, IsEqualConfig, IsEqualInstruction}, - util::{and, not}, -}; +use gadgets::util::{and, not, sum}; use halo2_proofs::{ circuit::{Layouter, Region, SimpleFloorPlanner, Value}, plonk::{ @@ -200,8 +197,6 @@ pub struct RlpDecoderCircuitConfigWitness { pub decodable: bool, /// valid, 0 for invalid, 1 for valid, should be == decodable at the end of the circuit pub valid: bool, - /// dynamic selector for fields - pub q_fields: [bool; LEGACY_TX_FIELD_NUM as usize], /// full chip enable pub q_enable: bool, /// the begining @@ -224,7 +219,7 @@ pub struct RlpDecoderCircuitConfig { /// rlp types: [single, short, long, very_long, fixed(33)] pub rlp_type: Column, /// rlp_type checking gadget - pub is_rlp_type: [IsEqualConfig; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], + pub q_rlp_types: [Column; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], /// rlp_tag_length, the length of this rlp field pub rlp_tag_length: Column, /// remained rows, for n < 33 fields, it is n, for m > 33 fields, it is 33 and next row is @@ -304,20 +299,19 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let q_last = meta.fixed_column(); // type checking - let is_rlp_type: [IsEqualConfig; RlpDecodeTypeTag::RlpDecodeTypeNum as usize] = (0 + let q_rlp_types: [Column; RlpDecodeTypeTag::RlpDecodeTypeNum as usize] = (0 ..RlpDecodeTypeTag::RlpDecodeTypeNum as usize) - .map(|t| { - IsEqualChip::configure( - meta, - |meta| meta.query_selector(q_enable), - |meta| meta.query_advice(rlp_type, Rotation::cur()), - |_| t.expr(), - ) - }) - .collect::>>() + .map(|_| meta.advice_column()) + .collect::>>() .try_into() .unwrap(); + macro_rules! rlp_type_enabled { + ($meta:expr, $rlp_type:expr) => { + $meta.query_advice(q_rlp_types[$rlp_type], Rotation::cur()) + }; + } + // TODO: lookup bytes range table // TODO: lookup q_fields table @@ -330,8 +324,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let decodable = meta.query_advice(decodable, Rotation::cur()); let q_enable = meta.query_selector(q_enable); - let is_not_partial = - not::expr(is_rlp_type[RlpDecodeTypeTag::PartialRlp as usize].is_equal()); + let is_not_partial = not::expr(rlp_type_enabled!(meta, RlpDecodeTypeTag::PartialRlp)); let tx_type_in_table = meta.query_fixed(args.rlp_decoder_table.tx_type, Rotation::cur()); @@ -394,6 +387,44 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { meta.create_gate("common constraints for all rows", |meta| { let mut cb = BaseConstraintBuilder::default(); + // bind the rlp_type and rlp_type selector + q_rlp_types.iter().enumerate().for_each(|(i, q_rlp_type)| { + let q_rlp_type_enabled = meta.query_advice(*q_rlp_type, Rotation::cur()); + cb.require_boolean("q_rlp_types are bool", q_rlp_type_enabled.expr()); + cb.condition(q_rlp_type_enabled.expr(), |cb| { + let rlp_type = meta.query_advice(rlp_type, Rotation::cur()); + cb.require_equal("rlp type check", rlp_type, i.expr()) + }); + }); + cb.require_equal( + "1 rlp type only", + sum::expr( + q_rlp_types + .iter() + .map(|t| meta.query_advice(*t, Rotation::cur())), + ), + 1.expr(), + ); + + // bind the q_field with the field tag + q_fields.iter().enumerate().for_each(|(i, q_field)| { + let q_field_enabled = meta.query_advice(*q_field, Rotation::cur()); + cb.require_boolean("q_fields are bool", q_field_enabled.expr()); + cb.condition(q_field_enabled.expr(), |cb| { + let tag = meta.query_advice(tag, Rotation::cur()); + cb.require_equal("tag check", tag, i.expr()) + }); + }); + cb.require_equal( + "1 tx field only", + sum::expr( + q_fields + .iter() + .map(|field| meta.query_advice(*field, Rotation::cur())), + ), + 1.expr(), + ); + let valid_cur = meta.query_advice(valid, Rotation::cur()); let valid_next = meta.query_advice(valid, Rotation::next()); cb.require_equal( @@ -447,17 +478,18 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_boolean("valid", valid); // length with leading bytes - cb.condition(is_rlp_type[RlpDecodeTypeTag::DoNothing].is_equal(), |cb| { + cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::DoNothing), |cb| { cb.require_equal("0 length", rlp_tag_length_cur.clone(), 0.expr()) }); - cb.condition(is_rlp_type[RlpDecodeTypeTag::SingleByte].is_equal(), |cb| { - cb.require_equal("single length", rlp_tag_length_cur.clone(), 1.expr()) - }); - cb.condition(is_rlp_type[RlpDecodeTypeTag::NullValue].is_equal(), |cb| { + cb.condition( + rlp_type_enabled!(meta, RlpDecodeTypeTag::SingleByte), + |cb| cb.require_equal("single length", rlp_tag_length_cur.clone(), 1.expr()), + ); + cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::NullValue), |cb| { cb.require_equal("empty length", rlp_tag_length_cur.clone(), 1.expr()) }); cb.condition( - is_rlp_type[RlpDecodeTypeTag::ShortString].is_equal(), + rlp_type_enabled!(meta, RlpDecodeTypeTag::ShortString), |cb| { cb.require_equal( "ShortString length", @@ -467,7 +499,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }, ); cb.condition( - is_rlp_type[RlpDecodeTypeTag::LongString1].is_equal(), + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongString1), |cb| { cb.require_equal( "Long String 0xb8 length", @@ -477,7 +509,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }, ); cb.condition( - is_rlp_type[RlpDecodeTypeTag::LongString2].is_equal(), + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongString2), |cb| { cb.require_equal( "Long String 0xb9 length", @@ -487,7 +519,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }, ); cb.condition( - is_rlp_type[RlpDecodeTypeTag::LongString3].is_equal(), + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongString3), |cb| { cb.require_equal( "Long String 0xba length", @@ -499,31 +531,34 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ) }, ); - cb.condition(is_rlp_type[RlpDecodeTypeTag::EmptyList].is_equal(), |cb| { + cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::EmptyList), |cb| { cb.require_equal("empty list length", rlp_tag_length_cur.clone(), 1.expr()) }); - cb.condition(is_rlp_type[RlpDecodeTypeTag::ShortList].is_equal(), |cb| { + cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::ShortList), |cb| { cb.require_equal( "short length", rlp_tag_length_cur.clone(), byte_cells_cur[0].expr() - 0xc0.expr() + 1.expr(), ) }); - cb.condition(is_rlp_type[RlpDecodeTypeTag::PartialRlp].is_equal(), |cb| { - cb.require_equal( - "length = prev_length - prev_bytes_in_row", - rlp_tag_length_cur.clone(), - meta.query_advice(rlp_tag_length, Rotation::prev()) - - meta.query_advice(tag_bytes_in_row, Rotation::prev()), - ); + cb.condition( + rlp_type_enabled!(meta, RlpDecodeTypeTag::PartialRlp), + |cb| { + cb.require_equal( + "length = prev_length - prev_bytes_in_row", + rlp_tag_length_cur.clone(), + meta.query_advice(rlp_tag_length, Rotation::prev()) + - meta.query_advice(tag_bytes_in_row, Rotation::prev()), + ); - cb.require_zero( - "above row is incomplete", - meta.query_advice(complete, Rotation::prev()), - ); + cb.require_zero( + "above row is incomplete", + meta.query_advice(complete, Rotation::prev()), + ); - cb.require_equal("only data has partial rlp", tag, RlpTxFieldTag::Data.expr()); - }); + cb.require_equal("only data has partial rlp", tag, RlpTxFieldTag::Data.expr()); + }, + ); cb.condition(complete_cur.expr(), |cb| { cb.require_equal( @@ -586,7 +621,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_zero("0 tx_tag", tag_cur); cb.require_equal("field completed", complete.expr(), 1.expr()); - cb.condition(is_rlp_type[RlpDecodeTypeTag::LongList1].is_equal(), |cb| { + cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList1), |cb| { cb.require_equal( "long length: f8 + 1", remain_length.expr(), @@ -594,16 +629,15 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ) // TODO: byte_cells_cur[1] > 55 }); - cb.condition(is_rlp_type[RlpDecodeTypeTag::LongList2].is_equal(), |cb| { + cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList2), |cb| { cb.require_equal( "long length: f9 + 2", remain_length.expr(), byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr(), ) - // TODO: byte_cells_cur[1] != 0 }); - cb.condition(is_rlp_type[RlpDecodeTypeTag::LongList3].is_equal(), |cb| { + cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList3), |cb| { cb.require_equal( "long length: fa + 3", remain_length.expr(), @@ -768,7 +802,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { tag, complete, rlp_type, - is_rlp_type, + q_rlp_types, rlp_tag_length, tag_bytes_in_row, r_mult, @@ -798,19 +832,6 @@ impl RlpDecoderCircuitConfig { self.name_row_members(region); for wit in wits { self.assign_row(region, offset, wit)?; - - self.is_rlp_type - .iter() - .enumerate() - .try_for_each(|(idx, config)| { - let chip = IsEqualChip::construct(config.clone()); - chip.assign( - region, - offset, - Value::known(F::from(wit.rlp_type as u64)), - Value::known(F::from(idx as u64)), - ) - })?; offset += 1; } Ok(()) @@ -865,11 +886,27 @@ impl RlpDecoderCircuitConfig { || Value::known(F::from(w.complete)), )?; region.assign_advice( - || "config.rlp_types", + || "config.rlp_type", self.rlp_type, offset, || Value::known(F::from(w.rlp_type as u64)), )?; + self.q_rlp_types.iter().enumerate().try_for_each(|(i, q)| { + region + .assign_advice( + || format!("config.q_rlp_types[{}]", i), + *q, + offset, + || { + if i as u64 == w.rlp_type as u64 { + Value::known(F::one()) + } else { + Value::known(F::zero()) + } + }, + ) + .map(|_| ()) + })?; region.assign_advice( || "config.rlp_tag_length", self.rlp_tag_length, @@ -932,14 +969,25 @@ impl RlpDecoderCircuitConfig { offset, || Value::known(F::from(w.valid)), )?; - for (i, q_field) in self.q_fields.iter().enumerate() { - region.assign_advice( - || format!("config.q_fields[{}]", i), - *q_field, - offset, - || Value::known(F::from(w.q_fields[i])), - )?; - } + self.q_fields + .iter() + .enumerate() + .try_for_each(|(i, q_field)| { + region + .assign_advice( + || format!("config.q_fields[{}]", i), + *q_field, + offset, + || { + if i == w.tag as usize { + Value::known(F::one()) + } else { + Value::known(F::zero()) + } + }, + ) + .map(|_| ()) + })?; region.assign_fixed( || "config.q_first", self.q_first, @@ -1147,15 +1195,6 @@ fn generate_rlp_type_witness(header_byte: u8) -> (RlpDecodeTypeTag, bool) { (rlp_type, decodable) } -fn generate_q_fields_witness(tag: &RlpTxFieldTag) -> [bool; LEGACY_TX_FIELD_NUM as usize] { - let mut q_fields = [false; LEGACY_TX_FIELD_NUM as usize]; - q_fields[*tag as usize] = true; - if tag > &RlpTxFieldTag::Padding { - unreachable!("1559 not support now") - } - q_fields -} - fn generate_fields_witness_len(tag: &RlpTxFieldTag, payload: &PayloadInfo) -> usize { match tag { RlpTxFieldTag::TxListRlpHeader => payload.header_len, @@ -1174,7 +1213,6 @@ fn generate_rlp_row_witness( let mut witness = vec![]; let (mut rlp_type, decodable) = generate_rlp_type_witness(raw_bytes[0]); let partial_rlp_type = RlpDecodeTypeTag::PartialRlp; - let q_fields = generate_q_fields_witness(tag); let rlp_tag_len = raw_bytes.len(); let mut prev_rlp_remain_length = rlp_remain_length; @@ -1199,7 +1237,6 @@ fn generate_rlp_row_witness( bytes: raw_bytes[..MAX_BYTE_COLUMN_NUM].to_vec(), decodable: decodable, valid: true, - q_fields: q_fields, q_enable: true, q_first: false, q_last: false, @@ -1224,7 +1261,6 @@ fn generate_rlp_row_witness( bytes: raw_bytes[raw_bytes_offset..].to_vec(), decodable: decodable, valid: true, - q_fields: q_fields, q_enable: true, q_first: false, q_last: false, @@ -1538,7 +1574,6 @@ fn complete_paddings( bytes: [0; MAX_BYTE_COLUMN_NUM].to_vec(), decodable: true, valid: true, - q_fields: [false; LEGACY_TX_FIELD_NUM as usize], q_enable: true, q_first: false, q_last: i == num_padding_to_last_row - 1, @@ -1801,7 +1836,9 @@ mod rlp_decode_circuit_tests { } #[test] + #[ignore] fn tx_circuit_0tx() { + // 0xc0 is for invalid case. assert_eq!(run::(vec![]), Ok(())); } @@ -1898,7 +1935,7 @@ mod bench { use std::env::var; #[test] - fn bench_super_circuit_prover() { + fn bench_rlp_decode_circuit_prover() { let setup_prfx = "crate::constants::SETUP"; let proof_gen_prfx = "crate::constants::PROOFGEN_PREFIX"; let proof_ver_prfx = "crate::constants::PROOFVER_PREFIX"; From 34c46f3b9c6d0af118664fc0ff38cc9c47af3fb3 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Wed, 24 May 2023 12:09:13 +0000 Subject: [PATCH 07/21] code refine --- zkevm-circuits/src/rlp_decoder.rs | 8 +-- zkevm-circuits/src/rlp_decoder_tables.rs | 68 +++++++++++++----------- 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index b6ef8ccda5..e9b7da91a1 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -313,7 +313,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { } // TODO: lookup bytes range table - // TODO: lookup q_fields table // lookup rlp_types table // TODO: bytes[1] as prefix of len also need to be constrainted @@ -1189,7 +1188,7 @@ fn generate_rlp_type_witness(header_byte: u8) -> (RlpDecodeTypeTag, bool) { 0xfa => RlpDecodeTypeTag::LongList3, _ => { decodable = false; - RlpDecodeTypeTag::NullValue + RlpDecodeTypeTag::DoNothing } }; (rlp_type, decodable) @@ -1234,7 +1233,8 @@ fn generate_rlp_row_witness( rlp_remain_length: prev_rlp_remain_length - MAX_BYTE_COLUMN_NUM, value: F::zero(), acc_rlc_value: F::zero(), - bytes: raw_bytes[..MAX_BYTE_COLUMN_NUM].to_vec(), + bytes: raw_bytes[raw_bytes_offset..raw_bytes_offset + MAX_BYTE_COLUMN_NUM] + .to_vec(), decodable: decodable, valid: true, q_enable: true, @@ -1635,7 +1635,7 @@ impl From for SignedTransaction { s: mock_tx.s.expect("tx expected to be signed"), v: mock_tx.v.expect("tx expected to be signed").as_u64(), }; - let (rlp_unsigned, rlp_signed) = { + let (_rlp_unsigned, _rlp_signed) = { let mut legacy_tx = TransactionRequest::new() .from(mock_tx.from.address()) .nonce(mock_tx.nonce) diff --git a/zkevm-circuits/src/rlp_decoder_tables.rs b/zkevm-circuits/src/rlp_decoder_tables.rs index 3bc3e0b7d1..b2f6d4e402 100644 --- a/zkevm-circuits/src/rlp_decoder_tables.rs +++ b/zkevm-circuits/src/rlp_decoder_tables.rs @@ -42,7 +42,14 @@ pub enum RlpDecodeRule { } impl RlpDecodeRule { - /// Get the length of the RLP encoding type + /// load the decode rult table, like.: + /// | tx_type(legacy/1559) | field | rlp type | byte[0] | decodable | + /// | legacy | nonce | uint96 | 0x00 | false | + /// | legacy | nonce | uint96 | 0x01 | true | + /// ... + /// | legacy | signS | byte32 | 0xa0 | true | + /// | legacy | signS | byte32 | 0xa1 | false | + /// ... pub fn load( &self, tx_type: &RlpTxTypeTag, @@ -54,48 +61,51 @@ impl RlpDecodeRule { let rule_table_rows = { (0..256u64) .map(|i| { - let (rlp_type, decodable, length) = match self { - RlpDecodeRule::Padding => (RlpDecodeTypeTag::DoNothing, true, 0u64), + let (rlp_type, decodable) = match self { + RlpDecodeRule::Padding => (RlpDecodeTypeTag::DoNothing, true), RlpDecodeRule::Empty => match i { - 0x80 => (RlpDecodeTypeTag::SingleByte, true, 1u64), - _ => (RlpDecodeTypeTag::DoNothing, false, 0u64), + 0x80 => (RlpDecodeTypeTag::SingleByte, true), + _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::Uint64 => match i { // 0 is error: non-canonical integer (leading zero bytes) for uint64 - 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true, 1u64), - 0x81..=0x88 => (RlpDecodeTypeTag::ShortString, true, i - 0x80 + 1), - _ => (RlpDecodeTypeTag::DoNothing, false, 0u64), + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), + 0x81..=0x88 => (RlpDecodeTypeTag::ShortString, true), + _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::Uint96 => match i { // 0 is error: non-canonical integer (leading zero bytes) for uint96 - 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true, 1), - 0x81..=0x8c => (RlpDecodeTypeTag::ShortString, true, i - 0x80 + 1), - _ => (RlpDecodeTypeTag::DoNothing, false, 0), + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), + 0x81..=0x8c => (RlpDecodeTypeTag::ShortString, true), + _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::Address => match i { - 0x94 => (RlpDecodeTypeTag::ShortString, true, 20 + 1), - _ => (RlpDecodeTypeTag::DoNothing, false, 0), + 0x94 => (RlpDecodeTypeTag::ShortString, true), + _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::Bytes32 => match i { // TODO: what if sig is less then 32 bytes? - 0xa0 => (RlpDecodeTypeTag::ShortString, true, 20 + 1), - _ => (RlpDecodeTypeTag::DoNothing, false, 0), + 0xa0 => (RlpDecodeTypeTag::ShortString, true), + _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::Bytes48K => match i { - 0 => (RlpDecodeTypeTag::SingleByte, true, 1), // 0x00 - 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true, 1), // 0x01..=0x80 - 0x81..=0xbf => (RlpDecodeTypeTag::ShortString, true, i - 0x80 + 1), - _ => (RlpDecodeTypeTag::DoNothing, false, 0), + 0 => (RlpDecodeTypeTag::SingleByte, true), // 0x00 + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), // 0x01..=0x80 + 0x81..=0xb7 => (RlpDecodeTypeTag::ShortString, true), + 0xb8 => (RlpDecodeTypeTag::LongString1, true), + 0xb9 => (RlpDecodeTypeTag::LongString2, true), + 0xba => (RlpDecodeTypeTag::LongString3, true), + _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::EmptyList => match i { - 0xc0 => (RlpDecodeTypeTag::ShortString, false, 0), - _ => (RlpDecodeTypeTag::DoNothing, false, 0), + 0xc0 => (RlpDecodeTypeTag::ShortString, false), + _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::LongList => match i { - 0xf8 => (RlpDecodeTypeTag::LongList1, true, 2), - 0xf9 => (RlpDecodeTypeTag::LongList2, true, 3), - 0xfa => (RlpDecodeTypeTag::LongList3, true, 4), - _ => (RlpDecodeTypeTag::DoNothing, false, 0), + 0xf8 => (RlpDecodeTypeTag::LongList1, true), + 0xf9 => (RlpDecodeTypeTag::LongList2, true), + 0xfa => (RlpDecodeTypeTag::LongList3, true), + _ => (RlpDecodeTypeTag::DoNothing, false), }, }; [ @@ -104,10 +114,9 @@ impl RlpDecodeRule { rlp_type as u64, i, decodable as u64, - length, ] }) - .collect::>() + .collect::>() }; let mut offset = offset; @@ -121,7 +130,6 @@ impl RlpDecodeRule { table.rlp_type, table.byte_0, table.decodable, - table.length, ]) .try_for_each(|(value, col)| { region @@ -181,7 +189,7 @@ impl RlpDecoderTable { challenges: &Challenges>, ) -> Result<(), Error> { // make a list with all member of rlpTxFieldTag literally - let rlp_tx_field_tag_list: Vec<(RlpTxTypeTag, RlpTxFieldTag, RlpDecodeRule)> = vec![ + let rlp_tx_field_decode_rules: Vec<(RlpTxTypeTag, RlpTxFieldTag, RlpDecodeRule)> = vec![ ( RlpTxTypeTag::TxLegacyType, RlpTxFieldTag::TxListRlpHeader, @@ -253,7 +261,7 @@ impl RlpDecoderTable { || "load rlp decoder table", |mut region| { let mut offset = 0; - for (tx_type, tx_field_tag, decode_rule) in rlp_tx_field_tag_list.iter() { + for (tx_type, tx_field_tag, decode_rule) in rlp_tx_field_decode_rules.iter() { decode_rule.load(tx_type, tx_field_tag, self, &mut region, offset)?; offset += 256; } From 631ae5576210f86a7a714d72bd056c135aab175c Mon Sep 17 00:00:00 2001 From: smtmfft Date: Wed, 24 May 2023 13:59:34 +0000 Subject: [PATCH 08/21] keep refing --- zkevm-circuits/src/rlp_decoder.rs | 233 +++++++++++++++--------------- 1 file changed, 113 insertions(+), 120 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index e9b7da91a1..a17377f759 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -173,16 +173,16 @@ pub struct RlpDecoderCircuitConfigWitness { /// tx_type column pub tx_type: RlpTxTypeTag, /// tag column - pub tag: RlpTxFieldTag, + pub tx_member: RlpTxFieldTag, /// complete column pub complete: bool, /// rlp types: [single, short, long, very_long, fixed(33)] pub rlp_type: RlpDecodeTypeTag, /// rlp_tag_length, the length of this rlp field - pub rlp_tag_length: u64, + pub rlp_tx_member_length: u64, /// remained rows, for n < 33 fields, it is n, for m > 33 fields, it is 33 and next row is /// partial, next_length = m - 33 - pub tag_bytes_in_row: u8, + pub rlp_bytes_in_row: u8, /// r_mult column, (length, r_mult) => @fixed pub r_mult: F, /// remain_length @@ -213,7 +213,7 @@ pub struct RlpDecoderCircuitConfig { /// tx_type column pub tx_type: Column, /// tag column - pub tag: Column, + pub tx_member: Column, /// complete column pub complete: Column, /// rlp types: [single, short, long, very_long, fixed(33)] @@ -221,13 +221,13 @@ pub struct RlpDecoderCircuitConfig { /// rlp_type checking gadget pub q_rlp_types: [Column; RlpDecodeTypeTag::RlpDecodeTypeNum as usize], /// rlp_tag_length, the length of this rlp field - pub rlp_tag_length: Column, + pub rlp_tx_member_length: Column, /// remained rows, for n < 33 fields, it is n, for m > 33 fields, it is 33 and next row is /// partial, next_length = m - 33 - pub tag_bytes_in_row: Column, + pub rlp_bytes_in_row: Column, /// r_mult column, (length, r_mult) => @fixed pub r_mult: Column, - /// remain_length + /// remain_length, to be 0 at the end. pub rlp_remain_length: Column, /// value pub value: Column, @@ -240,7 +240,7 @@ pub struct RlpDecoderCircuitConfig { /// valid, 0 for invalid, 1 for valid, should be == decodable at the end of the circuit pub valid: Column, /// dynamic selector for fields - pub q_fields: [Column; LEGACY_TX_FIELD_NUM as usize], + pub q_tx_members: [Column; LEGACY_TX_FIELD_NUM as usize], /// full chip enable pub q_enable: Selector, /// the begining @@ -273,11 +273,11 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { fn new(meta: &mut ConstraintSystem, args: Self::ConfigArgs) -> Self { let tx_id = meta.advice_column(); let tx_type = meta.advice_column(); - let tag = meta.advice_column(); + let tx_member = meta.advice_column(); let complete = meta.advice_column(); let rlp_type = meta.advice_column(); - let rlp_tag_length = meta.advice_column(); - let tag_bytes_in_row = meta.advice_column(); + let rlp_tx_member_length = meta.advice_column(); + let tx_member_bytes_in_row = meta.advice_column(); let rlp_remain_length = meta.advice_column(); let r_mult = meta.advice_column(); let value = meta.advice_column(); @@ -289,7 +289,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .unwrap(); let decodable = meta.advice_column(); let valid = meta.advice_column(); - let q_fields: [Column; LEGACY_TX_FIELD_NUM as usize] = (0..LEGACY_TX_FIELD_NUM) + let q_tx_members: [Column; LEGACY_TX_FIELD_NUM as usize] = (0..LEGACY_TX_FIELD_NUM) .map(|_| meta.advice_column()) .collect::>>() .try_into() @@ -318,7 +318,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { // TODO: bytes[1] as prefix of len also need to be constrainted meta.lookup_any("rlp decodable check", |meta| { let tx_type = meta.query_advice(tx_type, Rotation::cur()); - let tag = meta.query_advice(tag, Rotation::cur()); + let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); let byte0 = meta.query_advice(bytes[0], Rotation::cur()); let decodable = meta.query_advice(decodable, Rotation::cur()); let q_enable = meta.query_selector(q_enable); @@ -327,7 +327,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tx_type_in_table = meta.query_fixed(args.rlp_decoder_table.tx_type, Rotation::cur()); - let tag_in_table = + let tx_member_in_table = meta.query_fixed(args.rlp_decoder_table.tx_field_tag, Rotation::cur()); let byte0_in_table = meta.query_fixed(args.rlp_decoder_table.byte_0, Rotation::cur()); let decodable_in_table = @@ -337,7 +337,10 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { q_enable.expr() * is_not_partial.expr() * tx_type, tx_type_in_table, ), - (q_enable.expr() * is_not_partial.expr() * tag, tag_in_table), + ( + q_enable.expr() * is_not_partial.expr() * tx_member_cur, + tx_member_in_table, + ), ( q_enable.expr() * is_not_partial.expr() * byte0, byte0_in_table, @@ -351,23 +354,23 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { // // lookup tx_field_switch table meta.lookup_any("rlp tx field transition", |meta| { - let current_field = meta.query_advice(tag, Rotation::cur()); - let next_filed = meta.query_advice(tag, Rotation::next()); - let current_field_in_table = + let current_member = meta.query_advice(tx_member, Rotation::cur()); + let next_member = meta.query_advice(tx_member, Rotation::next()); + let curr_member_in_table = meta.query_fixed(args.tx_field_switch_table.current_tx_field, Rotation::cur()); - let next_field_in_table = + let next_member_in_table = meta.query_fixed(args.tx_field_switch_table.next_tx_field, Rotation::cur()); let q_enable = meta.query_selector(q_enable); let is_last = meta.query_fixed(q_last, Rotation::cur()); vec![ ( - and::expr([not::expr(is_last.expr()), q_enable.expr()]) * current_field, - current_field_in_table, + and::expr([not::expr(is_last.expr()), q_enable.expr()]) * current_member, + curr_member_in_table, ), ( - and::expr([not::expr(is_last.expr()), q_enable.expr()]) * next_filed, - next_field_in_table, + and::expr([not::expr(is_last.expr()), q_enable.expr()]) * next_member, + next_member_in_table, ), ] }); @@ -376,7 +379,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { // TODO: r_mult is adv, add constraint for pow meta.lookup_any("rlp r_mult check", |meta| { let r_mult = meta.query_advice(r_mult, Rotation::cur()); - let pow = meta.query_advice(tag_bytes_in_row, Rotation::cur()); + let pow = meta.query_advice(tx_member_bytes_in_row, Rotation::cur()); let r_mult_in_table = meta.query_fixed(args.r_mult_pow_table.r_mult, Rotation::cur()); let r_pow_in_table = meta.query_fixed(args.r_mult_pow_table.length, Rotation::cur()); @@ -386,6 +389,20 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { meta.create_gate("common constraints for all rows", |meta| { let mut cb = BaseConstraintBuilder::default(); + // boolean constraints + cb.require_boolean( + "field complete boolean", + meta.query_advice(complete, Rotation::cur()), + ); + cb.require_boolean( + "decodable is boolean", + meta.query_advice(decodable, Rotation::cur()), + ); + cb.require_boolean( + "valid is boolean", + meta.query_advice(valid, Rotation::cur()), + ); + // bind the rlp_type and rlp_type selector q_rlp_types.iter().enumerate().for_each(|(i, q_rlp_type)| { let q_rlp_type_enabled = meta.query_advice(*q_rlp_type, Rotation::cur()); @@ -406,18 +423,18 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ); // bind the q_field with the field tag - q_fields.iter().enumerate().for_each(|(i, q_field)| { - let q_field_enabled = meta.query_advice(*q_field, Rotation::cur()); - cb.require_boolean("q_fields are bool", q_field_enabled.expr()); - cb.condition(q_field_enabled.expr(), |cb| { - let tag = meta.query_advice(tag, Rotation::cur()); + q_tx_members.iter().enumerate().for_each(|(i, q_member)| { + let q_member_enabled = meta.query_advice(*q_member, Rotation::cur()); + cb.require_boolean("q_member are bool", q_member_enabled.expr()); + cb.condition(q_member_enabled.expr(), |cb| { + let tag = meta.query_advice(tx_member, Rotation::cur()); cb.require_equal("tag check", tag, i.expr()) }); }); cb.require_equal( "1 tx field only", sum::expr( - q_fields + q_tx_members .iter() .map(|field| meta.query_advice(*field, Rotation::cur())), ), @@ -444,38 +461,26 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ])) }); - // common logic for tx fields - meta.create_gate("tx fields common constraints", |meta| { + // common logic for tx members + meta.create_gate("tx members common constraints", |meta| { let mut cb = BaseConstraintBuilder::default(); - let tag = meta.query_advice(tag, Rotation::cur()); + let tag = meta.query_advice(tx_member, Rotation::cur()); let complete_cur = meta.query_advice(complete, Rotation::cur()); - let rlp_tag_length_cur = meta.query_advice(rlp_tag_length, Rotation::cur()); + let rlp_tag_length_cur = meta.query_advice(rlp_tx_member_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); - let tag_bytes_in_row_cur = meta.query_advice(tag_bytes_in_row, Rotation::cur()); + let bytes_in_row_cur = meta.query_advice(tx_member_bytes_in_row, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); let byte_cells_cur = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let valid = meta.query_advice(valid, Rotation::cur()); - let q_fields: Vec> = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); + let q_tx_rlp_header = + meta.query_advice(q_tx_members[RlpTxFieldTag::TxRlpHeader], Rotation::cur()); let q_enable = meta.query_selector(q_enable); let q_first = meta.query_fixed(q_first, Rotation::cur()); - // cb.require_boolean("q_enable boolean", q_enable); - cb.require_boolean("field complete boolean", complete_cur.expr()); - q_fields.iter().for_each(|q_col| { - cb.require_boolean("q_fields boolean", q_col.expr()); - }); - cb.require_boolean("decodable", decodable); - cb.require_boolean("valid", valid); - // length with leading bytes cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::DoNothing), |cb| { cb.require_equal("0 length", rlp_tag_length_cur.clone(), 0.expr()) @@ -546,8 +551,8 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_equal( "length = prev_length - prev_bytes_in_row", rlp_tag_length_cur.clone(), - meta.query_advice(rlp_tag_length, Rotation::prev()) - - meta.query_advice(tag_bytes_in_row, Rotation::prev()), + meta.query_advice(rlp_tx_member_length, Rotation::prev()) + - meta.query_advice(tx_member_bytes_in_row, Rotation::prev()), ); cb.require_zero( @@ -562,7 +567,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.condition(complete_cur.expr(), |cb| { cb.require_equal( "complete = 1 => rlp_tag_length = bytes_in_row", - tag_bytes_in_row_cur.expr(), + bytes_in_row_cur.expr(), rlp_tag_length_cur.expr(), ); @@ -570,14 +575,14 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { "rlp_remain_length = rlp_remain_length.prev - length", remain_length.expr(), meta.query_advice(rlp_remain_length, Rotation::prev()) - - tag_bytes_in_row_cur.expr(), + - bytes_in_row_cur.expr(), ); }); cb.condition(not::expr(complete_cur.expr()), |cb| { cb.require_equal( "!complete => MAX_BYTES_COL == bytes_in_row", - tag_bytes_in_row_cur.expr(), + bytes_in_row_cur.expr(), MAX_BYTE_COLUMN_NUM.expr(), ); }); @@ -592,7 +597,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.gate(and::expr([ q_enable, not::expr(q_first), - not::expr(q_fields[RlpTxFieldTag::TxRlpHeader].expr()), + not::expr(q_tx_rlp_header), ])) }); @@ -602,9 +607,9 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tx_id = meta.query_advice(tx_id, Rotation::cur()); let tx_type_cur = meta.query_advice(tx_type, Rotation::cur()); - let tag_cur = meta.query_advice(tag, Rotation::cur()); + let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); let complete = meta.query_advice(complete, Rotation::cur()); - let rlp_tag_length_cur = meta.query_advice(rlp_tag_length, Rotation::cur()); + let rlp_tag_length_cur = meta.query_advice(rlp_tx_member_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); @@ -617,7 +622,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_zero("0 tx_id", tx_id); cb.require_zero("0 tx_type", tx_type_cur.expr()); - cb.require_zero("0 tx_tag", tag_cur); + cb.require_zero("0 tx_tag", tx_member_cur); cb.require_equal("field completed", complete.expr(), 1.expr()); cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList1), |cb| { @@ -671,10 +676,9 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tx_id_cur = meta.query_advice(tx_id, Rotation::cur()); let tx_id_prev = meta.query_advice(tx_id, Rotation::prev()); let tx_type_cur = meta.query_advice(tx_type, Rotation::cur()); - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let tag_next = meta.query_advice(tag, Rotation::next()); + let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); let complete = meta.query_advice(complete, Rotation::cur()); - let rlp_tag_length_cur = meta.query_advice(rlp_tag_length, Rotation::cur()); + let rlp_tag_length_cur = meta.query_advice(rlp_tx_member_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); let byte_cells_cur = bytes @@ -682,35 +686,26 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); let decodable = meta.query_advice(decodable, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); + let q_tx_rlp_header = + meta.query_advice(q_tx_members[RlpTxFieldTag::TxRlpHeader], Rotation::cur()); cb.require_equal( "tx_id == tx_id_prev + 1", tx_id_cur.expr(), tx_id_prev.expr() + 1.expr(), ); - cb.require_zero("legacy tx_type", tx_type_cur.expr()); + cb.require_equal( + "legacy tx_type", + tx_type_cur.expr(), + RlpTxTypeTag::TxLegacyType.expr(), + ); cb.require_equal( "tag is tx header", - tag_cur, + tx_member_cur, RlpTxFieldTag::TxRlpHeader.expr(), ); cb.require_equal("field completed", complete.expr(), 1.expr()); - // next should be nonce if legacy(0) or chain_id if 1559 - cb.condition(not::expr(tx_type_cur.expr()), |cb| { - let tx_type_next = meta.query_advice(tx_type, Rotation::next()); - cb.require_equal( - "next tx is legacy", - tx_type_next, - RlpTxTypeTag::TxLegacyType.expr(), - ); - cb.require_equal("next field is nonce", tag_next, RlpTxFieldTag::Nonce.expr()); - }); - cb.condition(decodable, |cb| { cb.require_equal( "rlp_tag_length = rlp_header length", @@ -726,16 +721,16 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { + rlc::expr(&byte_cells_cur, args.challenges.keccak_input()), ); - cb.gate(q_fields[RlpTxFieldTag::TxRlpHeader].expr() * meta.query_selector(q_enable)) + cb.gate(q_tx_rlp_header * meta.query_selector(q_enable)) }); // padding meta.create_gate("Padding", |meta| { let mut cb = BaseConstraintBuilder::default(); - let tag_cur = meta.query_advice(tag, Rotation::cur()); + let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); let complete = meta.query_advice(complete, Rotation::cur()); - let length = meta.query_advice(rlp_tag_length, Rotation::cur()); + let length = meta.query_advice(rlp_tx_member_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); let acc_rlc_value = meta.query_advice(acc_rlc_value, Rotation::cur()); @@ -744,12 +739,10 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); let q_last = meta.query_fixed(q_last, Rotation::cur()); - let q_fields = q_fields - .iter() - .map(|q_col| meta.query_advice(*q_col, Rotation::cur())) - .collect::>(); + let q_padding = + meta.query_advice(q_tx_members[RlpTxFieldTag::Padding], Rotation::cur()); - cb.require_equal("tag", tag_cur, RlpTxFieldTag::Padding.expr()); + cb.require_equal("tag", tx_member_cur, RlpTxFieldTag::Padding.expr()); cb.require_equal("field completed", complete.expr(), 1.expr()); cb.require_zero("padding has no r_mult", r_mult); cb.require_zero("padding has no length", length); @@ -763,19 +756,15 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_zero("padding has no bytes", byte.expr()); }); - cb.gate( - q_fields[RlpTxFieldTag::Padding].expr() - * not::expr(q_last) - * meta.query_selector(q_enable), - ) + cb.gate(q_padding.expr() * not::expr(q_last) * meta.query_selector(q_enable)) }); meta.create_gate("end logic", |meta| { let mut cb = BaseConstraintBuilder::default(); let complete = meta.query_advice(complete, Rotation::cur()); - let tag_cur = meta.query_advice(tag, Rotation::cur()); - let length = meta.query_advice(rlp_tag_length, Rotation::cur()); + let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); + let length = meta.query_advice(rlp_tx_member_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); let acc_rlc_value = meta.query_advice(acc_rlc_value, Rotation::cur()); @@ -785,7 +774,11 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let q_last = meta.query_fixed(q_last, Rotation::cur()); cb.require_equal("completed at last", complete, 1.expr()); - cb.require_equal("padding at last", tag_cur, RlpTxFieldTag::Padding.expr()); + cb.require_equal( + "padding at last", + tx_member_cur, + RlpTxFieldTag::Padding.expr(), + ); cb.require_equal("padding has no r_mult", r_mult, 0.expr()); cb.require_equal("padding has no length", length, 0.expr()); cb.require_equal("padding has no remain length", remain_length, 0.expr()); @@ -798,12 +791,12 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { Self { tx_id, tx_type, - tag, + tx_member, complete, rlp_type, q_rlp_types, - rlp_tag_length, - tag_bytes_in_row, + rlp_tx_member_length, + rlp_bytes_in_row: tx_member_bytes_in_row, r_mult, rlp_remain_length, value, @@ -811,7 +804,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { bytes, decodable, valid, - q_fields, + q_tx_members, q_enable, q_first, q_last, @@ -839,10 +832,10 @@ impl RlpDecoderCircuitConfig { fn name_row_members(&self, region: &mut Region<'_, F>) { region.name_column(|| "config.tx_id", self.tx_id); region.name_column(|| "config.tx_type", self.tx_type); - region.name_column(|| "config.tag", self.tag); + region.name_column(|| "config.tag", self.tx_member); region.name_column(|| "config.complete", self.complete); region.name_column(|| "config.rlp_types", self.rlp_type); - region.name_column(|| "config.rlp_tag_length", self.rlp_tag_length); + region.name_column(|| "config.rlp_tag_length", self.rlp_tx_member_length); region.name_column(|| "config.rlp_remain_length", self.rlp_remain_length); region.name_column(|| "config.r_mult", self.r_mult); region.name_column(|| "config.value", self.value); @@ -874,9 +867,9 @@ impl RlpDecoderCircuitConfig { )?; region.assign_advice( || "config.tag", - self.tag, + self.tx_member, offset, - || Value::known(F::from(w.tag as u64)), + || Value::known(F::from(w.tx_member as u64)), )?; region.assign_advice( || "config.complete", @@ -908,15 +901,15 @@ impl RlpDecoderCircuitConfig { })?; region.assign_advice( || "config.rlp_tag_length", - self.rlp_tag_length, + self.rlp_tx_member_length, offset, - || Value::known(F::from(w.rlp_tag_length)), + || Value::known(F::from(w.rlp_tx_member_length)), )?; region.assign_advice( || "config.tag_bytes_in_row", - self.tag_bytes_in_row, + self.rlp_bytes_in_row, offset, - || Value::known(F::from(w.tag_bytes_in_row as u64)), + || Value::known(F::from(w.rlp_bytes_in_row as u64)), )?; region.assign_advice( || "config.r_mult", @@ -968,7 +961,7 @@ impl RlpDecoderCircuitConfig { offset, || Value::known(F::from(w.valid)), )?; - self.q_fields + self.q_tx_members .iter() .enumerate() .try_for_each(|(i, q_field)| { @@ -978,7 +971,7 @@ impl RlpDecoderCircuitConfig { *q_field, offset, || { - if i == w.tag as usize { + if i == w.tx_member as usize { Value::known(F::one()) } else { Value::known(F::zero()) @@ -1204,7 +1197,7 @@ fn generate_fields_witness_len(tag: &RlpTxFieldTag, payload: &PayloadInfo) -> us fn generate_rlp_row_witness( tx_id: u64, - tag: &RlpTxFieldTag, + tx_member: &RlpTxFieldTag, raw_bytes: &[u8], r: F, rlp_remain_length: usize, @@ -1224,11 +1217,11 @@ fn generate_rlp_row_witness( temp_witness_vec.push(RlpDecoderCircuitConfigWitness:: { tx_id: tx_id, tx_type: RlpTxTypeTag::TxLegacyType, - tag: tag.clone(), + tx_member: tx_member.clone(), complete: false, rlp_type: rlp_type, - rlp_tag_length: tag_remain_length as u64, - tag_bytes_in_row: MAX_BYTE_COLUMN_NUM as u8, + rlp_tx_member_length: tag_remain_length as u64, + rlp_bytes_in_row: MAX_BYTE_COLUMN_NUM as u8, r_mult: r.pow(&[MAX_BYTE_COLUMN_NUM as u64, 0, 0, 0]), rlp_remain_length: prev_rlp_remain_length - MAX_BYTE_COLUMN_NUM, value: F::zero(), @@ -1249,11 +1242,11 @@ fn generate_rlp_row_witness( temp_witness_vec.push(RlpDecoderCircuitConfigWitness:: { tx_id: tx_id, tx_type: RlpTxTypeTag::TxLegacyType, - tag: tag.clone(), + tx_member: tx_member.clone(), complete: true, rlp_type: rlp_type, - rlp_tag_length: tag_remain_length as u64, - tag_bytes_in_row: tag_remain_length as u8, + rlp_tx_member_length: tag_remain_length as u64, + rlp_bytes_in_row: tag_remain_length as u8, r_mult: r.pow(&[tag_remain_length as u64, 0, 0, 0]), rlp_remain_length: prev_rlp_remain_length - tag_remain_length, value: F::zero(), @@ -1270,7 +1263,7 @@ fn generate_rlp_row_witness( } // TODO: reorganize the match - match tag { + match tx_member { RlpTxFieldTag::TxListRlpHeader => witness.append(&mut generate_witness!()), RlpTxFieldTag::TxRlpHeader => witness.append(&mut generate_witness!()), RlpTxFieldTag::Nonce => witness.append(&mut generate_witness!()), @@ -1552,7 +1545,7 @@ fn complete_paddings( let mut complete_witness = vec![]; let mut pre_padding = RlpDecoderCircuitConfigWitness::::default(); pre_padding.rlp_remain_length = - witness[0].rlp_remain_length + witness[0].tag_bytes_in_row as usize; + witness[0].rlp_remain_length + witness[0].rlp_bytes_in_row as usize; complete_witness.push(pre_padding); witness[0].q_first = true; @@ -1562,11 +1555,11 @@ fn complete_paddings( complete_witness.push(RlpDecoderCircuitConfigWitness:: { tx_id: 0, tx_type: RlpTxTypeTag::TxLegacyType, - tag: RlpTxFieldTag::Padding, + tx_member: RlpTxFieldTag::Padding, complete: true, rlp_type: RlpDecodeTypeTag::DoNothing, - rlp_tag_length: 0, - tag_bytes_in_row: 0, + rlp_tx_member_length: 0, + rlp_bytes_in_row: 0, r_mult: F::zero(), rlp_remain_length: 0, value: F::zero(), From 701dfd3a49cb136142a4506e4580dce6fb5cd7b6 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Thu, 25 May 2023 08:30:48 +0000 Subject: [PATCH 09/21] combine all fixed tables together --- zkevm-circuits/src/rlp_decoder.rs | 190 ++++---- zkevm-circuits/src/rlp_decoder_tables.rs | 528 ++++++++++++++++++----- 2 files changed, 520 insertions(+), 198 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index a17377f759..064c86bac2 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -5,7 +5,7 @@ use std::marker::PhantomData; use crate::{ evm_circuit::util::{constraint_builder::BaseConstraintBuilder, rlc}, impl_expr, - rlp_decoder_tables::{RMultPowTable, RlpDecoderTable, TxFieldSwitchTable}, + rlp_decoder_tables::{RlpDecoderFixedTable, RlpDecoderFixedTableTag}, table::KeccakTable, util::{log2_ceil, Challenges, SubCircuit, SubCircuitConfig}, witness, @@ -37,6 +37,8 @@ use mock::MockTransaction; const NUM_BLINDING_ROWS: usize = 64; +type RlpDecoderFixedTable6Columns = RlpDecoderFixedTable<6>; + /// RlpDecodeTypeTag is used to index the flag of rlp decoding type #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] pub enum RlpDecodeTypeTag { @@ -254,12 +256,8 @@ pub struct RlpDecoderCircuitConfig { #[derive(Clone, Debug)] /// Circuit configuration arguments pub struct RlpDecoderCircuitConfigArgs { - /// RlpDecoderTable - pub rlp_decoder_table: RlpDecoderTable, - /// state transition table - pub tx_field_switch_table: TxFieldSwitchTable, - /// r_mult pow table - pub r_mult_pow_table: RMultPowTable, + /// shared fixed tables + pub rlp_fixed_table: RlpDecoderFixedTable6Columns, /// KeccakTable pub keccak_table: KeccakTable, /// Challenges @@ -312,7 +310,21 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }; } - // TODO: lookup bytes range table + bytes.iter().for_each(|byte| { + meta.lookup_any("rlp byte range check", |meta| { + let table_tag = meta.query_fixed( + args.rlp_fixed_table.byte_range_table.table_tag, + Rotation::cur(), + ); + + let value = + meta.query_fixed(args.rlp_fixed_table.byte_range_table.value, Rotation::cur()); + vec![ + (RlpDecoderFixedTableTag::Range256.expr(), table_tag.expr()), + (meta.query_advice(*byte, Rotation::cur()), value.expr()), + ] + }); + }); // lookup rlp_types table // TODO: bytes[1] as prefix of len also need to be constrainted @@ -325,30 +337,35 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let is_not_partial = not::expr(rlp_type_enabled!(meta, RlpDecodeTypeTag::PartialRlp)); - let tx_type_in_table = - meta.query_fixed(args.rlp_decoder_table.tx_type, Rotation::cur()); - let tx_member_in_table = - meta.query_fixed(args.rlp_decoder_table.tx_field_tag, Rotation::cur()); - let byte0_in_table = meta.query_fixed(args.rlp_decoder_table.byte_0, Rotation::cur()); - let decodable_in_table = - meta.query_fixed(args.rlp_decoder_table.decodable, Rotation::cur()); + let table_tag = meta.query_fixed( + args.rlp_fixed_table.tx_decode_table.table_tag, + Rotation::cur(), + ); + let tx_type_in_table = meta.query_fixed( + args.rlp_fixed_table.tx_decode_table.tx_type, + Rotation::cur(), + ); + let tx_member_in_table = meta.query_fixed( + args.rlp_fixed_table.tx_decode_table.tx_field_tag, + Rotation::cur(), + ); + let byte0_in_table = + meta.query_fixed(args.rlp_fixed_table.tx_decode_table.byte_0, Rotation::cur()); + let decodable_in_table = meta.query_fixed( + args.rlp_fixed_table.tx_decode_table.decodable, + Rotation::cur(), + ); + + let query_able = q_enable.expr() * is_not_partial.expr(); vec![ ( - q_enable.expr() * is_not_partial.expr() * tx_type, - tx_type_in_table, - ), - ( - q_enable.expr() * is_not_partial.expr() * tx_member_cur, - tx_member_in_table, - ), - ( - q_enable.expr() * is_not_partial.expr() * byte0, - byte0_in_table, - ), - ( - q_enable.expr() * is_not_partial.expr() * decodable, - decodable_in_table, + query_able.expr() * RlpDecoderFixedTableTag::RlpDecoderTable.expr(), + table_tag, ), + (query_able.expr() * tx_type, tx_type_in_table), + (query_able.expr() * tx_member_cur, tx_member_in_table), + (query_able.expr() * byte0, byte0_in_table), + (query_able.expr() * decodable, decodable_in_table), ] }); @@ -356,22 +373,30 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { meta.lookup_any("rlp tx field transition", |meta| { let current_member = meta.query_advice(tx_member, Rotation::cur()); let next_member = meta.query_advice(tx_member, Rotation::next()); - let curr_member_in_table = - meta.query_fixed(args.tx_field_switch_table.current_tx_field, Rotation::cur()); - let next_member_in_table = - meta.query_fixed(args.tx_field_switch_table.next_tx_field, Rotation::cur()); + + let table_tag = meta.query_fixed( + args.rlp_fixed_table.tx_member_switch_table.table_tag, + Rotation::cur(), + ); + let curr_member_in_table = meta.query_fixed( + args.rlp_fixed_table.tx_member_switch_table.current_tx_field, + Rotation::cur(), + ); + let next_member_in_table = meta.query_fixed( + args.rlp_fixed_table.tx_member_switch_table.next_tx_field, + Rotation::cur(), + ); let q_enable = meta.query_selector(q_enable); let is_last = meta.query_fixed(q_last, Rotation::cur()); + let query_able = and::expr([not::expr(is_last.expr()), q_enable.expr()]); vec![ ( - and::expr([not::expr(is_last.expr()), q_enable.expr()]) * current_member, - curr_member_in_table, - ), - ( - and::expr([not::expr(is_last.expr()), q_enable.expr()]) * next_member, - next_member_in_table, + query_able.expr() * RlpDecoderFixedTableTag::TxFieldSwitchTable.expr(), + table_tag, ), + (query_able.expr() * current_member, curr_member_in_table), + (query_able.expr() * next_member, next_member_in_table), ] }); @@ -380,10 +405,28 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { meta.lookup_any("rlp r_mult check", |meta| { let r_mult = meta.query_advice(r_mult, Rotation::cur()); let pow = meta.query_advice(tx_member_bytes_in_row, Rotation::cur()); - let r_mult_in_table = meta.query_fixed(args.r_mult_pow_table.r_mult, Rotation::cur()); - let r_pow_in_table = meta.query_fixed(args.r_mult_pow_table.length, Rotation::cur()); + let table_tag = meta.query_fixed( + args.rlp_fixed_table.r_mult_pow_table.table_tag, + Rotation::cur(), + ); + let r_mult_in_table = meta.query_fixed( + args.rlp_fixed_table.r_mult_pow_table.r_mult, + Rotation::cur(), + ); + let r_pow_in_table = meta.query_fixed( + args.rlp_fixed_table.r_mult_pow_table.length, + Rotation::cur(), + ); - vec![(r_mult, r_mult_in_table), (pow, r_pow_in_table)] + let q_enable = meta.query_selector(q_enable); + vec![ + ( + q_enable.expr() * RlpDecoderFixedTableTag::RMult.expr(), + table_tag, + ), + (q_enable.expr() * r_mult, r_mult_in_table), + (q_enable.expr() * pow, r_pow_in_table), + ] }); meta.create_gate("common constraints for all rows", |meta| { @@ -744,7 +787,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_equal("tag", tx_member_cur, RlpTxFieldTag::Padding.expr()); cb.require_equal("field completed", complete.expr(), 1.expr()); - cb.require_zero("padding has no r_mult", r_mult); + cb.require_equal("padding has 1 r_mult", r_mult, 1.expr()); cb.require_zero("padding has no length", length); cb.require_zero("padding has no remain length", remain_length); cb.require_zero( @@ -756,34 +799,18 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_zero("padding has no bytes", byte.expr()); }); - cb.gate(q_padding.expr() * not::expr(q_last) * meta.query_selector(q_enable)) + cb.gate(q_padding.expr() * meta.query_selector(q_enable)) }); - meta.create_gate("end logic", |meta| { + meta.create_gate("end with padding", |meta| { let mut cb = BaseConstraintBuilder::default(); - let complete = meta.query_advice(complete, Rotation::cur()); - let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); - let length = meta.query_advice(rlp_tx_member_length, Rotation::cur()); - let r_mult = meta.query_advice(r_mult, Rotation::cur()); - let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); - let acc_rlc_value = meta.query_advice(acc_rlc_value, Rotation::cur()); - let decodable = meta.query_advice(decodable, Rotation::cur()); - let valid = meta.query_advice(valid, Rotation::cur()); let q_enable = meta.query_selector(q_enable); let q_last = meta.query_fixed(q_last, Rotation::cur()); + let q_padding = + meta.query_advice(q_tx_members[RlpTxFieldTag::Padding], Rotation::cur()); - cb.require_equal("completed at last", complete, 1.expr()); - cb.require_equal( - "padding at last", - tx_member_cur, - RlpTxFieldTag::Padding.expr(), - ); - cb.require_equal("padding has no r_mult", r_mult, 0.expr()); - cb.require_equal("padding has no length", length, 0.expr()); - cb.require_equal("padding has no remain length", remain_length, 0.expr()); - cb.require_equal("padding has no rlc (all 0)", acc_rlc_value, 0.expr()); - cb.require_equal("valid == decodable", valid, decodable); + cb.require_equal("padding at last", q_padding, 1.expr()); cb.gate(q_last * q_enable) }); @@ -1048,8 +1075,12 @@ impl RlpDecoderCircuit { fn calc_min_num_rows(txs_len: usize, call_data_rows: usize) -> usize { // add 2 for prev and next rotations. let constraint_size = txs_len * LEGACY_TX_FIELD_NUM + call_data_rows + 2; - let tables_size = - RlpDecoderTable::table_size() + TxFieldSwitchTable::table_size() + MAX_BYTE_COLUMN_NUM; + let tables_size = RlpDecoderFixedTable6Columns::table_size(); + log::info!( + "constraint_size: {}, tables_size: {}", + constraint_size, + tables_size + ); constraint_size + tables_size + NUM_BLINDING_ROWS } } @@ -1090,16 +1121,7 @@ impl SubCircuit for RlpDecoderCircuit { let witness: Vec> = rlp_decode_tx_list_manually(&self.bytes, randomness, self.size as u32); - config.args.rlp_decoder_table.load(layouter, challenges)?; - config - .args - .tx_field_switch_table - .load(layouter, challenges)?; - config.args.r_mult_pow_table.load(layouter, challenges)?; - config - .args - .keccak_table - .dev_load(layouter, vec![&self.bytes], challenges)?; + config.args.rlp_fixed_table.load(layouter, challenges)?; layouter.assign_region( || "rlp witness region", @@ -1127,9 +1149,7 @@ impl Circuit for RlpDecoderCircuit { } fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let rlp_decoder_table = RlpDecoderTable::construct(meta); - let tx_field_switch_table = TxFieldSwitchTable::construct(meta); - let r_mult_pow_table = RMultPowTable::construct(meta); + let rlp_fixed_table = RlpDecoderFixedTable6Columns::construct(meta); let keccak_table = KeccakTable::construct(meta); let challenges = Challenges::construct(meta); @@ -1140,9 +1160,7 @@ impl Circuit for RlpDecoderCircuit { RlpDecoderCircuitConfig::new( meta, RlpDecoderCircuitConfigArgs { - rlp_decoder_table, - tx_field_switch_table, - r_mult_pow_table, + rlp_fixed_table, keccak_table, challenges: challenges_expr, }, @@ -1520,9 +1538,9 @@ fn rlp_decode_tx_list_manually( k as usize - witness_len - 2 - NUM_BLINDING_ROWS, ); - // for iw in complete_witness.iter().enumerate() { - // println!("witness[{}] {:?}", iw.0, iw.1); - // } + for iw in complete_witness.iter().enumerate() { + log::trace!("witness[{}] {:?}", iw.0, iw.1); + } complete_witness } @@ -1560,7 +1578,7 @@ fn complete_paddings( rlp_type: RlpDecodeTypeTag::DoNothing, rlp_tx_member_length: 0, rlp_bytes_in_row: 0, - r_mult: F::zero(), + r_mult: F::one(), rlp_remain_length: 0, value: F::zero(), acc_rlc_value: F::zero(), diff --git a/zkevm-circuits/src/rlp_decoder_tables.rs b/zkevm-circuits/src/rlp_decoder_tables.rs index b2f6d4e402..be0b7f6e40 100644 --- a/zkevm-circuits/src/rlp_decoder_tables.rs +++ b/zkevm-circuits/src/rlp_decoder_tables.rs @@ -1,6 +1,7 @@ //! The rlp decoding tables implementation. use crate::{ + impl_expr, rlp_decoder::{RlpDecodeTypeTag, RlpTxFieldTag, RlpTxTypeTag, MAX_BYTE_COLUMN_NUM}, util::Challenges, }; @@ -14,8 +15,8 @@ pub use halo2_proofs::halo2curves::{ secp256k1::{self, Secp256k1Affine, Secp256k1Compressed}, }; use halo2_proofs::{ - circuit::{Layouter, Region, Value}, - plonk::{Column, ConstraintSystem, Error, Fixed}, + circuit::{Layouter, Value}, + plonk::{Column, ConstraintSystem, Error, Expression, Fixed}, }; /// Rlp encoding types @@ -50,106 +51,63 @@ impl RlpDecodeRule { /// | legacy | signS | byte32 | 0xa0 | true | /// | legacy | signS | byte32 | 0xa1 | false | /// ... - pub fn load( - &self, - tx_type: &RlpTxTypeTag, - tx_field_tag: &RlpTxFieldTag, - table: &RlpDecoderTable, - region: &mut Region<'_, F>, - offset: usize, - ) -> Result<(), Error> { - let rule_table_rows = { - (0..256u64) - .map(|i| { - let (rlp_type, decodable) = match self { - RlpDecodeRule::Padding => (RlpDecodeTypeTag::DoNothing, true), - RlpDecodeRule::Empty => match i { - 0x80 => (RlpDecodeTypeTag::SingleByte, true), - _ => (RlpDecodeTypeTag::DoNothing, false), - }, - RlpDecodeRule::Uint64 => match i { - // 0 is error: non-canonical integer (leading zero bytes) for uint64 - 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), - 0x81..=0x88 => (RlpDecodeTypeTag::ShortString, true), - _ => (RlpDecodeTypeTag::DoNothing, false), - }, - RlpDecodeRule::Uint96 => match i { - // 0 is error: non-canonical integer (leading zero bytes) for uint96 - 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), - 0x81..=0x8c => (RlpDecodeTypeTag::ShortString, true), - _ => (RlpDecodeTypeTag::DoNothing, false), - }, - RlpDecodeRule::Address => match i { - 0x94 => (RlpDecodeTypeTag::ShortString, true), - _ => (RlpDecodeTypeTag::DoNothing, false), - }, - RlpDecodeRule::Bytes32 => match i { - // TODO: what if sig is less then 32 bytes? - 0xa0 => (RlpDecodeTypeTag::ShortString, true), - _ => (RlpDecodeTypeTag::DoNothing, false), - }, - RlpDecodeRule::Bytes48K => match i { - 0 => (RlpDecodeTypeTag::SingleByte, true), // 0x00 - 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), // 0x01..=0x80 - 0x81..=0xb7 => (RlpDecodeTypeTag::ShortString, true), - 0xb8 => (RlpDecodeTypeTag::LongString1, true), - 0xb9 => (RlpDecodeTypeTag::LongString2, true), - 0xba => (RlpDecodeTypeTag::LongString3, true), - _ => (RlpDecodeTypeTag::DoNothing, false), - }, - RlpDecodeRule::EmptyList => match i { - 0xc0 => (RlpDecodeTypeTag::ShortString, false), - _ => (RlpDecodeTypeTag::DoNothing, false), - }, - RlpDecodeRule::LongList => match i { - 0xf8 => (RlpDecodeTypeTag::LongList1, true), - 0xf9 => (RlpDecodeTypeTag::LongList2, true), - 0xfa => (RlpDecodeTypeTag::LongList3, true), - _ => (RlpDecodeTypeTag::DoNothing, false), - }, - }; - [ - *tx_type as u64, - *tx_field_tag as u64, - rlp_type as u64, - i, - decodable as u64, - ] - }) - .collect::>() + pub fn rule_check(&self, byte0: u8) -> (RlpDecodeTypeTag, bool) { + let (rlp_type, decodable) = match self { + RlpDecodeRule::Padding => (RlpDecodeTypeTag::DoNothing, true), + RlpDecodeRule::Empty => match byte0 { + 0x80 => (RlpDecodeTypeTag::SingleByte, true), + _ => (RlpDecodeTypeTag::DoNothing, false), + }, + RlpDecodeRule::Uint64 => match byte0 { + // 0 is error: non-canonical integer (leading zero bytes) for uint64 + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), + 0x81..=0x88 => (RlpDecodeTypeTag::ShortString, true), + _ => (RlpDecodeTypeTag::DoNothing, false), + }, + RlpDecodeRule::Uint96 => match byte0 { + // 0 is error: non-canonical integer (leading zero bytes) for uint96 + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), + 0x81..=0x8c => (RlpDecodeTypeTag::ShortString, true), + _ => (RlpDecodeTypeTag::DoNothing, false), + }, + RlpDecodeRule::Address => match byte0 { + 0x94 => (RlpDecodeTypeTag::ShortString, true), + _ => (RlpDecodeTypeTag::DoNothing, false), + }, + RlpDecodeRule::Bytes32 => match byte0 { + // TODO: what if sig is less then 32 bytes? + 0xa0 => (RlpDecodeTypeTag::ShortString, true), + _ => (RlpDecodeTypeTag::DoNothing, false), + }, + RlpDecodeRule::Bytes48K => match byte0 { + 0 => (RlpDecodeTypeTag::SingleByte, true), // 0x00 + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), // 0x01..=0x80 + 0x81..=0xb7 => (RlpDecodeTypeTag::ShortString, true), + 0xb8 => (RlpDecodeTypeTag::LongString1, true), + 0xb9 => (RlpDecodeTypeTag::LongString2, true), + 0xba => (RlpDecodeTypeTag::LongString3, true), + _ => (RlpDecodeTypeTag::DoNothing, false), + }, + RlpDecodeRule::EmptyList => match byte0 { + 0xc0 => (RlpDecodeTypeTag::ShortString, false), + _ => (RlpDecodeTypeTag::DoNothing, false), + }, + RlpDecodeRule::LongList => match byte0 { + 0xf8 => (RlpDecodeTypeTag::LongList1, true), + 0xf9 => (RlpDecodeTypeTag::LongList2, true), + 0xfa => (RlpDecodeTypeTag::LongList3, true), + _ => (RlpDecodeTypeTag::DoNothing, false), + }, }; - - let mut offset = offset; - for rule_table_row in rule_table_rows.iter() { - // println!("rule_table_row: {:?} @ offset {}.", rule_table_row, offset); - rule_table_row - .iter() - .zip([ - table.tx_type, - table.tx_field_tag, - table.rlp_type, - table.byte_0, - table.decodable, - ]) - .try_for_each(|(value, col)| { - region - .assign_fixed( - || "load rlp decoder table", - col, - offset, - || Value::known(F::from(*value)), - ) - .map(|_| ()) - })?; - offset += 1; - } - Ok(()) + (rlp_type, decodable) } } /// Table that contains the fields of all possible RLP decodable fields #[derive(Clone, Debug)] pub struct RlpDecoderTable { + /// The length of the field + pub table_tag: Column, /// The tx type tag pub tx_type: Column, /// The tx field tag @@ -160,20 +118,31 @@ pub struct RlpDecoderTable { pub byte_0: Column, /// Whether the field is decodable pub decodable: Column, - /// The length of the field - pub length: Column, } impl RlpDecoderTable { /// Construct a new RlpDecoderTable pub fn construct(meta: &mut ConstraintSystem) -> Self { Self { + table_tag: meta.fixed_column(), tx_type: meta.fixed_column(), tx_field_tag: meta.fixed_column(), rlp_type: meta.fixed_column(), byte_0: meta.fixed_column(), decodable: meta.fixed_column(), - length: meta.fixed_column(), + } + } + + /// build from existed columns + pub fn build_from_columns(columns: &[Column]) -> Self { + assert!(columns.len() > 5); + Self { + table_tag: columns[0], + tx_type: columns[1], + tx_field_tag: columns[2], + byte_0: columns[3], + rlp_type: columns[4], + decodable: columns[5], } } @@ -186,7 +155,7 @@ impl RlpDecoderTable { pub fn load( &self, layouter: &mut impl Layouter, - challenges: &Challenges>, + _challenges: &Challenges>, ) -> Result<(), Error> { // make a list with all member of rlpTxFieldTag literally let rlp_tx_field_decode_rules: Vec<(RlpTxTypeTag, RlpTxFieldTag, RlpDecodeRule)> = vec![ @@ -261,21 +230,55 @@ impl RlpDecoderTable { || "load rlp decoder table", |mut region| { let mut offset = 0; + let table_tag = RlpDecoderFixedTableTag::RlpDecoderTable as u64; + for (tx_type, tx_field_tag, decode_rule) in rlp_tx_field_decode_rules.iter() { - decode_rule.load(tx_type, tx_field_tag, self, &mut region, offset)?; - offset += 256; + for byte_val in 0..=255u8 { + let (rlp_type, decodable) = decode_rule.rule_check(byte_val); + let rule_table_row = [ + table_tag, + *tx_type as u64, + *tx_field_tag as u64, + rlp_type as u64, + byte_val as u64, + decodable as u64, + ]; + + log::trace!("rule_table_row: {:?} @ offset {}.", &rule_table_row, offset); + rule_table_row + .iter() + .zip([ + self.table_tag, + self.tx_type, + self.tx_field_tag, + self.rlp_type, + self.byte_0, + self.decodable, + ]) + .try_for_each(|(value, col)| { + region + .assign_fixed( + || "load rlp rule decoder table", + col, + offset, + || Value::known(F::from(*value)), + ) + .map(|_| ()) + })?; + offset += 1; + } } Ok(()) }, - )?; - - Ok(()) + ) } } /// Table that contains the fields of possible state transitions #[derive(Clone, Debug)] pub struct TxFieldSwitchTable { + /// table tag of the table + pub table_tag: Column, /// The current tx field pub current_tx_field: Column, /// The next tx field @@ -304,11 +307,22 @@ impl TxFieldSwitchTable { /// Construct a new RlpDecoderTable pub fn construct(meta: &mut ConstraintSystem) -> Self { Self { + table_tag: meta.fixed_column(), current_tx_field: meta.fixed_column(), next_tx_field: meta.fixed_column(), } } + /// build from existed columns + pub fn build_from_columns(columns: &[Column]) -> Self { + assert!(columns.len() > 2); + Self { + table_tag: columns[0], + current_tx_field: columns[1], + next_tx_field: columns[2], + } + } + /// Get the row num of the table pub fn table_size() -> usize { TX_FIELD_TRANSITION_TABLE.len() @@ -318,7 +332,7 @@ impl TxFieldSwitchTable { pub fn load( &self, layouter: &mut impl Layouter, - challenges: &Challenges>, + _challenges: &Challenges>, ) -> Result<(), Error> { // make a list with all member of rlpTxFieldTag literally let tx_field_trans_table = &TX_FIELD_TRANSITION_TABLE; @@ -330,6 +344,16 @@ impl TxFieldSwitchTable { tx_field_trans_table .iter() .try_for_each(|(current_tx_field, next_tx_field)| { + region.assign_fixed( + || "table tag", + self.table_tag, + offset, + || { + Value::known(F::from( + RlpDecoderFixedTableTag::TxFieldSwitchTable as u64, + )) + }, + )?; region.assign_fixed( || "current tx field", self.current_tx_field, @@ -353,6 +377,8 @@ impl TxFieldSwitchTable { /// Table that contains the pow of randomness #[derive(Clone, Debug)] pub struct RMultPowTable { + /// table tag + pub table_tag: Column, /// pow number pub length: Column, /// pow of randomness @@ -363,11 +389,22 @@ impl RMultPowTable { /// Construct a new RlpDecoderTable pub fn construct(meta: &mut ConstraintSystem) -> Self { Self { + table_tag: meta.fixed_column(), length: meta.fixed_column(), r_mult: meta.fixed_column(), } } + /// build from existed columns + pub fn build_from_columns(columns: &[Column]) -> Self { + assert!(columns.len() > 2); + Self { + table_tag: columns[0], + length: columns[1], + r_mult: columns[2], + } + } + /// Get the row num of the table pub fn table_size() -> usize { MAX_BYTE_COLUMN_NUM @@ -382,10 +419,16 @@ impl RMultPowTable { let mut randomness = F::zero(); challenges.keccak_input().map(|r| randomness = r); - (0..=MAX_BYTE_COLUMN_NUM).try_for_each(|i| { - layouter.assign_region( - || "load rlp r_mult table", - |mut region| { + layouter.assign_region( + || "load rlp r_mult table", + |mut region| { + (0..=MAX_BYTE_COLUMN_NUM).try_for_each(|i| { + region.assign_fixed( + || "table tag", + self.table_tag, + i, + || Value::known(F::from(RlpDecoderFixedTableTag::RMult as u64)), + )?; region.assign_fixed( || "pow", self.length, @@ -399,9 +442,270 @@ impl RMultPowTable { || Value::known(randomness.pow(&[i as u64, 0, 0, 0])), )?; Ok(()) - }, - ) - })?; + }) + }, + )?; + Ok(()) + } +} + +/// for value range lookup +#[derive(Clone, Debug)] +pub struct RangeTable { + /// table tag + pub table_tag: Column, + /// value in range + pub value: Column, +} + +impl RangeTable { + /// Construct a new RlpDecoderTable + pub fn construct(meta: &mut ConstraintSystem) -> Self { + Self { + table_tag: meta.fixed_column(), + value: meta.fixed_column(), + } + } + + /// build from existed columns + pub fn build_from_columns(columns: &[Column]) -> Self { + assert!(columns.len() > 2); + Self { + table_tag: columns[0], + value: columns[1], + } + } + + /// Get the row num of the table + pub fn table_size() -> usize { + match N { + 0..=256 => 256, + _ => unimplemented!(), + } + } + + /// Assign the values of the table to the circuit + pub fn load( + &self, + layouter: &mut impl Layouter, + challenges: &Challenges>, + ) -> Result<(), Error> { + let mut randomness = F::zero(); + challenges.keccak_input().map(|r| randomness = r); + + let tag = match N { + 0..=256 => RlpDecoderFixedTableTag::Range256 as u64, + _ => unimplemented!(), + }; + layouter.assign_region( + || format!("load rlp range {} table", N), + |mut region| { + (0..N).try_for_each(|i| { + region.assign_fixed( + || "table tag", + self.table_tag, + i, + || Value::known(F::from(tag)), + )?; + region.assign_fixed( + || "pow", + self.value, + i, + || Value::known(F::from(i as u64)), + )?; + Ok(()) + }) + }, + )?; + Ok(()) + } +} + +type ByteRangeTable = RangeTable<256>; + +/// For decodable flag check, for example: +/// 1. 0xF836 is invalid because the len_of_len is 0x36 which is < 55, so the len_decodable is +/// false. +/// 2. 0x8100 is invalid because the value is 00 which <0x80 should be not after 0x81, normally +/// value needs to be non-zero as rlp does not have leading 0. +#[derive(Clone, Debug)] +pub struct InvalidRlpBytesTable { + /// table tag + pub table_tag: Column, + /// byte value + pub value: Column, + /// decodable in len_of_len heading + pub len_decodable: Column, + /// decodable in value heading + pub val_decodable: Column, +} + +impl InvalidRlpBytesTable { + /// Construct a new RlpDecoderTable + pub fn construct(meta: &mut ConstraintSystem) -> Self { + Self { + table_tag: meta.fixed_column(), + value: meta.fixed_column(), + len_decodable: meta.fixed_column(), + val_decodable: meta.fixed_column(), + } + } + + /// build from existed columns + pub fn build_from_columns(columns: &[Column]) -> Self { + assert!(columns.len() > 2); + Self { + table_tag: columns[0], + value: columns[1], + len_decodable: columns[2], + val_decodable: columns[3], + } + } + + /// Get the row num of the table + pub fn table_size() -> usize { + 256 + } + + /// Assign the values of the table to the circuit + pub fn load( + &self, + layouter: &mut impl Layouter, + challenges: &Challenges>, + ) -> Result<(), Error> { + let mut randomness = F::zero(); + challenges.keccak_input().map(|r| randomness = r); + + layouter.assign_region( + || format!("load rlp heading bytes"), + |mut region| { + (0..256).try_for_each(|i| { + region.assign_fixed( + || "table tag", + self.table_tag, + i, + || { + Value::known(F::from( + RlpDecoderFixedTableTag::HeadingByteValidTable as u64, + )) + }, + )?; + region.assign_fixed( + || "value", + self.value, + i, + || Value::known(F::from(i as u64)), + )?; + region.assign_fixed( + || "len_of_len valid", + self.len_decodable, + i, + || { + if i <= 55 { + Value::known(F::zero()) + } else { + Value::known(F::one()) + } + }, + )?; + region.assign_fixed( + || "value valid", + self.val_decodable, + i, + || { + if i > 0x0 { + Value::known(F::one()) + } else { + Value::known(F::zero()) + } + }, + )?; + Ok(()) + }) + }, + )?; + Ok(()) + } +} + +/// tag for shared fixed table +#[derive(Clone, Copy, Debug)] +pub enum RlpDecoderFixedTableTag { + /// All zero lookup data + Disabled, + /// Power of randomness: [1, r], [2, r^2],... + RMult, + /// 0 - 255 + Range256, + /// Decode rule table for rlp tx + RlpDecoderTable, + /// Tx field switch table + TxFieldSwitchTable, + /// valid len/value heading byte + HeadingByteValidTable, +} +impl_expr!(RlpDecoderFixedTableTag); + +#[derive(Clone, Debug)] +/// shared fix tables +pub struct RlpDecoderFixedTable { + /// rlp decoder table + pub tx_decode_table: RlpDecoderTable, + /// tx field switch table + pub tx_member_switch_table: TxFieldSwitchTable, + /// r_mult pow table + pub r_mult_pow_table: RMultPowTable, + /// range table + pub byte_range_table: ByteRangeTable, + // TODO: range table, invalid byte table + /// shared columns for all fix tables + fixed_columns: [Column; N], +} + +impl RlpDecoderFixedTable { + /// Construct a new RlpDecoderTable + pub fn construct(meta: &mut ConstraintSystem) -> Self { + let fix_columns = array_init::array_init(|_| meta.fixed_column()); + Self { + tx_decode_table: RlpDecoderTable::build_from_columns(&fix_columns), + tx_member_switch_table: TxFieldSwitchTable::build_from_columns(&fix_columns), + r_mult_pow_table: RMultPowTable::build_from_columns(&fix_columns), + byte_range_table: ByteRangeTable::build_from_columns(&fix_columns), + fixed_columns: fix_columns, + } + } + + /// Get the row num of the table + pub fn table_size() -> usize { + RlpDecoderTable::table_size() + + TxFieldSwitchTable::table_size() + + RMultPowTable::table_size() + + ByteRangeTable::table_size() + + 1 + } + + /// Assign the values of the table to the circuit + pub fn load( + &self, + layouter: &mut impl Layouter, + challenges: &Challenges>, + ) -> Result<(), Error> { + // TODO: load all in one region explicitly + layouter.assign_region( + || "load disabled row", + |mut region| { + self.fixed_columns.iter().try_for_each(|column| { + region + .assign_fixed(|| "table tag", *column, 0, || Value::known(F::zero())) + .map(|_| ()) + })?; + Ok(()) + }, + )?; + self.tx_decode_table.load(layouter, challenges)?; + self.tx_member_switch_table.load(layouter, challenges)?; + self.r_mult_pow_table.load(layouter, challenges)?; + self.byte_range_table.load(layouter, challenges)?; Ok(()) } } From 5e650cf1883bff8d12df572cc75d9b9c13cb39e2 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Thu, 25 May 2023 14:13:20 +0000 Subject: [PATCH 10/21] add leading byte check --- zkevm-circuits/src/rlp_decoder.rs | 160 +++++++++++++++++------------- 1 file changed, 90 insertions(+), 70 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 064c86bac2..c507e4fcfa 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -15,7 +15,10 @@ use ethers_core::{ types::TransactionRequest, utils::rlp::{self, PayloadInfo}, }; -use gadgets::util::{and, not, sum}; +use gadgets::{ + less_than::{LtChip, LtConfig, LtInstruction}, + util::{and, not, or, sum}, +}; use halo2_proofs::{ circuit::{Layouter, Region, SimpleFloorPlanner, Value}, plonk::{ @@ -249,8 +252,12 @@ pub struct RlpDecoderCircuitConfig { pub q_first: Column, /// the end pub q_last: Column, - /// args - pub args: RlpDecoderCircuitConfigArgs, + /// aux tables + pub aux_tables: RlpDecoderCircuitConfigArgs, + /// condition check for <=55 + pub v_gt_55: LtConfig, + /// condition check for > 0 + pub v_gt_0: LtConfig, } #[derive(Clone, Debug)] @@ -268,7 +275,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { type ConfigArgs = RlpDecoderCircuitConfigArgs; /// Return a new RlpDecoderCircuitConfig - fn new(meta: &mut ConstraintSystem, args: Self::ConfigArgs) -> Self { + fn new(meta: &mut ConstraintSystem, aux_tables: Self::ConfigArgs) -> Self { let tx_id = meta.advice_column(); let tx_type = meta.advice_column(); let tx_member = meta.advice_column(); @@ -310,15 +317,36 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }; } + let v_gt_55 = LtChip::configure( + meta, + |meta| { + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList1) * meta.query_selector(q_enable) + }, + |_| 55.expr(), + |meta| meta.query_advice(bytes[1], Rotation::cur()), + ); + + let v_gt_0 = LtChip::configure( + meta, + |meta| { + or::expr([ + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList2), + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList3), + ]) * meta.query_selector(q_enable) + }, + |_| 0.expr(), + |meta| meta.query_advice(bytes[1], Rotation::cur()), + ); + + ///////////////////////////////// + //// lookups + //// ///////////////////////////// + // bytes range check bytes.iter().for_each(|byte| { meta.lookup_any("rlp byte range check", |meta| { - let table_tag = meta.query_fixed( - args.rlp_fixed_table.byte_range_table.table_tag, - Rotation::cur(), - ); - - let value = - meta.query_fixed(args.rlp_fixed_table.byte_range_table.value, Rotation::cur()); + let table = &aux_tables.rlp_fixed_table.byte_range_table; + let table_tag = meta.query_fixed(table.table_tag, Rotation::cur()); + let value = meta.query_fixed(table.value, Rotation::cur()); vec![ (RlpDecoderFixedTableTag::Range256.expr(), table_tag.expr()), (meta.query_advice(*byte, Rotation::cur()), value.expr()), @@ -337,24 +365,12 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let is_not_partial = not::expr(rlp_type_enabled!(meta, RlpDecodeTypeTag::PartialRlp)); - let table_tag = meta.query_fixed( - args.rlp_fixed_table.tx_decode_table.table_tag, - Rotation::cur(), - ); - let tx_type_in_table = meta.query_fixed( - args.rlp_fixed_table.tx_decode_table.tx_type, - Rotation::cur(), - ); - let tx_member_in_table = meta.query_fixed( - args.rlp_fixed_table.tx_decode_table.tx_field_tag, - Rotation::cur(), - ); - let byte0_in_table = - meta.query_fixed(args.rlp_fixed_table.tx_decode_table.byte_0, Rotation::cur()); - let decodable_in_table = meta.query_fixed( - args.rlp_fixed_table.tx_decode_table.decodable, - Rotation::cur(), - ); + let table = &aux_tables.rlp_fixed_table.tx_decode_table; + let table_tag = meta.query_fixed(table.table_tag, Rotation::cur()); + let tx_type_in_table = meta.query_fixed(table.tx_type, Rotation::cur()); + let tx_member_in_table = meta.query_fixed(table.tx_field_tag, Rotation::cur()); + let byte0_in_table = meta.query_fixed(table.byte_0, Rotation::cur()); + let decodable_in_table = meta.query_fixed(table.decodable, Rotation::cur()); let query_able = q_enable.expr() * is_not_partial.expr(); vec![ @@ -374,18 +390,10 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let current_member = meta.query_advice(tx_member, Rotation::cur()); let next_member = meta.query_advice(tx_member, Rotation::next()); - let table_tag = meta.query_fixed( - args.rlp_fixed_table.tx_member_switch_table.table_tag, - Rotation::cur(), - ); - let curr_member_in_table = meta.query_fixed( - args.rlp_fixed_table.tx_member_switch_table.current_tx_field, - Rotation::cur(), - ); - let next_member_in_table = meta.query_fixed( - args.rlp_fixed_table.tx_member_switch_table.next_tx_field, - Rotation::cur(), - ); + let table = &aux_tables.rlp_fixed_table.tx_member_switch_table; + let table_tag = meta.query_fixed(table.table_tag, Rotation::cur()); + let curr_member_in_table = meta.query_fixed(table.current_tx_field, Rotation::cur()); + let next_member_in_table = meta.query_fixed(table.next_tx_field, Rotation::cur()); let q_enable = meta.query_selector(q_enable); let is_last = meta.query_fixed(q_last, Rotation::cur()); @@ -405,18 +413,11 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { meta.lookup_any("rlp r_mult check", |meta| { let r_mult = meta.query_advice(r_mult, Rotation::cur()); let pow = meta.query_advice(tx_member_bytes_in_row, Rotation::cur()); - let table_tag = meta.query_fixed( - args.rlp_fixed_table.r_mult_pow_table.table_tag, - Rotation::cur(), - ); - let r_mult_in_table = meta.query_fixed( - args.rlp_fixed_table.r_mult_pow_table.r_mult, - Rotation::cur(), - ); - let r_pow_in_table = meta.query_fixed( - args.rlp_fixed_table.r_mult_pow_table.length, - Rotation::cur(), - ); + + let table = &aux_tables.rlp_fixed_table.r_mult_pow_table; + let table_tag = meta.query_fixed(table.table_tag, Rotation::cur()); + let r_mult_in_table = meta.query_fixed(table.r_mult, Rotation::cur()); + let r_pow_in_table = meta.query_fixed(table.length, Rotation::cur()); let q_enable = meta.query_selector(q_enable); vec![ @@ -429,6 +430,9 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ] }); + ///////////////////////////////// + //// constraints + //// ///////////////////////////// meta.create_gate("common constraints for all rows", |meta| { let mut cb = BaseConstraintBuilder::default(); @@ -634,7 +638,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { "rlc = r_mult_cur * rlc_next + rlc(bytes_cur)", acc_rlc_cur, r_mult * meta.query_advice(acc_rlc_value, Rotation::next()) - + rlc::expr(&byte_cells_cur, args.challenges.keccak_input()), + + rlc::expr(&byte_cells_cur, aux_tables.challenges.keccak_input()), ); cb.gate(and::expr([ @@ -670,29 +674,33 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList1), |cb| { cb.require_equal( - "long length: f8 + 1", + "long length 1 byte after 0xf8", remain_length.expr(), byte_cells_cur[1].expr(), - ) - // TODO: byte_cells_cur[1] > 55 + ); + + // TODO: byte_cells_cur[1] > 55, and check with len_decode flag + cb.require_equal("v should be >55", v_gt_55.is_lt(meta, None), 1.expr()) }); cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList2), |cb| { cb.require_equal( - "long length: f9 + 2", + "long length 2 bytes after f9", remain_length.expr(), byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr(), - ) - // TODO: byte_cells_cur[1] != 0 + ); + // TODO: byte_cells_cur[1] != 0, and check with len_decode flag + cb.require_equal("v should be >0", v_gt_0.is_lt(meta, None), 1.expr()) }); cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList3), |cb| { cb.require_equal( - "long length: fa + 3", + "long length 3 bytes after fa", remain_length.expr(), byte_cells_cur[1].expr() * 65536.expr() + byte_cells_cur[2].expr() * 256.expr() + byte_cells_cur[3].expr(), - ) - // TODO: byte_cells_cur[1] != 0 + ); + // TODO: byte_cells_cur[1] != 0, and check with len_decode flag + cb.require_equal("v should be >0", v_gt_0.is_lt(meta, None), 1.expr()) }); cb.condition(decodable, |cb| { @@ -707,7 +715,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { "rlc = r_mult_cur * rlc_next + rlc(bytes_cur)", acc_rlc_cur, r_mult * meta.query_advice(acc_rlc_value, Rotation::next()) - + rlc::expr(&byte_cells_cur, args.challenges.keccak_input()), + + rlc::expr(&byte_cells_cur, aux_tables.challenges.keccak_input()), ); cb.gate(q_first) @@ -761,7 +769,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { "rlc = r_mult_cur * rlc_next + rlc(bytes_cur)", acc_rlc_cur, r_mult * meta.query_advice(acc_rlc_value, Rotation::next()) - + rlc::expr(&byte_cells_cur, args.challenges.keccak_input()), + + rlc::expr(&byte_cells_cur, aux_tables.challenges.keccak_input()), ); cb.gate(q_tx_rlp_header * meta.query_selector(q_enable)) @@ -781,7 +789,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); - let q_last = meta.query_fixed(q_last, Rotation::cur()); let q_padding = meta.query_advice(q_tx_members[RlpTxFieldTag::Padding], Rotation::cur()); @@ -815,7 +822,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.gate(q_last * q_enable) }); - Self { + let circuit_config = RlpDecoderCircuitConfig { tx_id, tx_type, tx_member, @@ -835,8 +842,11 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { q_enable, q_first, q_last, - args, - } + aux_tables, + v_gt_55, + v_gt_0, + }; + circuit_config } } @@ -850,6 +860,13 @@ impl RlpDecoderCircuitConfig { let mut offset = offset; self.name_row_members(region); for wit in wits { + let gt_55_chip = LtChip::construct(self.v_gt_55); + let gt_0_chip = LtChip::construct(self.v_gt_0); + + let leading_val = if wit.bytes.len() > 1 { wit.bytes[1] } else { 0 }; + gt_55_chip.assign(region, offset, F::from(55u64), F::from(leading_val as u64))?; + gt_0_chip.assign(region, offset, F::zero(), F::from(leading_val as u64))?; + self.assign_row(region, offset, wit)?; offset += 1; } @@ -1121,7 +1138,10 @@ impl SubCircuit for RlpDecoderCircuit { let witness: Vec> = rlp_decode_tx_list_manually(&self.bytes, randomness, self.size as u32); - config.args.rlp_fixed_table.load(layouter, challenges)?; + config + .aux_tables + .rlp_fixed_table + .load(layouter, challenges)?; layouter.assign_region( || "rlp witness region", From b68e3e366d821c2046e713de145bdc673f1ad7bd Mon Sep 17 00:00:00 2001 From: smtmfft Date: Sat, 27 May 2023 06:24:02 +0000 Subject: [PATCH 11/21] tx field r/s should be uint256 as they are big integers --- zkevm-circuits/src/rlp_decoder_tables.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder_tables.rs b/zkevm-circuits/src/rlp_decoder_tables.rs index be0b7f6e40..b387f95028 100644 --- a/zkevm-circuits/src/rlp_decoder_tables.rs +++ b/zkevm-circuits/src/rlp_decoder_tables.rs @@ -30,6 +30,8 @@ pub enum RlpDecodeRule { Uint64, /// The RLP encoding type is a uint96 Uint96, + /// The RLP encoding type is a uint256 + Uint256, /// The RLP encoding type is a address 20bytes i.e., 0x94xxxx Address, /// The RLP encoding type is a hash string 32bytes, i.e., 0xa0xxx @@ -70,6 +72,12 @@ impl RlpDecodeRule { 0x81..=0x8c => (RlpDecodeTypeTag::ShortString, true), _ => (RlpDecodeTypeTag::DoNothing, false), }, + RlpDecodeRule::Uint256 => match byte0 { + // 0 is error: non-canonical integer (leading zero bytes) for uint256 + 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), + 0x81..=0xa0 => (RlpDecodeTypeTag::ShortString, true), + _ => (RlpDecodeTypeTag::DoNothing, false), + }, RlpDecodeRule::Address => match byte0 { 0x94 => (RlpDecodeTypeTag::ShortString, true), _ => (RlpDecodeTypeTag::DoNothing, false), @@ -212,12 +220,12 @@ impl RlpDecoderTable { ( RlpTxTypeTag::TxLegacyType, RlpTxFieldTag::SignR, - RlpDecodeRule::Bytes32, + RlpDecodeRule::Uint256, ), ( RlpTxTypeTag::TxLegacyType, RlpTxFieldTag::SignS, - RlpDecodeRule::Bytes48K, + RlpDecodeRule::Uint256, ), ( RlpTxTypeTag::TxLegacyType, From 45e18a17aa96946c8c123065bbef73d55b3febf5 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Wed, 31 May 2023 14:04:20 +0000 Subject: [PATCH 12/21] add invalid byte stream support 1. split error types 2. add invalid and error binding --- zkevm-circuits/src/rlp_decoder.rs | 421 ++++++++++++++++++++--- zkevm-circuits/src/rlp_decoder_tables.rs | 292 +++++++++------- 2 files changed, 532 insertions(+), 181 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index c507e4fcfa..f6ef78b322 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -26,6 +26,7 @@ use halo2_proofs::{ }, poly::Rotation, }; +use keccak256::plain::Keccak; use crate::util::Expr; pub use halo2_proofs::halo2curves::{ @@ -52,8 +53,10 @@ pub enum RlpDecodeTypeTag { SingleByte, /// NullValue: 0x80 NullValue, - /// ShortString: 0x81~0xb7 - ShortString, + /// ShortString: 0x81~0xb7, value means bytes without leading 0 + ShortStringValue, + /// ShortString: 0x81~0xb7, bytes contains leading 0 + ShortStringBytes, /// LongString: 0xb8 LongString1, /// LongString: 0xb9 @@ -93,6 +96,35 @@ impl std::ops::Index for Vec { } } +/// index type of decode error +pub enum RlpDecodeErrorType { + /// the first byte is invalid, for example 0x00 for byte or 0xBF for list + HeaderDecError, + /// the length of rlp is invalid, for example 0xB854 or 0xB900FF for string + LenOfLenError, + /// the value of rlp is invalid, for example 0x8100 or 0x8179 for string + ValueError, + /// the rlp is not complete, for example 0xF8 for list + RunOutOfDataError, +} +const RLP_DECODE_ERROR_TYPE_NUM: usize = RlpDecodeErrorType::RunOutOfDataError as usize + 1; + +impl std::ops::Index for [T; N] { + type Output = T; + + fn index(&self, index: RlpDecodeErrorType) -> &Self::Output { + &self[index as usize] + } +} + +impl std::ops::Index for Vec { + type Output = T; + + fn index(&self, index: RlpDecodeErrorType) -> &Self::Output { + &self[index as usize] + } +} + // TODO: combine with TxFieldTag in table.rs // Marker that defines whether an Operation performs a `READ` or a `WRITE`. /// RlpTxFieldTag is used to tell the field of tx, used as state in the circuit @@ -121,6 +153,8 @@ pub enum RlpTxFieldTag { SignR, /// SignS SignS, + /// DecodeError + DecodeError, /// Padding Padding, // 1559 extra field @@ -198,8 +232,8 @@ pub struct RlpDecoderCircuitConfigWitness { pub acc_rlc_value: F, /// bytes pub bytes: Vec, //[u8; MAX_BYTE_COLUMN], - /// decodable, 0 for decode failed, 1 for success - pub decodable: bool, + /// decode error types: [header, len_of_len, value, run_out_of_data] + pub errors: [bool; RLP_DECODE_ERROR_TYPE_NUM], /// valid, 0 for invalid, 1 for valid, should be == decodable at the end of the circuit pub valid: bool, /// full chip enable @@ -240,8 +274,8 @@ pub struct RlpDecoderCircuitConfig { pub acc_rlc_value: Column, /// bytes pub bytes: [Column; MAX_BYTE_COLUMN_NUM], - /// decodable, 0 for decode failed, 1 for success - pub decodable: Column, + /// decode error types: [header, len_of_len, value, run_out_of_data] + pub errors: [Column; RLP_DECODE_ERROR_TYPE_NUM], /// valid, 0 for invalid, 1 for valid, should be == decodable at the end of the circuit pub valid: Column, /// dynamic selector for fields @@ -258,6 +292,10 @@ pub struct RlpDecoderCircuitConfig { pub v_gt_55: LtConfig, /// condition check for > 0 pub v_gt_0: LtConfig, + /// condition check for prev_remain_length > 33 + pub remain_length_gt_33: LtConfig, + /// condition check for prev_remain_length >= cur_length + pub remain_length_ge_length: LtConfig, } #[derive(Clone, Debug)] @@ -292,7 +330,12 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .collect::>>() .try_into() .unwrap(); - let decodable = meta.advice_column(); + let decode_errors: [Column; RLP_DECODE_ERROR_TYPE_NUM] = (0 + ..RLP_DECODE_ERROR_TYPE_NUM) + .map(|_| meta.advice_column()) + .collect::>>() + .try_into() + .unwrap(); let valid = meta.advice_column(); let q_tx_members: [Column; LEGACY_TX_FIELD_NUM as usize] = (0..LEGACY_TX_FIELD_NUM) .map(|_| meta.advice_column()) @@ -317,7 +360,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }; } - let v_gt_55 = LtChip::configure( + let cmp_55_lt_byte1 = LtChip::configure( meta, |meta| { rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList1) * meta.query_selector(q_enable) @@ -326,10 +369,11 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { |meta| meta.query_advice(bytes[1], Rotation::cur()), ); - let v_gt_0 = LtChip::configure( + let cmp_0_lt_byte1 = LtChip::configure( meta, |meta| { or::expr([ + rlp_type_enabled!(meta, RlpDecodeTypeTag::ShortStringValue), rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList2), rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList3), ]) * meta.query_selector(q_enable) @@ -338,9 +382,47 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { |meta| meta.query_advice(bytes[1], Rotation::cur()), ); + let cmp_33_lt_prev_remain: LtConfig = LtChip::configure( + meta, + |meta| { + not::expr(meta.query_advice(valid, Rotation::cur())) * meta.query_selector(q_enable) + }, + |_| 33.expr(), + |meta| meta.query_advice(rlp_remain_length, Rotation::prev()), + ); + + // less equal n => less than n+1 + let cmp_length_le_prev_remain: LtConfig = LtChip::configure( + meta, + |meta| meta.query_selector(q_enable), + |meta| meta.query_advice(rlp_tx_member_length, Rotation::cur()), + |meta| meta.query_advice(rlp_remain_length, Rotation::prev()) + 1.expr(), + ); + ///////////////////////////////// //// lookups //// ///////////////////////////// + // output txlist hash check + // meta.lookup_any("comsumed all bytes correctly", |meta| { + // let is_enabled = meta.query_fixed(q_first, Rotation::next()); + // let input_rlc = meta.query_advice(acc_rlc_value, Rotation::cur()); + // let input_len = meta.query_advice(rlp_remain_length, Rotation::cur()); + // let hash_rlc = meta.query_advice(value, Rotation::cur()); + + // let table = &aux_tables.keccak_table; + // let table_is_enabled = meta.query_advice(table.is_enabled, Rotation::cur()); + // let table_input_rlc = meta.query_advice(table.input_rlc, Rotation::cur()); + // let table_input_len = meta.query_advice(table.input_len, Rotation::cur()); + // let table_hash_rlc = meta.query_advice(table.output_rlc, Rotation::cur()); + + // vec![ + // (is_enabled.expr(), table_is_enabled.expr()), + // (is_enabled.expr() * input_rlc.expr(), table_input_rlc.expr()), + // (is_enabled.expr() * input_len.expr(), table_input_len.expr()), + // (is_enabled.expr() * hash_rlc.expr(), table_hash_rlc.expr()), + // ] + // }); + // bytes range check bytes.iter().for_each(|byte| { meta.lookup_any("rlp byte range check", |meta| { @@ -360,7 +442,10 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tx_type = meta.query_advice(tx_type, Rotation::cur()); let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); let byte0 = meta.query_advice(bytes[0], Rotation::cur()); - let decodable = meta.query_advice(decodable, Rotation::cur()); + let decodable = not::expr(meta.query_advice( + decode_errors[RlpDecodeErrorType::HeaderDecError], + Rotation::cur(), + )); let q_enable = meta.query_selector(q_enable); let is_not_partial = not::expr(rlp_type_enabled!(meta, RlpDecodeTypeTag::PartialRlp)); @@ -441,10 +526,12 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { "field complete boolean", meta.query_advice(complete, Rotation::cur()), ); - cb.require_boolean( - "decodable is boolean", - meta.query_advice(decodable, Rotation::cur()), - ); + decode_errors.iter().for_each(|error| { + cb.require_boolean( + "decode error is boolean", + meta.query_advice(*error, Rotation::cur()), + ); + }); cb.require_boolean( "valid is boolean", meta.query_advice(valid, Rotation::cur()), @@ -491,15 +578,26 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let valid_cur = meta.query_advice(valid, Rotation::cur()); let valid_next = meta.query_advice(valid, Rotation::next()); cb.require_equal( - "valid should be consistent", - valid_cur.expr(), + "valid should be consistent after invalid", + and::expr([valid_cur.expr(), valid_next.expr()]), valid_next.expr(), ); - let decodable = meta.query_advice(decodable, Rotation::cur()); - cb.require_zero( - "if decode == 0 then valid must 0", - not::expr(decodable.expr()) * valid_cur.expr(), + cb.require_equal( + "if any(errors) then valid must 0", + or::expr( + decode_errors + .iter() + .map(|e| meta.query_advice(*e, Rotation::cur())) + .collect::>>(), + ), + not::expr(valid_cur.expr()), + ); + + cb.require_equal( + "check if bytes run out", + cmp_length_le_prev_remain.is_lt(meta, None), + valid_cur.expr(), ); cb.gate(and::expr([ @@ -534,13 +632,36 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }); cb.condition( rlp_type_enabled!(meta, RlpDecodeTypeTag::SingleByte), - |cb| cb.require_equal("single length", rlp_tag_length_cur.clone(), 1.expr()), + |cb| { + cb.require_equal("single length", rlp_tag_length_cur.clone(), 1.expr()); + // TODO: + }, ); cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::NullValue), |cb| { cb.require_equal("empty length", rlp_tag_length_cur.clone(), 1.expr()) }); cb.condition( - rlp_type_enabled!(meta, RlpDecodeTypeTag::ShortString), + rlp_type_enabled!(meta, RlpDecodeTypeTag::ShortStringValue), + |cb| { + cb.require_equal( + "ShortStringValue length", + rlp_tag_length_cur.clone(), + byte_cells_cur[0].expr() - 0x80.expr() + 1.expr(), + ); + + // 0x8100 is invalid for value, 0x8180 instead + cb.require_equal( + "v should be >0", + cmp_0_lt_byte1.is_lt(meta, None), + not::expr(meta.query_advice( + decode_errors[RlpDecodeErrorType::ValueError], + Rotation::cur(), + )), + ) + }, + ); + cb.condition( + rlp_type_enabled!(meta, RlpDecodeTypeTag::ShortStringBytes), |cb| { cb.require_equal( "ShortString length", @@ -554,9 +675,20 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { |cb| { cb.require_equal( "Long String 0xb8 length", - rlp_tag_length_cur.clone(), + rlp_tag_length_cur.expr(), byte_cells_cur[1].expr() + 2.expr(), - ) + ); + + let len_valid = not::expr(meta.query_advice( + decode_errors[RlpDecodeErrorType::LenOfLenError], + Rotation::cur(), + )); + // 0x8100 is invalid for value, 0x8180 instead + cb.require_equal( + "length of 0xb8 should be >55", + cmp_55_lt_byte1.is_lt(meta, None), + len_valid.expr(), + ); }, ); cb.condition( @@ -566,6 +698,16 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { "Long String 0xb9 length", rlp_tag_length_cur.clone(), byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr() + 3.expr(), + ); + + // 0x8100 is invalid for value, 0x8180 instead + cb.require_equal( + "lenght 0 of 0xb9 should be >0", + cmp_0_lt_byte1.is_lt(meta, None), + not::expr(meta.query_advice( + decode_errors[RlpDecodeErrorType::LenOfLenError], + Rotation::cur(), + )), ) }, ); @@ -579,6 +721,15 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { + byte_cells_cur[2].expr() * 256.expr() + byte_cells_cur[3].expr() + 4.expr(), + ); + // 0x8100 is invalid for value, 0x8180 instead + cb.require_equal( + "length 0 of 0xba should be >0", + cmp_0_lt_byte1.is_lt(meta, None), + not::expr(meta.query_advice( + decode_errors[RlpDecodeErrorType::LenOfLenError], + Rotation::cur(), + )), ) }, ); @@ -664,7 +815,10 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); + let decodable = not::expr(meta.query_advice( + decode_errors[RlpDecodeErrorType::HeaderDecError], + Rotation::cur(), + )); let q_first = meta.query_fixed(q_first, Rotation::cur()); cb.require_zero("0 tx_id", tx_id); @@ -680,7 +834,11 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ); // TODO: byte_cells_cur[1] > 55, and check with len_decode flag - cb.require_equal("v should be >55", v_gt_55.is_lt(meta, None), 1.expr()) + cb.require_equal( + "v should be >55", + cmp_55_lt_byte1.is_lt(meta, None), + 1.expr(), + ) }); cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList2), |cb| { cb.require_equal( @@ -689,7 +847,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr(), ); // TODO: byte_cells_cur[1] != 0, and check with len_decode flag - cb.require_equal("v should be >0", v_gt_0.is_lt(meta, None), 1.expr()) + cb.require_equal("v should be >0", cmp_0_lt_byte1.is_lt(meta, None), 1.expr()) }); cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList3), |cb| { cb.require_equal( @@ -700,7 +858,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { + byte_cells_cur[3].expr(), ); // TODO: byte_cells_cur[1] != 0, and check with len_decode flag - cb.require_equal("v should be >0", v_gt_0.is_lt(meta, None), 1.expr()) + cb.require_equal("v should be >0", cmp_0_lt_byte1.is_lt(meta, None), 1.expr()) }); cb.condition(decodable, |cb| { @@ -736,7 +894,10 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); - let decodable = meta.query_advice(decodable, Rotation::cur()); + let decodable = not::expr(meta.query_advice( + decode_errors[RlpDecodeErrorType::HeaderDecError], + Rotation::cur(), + )); let q_tx_rlp_header = meta.query_advice(q_tx_members[RlpTxFieldTag::TxRlpHeader], Rotation::cur()); @@ -822,6 +983,60 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.gate(q_last * q_enable) }); + // decode error + meta.create_gate("Decode Error", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); + let complete = meta.query_advice(complete, Rotation::cur()); + let length = meta.query_advice(rlp_tx_member_length, Rotation::cur()); + let r_mult = meta.query_advice(r_mult, Rotation::cur()); + let prev_remain_length = meta.query_advice(rlp_remain_length, Rotation::prev()); + let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); + let prev_row_valid = meta.query_advice(valid, Rotation::prev()); + let q_error = + meta.query_advice(q_tx_members[RlpTxFieldTag::DecodeError], Rotation::cur()); + + cb.require_equal("tag", tx_member_cur, RlpTxFieldTag::DecodeError.expr()); + cb.require_equal("field completed", complete.expr(), 1.expr()); + cb.require_equal("padding has 1 r_mult", r_mult, 1.expr()); + + // if prev_remain > 33, then length = 33 else, length = prev_remain + cb.condition(cmp_33_lt_prev_remain.is_lt(meta, None), |cb| { + cb.require_equal("decode_error length = 33", length.expr(), 33.expr()); + }); + cb.condition(not::expr(cmp_33_lt_prev_remain.is_lt(meta, None)), |cb| { + cb.require_equal( + "decode_error length = remain", + length.expr(), + remain_length.expr(), + ); + }); + + // remain_length = prev_remain_length - length; + cb.require_equal( + "remain_length = prev_remain - length_cur", + remain_length.expr(), + prev_remain_length.expr() - length.expr(), + ); + cb.require_zero("row above error has error", prev_row_valid.expr()); + + cb.gate(q_error.expr() * meta.query_selector(q_enable)) + }); + + meta.create_gate("end with padding", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let q_enable = meta.query_selector(q_enable); + let q_last = meta.query_fixed(q_last, Rotation::cur()); + let q_padding = + meta.query_advice(q_tx_members[RlpTxFieldTag::Padding], Rotation::cur()); + + cb.require_equal("padding at last", q_padding, 1.expr()); + + cb.gate(q_last * q_enable) + }); + let circuit_config = RlpDecoderCircuitConfig { tx_id, tx_type, @@ -836,15 +1051,17 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { value, acc_rlc_value, bytes, - decodable, + errors: decode_errors, valid, q_tx_members, q_enable, q_first, q_last, aux_tables, - v_gt_55, - v_gt_0, + v_gt_55: cmp_55_lt_byte1, + v_gt_0: cmp_0_lt_byte1, + remain_length_gt_33: cmp_33_lt_prev_remain, + remain_length_ge_length: cmp_length_le_prev_remain, }; circuit_config } @@ -859,15 +1076,31 @@ impl RlpDecoderCircuitConfig { ) -> Result<(), Error> { let mut offset = offset; self.name_row_members(region); + + let mut prev_wit = wits.last().unwrap(); for wit in wits { let gt_55_chip = LtChip::construct(self.v_gt_55); let gt_0_chip = LtChip::construct(self.v_gt_0); + let gt_33_chip = LtChip::construct(self.remain_length_gt_33); + let enough_remain_chip = LtChip::construct(self.remain_length_ge_length); + let leading_val = if wit.bytes.len() > 1 { wit.bytes[1] } else { 0 }; gt_55_chip.assign(region, offset, F::from(55u64), F::from(leading_val as u64))?; gt_0_chip.assign(region, offset, F::zero(), F::from(leading_val as u64))?; + let remain_bytes = prev_wit.rlp_remain_length as u64; + let current_member_bytes = wit.rlp_tx_member_length; + gt_33_chip.assign(region, offset, F::from(33u64), F::from(remain_bytes))?; + enough_remain_chip.assign( + region, + offset, + F::from(current_member_bytes), + F::from(remain_bytes) + F::one(), + )?; + self.assign_row(region, offset, wit)?; + prev_wit = wit; offset += 1; } Ok(()) @@ -887,7 +1120,9 @@ impl RlpDecoderCircuitConfig { for (i, byte) in self.bytes.iter().enumerate() { region.name_column(|| format!("config.bytes-[{}]", i), *byte); } - region.name_column(|| "config.decodable", self.decodable); + for (i, error) in self.errors.iter().enumerate() { + region.name_column(|| format!("config.errors-[{}]", i), *error); + } region.name_column(|| "config.valid", self.valid); } @@ -993,12 +1228,14 @@ impl RlpDecoderCircuitConfig { }, )?; } - region.assign_advice( - || "config.decodable", - self.decodable, - offset, - || Value::known(F::from(w.decodable)), - )?; + for (i, error) in self.errors.iter().enumerate() { + region.assign_advice( + || format!("config.errors[{}]", i), + *error, + offset, + || Value::known(F::from(w.errors[i] as u64)), + )?; + } region.assign_advice( || "config.valid", self.valid, @@ -1143,6 +1380,11 @@ impl SubCircuit for RlpDecoderCircuit { .rlp_fixed_table .load(layouter, challenges)?; + config + .aux_tables + .keccak_table + .dev_load(layouter, &[self.bytes.clone()], challenges)?; + layouter.assign_region( || "rlp witness region", |mut region| { @@ -1203,26 +1445,56 @@ impl Circuit for RlpDecoderCircuit { } } -fn generate_rlp_type_witness(header_byte: u8) -> (RlpDecodeTypeTag, bool) { - let mut decodable = true; +fn generate_rlp_type_witness( + tx_member: &RlpTxFieldTag, + bytes: &[u8], +) -> (RlpDecodeTypeTag, bool, bool, bool) { + let mut header_decodable = true; + let mut len_decodable = true; + let mut value_decodable = true; + let header_byte = bytes[0]; let rlp_type = match header_byte { - 0x00..=0x7f => RlpDecodeTypeTag::SingleByte, + 0x00 => { + value_decodable = false; + RlpDecodeTypeTag::SingleByte + } + 0x01..=0x7f => RlpDecodeTypeTag::SingleByte, 0x80 => RlpDecodeTypeTag::NullValue, - 0x81..=0xb7 => RlpDecodeTypeTag::ShortString, - 0xb8 => RlpDecodeTypeTag::LongString1, - 0xb9 => RlpDecodeTypeTag::LongString2, - 0xba => RlpDecodeTypeTag::LongString3, + 0x81..=0xb7 => { + if header_byte == 0x81 { + value_decodable = bytes[1] >= 0x80; + } else { + value_decodable = bytes[1] >= 0; + } + match tx_member { + RlpTxFieldTag::To => RlpDecodeTypeTag::ShortStringBytes, + RlpTxFieldTag::Data => RlpDecodeTypeTag::ShortStringBytes, + _ => RlpDecodeTypeTag::ShortStringValue, + } + } + 0xb8 => { + len_decodable = bytes[1] >= 0x80; + RlpDecodeTypeTag::LongString1 + } + 0xb9 => { + len_decodable = bytes[1] >= 0; + RlpDecodeTypeTag::LongString2 + } + 0xba => { + len_decodable = bytes[1] >= 0; + RlpDecodeTypeTag::LongString3 + } 0xc0 => RlpDecodeTypeTag::EmptyList, 0xc1..=0xf7 => RlpDecodeTypeTag::ShortList, 0xf8 => RlpDecodeTypeTag::LongList1, 0xf9 => RlpDecodeTypeTag::LongList2, 0xfa => RlpDecodeTypeTag::LongList3, _ => { - decodable = false; + header_decodable = false; RlpDecodeTypeTag::DoNothing } }; - (rlp_type, decodable) + (rlp_type, header_decodable, len_decodable, value_decodable) } fn generate_fields_witness_len(tag: &RlpTxFieldTag, payload: &PayloadInfo) -> usize { @@ -1241,7 +1513,8 @@ fn generate_rlp_row_witness( rlp_remain_length: usize, ) -> Vec> { let mut witness = vec![]; - let (mut rlp_type, decodable) = generate_rlp_type_witness(raw_bytes[0]); + let (mut rlp_type, header_decodable, len_decodable, value_decodable) = + generate_rlp_type_witness(tx_member, raw_bytes); let partial_rlp_type = RlpDecodeTypeTag::PartialRlp; let rlp_tag_len = raw_bytes.len(); let mut prev_rlp_remain_length = rlp_remain_length; @@ -1266,8 +1539,8 @@ fn generate_rlp_row_witness( acc_rlc_value: F::zero(), bytes: raw_bytes[raw_bytes_offset..raw_bytes_offset + MAX_BYTE_COLUMN_NUM] .to_vec(), - decodable: decodable, - valid: true, + errors: [!header_decodable, !len_decodable, !value_decodable, false], + valid: header_decodable && len_decodable && value_decodable, q_enable: true, q_first: false, q_last: false, @@ -1290,8 +1563,8 @@ fn generate_rlp_row_witness( value: F::zero(), acc_rlc_value: F::zero(), bytes: raw_bytes[raw_bytes_offset..].to_vec(), - decodable: decodable, - valid: true, + errors: [!header_decodable, !len_decodable, !value_decodable, false], + valid: header_decodable && len_decodable && value_decodable, q_enable: true, q_first: false, q_last: false, @@ -1553,11 +1826,30 @@ fn rlp_decode_tx_list_manually( let witness_len = witness.len(); assert!(k > (witness_len + 2 + NUM_BLINDING_ROWS) as u32); - let complete_witness = complete_paddings( + let mut complete_witness = complete_paddings( &mut witness, k as usize - witness_len - 2 - NUM_BLINDING_ROWS, ); + // make sure we have comsumed all bytes + assert!(complete_witness[0].rlp_remain_length == bytes.len()); + debug_assert_eq!( + complete_witness[0].acc_rlc_value, + bytes + .iter() + .rev() + .fold(F::zero(), |acc, b| acc * r + F::from(*b as u64)) + ); + + // update the rlp bytes hash + let mut hasher = Keccak::default(); + hasher.update(bytes); + let hash = hasher.digest(); + complete_witness[0].value = hash + .iter() + .rev() + .fold(F::zero(), |acc, b| acc * r + F::from(*b as u64)); + for iw in complete_witness.iter().enumerate() { log::trace!("witness[{}] {:?}", iw.0, iw.1); } @@ -1584,6 +1876,7 @@ fn complete_paddings( let mut pre_padding = RlpDecoderCircuitConfigWitness::::default(); pre_padding.rlp_remain_length = witness[0].rlp_remain_length + witness[0].rlp_bytes_in_row as usize; + pre_padding.acc_rlc_value = witness[0].acc_rlc_value; complete_witness.push(pre_padding); witness[0].q_first = true; @@ -1603,7 +1896,7 @@ fn complete_paddings( value: F::zero(), acc_rlc_value: F::zero(), bytes: [0; MAX_BYTE_COLUMN_NUM].to_vec(), - decodable: true, + errors: [false, false, false, false], valid: true, q_enable: true, q_first: false, @@ -1709,6 +2002,7 @@ mod rlp_test { use ethers_core::utils::rlp; use halo2_proofs::halo2curves::bn256::Fr; use hex; + use keccak256::plain::Keccak; use mock::AddrOrWallet; use rand::SeedableRng; use rand_chacha::ChaCha20Rng; @@ -1827,6 +2121,23 @@ mod rlp_test { } } + #[test] + fn test_keccak() { + let tx: SignedTransaction = mock::CORRECT_MOCK_TXS[0].clone().into(); + let rlp_txs = rlp::encode_list(&[tx]); + println!("rlp_txs = {:?}", hex::encode(rlp_txs.clone())); + // update the rlp bytes hash + let mut hasher = Keccak::default(); + hasher.update(&rlp_txs.to_vec()); + let hash = hasher.digest(); + println!("hash = {:?}", hex::encode(&hash)); + + let rlc = hash.iter().fold(Fr::zero(), |acc, b| { + acc * Fr::from(11 as u64) + Fr::from(*b as u64) + }); + println!("rlc = {:?}", rlc); + } + #[test] fn test_wrong_witness_generation() { todo!() diff --git a/zkevm-circuits/src/rlp_decoder_tables.rs b/zkevm-circuits/src/rlp_decoder_tables.rs index b387f95028..e0c151f0a1 100644 --- a/zkevm-circuits/src/rlp_decoder_tables.rs +++ b/zkevm-circuits/src/rlp_decoder_tables.rs @@ -28,15 +28,14 @@ pub enum RlpDecodeRule { Empty, /// The RLP encoding type is a uint96 Uint64, - /// The RLP encoding type is a uint96 + /// The RLP encoding type is a uint96, for gas/nonce/price/ect Uint96, - /// The RLP encoding type is a uint256 + /// The RLP encoding type is a uint256, normally for signature Uint256, /// The RLP encoding type is a address 20bytes i.e., 0x94xxxx Address, - /// The RLP encoding type is a hash string 32bytes, i.e., 0xa0xxx - Bytes32, - /// The RLP encoding type is a string which is upto 48k bytes + /// The RLP encoding type is a string which is upto 48k bytes, a exception is it accepts + /// leading 00 Bytes48K, /// The RLP encoding empty list type EmptyList, @@ -50,8 +49,8 @@ impl RlpDecodeRule { /// | legacy | nonce | uint96 | 0x00 | false | /// | legacy | nonce | uint96 | 0x01 | true | /// ... - /// | legacy | signS | byte32 | 0xa0 | true | - /// | legacy | signS | byte32 | 0xa1 | false | + /// | legacy | signS | uint256 | 0xa0 | true | + /// | legacy | signS | byte256 | 0xa1 | false | /// ... pub fn rule_check(&self, byte0: u8) -> (RlpDecodeTypeTag, bool) { let (rlp_type, decodable) = match self { @@ -63,41 +62,36 @@ impl RlpDecodeRule { RlpDecodeRule::Uint64 => match byte0 { // 0 is error: non-canonical integer (leading zero bytes) for uint64 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), - 0x81..=0x88 => (RlpDecodeTypeTag::ShortString, true), + 0x81..=0x88 => (RlpDecodeTypeTag::ShortStringValue, true), _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::Uint96 => match byte0 { // 0 is error: non-canonical integer (leading zero bytes) for uint96 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), - 0x81..=0x8c => (RlpDecodeTypeTag::ShortString, true), + 0x81..=0x8c => (RlpDecodeTypeTag::ShortStringValue, true), _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::Uint256 => match byte0 { // 0 is error: non-canonical integer (leading zero bytes) for uint256 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), - 0x81..=0xa0 => (RlpDecodeTypeTag::ShortString, true), + 0x81..=0xa0 => (RlpDecodeTypeTag::ShortStringValue, true), _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::Address => match byte0 { - 0x94 => (RlpDecodeTypeTag::ShortString, true), - _ => (RlpDecodeTypeTag::DoNothing, false), - }, - RlpDecodeRule::Bytes32 => match byte0 { - // TODO: what if sig is less then 32 bytes? - 0xa0 => (RlpDecodeTypeTag::ShortString, true), + 0x94 => (RlpDecodeTypeTag::ShortStringBytes, true), _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::Bytes48K => match byte0 { 0 => (RlpDecodeTypeTag::SingleByte, true), // 0x00 1..=0x80 => (RlpDecodeTypeTag::SingleByte, true), // 0x01..=0x80 - 0x81..=0xb7 => (RlpDecodeTypeTag::ShortString, true), + 0x81..=0xb7 => (RlpDecodeTypeTag::ShortStringBytes, true), 0xb8 => (RlpDecodeTypeTag::LongString1, true), 0xb9 => (RlpDecodeTypeTag::LongString2, true), 0xba => (RlpDecodeTypeTag::LongString3, true), _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::EmptyList => match byte0 { - 0xc0 => (RlpDecodeTypeTag::ShortString, false), + 0xc0 => (RlpDecodeTypeTag::EmptyList, false), _ => (RlpDecodeTypeTag::DoNothing, false), }, RlpDecodeRule::LongList => match byte0 { @@ -111,6 +105,75 @@ impl RlpDecodeRule { } } +/// rules of tx members +pub const RLP_TX_FIELD_DECODE_RULES: [(RlpTxTypeTag, RlpTxFieldTag, RlpDecodeRule); 13] = [ + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::TxListRlpHeader, + RlpDecodeRule::LongList, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::TxRlpHeader, + RlpDecodeRule::LongList, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::Nonce, + RlpDecodeRule::Uint96, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::GasPrice, + RlpDecodeRule::Uint96, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::Gas, + RlpDecodeRule::Uint96, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::To, + RlpDecodeRule::Address, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::To, + RlpDecodeRule::Empty, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::Value, + RlpDecodeRule::Uint96, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::Data, + RlpDecodeRule::Bytes48K, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::SignV, + RlpDecodeRule::Uint96, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::SignR, + RlpDecodeRule::Uint256, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::SignS, + RlpDecodeRule::Uint256, + ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::Padding, + RlpDecodeRule::Padding, + ), +]; + /// Table that contains the fields of all possible RLP decodable fields #[derive(Clone, Debug)] pub struct RlpDecoderTable { @@ -166,81 +229,13 @@ impl RlpDecoderTable { _challenges: &Challenges>, ) -> Result<(), Error> { // make a list with all member of rlpTxFieldTag literally - let rlp_tx_field_decode_rules: Vec<(RlpTxTypeTag, RlpTxFieldTag, RlpDecodeRule)> = vec![ - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::TxListRlpHeader, - RlpDecodeRule::LongList, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::TxRlpHeader, - RlpDecodeRule::LongList, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::Nonce, - RlpDecodeRule::Uint96, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::GasPrice, - RlpDecodeRule::Uint96, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::Gas, - RlpDecodeRule::Uint96, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::To, - RlpDecodeRule::Address, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::To, - RlpDecodeRule::Empty, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::Value, - RlpDecodeRule::Uint96, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::Data, - RlpDecodeRule::Bytes48K, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::SignV, - RlpDecodeRule::Uint96, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::SignR, - RlpDecodeRule::Uint256, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::SignS, - RlpDecodeRule::Uint256, - ), - ( - RlpTxTypeTag::TxLegacyType, - RlpTxFieldTag::Padding, - RlpDecodeRule::Padding, - ), - ]; - layouter.assign_region( || "load rlp decoder table", |mut region| { let mut offset = 0; let table_tag = RlpDecoderFixedTableTag::RlpDecoderTable as u64; - for (tx_type, tx_field_tag, decode_rule) in rlp_tx_field_decode_rules.iter() { + for (tx_type, tx_field_tag, decode_rule) in RLP_TX_FIELD_DECODE_RULES.iter() { for byte_val in 0..=255u8 { let (rlp_type, decodable) = decode_rule.rule_check(byte_val); let rule_table_row = [ @@ -293,21 +288,64 @@ pub struct TxFieldSwitchTable { pub next_tx_field: Column, } -static TX_FIELD_TRANSITION_TABLE: [(RlpTxFieldTag, RlpTxFieldTag); 14] = [ - (RlpTxFieldTag::TxListRlpHeader, RlpTxFieldTag::TxRlpHeader), - (RlpTxFieldTag::TxRlpHeader, RlpTxFieldTag::Nonce), - (RlpTxFieldTag::Nonce, RlpTxFieldTag::GasPrice), - (RlpTxFieldTag::GasPrice, RlpTxFieldTag::Gas), - (RlpTxFieldTag::Gas, RlpTxFieldTag::To), - (RlpTxFieldTag::To, RlpTxFieldTag::Value), - (RlpTxFieldTag::Value, RlpTxFieldTag::Data), - (RlpTxFieldTag::Data, RlpTxFieldTag::Data), - (RlpTxFieldTag::Data, RlpTxFieldTag::SignV), - (RlpTxFieldTag::SignV, RlpTxFieldTag::SignR), - (RlpTxFieldTag::SignR, RlpTxFieldTag::SignS), - (RlpTxFieldTag::SignS, RlpTxFieldTag::TxRlpHeader), - (RlpTxFieldTag::SignS, RlpTxFieldTag::Padding), - (RlpTxFieldTag::Padding, RlpTxFieldTag::Padding), +static TX_FIELD_TRANSITION_TABLE: [(RlpTxFieldTag, &[RlpTxFieldTag]); 15] = [ + ( + RlpTxFieldTag::TxListRlpHeader, + &[RlpTxFieldTag::TxRlpHeader, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::TxRlpHeader, + &[RlpTxFieldTag::Nonce, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::Nonce, + &[RlpTxFieldTag::GasPrice, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::GasPrice, + &[RlpTxFieldTag::Gas, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::Gas, + &[RlpTxFieldTag::To, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::To, + &[RlpTxFieldTag::Value, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::Value, + &[RlpTxFieldTag::Data, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::Data, + &[RlpTxFieldTag::Data, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::Data, + &[RlpTxFieldTag::SignV, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::SignV, + &[RlpTxFieldTag::SignR, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::SignR, + &[RlpTxFieldTag::SignS, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::SignS, + &[RlpTxFieldTag::TxRlpHeader, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::SignS, + &[RlpTxFieldTag::Padding, RlpTxFieldTag::DecodeError], + ), + ( + RlpTxFieldTag::DecodeError, + &[RlpTxFieldTag::Padding, RlpTxFieldTag::DecodeError], + ), + (RlpTxFieldTag::Padding, &[RlpTxFieldTag::Padding]), // TODO: add 1559 fields ]; @@ -351,30 +389,32 @@ impl TxFieldSwitchTable { let mut offset = 0; tx_field_trans_table .iter() - .try_for_each(|(current_tx_field, next_tx_field)| { - region.assign_fixed( - || "table tag", - self.table_tag, - offset, - || { - Value::known(F::from( - RlpDecoderFixedTableTag::TxFieldSwitchTable as u64, - )) - }, - )?; - region.assign_fixed( - || "current tx field", - self.current_tx_field, - offset, - || Value::known(F::from(*current_tx_field as u64)), - )?; - region.assign_fixed( - || "next tx field", - self.next_tx_field, - offset, - || Value::known(F::from(*next_tx_field as u64)), - )?; - offset += 1; + .try_for_each(|(current_tx_field, next_tx_fields)| { + for next_tx_field in next_tx_fields.iter() { + region.assign_fixed( + || "table tag", + self.table_tag, + offset, + || { + Value::known(F::from( + RlpDecoderFixedTableTag::TxFieldSwitchTable as u64, + )) + }, + )?; + region.assign_fixed( + || "current tx field", + self.current_tx_field, + offset, + || Value::known(F::from(*current_tx_field as u64)), + )?; + region.assign_fixed( + || "next tx field", + self.next_tx_field, + offset, + || Value::known(F::from(*next_tx_field as u64)), + )?; + offset += 1; + } Ok(()) }) }, From 79aa3c6cdb52213301ea4bd44257f70d23eb892d Mon Sep 17 00:00:00 2001 From: smtmfft Date: Fri, 2 Jun 2023 14:22:52 +0000 Subject: [PATCH 13/21] try using big endian to align with keccak, meanwhile rlc::xxx using little endian --- zkevm-circuits/src/rlp_decoder.rs | 137 ++++++++++++++++++------------ 1 file changed, 85 insertions(+), 52 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index f6ef78b322..2ec2527aea 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -242,6 +242,10 @@ pub struct RlpDecoderCircuitConfigWitness { pub q_first: bool, /// the end pub q_last: bool, + /// r_mult_comp + pub r_mult_comp: F, + /// rlc_quotient + pub rlc_quotient: F, } /// Config for RlpDecoderCircuit @@ -264,7 +268,7 @@ pub struct RlpDecoderCircuitConfig { /// remained rows, for n < 33 fields, it is n, for m > 33 fields, it is 33 and next row is /// partial, next_length = m - 33 pub rlp_bytes_in_row: Column, - /// r_mult column, (length, r_mult) => @fixed + /// r_mult column, (length, r_mult) => @fixed, r_mult == r ^ length pub r_mult: Column, /// remain_length, to be 0 at the end. pub rlp_remain_length: Column, @@ -296,6 +300,10 @@ pub struct RlpDecoderCircuitConfig { pub remain_length_gt_33: LtConfig, /// condition check for prev_remain_length >= cur_length pub remain_length_ge_length: LtConfig, + /// divide factor for big endian rlc, r_mult_comp * r_mult = r ^ MAX_BYTE_COLUMN_NUM(33) + pub r_mult_comp: Column, + /// quotient value for big endian rlc, rlc_quotient = rlc[0..MAX_BYTE_COLUMN_NUM] / r_mult_comp + pub rlc_quotient: Column, } #[derive(Clone, Debug)] @@ -345,6 +353,8 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let q_enable = meta.complex_selector(); let q_first = meta.fixed_column(); let q_last = meta.fixed_column(); + let r_mult_comp = meta.advice_column(); + let rlc_quotient = meta.advice_column(); // type checking let q_rlp_types: [Column; RlpDecodeTypeTag::RlpDecodeTypeNum as usize] = (0 @@ -493,7 +503,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ] }); - // lookup r_mult table with length, + // lookup r_mult/r_mult_comp table with length, // TODO: r_mult is adv, add constraint for pow meta.lookup_any("rlp r_mult check", |meta| { let r_mult = meta.query_advice(r_mult, Rotation::cur()); @@ -514,6 +524,25 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { (q_enable.expr() * pow, r_pow_in_table), ] }); + meta.lookup_any("rlp r_mult_comp check", |meta| { + let r_mult_comp = meta.query_advice(r_mult_comp, Rotation::cur()); + let pow = 33.expr() - meta.query_advice(tx_member_bytes_in_row, Rotation::cur()); + + let table = &aux_tables.rlp_fixed_table.r_mult_pow_table; + let table_tag = meta.query_fixed(table.table_tag, Rotation::cur()); + let r_mult_in_table = meta.query_fixed(table.r_mult, Rotation::cur()); + let r_pow_in_table = meta.query_fixed(table.length, Rotation::cur()); + + let q_enable = meta.query_selector(q_enable); + vec![ + ( + q_enable.expr() * RlpDecoderFixedTableTag::RMult.expr(), + table_tag, + ), + (q_enable.expr() * r_mult_comp, r_mult_in_table), + (q_enable.expr() * pow, r_pow_in_table), + ] + }); ///////////////////////////////// //// constraints @@ -575,6 +604,26 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { 1.expr(), ); + let r_mult = meta.query_advice(r_mult, Rotation::cur()); + let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); + let rev_byte_cells = bytes + .iter() + .rev() + .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) + .collect::>(); + let rlc_quotient = meta.query_advice(rlc_quotient, Rotation::cur()); + let r_mult_comp = meta.query_advice(r_mult_comp, Rotation::cur()); + cb.require_equal( + "rlc_quotient = rlc[0..32]/r_mult_comp", + rlc_quotient.expr() * r_mult_comp.expr(), + rlc::expr(&rev_byte_cells, aux_tables.challenges.keccak_input()), + ); + cb.require_equal( + "rlc = prev_rlc * r_mult + rlc[0..32]/r_mult_comp", + acc_rlc_cur, + r_mult * meta.query_advice(acc_rlc_value, Rotation::prev()) + rlc_quotient.expr(), + ); + let valid_cur = meta.query_advice(valid, Rotation::cur()); let valid_next = meta.query_advice(valid, Rotation::next()); cb.require_equal( @@ -613,10 +662,8 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tag = meta.query_advice(tx_member, Rotation::cur()); let complete_cur = meta.query_advice(complete, Rotation::cur()); let rlp_tag_length_cur = meta.query_advice(rlp_tx_member_length, Rotation::cur()); - let r_mult = meta.query_advice(r_mult, Rotation::cur()); let bytes_in_row_cur = meta.query_advice(tx_member_bytes_in_row, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); - let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); let byte_cells_cur = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) @@ -785,13 +832,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ); }); - cb.require_equal( - "rlc = r_mult_cur * rlc_next + rlc(bytes_cur)", - acc_rlc_cur, - r_mult * meta.query_advice(acc_rlc_value, Rotation::next()) - + rlc::expr(&byte_cells_cur, aux_tables.challenges.keccak_input()), - ); - cb.gate(and::expr([ q_enable, not::expr(q_first), @@ -808,9 +848,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); let complete = meta.query_advice(complete, Rotation::cur()); let rlp_tag_length_cur = meta.query_advice(rlp_tx_member_length, Rotation::cur()); - let r_mult = meta.query_advice(r_mult, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); - let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); let byte_cells_cur = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) @@ -869,13 +907,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ); }); - cb.require_equal( - "rlc = r_mult_cur * rlc_next + rlc(bytes_cur)", - acc_rlc_cur, - r_mult * meta.query_advice(acc_rlc_value, Rotation::next()) - + rlc::expr(&byte_cells_cur, aux_tables.challenges.keccak_input()), - ); - cb.gate(q_first) }); @@ -888,8 +919,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); let complete = meta.query_advice(complete, Rotation::cur()); let rlp_tag_length_cur = meta.query_advice(rlp_tx_member_length, Rotation::cur()); - let r_mult = meta.query_advice(r_mult, Rotation::cur()); - let acc_rlc_cur = meta.query_advice(acc_rlc_value, Rotation::cur()); let byte_cells_cur = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) @@ -926,13 +955,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ); }); - cb.require_equal( - "rlc = r_mult_cur * rlc_next + rlc(bytes_cur)", - acc_rlc_cur, - r_mult * meta.query_advice(acc_rlc_value, Rotation::next()) - + rlc::expr(&byte_cells_cur, aux_tables.challenges.keccak_input()), - ); - cb.gate(q_tx_rlp_header * meta.query_selector(q_enable)) }); @@ -1062,6 +1084,8 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { v_gt_0: cmp_0_lt_byte1, remain_length_gt_33: cmp_33_lt_prev_remain, remain_length_ge_length: cmp_length_le_prev_remain, + r_mult_comp, + rlc_quotient, }; circuit_config } @@ -1464,7 +1488,7 @@ fn generate_rlp_type_witness( if header_byte == 0x81 { value_decodable = bytes[1] >= 0x80; } else { - value_decodable = bytes[1] >= 0; + value_decodable = bytes[1] > 0; } match tx_member { RlpTxFieldTag::To => RlpDecodeTypeTag::ShortStringBytes, @@ -1477,11 +1501,11 @@ fn generate_rlp_type_witness( RlpDecodeTypeTag::LongString1 } 0xb9 => { - len_decodable = bytes[1] >= 0; + len_decodable = bytes[1] > 0; RlpDecodeTypeTag::LongString2 } 0xba => { - len_decodable = bytes[1] >= 0; + len_decodable = bytes[1] > 0; RlpDecodeTypeTag::LongString3 } 0xc0 => RlpDecodeTypeTag::EmptyList, @@ -1544,6 +1568,8 @@ fn generate_rlp_row_witness( q_enable: true, q_first: false, q_last: false, + r_mult_comp: F::one(), + rlc_quotient: F::zero(), }); raw_bytes_offset += MAX_BYTE_COLUMN_NUM; tag_remain_length -= MAX_BYTE_COLUMN_NUM; @@ -1568,6 +1594,8 @@ fn generate_rlp_row_witness( q_enable: true, q_first: false, q_last: false, + r_mult_comp: r.pow(&[(MAX_BYTE_COLUMN_NUM - tag_remain_length) as u64, 0, 0, 0]), + rlc_quotient: F::zero(), }); temp_witness_vec }}; @@ -1831,16 +1859,6 @@ fn rlp_decode_tx_list_manually( k as usize - witness_len - 2 - NUM_BLINDING_ROWS, ); - // make sure we have comsumed all bytes - assert!(complete_witness[0].rlp_remain_length == bytes.len()); - debug_assert_eq!( - complete_witness[0].acc_rlc_value, - bytes - .iter() - .rev() - .fold(F::zero(), |acc, b| acc * r + F::from(*b as u64)) - ); - // update the rlp bytes hash let mut hasher = Keccak::default(); hasher.update(bytes); @@ -1853,19 +1871,32 @@ fn rlp_decode_tx_list_manually( for iw in complete_witness.iter().enumerate() { log::trace!("witness[{}] {:?}", iw.0, iw.1); } + + // make sure we have comsumed all bytes + assert!(complete_witness[0].rlp_remain_length == bytes.len()); + debug_assert_eq!( + complete_witness[complete_witness.len() - 2].acc_rlc_value, + bytes + .iter() + .fold(F::zero(), |acc, b| acc * r + F::from(*b as u64)) + ); + complete_witness } fn fixup_acc_rlc(witness: &mut Vec>, randomness: F) { - let mut rev_iter = witness.iter_mut().rev(); + let mut wit_iter = witness.iter_mut(); let mut prev: Option<&mut RlpDecoderCircuitConfigWitness> = None; - while let Some(current_witness) = rev_iter.next() { - let prev_acc_rlc_value = - prev.map_or(F::zero(), |w| w.acc_rlc_value * current_witness.r_mult); - current_witness.acc_rlc_value = - prev_acc_rlc_value + rlc::value(¤t_witness.bytes, randomness); - - prev = Some(current_witness); + while let Some(cur_wit) = wit_iter.next() { + let prev_acc_rlc = prev.map_or(F::zero(), |w| w.acc_rlc_value); + let mut bytes = cur_wit.bytes.clone(); + bytes.resize(MAX_BYTE_COLUMN_NUM, 0); + bytes.reverse(); + cur_wit.rlc_quotient = + rlc::value(&bytes, randomness) * cur_wit.r_mult_comp.invert().unwrap(); + cur_wit.acc_rlc_value = prev_acc_rlc * cur_wit.r_mult + cur_wit.rlc_quotient; + + prev = Some(cur_wit); } } fn complete_paddings( @@ -1876,12 +1907,12 @@ fn complete_paddings( let mut pre_padding = RlpDecoderCircuitConfigWitness::::default(); pre_padding.rlp_remain_length = witness[0].rlp_remain_length + witness[0].rlp_bytes_in_row as usize; - pre_padding.acc_rlc_value = witness[0].acc_rlc_value; complete_witness.push(pre_padding); witness[0].q_first = true; complete_witness.append(witness); + let before_padding = complete_witness.last().unwrap().clone(); for i in 0..num_padding_to_last_row { complete_witness.push(RlpDecoderCircuitConfigWitness:: { tx_id: 0, @@ -1894,13 +1925,15 @@ fn complete_paddings( r_mult: F::one(), rlp_remain_length: 0, value: F::zero(), - acc_rlc_value: F::zero(), + acc_rlc_value: before_padding.acc_rlc_value, bytes: [0; MAX_BYTE_COLUMN_NUM].to_vec(), errors: [false, false, false, false], valid: true, q_enable: true, q_first: false, q_last: i == num_padding_to_last_row - 1, + r_mult_comp: F::one(), + rlc_quotient: F::zero(), }); } complete_witness.push(RlpDecoderCircuitConfigWitness::::default()); From 321c4df61db3ca3119c57b2a4b186cfe0bb25291 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Sun, 2 Jul 2023 10:09:17 +0000 Subject: [PATCH 14/21] fix error case witness generation --- zkevm-circuits/src/rlp_decoder.rs | 913 +++++++++++++++++++++-- zkevm-circuits/src/rlp_decoder_tables.rs | 7 +- 2 files changed, 862 insertions(+), 58 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 2ec2527aea..06444be9ad 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -5,7 +5,9 @@ use std::marker::PhantomData; use crate::{ evm_circuit::util::{constraint_builder::BaseConstraintBuilder, rlc}, impl_expr, - rlp_decoder_tables::{RlpDecoderFixedTable, RlpDecoderFixedTableTag}, + rlp_decoder_tables::{ + RlpDecodeRule, RlpDecoderFixedTable, RlpDecoderFixedTableTag, RLP_TX_FIELD_DECODE_RULES, + }, table::KeccakTable, util::{log2_ceil, Challenges, SubCircuit, SubCircuitConfig}, witness, @@ -96,6 +98,7 @@ impl std::ops::Index for Vec { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] /// index type of decode error pub enum RlpDecodeErrorType { /// the first byte is invalid, for example 0x00 for byte or 0xBF for list @@ -392,12 +395,12 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { |meta| meta.query_advice(bytes[1], Rotation::cur()), ); - let cmp_33_lt_prev_remain: LtConfig = LtChip::configure( + let cmp_bytes_in_row_lt_prev_remain: LtConfig = LtChip::configure( meta, |meta| { not::expr(meta.query_advice(valid, Rotation::cur())) * meta.query_selector(q_enable) }, - |_| 33.expr(), + |_| MAX_BYTE_COLUMN_NUM.expr(), |meta| meta.query_advice(rlp_remain_length, Rotation::prev()), ); @@ -1024,16 +1027,19 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_equal("padding has 1 r_mult", r_mult, 1.expr()); // if prev_remain > 33, then length = 33 else, length = prev_remain - cb.condition(cmp_33_lt_prev_remain.is_lt(meta, None), |cb| { + cb.condition(cmp_bytes_in_row_lt_prev_remain.is_lt(meta, None), |cb| { cb.require_equal("decode_error length = 33", length.expr(), 33.expr()); }); - cb.condition(not::expr(cmp_33_lt_prev_remain.is_lt(meta, None)), |cb| { - cb.require_equal( - "decode_error length = remain", - length.expr(), - remain_length.expr(), - ); - }); + cb.condition( + not::expr(cmp_bytes_in_row_lt_prev_remain.is_lt(meta, None)), + |cb| { + cb.require_equal( + "decode_error length = remain", + length.expr(), + remain_length.expr(), + ); + }, + ); // remain_length = prev_remain_length - length; cb.require_equal( @@ -1082,7 +1088,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { aux_tables, v_gt_55: cmp_55_lt_byte1, v_gt_0: cmp_0_lt_byte1, - remain_length_gt_33: cmp_33_lt_prev_remain, + remain_length_gt_33: cmp_bytes_in_row_lt_prev_remain, remain_length_ge_length: cmp_length_le_prev_remain, r_mult_comp, rlc_quotient, @@ -1476,10 +1482,10 @@ fn generate_rlp_type_witness( let mut header_decodable = true; let mut len_decodable = true; let mut value_decodable = true; - let header_byte = bytes[0]; + let header_byte = bytes.first().unwrap_or(&0).to_owned(); let rlp_type = match header_byte { 0x00 => { - value_decodable = false; + header_decodable = false; RlpDecodeTypeTag::SingleByte } 0x01..=0x7f => RlpDecodeTypeTag::SingleByte, @@ -1614,6 +1620,7 @@ fn generate_rlp_row_witness( RlpTxFieldTag::SignV => witness.append(&mut generate_witness!()), RlpTxFieldTag::SignR => witness.append(&mut generate_witness!()), RlpTxFieldTag::SignS => witness.append(&mut generate_witness!()), + RlpTxFieldTag::DecodeError => witness.append(&mut generate_witness!()), RlpTxFieldTag::Padding => { unreachable!("Padding should not be here") } @@ -1660,46 +1667,595 @@ fn generate_rlp_txfield_witness( } } -// trait RlpTxFieldWittnessGenerator { -// fn generate_rlp_txfield_witness( -// &self, -// tx_id: u64, -// bytes: &[u8], -// r: F, -// witness: &mut Vec>, -// ) -> Option; -// } - -// impl RlpTxFieldWittnessGenerator for RlpTxFieldTag { -// fn generate_rlp_txfield_witness( -// &self, -// tx_id: u64, -// bytes: &[u8], -// r: F, -// witness: &mut Vec>, -// ) -> Option { -// let offset = 0; -// let decode_result = PayloadInfo::from(&bytes[offset..]); -// match self { -// RlpTxFieldTag::TxListRlpHeader => todo!(), -// RlpTxFieldTag::TxRlpHeader => todo!(), -// RlpTxFieldTag::Nonce => todo!(), -// RlpTxFieldTag::GasPrice => todo!(), -// RlpTxFieldTag::Gas => todo!(), -// RlpTxFieldTag::To => todo!(), -// RlpTxFieldTag::Value => todo!(), -// RlpTxFieldTag::Data => todo!(), -// RlpTxFieldTag::SignV => todo!(), -// RlpTxFieldTag::SignR => todo!(), -// RlpTxFieldTag::SignS => todo!(), -// RlpTxFieldTag::Padding => todo!(), -// RlpTxFieldTag::ChainID => todo!(), -// RlpTxFieldTag::GasTipCap => todo!(), -// RlpTxFieldTag::GasFeeCap => todo!(), -// RlpTxFieldTag::AccessList => todo!(), -// } -// } -// } +trait RlpTxFieldStateWittnessGenerator { + fn next( + &self, + k: usize, + tx_id: u64, + bytes: &[u8], + r: F, + witness: &mut Vec>, + ) -> (Self, Option) + where + Self: Sized; + + fn rlp_decode_field_check( + &self, + bytes: &[u8], + tx_id: u64, + r: F, + decode_rule: &RlpDecodeRule, + witness: &mut Vec>, + next_state: RlpTxFieldTag, + ) -> (Self, Option) + where + Self: Sized; +} + +// using error to tell n +// consider the case which both error happens like 0xFA 0x00 0x01 EOF, both EOF error & len_of_len +// error happens +fn read_nbytes(bytes: &[u8], n: usize) -> Result<&[u8], &[u8]> { + if n <= bytes.len() { + Ok(&bytes[..n]) + } else { + Err(bytes) + } +} + +fn rlp_bytes_len(bytes: &[u8]) -> usize { + bytes.iter().fold(0, |acc, byte| acc * 256 + *byte as usize) +} + +impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { + fn next( + &self, + k: usize, + tx_id: u64, + bytes: &[u8], + r: F, + witness: &mut Vec>, + ) -> (Self, Option) { + let rule_entry_opt = RLP_TX_FIELD_DECODE_RULES + .iter() + .find(|rule| rule.0 == RlpTxTypeTag::TxLegacyType && rule.1 == *self); + let rule_entry = rule_entry_opt.unwrap(); + let (_, _, decode_rule) = rule_entry; + + macro_rules! state_switch { + ($next_state: expr) => { + self.rlp_decode_field_check(bytes, tx_id, r, &decode_rule, witness, $next_state) + }; + } + + match self { + RlpTxFieldTag::TxListRlpHeader => state_switch!(RlpTxFieldTag::TxRlpHeader), + RlpTxFieldTag::TxRlpHeader => state_switch!(RlpTxFieldTag::Nonce), + RlpTxFieldTag::Nonce => state_switch!(RlpTxFieldTag::GasPrice), + RlpTxFieldTag::GasPrice => state_switch!(RlpTxFieldTag::Gas), + RlpTxFieldTag::Gas => state_switch!(RlpTxFieldTag::To), + RlpTxFieldTag::To => state_switch!(RlpTxFieldTag::Value), + RlpTxFieldTag::Value => state_switch!(RlpTxFieldTag::Data), + RlpTxFieldTag::Data => state_switch!(RlpTxFieldTag::SignV), + RlpTxFieldTag::SignV => state_switch!(RlpTxFieldTag::SignR), + RlpTxFieldTag::SignR => state_switch!(RlpTxFieldTag::SignS), + RlpTxFieldTag::SignS => { + // Tricky: we need to check if the bytes hold SignS only. + let next_state = if bytes.len() == MAX_BYTE_COLUMN_NUM { + RlpTxFieldTag::Padding + } else { + RlpTxFieldTag::TxRlpHeader + }; + self.rlp_decode_field_check(bytes, tx_id, r, &decode_rule, witness, next_state) + } + RlpTxFieldTag::Padding => { + let witness_len = witness.len(); + assert!(k > (witness_len + 2 + NUM_BLINDING_ROWS)); + fixup_acc_rlc_new(witness, r); + complete_paddings_new(witness, k as usize - witness_len - 2 - NUM_BLINDING_ROWS); + (RlpTxFieldTag::Padding, None) + } + RlpTxFieldTag::ChainID => todo!(), + RlpTxFieldTag::GasTipCap => todo!(), + RlpTxFieldTag::GasFeeCap => todo!(), + RlpTxFieldTag::AccessList => todo!(), + RlpTxFieldTag::DecodeError => { + let rest_bytes = bytes.len().min(MAX_BYTE_COLUMN_NUM); + let rlp_remain_length: usize = witness.last().unwrap().rlp_remain_length; + witness.append(&mut generate_rlp_row_witness( + tx_id, + self, + &bytes[..rest_bytes], + r, + rlp_remain_length, + )); + + if rest_bytes == bytes.len() { + (RlpTxFieldTag::Padding, Some(rest_bytes)) + } else { + (RlpTxFieldTag::DecodeError, Some(rest_bytes)) + } + } + } + } + + fn rlp_decode_field_check( + &self, + bytes: &[u8], + tx_id: u64, + r: F, + decode_rule: &RlpDecodeRule, + witness: &mut Vec>, + next_state: RlpTxFieldTag, + ) -> (RlpTxFieldTag, Option) { + let rlp_remain_length: usize = witness.last().unwrap().rlp_remain_length; + let res = read_nbytes(bytes, 1); + match res { + Ok(bytes_read_header) => { + let head_byte0 = bytes_read_header[0]; + // if decode rule check failed + let (_, decodable) = decode_rule.rule_check(head_byte0); + if !decodable { + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..1], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::HeaderDecError), + )); + (RlpTxFieldTag::DecodeError, Some(1)) + } else { + match decode_rule { + RlpDecodeRule::Padding => unreachable!(), + RlpDecodeRule::Empty => unreachable!(), + RlpDecodeRule::Uint64 => unreachable!(), + RlpDecodeRule::Uint96 => match head_byte0 { + 1..=0x80 => { + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..1], + r, + rlp_remain_length, + None, + )); + (next_state, Some(1)) + } + 0x81..=0x88 => { + let mut offset = 1; + let len_of_val = head_byte0 - 0x80; + let res = read_nbytes(&bytes[offset..], len_of_val as usize); + match res { + Ok(val_bytes_read) => { + let val_byte0 = val_bytes_read[0]; + if len_of_val == 1 && val_byte0 < 0x80 { + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset + 1], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::LenOfLenError), // maybe val error is better + )); + (RlpTxFieldTag::DecodeError, Some(offset + 1)) + } else if len_of_val > 1 && val_byte0 == 0 { + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset + 1], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::LenOfLenError), + )); + (RlpTxFieldTag::DecodeError, Some(offset + 1)) + } else { + offset += val_bytes_read.len(); + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + None, + )); + (next_state, Some(offset)) + } + } + Err(val_bytes_read) => { + offset += val_bytes_read.len(); + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::RunOutOfDataError), + )); + (RlpTxFieldTag::DecodeError, Some(offset)) + } + } + } + _ => unreachable!(), + }, + RlpDecodeRule::Uint256 => match head_byte0 { + 1..=0x80 => { + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..1], + r, + rlp_remain_length, + None, + )); + (next_state, Some(1)) + } + 0x81..=0xa0 => { + let mut offset = 1; + let len_of_val = head_byte0 - 0x80; + let res = read_nbytes(&bytes[offset..], len_of_val as usize); + match res { + Ok(val_bytes_read) => { + let val_byte0 = val_bytes_read[0]; + if len_of_val == 1 && val_byte0 <= 0x80 { + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset + 1], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::LenOfLenError), + )); + (RlpTxFieldTag::DecodeError, Some(offset + 1)) + } else if len_of_val > 1 && val_byte0 == 0 { + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset + 1], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::LenOfLenError), + )); + (RlpTxFieldTag::DecodeError, Some(offset + 1)) + } else { + offset += val_bytes_read.len(); + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + None, + )); + (next_state, Some(offset)) + } + } + Err(val_bytes_read) => { + offset += val_bytes_read.len(); + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::RunOutOfDataError), + )); + (RlpTxFieldTag::DecodeError, Some(offset)) + } + } + } + _ => unreachable!(), + }, + RlpDecodeRule::Address => match head_byte0 { + 0x94 => { + let mut offset = 1; + let len_of_val = 0x14; + let res = read_nbytes(&bytes[offset..], len_of_val as usize); + match res { + Ok(val_bytes_read) => { + offset += val_bytes_read.len(); + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + None, + )); + (next_state, Some(offset)) + } + Err(val_bytes_read) => { + offset += val_bytes_read.len(); + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::RunOutOfDataError), + )); + (RlpTxFieldTag::DecodeError, Some(offset)) + } + } + } + _ => unreachable!(), + }, + RlpDecodeRule::Bytes48K => match head_byte0 { + 0..=0x80 => { + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..1], + r, + rlp_remain_length, + None, + )); + (next_state, Some(1)) + } + 0x81..=0xb7 => { + let mut offset = 1; + let len_of_val = head_byte0 - 0x80; + let res = read_nbytes(&bytes[offset..], len_of_val as usize); + match res { + Ok(val_bytes_read) => { + let val_byte0 = val_bytes_read[0]; + if len_of_val == 1 && val_byte0 < 0x80 { + offset += 1; + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::LenOfLenError), + )); + (RlpTxFieldTag::DecodeError, Some(offset)) + } else { + offset += len_of_val as usize; + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + None, + )); + (next_state, Some(offset)) + } + } + Err(val_bytes_read) => { + let bytes_len = (val_bytes_read.len() + offset) + .min(MAX_BYTE_COLUMN_NUM); + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..bytes_len], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::RunOutOfDataError), + )); + ( + RlpTxFieldTag::DecodeError, + Some(offset + val_bytes_read.len()), + ) + } + } + } + 0xb8..=0xba => { + let mut offset = 1; + let len_of_len = head_byte0 - 0xb7; + let res = read_nbytes(&bytes[offset..], len_of_len as usize); + match res { + Ok(len_bytes_read) => { + let len_byte0 = len_bytes_read[0]; + if len_of_len == 1 && len_byte0 <= 55 { + offset += 1; + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::LenOfLenError), + )); + (RlpTxFieldTag::DecodeError, Some(offset)) + } else if len_of_len > 1 && len_byte0 == 0 { + offset += 1; + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::LenOfLenError), + )); + (RlpTxFieldTag::DecodeError, Some(offset)) + } else { + offset += len_bytes_read.len(); + let val_bytes_len = rlp_bytes_len(len_bytes_read); + let res = read_nbytes(&bytes[offset..], val_bytes_len); + match res { + Ok(val_bytes_read) => { + offset += val_bytes_read.len(); + witness.append( + &mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + None, + ), + ); + (next_state, Some(offset)) + } + Err(val_bytes_read) => { + let bytes_len = (offset + val_bytes_read.len()) + .min(MAX_BYTE_COLUMN_NUM); + witness + .append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..bytes_len], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::RunOutOfDataError), + )); + (RlpTxFieldTag::DecodeError, Some(bytes_len)) + } + } + } + } + Err(len_bytes_read) => { + offset += len_bytes_read.len(); + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::RunOutOfDataError), + )); + (RlpTxFieldTag::DecodeError, Some(offset)) + } + } + } + _ => unreachable!(), + }, + RlpDecodeRule::EmptyList => todo!(), + RlpDecodeRule::LongList => { + let header_byte0 = bytes_read_header[0]; + // if decode rule check failed + let (_, decodable) = decode_rule.rule_check(header_byte0); + if !decodable { + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..1], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::HeaderDecError), + )); + (RlpTxFieldTag::DecodeError, Some(1)) + } else { + let mut offset = 1; + let len_of_len = header_byte0 - 0xF7; + let res = read_nbytes(&bytes[offset..], len_of_len as usize); + match res { + Ok(len_bytes_read) => { + let len_byte0 = len_bytes_read[0]; + if len_of_len == 1 && len_byte0 <= 55 { + offset += 1; + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::LenOfLenError), + )); + (RlpTxFieldTag::DecodeError, Some(offset)) + } else if len_of_len > 1 && len_byte0 == 0 { + offset += 1; + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::LenOfLenError), + )); + (RlpTxFieldTag::DecodeError, Some(offset)) + } else { + // TODO: consume rlp_bytes_len(consumed_bytes) and get + // EOF error earlier? + offset += len_bytes_read.len(); + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + None, + )); + (next_state, Some(offset)) + } + } + Err(consumed_bytes) => { + offset += consumed_bytes.len(); + (RlpTxFieldTag::DecodeError, Some(offset)) + } + } + } + } + } + } + } + Err(_) => { + // error flag row + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes, + r, + rlp_remain_length, + Some(RlpDecodeErrorType::RunOutOfDataError), + )); + (RlpTxFieldTag::DecodeError, Some(0)) + } + } + } +} + +fn gen_rlp_decode_state_witness( + bytes: &[u8], + r: F, + k: usize, +) -> Vec> { + let mut tx_id: u64 = 0; + + let mut witness = vec![RlpDecoderCircuitConfigWitness:: { + tx_id: tx_id, + tx_type: RlpTxTypeTag::TxLegacyType, + tx_member: RlpTxFieldTag::TxListRlpHeader, + complete: false, + rlp_type: RlpDecodeTypeTag::DoNothing, + rlp_tx_member_length: 0u64, + rlp_bytes_in_row: MAX_BYTE_COLUMN_NUM as u8, + r_mult: F::zero(), + rlp_remain_length: bytes.len(), + value: F::zero(), + acc_rlc_value: F::zero(), + bytes: [0; MAX_BYTE_COLUMN_NUM].to_vec(), + errors: [false; 4], + valid: false, + q_enable: false, + q_first: false, + q_last: false, + r_mult_comp: F::one(), + rlc_quotient: F::zero(), + }]; + + let mut offset = 0; + let mut init_state = RlpTxFieldTag::TxListRlpHeader; + + loop { + tx_id = 1; + println!("Current state: {:?}, offset = {:?}", init_state, offset); + let (next_state, next_offset) = + init_state.next(k, tx_id, &bytes[offset..], r, &mut witness); + match next_offset { + Some(n) => { + offset += n; + init_state = next_state; + } + None => { + break; + } + } + } + witness +} // TODO: use a state machine to decode the tx list as above fn rlp_decode_tx_list_manually( @@ -1940,6 +2496,156 @@ fn complete_paddings( complete_witness } +fn fixup_acc_rlc_new( + witness: &mut Vec>, + randomness: F, +) { + let mut prev_acc_rlc = F::zero(); + // skip the first line + for i in 1..witness.len() { + let cur_wit = &mut witness[i]; + let mut bytes = cur_wit.bytes.clone(); + bytes.resize(MAX_BYTE_COLUMN_NUM, 0); + bytes.reverse(); + cur_wit.rlc_quotient = + rlc::value(&bytes, randomness) * cur_wit.r_mult_comp.invert().unwrap(); + cur_wit.acc_rlc_value = prev_acc_rlc * cur_wit.r_mult + cur_wit.rlc_quotient; + prev_acc_rlc = cur_wit.acc_rlc_value; + } +} + +fn complete_paddings_new( + witness: &mut Vec>, + num_padding_to_last_row: usize, +) { + let before_padding = witness.last().unwrap().clone(); + for i in 0..num_padding_to_last_row { + witness.push(RlpDecoderCircuitConfigWitness:: { + tx_id: 0, + tx_type: RlpTxTypeTag::TxLegacyType, + tx_member: RlpTxFieldTag::Padding, + complete: true, + rlp_type: RlpDecodeTypeTag::DoNothing, + rlp_tx_member_length: 0, + rlp_bytes_in_row: 0, + r_mult: F::one(), + rlp_remain_length: 0, + value: F::zero(), + acc_rlc_value: before_padding.acc_rlc_value, + bytes: [0; MAX_BYTE_COLUMN_NUM].to_vec(), + errors: [false, false, false, false], + valid: true, + q_enable: true, + q_first: false, + q_last: i == num_padding_to_last_row - 1, + r_mult_comp: F::one(), + rlc_quotient: F::zero(), + }); + } + witness.push(RlpDecoderCircuitConfigWitness::::default()); +} + +fn generate_rlp_row_witness_new( + tx_id: u64, + tx_member: &RlpTxFieldTag, + raw_bytes: &[u8], + r: F, + rlp_remain_length: usize, + error_id: Option, +) -> Vec> { + println!("generate_rlp_row_witness_new (tx_id: {}, tx_member: {:?}, raw_bytes: {:?}, r: {:?}, rlp_remain_length: {:?}, error_id: {:?})", tx_id, tx_member, raw_bytes, r, rlp_remain_length, error_id); + let mut witness = vec![]; + let (mut rlp_type, _, _, _) = generate_rlp_type_witness(tx_member, raw_bytes); + let partial_rlp_type = RlpDecodeTypeTag::PartialRlp; + let rlp_tag_len = raw_bytes.len(); + let mut prev_rlp_remain_length = rlp_remain_length; + + // error case never cross raw + assert!(error_id.is_none() || (raw_bytes.len() <= MAX_BYTE_COLUMN_NUM)); + let mut errors = [false; 4]; + error_id.map(|id| errors[id as usize] = true); + macro_rules! generate_witness { + () => {{ + let mut temp_witness_vec = Vec::new(); + let mut tag_remain_length = rlp_tag_len; + let mut raw_bytes_offset = 0; + while tag_remain_length > MAX_BYTE_COLUMN_NUM { + temp_witness_vec.push(RlpDecoderCircuitConfigWitness:: { + tx_id: tx_id, + tx_type: RlpTxTypeTag::TxLegacyType, + tx_member: tx_member.clone(), + complete: false, + rlp_type: rlp_type, + rlp_tx_member_length: tag_remain_length as u64, + rlp_bytes_in_row: MAX_BYTE_COLUMN_NUM as u8, + r_mult: r.pow(&[MAX_BYTE_COLUMN_NUM as u64, 0, 0, 0]), + rlp_remain_length: prev_rlp_remain_length - MAX_BYTE_COLUMN_NUM, + value: F::zero(), + acc_rlc_value: F::zero(), + bytes: raw_bytes[raw_bytes_offset..raw_bytes_offset + MAX_BYTE_COLUMN_NUM] + .to_vec(), + errors: errors, + valid: errors.iter().all(|&err| !err), + q_enable: true, + q_first: false, + q_last: false, + r_mult_comp: F::one(), + rlc_quotient: F::zero(), + }); + raw_bytes_offset += MAX_BYTE_COLUMN_NUM; + tag_remain_length -= MAX_BYTE_COLUMN_NUM; + prev_rlp_remain_length -= MAX_BYTE_COLUMN_NUM; + rlp_type = partial_rlp_type; + } + temp_witness_vec.push(RlpDecoderCircuitConfigWitness:: { + tx_id: tx_id, + tx_type: RlpTxTypeTag::TxLegacyType, + tx_member: tx_member.clone(), + complete: true, + rlp_type: rlp_type, + rlp_tx_member_length: tag_remain_length as u64, + rlp_bytes_in_row: tag_remain_length as u8, + r_mult: r.pow(&[tag_remain_length as u64, 0, 0, 0]), + rlp_remain_length: prev_rlp_remain_length - tag_remain_length, + value: F::zero(), + acc_rlc_value: F::zero(), + bytes: raw_bytes[raw_bytes_offset..].to_vec(), + errors: errors, + valid: errors.iter().all(|&err| !err), + q_enable: true, + q_first: false, + q_last: false, + r_mult_comp: r.pow(&[(MAX_BYTE_COLUMN_NUM - tag_remain_length) as u64, 0, 0, 0]), + rlc_quotient: F::zero(), + }); + temp_witness_vec + }}; + } + + // TODO: reorganize the match + match tx_member { + RlpTxFieldTag::TxListRlpHeader => witness.append(&mut generate_witness!()), + RlpTxFieldTag::TxRlpHeader => witness.append(&mut generate_witness!()), + RlpTxFieldTag::Nonce => witness.append(&mut generate_witness!()), + RlpTxFieldTag::GasPrice => witness.append(&mut generate_witness!()), + RlpTxFieldTag::Gas => witness.append(&mut generate_witness!()), + RlpTxFieldTag::To => witness.append(&mut generate_witness!()), + RlpTxFieldTag::Value => witness.append(&mut generate_witness!()), + RlpTxFieldTag::Data => witness.append(&mut generate_witness!()), + RlpTxFieldTag::SignV => witness.append(&mut generate_witness!()), + RlpTxFieldTag::SignR => witness.append(&mut generate_witness!()), + RlpTxFieldTag::SignS => witness.append(&mut generate_witness!()), + RlpTxFieldTag::DecodeError => witness.append(&mut generate_witness!()), + RlpTxFieldTag::Padding => { + unreachable!("Padding should not be here") + } + _ => { + unreachable!("1559 not support now") + } + } + witness +} + /// Signed transaction in a witness block #[derive(Debug, Clone)] pub struct SignedTransaction { @@ -2031,7 +2737,7 @@ impl From for SignedTransaction { #[cfg(test)] mod rlp_test { - use super::{rlp_decode_tx_list_manually, SignedTransaction}; + use super::{gen_rlp_decode_state_witness, rlp_decode_tx_list_manually, SignedTransaction}; use ethers_core::utils::rlp; use halo2_proofs::halo2curves::bn256::Fr; use hex; @@ -2102,7 +2808,13 @@ mod rlp_test { let randomness = Fr::from(100); let k = 128; - let witness = rlp_decode_tx_list_manually::(&rlp_bytes, randomness, k); + // let witness = rlp_decode_tx_list_manually::(&rlp_bytes, randomness, k); + // for (i, w) in witness.iter().enumerate() { + // print!("witness[{}] = {:?}\n", i, w); + // } + + let witness: Vec> = + gen_rlp_decode_state_witness::(&rlp_bytes, randomness, k); for (i, w) in witness.iter().enumerate() { print!("witness[{}] = {:?}\n", i, w); } @@ -2114,7 +2826,8 @@ mod rlp_test { let randomness = Fr::from(100); let k = 128; - let witness = rlp_decode_tx_list_manually::(&rlp_bytes, randomness, k); + let witness: Vec> = + gen_rlp_decode_state_witness::(&rlp_bytes, randomness, k); for (i, w) in witness.iter().enumerate() { print!("witness[{}] = {:?}\n", i, w); } @@ -2284,6 +2997,92 @@ mod rlp_decode_circuit_tests { .into(); assert_eq!(run::(vec![tx.clone(), tx.clone()]), Ok(())); } + + mod invalid_rlp_test { + use super::*; + + fn generate_rlp_bytes(txs: Vec) -> Vec { + let k = log2_ceil(RlpDecoderCircuit::::min_num_rows_from_tx(&txs).0); + + let encodable_txs: Vec = + txs.iter().map(|tx| tx.into()).collect::>(); + let rlp_bytes = rlp::encode_list(&encodable_txs); + println!( + "input rlp_bytes = {:?}, k = {}.", + hex::encode(&rlp_bytes), + k + ); + rlp_bytes.to_vec() + } + + fn run_invalid_rlp( + rlp_bytes: Vec, + k: usize, + ) -> Result<(), Vec> { + let circuit = RlpDecoderCircuit::::new(rlp_bytes.to_vec(), k); + let prover = match MockProver::run(k as u32, &circuit, vec![]) { + Ok(prover) => prover, + Err(e) => panic!("{:#?}", e), + }; + prover.verify() + } + + #[test] + fn invalid_rlp_wrong_list_header_header() { + let mut rng = ChaCha20Rng::seed_from_u64(2u64); + let tx: Transaction = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from(b"0")) + .build() + .into(); + let mut rlp_bytes = generate_rlp_bytes(vec![tx.clone()]); + rlp_bytes[0] = 0xc0; + + let k = log2_ceil(RlpDecoderCircuit::::min_num_rows_from_tx(&vec![tx.clone()]).0) + as usize; + assert_ne!(run_invalid_rlp::(rlp_bytes, k), Ok(())); + } + + #[test] + fn invalid_rlp_wrong_list_header_len() { + todo!() + } + + #[test] + fn invalid_rlp_wrong_tx_header_header() { + todo!() + } + + #[test] + fn invalid_rlp_wrong_tx_header_len() { + todo!() + } + + #[test] + fn invalid_rlp_wrong_tx_field_nonce() { + todo!() + } + + #[test] + fn invalid_rlp_wrong_tx_field_gas() { + todo!() + } + + #[test] + fn invalid_rlp_wrong_tx_field_to() { + todo!() + } + + #[test] + fn invalid_rlp_wrong_tx_field_data() { + todo!() + } + + #[test] + fn invalid_rlp_not_enough_length() { + todo!() + } + } } #[cfg(test)] diff --git a/zkevm-circuits/src/rlp_decoder_tables.rs b/zkevm-circuits/src/rlp_decoder_tables.rs index e0c151f0a1..3f9813cb7f 100644 --- a/zkevm-circuits/src/rlp_decoder_tables.rs +++ b/zkevm-circuits/src/rlp_decoder_tables.rs @@ -106,7 +106,7 @@ impl RlpDecodeRule { } /// rules of tx members -pub const RLP_TX_FIELD_DECODE_RULES: [(RlpTxTypeTag, RlpTxFieldTag, RlpDecodeRule); 13] = [ +pub const RLP_TX_FIELD_DECODE_RULES: [(RlpTxTypeTag, RlpTxFieldTag, RlpDecodeRule); 14] = [ ( RlpTxTypeTag::TxLegacyType, RlpTxFieldTag::TxListRlpHeader, @@ -172,6 +172,11 @@ pub const RLP_TX_FIELD_DECODE_RULES: [(RlpTxTypeTag, RlpTxFieldTag, RlpDecodeRul RlpTxFieldTag::Padding, RlpDecodeRule::Padding, ), + ( + RlpTxTypeTag::TxLegacyType, + RlpTxFieldTag::DecodeError, + RlpDecodeRule::Padding, + ), ]; /// Table that contains the fields of all possible RLP decodable fields From abe7c8155a199b5b9817f5ca094f085396abc2b1 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Mon, 3 Jul 2023 04:27:43 +0000 Subject: [PATCH 15/21] make new witness == old witness --- zkevm-circuits/src/rlp_decoder.rs | 61 +++++++++++++++++-------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 06444be9ad..6b24b51cf3 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -208,7 +208,7 @@ impl_expr!(RlpTxTypeTag); pub const MAX_BYTE_COLUMN_NUM: usize = 33; /// Witness for RlpDecoderCircuit -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct RlpDecoderCircuitConfigWitness { /// tx_id column pub tx_id: u64, @@ -1497,7 +1497,10 @@ fn generate_rlp_type_witness( value_decodable = bytes[1] > 0; } match tx_member { - RlpTxFieldTag::To => RlpDecodeTypeTag::ShortStringBytes, + RlpTxFieldTag::To => { + value_decodable = true; + RlpDecodeTypeTag::ShortStringBytes + } RlpTxFieldTag::Data => RlpDecodeTypeTag::ShortStringBytes, _ => RlpDecodeTypeTag::ShortStringValue, } @@ -1750,9 +1753,9 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } RlpTxFieldTag::Padding => { let witness_len = witness.len(); - assert!(k > (witness_len + 2 + NUM_BLINDING_ROWS)); + assert!(k > (witness_len + 1 + NUM_BLINDING_ROWS)); fixup_acc_rlc_new(witness, r); - complete_paddings_new(witness, k as usize - witness_len - 2 - NUM_BLINDING_ROWS); + complete_paddings_new(witness, k as usize - witness_len - 1 - NUM_BLINDING_ROWS); (RlpTxFieldTag::Padding, None) } RlpTxFieldTag::ChainID => todo!(), @@ -2214,36 +2217,30 @@ fn gen_rlp_decode_state_witness( ) -> Vec> { let mut tx_id: u64 = 0; + // update the rlp bytes hash + let mut hasher = Keccak::default(); + hasher.update(bytes); + let hash = hasher.digest(); + let mut witness = vec![RlpDecoderCircuitConfigWitness:: { - tx_id: tx_id, - tx_type: RlpTxTypeTag::TxLegacyType, - tx_member: RlpTxFieldTag::TxListRlpHeader, - complete: false, - rlp_type: RlpDecodeTypeTag::DoNothing, - rlp_tx_member_length: 0u64, - rlp_bytes_in_row: MAX_BYTE_COLUMN_NUM as u8, - r_mult: F::zero(), rlp_remain_length: bytes.len(), - value: F::zero(), - acc_rlc_value: F::zero(), - bytes: [0; MAX_BYTE_COLUMN_NUM].to_vec(), - errors: [false; 4], - valid: false, - q_enable: false, - q_first: false, - q_last: false, - r_mult_comp: F::one(), - rlc_quotient: F::zero(), + value: hash + .iter() + .rev() + .fold(F::zero(), |acc, b| acc * r + F::from(*b as u64)), + ..Default::default() }]; let mut offset = 0; let mut init_state = RlpTxFieldTag::TxListRlpHeader; loop { - tx_id = 1; - println!("Current state: {:?}, offset = {:?}", init_state, offset); + // println!("Current state: {:?}, offset = {:?}", init_state, offset); let (next_state, next_offset) = init_state.next(k, tx_id, &bytes[offset..], r, &mut witness); + if next_state == RlpTxFieldTag::TxRlpHeader { + tx_id += 1; + } match next_offset { Some(n) => { offset += n; @@ -2613,7 +2610,7 @@ fn generate_rlp_row_witness_new( errors: errors, valid: errors.iter().all(|&err| !err), q_enable: true, - q_first: false, + q_first: tx_member == &RlpTxFieldTag::TxListRlpHeader, q_last: false, r_mult_comp: r.pow(&[(MAX_BYTE_COLUMN_NUM - tag_remain_length) as u64, 0, 0, 0]), rlc_quotient: F::zero(), @@ -2840,8 +2837,18 @@ mod rlp_test { let k = 256; let witness = rlp_decode_tx_list_manually::(&rlp_bytes, randomness, k); - for (i, w) in witness.iter().enumerate() { - print!("witness[{}] = {:?}\n", i, w); + // for (i, w) in witness.iter().enumerate() { + // print!("witness[{}] = {:?}\n", i, w); + // } + + let witness1: Vec> = + gen_rlp_decode_state_witness::(&rlp_bytes, randomness, k as usize); + + let mut i = 0; + for (w, w1) in witness.iter().zip(witness1.iter()) { + println!("{}th row", i); + assert_eq!(w, w1); + i += 1; } } From b4b9a51e535795d97aedea50239502cd8ead98ff Mon Sep 17 00:00:00 2001 From: smtmfft Date: Mon, 3 Jul 2023 09:11:59 +0000 Subject: [PATCH 16/21] fix To and Data field --- zkevm-circuits/src/rlp_decoder.rs | 53 +++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 6b24b51cf3..e4b75307c4 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -1501,7 +1501,10 @@ fn generate_rlp_type_witness( value_decodable = true; RlpDecodeTypeTag::ShortStringBytes } - RlpTxFieldTag::Data => RlpDecodeTypeTag::ShortStringBytes, + RlpTxFieldTag::Data => { + value_decodable = true; + RlpDecodeTypeTag::ShortStringBytes + } _ => RlpDecodeTypeTag::ShortStringValue, } } @@ -1719,11 +1722,12 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { r: F, witness: &mut Vec>, ) -> (Self, Option) { - let rule_entry_opt = RLP_TX_FIELD_DECODE_RULES + let decode_rules = RLP_TX_FIELD_DECODE_RULES .iter() - .find(|rule| rule.0 == RlpTxTypeTag::TxLegacyType && rule.1 == *self); - let rule_entry = rule_entry_opt.unwrap(); - let (_, _, decode_rule) = rule_entry; + .filter(|rule| rule.0 == RlpTxTypeTag::TxLegacyType && rule.1 == *self) + .collect::>(); + assert!(decode_rules.len() >= 1); + let (_, _, mut decode_rule) = decode_rules[0]; macro_rules! state_switch { ($next_state: expr) => { @@ -1737,7 +1741,14 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { RlpTxFieldTag::Nonce => state_switch!(RlpTxFieldTag::GasPrice), RlpTxFieldTag::GasPrice => state_switch!(RlpTxFieldTag::Gas), RlpTxFieldTag::Gas => state_switch!(RlpTxFieldTag::To), - RlpTxFieldTag::To => state_switch!(RlpTxFieldTag::Value), + RlpTxFieldTag::To => { + assert!(decode_rules.len() == 2); + if bytes.len() >= 1 && bytes[0] == 0x80 { + // empty to address + decode_rule = decode_rules[1].2; + } + state_switch!(RlpTxFieldTag::Value) + } RlpTxFieldTag::Value => state_switch!(RlpTxFieldTag::Data), RlpTxFieldTag::Data => state_switch!(RlpTxFieldTag::SignV), RlpTxFieldTag::SignV => state_switch!(RlpTxFieldTag::SignR), @@ -1811,7 +1822,20 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } else { match decode_rule { RlpDecodeRule::Padding => unreachable!(), - RlpDecodeRule::Empty => unreachable!(), + RlpDecodeRule::Empty => match head_byte0 { + 0x80 => { + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..1], + r, + rlp_remain_length, + None, + )); + (next_state, Some(1)) + } + _ => unreachable!(), + }, RlpDecodeRule::Uint64 => unreachable!(), RlpDecodeRule::Uint96 => match head_byte0 { 1..=0x80 => { @@ -2862,15 +2886,24 @@ mod rlp_test { )) .build() .into(); + println!("tx = {:?}", tx); let rlp_txs = rlp::encode_list(&[tx]); println!("rlp_txs = {:?}", hex::encode(rlp_txs.clone())); let randomness = Fr::from(100); let k = 256; - let witness = rlp_decode_tx_list_manually::(&rlp_txs.to_vec(), randomness, k); - for (i, w) in witness.iter().enumerate() { - print!("witness[{}] = {:?}\n", i, w); + let rlp_bytes = rlp_txs.to_vec(); + let witness = rlp_decode_tx_list_manually::(&rlp_bytes, randomness, k); + + let witness1: Vec> = + gen_rlp_decode_state_witness::(&rlp_bytes, randomness, k as usize); + + let mut i = 0; + for (w, w1) in witness.iter().zip(witness1.iter()) { + println!("{}th row", i); + assert_eq!(w, w1); + i += 1; } } From d693c93041294c36129b3426037e6a37cdf27787 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Tue, 4 Jul 2023 02:22:27 +0000 Subject: [PATCH 17/21] fix existed tests --- zkevm-circuits/src/rlp_decoder.rs | 595 +++++++++++++----------------- 1 file changed, 254 insertions(+), 341 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index e4b75307c4..5c9766dba0 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -404,7 +404,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { |meta| meta.query_advice(rlp_remain_length, Rotation::prev()), ); - // less equal n => less than n+1 + // less equal n == less than n+1 let cmp_length_le_prev_remain: LtConfig = LtChip::configure( meta, |meta| meta.query_selector(q_enable), @@ -459,6 +459,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { decode_errors[RlpDecodeErrorType::HeaderDecError], Rotation::cur(), )); + let prev_is_valid = meta.query_advice(valid, Rotation::prev()); let q_enable = meta.query_selector(q_enable); let is_not_partial = not::expr(rlp_type_enabled!(meta, RlpDecodeTypeTag::PartialRlp)); @@ -470,7 +471,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let byte0_in_table = meta.query_fixed(table.byte_0, Rotation::cur()); let decodable_in_table = meta.query_fixed(table.decodable, Rotation::cur()); - let query_able = q_enable.expr() * is_not_partial.expr(); + let query_able = q_enable.expr() * is_not_partial.expr() * prev_is_valid.expr(); vec![ ( query_able.expr() * RlpDecoderFixedTableTag::RlpDecoderTable.expr(), @@ -635,22 +636,32 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { valid_next.expr(), ); - cb.require_equal( - "if any(errors) then valid must 0", - or::expr( - decode_errors - .iter() - .map(|e| meta.query_advice(*e, Rotation::cur())) - .collect::>>(), - ), - not::expr(valid_cur.expr()), + // if not in error state and not in padding state, the valid comes from the error states + let not_error_state = not::expr( + meta.query_advice(q_tx_members[RlpTxFieldTag::DecodeError], Rotation::cur()), ); + let not_padding_state = + not::expr(meta.query_advice(q_tx_members[RlpTxFieldTag::Padding], Rotation::cur())); + cb.condition(and::expr([not_error_state, not_padding_state]), |cb| { + cb.require_equal( + "if any(errors) then valid must false", + or::expr( + decode_errors + .iter() + .map(|e| meta.query_advice(*e, Rotation::cur())) + .collect::>>(), + ), + not::expr(valid_cur.expr()), + ) + }); - cb.require_equal( - "check if bytes run out", - cmp_length_le_prev_remain.is_lt(meta, None), - valid_cur.expr(), - ); + cb.condition(valid_cur.expr(), |cb| { + cb.require_equal( + "check if bytes run out", + cmp_length_le_prev_remain.is_lt(meta, None), + 1.expr(), + ); + }); cb.gate(and::expr([ meta.query_selector(q_enable), @@ -673,6 +684,8 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { .collect::>(); let q_tx_rlp_header = meta.query_advice(q_tx_members[RlpTxFieldTag::TxRlpHeader], Rotation::cur()); + let q_dec_error = + meta.query_advice(q_tx_members[RlpTxFieldTag::DecodeError], Rotation::cur()); let q_enable = meta.query_selector(q_enable); let q_first = meta.query_fixed(q_first, Rotation::cur()); @@ -838,6 +851,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.gate(and::expr([ q_enable, not::expr(q_first), + not::expr(q_dec_error), not::expr(q_tx_rlp_header), ])) }); @@ -850,59 +864,67 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tx_type_cur = meta.query_advice(tx_type, Rotation::cur()); let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); let complete = meta.query_advice(complete, Rotation::cur()); + let init_acc_rlc = meta.query_advice(acc_rlc_value, Rotation::prev()); let rlp_tag_length_cur = meta.query_advice(rlp_tx_member_length, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); let byte_cells_cur = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) .collect::>(); - let decodable = not::expr(meta.query_advice( - decode_errors[RlpDecodeErrorType::HeaderDecError], - Rotation::cur(), - )); + let valid = meta.query_advice(valid, Rotation::cur()); let q_first = meta.query_fixed(q_first, Rotation::cur()); cb.require_zero("0 tx_id", tx_id); cb.require_zero("0 tx_type", tx_type_cur.expr()); cb.require_zero("0 tx_tag", tx_member_cur); cb.require_equal("field completed", complete.expr(), 1.expr()); + cb.require_zero("init acc rlc is 0", init_acc_rlc); - cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList1), |cb| { - cb.require_equal( - "long length 1 byte after 0xf8", - remain_length.expr(), - byte_cells_cur[1].expr(), - ); + cb.condition( + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList1) * valid.expr(), + |cb| { + cb.require_equal( + "long length 1 byte after 0xf8", + remain_length.expr(), + byte_cells_cur[1].expr(), + ); - // TODO: byte_cells_cur[1] > 55, and check with len_decode flag - cb.require_equal( - "v should be >55", - cmp_55_lt_byte1.is_lt(meta, None), - 1.expr(), - ) - }); - cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList2), |cb| { - cb.require_equal( - "long length 2 bytes after f9", - remain_length.expr(), - byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr(), - ); - // TODO: byte_cells_cur[1] != 0, and check with len_decode flag - cb.require_equal("v should be >0", cmp_0_lt_byte1.is_lt(meta, None), 1.expr()) - }); - cb.condition(rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList3), |cb| { - cb.require_equal( - "long length 3 bytes after fa", - remain_length.expr(), - byte_cells_cur[1].expr() * 65536.expr() - + byte_cells_cur[2].expr() * 256.expr() - + byte_cells_cur[3].expr(), - ); - // TODO: byte_cells_cur[1] != 0, and check with len_decode flag - cb.require_equal("v should be >0", cmp_0_lt_byte1.is_lt(meta, None), 1.expr()) - }); + // TODO: byte_cells_cur[1] > 55, and check with len_decode flag + cb.require_equal( + "v should be >55", + cmp_55_lt_byte1.is_lt(meta, None), + 1.expr(), + ) + }, + ); + cb.condition( + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList2) * valid.expr(), + |cb| { + cb.require_equal( + "long length 2 bytes after f9", + remain_length.expr(), + byte_cells_cur[1].expr() * 256.expr() + byte_cells_cur[2].expr(), + ); + // TODO: byte_cells_cur[1] != 0, and check with len_decode flag + cb.require_equal("v should be >0", cmp_0_lt_byte1.is_lt(meta, None), 1.expr()) + }, + ); + cb.condition( + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList3) * valid.expr(), + |cb| { + cb.require_equal( + "long length 3 bytes after fa", + remain_length.expr(), + byte_cells_cur[1].expr() * 65536.expr() + + byte_cells_cur[2].expr() * 256.expr() + + byte_cells_cur[3].expr(), + ); + // TODO: byte_cells_cur[1] != 0, and check with len_decode flag + cb.require_equal("v should be >0", cmp_0_lt_byte1.is_lt(meta, None), 1.expr()) + }, + ); - cb.condition(decodable, |cb| { + cb.condition(valid, |cb| { cb.require_equal( "rlp_tag_length = rlp_header length", rlp_tag_length_cur.expr(), @@ -970,7 +992,8 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let length = meta.query_advice(rlp_tx_member_length, Rotation::cur()); let r_mult = meta.query_advice(r_mult, Rotation::cur()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); - let acc_rlc_value = meta.query_advice(acc_rlc_value, Rotation::cur()); + let acc_rlc = meta.query_advice(acc_rlc_value, Rotation::cur()); + let acc_rlc_prev = meta.query_advice(acc_rlc_value, Rotation::prev()); let bytes_values = bytes .iter() .map(|byte_col| meta.query_advice(*byte_col, Rotation::cur())) @@ -987,7 +1010,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { "last row above padding has no remain length", meta.query_advice(rlp_remain_length, Rotation::prev()), ); - cb.require_equal("padding has no rlc (all 0)", acc_rlc_value, 0.expr()); + cb.require_equal("padding has fixed rlc", acc_rlc, acc_rlc_prev); bytes_values.iter().for_each(|byte| { cb.require_zero("padding has no bytes", byte.expr()); }); @@ -1008,6 +1031,100 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.gate(q_last * q_enable) }); + // error gates and error state handling + // 1. each error has its own check to avoid fake error witness + // 2. error state needs extra logic to process all the rest bytes + + // header error is looked up, so, only check consistence with valid + meta.create_gate("header decode error", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let q_enable = meta.query_selector(q_enable); + let header_dec_error = meta.query_advice( + decode_errors[RlpDecodeErrorType::HeaderDecError], + Rotation::cur(), + ); + let is_valid = meta.query_advice(valid, Rotation::cur()); + cb.require_equal( + "header decode error", + header_dec_error.expr(), + not::expr(is_valid), + ); + + cb.gate(q_enable.expr() * header_dec_error.expr()) + }); + + // len dec error depends on type + meta.create_gate("len decode error", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let q_enable = meta.query_selector(q_enable); + let len_dec_error = meta.query_advice( + decode_errors[RlpDecodeErrorType::LenOfLenError], + Rotation::cur(), + ); + + // error if byte_cells_cur[1] < 55 for longlist1 + cb.condition( + or::expr([ + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongString1), + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList1), + ]), + |cb| { + cb.require_zero("error if v <= 55", cmp_55_lt_byte1.is_lt(meta, None)); + }, + ); + // error if byte[1] == 0 for longlist2 & 3 + cb.condition( + or::expr([ + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongString2), + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongString3), + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList2), + rlp_type_enabled!(meta, RlpDecodeTypeTag::LongList3), + ]), + |cb| { + cb.require_zero("error if v == 0", cmp_0_lt_byte1.is_lt(meta, None)); + }, + ); + + cb.gate(q_enable.expr() * len_dec_error) + }); + + meta.create_gate("val decode error", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let q_enable = meta.query_selector(q_enable); + let val_dec_error = meta.query_advice( + decode_errors[RlpDecodeErrorType::ValueError], + Rotation::cur(), + ); + + cb.condition( + rlp_type_enabled!(meta, RlpDecodeTypeTag::ShortStringValue), + |cb| { + cb.require_zero("error if v == 0", cmp_0_lt_byte1.is_lt(meta, None)); + }, + ); + cb.gate(q_enable.expr() * val_dec_error) + }); + + meta.create_gate("eof decode error", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + let q_enable = meta.query_selector(q_enable); + let is_eof = meta.query_advice( + decode_errors[RlpDecodeErrorType::RunOutOfDataError], + Rotation::cur(), + ); + + cb.require_zero( + "remain < tag_len", + cmp_length_le_prev_remain.is_lt(meta, None), + ); + + cb.gate(q_enable * is_eof) + }); + // decode error meta.create_gate("Decode Error", |meta| { let mut cb = BaseConstraintBuilder::default(); @@ -1015,7 +1132,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let tx_member_cur = meta.query_advice(tx_member, Rotation::cur()); let complete = meta.query_advice(complete, Rotation::cur()); let length = meta.query_advice(rlp_tx_member_length, Rotation::cur()); - let r_mult = meta.query_advice(r_mult, Rotation::cur()); let prev_remain_length = meta.query_advice(rlp_remain_length, Rotation::prev()); let remain_length = meta.query_advice(rlp_remain_length, Rotation::cur()); let prev_row_valid = meta.query_advice(valid, Rotation::prev()); @@ -1024,7 +1140,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_equal("tag", tx_member_cur, RlpTxFieldTag::DecodeError.expr()); cb.require_equal("field completed", complete.expr(), 1.expr()); - cb.require_equal("padding has 1 r_mult", r_mult, 1.expr()); // if prev_remain > 33, then length = 33 else, length = prev_remain cb.condition(cmp_bytes_in_row_lt_prev_remain.is_lt(meta, None), |cb| { @@ -1034,9 +1149,9 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { not::expr(cmp_bytes_in_row_lt_prev_remain.is_lt(meta, None)), |cb| { cb.require_equal( - "decode_error length = remain", + "decode_error length = prev_remain", length.expr(), - remain_length.expr(), + prev_remain_length.expr(), ); }, ); @@ -1047,7 +1162,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { remain_length.expr(), prev_remain_length.expr() - length.expr(), ); - cb.require_zero("row above error has error", prev_row_valid.expr()); + cb.require_zero("row above is not valid", prev_row_valid.expr()); cb.gate(q_error.expr() * meta.query_selector(q_enable)) }); @@ -1303,6 +1418,18 @@ impl RlpDecoderCircuitConfig { offset, || Value::known(F::from(w.q_last)), )?; + region.assign_advice( + || "config.r_mult_comp", + self.r_mult_comp, + offset, + || Value::known(F::from(w.r_mult_comp)), + )?; + region.assign_advice( + || "config.rlc_quotient", + self.rlc_quotient, + offset, + || Value::known(F::from(w.rlc_quotient)), + )?; if w.q_enable { self.q_enable.enable(region, offset)?; } @@ -1402,8 +1529,18 @@ impl SubCircuit for RlpDecoderCircuit { ) -> Result<(), Error> { let mut randomness = F::zero(); challenges.keccak_input().map(|r| randomness = r); + log::trace!( + "randomness: {:?}, rlc_bytes = {:?}", + randomness, + rlc::value(self.bytes.iter().rev(), randomness) + ); + let witness: Vec> = - rlp_decode_tx_list_manually(&self.bytes, randomness, self.size as u32); + gen_rlp_decode_state_witness(&self.bytes, randomness, self.size); + + for (i, w) in witness.iter().enumerate() { + log::trace!("witness[{}]: {:?}", i, w); + } config .aux_tables @@ -1766,7 +1903,7 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { let witness_len = witness.len(); assert!(k > (witness_len + 1 + NUM_BLINDING_ROWS)); fixup_acc_rlc_new(witness, r); - complete_paddings_new(witness, k as usize - witness_len - 1 - NUM_BLINDING_ROWS); + complete_paddings_new(witness, r, k as usize - witness_len - 1 - NUM_BLINDING_ROWS); (RlpTxFieldTag::Padding, None) } RlpTxFieldTag::ChainID => todo!(), @@ -1776,12 +1913,13 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { RlpTxFieldTag::DecodeError => { let rest_bytes = bytes.len().min(MAX_BYTE_COLUMN_NUM); let rlp_remain_length: usize = witness.last().unwrap().rlp_remain_length; - witness.append(&mut generate_rlp_row_witness( + witness.append(&mut generate_rlp_row_witness_new( tx_id, self, &bytes[..rest_bytes], r, rlp_remain_length, + None, )); if rest_bytes == bytes.len() { @@ -2248,10 +2386,8 @@ fn gen_rlp_decode_state_witness( let mut witness = vec![RlpDecoderCircuitConfigWitness:: { rlp_remain_length: bytes.len(), - value: hash - .iter() - .rev() - .fold(F::zero(), |acc, b| acc * r + F::from(*b as u64)), + value: rlc::value(hash.iter().rev(), r), + // acc_rlc_value: rlc::value(bytes.iter().rev(), r), ..Default::default() }]; @@ -2278,245 +2414,6 @@ fn gen_rlp_decode_state_witness( witness } -// TODO: use a state machine to decode the tx list as above -fn rlp_decode_tx_list_manually( - bytes: &[u8], - r: F, - k: u32, -) -> Vec> { - let mut witness = vec![]; - let mut tx_id: u64 = 0; - - let mut offset = 0; - let tx_list_header = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::TxListRlpHeader, - &bytes[offset..], - r, - &mut witness, - ); - if tx_list_header.is_none() { - return witness; - } - let tx_list_rlp_header = tx_list_header.unwrap(); - offset += tx_list_rlp_header.header_len; - - let total_list_len = tx_list_rlp_header.total(); - tx_id = 1; // tx_id started from 1 as we have a Anchor tx - while offset < total_list_len { - let tx_rlp_header = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::TxRlpHeader, - &bytes[offset..], - r, - &mut witness, - ); - if tx_rlp_header.is_none() { - return witness; - } - offset += tx_rlp_header.unwrap().header_len; - - let tx_rlp_nonce = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::Nonce, - &bytes[offset..], - r, - &mut witness, - ); - if tx_rlp_nonce.is_none() { - return witness; - } - offset += tx_rlp_nonce.unwrap().total(); - - let tx_rlp_gas_price = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::GasPrice, - &bytes[offset..], - r, - &mut witness, - ); - if tx_rlp_gas_price.is_none() { - return witness; - } - offset += tx_rlp_gas_price.unwrap().total(); - - let tx_rlp_gas = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::Gas, - &bytes[offset..], - r, - &mut witness, - ); - if tx_rlp_gas.is_none() { - return witness; - } - offset += tx_rlp_gas.unwrap().total(); - - let tx_rlp_to_addr = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::To, - &bytes[offset..], - r, - &mut witness, - ); - if tx_rlp_to_addr.is_none() { - return witness; - } - offset += tx_rlp_to_addr.unwrap().total(); - - let tx_rlp_value = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::Value, - &bytes[offset..], - r, - &mut witness, - ); - if tx_rlp_value.is_none() { - return witness; - } - offset += tx_rlp_value.unwrap().total(); - - let tx_rlp_data = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::Data, - &bytes[offset..], - r, - &mut witness, - ); - if tx_rlp_data.is_none() { - return witness; - } - offset += tx_rlp_data.unwrap().total(); - - let tx_rlp_v = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::SignV, - &bytes[offset..], - r, - &mut witness, - ); - if tx_rlp_v.is_none() { - return witness; - } - offset += tx_rlp_v.unwrap().total(); - - let tx_rlp_r = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::SignR, - &bytes[offset..], - r, - &mut witness, - ); - if tx_rlp_r.is_none() { - return witness; - } - offset += tx_rlp_r.unwrap().total(); - - let tx_rlp_s = generate_rlp_txfield_witness( - tx_id, - &RlpTxFieldTag::SignS, - &bytes[offset..], - r, - &mut witness, - ); - if tx_rlp_s.is_none() { - return witness; - } - offset += tx_rlp_s.unwrap().total(); - tx_id += 1; - } - - assert!(offset == total_list_len); - fixup_acc_rlc(&mut witness, r); - - let witness_len = witness.len(); - assert!(k > (witness_len + 2 + NUM_BLINDING_ROWS) as u32); - let mut complete_witness = complete_paddings( - &mut witness, - k as usize - witness_len - 2 - NUM_BLINDING_ROWS, - ); - - // update the rlp bytes hash - let mut hasher = Keccak::default(); - hasher.update(bytes); - let hash = hasher.digest(); - complete_witness[0].value = hash - .iter() - .rev() - .fold(F::zero(), |acc, b| acc * r + F::from(*b as u64)); - - for iw in complete_witness.iter().enumerate() { - log::trace!("witness[{}] {:?}", iw.0, iw.1); - } - - // make sure we have comsumed all bytes - assert!(complete_witness[0].rlp_remain_length == bytes.len()); - debug_assert_eq!( - complete_witness[complete_witness.len() - 2].acc_rlc_value, - bytes - .iter() - .fold(F::zero(), |acc, b| acc * r + F::from(*b as u64)) - ); - - complete_witness -} - -fn fixup_acc_rlc(witness: &mut Vec>, randomness: F) { - let mut wit_iter = witness.iter_mut(); - let mut prev: Option<&mut RlpDecoderCircuitConfigWitness> = None; - while let Some(cur_wit) = wit_iter.next() { - let prev_acc_rlc = prev.map_or(F::zero(), |w| w.acc_rlc_value); - let mut bytes = cur_wit.bytes.clone(); - bytes.resize(MAX_BYTE_COLUMN_NUM, 0); - bytes.reverse(); - cur_wit.rlc_quotient = - rlc::value(&bytes, randomness) * cur_wit.r_mult_comp.invert().unwrap(); - cur_wit.acc_rlc_value = prev_acc_rlc * cur_wit.r_mult + cur_wit.rlc_quotient; - - prev = Some(cur_wit); - } -} -fn complete_paddings( - witness: &mut Vec>, - num_padding_to_last_row: usize, -) -> Vec> { - let mut complete_witness = vec![]; - let mut pre_padding = RlpDecoderCircuitConfigWitness::::default(); - pre_padding.rlp_remain_length = - witness[0].rlp_remain_length + witness[0].rlp_bytes_in_row as usize; - - complete_witness.push(pre_padding); - witness[0].q_first = true; - complete_witness.append(witness); - - let before_padding = complete_witness.last().unwrap().clone(); - for i in 0..num_padding_to_last_row { - complete_witness.push(RlpDecoderCircuitConfigWitness:: { - tx_id: 0, - tx_type: RlpTxTypeTag::TxLegacyType, - tx_member: RlpTxFieldTag::Padding, - complete: true, - rlp_type: RlpDecodeTypeTag::DoNothing, - rlp_tx_member_length: 0, - rlp_bytes_in_row: 0, - r_mult: F::one(), - rlp_remain_length: 0, - value: F::zero(), - acc_rlc_value: before_padding.acc_rlc_value, - bytes: [0; MAX_BYTE_COLUMN_NUM].to_vec(), - errors: [false, false, false, false], - valid: true, - q_enable: true, - q_first: false, - q_last: i == num_padding_to_last_row - 1, - r_mult_comp: F::one(), - rlc_quotient: F::zero(), - }); - } - complete_witness.push(RlpDecoderCircuitConfigWitness::::default()); - complete_witness -} - fn fixup_acc_rlc_new( witness: &mut Vec>, randomness: F, @@ -2537,9 +2434,11 @@ fn fixup_acc_rlc_new( fn complete_paddings_new( witness: &mut Vec>, + randomness: F, num_padding_to_last_row: usize, ) { let before_padding = witness.last().unwrap().clone(); + let r_mult_comp_padding = randomness.pow(&[(MAX_BYTE_COLUMN_NUM) as u64, 0, 0, 0]); for i in 0..num_padding_to_last_row { witness.push(RlpDecoderCircuitConfigWitness:: { tx_id: 0, @@ -2554,12 +2453,12 @@ fn complete_paddings_new( value: F::zero(), acc_rlc_value: before_padding.acc_rlc_value, bytes: [0; MAX_BYTE_COLUMN_NUM].to_vec(), - errors: [false, false, false, false], - valid: true, + errors: before_padding.errors, + valid: before_padding.valid, q_enable: true, q_first: false, q_last: i == num_padding_to_last_row - 1, - r_mult_comp: F::one(), + r_mult_comp: r_mult_comp_padding, rlc_quotient: F::zero(), }); } @@ -2574,7 +2473,8 @@ fn generate_rlp_row_witness_new( rlp_remain_length: usize, error_id: Option, ) -> Vec> { - println!("generate_rlp_row_witness_new (tx_id: {}, tx_member: {:?}, raw_bytes: {:?}, r: {:?}, rlp_remain_length: {:?}, error_id: {:?})", tx_id, tx_member, raw_bytes, r, rlp_remain_length, error_id); + log::trace!("generate witness for (tx_id: {}, tx_member: {:?}, raw_bytes: {:?}, r: {:?}, rlp_remain_length: {:?}, error_id: {:?})", + tx_id, tx_member, raw_bytes, r, rlp_remain_length, error_id); let mut witness = vec![]; let (mut rlp_type, _, _, _) = generate_rlp_type_witness(tx_member, raw_bytes); let partial_rlp_type = RlpDecodeTypeTag::PartialRlp; @@ -2606,7 +2506,8 @@ fn generate_rlp_row_witness_new( bytes: raw_bytes[raw_bytes_offset..raw_bytes_offset + MAX_BYTE_COLUMN_NUM] .to_vec(), errors: errors, - valid: errors.iter().all(|&err| !err), + valid: (tx_member != &RlpTxFieldTag::DecodeError) + && errors.iter().all(|&err| !err), q_enable: true, q_first: false, q_last: false, @@ -2632,7 +2533,7 @@ fn generate_rlp_row_witness_new( acc_rlc_value: F::zero(), bytes: raw_bytes[raw_bytes_offset..].to_vec(), errors: errors, - valid: errors.iter().all(|&err| !err), + valid: (tx_member != &RlpTxFieldTag::DecodeError) && errors.iter().all(|&err| !err), q_enable: true, q_first: tx_member == &RlpTxFieldTag::TxListRlpHeader, q_last: false, @@ -2758,7 +2659,7 @@ impl From for SignedTransaction { #[cfg(test)] mod rlp_test { - use super::{gen_rlp_decode_state_witness, rlp_decode_tx_list_manually, SignedTransaction}; + use super::{gen_rlp_decode_state_witness, SignedTransaction}; use ethers_core::utils::rlp; use halo2_proofs::halo2curves::bn256::Fr; use hex; @@ -2860,19 +2761,9 @@ mod rlp_test { let randomness = Fr::from(100); let k = 256; - let witness = rlp_decode_tx_list_manually::(&rlp_bytes, randomness, k); - // for (i, w) in witness.iter().enumerate() { - // print!("witness[{}] = {:?}\n", i, w); - // } - - let witness1: Vec> = - gen_rlp_decode_state_witness::(&rlp_bytes, randomness, k as usize); - - let mut i = 0; - for (w, w1) in witness.iter().zip(witness1.iter()) { - println!("{}th row", i); - assert_eq!(w, w1); - i += 1; + let witness = gen_rlp_decode_state_witness::(&rlp_bytes, randomness, k as usize); + for (i, w) in witness.iter().enumerate() { + print!("witness[{}] = {:?}\n", i, w); } } @@ -2894,16 +2785,9 @@ mod rlp_test { let k = 256; let rlp_bytes = rlp_txs.to_vec(); - let witness = rlp_decode_tx_list_manually::(&rlp_bytes, randomness, k); - - let witness1: Vec> = - gen_rlp_decode_state_witness::(&rlp_bytes, randomness, k as usize); - - let mut i = 0; - for (w, w1) in witness.iter().zip(witness1.iter()) { - println!("{}th row", i); - assert_eq!(w, w1); - i += 1; + let witness = gen_rlp_decode_state_witness::(&rlp_bytes, randomness, k as usize); + for (i, w) in witness.iter().enumerate() { + print!("witness[{}] = {:?}\n", i, w); } } @@ -3040,6 +2924,7 @@ mod rlp_decode_circuit_tests { mod invalid_rlp_test { use super::*; + use pretty_assertions::assert_eq; fn generate_rlp_bytes(txs: Vec) -> Vec { let k = log2_ceil(RlpDecoderCircuit::::min_num_rows_from_tx(&txs).0); @@ -3059,7 +2944,7 @@ mod rlp_decode_circuit_tests { rlp_bytes: Vec, k: usize, ) -> Result<(), Vec> { - let circuit = RlpDecoderCircuit::::new(rlp_bytes.to_vec(), k); + let circuit = RlpDecoderCircuit::::new(rlp_bytes, k); let prover = match MockProver::run(k as u32, &circuit, vec![]) { Ok(prover) => prover, Err(e) => panic!("{:#?}", e), @@ -3080,17 +2965,45 @@ mod rlp_decode_circuit_tests { let k = log2_ceil(RlpDecoderCircuit::::min_num_rows_from_tx(&vec![tx.clone()]).0) as usize; - assert_ne!(run_invalid_rlp::(rlp_bytes, k), Ok(())); + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] fn invalid_rlp_wrong_list_header_len() { - todo!() + let mut rng = ChaCha20Rng::seed_from_u64(2u64); + let tx: Transaction = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from(b"0")) + .build() + .into(); + let mut rlp_bytes = generate_rlp_bytes(vec![tx.clone()]); + rlp_bytes[1] = 0x00; + + let k = log2_ceil(RlpDecoderCircuit::::min_num_rows_from_tx(&vec![tx.clone()]).0) + as usize; + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] fn invalid_rlp_wrong_tx_header_header() { - todo!() + let mut rlp_bytes = hex::decode( + "f850\ + f84e\ + 80\ + 01\ + 830f4240\ + 80\ + 80\ + 30\ + 820a98\ + a0b05805737618f6ac1ef211c02575f2fa82026fa1742caf192e2cffcd4161adca\ + a053fbe3d9957dffafca84c419fdd1cead150834c5de9f3215c66327123c0a0541", + ) + .unwrap(); + rlp_bytes[3] = 0xf5; + + let k = 12; + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] From 0c02dbfeefabdd4ede0d27d28325f00e2c65eab6 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Wed, 5 Jul 2023 13:29:04 +0000 Subject: [PATCH 18/21] add more invalid cases --- zkevm-circuits/src/rlp_decoder.rs | 142 ++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 38 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 5c9766dba0..1bd70ef0e6 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -2926,6 +2926,32 @@ mod rlp_decode_circuit_tests { use super::*; use pretty_assertions::assert_eq; + /// predefined tx bytes + /// "f8 50" // witness[1]: list header + /// "f8 4e" // witness[2]: tx header + /// "80" // witness[3]: nonce + /// "01" // witness[4]: gas_price + /// "83 0f4240" // witness[5]: gas + /// "80" // witness[6]: to + /// "80" // witness[7]: value + /// "82 3031" // witness[8]: input + /// "82 0a98" // witness[9]: v + /// "a0 b05805737618f6ac1ef211c02575f2fa82026fa1742caf192e2cffcd4161adca" // witness[10]: r + /// "a0 53fbe3d9957dffafca84c419fdd1cead150834c5de9f3215c66327123c0a0541" // witness[11]: s + fn const_tx_hex() -> String { + String::from("f852") + + "f850" + + "80" + + "01" + + "830f4240" + + "80" + + "80" + + "823031" + + "820a98" + + "a0b05805737618f6ac1ef211c02575f2fa82026fa1742caf192e2cffcd4161adca" + + "a053fbe3d9957dffafca84c419fdd1cead150834c5de9f3215c66327123c0a0541" + } + fn generate_rlp_bytes(txs: Vec) -> Vec { let k = log2_ceil(RlpDecoderCircuit::::min_num_rows_from_tx(&txs).0); @@ -2952,83 +2978,123 @@ mod rlp_decode_circuit_tests { prover.verify() } + #[test] + fn const_tx_decode_is_ok() { + let k = 12; + let rlp_bytes = hex::decode(const_tx_hex()).unwrap(); + let witness = gen_rlp_decode_state_witness(&rlp_bytes, Fr::one(), 1 << k); + // println!("witness = {:?}", &witness); + assert_eq!(witness[witness.len() - 2].valid, true); + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); + } + #[test] fn invalid_rlp_wrong_list_header_header() { - let mut rng = ChaCha20Rng::seed_from_u64(2u64); - let tx: Transaction = mock::MockTransaction::default() - .from(AddrOrWallet::random(&mut rng)) - .input(eth_types::Bytes::from(b"0")) - .build() - .into(); - let mut rlp_bytes = generate_rlp_bytes(vec![tx.clone()]); + let mut rlp_bytes = hex::decode(const_tx_hex()).unwrap(); rlp_bytes[0] = 0xc0; - let k = log2_ceil(RlpDecoderCircuit::::min_num_rows_from_tx(&vec![tx.clone()]).0) - as usize; + let k = 12; + let witness = gen_rlp_decode_state_witness(&rlp_bytes, Fr::one(), 1 << k); + assert_eq!(witness[1].valid, false); + assert_eq!(witness[witness.len() - 2].valid, false); + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] fn invalid_rlp_wrong_list_header_len() { - let mut rng = ChaCha20Rng::seed_from_u64(2u64); - let tx: Transaction = mock::MockTransaction::default() - .from(AddrOrWallet::random(&mut rng)) - .input(eth_types::Bytes::from(b"0")) - .build() - .into(); - let mut rlp_bytes = generate_rlp_bytes(vec![tx.clone()]); + let mut rlp_bytes = hex::decode(const_tx_hex()).unwrap(); rlp_bytes[1] = 0x00; - let k = log2_ceil(RlpDecoderCircuit::::min_num_rows_from_tx(&vec![tx.clone()]).0) - as usize; + let k = 12; + let witness = gen_rlp_decode_state_witness(&rlp_bytes, Fr::one(), 1 << k); + assert_eq!(witness[1].valid, false); + assert_eq!(witness[witness.len() - 2].valid, false); + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] fn invalid_rlp_wrong_tx_header_header() { - let mut rlp_bytes = hex::decode( - "f850\ - f84e\ - 80\ - 01\ - 830f4240\ - 80\ - 80\ - 30\ - 820a98\ - a0b05805737618f6ac1ef211c02575f2fa82026fa1742caf192e2cffcd4161adca\ - a053fbe3d9957dffafca84c419fdd1cead150834c5de9f3215c66327123c0a0541", - ) - .unwrap(); - rlp_bytes[3] = 0xf5; + let mut rlp_bytes = hex::decode(&const_tx_hex()).unwrap(); + rlp_bytes[2] = 0xf5; let k = 12; + let witness = gen_rlp_decode_state_witness(&rlp_bytes, Fr::one(), 1 << k); + assert_eq!(witness[1].valid, true); + assert_eq!(witness[2].valid, false); + assert_eq!(witness[witness.len() - 2].valid, false); + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] fn invalid_rlp_wrong_tx_header_len() { - todo!() + let mut rlp_bytes = hex::decode(&const_tx_hex()).unwrap(); + rlp_bytes[3] = 0x00; + + let k = 12; + let witness = gen_rlp_decode_state_witness(&rlp_bytes, Fr::one(), 1 << k); + assert_eq!(witness[witness.len() - 2].valid, false); + + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] fn invalid_rlp_wrong_tx_field_nonce() { - todo!() + let mut rlp_bytes = hex::decode(&const_tx_hex()).unwrap(); + rlp_bytes[4] = 0x00; + + let k = 12; + let witness = gen_rlp_decode_state_witness(&rlp_bytes, Fr::one(), 1 << k); + assert_eq!(witness[2].valid, true); + assert_eq!(witness[3].valid, false); + assert_eq!(witness[witness.len() - 2].valid, false); + + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] fn invalid_rlp_wrong_tx_field_gas() { - todo!() + let mut rlp_bytes = hex::decode(&const_tx_hex()).unwrap(); + rlp_bytes[5] = 0x00; + + let k = 12; + let witness = gen_rlp_decode_state_witness(&rlp_bytes, Fr::one(), 1 << k); + assert_eq!(witness[3].valid, true); + assert_eq!(witness[4].valid, false); + assert_eq!(witness[witness.len() - 2].valid, false); + + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] fn invalid_rlp_wrong_tx_field_to() { - todo!() + let mut rlp_bytes = hex::decode(&const_tx_hex()).unwrap(); + rlp_bytes[10] = 0x00; + + let k = 12; + let witness = gen_rlp_decode_state_witness(&rlp_bytes, Fr::one(), 1 << k); + assert_eq!(witness[5].valid, true); + assert_eq!(witness[6].valid, false); + assert_eq!(witness[witness.len() - 2].valid, false); + + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] fn invalid_rlp_wrong_tx_field_data() { - todo!() + let mut rlp_bytes = hex::decode(&const_tx_hex()).unwrap(); + rlp_bytes[12] = 0x81; + rlp_bytes[13] = 0x02; + + let k = 12; + let witness = gen_rlp_decode_state_witness(&rlp_bytes, Fr::one(), 1 << k); + assert_eq!(witness[7].valid, true); + assert_eq!(witness[8].valid, false); + assert_eq!(witness[witness.len() - 2].valid, false); + + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); } #[test] From f3ce4151352122bb061a5b952d58a8fd17599cf9 Mon Sep 17 00:00:00 2001 From: smtmfft Date: Thu, 6 Jul 2023 08:02:27 +0000 Subject: [PATCH 19/21] add eof testcase --- zkevm-circuits/src/rlp_decoder.rs | 76 +++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 1bd70ef0e6..31b32baeca 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -301,6 +301,8 @@ pub struct RlpDecoderCircuitConfig { pub v_gt_0: LtConfig, /// condition check for prev_remain_length > 33 pub remain_length_gt_33: LtConfig, + /// eof error check of last remain_length must < 33 + pub remain_length_lt_33: LtConfig, /// condition check for prev_remain_length >= cur_length pub remain_length_ge_length: LtConfig, /// divide factor for big endian rlc, r_mult_comp * r_mult = r ^ MAX_BYTE_COLUMN_NUM(33) @@ -395,7 +397,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { |meta| meta.query_advice(bytes[1], Rotation::cur()), ); - let cmp_bytes_in_row_lt_prev_remain: LtConfig = LtChip::configure( + let cmp_max_row_bytes_lt_remains: LtConfig = LtChip::configure( meta, |meta| { not::expr(meta.query_advice(valid, Rotation::cur())) * meta.query_selector(q_enable) @@ -404,6 +406,15 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { |meta| meta.query_advice(rlp_remain_length, Rotation::prev()), ); + let cmp_remains_lt_max_row_bytes: LtConfig = LtChip::configure( + meta, + |meta| { + not::expr(meta.query_advice(valid, Rotation::cur())) * meta.query_selector(q_enable) + }, + |meta| meta.query_advice(rlp_remain_length, Rotation::prev()), + |_| MAX_BYTE_COLUMN_NUM.expr(), + ); + // less equal n == less than n+1 let cmp_length_le_prev_remain: LtConfig = LtChip::configure( meta, @@ -1112,15 +1123,26 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let mut cb = BaseConstraintBuilder::default(); let q_enable = meta.query_selector(q_enable); + let remain_bytes_length = meta.query_advice(rlp_remain_length, Rotation::prev()); + let tx_member_length = meta.query_advice(rlp_tx_member_length, Rotation::cur()); + let is_signs = meta.query_advice(q_tx_members[RlpTxFieldTag::SignS], Rotation::cur()); + let is_eof = meta.query_advice( decode_errors[RlpDecodeErrorType::RunOutOfDataError], Rotation::cur(), ); - cb.require_zero( - "remain < tag_len", - cmp_length_le_prev_remain.is_lt(meta, None), + cb.require_equal( + "remain == tx_member_len shows an eof error", + remain_bytes_length, + tx_member_length, ); + cb.condition(is_signs, |cb| { + cb.require_zero( + "remain < max_row_bytes in last field shows an eof error", + cmp_remains_lt_max_row_bytes.is_lt(meta, None), + ); + }); cb.gate(q_enable * is_eof) }); @@ -1142,11 +1164,11 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.require_equal("field completed", complete.expr(), 1.expr()); // if prev_remain > 33, then length = 33 else, length = prev_remain - cb.condition(cmp_bytes_in_row_lt_prev_remain.is_lt(meta, None), |cb| { + cb.condition(cmp_max_row_bytes_lt_remains.is_lt(meta, None), |cb| { cb.require_equal("decode_error length = 33", length.expr(), 33.expr()); }); cb.condition( - not::expr(cmp_bytes_in_row_lt_prev_remain.is_lt(meta, None)), + not::expr(cmp_max_row_bytes_lt_remains.is_lt(meta, None)), |cb| { cb.require_equal( "decode_error length = prev_remain", @@ -1203,7 +1225,8 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { aux_tables, v_gt_55: cmp_55_lt_byte1, v_gt_0: cmp_0_lt_byte1, - remain_length_gt_33: cmp_bytes_in_row_lt_prev_remain, + remain_length_gt_33: cmp_max_row_bytes_lt_remains, + remain_length_lt_33: cmp_remains_lt_max_row_bytes, remain_length_ge_length: cmp_length_le_prev_remain, r_mult_comp, rlc_quotient, @@ -1228,6 +1251,7 @@ impl RlpDecoderCircuitConfig { let gt_0_chip = LtChip::construct(self.v_gt_0); let gt_33_chip = LtChip::construct(self.remain_length_gt_33); + let lt_33_chip = LtChip::construct(self.remain_length_lt_33); let enough_remain_chip = LtChip::construct(self.remain_length_ge_length); let leading_val = if wit.bytes.len() > 1 { wit.bytes[1] } else { 0 }; @@ -1236,7 +1260,18 @@ impl RlpDecoderCircuitConfig { let remain_bytes = prev_wit.rlp_remain_length as u64; let current_member_bytes = wit.rlp_tx_member_length; - gt_33_chip.assign(region, offset, F::from(33u64), F::from(remain_bytes))?; + gt_33_chip.assign( + region, + offset, + F::from(MAX_BYTE_COLUMN_NUM as u64), + F::from(remain_bytes), + )?; + lt_33_chip.assign( + region, + offset, + F::from(remain_bytes), + F::from(MAX_BYTE_COLUMN_NUM as u64), + )?; enough_remain_chip.assign( region, offset, @@ -1882,6 +1917,7 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { assert!(decode_rules.len() == 2); if bytes.len() >= 1 && bytes[0] == 0x80 { // empty to address + assert!(decode_rules[1].2 == RlpDecodeRule::Empty); decode_rule = decode_rules[1].2; } state_switch!(RlpTxFieldTag::Value) @@ -2348,6 +2384,14 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } Err(consumed_bytes) => { offset += consumed_bytes.len(); + witness.append(&mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::RunOutOfDataError), + )); (RlpTxFieldTag::DecodeError, Some(offset)) } } @@ -2377,8 +2421,6 @@ fn gen_rlp_decode_state_witness( r: F, k: usize, ) -> Vec> { - let mut tx_id: u64 = 0; - // update the rlp bytes hash let mut hasher = Keccak::default(); hasher.update(bytes); @@ -2387,15 +2429,14 @@ fn gen_rlp_decode_state_witness( let mut witness = vec![RlpDecoderCircuitConfigWitness:: { rlp_remain_length: bytes.len(), value: rlc::value(hash.iter().rev(), r), - // acc_rlc_value: rlc::value(bytes.iter().rev(), r), ..Default::default() }]; + let mut tx_id: u64 = 0; let mut offset = 0; let mut init_state = RlpTxFieldTag::TxListRlpHeader; loop { - // println!("Current state: {:?}, offset = {:?}", init_state, offset); let (next_state, next_offset) = init_state.next(k, tx_id, &bytes[offset..], r, &mut witness); if next_state == RlpTxFieldTag::TxRlpHeader { @@ -3099,7 +3140,16 @@ mod rlp_decode_circuit_tests { #[test] fn invalid_rlp_not_enough_length() { - todo!() + let rlp_bytes = hex::decode(&const_tx_hex()).unwrap(); + let trimmed_rlp_bytes = &rlp_bytes[..1]; + println!("trimmed_rlp_bytes: {:?}", trimmed_rlp_bytes); + + let k = 12; + let witness = gen_rlp_decode_state_witness(trimmed_rlp_bytes, Fr::one(), 1 << k); + assert_eq!(witness[1].valid, false); + assert_eq!(witness[witness.len() - 2].valid, false); + + assert_eq!(run_invalid_rlp::(trimmed_rlp_bytes.to_vec(), k), Ok(())); } } } From 6bcb0002b9e796bf3db5315e4c88ef35a5db014f Mon Sep 17 00:00:00 2001 From: smtmfft Date: Fri, 7 Jul 2023 15:56:58 +0000 Subject: [PATCH 20/21] add more eof test --- zkevm-circuits/src/rlp_decoder.rs | 322 ++++++++++-------------------- 1 file changed, 104 insertions(+), 218 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index 31b32baeca..c3f91a708a 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -13,10 +13,7 @@ use crate::{ witness, }; use eth_types::{Field, Signature, Transaction, Word}; -use ethers_core::{ - types::TransactionRequest, - utils::rlp::{self, PayloadInfo}, -}; +use ethers_core::{types::TransactionRequest, utils::rlp}; use gadgets::{ less_than::{LtChip, LtConfig, LtInstruction}, util::{and, not, or, sum}, @@ -108,15 +105,26 @@ pub enum RlpDecodeErrorType { /// the value of rlp is invalid, for example 0x8100 or 0x8179 for string ValueError, /// the rlp is not complete, for example 0xF8 for list - RunOutOfDataError, + RunOutOfDataError(usize), +} +const RLP_DECODE_ERROR_TYPE_NUM: usize = 4; + +impl From for usize { + fn from(rlp_decode_error: RlpDecodeErrorType) -> usize { + match rlp_decode_error { + RlpDecodeErrorType::HeaderDecError => 0, + RlpDecodeErrorType::LenOfLenError => 1, + RlpDecodeErrorType::ValueError => 2, + RlpDecodeErrorType::RunOutOfDataError(_) => 3, + } + } } -const RLP_DECODE_ERROR_TYPE_NUM: usize = RlpDecodeErrorType::RunOutOfDataError as usize + 1; impl std::ops::Index for [T; N] { type Output = T; fn index(&self, index: RlpDecodeErrorType) -> &Self::Output { - &self[index as usize] + &self[usize::from(index)] } } @@ -124,7 +132,7 @@ impl std::ops::Index for Vec { type Output = T; fn index(&self, index: RlpDecodeErrorType) -> &Self::Output { - &self[index as usize] + &self[usize::from(index)] } } @@ -541,7 +549,8 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { }); meta.lookup_any("rlp r_mult_comp check", |meta| { let r_mult_comp = meta.query_advice(r_mult_comp, Rotation::cur()); - let pow = 33.expr() - meta.query_advice(tx_member_bytes_in_row, Rotation::cur()); + let pow = MAX_BYTE_COLUMN_NUM.expr() + - meta.query_advice(tx_member_bytes_in_row, Rotation::cur()); let table = &aux_tables.rlp_fixed_table.r_mult_pow_table; let table_tag = meta.query_fixed(table.table_tag, Rotation::cur()); @@ -1128,7 +1137,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { let is_signs = meta.query_advice(q_tx_members[RlpTxFieldTag::SignS], Rotation::cur()); let is_eof = meta.query_advice( - decode_errors[RlpDecodeErrorType::RunOutOfDataError], + decode_errors[RlpDecodeErrorType::RunOutOfDataError(0)], Rotation::cur(), ); @@ -1189,19 +1198,6 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { cb.gate(q_error.expr() * meta.query_selector(q_enable)) }); - meta.create_gate("end with padding", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - let q_enable = meta.query_selector(q_enable); - let q_last = meta.query_fixed(q_last, Rotation::cur()); - let q_padding = - meta.query_advice(q_tx_members[RlpTxFieldTag::Padding], Rotation::cur()); - - cb.require_equal("padding at last", q_padding, 1.expr()); - - cb.gate(q_last * q_enable) - }); - let circuit_config = RlpDecoderCircuitConfig { tx_id, tx_type, @@ -1705,146 +1701,6 @@ fn generate_rlp_type_witness( (rlp_type, header_decodable, len_decodable, value_decodable) } -fn generate_fields_witness_len(tag: &RlpTxFieldTag, payload: &PayloadInfo) -> usize { - match tag { - RlpTxFieldTag::TxListRlpHeader => payload.header_len, - RlpTxFieldTag::TxRlpHeader => payload.header_len, - _ => payload.total(), - } -} - -fn generate_rlp_row_witness( - tx_id: u64, - tx_member: &RlpTxFieldTag, - raw_bytes: &[u8], - r: F, - rlp_remain_length: usize, -) -> Vec> { - let mut witness = vec![]; - let (mut rlp_type, header_decodable, len_decodable, value_decodable) = - generate_rlp_type_witness(tx_member, raw_bytes); - let partial_rlp_type = RlpDecodeTypeTag::PartialRlp; - let rlp_tag_len = raw_bytes.len(); - let mut prev_rlp_remain_length = rlp_remain_length; - - macro_rules! generate_witness { - () => {{ - let mut temp_witness_vec = Vec::new(); - let mut tag_remain_length = rlp_tag_len; - let mut raw_bytes_offset = 0; - while tag_remain_length > MAX_BYTE_COLUMN_NUM { - temp_witness_vec.push(RlpDecoderCircuitConfigWitness:: { - tx_id: tx_id, - tx_type: RlpTxTypeTag::TxLegacyType, - tx_member: tx_member.clone(), - complete: false, - rlp_type: rlp_type, - rlp_tx_member_length: tag_remain_length as u64, - rlp_bytes_in_row: MAX_BYTE_COLUMN_NUM as u8, - r_mult: r.pow(&[MAX_BYTE_COLUMN_NUM as u64, 0, 0, 0]), - rlp_remain_length: prev_rlp_remain_length - MAX_BYTE_COLUMN_NUM, - value: F::zero(), - acc_rlc_value: F::zero(), - bytes: raw_bytes[raw_bytes_offset..raw_bytes_offset + MAX_BYTE_COLUMN_NUM] - .to_vec(), - errors: [!header_decodable, !len_decodable, !value_decodable, false], - valid: header_decodable && len_decodable && value_decodable, - q_enable: true, - q_first: false, - q_last: false, - r_mult_comp: F::one(), - rlc_quotient: F::zero(), - }); - raw_bytes_offset += MAX_BYTE_COLUMN_NUM; - tag_remain_length -= MAX_BYTE_COLUMN_NUM; - prev_rlp_remain_length -= MAX_BYTE_COLUMN_NUM; - rlp_type = partial_rlp_type; - } - temp_witness_vec.push(RlpDecoderCircuitConfigWitness:: { - tx_id: tx_id, - tx_type: RlpTxTypeTag::TxLegacyType, - tx_member: tx_member.clone(), - complete: true, - rlp_type: rlp_type, - rlp_tx_member_length: tag_remain_length as u64, - rlp_bytes_in_row: tag_remain_length as u8, - r_mult: r.pow(&[tag_remain_length as u64, 0, 0, 0]), - rlp_remain_length: prev_rlp_remain_length - tag_remain_length, - value: F::zero(), - acc_rlc_value: F::zero(), - bytes: raw_bytes[raw_bytes_offset..].to_vec(), - errors: [!header_decodable, !len_decodable, !value_decodable, false], - valid: header_decodable && len_decodable && value_decodable, - q_enable: true, - q_first: false, - q_last: false, - r_mult_comp: r.pow(&[(MAX_BYTE_COLUMN_NUM - tag_remain_length) as u64, 0, 0, 0]), - rlc_quotient: F::zero(), - }); - temp_witness_vec - }}; - } - - // TODO: reorganize the match - match tx_member { - RlpTxFieldTag::TxListRlpHeader => witness.append(&mut generate_witness!()), - RlpTxFieldTag::TxRlpHeader => witness.append(&mut generate_witness!()), - RlpTxFieldTag::Nonce => witness.append(&mut generate_witness!()), - RlpTxFieldTag::GasPrice => witness.append(&mut generate_witness!()), - RlpTxFieldTag::Gas => witness.append(&mut generate_witness!()), - RlpTxFieldTag::To => witness.append(&mut generate_witness!()), - RlpTxFieldTag::Value => witness.append(&mut generate_witness!()), - RlpTxFieldTag::Data => witness.append(&mut generate_witness!()), - RlpTxFieldTag::SignV => witness.append(&mut generate_witness!()), - RlpTxFieldTag::SignR => witness.append(&mut generate_witness!()), - RlpTxFieldTag::SignS => witness.append(&mut generate_witness!()), - RlpTxFieldTag::DecodeError => witness.append(&mut generate_witness!()), - RlpTxFieldTag::Padding => { - unreachable!("Padding should not be here") - } - _ => { - unreachable!("1559 not support now") - } - } - witness -} - -fn generate_rlp_txfield_witness( - tx_id: u64, - tag: &RlpTxFieldTag, - bytes: &[u8], - r: F, - witness: &mut Vec>, -) -> Option { - let offset = 0; - let decode_result = PayloadInfo::from(&bytes[offset..]); - - match decode_result { - Ok(payload_info) => { - let bytes_num = generate_fields_witness_len(tag, &payload_info); - let rlp_remain_length = witness - .last() - .map_or(payload_info.total(), |w| w.rlp_remain_length); - - witness.append(&mut generate_rlp_row_witness( - tx_id, - tag, - &bytes[offset..offset + bytes_num], - r, - rlp_remain_length, - )); - Some(payload_info) - } - // TODO: error case - Err(decoder_err) => match decoder_err { - rlp::DecoderError::RlpIsTooShort => todo!(), - rlp::DecoderError::RlpDataLenWithZeroPrefix => todo!(), - rlp::DecoderError::RlpInvalidIndirection => todo!(), - _ => unimplemented!("Unsupport payload decode error: {:?}", decoder_err), - }, - } -} - trait RlpTxFieldStateWittnessGenerator { fn next( &self, @@ -2025,8 +1881,8 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } 0x81..=0x88 => { let mut offset = 1; - let len_of_val = head_byte0 - 0x80; - let res = read_nbytes(&bytes[offset..], len_of_val as usize); + let len_of_val = (head_byte0 - 0x80) as usize; + let res = read_nbytes(&bytes[offset..], len_of_val); match res { Ok(val_bytes_read) => { let val_byte0 = val_bytes_read[0]; @@ -2071,7 +1927,7 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { &bytes[..offset], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError), + Some(RlpDecodeErrorType::RunOutOfDataError(len_of_val)), )); (RlpTxFieldTag::DecodeError, Some(offset)) } @@ -2093,8 +1949,8 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } 0x81..=0xa0 => { let mut offset = 1; - let len_of_val = head_byte0 - 0x80; - let res = read_nbytes(&bytes[offset..], len_of_val as usize); + let len_of_val = (head_byte0 - 0x80) as usize; + let res = read_nbytes(&bytes[offset..], len_of_val); match res { Ok(val_bytes_read) => { let val_byte0 = val_bytes_read[0]; @@ -2139,7 +1995,7 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { &bytes[..offset], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError), + Some(RlpDecodeErrorType::RunOutOfDataError(len_of_val)), )); (RlpTxFieldTag::DecodeError, Some(offset)) } @@ -2150,8 +2006,8 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { RlpDecodeRule::Address => match head_byte0 { 0x94 => { let mut offset = 1; - let len_of_val = 0x14; - let res = read_nbytes(&bytes[offset..], len_of_val as usize); + let len_of_val = 0x14 as usize; + let res = read_nbytes(&bytes[offset..], len_of_val); match res { Ok(val_bytes_read) => { offset += val_bytes_read.len(); @@ -2173,7 +2029,7 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { &bytes[..offset], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError), + Some(RlpDecodeErrorType::RunOutOfDataError(len_of_val)), )); (RlpTxFieldTag::DecodeError, Some(offset)) } @@ -2195,8 +2051,8 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } 0x81..=0xb7 => { let mut offset = 1; - let len_of_val = head_byte0 - 0x80; - let res = read_nbytes(&bytes[offset..], len_of_val as usize); + let len_of_val = (head_byte0 - 0x80) as usize; + let res = read_nbytes(&bytes[offset..], len_of_val); match res { Ok(val_bytes_read) => { let val_byte0 = val_bytes_read[0]; @@ -2225,15 +2081,14 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } } Err(val_bytes_read) => { - let bytes_len = (val_bytes_read.len() + offset) - .min(MAX_BYTE_COLUMN_NUM); + let bytes_len = val_bytes_read.len() + offset; witness.append(&mut generate_rlp_row_witness_new( tx_id, self, &bytes[..bytes_len], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError), + Some(RlpDecodeErrorType::RunOutOfDataError(len_of_val)), )); ( RlpTxFieldTag::DecodeError, @@ -2244,8 +2099,8 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } 0xb8..=0xba => { let mut offset = 1; - let len_of_len = head_byte0 - 0xb7; - let res = read_nbytes(&bytes[offset..], len_of_len as usize); + let len_of_len = (head_byte0 - 0xb7) as usize; + let res = read_nbytes(&bytes[offset..], len_of_len); match res { Ok(len_bytes_read) => { let len_byte0 = len_bytes_read[0]; @@ -2291,8 +2146,7 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { (next_state, Some(offset)) } Err(val_bytes_read) => { - let bytes_len = (offset + val_bytes_read.len()) - .min(MAX_BYTE_COLUMN_NUM); + let bytes_len = offset + val_bytes_read.len(); witness .append(&mut generate_rlp_row_witness_new( tx_id, @@ -2300,7 +2154,11 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { &bytes[..bytes_len], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError), + Some( + RlpDecodeErrorType::RunOutOfDataError( + val_bytes_len, + ), + ), )); (RlpTxFieldTag::DecodeError, Some(bytes_len)) } @@ -2315,7 +2173,7 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { &bytes[..offset], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError), + Some(RlpDecodeErrorType::RunOutOfDataError(len_of_len)), )); (RlpTxFieldTag::DecodeError, Some(offset)) } @@ -2340,8 +2198,8 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { (RlpTxFieldTag::DecodeError, Some(1)) } else { let mut offset = 1; - let len_of_len = header_byte0 - 0xF7; - let res = read_nbytes(&bytes[offset..], len_of_len as usize); + let len_of_len = (header_byte0 - 0xF7) as usize; + let res = read_nbytes(&bytes[offset..], len_of_len); match res { Ok(len_bytes_read) => { let len_byte0 = len_bytes_read[0]; @@ -2390,7 +2248,7 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { &bytes[..offset], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError), + Some(RlpDecodeErrorType::RunOutOfDataError(len_of_len)), )); (RlpTxFieldTag::DecodeError, Some(offset)) } @@ -2408,7 +2266,7 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { &bytes, r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError), + Some(RlpDecodeErrorType::RunOutOfDataError(1)), )); (RlpTxFieldTag::DecodeError, Some(0)) } @@ -2512,10 +2370,10 @@ fn generate_rlp_row_witness_new( raw_bytes: &[u8], r: F, rlp_remain_length: usize, - error_id: Option, + error_type: Option, ) -> Vec> { log::trace!("generate witness for (tx_id: {}, tx_member: {:?}, raw_bytes: {:?}, r: {:?}, rlp_remain_length: {:?}, error_id: {:?})", - tx_id, tx_member, raw_bytes, r, rlp_remain_length, error_id); + tx_id, tx_member, raw_bytes, r, rlp_remain_length, error_type); let mut witness = vec![]; let (mut rlp_type, _, _, _) = generate_rlp_type_witness(tx_member, raw_bytes); let partial_rlp_type = RlpDecodeTypeTag::PartialRlp; @@ -2523,9 +2381,21 @@ fn generate_rlp_row_witness_new( let mut prev_rlp_remain_length = rlp_remain_length; // error case never cross raw - assert!(error_id.is_none() || (raw_bytes.len() <= MAX_BYTE_COLUMN_NUM)); let mut errors = [false; 4]; - error_id.map(|id| errors[id as usize] = true); + if let Some(error_idx) = error_type { + match error_idx { + RlpDecodeErrorType::HeaderDecError + | RlpDecodeErrorType::LenOfLenError + | RlpDecodeErrorType::ValueError => { + assert!(error_type.is_none() || (raw_bytes.len() <= MAX_BYTE_COLUMN_NUM)); + errors[usize::from(error_idx)] = true; + } + RlpDecodeErrorType::RunOutOfDataError(_) => { + errors[usize::from(error_idx)] = true; + } + } + } + macro_rules! generate_witness { () => {{ let mut temp_witness_vec = Vec::new(); @@ -2546,7 +2416,7 @@ fn generate_rlp_row_witness_new( acc_rlc_value: F::zero(), bytes: raw_bytes[raw_bytes_offset..raw_bytes_offset + MAX_BYTE_COLUMN_NUM] .to_vec(), - errors: errors, + errors: [false; 4], valid: (tx_member != &RlpTxFieldTag::DecodeError) && errors.iter().all(|&err| !err), q_enable: true, @@ -2874,11 +2744,6 @@ mod rlp_decode_circuit_tests { let encodable_txs: Vec = txs.iter().map(|tx| tx.into()).collect::>(); let rlp_bytes = rlp::encode_list(&encodable_txs); - println!( - "input rlp_bytes = {:?}, k = {}.", - hex::encode(&rlp_bytes), - k - ); let circuit = RlpDecoderCircuit::::new(rlp_bytes.to_vec(), k as usize); let prover = match MockProver::run(k, &circuit, vec![]) { @@ -2967,18 +2832,18 @@ mod rlp_decode_circuit_tests { use super::*; use pretty_assertions::assert_eq; - /// predefined tx bytes - /// "f8 50" // witness[1]: list header - /// "f8 4e" // witness[2]: tx header - /// "80" // witness[3]: nonce - /// "01" // witness[4]: gas_price - /// "83 0f4240" // witness[5]: gas - /// "80" // witness[6]: to - /// "80" // witness[7]: value - /// "82 3031" // witness[8]: input - /// "82 0a98" // witness[9]: v - /// "a0 b05805737618f6ac1ef211c02575f2fa82026fa1742caf192e2cffcd4161adca" // witness[10]: r - /// "a0 53fbe3d9957dffafca84c419fdd1cead150834c5de9f3215c66327123c0a0541" // witness[11]: s + /// predefined tx bytes:
+ /// "f8 50" : witness[1]: list header
+ /// "f8 4e" : witness[2]: tx header
+ /// "80" : witness[3]: nonce
+ /// "01" : witness[4]: gas_price
+ /// "83 0f4240" : witness[5]: gas
+ /// "80" : witness[6]: to
+ /// "80" : witness[7]: value
+ /// "82 3031" : witness[8]: input
+ /// "82 0a98" : witness[9]: v
+ /// "a0 b058..adca" : witness[10]: r
+ /// "a0 53fb..0541" : witness[11]: s
fn const_tx_hex() -> String { String::from("f852") + "f850" @@ -2994,16 +2859,10 @@ mod rlp_decode_circuit_tests { } fn generate_rlp_bytes(txs: Vec) -> Vec { - let k = log2_ceil(RlpDecoderCircuit::::min_num_rows_from_tx(&txs).0); - let encodable_txs: Vec = txs.iter().map(|tx| tx.into()).collect::>(); let rlp_bytes = rlp::encode_list(&encodable_txs); - println!( - "input rlp_bytes = {:?}, k = {}.", - hex::encode(&rlp_bytes), - k - ); + // println!("input rlp_bytes = {:?}", hex::encode(&rlp_bytes)); rlp_bytes.to_vec() } @@ -3146,11 +3005,38 @@ mod rlp_decode_circuit_tests { let k = 12; let witness = gen_rlp_decode_state_witness(trimmed_rlp_bytes, Fr::one(), 1 << k); - assert_eq!(witness[1].valid, false); - assert_eq!(witness[witness.len() - 2].valid, false); + // assert_eq!(witness[1].valid, false); + // assert_eq!(witness[witness.len() - 2].valid, false); assert_eq!(run_invalid_rlp::(trimmed_rlp_bytes.to_vec(), k), Ok(())); } + + #[test] + fn invalid_rlp_eof_in_data() { + let mut rng = ChaCha20Rng::seed_from_u64(2u64); + let txs: Vec = vec![mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from( + (0..65536).map(|v| v as u8).collect::>(), + )) + .build() + .into()]; + let rlp_bytes = generate_rlp_bytes(txs.clone()); + assert_eq!(rlp_bytes.len(), 16 + 4 + 65536 + 3 + 33 + 33); + + let trimmed_size = rlp_bytes.len() - 33 - 33 - 3 - 1500; + let trimmed_rlp_bytes = &rlp_bytes[..trimmed_size]; + + let size = RlpDecoderCircuit::::min_num_rows_from_tx(&txs.clone()).0; + let witness = gen_rlp_decode_state_witness(trimmed_rlp_bytes, Fr::one(), size); + let eof_error_offset = (65536 - 1500) / 33 + 8 + 1; + // assert_eq!(witness[eof_error_offset - 1].valid, true); + // assert_eq!(witness[eof_error_offset].valid, false); + // assert_eq!(witness[witness.len() - 2].valid, false); + + let k = log2_ceil(size) as usize; + assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); + } } } From 6e151a9e2ab1c75801bed376221e91472514093b Mon Sep 17 00:00:00 2001 From: smtmfft Date: Sun, 9 Jul 2023 09:33:28 +0000 Subject: [PATCH 21/21] refine eof error logic --- zkevm-circuits/src/rlp_decoder.rs | 196 +++++++++++++++++++++--------- 1 file changed, 137 insertions(+), 59 deletions(-) diff --git a/zkevm-circuits/src/rlp_decoder.rs b/zkevm-circuits/src/rlp_decoder.rs index c3f91a708a..59c6e70b9d 100644 --- a/zkevm-circuits/src/rlp_decoder.rs +++ b/zkevm-circuits/src/rlp_decoder.rs @@ -706,6 +706,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { meta.query_advice(q_tx_members[RlpTxFieldTag::TxRlpHeader], Rotation::cur()); let q_dec_error = meta.query_advice(q_tx_members[RlpTxFieldTag::DecodeError], Rotation::cur()); + let q_valid = meta.query_advice(valid, Rotation::cur()); let q_enable = meta.query_selector(q_enable); let q_first = meta.query_fixed(q_first, Rotation::cur()); @@ -827,7 +828,7 @@ impl SubCircuitConfig for RlpDecoderCircuitConfig { ) }); cb.condition( - rlp_type_enabled!(meta, RlpDecodeTypeTag::PartialRlp), + rlp_type_enabled!(meta, RlpDecodeTypeTag::PartialRlp) * q_valid.expr(), |cb| { cb.require_equal( "length = prev_length - prev_bytes_in_row", @@ -1920,16 +1921,18 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } } Err(val_bytes_read) => { - offset += val_bytes_read.len(); + let readed_len = val_bytes_read.len(); witness.append(&mut generate_rlp_row_witness_new( tx_id, self, - &bytes[..offset], + &bytes[..offset + readed_len], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError(len_of_val)), + Some(RlpDecodeErrorType::RunOutOfDataError( + offset + len_of_val, + )), )); - (RlpTxFieldTag::DecodeError, Some(offset)) + (RlpTxFieldTag::DecodeError, Some(offset + readed_len)) } } } @@ -1988,16 +1991,18 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } } Err(val_bytes_read) => { - offset += val_bytes_read.len(); + let read_len = val_bytes_read.len(); witness.append(&mut generate_rlp_row_witness_new( tx_id, self, - &bytes[..offset], + &bytes[..offset + read_len], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError(len_of_val)), + Some(RlpDecodeErrorType::RunOutOfDataError( + offset + len_of_val, + )), )); - (RlpTxFieldTag::DecodeError, Some(offset)) + (RlpTxFieldTag::DecodeError, Some(offset + read_len)) } } } @@ -2022,16 +2027,18 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { (next_state, Some(offset)) } Err(val_bytes_read) => { - offset += val_bytes_read.len(); + let read_len = val_bytes_read.len(); witness.append(&mut generate_rlp_row_witness_new( tx_id, self, - &bytes[..offset], + &bytes[..offset + read_len], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError(len_of_val)), + Some(RlpDecodeErrorType::RunOutOfDataError( + offset + len_of_val, + )), )); - (RlpTxFieldTag::DecodeError, Some(offset)) + (RlpTxFieldTag::DecodeError, Some(offset + read_len)) } } } @@ -2081,19 +2088,19 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } } Err(val_bytes_read) => { - let bytes_len = val_bytes_read.len() + offset; + let read_len = val_bytes_read.len(); + let bytes_len = offset + read_len; witness.append(&mut generate_rlp_row_witness_new( tx_id, self, &bytes[..bytes_len], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError(len_of_val)), + Some(RlpDecodeErrorType::RunOutOfDataError( + offset + len_of_val, + )), )); - ( - RlpTxFieldTag::DecodeError, - Some(offset + val_bytes_read.len()), - ) + (RlpTxFieldTag::DecodeError, Some(bytes_len)) } } } @@ -2146,7 +2153,8 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { (next_state, Some(offset)) } Err(val_bytes_read) => { - let bytes_len = offset + val_bytes_read.len(); + let read_len = val_bytes_read.len(); + let bytes_len = offset + read_len; witness .append(&mut generate_rlp_row_witness_new( tx_id, @@ -2156,7 +2164,7 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { rlp_remain_length, Some( RlpDecodeErrorType::RunOutOfDataError( - val_bytes_len, + offset + val_bytes_len, ), ), )); @@ -2166,16 +2174,19 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { } } Err(len_bytes_read) => { - offset += len_bytes_read.len(); + let read_len = len_bytes_read.len(); + let bytes_len = offset + read_len; witness.append(&mut generate_rlp_row_witness_new( tx_id, self, - &bytes[..offset], + &bytes[..bytes_len], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError(len_of_len)), + Some(RlpDecodeErrorType::RunOutOfDataError( + offset + len_of_len, + )), )); - (RlpTxFieldTag::DecodeError, Some(offset)) + (RlpTxFieldTag::DecodeError, Some(bytes_len)) } } } @@ -2229,28 +2240,52 @@ impl RlpTxFieldStateWittnessGenerator for RlpTxFieldTag { // TODO: consume rlp_bytes_len(consumed_bytes) and get // EOF error earlier? offset += len_bytes_read.len(); - witness.append(&mut generate_rlp_row_witness_new( - tx_id, - self, - &bytes[..offset], - r, - rlp_remain_length, - None, - )); - (next_state, Some(offset)) + let val_bytes_len = rlp_bytes_len(len_bytes_read); + let res = read_nbytes(&bytes[offset..], val_bytes_len); + match res { + Ok(_) => { + witness.append( + &mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + None, + ), + ); + (next_state, Some(offset)) + } + Err(_) => { + witness.append( + &mut generate_rlp_row_witness_new( + tx_id, + self, + &bytes[..offset], + r, + rlp_remain_length, + Some(RlpDecodeErrorType::ValueError), + ), + ); + (RlpTxFieldTag::DecodeError, Some(offset)) + } + } } } Err(consumed_bytes) => { - offset += consumed_bytes.len(); + let read_len = consumed_bytes.len(); + let bytes_len = offset + read_len; witness.append(&mut generate_rlp_row_witness_new( tx_id, self, - &bytes[..offset], + &bytes[..bytes_len], r, rlp_remain_length, - Some(RlpDecodeErrorType::RunOutOfDataError(len_of_len)), + Some(RlpDecodeErrorType::RunOutOfDataError( + offset + len_of_len, + )), )); - (RlpTxFieldTag::DecodeError, Some(offset)) + (RlpTxFieldTag::DecodeError, Some(bytes_len)) } } } @@ -2372,26 +2407,30 @@ fn generate_rlp_row_witness_new( rlp_remain_length: usize, error_type: Option, ) -> Vec> { - log::trace!("generate witness for (tx_id: {}, tx_member: {:?}, raw_bytes: {:?}, r: {:?}, rlp_remain_length: {:?}, error_id: {:?})", - tx_id, tx_member, raw_bytes, r, rlp_remain_length, error_type); + // log::trace!("generate witness for (tx_id: {}, tx_member: {:?}, raw_bytes: {:?}, r: {:?}, + // rlp_remain_length: {:?}, error_id: {:?})", tx_id, tx_member, raw_bytes, r, + // rlp_remain_length, error_type); let mut witness = vec![]; let (mut rlp_type, _, _, _) = generate_rlp_type_witness(tx_member, raw_bytes); let partial_rlp_type = RlpDecodeTypeTag::PartialRlp; - let rlp_tag_len = raw_bytes.len(); + let mut rlp_tx_member_len = raw_bytes.len(); + let mut rlp_bytes_remain_len = raw_bytes.len(); let mut prev_rlp_remain_length = rlp_remain_length; - // error case never cross raw let mut errors = [false; 4]; if let Some(error_idx) = error_type { match error_idx { RlpDecodeErrorType::HeaderDecError | RlpDecodeErrorType::LenOfLenError | RlpDecodeErrorType::ValueError => { + // these error cases never cross raw assert!(error_type.is_none() || (raw_bytes.len() <= MAX_BYTE_COLUMN_NUM)); errors[usize::from(error_idx)] = true; } - RlpDecodeErrorType::RunOutOfDataError(_) => { + RlpDecodeErrorType::RunOutOfDataError(decode_len) => { errors[usize::from(error_idx)] = true; + assert!(rlp_tx_member_len < decode_len); + rlp_tx_member_len = decode_len; } } } @@ -2399,9 +2438,9 @@ fn generate_rlp_row_witness_new( macro_rules! generate_witness { () => {{ let mut temp_witness_vec = Vec::new(); - let mut tag_remain_length = rlp_tag_len; + let mut tag_remain_length = rlp_tx_member_len; let mut raw_bytes_offset = 0; - while tag_remain_length > MAX_BYTE_COLUMN_NUM { + while rlp_bytes_remain_len > MAX_BYTE_COLUMN_NUM { temp_witness_vec.push(RlpDecoderCircuitConfigWitness:: { tx_id: tx_id, tx_type: RlpTxTypeTag::TxLegacyType, @@ -2417,8 +2456,7 @@ fn generate_rlp_row_witness_new( bytes: raw_bytes[raw_bytes_offset..raw_bytes_offset + MAX_BYTE_COLUMN_NUM] .to_vec(), errors: [false; 4], - valid: (tx_member != &RlpTxFieldTag::DecodeError) - && errors.iter().all(|&err| !err), + valid: true, q_enable: true, q_first: false, q_last: false, @@ -2427,6 +2465,7 @@ fn generate_rlp_row_witness_new( }); raw_bytes_offset += MAX_BYTE_COLUMN_NUM; tag_remain_length -= MAX_BYTE_COLUMN_NUM; + rlp_bytes_remain_len -= MAX_BYTE_COLUMN_NUM; prev_rlp_remain_length -= MAX_BYTE_COLUMN_NUM; rlp_type = partial_rlp_type; } @@ -2436,10 +2475,10 @@ fn generate_rlp_row_witness_new( tx_member: tx_member.clone(), complete: true, rlp_type: rlp_type, - rlp_tx_member_length: tag_remain_length as u64, - rlp_bytes_in_row: tag_remain_length as u8, - r_mult: r.pow(&[tag_remain_length as u64, 0, 0, 0]), - rlp_remain_length: prev_rlp_remain_length - tag_remain_length, + rlp_tx_member_length: rlp_bytes_remain_len as u64, + rlp_bytes_in_row: rlp_bytes_remain_len as u8, + r_mult: r.pow(&[rlp_bytes_remain_len as u64, 0, 0, 0]), + rlp_remain_length: prev_rlp_remain_length - rlp_bytes_remain_len, value: F::zero(), acc_rlc_value: F::zero(), bytes: raw_bytes[raw_bytes_offset..].to_vec(), @@ -2448,7 +2487,7 @@ fn generate_rlp_row_witness_new( q_enable: true, q_first: tx_member == &RlpTxFieldTag::TxListRlpHeader, q_last: false, - r_mult_comp: r.pow(&[(MAX_BYTE_COLUMN_NUM - tag_remain_length) as u64, 0, 0, 0]), + r_mult_comp: r.pow(&[(MAX_BYTE_COLUMN_NUM - rlp_bytes_remain_len) as u64, 0, 0, 0]), rlc_quotient: F::zero(), }); temp_witness_vec @@ -2720,8 +2759,50 @@ mod rlp_test { } #[test] - fn test_wrong_witness_generation() { - todo!() + fn test_wrong_witness_generation_eof_in_txlist_header() { + let mut rng = ChaCha20Rng::seed_from_u64(2u64); + let tx: SignedTransaction = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from( + (0..30000).map(|v| v as u8).collect::>(), + )) + .build() + .into(); + println!("tx = {:?}", tx); + + let rlp_txs = rlp::encode_list(&[tx]); + println!("rlp_txs = {:?}", hex::encode(rlp_txs.clone())); + let randomness = Fr::from(100); + let k = 4096; + + let rlp_bytes = rlp_txs.to_vec(); + let trimmed_bytes = &rlp_bytes[0..rlp_bytes.len() - 500]; + let witness = gen_rlp_decode_state_witness::(trimmed_bytes, randomness, k as usize); + assert_eq!(witness[1].valid, false); + } + + #[test] + fn test_wrong_witness_generation_eof_in_tx_header() { + let mut rng = ChaCha20Rng::seed_from_u64(2u64); + let tx: SignedTransaction = mock::MockTransaction::default() + .from(AddrOrWallet::random(&mut rng)) + .input(eth_types::Bytes::from( + (0..30000).map(|v| v as u8).collect::>(), + )) + .build() + .into(); + println!("tx = {:?}", tx); + + let rlp_txs = rlp::encode_list(&[tx]); + println!("rlp_txs = {:?}", hex::encode(rlp_txs.clone())); + let randomness = Fr::from(100); + let k = 4096; + + let mut rlp_bytes = rlp_txs.to_vec(); + rlp_bytes[3] = 0xFF; + let wront_tx_bytes = &rlp_bytes; + let witness = gen_rlp_decode_state_witness::(wront_tx_bytes, randomness, k as usize); + assert_eq!(witness[2].valid, false); } } @@ -3029,13 +3110,10 @@ mod rlp_decode_circuit_tests { let size = RlpDecoderCircuit::::min_num_rows_from_tx(&txs.clone()).0; let witness = gen_rlp_decode_state_witness(trimmed_rlp_bytes, Fr::one(), size); - let eof_error_offset = (65536 - 1500) / 33 + 8 + 1; - // assert_eq!(witness[eof_error_offset - 1].valid, true); - // assert_eq!(witness[eof_error_offset].valid, false); - // assert_eq!(witness[witness.len() - 2].valid, false); + assert_eq!(witness[1].valid, false); let k = log2_ceil(size) as usize; - assert_eq!(run_invalid_rlp::(rlp_bytes, k), Ok(())); + assert_eq!(run_invalid_rlp::(trimmed_rlp_bytes.to_vec(), k), Ok(())); } } }