diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..6f95e9cd9 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,5 @@ +[patch.crates-io] +cc = { git = "https://github.com/rust-lang/cc-rs", tag = "1.0.79" } + +[env] +CARGO_WORKSPACE_DIR = { value = "", relative = true } diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..3ace994aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +target/ +tmp/ +log.txt +*.pb +rpc_cache.json diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..9b8dacbaf --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/testdata"] + path = lib/testdata + url = https://github.com/ethereum/tests.git diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..61de21922 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "rust-analyzer.linkedProjects": [ + "./guests/eth-block/Cargo.toml", + "./host/Cargo.toml" + ] +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..ea2327bd2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4602 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addchain" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" +dependencies = [ + "num-bigint 0.3.3", + "num-integer", + "num-traits", +] + +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "cpp_demangle", + "fallible-iterator", + "gimli", + "memmap2", + "object", + "rustc-demangle", + "smallvec", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aes" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[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]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloy-primitives" +version = "0.3.1" +source = "git+https://github.com/alloy-rs/core.git?rev=58e2259#58e2259a858f9a1ac7ebb0eb421dce5bb6305850" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "proptest", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f938f00332d63a5b0ac687bd6f46d03884638948921d9f8b50c59563d421ae25" +dependencies = [ + "arrayvec", + "bytes", + "smol_str", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa5bb468bc7c46e0c5074d418f575262ff79451242e5ac1380121ed4e23c4fd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint 0.4.3", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools", + "num-bigint 0.4.3", + "num-traits", + "paste", + "rustc_version 0.4.0", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint 0.4.3", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint 0.4.3", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint 0.4.3", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "assert_cmd" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "async-trait" +version = "0.1.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "async_io_stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +dependencies = [ + "futures", + "pharos", + "rustc_version 0.4.0", +] + +[[package]] +name = "auto_impl" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "autotools" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8da1805e028a172334c3b680f93e71126f2327622faef2ec3d893c0a4ad77" +dependencies = [ + "cc", +] + +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "serde", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bonsai-sdk" +version = "0.2.0" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "reqwest", + "serde", + "thiserror", +] + +[[package]] +name = "bstr" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.18", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "git+https://github.com/rust-lang/cc-rs?tag=1.0.79#e5bbdfa1fa468c028cb38fee6c35a3cf2e5a2736" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "winapi", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clap" +version = "4.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eab9e8ceb9afdade1ab3f0fd8dbce5b1b2f468ad653baf10e771781b2b67b73" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f2763db829349bf00cfc06251268865ed4363b93a943174f638daf3ecdba2cd" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "const-hex" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "268f52aae268980d03dd9544c1ea591965b2735b038d6998d6e4ab37c8c24445" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpp_demangle" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee34052ee3d93d6d8f3e6f81d85c47921f6653a19a7b70e939e3e602d893a674" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.2" +source = "git+https://github.com/risc0/RustCrypto-crypto-bigint?tag=v0.5.2-risc0#8b30304277cfe553b51a78a0e693f48bbb059eb3" +dependencies = [ + "generic-array", + "getrandom", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.26", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + +[[package]] +name = "der" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "downloader" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05213e96f184578b5f70105d4d0a644a168e99e12d7bea0b200c15d67b5c182" +dependencies = [ + "futures", + "rand", + "reqwest", + "thiserror", + "tokio", +] + +[[package]] +name = "dyn_partial_eq" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07039d197226c4b9a3810c4f165328fb4e715258a4b8584f143d38e9de04301" +dependencies = [ + "dyn_partial_eq_derive", +] + +[[package]] +name = "dyn_partial_eq_derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e217c6c1435ebf9b88662354589d339192b8eaf506edd22951e75e045c8e8bd" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ecdsa" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "elf" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b183d6ce6ca4cf30e3db37abf5b52568b5f9015c97d9fbdd7026aa5dcdd758" + +[[package]] +name = "elliptic-curve" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf56acd72bb22d2824e66ae8e9e5ada4d0de17a69c7fd35569dde2ada8ec9116" +dependencies = [ + "base64 0.13.1", + "bytes", + "hex", + "k256", + "log", + "rand", + "rlp", + "serde", + "sha3", + "zeroize", +] + +[[package]] +name = "enumn" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9838a970f5de399d3070ae1739e131986b2f5dcc223c7423ca0927e3a878522" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "erased-serde" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da96524cc884f6558f1769b6c46686af2fe8e8b4cd253bd5a3cdba8181b8e070" +dependencies = [ + "serde", +] + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "ethabi" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "scale-info", + "uint", +] + +[[package]] +name = "ethers-core" +version = "2.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60ca2514feb98918a0a31de7e1983c29f2267ebf61b2dc5d4294f91e5b866623" +dependencies = [ + "arrayvec", + "bytes", + "chrono", + "elliptic-curve", + "ethabi", + "generic-array", + "hex", + "k256", + "num_enum", + "open-fastrlp", + "rand", + "rlp", + "serde", + "serde_json", + "strum", + "tempfile", + "thiserror", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "ethers-providers" +version = "2.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b411b119f1cf0efb69e2190883dee731251882bb21270f893ee9513b3a697c48" +dependencies = [ + "async-trait", + "auto_impl", + "base64 0.21.2", + "bytes", + "enr", + "ethers-core", + "futures-channel", + "futures-core", + "futures-timer", + "futures-util", + "hashers", + "hex", + "http", + "instant", + "once_cell", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-tungstenite", + "tracing", + "tracing-futures", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "ws_stream_wasm", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "bitvec", + "byteorder", + "ff_derive", + "rand_core", + "subtle", +] + +[[package]] +name = "ff_derive" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f54704be45ed286151c5e11531316eaef5b8f5af7d597b806fdb8af108d84a" +dependencies = [ + "addchain", + "cfg-if", + "num-bigint 0.3.3", + "num-integer", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +dependencies = [ + "fallible-iterator", + "indexmap 1.9.3", + "stable_deref_trait", +] + +[[package]] +name = "glob" +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 = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "hashers" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" +dependencies = [ + "fxhash", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "inventory" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b1d6b4b9fb75fc419bdef998b689df5080a32931cb3395b86202046b56a9ea" + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "ipnet" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix 0.38.4", + "windows-sys", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.1" +source = "git+https://github.com/risc0/RustCrypto-elliptic-curves?tag=k256/v0.13.1-risc0#44b1fc2b317e76bb150636cf67d0fbdfcac39601" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy-regex" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff63c423c68ea6814b7da9e88ce585f793c87ddd9e78f646970891769c8235d4" +dependencies = [ + "lazy-regex-proc_macros", + "once_cell", + "regex", +] + +[[package]] +name = "lazy-regex-proc_macros" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8edfc11b8f56ce85e207e62ea21557cfa09bb24a8f6b04ae181b086ff8611c22" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "libm" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "matrixmultiply" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090126dc04f95dc0d1c1c91f61bdd474b3930ca064c1edc8a849da2c6cbe1e77" +dependencies = [ + "autocfg", + "rawpointer", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "ndarray" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits", + "rawpointer", + "rayon", +] + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint 0.4.3", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e6a0fd4f737c707bd9086cc16c925f294943eb62eb71499e9fd4cf71f8b9f4e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint 0.4.3", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "flate2", + "memchr", + "ruzstd", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.109", +] + +[[package]] +name = "openssl" +version = "0.10.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "parity-scale-codec" +version = "3.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756d439303e94fae44f288ba881ad29670c65b0c4b0e05674ca81061bb65f2c5" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d884d78fcf214d70b1e239fcd1c6e5e95aa3be1881918da2e488cc946c7a476" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "smallvec", + "windows-targets", +] + +[[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 = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", + "hmac", + "password-hash", + "sha2", +] + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pest" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "petgraph" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +dependencies = [ + "fixedbitset", + "indexmap 1.9.3", +] + +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version 0.4.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "predicates" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" +dependencies = [ + "anstyle", + "difflib", + "itertools", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + +[[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.109", +] + +[[package]] +name = "primitive-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +dependencies = [ + "bit-set", + "bitflags 1.3.2", + "byteorder", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax 0.6.29", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 1.0.109", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost", +] + +[[package]] +name = "protobuf-src" +version = "1.1.0+21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7ac8852baeb3cc6fb83b93646fb93c0ffe5d14bf138c945ceb4b9948ee0e3c1" +dependencies = [ + "autotools", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax 0.7.4", +] + +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.4", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + +[[package]] +name = "relative-path" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf2521270932c3c7bed1a59151222bd7643c79310f2916f01925e1e16255698" + +[[package]] +name = "reqwest" +version = "0.11.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +dependencies = [ + "base64 0.21.2", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.22.6", + "winreg", +] + +[[package]] +name = "revm" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f293f351c4c203d321744e54ed7eed3d2b6eef4c140228910dde3ac9a5ea8031" +dependencies = [ + "auto_impl", + "revm-interpreter", + "revm-precompile", + "serde", + "serde_json", +] + +[[package]] +name = "revm-interpreter" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a53980a26f9b5a66d13511c35074d4b53631e157850a1d7cf1af4efc2c2b72c9" +dependencies = [ + "derive_more", + "enumn", + "revm-primitives", + "serde", + "sha3", +] + +[[package]] +name = "revm-precompile" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41320af3bd6a65153d38eb1d3638ba89104cc9513c7feedb2d8510e8307dab29" +dependencies = [ + "k256", + "num", + "once_cell", + "revm-primitives", + "ripemd", + "sha2", + "sha3", + "substrate-bn", +] + +[[package]] +name = "revm-primitives" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304d998f466ffef72d76c7f20b05bf08a96801736a6fb1fdef47d49a292618df" +dependencies = [ + "auto_impl", + "bitvec", + "bytes", + "derive_more", + "enumn", + "fixed-hash", + "hashbrown 0.13.2", + "hex", + "hex-literal", + "primitive-types", + "rlp", + "ruint", + "serde", + "sha3", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "risc0-build" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "cargo_metadata", + "directories", + "downloader", + "risc0-zkvm", + "risc0-zkvm-platform", + "serde", + "serde_json", + "sha2", + "tempfile", + "zip", +] + +[[package]] +name = "risc0-build-kernel" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "cc", + "directories", + "glob", + "hex", + "sha2", + "tempfile", +] + +[[package]] +name = "risc0-circuit-rv32im" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "anyhow", + "log", + "rand", + "rayon", + "risc0-circuit-rv32im-sys", + "risc0-core", + "risc0-sys", + "risc0-zkp", + "risc0-zkvm-platform", + "tracing", +] + +[[package]] +name = "risc0-circuit-rv32im-sys" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "glob", + "risc0-build-kernel", + "risc0-core", + "risc0-sys", +] + +[[package]] +name = "risc0-core" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "bytemuck", + "rand_core", +] + +[[package]] +name = "risc0-sys" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "cc", + "glob", + "risc0-build-kernel", + "risc0-core", +] + +[[package]] +name = "risc0-zkp" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "anyhow", + "blake2", + "bytemuck", + "digest 0.10.7", + "ff", + "hex", + "lazy_static", + "log", + "ndarray", + "paste", + "rand", + "rand_core", + "rayon", + "risc0-core", + "risc0-sys", + "risc0-zkvm-platform", + "serde", + "sha2", + "thiserror", + "tracing", +] + +[[package]] +name = "risc0-zkvm" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "addr2line", + "anyhow", + "bincode", + "bonsai-sdk", + "bytemuck", + "cfg-if", + "crypto-bigint", + "dyn_partial_eq", + "elf", + "generic-array", + "getrandom", + "gimli", + "hex", + "lazy-regex", + "libm", + "log", + "num-derive", + "num-traits", + "prost", + "prost-build", + "protobuf-src", + "rand", + "rayon", + "risc0-circuit-rv32im", + "risc0-core", + "risc0-zkp", + "risc0-zkvm-platform", + "rrs-lib", + "serde", + "sha2", + "thiserror", + "tracing", + "typetag", +] + +[[package]] +name = "risc0-zkvm-platform" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rlp-derive", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rrs-lib" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4382d3af3a4ebdae7f64ba6edd9114fff92c89808004c4943b393377a25d001" +dependencies = [ + "downcast-rs", + "paste", +] + +[[package]] +name = "rstest" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b96577ca10cb3eade7b337eb46520108a67ca2818a24d0b63f41fd62bc9651c" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version 0.4.0", +] + +[[package]] +name = "rstest_macros" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225e674cf31712b8bb15fdbca3ec0c1b9d825c5a24407ff2b7e005fb6a29ba03" +dependencies = [ + "cfg-if", + "glob", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version 0.4.0", + "syn 2.0.26", + "unicode-ident", +] + +[[package]] +name = "ruint" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95294d6e3a6192f3aabf91c38f56505a625aa495533442744185a36d75a790c4" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint 0.4.3", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.18", +] + +[[package]] +name = "rustix" +version = "0.37.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys", +] + +[[package]] +name = "rustix" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys 0.4.3", + "windows-sys", +] + +[[package]] +name = "rustls" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.1", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +dependencies = [ + "base64 0.21.2", +] + +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ruzstd" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a15e661f0f9dac21f3494fe5d23a6338c0ac116a2d22c2b63010acd89467ffe" +dependencies = [ + "byteorder", + "thiserror", + "twox-hash", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "scale-info" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + +[[package]] +name = "serde" +version = "1.0.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "serde_json" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" +dependencies = [ + "indexmap 2.0.0", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e47d95bc83ed33b2ecf84f4187ad1ab9685d18ff28db000c99deac8ce180e3" +dependencies = [ + "base64 0.21.2", + "chrono", + "hex", + "indexmap 1.9.3", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea3cee93715c2e266b9338b7544da68a9f24e227722ba482bd1c024367c77c65" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2/v0.10.6-risc0#e75cafd9f55da196061f6fadf8bc8a86778192b7" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "smol_str" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6069ca09d878a33f883cc06aaa9718ede171841d3832450354410b718b097232" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.26", +] + +[[package]] +name = "substrate-bn" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +dependencies = [ + "byteorder", + "crunchy", + "lazy_static", + "rand", + "rustc-hex", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +dependencies = [ + "autocfg", + "cfg-if", + "fastrand", + "redox_syscall 0.3.5", + "rustix 0.37.23", + "windows-sys", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + +[[package]] +name = "thiserror" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "time" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +dependencies = [ + "autocfg", + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c" +dependencies = [ + "futures-util", + "log", + "rustls", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots 0.23.1", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "tungstenite" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand", + "rustls", + "sha1", + "thiserror", + "url", + "utf-8", + "webpki", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "typetag" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66aafcfb982bf1f9a28755ac6bcbdcd4631ff516cb038fa61299201ebb4364" +dependencies = [ + "erased-serde", + "inventory", + "once_cell", + "serde", + "typetag-impl", +] + +[[package]] +name = "typetag-impl" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d836cd032f71d90cbaa3c1f85ce84266af23659766d8c0b1c4c6524a0fb4c36f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.26", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + +[[package]] +name = "webpki-roots" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +dependencies = [ + "rustls-webpki 0.100.1", +] + +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[package]] +name = "ws_stream_wasm" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +dependencies = [ + "async_io_stream", + "futures", + "js-sys", + "log", + "pharos", + "rustc_version 0.4.0", + "send_wrapper 0.6.0", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "zeth" +version = "0.1.0" +dependencies = [ + "anyhow", + "assert_cmd", + "bincode", + "bonsai-sdk", + "bytemuck", + "clap", + "env_logger", + "ethers-core", + "hashbrown 0.13.2", + "hex", + "log", + "revm", + "risc0-zkvm", + "rstest", + "serde", + "tempfile", + "tokio", + "zeth-primitives", + "zeth_guests", + "zeth_lib", +] + +[[package]] +name = "zeth-primitives" +version = "0.1.0" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-rlp-derive", + "anyhow", + "bincode", + "bytes", + "ethers-core", + "hex-literal", + "k256", + "log", + "rand", + "revm-primitives", + "rlp", + "serde", + "serde_json", + "sha2", + "sha3", +] + +[[package]] +name = "zeth_guests" +version = "0.1.0" +dependencies = [ + "risc0-build", +] + +[[package]] +name = "zeth_lib" +version = "0.1.0" +dependencies = [ + "anyhow", + "bincode", + "chrono", + "env_logger", + "ethers-core", + "ethers-providers", + "flate2", + "hashbrown 0.13.2", + "hex-literal", + "log", + "once_cell", + "phf", + "revm", + "rstest", + "ruint", + "serde", + "serde_json", + "serde_with", + "thiserror", + "tokio", + "zeth-primitives", +] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.8+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +dependencies = [ + "cc", + "libc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..792607948 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,32 @@ +[workspace] +members = [ + "guests", + "host", + "lib", + "primitives", +] + +# Always optimize; building and running the guest takes much longer without optimization. +[profile.dev] +opt-level = 3 + +[profile.dev.build-override] +opt-level = 3 + +[profile.release] +debug = 1 +lto = true + +[profile.release.build-override] +opt-level = 3 + +[patch.crates-io] +# use optimized risc0 circuit +crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.2-risc0" } +k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.1-risc0" } +sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2/v0.10.6-risc0" } + +[workspace.dependencies] +bonsai-sdk = { git = "https://github.com/risc0/risc0.git", branch = "release-0.16" } +risc0-build = { git = "https://github.com/risc0/risc0.git", branch = "release-0.16" } +risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-0.16", default-features = false } diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 000000000..986e035df --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# zeth + +## git-lfs + +To facilitate testing, this repository includes cached RPC data. These data are tracked using [git-lfs](https://git-lfs.com/). To use these files: + +1. Install `git-lfs`. +2. Pull the cache files using `git lfs pull`. + +This will fetch the cached RPC data and store the results in the `host/testdata` directory. + +## Building + +```console +$ cargo build --release +``` + +## Running + +The `zeth` tool requires an Eth data provider. Three different providers are supported: + +* File provider. Specified by giving `--cache-path FILENAME`. +* RPC provider. Specified by giving `--rpc-url RPC_URL`. +* Cached RPC provider. Specified by giving both `--cache-path FILENAME` and `--rpc-url RPC_URL`. + +Example (replace `YOUR_API_KEY` with your API key for Alchemy): + +```console +$ RUST_LOG=info ./target/release/zeth \ + --cache-path host/testdata \ + --block-no 16424130 \ + --rpc-url "https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY" +``` + +### Running in the zkVM executor + +Add the flag `--local-exec (segment limit)`. + +### Running on Bonsai + +First, set the following environment variables: + +* `BONSAI_API_URL` +* `BONSAI_API_KEY` + +For example, + +```console +$ export BONSAI_API_URL="bonsai_url" +$ export BONSAI_API_KEY="my_api_key" +``` + +To submit a proving job to Bonsai, add the flag `--bonsai-submit`. This will submit the job to Bonsai, print the session UUID to console, and poll Bonsai until the job is complete. For example, + +```console +$ RUST_LOG=info ./target/release/zketh --cache-path host/testdata --block-no 17735424 --bonsai-submit +``` + +To check the status of a job that's already been submitted to Bonsai, add the flag `--bonsai-verify SESSION_UUID`, where `SESSION_UUID` is the UUID printed by the `--bonsai-submit` command. For example, + +```console +$ RUST_LOG=info ./target/release/zketh --cache-path host/testdata --block-no 17735424 --bonsai-verify f150e1c6-ca9f-4c8f-9dfb-e9e022315e5c +``` diff --git a/config.toml b/config.toml new file mode 100644 index 000000000..6f95e9cd9 --- /dev/null +++ b/config.toml @@ -0,0 +1,5 @@ +[patch.crates-io] +cc = { git = "https://github.com/rust-lang/cc-rs", tag = "1.0.79" } + +[env] +CARGO_WORKSPACE_DIR = { value = "", relative = true } diff --git a/guests/Cargo.toml b/guests/Cargo.toml new file mode 100644 index 000000000..d56d20c0c --- /dev/null +++ b/guests/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "zeth_guests" +version = "0.1.0" +edition = "2021" + +[build-dependencies] +risc0-build = { workspace = true } + +[package.metadata.risc0] +methods = ["eth-block"] diff --git a/guests/build.rs b/guests/build.rs new file mode 100644 index 000000000..42c6db8ec --- /dev/null +++ b/guests/build.rs @@ -0,0 +1,17 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +fn main() { + risc0_build::embed_methods(); +} diff --git a/guests/eth-block/Cargo.lock b/guests/eth-block/Cargo.lock new file mode 100644 index 000000000..8c6145237 --- /dev/null +++ b/guests/eth-block/Cargo.lock @@ -0,0 +1,3374 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[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]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloy-primitives" +version = "0.3.1" +source = "git+https://github.com/alloy-rs/core.git?rev=58e2259#58e2259a858f9a1ac7ebb0eb421dce5bb6305850" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "proptest", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f938f00332d63a5b0ac687bd6f46d03884638948921d9f8b50c59563d421ae25" +dependencies = [ + "arrayvec", + "bytes", + "smol_str", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa5bb468bc7c46e0c5074d418f575262ff79451242e5ac1380121ed4e23c4fd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.0", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "async-trait" +version = "0.1.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "async_io_stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +dependencies = [ + "futures", + "pharos", + "rustc_version 0.4.0", +] + +[[package]] +name = "auto_impl" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "serde", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "git+https://github.com/rust-lang/cc-rs?tag=1.0.79#e5bbdfa1fa468c028cb38fee6c35a3cf2e5a2736" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "winapi", +] + +[[package]] +name = "const-hex" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "268f52aae268980d03dd9544c1ea591965b2735b038d6998d6e4ab37c8c24445" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.2" +source = "git+https://github.com/risc0/RustCrypto-crypto-bigint?tag=v0.5.2-risc0#8b30304277cfe553b51a78a0e693f48bbb059eb3" +dependencies = [ + "generic-array", + "getrandom", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.25", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + +[[package]] +name = "der" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn_partial_eq" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07039d197226c4b9a3810c4f165328fb4e715258a4b8584f143d38e9de04301" +dependencies = [ + "dyn_partial_eq_derive", +] + +[[package]] +name = "dyn_partial_eq_derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e217c6c1435ebf9b88662354589d339192b8eaf506edd22951e75e045c8e8bd" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ecdsa" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "elliptic-curve" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf56acd72bb22d2824e66ae8e9e5ada4d0de17a69c7fd35569dde2ada8ec9116" +dependencies = [ + "base64 0.13.1", + "bytes", + "hex", + "k256", + "log", + "rand", + "rlp", + "serde", + "sha3", + "zeroize", +] + +[[package]] +name = "enumn" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9838a970f5de399d3070ae1739e131986b2f5dcc223c7423ca0927e3a878522" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "erased-serde" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f94c0e13118e7d7533271f754a168ae8400e6a1cc043f2bfd53cc7290f1a1de3" +dependencies = [ + "serde", +] + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "eth-block" +version = "0.1.0" +dependencies = [ + "k256", + "risc0-zkvm", + "zeth_lib", +] + +[[package]] +name = "ethabi" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "scale-info", + "uint", +] + +[[package]] +name = "ethers-core" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6da5fa198af0d3be20c19192df2bd9590b92ce09a8421e793bec8851270f1b05" +dependencies = [ + "arrayvec", + "bytes", + "chrono", + "elliptic-curve", + "ethabi", + "generic-array", + "hex", + "k256", + "num_enum", + "open-fastrlp", + "rand", + "rlp", + "serde", + "serde_json", + "strum", + "tempfile", + "thiserror", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "ethers-providers" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56b498fd2a6c019d023e43e83488cd1fb0721f299055975aa6bac8dbf1e95f2c" +dependencies = [ + "async-trait", + "auto_impl", + "base64 0.21.2", + "bytes", + "enr", + "ethers-core", + "futures-channel", + "futures-core", + "futures-timer", + "futures-util", + "hashers", + "hex", + "http", + "instant", + "once_cell", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-tungstenite", + "tracing", + "tracing-futures", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "ws_stream_wasm", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "flate2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + +[[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 = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "hashers" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" +dependencies = [ + "fxhash", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "inventory" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c38a87a1e0e2752433cd4b26019a469112a25fb43b30f5ee9b3b898925c5a0f9" + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "ipnet" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.1" +source = "git+https://github.com/risc0/RustCrypto-elliptic-curves?tag=k256/v0.13.1-risc0#44b1fc2b317e76bb150636cf67d0fbdfcac39601" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "libm" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e6a0fd4f737c707bd9086cc16c925f294943eb62eb71499e9fd4cf71f8b9f4e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.109", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756d439303e94fae44f288ba881ad29670c65b0c4b0e05674ca81061bb65f2c5" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d884d78fcf214d70b1e239fcd1c6e5e95aa3be1881918da2e488cc946c7a476" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pest" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version 0.4.0", +] + +[[package]] +name = "pin-project" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "primitive-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +dependencies = [ + "bit-set", + "bitflags", + "byteorder", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax 0.6.29", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.1" +source = "git+https://github.com/ferrilab/radium.git?rev=723bed5#723bed5abd75994ee4b7221b8b12c9f4e77ce408" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax 0.7.4", +] + +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.4", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + +[[package]] +name = "reqwest" +version = "0.11.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +dependencies = [ + "base64 0.21.2", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.22.6", + "winreg", +] + +[[package]] +name = "revm" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f293f351c4c203d321744e54ed7eed3d2b6eef4c140228910dde3ac9a5ea8031" +dependencies = [ + "auto_impl", + "revm-interpreter", + "revm-precompile", + "serde", + "serde_json", +] + +[[package]] +name = "revm-interpreter" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a53980a26f9b5a66d13511c35074d4b53631e157850a1d7cf1af4efc2c2b72c9" +dependencies = [ + "derive_more", + "enumn", + "revm-primitives", + "serde", + "sha3", +] + +[[package]] +name = "revm-precompile" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41320af3bd6a65153d38eb1d3638ba89104cc9513c7feedb2d8510e8307dab29" +dependencies = [ + "k256", + "num", + "once_cell", + "revm-primitives", + "ripemd", + "sha2", + "sha3", + "substrate-bn", +] + +[[package]] +name = "revm-primitives" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304d998f466ffef72d76c7f20b05bf08a96801736a6fb1fdef47d49a292618df" +dependencies = [ + "auto_impl", + "bitvec", + "bytes", + "derive_more", + "enumn", + "fixed-hash", + "hashbrown 0.13.2", + "hex", + "hex-literal", + "primitive-types", + "rlp", + "ruint", + "serde", + "sha3", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "risc0-circuit-rv32im" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "anyhow", + "log", + "risc0-core", + "risc0-zkp", + "risc0-zkvm-platform", + "tracing", +] + +[[package]] +name = "risc0-core" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "bytemuck", + "rand_core", +] + +[[package]] +name = "risc0-zkp" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "anyhow", + "blake2", + "bytemuck", + "digest 0.10.7", + "hex", + "log", + "paste", + "rand_core", + "risc0-core", + "risc0-zkvm-platform", + "serde", + "sha2", + "thiserror", + "tracing", +] + +[[package]] +name = "risc0-zkvm" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" +dependencies = [ + "anyhow", + "bytemuck", + "cfg-if", + "dyn_partial_eq", + "getrandom", + "hex", + "libm", + "log", + "num-derive", + "num-traits", + "risc0-circuit-rv32im", + "risc0-core", + "risc0-zkp", + "risc0-zkvm-platform", + "serde", + "thiserror", + "tracing", + "typetag", +] + +[[package]] +name = "risc0-zkvm-platform" +version = "0.16.1" +source = "git+https://github.com/risc0/risc0.git?branch=release-0.16#0d02111b2f84a53cf6198a0064086b281ed0f749" + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rlp-derive", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ruint" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95294d6e3a6192f3aabf91c38f56505a625aa495533442744185a36d75a790c4" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.17", +] + +[[package]] +name = "rustix" +version = "0.37.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustls" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.1", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +dependencies = [ + "base64 0.21.2", +] + +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc31bd9b61a32c31f9650d18add92aa83a49ba979c143eefd27fe7177b05bd5f" + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" + +[[package]] +name = "scale-info" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + +[[package]] +name = "serde" +version = "1.0.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "serde_json" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" +dependencies = [ + "indexmap 2.0.0", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02d8aa6e3c385bf084924f660ce2a3a6bd333ba55b35e8590b321f35d88513" +dependencies = [ + "base64 0.21.2", + "chrono", + "hex", + "indexmap 1.9.3", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc7d5d3932fb12ce722ee5e64dd38c504efba37567f0c402f6ca728c3b8b070" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2/v0.10.6-risc0#e75cafd9f55da196061f6fadf8bc8a86778192b7" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "smol_str" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "substrate-bn" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +dependencies = [ + "byteorder", + "crunchy", + "lazy_static", + "rand", + "rustc-hex", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +dependencies = [ + "autocfg", + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + +[[package]] +name = "thiserror" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "time" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +dependencies = [ + "autocfg", + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c" +dependencies = [ + "futures-util", + "log", + "rustls", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots 0.23.1", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "tungstenite" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand", + "rustls", + "sha1", + "thiserror", + "url", + "utf-8", + "webpki", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "typetag" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66aafcfb982bf1f9a28755ac6bcbdcd4631ff516cb038fa61299201ebb4364" +dependencies = [ + "erased-serde", + "inventory", + "once_cell", + "serde", + "typetag-impl", +] + +[[package]] +name = "typetag-impl" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d836cd032f71d90cbaa3c1f85ce84266af23659766d8c0b1c4c6524a0fb4c36f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.25", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + +[[package]] +name = "webpki-roots" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +dependencies = [ + "rustls-webpki 0.100.1", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[package]] +name = "ws_stream_wasm" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +dependencies = [ + "async_io_stream", + "futures", + "js-sys", + "log", + "pharos", + "rustc_version 0.4.0", + "send_wrapper 0.6.0", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "zeth-primitives" +version = "0.1.0" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-rlp-derive", + "anyhow", + "bytes", + "ethers-core", + "k256", + "log", + "revm-primitives", + "rlp", + "serde", + "sha2", + "sha3", +] + +[[package]] +name = "zeth_lib" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "ethers-core", + "ethers-providers", + "flate2", + "hashbrown 0.13.2", + "hex-literal", + "log", + "once_cell", + "revm", + "ruint", + "serde", + "serde_json", + "serde_with", + "thiserror", + "tokio", + "zeth-primitives", +] diff --git a/guests/eth-block/Cargo.toml b/guests/eth-block/Cargo.toml new file mode 100644 index 000000000..3cb2f3550 --- /dev/null +++ b/guests/eth-block/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "eth-block" +version = "0.1.0" +edition = "2021" + +[workspace] + +[dependencies] +k256 = { version = "=0.13.1", features = ["std", "ecdsa"], default_features = false } +risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-0.16", default-features = false, features = ['std'] } +zeth_lib = { path = "../../lib", default-features = false } + +[patch.crates-io] +radium = { git = 'https://github.com/ferrilab/radium.git', rev = "723bed5" } +# use optimized risc0 circuit +crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.2-risc0" } +k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.1-risc0" } +sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2/v0.10.6-risc0" } diff --git a/guests/eth-block/src/main.rs b/guests/eth-block/src/main.rs new file mode 100644 index 000000000..71453bf5e --- /dev/null +++ b/guests/eth-block/src/main.rs @@ -0,0 +1,39 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![no_main] + +use risc0_zkvm::guest::env; +use zeth_lib::{block_builder::BlockBuilder, validation::Input}; + +risc0_zkvm::guest::entry!(main); + +pub fn main() { + let input: Input = env::read(); + + let result = BlockBuilder::from(input) + .initialize_evm_storage() + .expect("Failed to create in-memory evm storage") + .initialize_header() + .expect("Failed to create the initial block header fields") + .execute_transactions() + .expect("Failed to execute transactions") + .build(None) + .expect("Failed to build the resulting block"); + + env::commit(&result.hash()); + + // Leak memory, save cycles + core::mem::forget(result); +} diff --git a/guests/src/lib.rs b/guests/src/lib.rs new file mode 100644 index 000000000..0c7a9dd66 --- /dev/null +++ b/guests/src/lib.rs @@ -0,0 +1,15 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +include!(concat!(env!("OUT_DIR"), "/methods.rs")); diff --git a/host/Cargo.toml b/host/Cargo.toml new file mode 100644 index 000000000..5e07ff2af --- /dev/null +++ b/host/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "zeth" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0" +bincode = "1.3.3" +bonsai-sdk = { workspace = true } +bytemuck = "1.13" +clap = { version = "4.0", features = ["derive"] } +env_logger = "0.10" +ethers-core = "2.0" +hashbrown = "0.13" +hex = "0.4.3" +log = "0.4" +revm = { version = "3.0", default-features = false, features = ["std", "serde"] } +risc0-zkvm = { workspace = true, features = ["prove"] } +serde = "1.0" +tempfile = "3.6" +tokio = { version = "1.23", features = ["full"] } +zeth-primitives = { path = "../primitives" } +zeth_guests = { path = "../guests" } +zeth_lib = { path = "../lib" } + +[dev-dependencies] +assert_cmd = "2.0" +rstest = "0.18" + +[features] +profiler = ["risc0-zkvm/profiler"] diff --git a/host/src/main.rs b/host/src/main.rs new file mode 100644 index 000000000..ec144f0f5 --- /dev/null +++ b/host/src/main.rs @@ -0,0 +1,324 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +extern crate core; + +use std::time::Instant; + +use anyhow::{bail, Result}; +use bonsai_sdk::alpha as bonsai_sdk; +use clap::Parser; +use log::{error, info}; +use risc0_zkvm::{ + serde::{from_slice, to_vec}, + ExecutorEnv, FileSegmentRef, LocalExecutor, MemoryImage, Program, SessionReceipt, +}; +use tempfile::tempdir; +use zeth_guests::{ETH_BLOCK_ELF, ETH_BLOCK_ID}; +use zeth_lib::{block_builder::BlockBuilder, validation::Input}; +use zeth_primitives::BlockHash; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + #[clap(short, long)] + rpc_url: Option, + + #[clap(short, long)] + cache_path: Option, + + #[clap(short, long)] + block_no: u64, + + #[clap(short, long, default_value_t = 0)] + local_exec: u32, + + #[clap(long, default_value_t = false)] + bonsai_submit: bool, + + #[clap(long)] + bonsai_verify: Option, +} + +fn cache_file_path(cache_path: &String, block_no: u64, ext: &str) -> String { + format!("{}/{}.{}", cache_path, block_no, ext) +} + +#[tokio::main] +async fn main() -> Result<()> { + env_logger::init(); + let args = Args::parse(); + + // Fetch all of the initial data + let rpc_cache = args + .cache_path + .as_ref() + .map(|dir| cache_file_path(dir, args.block_no, "json.gz")); + + let init = tokio::task::spawn_blocking(move || { + zeth_lib::host::get_initial_data(rpc_cache, args.rpc_url, args.block_no) + .expect("Could not init") + }) + .await?; + + let input: Input = init.clone().into(); + + // Verify that the transactions run correctly + { + let input: Input = from_slice(&to_vec(&input).expect("Input serialization failed")) + .expect("Input deserialization failed"); + + info!("Running from memory ..."); + + let block_builder = BlockBuilder::from(input) + .initialize_evm_storage() + .expect("Error initializing MemDb from Input") + .initialize_header() + .expect("Error creating initial block header") + .execute_transactions() + .expect("Error while running transactions"); + + let fini_db = block_builder.clone().to_db(); + let accounts_len = fini_db.accounts_len(); + + let mut storage_deltas = Default::default(); + let validated_header = block_builder + .build(Some(&mut storage_deltas)) + .expect("Error while verifying final state"); + + info!( + "Memory-backed execution is Done! Database contains {} accounts", + accounts_len + ); + + // Verify final state + info!("Verifying final state using provider data ..."); + let errors = zeth_lib::host::verify_state(fini_db, init.fini_proofs, storage_deltas) + .expect("Could not verify final state!"); + for (address, address_errors) in &errors { + info!( + "Verify found {:?} error(s) for address {:?}", + address_errors.len(), + address + ); + for error in address_errors { + match error { + zeth_lib::host::VerifyError::BalanceMismatch { + rpc_value, + our_value, + difference, + } => error!( + " Error: BalanceMismatch: rpc_value={} our_value={} difference={}", + rpc_value, our_value, difference + ), + _ => error!(" Error: {:?}", error), + } + } + } + + let errors_len = errors.len(); + if errors_len > 0 { + error!( + "Verify found {:?} account(s) with error(s) ({}% correct)", + errors_len, + (100.0 * (accounts_len - errors_len) as f64 / accounts_len as f64) + ); + } + + let found_hash = validated_header.hash(); + let expected_hash = init.fini_block.hash(); + if found_hash.as_slice() != expected_hash.as_slice() { + error!( + "Final block hash mismatch {} (expected {})", + found_hash, expected_hash, + ); + + bail!("Invalid block hash"); + } + + info!("Final block hash derived successfully. {}", found_hash) + } + + // Run in the executor (if requested) + if args.local_exec > 0 { + let segment_limit_po2 = args.local_exec as usize; + + info!( + "Running in executor with segment_limit_po2 = {:?}", + segment_limit_po2 + ); + + let input = to_vec(&input).expect("Could not serialize input!"); + info!( + "Input size: {} words ( {} MB )", + input.len(), + input.len() * 4 / 1_000_000 + ); + + #[cfg(feature = "profiler")] + let mut profiler = + risc0_zkvm::Profiler::new(zeth_guests::ETH_BLOCK_PATH, ETH_BLOCK_ELF).unwrap(); + + info!("Running the executor..."); + let start_time = Instant::now(); + let session = { + let mut builder = ExecutorEnv::builder(); + builder + .session_limit(None) + .segment_limit_po2(segment_limit_po2) + .add_input(&input); + + #[cfg(feature = "profiler")] + builder.trace_callback(profiler.make_trace_callback()); + + let env = builder.build().unwrap(); + let mut exec = LocalExecutor::from_elf(env, ETH_BLOCK_ELF).unwrap(); + + let segment_dir = tempdir().unwrap(); + + exec.run_with_callback(|segment| { + Ok(Box::new(FileSegmentRef::new(&segment, segment_dir.path())?)) + }) + .unwrap() + }; + info!( + "Generated {:?} segments; elapsed time: {:?}", + session.segments.len(), + start_time.elapsed() + ); + + #[cfg(feature = "profiler")] + { + profiler.finalize(); + + let sys_time = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap(); + std::fs::write( + format!("profile_{}.pb", sys_time.as_secs()), + &profiler.encode_to_vec(), + ) + .expect("Failed to write profiling output"); + } + + info!( + "Executor ran in (roughly) {} cycles", + session.segments.len() * (1 << segment_limit_po2) + ); + + let expected_hash = init.fini_block.hash(); + let found_hash: BlockHash = from_slice(&session.journal).unwrap(); + + if found_hash == expected_hash { + info!("Block hash (from executor): {}", found_hash); + } else { + error!( + "Final block hash mismatch (from executor) {} (expected {})", + found_hash, expected_hash, + ); + } + } + + let mut bonsai_session_uuid = args.bonsai_verify; + + // Run in Bonsai (if requested) + if bonsai_session_uuid.is_none() && args.bonsai_submit { + info!("Creating Bonsai client"); + let client = bonsai_sdk::Client::from_env().expect("Could not create Bonsai client"); + + // create the memoryImg, upload it and return the imageId + info!("Uploading memory image"); + let img_id = { + let program = Program::load_elf(ETH_BLOCK_ELF, risc0_zkvm::MEM_SIZE as u32) + .expect("Could not load ELF"); + let image = MemoryImage::new(&program, risc0_zkvm::PAGE_SIZE as u32) + .expect("Could not create memory image"); + let image_id = hex::encode(image.compute_id()); + let image = bincode::serialize(&image).expect("Failed to serialize memory img"); + + match client.upload_img(&image_id, image) { + Ok(_) => (), + Err(bonsai_sdk::SdkErr::ImageIdExists) => (), + Err(err) => panic!("Could not upload ELF: {}", err), + }; + image_id + }; + + // Prepare input data and upload it. + info!("Uploading inputs"); + let input_data = to_vec(&input).unwrap(); + let input_data = bytemuck::cast_slice(&input_data).to_vec(); + let input_id = client + .upload_input(input_data) + .expect("Could not upload inputs"); + + // Start a session running the prover + info!("Starting session"); + let session = client + .create_session(img_id, input_id) + .expect("Could not create Bonsai session"); + + println!("Bonsai session UUID: {}", session.uuid); + bonsai_session_uuid = Some(session.uuid) + } + + // Verify receipt from Bonsai (if requested) + if let Some(session_uuid) = bonsai_session_uuid { + let client = bonsai_sdk::Client::from_env().expect("Could not create Bonsai client"); + let session = bonsai_sdk::SessionId { uuid: session_uuid }; + + loop { + let res = session + .status(&client) + .expect("Could not fetch Bonsai status"); + if res.status == "RUNNING" { + std::thread::sleep(std::time::Duration::from_secs(15)); + continue; + } + if res.status == "SUCCEEDED" { + // Download the receipt, containing the output + let receipt_url = res + .receipt_url + .expect("API error, missing receipt on completed session"); + + let receipt_buf = client + .download(&receipt_url) + .expect("Could not download receipt"); + let receipt: SessionReceipt = + bincode::deserialize(&receipt_buf).expect("Could not deserialize receipt"); + receipt + .verify(ETH_BLOCK_ID) + .expect("Receipt verification failed"); + + let expected_hash = init.fini_block.hash(); + let found_hash: BlockHash = from_slice(&receipt.journal).unwrap(); + + if found_hash == expected_hash { + info!("Block hash (from Bonsai): {}", found_hash); + } else { + error!( + "Final block hash mismatch (from Bonsai) {} (expected {})", + found_hash, expected_hash, + ); + } + } else { + panic!("Workflow exited: {}", res.status); + } + + break; + } + } + + Ok(()) +} diff --git a/host/testdata/.gitkeep b/host/testdata/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/host/tests/blocks.rs b/host/tests/blocks.rs new file mode 100644 index 000000000..0be0cfb8e --- /dev/null +++ b/host/tests/blocks.rs @@ -0,0 +1,38 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![feature(path_file_prefix)] + +use std::path::PathBuf; + +use assert_cmd::Command; +use rstest::rstest; + +#[rstest] +fn block_cli(#[files("testdata/*.json.gz")] mut path: PathBuf) { + let block_no = String::from(path.file_prefix().unwrap().to_str().unwrap()); + + path.pop(); + + let mut cmd = Command::cargo_bin("zeth").unwrap(); + let assert = cmd + .args(&[ + "--cache-path", + path.to_str().unwrap(), + "--block-no", + &block_no, + ]) + .assert(); + assert.success(); +} diff --git a/lib/Cargo.toml b/lib/Cargo.toml new file mode 100644 index 000000000..e6af101c1 --- /dev/null +++ b/lib/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "zeth_lib" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0" +hashbrown = "0.13" +hex-literal = "0.4" +once_cell = "1.18" +revm = { version = "3.3", default-features = false, features = ["std", "serde"] } +ruint = { version = "1.10", default-features = false } +serde = "1.0" +thiserror = "1.0" +zeth-primitives = { path = "../primitives", features = ["revm"] } + +[target.'cfg(not(target_os = "zkvm"))'.dependencies] +chrono = { version = "0.4", default-features = false } +ethers-core = "2.0" +ethers-providers = "2.0" +flate2 = "1.0.26" +log = "0.4" +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } +serde_with = "3.0" +tokio = { version = "1.23", features = ["full"] } +zeth-primitives = { path = "../primitives", features = ["revm", "ethers"] } + +[dev-dependencies] +bincode = "1.3" +env_logger = "0.10" +phf = { version = "0.11", features = ["macros"] } +rstest = "0.18" +serde_with = "3.1" diff --git a/lib/src/block_builder.rs b/lib/src/block_builder.rs new file mode 100644 index 000000000..9f49be2c3 --- /dev/null +++ b/lib/src/block_builder.rs @@ -0,0 +1,490 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::mem; + +use anyhow::{anyhow, bail, Context, Result}; +use hashbrown::{hash_map, HashMap}; +#[cfg(not(target_os = "zkvm"))] +use log::{debug, info}; +use revm::{ + primitives::{ + Account, AccountInfo, Address, BlockEnv, Bytecode, CfgEnv, ResultAndState, SpecId, + TransactTo, TxEnv, B160, B256, U256, + }, + EVM, +}; +use zeth_primitives::{ + block::Header, + keccak::{keccak, KECCAK_EMPTY}, + receipt::Receipt, + revm::{from_revm_b256, to_revm_b160, to_revm_b256}, + transaction::{Transaction, TransactionKind, TxEssence}, + trie::{MptNode, StateAccount}, + Bloom, Bytes, RlpBytes, +}; + +use crate::{ + consts::{self, GWEI_TO_WEI}, + guest_mem_forget, + mem_db::{AccountState, DbAccount, MemDb}, + validation::{ + compute_base_fee, compute_block_number, compute_spec_id, verify_extra_data, + verify_gas_limit, verify_parent_chain, verify_state_trie, verify_storage_trie, + verify_timestamp, Input, + }, +}; + +pub trait BlockBuilderDatabase: revm::Database + Sized { + /// Creates a new DB from the accounts and the block hashes. + fn load(accounts: HashMap, block_hashes: HashMap) -> Self; + /// Returns all non-deleted accounts with their storage entries. + fn accounts(&self) -> hash_map::Iter; + /// Increases the balance of `address` by `amount`. + fn increase_balance(&mut self, address: Address, amount: U256) -> Result<(), Self::Error>; + /// Updates the account of `address`. + fn update(&mut self, address: Address, account: Account); +} + +#[derive(Clone)] +pub struct BlockBuilder { + db: Option, + header: Option
, + input: Input, +} + +impl From for BlockBuilder { + fn from(input: Input) -> Self { + BlockBuilder { + db: None, + header: None, + input, + } + } +} + +impl BlockBuilder +where + D: BlockBuilderDatabase, + ::Error: std::fmt::Debug, +{ + pub fn new(db: Option, input: Input) -> Self { + BlockBuilder { + db, + header: None, + input, + } + } + + pub fn to_db(self) -> D { + self.db.unwrap() + } + + pub fn initialize_evm_storage(mut self) -> Result { + verify_state_trie( + &self.input.parent_state_trie, + &self.input.parent_header.state_root, + )?; + + // hash all the contract code + let contracts: HashMap = mem::take(&mut self.input.contracts) + .into_iter() + .map(|bytes| (keccak(&bytes).into(), bytes)) + .collect(); + + // Load account data into db + let mut accounts = HashMap::with_capacity(self.input.parent_storage.len()); + for (address, (storage_trie, slots)) in &mut self.input.parent_storage { + // consume the slots, as they are no longer needed afterwards + let slots = mem::take(slots); + + // load the account from the state trie or empty if it does not exist + let state_account = self + .input + .parent_state_trie + .rlp_lookup::(&keccak(address))? + .unwrap_or_default(); + verify_storage_trie(address, storage_trie, &state_account.storage_root)?; + + // load the corresponding code + let code_hash = to_revm_b256(state_account.code_hash); + let bytecode = if code_hash.0 == KECCAK_EMPTY.0 { + Bytecode::new() + } else { + let bytes = contracts.get(&code_hash).unwrap().clone(); + unsafe { Bytecode::new_raw_with_hash(bytes.0, code_hash) } + }; + + // load storage reads + let mut storage = HashMap::with_capacity(slots.len()); + for slot in slots { + let value: zeth_primitives::U256 = storage_trie + .rlp_lookup(&keccak(slot.to_be_bytes::<32>()))? + .unwrap_or_default(); + storage.insert(slot, value); + } + + let mem_account = DbAccount { + info: AccountInfo { + balance: state_account.balance, + nonce: state_account.nonce, + code_hash: to_revm_b256(state_account.code_hash), + code: Some(bytecode), + }, + state: AccountState::None, + storage, + }; + + accounts.insert(*address, mem_account); + } + guest_mem_forget(contracts); + + // prepare block hash history + let block_hashes = + verify_parent_chain(&self.input.parent_header, &self.input.ancestor_headers)?; + + // Store database + self.db = Some(D::load(accounts, block_hashes)); + + Ok(self) + } + + pub fn initialize_header(mut self) -> Result { + // Verify current block + verify_gas_limit(self.input.gas_limit, self.input.parent_header.gas_limit)?; + verify_timestamp(self.input.timestamp, self.input.parent_header.timestamp)?; + verify_extra_data(&self.input.extra_data)?; + // Initialize result header + self.header = Some(Header { + // Initialize fields that we can compute from the parent + parent_hash: self.input.parent_header.hash(), + number: compute_block_number(&self.input.parent_header)?, + base_fee_per_gas: compute_base_fee(&self.input.parent_header)?, + // Initialize metadata from input + beneficiary: self.input.beneficiary, + gas_limit: self.input.gas_limit, + timestamp: self.input.timestamp, + mix_hash: self.input.mix_hash, + extra_data: self.input.extra_data.clone(), + // do not fill the remaining fields + ..Default::default() + }); + Ok(self) + } + + pub fn execute_transactions(mut self) -> Result { + let header = self.header.as_mut().expect("Header is not initialized"); + let spec_id = compute_spec_id(&self.input.chain_spec, header.number)?; + + #[cfg(not(target_os = "zkvm"))] + { + use chrono::{TimeZone, Utc}; + let dt = Utc + .timestamp_opt(self.input.timestamp.try_into().unwrap(), 0) + .unwrap(); + + info!("Block no. {}", header.number); + info!(" EVM spec ID: {:?}", spec_id); + info!(" Timestamp: {}", dt); + info!(" Transactions: {}", self.input.transactions.len()); + info!(" Withdrawals: {}", self.input.withdrawals.len()); + info!(" Fee Recipient: {:?}", self.input.beneficiary); + info!(" Gas limit: {}", self.input.gas_limit); + info!(" Base fee per gas: {}", header.base_fee_per_gas); + info!(" Extra data: {:?}", self.input.extra_data); + } + + // initialize the EVM + let mut evm = EVM::new(); + + evm.env.cfg = CfgEnv { + chain_id: U256::from(self.input.chain_spec.chain_id()), + spec_id, + ..Default::default() + }; + evm.env.block = BlockEnv { + number: header.number.try_into().unwrap(), + coinbase: to_revm_b160(self.input.beneficiary), + timestamp: self.input.timestamp, + difficulty: U256::ZERO, + prevrandao: Some(to_revm_b256(self.input.mix_hash)), + basefee: header.base_fee_per_gas, + gas_limit: self.input.gas_limit, + }; + + evm.database(self.db.take().unwrap()); + + // bloom filter over all transaction logs + let mut logs_bloom = Bloom::default(); + // keep track of the gas used over all transactions + let mut cumulative_gas_used = consts::ZERO; + + // process all the transactions + let mut tx_trie = MptNode::default(); + let mut receipt_trie = MptNode::default(); + for (tx_no, tx) in self.input.transactions.iter().enumerate() { + // verify the transaction signature + let tx_from = tx + .recover_from() + .with_context(|| format!("Error recovering address for transaction {}", tx_no))?; + + #[cfg(not(target_os = "zkvm"))] + { + let tx_hash = tx.hash(); + debug!("Tx no. {} (hash: {})", tx_no, tx_hash); + debug!(" Type: {}", tx.tx_type()); + debug!(" Fr: {:?}", tx_from); + debug!(" To: {:?}", tx.to().unwrap_or_default()); + } + + // verify transaction gas + let block_available_gas = self.input.gas_limit - cumulative_gas_used; + if block_available_gas < tx.gas_limit() { + bail!("Error at transaction {}: gas exceeds block limit", tx_no); + } + + // process the transaction + let tx_from = to_revm_b160(tx_from); + fill_tx_env(&mut evm.env.tx, tx, tx_from); + let ResultAndState { result, state } = evm + .transact() + .map_err(|evm_err| anyhow!("Error at transaction {}: {:?}", tx_no, evm_err))?; + + let gas_used = result.gas_used().try_into().unwrap(); + cumulative_gas_used = cumulative_gas_used.checked_add(gas_used).unwrap(); + + #[cfg(not(target_os = "zkvm"))] + debug!(" Ok: {:?}", result); + + // create the receipt from the EVM result + let receipt = Receipt::new( + tx.tx_type(), + result.is_success(), + cumulative_gas_used, + result.logs().into_iter().map(|log| log.into()).collect(), + ); + + // accumulate logs to the block bloom filter + logs_bloom.accrue_bloom(receipt.payload.logs_bloom); + + // Add receipt and tx to tries + let trie_key = tx_no.to_rlp(); + tx_trie.rlp_update(&trie_key, tx); + receipt_trie.rlp_update(&trie_key, receipt); + + // update account states + let db = evm.db().unwrap(); + for (address, account) in state { + #[cfg(not(target_os = "zkvm"))] + if account.is_touched { + // log account + debug!( + " State {:?} (storage_cleared={}, is_destroyed={}, is_not_existing={})", + address, + account.storage_cleared, + account.is_destroyed, + account.is_not_existing + ); + // log balance changes + debug!( + " After balance: {} (Nonce: {})", + account.info.balance, account.info.nonce + ); + + // log state changes + for (addr, slot) in &account.storage { + if slot.is_changed() { + debug!(" Storage address: {:?}", addr); + debug!(" Before: {:?}", slot.original_value); + debug!(" After: {:?}", slot.present_value); + } + } + } + + db.update(address, account); + } + } + + self.db = Some(evm.take_db()); + + // process withdrawals unconditionally after any transactions + let mut withdrawals_trie = MptNode::default(); + for (i, withdrawal) in self.input.withdrawals.iter().enumerate() { + // the withdrawal amount is given in Gwei + let amount_wei = GWEI_TO_WEI + .checked_mul(withdrawal.amount.try_into().unwrap()) + .unwrap(); + + #[cfg(not(target_os = "zkvm"))] + { + debug!("Withdrawal no. {}", withdrawal.index); + debug!(" Recipient: {:?}", withdrawal.address); + debug!(" Value: {}", amount_wei); + } + + self.db + .as_mut() + .unwrap() + .increase_balance(to_revm_b160(withdrawal.address), amount_wei) + .unwrap(); + + // add to trie + withdrawals_trie.rlp_update(&i.to_rlp(), withdrawal); + } + + // Update result header with computed values + header.transactions_root = tx_trie.hash(); + header.receipts_root = receipt_trie.hash(); + header.logs_bloom = logs_bloom; + header.gas_used = cumulative_gas_used; + header.withdrawals_root = if spec_id < SpecId::SHANGHAI { + None + } else { + Some(withdrawals_trie.hash()) + }; + + // Leak memory, save cycles + guest_mem_forget([tx_trie, receipt_trie, withdrawals_trie]); + + Ok(self) + } + + pub fn build( + mut self, + mut debug_storage_tries: Option<&mut HashMap>, + ) -> Result
{ + let db = self.db.as_ref().unwrap(); + + // apply state updates + let state_trie = &mut self.input.parent_state_trie; + for (address, account) in db.accounts() { + // if the account has not been touched, it can be ignored + if account.state == AccountState::None { + if let Some(map) = &mut debug_storage_tries { + let storage_root = self.input.parent_storage.get(address).unwrap().0.clone(); + map.insert(*address, storage_root); + } + continue; + } + + // compute the index of the current account in the state trie + let state_trie_index = keccak(address); + + // remove deleted accounts from the state trie + if account.state == AccountState::Deleted { + state_trie.delete(&state_trie_index); + continue; + } + + // otherwise, compute the updated storage root for that account + let state_storage = &account.storage; + let storage_root = { + // getting a mutable reference is more efficient than calling remove + // every account must have an entry, even newly created accounts + let (storage_trie, _) = self.input.parent_storage.get_mut(address).unwrap(); + // for cleared accounts always start from the empty trie + if account.state == AccountState::StorageCleared { + storage_trie.clear(); + } + + // apply all new storage entries for the current account (address) + for (key, value) in state_storage { + let storage_trie_index = keccak(key.to_be_bytes::<32>()); + if value == &U256::ZERO { + storage_trie.delete(&storage_trie_index); + } else { + storage_trie.rlp_update(&storage_trie_index, *value); + } + } + + // insert the storage trie for host debugging + if let Some(map) = &mut debug_storage_tries { + map.insert(*address, storage_trie.clone()); + } + + storage_trie.hash() + }; + + let state_account = StateAccount { + nonce: account.info.nonce, + balance: account.info.balance, + storage_root, + code_hash: from_revm_b256(account.info.code_hash), + }; + state_trie.rlp_update(&state_trie_index, state_account); + } + + // update result header with the new state root + let mut header = self.header.take().expect("Header was not initialized"); + header.state_root = state_trie.hash(); + + // Leak memory, save cycles + guest_mem_forget(self); + + Ok(header) + } +} + +fn fill_tx_env(tx_env: &mut TxEnv, tx: &Transaction, caller: Address) { + match &tx.essence { + TxEssence::Legacy(tx) => { + tx_env.caller = caller; + tx_env.gas_limit = tx.gas_limit.try_into().unwrap(); + tx_env.gas_price = tx.gas_price; + tx_env.gas_priority_fee = None; + tx_env.transact_to = if let TransactionKind::Call(to_addr) = tx.to { + TransactTo::Call(to_revm_b160(to_addr)) + } else { + TransactTo::create() + }; + tx_env.value = tx.value; + tx_env.data = tx.data.0.clone(); + tx_env.chain_id = tx.chain_id; + tx_env.nonce = Some(tx.nonce); + tx_env.access_list.clear(); + } + TxEssence::Eip2930(tx) => { + tx_env.caller = caller; + tx_env.gas_limit = tx.gas_limit.try_into().unwrap(); + tx_env.gas_price = tx.gas_price; + tx_env.gas_priority_fee = None; + tx_env.transact_to = if let TransactionKind::Call(to_addr) = tx.to { + TransactTo::Call(to_revm_b160(to_addr)) + } else { + TransactTo::create() + }; + tx_env.value = tx.value; + tx_env.data = tx.data.0.clone(); + tx_env.chain_id = Some(tx.chain_id); + tx_env.nonce = Some(tx.nonce); + tx_env.access_list = tx.access_list.clone().into(); + } + TxEssence::Eip1559(tx) => { + tx_env.caller = caller; + tx_env.gas_limit = tx.gas_limit.try_into().unwrap(); + tx_env.gas_price = tx.max_fee_per_gas; + tx_env.gas_priority_fee = Some(tx.max_priority_fee_per_gas); + tx_env.transact_to = if let TransactionKind::Call(to_addr) = tx.to { + TransactTo::Call(to_revm_b160(to_addr)) + } else { + TransactTo::create() + }; + tx_env.value = tx.value; + tx_env.data = tx.data.0.clone(); + tx_env.chain_id = Some(tx.chain_id); + tx_env.nonce = Some(tx.nonce); + tx_env.access_list = tx.access_list.clone().into(); + } + }; +} diff --git a/lib/src/consts.rs b/lib/src/consts.rs new file mode 100644 index 000000000..2e7b6df25 --- /dev/null +++ b/lib/src/consts.rs @@ -0,0 +1,125 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Constants for the Ethereum protocol. + +use std::collections::BTreeMap; + +use once_cell::sync::Lazy; +use revm::primitives::SpecId; +use serde::{Deserialize, Serialize}; +use zeth_primitives::{uint, BlockNumber, ChainId, U256}; + +/// U256 representation of 0. +pub const ZERO: U256 = U256::ZERO; +/// U256 representation of 1. +pub const ONE: U256 = uint!(1_U256); + +/// The bound divisor of the gas limit, +pub const GAS_LIMIT_BOUND_DIVISOR: U256 = uint!(1024_U256); +/// Minimum the gas limit may ever be. +pub const MIN_GAS_LIMIT: U256 = uint!(5000_U256); + +/// Maximum size of extra data. +pub const MAX_EXTRA_DATA_BYTES: usize = 32; + +/// Maximum allowed block number difference for the `block_hash` call. +pub const MAX_BLOCK_HASH_AGE: u64 = 256; + +/// Multiplier for converting gwei to wei. +pub const GWEI_TO_WEI: U256 = uint!(1_000_000_000_U256); + +/// [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) parameter. +pub const BASE_FEE_MAX_CHANGE_DENOMINATOR: U256 = uint!(8_U256); +/// [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) parameter. +pub const ELASTICITY_MULTIPLIER: U256 = uint!(2_U256); + +/// Minimum supported protocol version: Paris (Block no. 15537394). +pub const MIN_SPEC_ID: SpecId = SpecId::MERGE; + +/// The Ethereum mainnet specification. +pub static MAINNET: Lazy = Lazy::new(|| { + ChainSpec { + chain_id: 1, + hard_forks: BTreeMap::from([ + (SpecId::FRONTIER, ForkCondition::Block(0)), + // previous versions not supported + (SpecId::MERGE, ForkCondition::Block(15537394)), + (SpecId::SHANGHAI, ForkCondition::Block(17034870)), + (SpecId::CANCUN, ForkCondition::TBD), + ]), + } +}); + +/// The condition at which a fork is activated. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum ForkCondition { + /// The fork is activated with a certain block. + Block(BlockNumber), + /// The fork is not yet active. + TBD, +} + +impl ForkCondition { + /// Returns wether the condition has been met. + pub fn active(&self, block_number: BlockNumber) -> bool { + match self { + ForkCondition::Block(block) => *block <= block_number, + ForkCondition::TBD => false, + } + } +} + +/// Specification of a specific chain. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct ChainSpec { + chain_id: ChainId, + hard_forks: BTreeMap, +} + +impl ChainSpec { + /// Creates a new configuration consisting of only one specification ID. + pub fn new_single(chain_id: ChainId, spec_id: SpecId) -> Self { + ChainSpec { + chain_id, + hard_forks: BTreeMap::from([(spec_id, ForkCondition::Block(0))]), + } + } + /// Returns the network chain ID. + pub fn chain_id(&self) -> ChainId { + self.chain_id + } + /// Returns the revm specification ID for `block_number`. + pub fn spec_id(&self, block_number: BlockNumber) -> SpecId { + for (spec_id, fork) in self.hard_forks.iter().rev() { + if fork.active(block_number) { + return *spec_id; + } + } + unreachable!() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn revm_spec_id() { + assert!(MAINNET.spec_id(15537393) < SpecId::MERGE); + assert_eq!(MAINNET.spec_id(15537394), SpecId::MERGE); + assert_eq!(MAINNET.spec_id(17034869), SpecId::MERGE); + assert_eq!(MAINNET.spec_id(17034870), SpecId::SHANGHAI); + } +} diff --git a/lib/src/host/mod.rs b/lib/src/host/mod.rs new file mode 100644 index 000000000..ed9f64865 --- /dev/null +++ b/lib/src/host/mod.rs @@ -0,0 +1,480 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{ + collections::HashSet, + iter::{once, zip}, +}; + +use anyhow::{Context, Result}; +use ethers_core::types::{Bytes, EIP1186ProofResponse, H256}; +use hashbrown::HashMap; +use log::info; +use revm::{ + primitives::{Address, B160, B256, U256}, + Database, +}; +use zeth_primitives::{ + block::Header, + ethers::{from_ethers_h160, from_ethers_h256, from_ethers_u256}, + keccak::keccak, + revm::to_revm_b256, + transaction::Transaction, + trie::{MptNode, MptNodeData, MptNodeReference, EMPTY_ROOT}, + withdrawal::Withdrawal, +}; + +use crate::{ + block_builder::BlockBuilder, + consts::{ChainSpec, MAINNET}, + host::{ + mpt::{load_pointers, orphaned_pointers, resolve_pointers, shorten_key}, + provider::{new_provider, BlockQuery}, + }, + mem_db::MemDb, + validation::{Input, StorageEntry}, +}; + +pub mod mpt; +pub mod provider; +pub mod provider_db; + +#[derive(Clone)] +pub struct Init { + pub db: MemDb, + pub init_block: Header, + pub init_proofs: HashMap, + pub fini_block: Header, + pub fini_transactions: Vec, + pub fini_withdrawals: Vec, + pub fini_proofs: HashMap, + pub ancestor_headers: Vec
, + pub chain_spec: ChainSpec, +} + +pub fn get_initial_data( + cache_path: Option, + rpc_url: Option, + block_no: u64, +) -> Result { + let mut provider = new_provider(cache_path, rpc_url)?; + + // Fetch the initial block + let init_block = provider.get_partial_block(&BlockQuery { + block_no: block_no - 1, + })?; + + info!( + "Initial block: {:?} ({:?})", + init_block.number.unwrap(), + init_block.hash.unwrap() + ); + + // Fetch the finished block + let fini_block = provider.get_full_block(&BlockQuery { block_no })?; + + info!( + "Final block number: {:?} ({:?})", + fini_block.number.unwrap(), + fini_block.hash.unwrap() + ); + info!("Transaction count: {:?}", fini_block.transactions.len()); + + // Create the provider DB + let mut provider_db = + crate::host::provider_db::ProviderDb::new(provider, init_block.number.unwrap().as_u64()); + + // Create input + let input = Input { + beneficiary: fini_block.author.map(from_ethers_h160).unwrap_or_default(), + gas_limit: from_ethers_u256(fini_block.gas_limit), + timestamp: from_ethers_u256(fini_block.timestamp), + extra_data: fini_block.extra_data.0.clone().into(), + mix_hash: from_ethers_h256(fini_block.mix_hash.unwrap()), + transactions: fini_block + .transactions + .clone() + .into_iter() + .map(|tx| tx.try_into().unwrap()) + .collect(), + withdrawals: fini_block + .withdrawals + .clone() + .unwrap_or_default() + .into_iter() + .map(|w| w.try_into().unwrap()) + .collect(), + parent_header: init_block.clone().try_into()?, + chain_spec: MAINNET.clone(), + ..Default::default() + }; + + // Create the block builder, run the transactions and extract the DB + provider_db = BlockBuilder::new(Some(provider_db), input) + .initialize_header()? + .execute_transactions()? + .to_db(); + + info!("Gathering inclusion proofs ..."); + + // Gather inclusion proofs for the initial and final state + let init_proofs = provider_db.get_initial_proofs()?; + let fini_proofs = provider_db.get_latest_proofs()?; + + // Gather proofs for block history + let ancestor_headers = provider_db.get_ancestor_headers()?; + + info!("Saving provider cache ..."); + + // Save the provider cache + provider_db.get_provider().save()?; + + info!("Provider-backed execution is Done!"); + + let transactions = fini_block + .transactions + .clone() + .into_iter() + .map(|tx| tx.try_into().unwrap()) + .collect(); + let withdrawals = fini_block + .withdrawals + .clone() + .unwrap_or_default() + .into_iter() + .map(|w| w.try_into().unwrap()) + .collect(); + + Ok(Init { + db: provider_db.get_initial_db().clone(), + init_block: init_block.try_into()?, + init_proofs, + fini_block: fini_block.try_into()?, + fini_transactions: transactions, + fini_withdrawals: withdrawals, + fini_proofs, + ancestor_headers, + chain_spec: MAINNET.clone(), + }) +} + +#[derive(Debug)] +pub enum VerifyError { + BalanceMismatch { + rpc_value: U256, + our_value: U256, + difference: U256, + }, + NonceMismatch { + rpc_value: u64, + our_value: u64, + }, + CodeHashMismatch { + rpc_value: B256, + our_value: B256, + }, + StorageMismatch { + index: U256, + rpc_value: U256, + our_db_value: U256, + our_trie_value: U256, + }, + StorageRootMismatch { + address: Address, + rpc_value: B256, + our_value: B256, + first_delta: Option, + indices: usize, + }, +} + +pub fn verify_state( + mut fini_db: MemDb, + fini_proofs: HashMap, + mut storage_deltas: HashMap, +) -> Result>> { + let mut errors = HashMap::new(); + let fini_storage_keys = fini_db.storage_keys(); + + // Construct expected tries from fini proofs + let (mut nodes_by_pointer, mut storage) = + proofs_to_tries(fini_proofs.values().cloned().collect()); + storage_deltas.values().for_each(|storage_trie| { + load_pointers(storage_trie, &mut nodes_by_pointer); + }); + storage + .values_mut() + .for_each(|(n, _)| *n = resolve_pointers(n, &nodes_by_pointer)); + storage_deltas + .values_mut() + .for_each(|n| *n = resolve_pointers(n, &nodes_by_pointer)); + + for (address, indices) in fini_storage_keys { + let mut address_errors = Vec::new(); + + let account_proof = fini_proofs + .get(&address) + .with_context(|| format!("Proof not found: {}", address))?; + // for deleted accounts, use the default to compare + let account_info = fini_db.basic(address)?.unwrap_or_default(); + + // Account balance + { + let rpc_value: U256 = account_proof.balance.into(); + let our_value: U256 = account_info.balance; + if rpc_value != our_value { + let difference = rpc_value.abs_diff(our_value); + address_errors.push(VerifyError::BalanceMismatch { + rpc_value, + our_value, + difference, + }) + } + } + + // Nonce + { + let rpc_value: u64 = account_proof.nonce.as_u64(); + let our_value: u64 = account_info.nonce; + if rpc_value != our_value { + address_errors.push(VerifyError::NonceMismatch { + rpc_value, + our_value, + }) + } + } + + // Code hash + { + let rpc_value: B256 = account_proof.code_hash.into(); + let our_value: B256 = account_info.code_hash; + if rpc_value != our_value { + address_errors.push(VerifyError::CodeHashMismatch { + rpc_value, + our_value, + }) + } + } + + // Storage root + { + let storage_root_node = storage_deltas.get(&address).cloned().unwrap_or_default(); + let our_value = to_revm_b256(storage_root_node.hash()); + let rpc_value = account_proof.storage_hash.into(); + if rpc_value != our_value { + let expected = storage + .get(&address) + .unwrap() + .0 + .rlp_debug::(); + let found_pp = storage_root_node.rlp_debug::(); + let first_delta = zip(expected, found_pp) + .find(|(e, f)| e != f) + .map(|(e, f)| format!("Storage trie delta!\nEXPECTED:\t{}FOUND:\t{}", e, f)); + address_errors.push(VerifyError::StorageRootMismatch { + address, + rpc_value, + our_value, + first_delta, + indices: indices.len(), + }); + } + } + + // Storage + { + let storage_trie = storage_deltas.get(&address).cloned().unwrap_or_default(); + for index in indices { + let storage_index = H256::from(index.to_be_bytes()); + let rpc_value = account_proof + .storage_proof + .iter() + .find(|&storage| storage_index == storage.key) + .expect("Could not find storage proof") + .value + .into(); + let our_db_value = fini_db.storage(address, index)?; + let trie_index = keccak(storage_index.as_bytes()); + let our_trie_value = storage_trie + .rlp_lookup(&trie_index) + .unwrap_or_default() + .unwrap_or_default(); + if rpc_value != our_db_value || our_db_value != our_trie_value { + address_errors.push(VerifyError::StorageMismatch { + index, + rpc_value, + our_db_value, + our_trie_value, + }) + } + } + } + + if !address_errors.is_empty() { + errors.insert(address, address_errors); + } + } + + Ok(errors) +} + +fn proofs_to_tries( + proofs: Vec, +) -> ( + HashMap, + HashMap, +) { + // construct the proof tries + let mut nodes_by_pointer = HashMap::new(); + let mut storage = HashMap::new(); + for proof in proofs { + // parse the nodes of the account proof + for bytes in &proof.account_proof { + let mpt_node = MptNode::decode(bytes).expect("Failed to decode state proof"); + nodes_by_pointer.insert(mpt_node.pointer(), mpt_node); + } + + // process the proof for each storage entry + let mut root_node = None; + for storage_proof in &proof.storage_proof { + // parse the nodes of the storage proof and return the root node + root_node = storage_proof + .proof + .iter() + .rev() + .map(|bytes| MptNode::decode(bytes).expect("Failed to decode storage proof")) + .inspect(|node| drop(nodes_by_pointer.insert(node.pointer(), node.clone()))) + .last(); + // the hash of the root node should match the proof's storage hash + assert_eq!( + root_node.as_ref().map_or(EMPTY_ROOT, |n| n.hash()), + from_ethers_h256(proof.storage_hash) + ); + } + + let root_node = if let Some(root_node) = root_node { + root_node + } else if proof.storage_hash.0 == EMPTY_ROOT.0 { + MptNode::default() + } else { + // if there are no storage proofs but the root is non-empty, create a dummy + // as this is just the digest any tries to update this trie will fail + MptNodeData::Digest(from_ethers_h256(proof.storage_hash)).into() + }; + // collect all storage slots with a proof + let slots = proof + .storage_proof + .into_iter() + .map(|p| zeth_primitives::U256::from_be_bytes(p.key.into())) + .collect(); + + storage.insert(proof.address.into(), (root_node, slots)); + } + (nodes_by_pointer, storage) +} + +fn resolve_orphans( + nodes: &Vec, + orphan_set: &mut HashSet, + nodes_by_pointer: &mut HashMap, +) { + for node in nodes { + let mpt_node = MptNode::decode(node).expect("Failed to decode state proof"); + for potential_orphan in shorten_key(mpt_node) { + let potential_orphan_hash = potential_orphan.pointer(); + if orphan_set.contains(&potential_orphan_hash) { + orphan_set.remove(&potential_orphan_hash); + nodes_by_pointer.insert(potential_orphan_hash, potential_orphan); + } + } + } +} + +// We implement Into here rather than From for BlockBuilder to keep this code outside of +// the guest +#[allow(clippy::from_over_into)] +impl Into for Init { + fn into(self) -> Input { + // construct the proof tries + let (mut nodes_by_pointer, mut storage) = + proofs_to_tries(self.init_proofs.values().cloned().collect()); + // there should be a trie and a list of storage slots for every account + assert_eq!(storage.len(), self.db.accounts_len()); + + info!( + "Constructed proof tries with {} nodes", + nodes_by_pointer.len(), + ); + + // collect the code from each account + let mut contracts = HashMap::new(); + for account in self.db.accounts.values() { + let code = account.info.code.clone().unwrap(); + if !code.is_empty() { + contracts.insert(code.hash, code.bytecode); + } + } + + // extract the state trie + let state_root = self.init_block.state_root; + let state_trie = nodes_by_pointer + .remove(&MptNodeReference::Digest(state_root)) + .expect("State root node not found"); + assert_eq!(state_root, state_trie.hash()); + + // Find orphaned pointers during deletion + let mut orphan_set = HashSet::new(); + for root in storage.values().map(|v| &v.0).chain(once(&state_trie)) { + let root = resolve_pointers(root, &nodes_by_pointer); + orphan_set.extend( + orphaned_pointers(&root) + .iter() + .map(|node: &MptNode| node.pointer()), + ); + } + for fini_proof in self.fini_proofs.values() { + resolve_orphans( + &fini_proof.account_proof, + &mut orphan_set, + &mut nodes_by_pointer, + ); + for storage_proof in &fini_proof.storage_proof { + resolve_orphans(&storage_proof.proof, &mut orphan_set, &mut nodes_by_pointer); + } + } + + // resolve the pointers in the state root node and all storage root nodes + let state_trie = resolve_pointers(&state_trie, &nodes_by_pointer); + storage + .values_mut() + .for_each(|(n, _)| *n = resolve_pointers(n, &nodes_by_pointer)); + + // Create the block builder input + Input { + chain_spec: self.chain_spec, + parent_header: self.init_block, + beneficiary: self.fini_block.beneficiary, + gas_limit: self.fini_block.gas_limit, + timestamp: self.fini_block.timestamp, + extra_data: self.fini_block.extra_data.0.clone().into(), + mix_hash: self.fini_block.mix_hash, + transactions: self.fini_transactions, + withdrawals: self.fini_withdrawals, + parent_state_trie: state_trie, + parent_storage: storage, + contracts: contracts.into_values().map(|bytes| bytes.into()).collect(), + ancestor_headers: self.ancestor_headers, + } + } +} diff --git a/lib/src/host/mpt.rs b/lib/src/host/mpt.rs new file mode 100644 index 000000000..078ec486a --- /dev/null +++ b/lib/src/host/mpt.rs @@ -0,0 +1,138 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use hashbrown::HashMap; +use zeth_primitives::{ + trie::{to_prefix, MptNode, MptNodeData, MptNodeReference}, + RlpBytes, +}; + +pub fn load_pointers( + root: &MptNode, + node_store: &mut HashMap, +) -> MptNode { + let compact_node = match root.as_data() { + MptNodeData::Null | MptNodeData::Digest(_) | MptNodeData::Leaf(_, _) => root.clone(), + MptNodeData::Branch(children, value) => { + let compact_children: Vec> = children + .iter() + .map(|child| Box::new(load_pointers(child, node_store))) + .collect(); + MptNodeData::Branch(compact_children.try_into().unwrap(), value.clone()).into() + } + MptNodeData::Extension(prefix, target) => MptNodeData::Extension( + prefix.clone(), + Box::new(MptNodeData::Digest(target.hash()).into()), + ) + .into(), + }; + if let MptNodeData::Digest(_) = compact_node.as_data() { + // do nothing + } else { + node_store.insert(compact_node.pointer(), compact_node.clone()); + } + compact_node +} + +pub fn resolve_pointers( + root: &MptNode, + node_store: &HashMap, +) -> MptNode { + let result: MptNode = match root.as_data() { + MptNodeData::Null | MptNodeData::Leaf(_, _) => root.clone(), + MptNodeData::Branch(nodes, value) => { + let node_list: Vec<_> = nodes + .iter() + .map(|n| Box::new(resolve_pointers(n, node_store))) + .collect(); + MptNodeData::Branch( + node_list + .try_into() + .expect("Could not convert vector to 16-element array."), + value.clone(), + ) + .into() + } + MptNodeData::Extension(prefix, node) => { + MptNodeData::Extension(prefix.clone(), Box::new(resolve_pointers(node, node_store))) + .into() + } + MptNodeData::Digest(digest) => { + if let Some(node) = node_store.get(&MptNodeReference::Digest(*digest)) { + resolve_pointers(node, node_store) + } else { + root.clone() + } + } + }; + assert_eq!( + root.hash(), + result.hash(), + "Invalid node resolution! {:?} ({:?})", + root.to_rlp(), + result.to_rlp(), + ); + result +} + +pub fn orphaned_pointers(node: &MptNode) -> Vec { + let mut result = Vec::new(); + _orphaned_pointers(node, &mut result); + result +} + +fn _orphaned_pointers(node: &MptNode, res: &mut Vec) { + match node.as_data() { + MptNodeData::Null => {} + MptNodeData::Branch(children, _) => { + let unresolved_count = children.iter().filter(|n| !n.is_resolved()).count(); + if unresolved_count == 1 { + let unresolved_index = children.iter().position(|n| !n.is_resolved()).unwrap(); + res.push(*children[unresolved_index].clone()); + } + // Continue descent + for child in children { + _orphaned_pointers(child, res); + } + } + MptNodeData::Leaf(_, _) => {} + MptNodeData::Extension(_, target) => { + _orphaned_pointers(target, res); + } + MptNodeData::Digest(_) => {} + } +} + +pub fn shorten_key(node: MptNode) -> Vec { + let mut res = Vec::new(); + let nibs = node.nibs(); + match node.as_data() { + MptNodeData::Null | MptNodeData::Branch(_, _) | MptNodeData::Digest(_) => { + res.push(node.clone()) + } + MptNodeData::Leaf(_, value) => { + for i in 0..nibs.len() { + res.push(MptNodeData::Leaf(to_prefix(&nibs[i..], true), value.clone()).into()) + } + } + MptNodeData::Extension(_, target) => { + for i in 0..nibs.len() { + res.push( + MptNodeData::Extension(to_prefix(&nibs[i..], false), target.clone()).into(), + ) + } + } + }; + res +} diff --git a/lib/src/host/provider/cached_rpc_provider.rs b/lib/src/host/provider/cached_rpc_provider.rs new file mode 100644 index 000000000..762d74bfc --- /dev/null +++ b/lib/src/host/provider/cached_rpc_provider.rs @@ -0,0 +1,128 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::Result; +use ethers_core::types::{Block, Bytes, EIP1186ProofResponse, Transaction, H256, U256}; + +use super::{ + file_provider::FileProvider, rpc_provider::RpcProvider, AccountQuery, BlockQuery, MutProvider, + ProofQuery, Provider, StorageQuery, +}; + +pub struct CachedRpcProvider { + cache: FileProvider, + rpc: RpcProvider, +} + +impl CachedRpcProvider { + pub fn new(cache_path: String, rpc_url: String) -> Result { + let cache = match FileProvider::read_from_file(cache_path.clone()) { + Ok(provider) => provider, + Err(_) => FileProvider::empty(cache_path), + }; + let rpc = RpcProvider::new(rpc_url)?; + + Ok(CachedRpcProvider { cache, rpc }) + } +} + +impl Provider for CachedRpcProvider { + fn save(&self) -> Result<()> { + self.cache.save() + } + + fn get_full_block(&mut self, query: &BlockQuery) -> Result> { + let cache_out = self.cache.get_full_block(query); + if cache_out.is_ok() { + return cache_out; + } + + let out = self.rpc.get_full_block(query)?; + self.cache.insert_full_block(query.clone(), out.clone()); + + Ok(out) + } + + fn get_partial_block(&mut self, query: &BlockQuery) -> Result> { + let cache_out = self.cache.get_partial_block(query); + if cache_out.is_ok() { + return cache_out; + } + + let out = self.rpc.get_partial_block(query)?; + self.cache.insert_partial_block(query.clone(), out.clone()); + + Ok(out) + } + + fn get_proof(&mut self, query: &ProofQuery) -> Result { + let cache_out = self.cache.get_proof(query); + if cache_out.is_ok() { + return cache_out; + } + + let out = self.rpc.get_proof(query)?; + self.cache.insert_proof(query.clone(), out.clone()); + + Ok(out) + } + + fn get_transaction_count(&mut self, query: &AccountQuery) -> Result { + let cache_out = self.cache.get_transaction_count(query); + if cache_out.is_ok() { + return cache_out; + } + + let out = self.rpc.get_transaction_count(query)?; + self.cache.insert_transaction_count(query.clone(), out); + + Ok(out) + } + + fn get_balance(&mut self, query: &AccountQuery) -> Result { + let cache_out = self.cache.get_balance(query); + if cache_out.is_ok() { + return cache_out; + } + + let out = self.rpc.get_balance(query)?; + self.cache.insert_balance(query.clone(), out); + + Ok(out) + } + + fn get_code(&mut self, query: &AccountQuery) -> Result { + let cache_out = self.cache.get_code(query); + if cache_out.is_ok() { + return cache_out; + } + + let out = self.rpc.get_code(query)?; + self.cache.insert_code(query.clone(), out.clone()); + + Ok(out) + } + + fn get_storage(&mut self, query: &StorageQuery) -> Result { + let cache_out = self.cache.get_storage(query); + if cache_out.is_ok() { + return cache_out; + } + + let out = self.rpc.get_storage(query)?; + self.cache.insert_storage(query.clone(), out); + + Ok(out) + } +} diff --git a/lib/src/host/provider/file_provider.rs b/lib/src/host/provider/file_provider.rs new file mode 100644 index 000000000..c927f2904 --- /dev/null +++ b/lib/src/host/provider/file_provider.rs @@ -0,0 +1,182 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{ + collections::HashMap, + fs::File, + io::{Read, Write}, +}; + +use anyhow::{anyhow, Result}; +use ethers_core::types::{Block, Bytes, EIP1186ProofResponse, Transaction, H256, U256}; +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; + +use super::{AccountQuery, BlockQuery, MutProvider, ProofQuery, Provider, StorageQuery}; + +#[serde_as] +#[derive(Deserialize, Serialize)] +pub struct FileProvider { + #[serde(skip)] + file_path: String, + #[serde(skip)] + dirty: bool, + #[serde_as(as = "Vec<(_, _)>")] + full_blocks: HashMap>, + #[serde_as(as = "Vec<(_, _)>")] + partial_blocks: HashMap>, + #[serde_as(as = "Vec<(_, _)>")] + proofs: HashMap, + #[serde_as(as = "Vec<(_, _)>")] + transaction_count: HashMap, + #[serde_as(as = "Vec<(_, _)>")] + balance: HashMap, + #[serde_as(as = "Vec<(_, _)>")] + code: HashMap, + #[serde_as(as = "Vec<(_, _)>")] + storage: HashMap, +} + +impl FileProvider { + pub fn empty(file_path: String) -> Self { + FileProvider { + file_path, + dirty: false, + full_blocks: HashMap::new(), + partial_blocks: HashMap::new(), + proofs: HashMap::new(), + transaction_count: HashMap::new(), + balance: HashMap::new(), + code: HashMap::new(), + storage: HashMap::new(), + } + } + + pub fn read_from_file(file_path: String) -> Result { + let mut buf = vec![]; + let mut decoder = flate2::read::GzDecoder::new(File::open(&file_path)?); + decoder.read_to_end(&mut buf)?; + + let mut out: Self = serde_json::from_slice(&buf[..])?; + + out.file_path = file_path; + out.dirty = false; + Ok(out) + } + + pub fn save_to_file(&self, file_path: &String) -> Result<()> { + if self.dirty { + let mut encoder = flate2::write::GzEncoder::new( + File::create(file_path)?, + flate2::Compression::best(), + ); + encoder.write_all(&serde_json::to_vec(self)?)?; + encoder.finish()?; + } + + Ok(()) + } +} + +impl Provider for FileProvider { + fn save(&self) -> Result<()> { + self.save_to_file(&self.file_path) + } + + fn get_full_block(&mut self, query: &BlockQuery) -> Result> { + match self.full_blocks.get(query) { + Some(val) => Ok(val.clone()), + None => Err(anyhow!("No data for {:?}", query)), + } + } + + fn get_partial_block(&mut self, query: &BlockQuery) -> Result> { + match self.partial_blocks.get(query) { + Some(val) => Ok(val.clone()), + None => Err(anyhow!("No data for {:?}", query)), + } + } + + fn get_proof(&mut self, query: &ProofQuery) -> Result { + match self.proofs.get(query) { + Some(val) => Ok(val.clone()), + None => Err(anyhow!("No data for {:?}", query)), + } + } + + fn get_transaction_count(&mut self, query: &AccountQuery) -> Result { + match self.transaction_count.get(query) { + Some(val) => Ok(*val), + None => Err(anyhow!("No data for {:?}", query)), + } + } + + fn get_balance(&mut self, query: &AccountQuery) -> Result { + match self.balance.get(query) { + Some(val) => Ok(*val), + None => Err(anyhow!("No data for {:?}", query)), + } + } + + fn get_code(&mut self, query: &AccountQuery) -> Result { + match self.code.get(query) { + Some(val) => Ok(val.clone()), + None => Err(anyhow!("No data for {:?}", query)), + } + } + + fn get_storage(&mut self, query: &StorageQuery) -> Result { + match self.storage.get(query) { + Some(val) => Ok(*val), + None => Err(anyhow!("No data for {:?}", query)), + } + } +} + +impl MutProvider for FileProvider { + fn insert_full_block(&mut self, query: BlockQuery, val: Block) { + self.full_blocks.insert(query, val); + self.dirty = true; + } + + fn insert_partial_block(&mut self, query: BlockQuery, val: Block) { + self.partial_blocks.insert(query, val); + self.dirty = true; + } + + fn insert_proof(&mut self, query: ProofQuery, val: EIP1186ProofResponse) { + self.proofs.insert(query, val); + self.dirty = true; + } + + fn insert_transaction_count(&mut self, query: AccountQuery, val: U256) { + self.transaction_count.insert(query, val); + self.dirty = true; + } + + fn insert_balance(&mut self, query: AccountQuery, val: U256) { + self.balance.insert(query, val); + self.dirty = true; + } + + fn insert_code(&mut self, query: AccountQuery, val: Bytes) { + self.code.insert(query, val); + self.dirty = true; + } + + fn insert_storage(&mut self, query: StorageQuery, val: H256) { + self.storage.insert(query, val); + self.dirty = true; + } +} diff --git a/lib/src/host/provider/mod.rs b/lib/src/host/provider/mod.rs new file mode 100644 index 000000000..9165a61c4 --- /dev/null +++ b/lib/src/host/provider/mod.rs @@ -0,0 +1,98 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::{anyhow, Result}; +use ethers_core::types::{Block, Bytes, EIP1186ProofResponse, Transaction, H160, H256, U256}; +use serde::{Deserialize, Serialize}; + +pub mod cached_rpc_provider; +pub mod file_provider; +pub mod rpc_provider; + +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +pub struct AccountQuery { + pub block_no: u64, + pub address: H160, +} + +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +pub struct BlockQuery { + pub block_no: u64, +} + +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +pub struct ProofQuery { + pub block_no: u64, + pub address: H160, + pub indices: Vec, +} + +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +pub struct StorageQuery { + pub block_no: u64, + pub address: H160, + pub index: H256, +} + +pub trait Provider: Send { + fn save(&self) -> Result<()>; + + fn get_full_block(&mut self, query: &BlockQuery) -> Result>; + fn get_partial_block(&mut self, query: &BlockQuery) -> Result>; + fn get_proof(&mut self, query: &ProofQuery) -> Result; + fn get_transaction_count(&mut self, query: &AccountQuery) -> Result; + fn get_balance(&mut self, query: &AccountQuery) -> Result; + fn get_code(&mut self, query: &AccountQuery) -> Result; + fn get_storage(&mut self, query: &StorageQuery) -> Result; +} + +pub trait MutProvider: Provider { + fn insert_full_block(&mut self, query: BlockQuery, val: Block); + fn insert_partial_block(&mut self, query: BlockQuery, val: Block); + fn insert_proof(&mut self, query: ProofQuery, val: EIP1186ProofResponse); + fn insert_transaction_count(&mut self, query: AccountQuery, val: U256); + fn insert_balance(&mut self, query: AccountQuery, val: U256); + fn insert_code(&mut self, query: AccountQuery, val: Bytes); + fn insert_storage(&mut self, query: StorageQuery, val: H256); +} + +pub fn new_file_provider(file_path: String) -> Result> { + let provider = file_provider::FileProvider::read_from_file(file_path)?; + + Ok(Box::new(provider)) +} + +pub fn new_rpc_provider(rpc_url: String) -> Result> { + let provider = rpc_provider::RpcProvider::new(rpc_url)?; + + Ok(Box::new(provider)) +} + +pub fn new_cached_rpc_provider(cache_path: String, rpc_url: String) -> Result> { + let provider = cached_rpc_provider::CachedRpcProvider::new(cache_path, rpc_url)?; + + Ok(Box::new(provider)) +} + +pub fn new_provider( + cache_path: Option, + rpc_url: Option, +) -> Result> { + match (cache_path, rpc_url) { + (Some(cache_path), Some(rpc_url)) => new_cached_rpc_provider(cache_path, rpc_url), + (Some(cache_path), None) => new_file_provider(cache_path), + (None, Some(rpc_url)) => new_rpc_provider(rpc_url), + (None, None) => Err(anyhow!("No cache_path or rpc_url given")), + } +} diff --git a/lib/src/host/provider/rpc_provider.rs b/lib/src/host/provider/rpc_provider.rs new file mode 100644 index 000000000..233a73b26 --- /dev/null +++ b/lib/src/host/provider/rpc_provider.rs @@ -0,0 +1,133 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::{anyhow, Result}; +use ethers_core::types::{Block, Bytes, EIP1186ProofResponse, Transaction, H256, U256}; +use ethers_providers::{Http, Middleware}; +use log::info; + +use super::{AccountQuery, BlockQuery, ProofQuery, Provider, StorageQuery}; + +pub struct RpcProvider { + http_client: ethers_providers::Provider, + tokio_handle: tokio::runtime::Handle, +} + +impl RpcProvider { + pub fn new(rpc_url: String) -> Result { + let http_client = ethers_providers::Provider::::try_from(&rpc_url)?; + let tokio_handle = tokio::runtime::Handle::current(); + + Ok(RpcProvider { + http_client, + tokio_handle, + }) + } +} + +impl Provider for RpcProvider { + fn save(&self) -> Result<()> { + Ok(()) + } + + fn get_full_block(&mut self, query: &BlockQuery) -> Result> { + info!("Querying RPC for full block: {:?}", query); + + let response = self + .tokio_handle + .block_on(async { self.http_client.get_block_with_txs(query.block_no).await })?; + + match response { + Some(out) => Ok(out), + None => Err(anyhow!("No data for {:?}", query)), + } + } + + fn get_partial_block(&mut self, query: &BlockQuery) -> Result> { + info!("Querying RPC for partial block: {:?}", query); + + let response = self + .tokio_handle + .block_on(async { self.http_client.get_block(query.block_no).await })?; + + match response { + Some(out) => Ok(out), + None => Err(anyhow!("No data for {:?}", query)), + } + } + + fn get_proof(&mut self, query: &ProofQuery) -> Result { + info!("Querying RPC for inclusion proof: {:?}", query); + + let out = self.tokio_handle.block_on(async { + self.http_client + .get_proof( + query.address, + query.indices.clone(), + Some(query.block_no.into()), + ) + .await + })?; + + Ok(out) + } + + fn get_transaction_count(&mut self, query: &AccountQuery) -> Result { + info!("Querying RPC for transaction count: {:?}", query); + + let out = self.tokio_handle.block_on(async { + self.http_client + .get_transaction_count(query.address, Some(query.block_no.into())) + .await + })?; + + Ok(out) + } + + fn get_balance(&mut self, query: &AccountQuery) -> Result { + info!("Querying RPC for balance: {:?}", query); + + let out = self.tokio_handle.block_on(async { + self.http_client + .get_balance(query.address, Some(query.block_no.into())) + .await + })?; + + Ok(out) + } + + fn get_code(&mut self, query: &AccountQuery) -> Result { + info!("Querying RPC for code: {:?}", query); + + let out = self.tokio_handle.block_on(async { + self.http_client + .get_code(query.address, Some(query.block_no.into())) + .await + })?; + + Ok(out) + } + + fn get_storage(&mut self, query: &StorageQuery) -> Result { + info!("Querying RPC for storage: {:?}", query); + + let out = self.tokio_handle.block_on(async { + self.http_client + .get_storage_at(query.address, query.index, Some(query.block_no.into())) + .await + })?; + + Ok(out) + } +} diff --git a/lib/src/host/provider_db.rs b/lib/src/host/provider_db.rs new file mode 100644 index 000000000..d8dd42cef --- /dev/null +++ b/lib/src/host/provider_db.rs @@ -0,0 +1,240 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use ethers_core::types::{EIP1186ProofResponse, H160, H256}; +use hashbrown::{hash_map, HashMap}; +use revm::{ + primitives::{Account, AccountInfo, Bytecode, B160, B256, U256}, + Database, +}; +use zeth_primitives::block::Header; + +use crate::{ + block_builder::BlockBuilderDatabase, + host::provider::{AccountQuery, BlockQuery, ProofQuery, Provider, StorageQuery}, + mem_db::{DbAccount, DbError, MemDb}, +}; + +pub struct ProviderDb { + provider: Box, + block_no: u64, + initial_db: MemDb, + latest_db: MemDb, +} + +impl ProviderDb { + pub fn new(provider: Box, block_no: u64) -> Self { + ProviderDb { + provider, + block_no, + initial_db: MemDb::default(), + latest_db: MemDb::default(), + } + } + + pub fn get_provider(&self) -> &dyn Provider { + self.provider.as_ref() + } + + pub fn get_initial_db(&self) -> &MemDb { + &self.initial_db + } + + pub fn get_latest_db(&self) -> &MemDb { + &self.latest_db + } + + fn get_proofs( + &mut self, + block_no: u64, + storage_keys: HashMap>, + ) -> Result, anyhow::Error> { + let mut out = HashMap::new(); + + for (address, indices) in storage_keys { + let proof = { + let address: H160 = address.0.into(); + let indices: Vec = indices + .into_iter() + .map(|x: U256| x.to_be_bytes().into()) + .collect(); + self.provider.get_proof(&ProofQuery { + block_no, + address, + indices, + })? + }; + out.insert(address, proof); + } + + Ok(out) + } + + pub fn get_initial_proofs( + &mut self, + ) -> Result, anyhow::Error> { + self.get_proofs(self.block_no, self.initial_db.storage_keys()) + } + + pub fn get_latest_proofs( + &mut self, + ) -> Result, anyhow::Error> { + let mut storage_keys = self.initial_db.storage_keys(); + + for (address, mut indices) in self.latest_db.storage_keys() { + match storage_keys.get_mut(&address) { + Some(initial_indices) => initial_indices.append(&mut indices), + None => { + storage_keys.insert(address, indices); + } + } + } + + self.get_proofs(self.block_no + 1, storage_keys) + } + + pub fn get_ancestor_headers(&mut self) -> Result, anyhow::Error> { + let earliest_block = self + .initial_db + .block_hashes + .keys() + .min() + .unwrap_or(&self.block_no); + let headers = (*earliest_block..self.block_no) + .rev() + .map(|block_no| { + self.provider + .get_partial_block(&BlockQuery { block_no }) + .expect("Failed to retrieve ancestor block") + .try_into() + .expect("Failed to convert ethers block to zeth block") + }) + .collect(); + Ok(headers) + } +} + +impl Database for ProviderDb { + type Error = anyhow::Error; + + fn basic(&mut self, address: B160) -> Result, Self::Error> { + match self.latest_db.basic(address) { + Ok(db_result) => return Ok(db_result), + Err(DbError::AccountNotFound(_)) => {} + Err(err) => return Err(err.into()), + } + match self.initial_db.basic(address) { + Ok(db_result) => return Ok(db_result), + Err(DbError::AccountNotFound(_)) => {} + Err(err) => return Err(err.into()), + } + + let account_info = { + let address = H160::from(address.0); + let query = AccountQuery { + block_no: self.block_no, + address, + }; + let nonce = self.provider.get_transaction_count(&query)?; + let balance = self.provider.get_balance(&query)?; + let code = self.provider.get_code(&query)?; + + AccountInfo::new(balance.into(), nonce.as_u64(), Bytecode::new_raw(code.0)) + }; + + self.initial_db + .insert_account_info(address, account_info.clone()); + Ok(Some(account_info)) + } + + fn code_by_hash(&mut self, _code_hash: B256) -> Result { + // not needed because we already load code with basic info + unreachable!() + } + + fn storage(&mut self, address: B160, index: U256) -> Result { + match self.latest_db.storage(address, index) { + Ok(db_result) => return Ok(db_result), + Err(DbError::AccountNotFound(_)) | Err(DbError::SlotNotFound(_, _)) => {} + Err(err) => return Err(err.into()), + } + match self.initial_db.storage(address, index) { + Ok(db_result) => return Ok(db_result), + Err(DbError::AccountNotFound(_)) | Err(DbError::SlotNotFound(_, _)) => {} + Err(err) => return Err(err.into()), + } + + // ensure that the corresponding account is loaded + self.initial_db.basic(address)?; + + let storage = { + let address = H160::from(address.0); + let bytes = index.to_be_bytes(); + let index = H256::from(bytes); + + let storage = self.provider.get_storage(&StorageQuery { + block_no: self.block_no, + address, + index, + })?; + ethers_core::types::U256::from(storage.0) + }; + + self.initial_db + .insert_account_storage(&address, index, storage.into()); + Ok(storage.into()) + } + + fn block_hash(&mut self, number: U256) -> Result { + match self.initial_db.block_hash(number) { + Ok(block_hash) => return Ok(block_hash), + Err(DbError::BlockNotFound(_)) => {} + Err(err) => return Err(err.into()), + } + + let block_no = u64::try_from(number).unwrap(); + let block_hash = self + .provider + .get_partial_block(&BlockQuery { block_no })? + .hash + .unwrap() + .0 + .into(); + + self.initial_db.insert_block_hash(block_no, block_hash); + Ok(block_hash) + } +} + +impl BlockBuilderDatabase for ProviderDb { + fn load(_accounts: HashMap, _block_hashes: HashMap) -> Self { + unimplemented!() + } + + fn accounts(&self) -> hash_map::Iter { + self.latest_db.accounts() + } + + fn increase_balance(&mut self, address: B160, amount: U256) -> Result<(), Self::Error> { + // ensure that the address is loaded into the latest_db + if let Some(account_info) = self.basic(address)? { + self.latest_db.insert_account_info(address, account_info); + } + Ok(self.latest_db.increase_balance(address, amount)?) + } + + fn update(&mut self, address: B160, account: Account) { + self.latest_db.update(address, account); + } +} diff --git a/lib/src/lib.rs b/lib/src/lib.rs new file mode 100644 index 000000000..391d02b21 --- /dev/null +++ b/lib/src/lib.rs @@ -0,0 +1,29 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +extern crate core; + +#[cfg(not(target_os = "zkvm"))] +pub mod host; + +pub mod block_builder; +pub mod consts; +pub mod mem_db; +pub mod validation; + +/// call forget only if running inside the guest +pub fn guest_mem_forget(_t: T) { + #[cfg(target_os = "zkvm")] + core::mem::forget(_t) +} diff --git a/lib/src/mem_db.rs b/lib/src/mem_db.rs new file mode 100644 index 000000000..d85cdbff5 --- /dev/null +++ b/lib/src/mem_db.rs @@ -0,0 +1,327 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::Context; +use hashbrown::{ + hash_map::{self, Entry}, + HashMap, +}; +#[cfg(not(target_os = "zkvm"))] +use log::debug; +use revm::{ + primitives::{Account, AccountInfo, Bytecode, B160, B256, U256}, + Database, DatabaseCommit, +}; +use thiserror::Error as ThisError; + +use crate::block_builder::BlockBuilderDatabase; + +/// Error returned by the [MemDb]. +#[derive(Debug, ThisError)] +pub enum DbError { + /// Returned when an account was accessed but not loaded into the DB. + #[error("account {0} not loaded")] + AccountNotFound(B160), + /// Returned when storage was accessed but not loaded into the DB. + #[error("storage {1}@{0} not loaded")] + SlotNotFound(B160, U256), + /// Returned when a block hash was accessed but not loaded into the DB. + #[error("block {0} not loaded")] + BlockNotFound(u64), + /// Unspecified error. + #[error(transparent)] + Unspecified(#[from] anyhow::Error), +} + +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub enum AccountState { + // Account can be cleared/removed from state. + Deleted, + /// EVM touched this account. + Touched, + /// EVM cleared storage of this account, mostly by `selfdestruct`. + StorageCleared, + /// EVM didn't interacted with this account. + #[default] + None, +} + +#[derive(Clone, Debug, Default)] +pub struct DbAccount { + pub info: AccountInfo, + pub state: AccountState, + pub storage: HashMap, +} + +impl DbAccount { + pub fn new(info: AccountInfo) -> Self { + Self { + info, + ..Default::default() + } + } + + /// Return the account info or `None` if the account has been deleted. + pub fn info(&self) -> Option { + if self.state == AccountState::Deleted { + None + } else { + Some(self.info.clone()) + } + } +} + +/// In-memory EVM database. +#[derive(Clone, Debug, Default)] +pub struct MemDb { + /// Account info where None means it is not existing. + pub accounts: HashMap, + /// All cached block hashes. + pub block_hashes: HashMap, +} + +impl MemDb { + pub fn accounts_len(&self) -> usize { + self.accounts.len() + } + + pub fn storage_keys(&self) -> HashMap> { + let mut out = HashMap::new(); + for (address, account) in &self.accounts { + out.insert(*address, account.storage.keys().cloned().collect()); + } + + out + } + + /// Insert account info without overriding its storage. + /// Panics if a different account info exists. + pub fn insert_account_info(&mut self, address: B160, info: AccountInfo) { + match self.accounts.entry(address) { + Entry::Occupied(entry) => assert_eq!(info, entry.get().info), + Entry::Vacant(entry) => { + entry.insert(DbAccount::new(info)); + } + } + } + + /// insert account storage without overriding the account info. + /// Panics if the account does not exist. + pub fn insert_account_storage(&mut self, address: &B160, index: U256, data: U256) { + let account = self.accounts.get_mut(address).expect("account not found"); + account.storage.insert(index, data); + } + + /// Insert the specified block hash. Panics if a different block hash exists. + pub fn insert_block_hash(&mut self, block_no: u64, block_hash: B256) { + match self.block_hashes.entry(block_no) { + Entry::Occupied(entry) => assert_eq!(&block_hash, entry.get()), + Entry::Vacant(entry) => { + entry.insert(block_hash); + } + }; + } +} + +impl Database for MemDb { + type Error = DbError; + + /// Get basic account information. + fn basic(&mut self, address: B160) -> Result, Self::Error> { + match self.accounts.get(&address) { + Some(db_account) => Ok(db_account.info()), + None => Err(DbError::AccountNotFound(address)), + } + } + + /// Get account code by its hash. + fn code_by_hash(&mut self, _code_hash: B256) -> Result { + // not needed because we already load code with basic info + unreachable!() + } + + /// Get storage value of address at index. + fn storage(&mut self, address: B160, index: U256) -> Result { + match self.accounts.get(&address) { + // if we have this account in the cache, we can query its storage + Some(account) => match account.storage.get(&index) { + Some(value) => Ok(*value), + None => match account.state { + // it is impossible to access the storage from a non-existing account + AccountState::Deleted => unreachable!(), + // if the account has been deleted or cleared, we must return 0 + AccountState::StorageCleared => Ok(U256::ZERO), + // otherwise this is an uncached load + _ => Err(DbError::SlotNotFound(address, index)), + }, + }, + // otherwise this is an uncached load + None => Err(DbError::AccountNotFound(address)), + } + } + + fn block_hash(&mut self, number: U256) -> Result { + let block_no: u64 = number.try_into().with_context(|| { + format!( + "invalid block number: expected <= {}, got {}", + u64::MAX, + &number + ) + })?; + self.block_hashes + .get(&block_no) + .cloned() + .ok_or(DbError::BlockNotFound(block_no)) + } +} + +impl BlockBuilderDatabase for MemDb { + fn load(accounts: HashMap, block_hashes: HashMap) -> Self { + MemDb { + accounts, + block_hashes, + } + } + + fn accounts(&self) -> hash_map::Iter { + self.accounts.iter() + } + + fn increase_balance(&mut self, address: B160, amount: U256) -> Result<(), Self::Error> { + let account = self + .accounts + .get_mut(&address) + .ok_or(DbError::AccountNotFound(address))?; + + account.info.balance = account + .info + .balance + .checked_add(amount) + .with_context(|| format!("addition overflow for {:?}", &address))?; + + match account.state { + // if the account was deleted, we still have to clear its storage + AccountState::Deleted => { + account.state = AccountState::StorageCleared; + } + // mark as touched + AccountState::None => { + account.state = AccountState::Touched; + } + _ => {} + }; + + Ok(()) + } + + fn update(&mut self, address: B160, new_account: Account) { + // if nothing was touched, there is nothing to do + if !new_account.is_touched { + return; + } + #[cfg(not(target_os = "zkvm"))] + debug!("State update {:?}: {:?}", &address, &new_account); + + if new_account.is_destroyed { + // get the account we are destroying + let db_account = match self.accounts.entry(address) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(_) => { + // destruction of a non-existing account, so there is nothing to do + // a) the account was created and destroyed in the same transaction + // b) or it was destroyed without reading and thus not cached + return; + } + }; + + // it is not possible to delete a deleted account + debug_assert!(db_account.state != AccountState::Deleted); + + // clear the account and mark it as deleted + db_account.storage.clear(); + db_account.state = AccountState::Deleted; + db_account.info = AccountInfo::default(); + + return; + } + + // empty accounts cannot have any non-zero storage + if new_account.is_empty() { + debug_assert!(new_account.storage.is_empty()); + } + + // update account info + let db_account = match self.accounts.entry(address) { + Entry::Occupied(entry) => { + let db_account = entry.into_mut(); + + // the account was touched, but it is empty, so it should be deleted + // this also deletes empty accounts previously contained in the state trie + if db_account.state != AccountState::Deleted && new_account.is_empty() { + db_account.storage.clear(); + db_account.state = AccountState::Deleted; + db_account.info = AccountInfo::default(); + + return; + } + + // create account only if it is not empty + if db_account.info.is_empty() && new_account.is_empty() { + return; + } + + // update the account info + db_account.info = new_account.info; + db_account + } + Entry::Vacant(entry) => { + // create a new account only if it is not empty + if new_account.is_empty() { + return; + } + + // create new non-empty account + entry.insert(DbAccount::new(new_account.info)) + } + }; + + // set the correct state + db_account.state = if new_account.storage_cleared { + db_account.storage.clear(); + AccountState::StorageCleared + } else if db_account.state == AccountState::StorageCleared { + // when creating the storage trie, it must be cleared it first + AccountState::StorageCleared + } else { + AccountState::Touched + }; + + // update all changed storage values + db_account.storage.extend( + new_account + .storage + .into_iter() + .filter(|(_, value)| value.is_changed()) + .map(|(key, value)| (key, value.present_value())), + ); + } +} + +impl DatabaseCommit for MemDb { + fn commit(&mut self, changes: HashMap) { + for (address, new_account) in changes { + self.update(address, new_account); + } + } +} diff --git a/lib/src/validation.rs b/lib/src/validation.rs new file mode 100644 index 000000000..51dc61a7d --- /dev/null +++ b/lib/src/validation.rs @@ -0,0 +1,227 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::fmt::Debug; + +use anyhow::{bail, Context, Result}; +use hashbrown::HashMap; +use revm::primitives::{SpecId, B160 as RevmB160, B256 as RevmB256}; +use serde::{Deserialize, Serialize}; +use zeth_primitives::{ + block::Header, revm::to_revm_b256, transaction::Transaction, trie::MptNode, + withdrawal::Withdrawal, BlockNumber, Bytes, B160, B256, U256, +}; + +use crate::consts::{ + ChainSpec, BASE_FEE_MAX_CHANGE_DENOMINATOR, ELASTICITY_MULTIPLIER, GAS_LIMIT_BOUND_DIVISOR, + MAX_BLOCK_HASH_AGE, MAX_EXTRA_DATA_BYTES, MIN_GAS_LIMIT, MIN_SPEC_ID, ONE, +}; + +/// External block input. +#[derive(Debug, Clone, Default, Deserialize, Serialize)] +pub struct Input { + /// Chain spec + pub chain_spec: ChainSpec, + /// Previous block header + pub parent_header: Header, + /// Address to which all priority fees in this block are transferred. + pub beneficiary: B160, + /// Scalar equal to the current limit of gas expenditure per block. + pub gas_limit: U256, + /// Scalar corresponding to the seconds since Epoch at this block's inception. + pub timestamp: U256, + /// Arbitrary byte array containing data relevant for this block. + pub extra_data: Bytes, + /// Hash previously used for the PoW now containing the RANDAO value. + pub mix_hash: B256, + /// List of transactions for execution + pub transactions: Vec, + /// List of stake withdrawals for execution + pub withdrawals: Vec, + /// State trie of the parent block. + pub parent_state_trie: MptNode, + /// Maps each address with its storage trie and the used storage slots. + pub parent_storage: HashMap, + /// The code of all unique contracts. + pub contracts: Vec, + /// List of at most 256 previous block headers + pub ancestor_headers: Vec
, +} + +pub type StorageEntry = (MptNode, Vec); + +pub fn verify_gas_limit(input_gas_limit: U256, parent_gas_limit: U256) -> Result<()> { + let diff = parent_gas_limit.abs_diff(input_gas_limit); + let limit = parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR; + if diff >= limit { + bail!( + "Invalid gas limit: expected {} +- {}, got {}", + parent_gas_limit, + limit, + input_gas_limit, + ); + } + if input_gas_limit < MIN_GAS_LIMIT { + bail!( + "Invalid gas limit: expected >= {}, got {}", + MIN_GAS_LIMIT, + input_gas_limit, + ); + } + + Ok(()) +} + +pub fn verify_timestamp(input_timestamp: U256, parent_timestamp: U256) -> Result<()> { + if input_timestamp <= parent_timestamp { + bail!( + "Invalid timestamp: expected > {}, got {}", + parent_timestamp, + input_timestamp, + ); + } + + Ok(()) +} + +pub fn verify_extra_data(input_extra_data: &Bytes) -> Result<()> { + let extra_data_bytes = input_extra_data.len(); + if extra_data_bytes >= MAX_EXTRA_DATA_BYTES { + bail!( + "Invalid extra data: expected <= {}, got {}", + MAX_EXTRA_DATA_BYTES, + extra_data_bytes, + ) + } + + Ok(()) +} + +pub fn verify_state_trie(state_trie: &MptNode, parent_state_root: &B256) -> Result<()> { + let state_root = state_trie.hash(); + if &state_root != parent_state_root { + bail!( + "Invalid state trie: expected {}, got {}", + parent_state_root, + state_root + ); + } + + Ok(()) +} + +pub fn verify_storage_trie( + address: impl Debug, + storage_trie: &MptNode, + account_storage_root: &B256, +) -> Result<()> { + let storage_root = storage_trie.hash(); + if &storage_root != account_storage_root { + bail!( + "Invalid storage trie for {:?}: expected {}, got {}", + address, + account_storage_root, + storage_root + ); + } + + Ok(()) +} + +pub fn verify_parent_chain( + parent: &Header, + ancestors: &[Header], +) -> Result> { + let mut block_hashes = HashMap::with_capacity(ancestors.len() + 1); + block_hashes.insert(parent.number, to_revm_b256(parent.hash())); + let mut prev = parent; + for current in ancestors { + let current_hash = current.hash(); + if prev.parent_hash != current_hash { + bail!( + "Invalid chain: {} is not the parent of {}", + current.number, + prev.number + ); + } + if parent.number < current.number || parent.number - current.number >= MAX_BLOCK_HASH_AGE { + bail!( + "Invalid chain: {} is not one of the {} most recent blocks", + current.number, + MAX_BLOCK_HASH_AGE, + ); + } + block_hashes.insert(current.number, to_revm_b256(current_hash)); + prev = current; + } + + Ok(block_hashes) +} + +pub fn compute_block_number(parent: &Header) -> Result { + parent + .number + .checked_add(1) + .context("Invalid block number: too large") +} + +pub fn compute_spec_id(chain_spec: &ChainSpec, block_number: BlockNumber) -> Result { + let spec_id = chain_spec.spec_id(block_number); + if !SpecId::enabled(spec_id, MIN_SPEC_ID) { + bail!( + "Invalid protocol version: expected >= {:?}, got {:?}", + MIN_SPEC_ID, + spec_id, + ) + } + Ok(spec_id) +} + +/// Calculate base fee for next block. [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) spec +pub fn compute_base_fee(parent: &Header) -> Result { + let parent_gas_target = parent.gas_limit / ELASTICITY_MULTIPLIER; + + match parent.gas_used.cmp(&parent_gas_target) { + std::cmp::Ordering::Equal => Ok(parent.base_fee_per_gas), + + std::cmp::Ordering::Greater => { + let gas_used_delta = parent.gas_used - parent_gas_target; + let base_fee_delta = ONE.max( + parent.base_fee_per_gas * gas_used_delta + / parent_gas_target + / BASE_FEE_MAX_CHANGE_DENOMINATOR, + ); + Ok(parent.base_fee_per_gas + base_fee_delta) + } + + std::cmp::Ordering::Less => { + let gas_used_delta = parent_gas_target - parent.gas_used; + let base_fee_delta = parent.base_fee_per_gas * gas_used_delta + / parent_gas_target + / BASE_FEE_MAX_CHANGE_DENOMINATOR; + Ok(parent.base_fee_per_gas - base_fee_delta) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn input_serde_roundtrip() { + let input = Input::default(); + let _: Input = bincode::deserialize(&bincode::serialize(&input).unwrap()).unwrap(); + } +} diff --git a/lib/testdata b/lib/testdata new file mode 160000 index 000000000..9b6382b12 --- /dev/null +++ b/lib/testdata @@ -0,0 +1 @@ +Subproject commit 9b6382b122140b5479a4ff6152ccf1459440ddff diff --git a/lib/tests/common/ethers.rs b/lib/tests/common/ethers.rs new file mode 100644 index 000000000..b584ddfeb --- /dev/null +++ b/lib/tests/common/ethers.rs @@ -0,0 +1,185 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use ethers_core::types::{ + Block, Bloom, Bytes, EIP1186ProofResponse, StorageProof, Transaction, H256, U256, +}; +use zeth_primitives::U256 as LibU256; + +use super::*; + +/// Provider that always returns the default if not contained in the state. +pub struct TestProvider { + pub state: TestState, + pub header: Header, +} + +impl Provider for TestProvider { + fn save(&self) -> Result<(), anyhow::Error> { + unimplemented!() + } + + fn get_full_block(&mut self, _: &BlockQuery) -> Result, anyhow::Error> { + unimplemented!() + } + + fn get_partial_block(&mut self, query: &BlockQuery) -> Result, anyhow::Error> { + if query.block_no != self.header.number { + bail!("block {} not found", query.block_no); + } + + Ok(Block:: { + parent_hash: self.header.parent_hash.0.into(), + uncles_hash: self.header.ommers_hash.0.into(), + author: Some(self.header.beneficiary.0.into()), + state_root: self.header.state_root.0.into(), + transactions_root: self.header.transactions_root.0.into(), + receipts_root: self.header.receipts_root.0.into(), + logs_bloom: Some(Bloom::from_slice(self.header.logs_bloom.as_slice())), + difficulty: self.header.difficulty.to_be_bytes().into(), + number: Some(self.header.number.into()), + gas_limit: self.header.gas_limit.to_be_bytes().into(), + gas_used: self.header.gas_used.to_be_bytes().into(), + timestamp: self.header.timestamp.to_be_bytes().into(), + extra_data: self.header.extra_data.0.clone().into(), + mix_hash: Some(self.header.mix_hash.0.into()), + nonce: Some(self.header.nonce.0.into()), + base_fee_per_gas: Some(self.header.base_fee_per_gas.to_be_bytes().into()), + withdrawals_root: self.header.withdrawals_root.map(|r| r.0.into()), + hash: Some(self.header.hash().0.into()), + ..Default::default() + }) + } + + fn get_proof(&mut self, query: &ProofQuery) -> Result { + assert_eq!(query.block_no, self.header.number); + + let address = from_ethers_h160(query.address); + let account = self.state.0.get(&address).cloned().unwrap_or_default(); + + let (state_trie, mut storage_tries) = build_tries(&self.state); + let storage_trie = storage_tries.remove(&address).unwrap_or_default(); + + let account_proof = mpt_proof(&state_trie, keccak(query.address))? + .into_iter() + .map(|p| p.into()) + .collect(); + let mut storage_proof = vec![]; + for index in &query.indices { + let proof = StorageProof { + key: index.clone().into(), + proof: mpt_proof(&storage_trie, keccak(index))? + .into_iter() + .map(|p| p.into()) + .collect(), + value: account + .storage + .get(&LibU256::from_be_bytes(index.0)) + .cloned() + .unwrap_or_default() + .to_be_bytes() + .into(), + }; + storage_proof.push(proof); + } + + Ok(EIP1186ProofResponse { + address: query.address, + balance: account.balance.to_be_bytes().into(), + code_hash: keccak(account.code).into(), + nonce: account.nonce.to_be_bytes().into(), + storage_hash: storage_trie.hash().0.into(), + account_proof, + storage_proof, + }) + } + + fn get_transaction_count(&mut self, query: &AccountQuery) -> Result { + assert_eq!(query.block_no, self.header.number); + + let nonce: u64 = self + .state + .0 + .get(&from_ethers_h160(query.address)) + .map(|account| account.nonce.try_into().unwrap()) + .unwrap_or_default(); + Ok(U256::from(nonce)) + } + + fn get_balance(&mut self, query: &AccountQuery) -> Result { + assert_eq!(query.block_no, self.header.number); + + let balance = self + .state + .0 + .get(&from_ethers_h160(query.address)) + .map(|account| account.balance) + .unwrap_or_default(); + Ok(balance.to_be_bytes().into()) + } + + fn get_code(&mut self, query: &AccountQuery) -> Result { + assert_eq!(query.block_no, self.header.number); + + let code = self + .state + .0 + .get(&from_ethers_h160(query.address)) + .map(|account| account.code.clone()) + .unwrap_or_default(); + Ok(code.0.into()) + } + + fn get_storage(&mut self, query: &StorageQuery) -> Result { + assert_eq!(query.block_no, self.header.number); + + match self.state.0.get(&from_ethers_h160(query.address)) { + Some(account) => { + let value = account + .storage + .get(&LibU256::from_be_bytes(query.index.0)) + .cloned() + .unwrap_or_default(); + Ok(value.to_be_bytes().into()) + } + None => Ok(H256::zero()), + } + } +} + +fn build_tries(state: &TestState) -> (MptNode, HashMap) { + let mut state_trie = MptNode::default(); + let mut storage_tries = HashMap::new(); + for (address, account) in &state.0 { + let mut storage_trie = MptNode::default(); + for (slot, value) in &account.storage { + if *value != LibU256::ZERO { + storage_trie.rlp_update(&keccak(&slot.to_be_bytes::<32>()), *value); + } + } + + state_trie.rlp_update( + &keccak(address), + StateAccount { + nonce: account.nonce.try_into().unwrap(), + balance: account.balance, + storage_root: storage_trie.hash(), + code_hash: keccak(account.code.clone()).into(), + }, + ); + storage_tries.insert(address.clone(), storage_trie); + } + + (state_trie, storage_tries) +} diff --git a/lib/tests/common/mod.rs b/lib/tests/common/mod.rs new file mode 100644 index 000000000..5fb03512f --- /dev/null +++ b/lib/tests/common/mod.rs @@ -0,0 +1,283 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::bail; +use hashbrown::HashMap; +use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, NoneAsEmptyString}; +use zeth_lib::{ + block_builder::BlockBuilderDatabase, + host::provider::{AccountQuery, BlockQuery, ProofQuery, Provider, StorageQuery}, + mem_db::DbAccount, +}; +use zeth_primitives::{ + access_list::{AccessList, AccessListItem}, + block::Header, + ethers::from_ethers_h160, + keccak::keccak, + revm::from_revm_b160, + signature::TxSignature, + transaction::{ + Transaction, TransactionKind, TxEssence, TxEssenceEip1559, TxEssenceEip2930, + TxEssenceLegacy, + }, + trie::{self, MptNode, MptNodeData, StateAccount}, + withdrawal::Withdrawal, + Bloom, Bytes, RlpBytes, StorageKey, B160, B256, B64, U256, U64, +}; + +pub mod ethers; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TestJson { + pub blocks: Vec, + #[serde(rename = "genesisBlockHeader")] + pub genesis: TestHeader, + #[serde(rename = "genesisRLP")] + pub genesis_rlp: Bytes, + pub network: String, + pub pre: TestState, + #[serde(rename = "postState")] + pub post: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TestBlock { + pub block_header: Option, + pub expect_exception: Option, + pub rlp: Bytes, + #[serde(default)] + pub transactions: Vec, + #[serde(default)] + pub uncle_headers: Vec, + pub withdrawals: Option>, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct TestAccount { + pub balance: U256, + pub nonce: U64, + pub code: Bytes, + pub storage: HashMap, +} + +impl From for TestAccount { + fn from(account: DbAccount) -> Self { + TestAccount { + balance: account.info.balance, + nonce: U64::from(account.info.nonce), + code: account.info.code.unwrap().bytecode.into(), + storage: account.storage.into_iter().map(|(k, v)| (k, v)).collect(), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct TestState(pub HashMap); + +impl From for TestState { + fn from(db: D) -> Self { + TestState( + db.accounts() + .map(|(addr, account)| (from_revm_b160(*addr), account.clone().into())) + .collect(), + ) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TestHeader { + pub base_fee_per_gas: Option, + pub bloom: Bloom, + pub coinbase: B160, + pub extra_data: Bytes, + pub difficulty: U256, + pub gas_limit: U256, + pub gas_used: U256, + pub hash: B256, + pub mix_hash: B256, + pub nonce: B64, + pub number: U64, + pub parent_hash: B256, + pub receipt_trie: B256, + pub state_root: B256, + pub timestamp: U256, + pub transactions_trie: B256, + pub uncle_hash: B256, + pub withdrawals_root: Option, +} + +impl From for Header { + fn from(header: TestHeader) -> Self { + Header { + parent_hash: header.parent_hash, + ommers_hash: header.uncle_hash, + beneficiary: header.coinbase, + state_root: header.state_root, + transactions_root: header.transactions_trie, + receipts_root: header.receipt_trie, + logs_bloom: header.bloom, + difficulty: header.difficulty, + number: header.number.try_into().unwrap(), + gas_limit: header.gas_limit, + gas_used: header.gas_used, + timestamp: header.timestamp, + extra_data: header.extra_data, + mix_hash: header.mix_hash, + nonce: header.nonce, + base_fee_per_gas: header.base_fee_per_gas.unwrap(), + withdrawals_root: header.withdrawals_root, + } + } +} + +#[serde_as] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TestTransaction { + pub data: Bytes, + pub access_list: Option, + pub gas_limit: U256, + pub gas_price: Option, + pub max_fee_per_gas: Option, + pub max_priority_fee_per_gas: Option, + pub value: U256, + #[serde_as(as = "NoneAsEmptyString")] + pub to: Option, + pub nonce: U64, + pub v: U64, + pub r: U256, + pub s: U256, +} + +impl From for Transaction { + fn from(tx: TestTransaction) -> Self { + let signature = TxSignature { + v: tx.v.try_into().unwrap(), + r: tx.r, + s: tx.s, + }; + let essence = if tx.access_list.is_none() { + TxEssence::Legacy(TxEssenceLegacy { + chain_id: None, + nonce: tx.nonce.try_into().unwrap(), + gas_price: tx.gas_price.unwrap(), + gas_limit: tx.gas_limit, + to: match tx.to { + Some(addr) => TransactionKind::Call(addr), + None => TransactionKind::Create, + }, + value: tx.value, + data: tx.data, + }) + } else if tx.max_fee_per_gas.is_none() { + TxEssence::Eip2930(TxEssenceEip2930 { + chain_id: 1, + nonce: tx.nonce.try_into().unwrap(), + gas_price: tx.gas_price.unwrap(), + gas_limit: tx.gas_limit, + to: match tx.to { + Some(addr) => TransactionKind::Call(addr), + None => TransactionKind::Create, + }, + value: tx.value, + data: tx.data, + access_list: tx.access_list.unwrap().into(), + }) + } else { + TxEssence::Eip1559(TxEssenceEip1559 { + chain_id: 1, + nonce: tx.nonce.try_into().unwrap(), + max_priority_fee_per_gas: tx.max_priority_fee_per_gas.unwrap(), + max_fee_per_gas: tx.max_fee_per_gas.unwrap(), + gas_limit: tx.gas_limit, + to: match tx.to { + Some(addr) => TransactionKind::Call(addr), + None => TransactionKind::Create, + }, + value: tx.value, + data: tx.data, + access_list: tx.access_list.unwrap().into(), + }) + }; + Transaction { essence, signature } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TestAccessList(pub Vec); + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TestAccessListItem { + pub address: B160, + pub storage_keys: Vec, +} + +impl From for AccessList { + fn from(list: TestAccessList) -> Self { + AccessList( + list.0 + .into_iter() + .map(|item| AccessListItem { + address: item.address, + storage_keys: item.storage_keys, + }) + .collect(), + ) + } +} + +/// Computes the Merkle proof for the given key in the trie. +pub fn mpt_proof(root: &MptNode, key: impl AsRef<[u8]>) -> Result>, anyhow::Error> { + let mut path = proof_internal(root, &trie::to_nibs(key.as_ref()))?; + path.reverse(); + Ok(path) +} + +fn proof_internal(node: &MptNode, key_nibs: &[u8]) -> Result>, anyhow::Error> { + if key_nibs.is_empty() { + return Ok(vec![node.to_rlp()]); + } + + let mut path: Vec> = match node.as_data() { + MptNodeData::Null | MptNodeData::Leaf(_, _) => vec![], + MptNodeData::Branch(children, _) => { + let mut path = Vec::new(); + for node in children { + path.extend(proof_internal(&node, &key_nibs[1..])?); + } + path + } + MptNodeData::Extension(_, child) => { + let ext_nibs = node.nibs(); + let ext_len = ext_nibs.len(); + if key_nibs[..ext_len] == ext_nibs { + proof_internal(&child, &key_nibs[ext_len..])? + } else { + vec![] + } + } + MptNodeData::Digest(_) => bail!("Cannot descend pointer!"), + }; + path.push(node.to_rlp()); + + Ok(path) +} diff --git a/lib/tests/evm.rs b/lib/tests/evm.rs new file mode 100644 index 000000000..7b16db0db --- /dev/null +++ b/lib/tests/evm.rs @@ -0,0 +1,188 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{fs::File, io::BufReader, path::PathBuf}; + +use common::ethers::TestProvider; +use hashbrown::HashMap; +use revm::primitives::SpecId; +use rstest::rstest; +use serde_json::Value; +use zeth_lib::{ + block_builder::BlockBuilder, + consts::ChainSpec, + host::{provider_db::ProviderDb, Init}, + mem_db::MemDb, + validation::Input, +}; +use zeth_primitives::{block::Header, transaction::Transaction, withdrawal::Withdrawal}; + +use crate::common::*; + +mod common; + +// TODO: investigate those stack overflows +static IGNORE_SET: phf::Set<&'static str> = phf::phf_set! { + "baseFeeDiffPlaces_d34g0v0_Shanghai", "gasPriceDiffPlaces_d34g0v0_Shanghai", "LoopCallsDepthThenRevert2_d0g0v0_Shanghai", + "LoopCallsDepthThenRevert3_d0g0v0_Shanghai", "diffPlaces_d34g0v0_Shanghai", "static_Call1024BalanceTooLow2_d1g0v0_Shanghai", + "static_Call1024BalanceTooLow_d1g0v0_Shanghai", "static_Call1024PreCalls3_d1g0v0_Shanghai", + "static_Call1024PreCalls_d1g0v0_Shanghai", "static_Call1024PreCalls2_d0g0v0_Shanghai", + "static_Call1024PreCalls2_d1g0v0_Shanghai", "static_CallRecursiveBomb0_OOG_atMaxCallDepth_d0g0v0_Shanghai", + "static_CallRecursiveBombPreCall2_d0g0v0_Shanghai", "static_CallRecursiveBombPreCall_d0g0v0_Shanghai", + "static_LoopCallsDepthThenRevert3_d0g0v0_Shanghai", "static_LoopCallsDepthThenRevert2_d0g0v0_Shanghai", + "CallRecursiveBomb0_OOG_atMaxCallDepth_d0g0v0_Shanghai", "Call1024BalanceTooLow_d0g0v0_Shanghai", + "Call1024PreCalls_d0g1v0_Shanghai", "Call1024PreCalls_d0g2v0_Shanghai", "CallRecursiveBombPreCall_d0g0v0_Shanghai", + "Delegatecall1024_d0g0v0_Shanghai", "Create2OnDepth1024_d0g0v0_Shanghai", "Create2OnDepth1023_d0g0v0_Shanghai", + "Create2Recursive_d0g0v0_Shanghai", "Create2Recursive_d0g2v0_Shanghai", "Call1024PreCalls_d0g0v0_Shanghai", + "Callcode1024BalanceTooLow_d0g0v0_Shanghai", "invalidDiffPlaces_d34g0v0_Shanghai", "opc0EDiffPlaces_d34g0v0_Shanghai", +}; + +#[rstest] +fn evm( + #[files("testdata/BlockchainTests/GeneralStateTests/**/*.json")] + #[exclude("stBadOpcode|refundResetFrontier")] + path: PathBuf, +) { + let _ = env_logger::builder() + .filter_level(log::LevelFilter::Debug) + .is_test(true) + .try_init(); + + println!("Using file: {}", path.display()); + let f = File::open(path).unwrap(); + let mut root: Value = serde_json::from_reader(BufReader::new(f)).unwrap(); + + for (name, test) in root.as_object_mut().unwrap() { + println!("test '{}'", name); + if IGNORE_SET.contains(name) { + println!("ignoring"); + continue; + } + let json: TestJson = serde_json::from_value(test.take()).unwrap(); + + // only run Shanghai tests + let spec: SpecId = json.network.as_str().into(); + if spec != SpecId::SHANGHAI { + println!("skipping ({:?})", spec); + continue; + } + let config = ChainSpec::new_single(1, spec); + + let genesis: Header = json.genesis.clone().into(); + assert_eq!(genesis.hash(), json.genesis.hash); + + // log the pre-state + dbg!(&json.pre); + + let mut state = json.pre; + let mut parent_header = genesis; + let mut ancestor_headers = vec![]; + for block in json.blocks { + // skip failing tests for now + if let Some(message) = block.expect_exception { + println!("skipping ({})", message); + break; + } + + let block_header = block.block_header.unwrap(); + let expected_header: Header = block_header.clone().into(); + assert_eq!(&expected_header.hash(), &block_header.hash); + + // construct the block + let builder = new_builder( + config.clone(), + state, + parent_header.clone(), + expected_header.clone(), + block.transactions, + block.withdrawals.unwrap_or_default(), + ) + .initialize_evm_storage() + .unwrap() + .initialize_header() + .unwrap() + .execute_transactions() + .unwrap(); + let result_header = builder.clone().build(None).unwrap(); + // the headers should match + assert_eq!(result_header.state_root, expected_header.state_root); + assert_eq!(result_header, expected_header); + + state = builder.to_db().into(); + ancestor_headers.push(parent_header); + parent_header = block_header.into(); + } + // log the post-state + dbg!(state, &json.post); + } +} + +fn new_builder( + config: ChainSpec, + state: TestState, + parent_header: Header, + header: Header, + transactions: Vec, + withdrawals: Vec, +) -> BlockBuilder { + // create the provider DB + let mut provider_db = ProviderDb::new( + Box::new(TestProvider { + state, + header: parent_header.clone(), + }), + parent_header.number, + ); + + let transactions: Vec = transactions.into_iter().map(Transaction::from).collect(); + let input = Input { + beneficiary: header.beneficiary, + gas_limit: header.gas_limit, + timestamp: header.timestamp, + extra_data: header.extra_data.clone(), + mix_hash: header.mix_hash, + transactions: transactions.clone(), + withdrawals: withdrawals.clone(), + chain_spec: config.clone(), + parent_header: parent_header.clone(), + ..Default::default() + }; + + // create and run the block builder once to create the initial DB + let block_builder = BlockBuilder::new(Some(provider_db), input) + .initialize_header() + .unwrap() + .execute_transactions() + .unwrap(); + provider_db = block_builder.to_db(); + + let init_proofs = provider_db.get_initial_proofs().unwrap(); + let fini_proofs = HashMap::new(); + let ancestor_headers = provider_db.get_ancestor_headers().unwrap(); + + let input: Input = Init { + db: provider_db.get_initial_db().clone(), + init_block: parent_header, + init_proofs, + fini_block: header, + fini_transactions: transactions, + fini_withdrawals: withdrawals, + fini_proofs, + ancestor_headers, + chain_spec: config, + } + .into(); + + input.into() +} diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml new file mode 100644 index 000000000..5a1909e2d --- /dev/null +++ b/primitives/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "zeth-primitives" +version = "0.1.0" +edition = "2021" + +[dependencies] +alloy-primitives = { git = "https://github.com/alloy-rs/core.git", rev = "58e2259", features = ["rlp", "serde"] } +alloy-rlp = { version = "0.3", default-features = false } +alloy-rlp-derive = { version = "0.3", default-features = false } +anyhow = "1.0" +bytes = { version = "1.1", default-features = false } +ethers-core = { version = "2.0", optional = true } +k256 = { version = "=0.13.1", features = ["std", "ecdsa"], default_features = false } +revm-primitives = { version = "1.1", optional = true } +rlp = "0.5.2" +serde = { version = "1.0", features = ["derive"] } +sha2 = "=0.10.6" +sha3 = "0.10" + +[dev-dependencies] +bincode = "1.3" +hex-literal = "0.4" +rand = "0.8" +serde_json = "1.0" + +[features] +ethers = ["dep:ethers-core"] +revm = ["dep:revm-primitives"] + +[target.'cfg(not(target_os = "zkvm"))'.dependencies] +log = "0.4" diff --git a/primitives/src/access_list.rs b/primitives/src/access_list.rs new file mode 100644 index 000000000..da0017ff1 --- /dev/null +++ b/primitives/src/access_list.rs @@ -0,0 +1,30 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use alloy_primitives::{StorageKey, B160}; +use alloy_rlp_derive::{RlpEncodable, RlpEncodableWrapper}; +use serde::{Deserialize, Serialize}; + +/// AccessList as defined in EIP-2930. +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodableWrapper)] +pub struct AccessList(pub Vec); + +/// A list of addresses and storage keys that the transaction plans to access. +#[derive(Debug, Clone, PartialEq, Eq, Default, RlpEncodable, Serialize, Deserialize)] +pub struct AccessListItem { + /// Account address. + pub address: B160, + /// Storage keys for that address. + pub storage_keys: Vec, +} diff --git a/primitives/src/block.rs b/primitives/src/block.rs new file mode 100644 index 000000000..4758a37ef --- /dev/null +++ b/primitives/src/block.rs @@ -0,0 +1,171 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use alloy_primitives::{b256, BlockHash, BlockNumber, Bloom, Bytes, B160, B256, B64, U256}; +use alloy_rlp::Encodable; +use alloy_rlp_derive::RlpEncodable; +use bytes::BytesMut; +use serde::{Deserialize, Serialize}; + +use crate::{keccak::keccak, trie::EMPTY_ROOT}; + +/// Keccak-256 hash of the RLP of an empty list, keccak256("\xc0"). +pub const EMPTY_LIST_HASH: B256 = + b256!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"); + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RlpEncodable)] +#[rlp(trailing)] +pub struct Header { + /// Hash of the parent block's header. + pub parent_hash: BlockHash, + /// Unused 256-bit hash, always [EMPTY_LIST_HASH]. + pub ommers_hash: B256, + /// Address to which the priority fees of each transaction is transferred. + pub beneficiary: B160, + /// Hash of the root node of the state trie, after all transactions are executed. + pub state_root: B256, + /// Hash of the root node of the trie populated with each transaction in the block. + pub transactions_root: B256, + /// Hash of the root node of the trie populated with the receipts of each transaction. + pub receipts_root: B256, + /// Bloom filter composed from indexable information contained in each log entry. + pub logs_bloom: Bloom, + /// Unused value, always `0`. + pub difficulty: U256, + /// Number of ancestor blocks in the chain. + pub number: BlockNumber, + /// Value equal to the current limit of gas expenditure per block. + pub gas_limit: U256, + /// Value equal to the total gas used in transactions in this block. + pub gas_used: U256, + /// Value corresponding to the seconds since Epoch at this block's inception. + pub timestamp: U256, + /// Arbitrary byte array containing data relevant for this block. + pub extra_data: Bytes, + /// Hash previously used for the PoW now containing the RANDAO value. + pub mix_hash: B256, + /// Unused 64-bit hash, always zero. + pub nonce: B64, + /// Base fee payed by all transactions in the block. + pub base_fee_per_gas: U256, + /// Hash of the root node of the trie populated with each withdrawal in the block. + /// Only present after the Shanghai update. + #[serde(default)] + pub withdrawals_root: Option, +} + +impl Default for Header { + fn default() -> Self { + Header { + parent_hash: B256::ZERO, + ommers_hash: EMPTY_LIST_HASH, + beneficiary: B160::ZERO, + state_root: EMPTY_ROOT, + transactions_root: EMPTY_ROOT, + receipts_root: EMPTY_ROOT, + logs_bloom: Bloom::default(), + difficulty: U256::ZERO, + number: 0, + gas_limit: U256::ZERO, + gas_used: U256::ZERO, + timestamp: U256::ZERO, + extra_data: Bytes::new(), + mix_hash: B256::ZERO, + nonce: B64::ZERO, + base_fee_per_gas: U256::ZERO, + withdrawals_root: None, + } + } +} + +impl Header { + /// Calculates the block hash. + pub fn hash(&self) -> BlockHash { + let mut bytes = BytesMut::new(); + self.encode(&mut bytes); + keccak(bytes).into() + } +} + +#[cfg(test)] +mod tests { + use serde_json::json; + + use super::*; + + #[test] + fn paris() { + // first block after the Paris network upgrade + let value = json!({ + "parent_hash":"0x55b11b918355b1ef9c5db810302ebad0bf2544255b530cdce90674d5887bb286", + "ommers_hash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "beneficiary": "0xeee27662c2b8eba3cd936a23f039f3189633e4c8", + "state_root": "0x40c07091e16263270f3579385090fea02dd5f061ba6750228fcc082ff762fda7", + "transactions_root": "0x1ea1746468686159ce730c1cc49a886721244e5d1fa9a06d6d4196b6f013c82c", + "receipts_root": "0x928073fb98ce316265ea35d95ab7e2e1206cecd85242eb841dbbcc4f568fca4b", + "logs_bloom": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "difficulty": "0x0", + "number": 15537394, + "gas_limit": "0x1c9c380", + "gas_used": "0x1c9811e", + "timestamp": "0x6322c973", + "extra_data": "0x", + "mix_hash": "0xa86c2e601b6c44eb4848f7d23d9df3113fbcac42041c49cbed5000cb4f118777", + "nonce": "0x0000000000000000", + "base_fee_per_gas": "0xb5d68e0a3" + }); + let header: Header = serde_json::from_value(value).unwrap(); + + // verify that bincode serialization works + let _: Header = bincode::deserialize(&bincode::serialize(&header).unwrap()).unwrap(); + + assert_eq!( + "0x56a9bb0302da44b8c0b3df540781424684c3af04d0b7a38d72842b762076a664", + header.hash().to_string() + ) + } + + #[test] + fn shanghai() { + // first block after the Shanghai network upgrade + let value = json!({ + "parent_hash": "0xc2558f8143d5f5acb8382b8cb2b8e2f1a10c8bdfeededad850eaca048ed85d8f", + "ommers_hash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "beneficiary": "0x388c818ca8b9251b393131c08a736a67ccb19297", + "state_root": "0x7fd42f5027bc18315b3781e65f19e4c8828fd5c5fce33410f0fb4fea0b65541f", + "transactions_root": "0x6f235d618461c08943aa5c23cc751310d6177ab8a9b9a7b66ffa637d988680e6", + "receipts_root": "0xe0ac34bafdd757bcca2dea27a3fc5870dd0836998877e29361c1fc55e19416ec", + "logs_bloom": "0xb06769bc11f4d7a51a3bc4bed59367b75c32d1bd79e5970e73732ac0eed0251af0e2abc8811fc1b4c5d45a4a4eb5c5af9e73cc9a8be6ace72faadc03536d6b69fcdf80116fd89f7efbdbf38ff957e8f6ae83ccac60cf4b7c8b1c9487bebfa8ed6e42297e17172d5b678dd3f283b22f49bbf4a0565eb93d9d797b2f9a0adaff9813af53d6fffa71d5a6fb056ab73ca87659dc97c19f99839c6c3138e527161b4dfee8b1f64d42f927abc745f3ff168e8e9510e2e079f4868ba8ff94faf37c9a7947a43c1b4c931dfbef88edeb2d7ede5ceaebc85095cfbbd206646def0138683b687fa63fdf22898260d616bc714d698bc5748c7a5bff0a4a32dd797596a794a0", + "difficulty": "0x0", + "number": 17034870, + "gas_limit": "0x1c9c380", + "gas_used": "0x1c9bfe2", + "timestamp": "0x6437306f", + "extra_data": "0xd883010b05846765746888676f312e32302e32856c696e7578", + "mix_hash": "0x812ed704cc408c435c7baa6e86296c1ac654a139ae8c4a26d6460742b951d4f9", + "nonce": "0x0000000000000000", + "base_fee_per_gas": "0x42fbae6d5", + "withdrawals_root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + }); + let header: Header = serde_json::from_value(value).unwrap(); + + // verify that bincode serialization works + let _: Header = bincode::deserialize(&bincode::serialize(&header).unwrap()).unwrap(); + + assert_eq!( + "0xe22c56f211f03baadcc91e4eb9a24344e6848c5df4473988f893b58223f5216c", + header.hash().to_string() + ) + } +} diff --git a/primitives/src/ethers.rs b/primitives/src/ethers.rs new file mode 100644 index 000000000..c4d3f8a8d --- /dev/null +++ b/primitives/src/ethers.rs @@ -0,0 +1,201 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Convert from Ethers types. + +use alloy_primitives::{Bloom, B160, B256, U256}; +use anyhow::{anyhow, Context}; +use ethers_core::types::{ + transaction::eip2930::{ + AccessList as EthersAccessList, AccessListItem as EthersAccessListItem, + }, + Block as EthersBlock, Transaction as EthersTransaction, Withdrawal as EthersWithdrawal, + H160 as EthersH160, H256 as EthersH256, U256 as EthersU256, +}; + +use crate::{ + access_list::{AccessList, AccessListItem}, + block::Header, + signature::TxSignature, + transaction::{ + Transaction, TransactionKind, TxEssence, TxEssenceEip1559, TxEssenceEip2930, + TxEssenceLegacy, + }, + withdrawal::Withdrawal, +}; + +#[inline] +pub fn from_ethers_u256(v: EthersU256) -> U256 { + U256::from_limbs(v.0) +} + +#[inline] +pub fn from_ethers_h160(v: EthersH160) -> B160 { + v.0.into() +} + +#[inline] +pub fn from_ethers_h256(v: EthersH256) -> B256 { + v.0.into() +} + +impl From for AccessListItem { + fn from(item: EthersAccessListItem) -> Self { + AccessListItem { + address: item.address.0.into(), + storage_keys: item + .storage_keys + .into_iter() + .map(|key| key.0.into()) + .collect(), + } + } +} + +impl From for AccessList { + fn from(list: EthersAccessList) -> Self { + AccessList(list.0.into_iter().map(|item| item.into()).collect()) + } +} + +impl From> for TransactionKind { + fn from(addr: Option) -> Self { + match addr { + Some(address) => TransactionKind::Call(address.0.into()), + None => TransactionKind::Create, + } + } +} + +impl TryFrom> for Header { + type Error = anyhow::Error; + + fn try_from(block: EthersBlock) -> Result { + Ok(Header { + parent_hash: from_ethers_h256(block.parent_hash), + ommers_hash: from_ethers_h256(block.uncles_hash), + beneficiary: from_ethers_h160(block.author.context("author missing")?), + state_root: from_ethers_h256(block.state_root), + transactions_root: from_ethers_h256(block.transactions_root), + receipts_root: from_ethers_h256(block.receipts_root), + logs_bloom: Bloom::from_slice( + block.logs_bloom.context("logs_bloom missing")?.as_bytes(), + ), + difficulty: from_ethers_u256(block.difficulty), + number: block.number.context("number missing")?.as_u64(), + gas_limit: from_ethers_u256(block.gas_limit), + gas_used: from_ethers_u256(block.gas_used), + timestamp: from_ethers_u256(block.timestamp), + extra_data: block.extra_data.0.into(), + mix_hash: block.mix_hash.context("mix_hash missing")?.0.into(), + nonce: block.nonce.context("nonce missing")?.0.into(), + base_fee_per_gas: from_ethers_u256( + block.base_fee_per_gas.context("base_fee_per_gas missing")?, + ), + withdrawals_root: block.withdrawals_root.map(from_ethers_h256), + }) + } +} + +impl TryFrom for Transaction { + type Error = anyhow::Error; + + fn try_from(tx: EthersTransaction) -> Result { + let essence = match tx.transaction_type.map(|t| t.as_u64()) { + None | Some(0) => TxEssence::Legacy(TxEssenceLegacy { + chain_id: match tx.chain_id { + None => None, + Some(chain_id) => Some( + chain_id + .try_into() + .map_err(|err| anyhow!("invalid chain_id: {}", err))?, + ), + }, + nonce: tx + .nonce + .try_into() + .map_err(|err| anyhow!("invalid nonce: {}", err))?, + gas_price: from_ethers_u256(tx.gas_price.context("gas_price missing")?), + gas_limit: from_ethers_u256(tx.gas), + to: tx.to.into(), + value: from_ethers_u256(tx.value), + data: tx.input.0.into(), + }), + Some(1) => TxEssence::Eip2930(TxEssenceEip2930 { + chain_id: tx + .chain_id + .context("chain_id missing")? + .try_into() + .map_err(|err| anyhow!("invalid chain_id: {}", err))?, + nonce: tx + .nonce + .try_into() + .map_err(|err| anyhow!("invalid nonce: {}", err))?, + gas_price: from_ethers_u256(tx.gas_price.context("gas_price missing")?), + gas_limit: from_ethers_u256(tx.gas), + to: tx.to.into(), + value: from_ethers_u256(tx.value), + access_list: tx.access_list.context("access_list missing")?.into(), + data: tx.input.0.into(), + }), + Some(2) => TxEssence::Eip1559(TxEssenceEip1559 { + chain_id: tx + .chain_id + .context("chain_id missing")? + .try_into() + .map_err(|err| anyhow!("invalid chain_id: {}", err))?, + nonce: tx + .nonce + .try_into() + .map_err(|err| anyhow!("invalid nonce: {}", err))?, + max_priority_fee_per_gas: from_ethers_u256( + tx.max_priority_fee_per_gas + .context("max_priority_fee_per_gas missing")?, + ), + max_fee_per_gas: from_ethers_u256( + tx.max_fee_per_gas.context("max_fee_per_gas missing")?, + ), + gas_limit: from_ethers_u256(tx.gas), + to: tx.to.into(), + value: from_ethers_u256(tx.value), + access_list: tx.access_list.context("access_list missing")?.into(), + data: tx.input.0.into(), + }), + _ => unreachable!(), + }; + let signature = TxSignature { + v: tx.v.as_u64(), + r: from_ethers_u256(tx.r), + s: from_ethers_u256(tx.s), + }; + + Ok(Transaction { essence, signature }) + } +} + +impl TryFrom for Withdrawal { + type Error = anyhow::Error; + + fn try_from(withdrawal: EthersWithdrawal) -> Result { + Ok(Withdrawal { + index: withdrawal.index.as_u64(), + validator_index: withdrawal.validator_index.as_u64(), + address: withdrawal.address.0.into(), + amount: withdrawal + .amount + .try_into() + .map_err(|err| anyhow!("invalid amount: {}", err))?, + }) + } +} diff --git a/primitives/src/keccak.rs b/primitives/src/keccak.rs new file mode 100644 index 000000000..0655963cc --- /dev/null +++ b/primitives/src/keccak.rs @@ -0,0 +1,29 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use alloy_primitives::{b256, B256}; +use sha3::{Digest, Keccak256}; + +/// Keccak hash of an empty slice. +pub const KECCAK_EMPTY: B256 = + b256!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); + +/// Computes the Keccak-256 hash. +/// TODO: consider switching to B256 to have consistent return types +#[inline] +pub fn keccak(data: impl AsRef<[u8]>) -> [u8; 32] { + // TODO: remove accelerated hashing benchmark + // std::hint::black_box(sha2::Sha256::digest(&data)); + Keccak256::digest(data).into() +} diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs new file mode 100644 index 000000000..3fc1b30bf --- /dev/null +++ b/primitives/src/lib.rs @@ -0,0 +1,50 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +extern crate core; + +pub mod access_list; +pub mod block; +pub mod keccak; +pub mod receipt; +pub mod signature; +pub mod transaction; +pub mod trie; +pub mod withdrawal; + +#[cfg(feature = "ethers")] +pub mod ethers; + +#[cfg(feature = "revm")] +pub mod revm; + +pub use alloy_primitives::*; +pub use alloy_rlp as rlp; + +pub trait RlpBytes { + /// Returns the RLP-encoding. + fn to_rlp(&self) -> Vec; +} + +impl RlpBytes for T +where + T: rlp::Encodable, +{ + #[inline] + fn to_rlp(&self) -> Vec { + let mut out = Vec::new(); + self.encode(&mut out); + out + } +} diff --git a/primitives/src/receipt.rs b/primitives/src/receipt.rs new file mode 100644 index 000000000..f60bbb1a3 --- /dev/null +++ b/primitives/src/receipt.rs @@ -0,0 +1,197 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use alloy_primitives::{Bloom, BloomInput, Bytes, B160, B256, U256}; +use alloy_rlp::Encodable; +use alloy_rlp_derive::RlpEncodable; +use serde::{Deserialize, Serialize}; + +/// Ethereum Log +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable)] +pub struct Log { + /// Contract that emitted this log. + pub address: B160, + /// Topics of the log. The number of logs depend on what `LOG` opcode is used. + pub topics: Vec, + /// Arbitrary length data. + pub data: Bytes, +} + +/// Payload of a [Receipt]. +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable)] +pub struct ReceiptPayload { + /// If transaction is executed successfully. + pub success: bool, + /// Gas used + pub cumulative_gas_used: U256, + /// Bloom filter composed from information in logs. + pub logs_bloom: Bloom, + /// Log send from contracts. + pub logs: Vec, +} + +/// Receipt containing result of transaction execution. +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] +pub struct Receipt { + /// Receipt type. + pub tx_type: u8, + /// Receipt payload. + pub payload: ReceiptPayload, +} + +impl Encodable for Receipt { + fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { + match self.tx_type { + // legacy + 0 => self.payload.encode(out), + // EIP-2718 + tx_type => { + // prepend the EIP-2718 transaction type + out.put_u8(tx_type); + // append the RLP-encoded payload + self.payload.encode(out); + } + } + } +} + +impl Receipt { + pub fn new(tx_type: u8, success: bool, cumulative_gas_used: U256, logs: Vec) -> Receipt { + let mut logs_bloom = Bloom::default(); + for log in &logs { + logs_bloom.accrue(BloomInput::Raw(log.address.as_slice())); + for topic in &log.topics { + logs_bloom.accrue(BloomInput::Raw(topic.as_slice())); + } + } + + Receipt { + tx_type, + payload: ReceiptPayload { + success, + cumulative_gas_used, + logs_bloom, + logs, + }, + } + } +} + +// test vectors from https://github.com/ethereum/go-ethereum/blob/c40ab6af72ce282020d03c33e8273ea9b03d58f6/core/types/receipt_test.go +#[cfg(test)] +mod tests { + use hex_literal::hex; + use serde_json::json; + + use super::*; + + #[test] + fn legacy() { + let expected = hex!("f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"); + let receipt = Receipt::new( + 0, + false, + U256::from(1), + serde_json::from_value(json!([ + { + "address": "0x0000000000000000000000000000000000000011", + "topics": [ + "0x000000000000000000000000000000000000000000000000000000000000dead", + "0x000000000000000000000000000000000000000000000000000000000000beef" + ], + "data": "0x0100ff" + }, + { + "address": "0x0000000000000000000000000000000000000111", + "topics": [ + "0x000000000000000000000000000000000000000000000000000000000000dead", + "0x000000000000000000000000000000000000000000000000000000000000beef" + ], + "data": "0x0100ff" + } + ])) + .unwrap(), + ); + let mut data = vec![]; + receipt.encode(&mut data); + + assert_eq!(data, expected); + } + + #[test] + fn eip2930() { + let expected = hex!("01f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"); + let receipt = Receipt::new( + 1, + false, + U256::from(1), + serde_json::from_value(json!([ + { + "address": "0x0000000000000000000000000000000000000011", + "topics": [ + "0x000000000000000000000000000000000000000000000000000000000000dead", + "0x000000000000000000000000000000000000000000000000000000000000beef" + ], + "data": "0x0100ff" + }, + { + "address": "0x0000000000000000000000000000000000000111", + "topics": [ + "0x000000000000000000000000000000000000000000000000000000000000dead", + "0x000000000000000000000000000000000000000000000000000000000000beef" + ], + "data": "0x0100ff" + } + ])) + .unwrap(), + ); + let mut data = vec![]; + receipt.encode(&mut data); + + assert_eq!(data, expected); + } + + #[test] + fn eip1559() { + let expected = hex!("02f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"); + let receipt = Receipt::new( + 2, + false, + U256::from(1), + serde_json::from_value(json!([ + { + "address": "0x0000000000000000000000000000000000000011", + "topics": [ + "0x000000000000000000000000000000000000000000000000000000000000dead", + "0x000000000000000000000000000000000000000000000000000000000000beef" + ], + "data": "0x0100ff" + }, + { + "address": "0x0000000000000000000000000000000000000111", + "topics": [ + "0x000000000000000000000000000000000000000000000000000000000000dead", + "0x000000000000000000000000000000000000000000000000000000000000beef" + ], + "data": "0x0100ff" + } + ])) + .unwrap(), + ); + let mut data = vec![]; + receipt.encode(&mut data); + + assert_eq!(data, expected); + } +} diff --git a/primitives/src/revm.rs b/primitives/src/revm.rs new file mode 100644 index 000000000..1b4261d30 --- /dev/null +++ b/primitives/src/revm.rs @@ -0,0 +1,71 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Convert to revm types. + +use alloy_primitives::{B160, B256}; +use revm_primitives::{Log as RevmLog, B160 as RevmB160, B256 as RevmB256, U256 as RevmU256}; + +use crate::{ + access_list::{AccessList, AccessListItem}, + receipt::Log, +}; + +#[inline] +pub fn to_revm_b160(v: B160) -> RevmB160 { + v.0.into() +} + +#[inline] +pub fn to_revm_b256(v: B256) -> RevmB256 { + v.0.into() +} + +#[inline] +pub fn from_revm_b160(v: RevmB160) -> B160 { + v.0.into() +} + +#[inline] +pub fn from_revm_b256(v: RevmB256) -> B256 { + v.0.into() +} + +impl From for (RevmB160, Vec) { + fn from(item: AccessListItem) -> (RevmB160, Vec) { + ( + to_revm_b160(item.address), + item.storage_keys + .into_iter() + .map(|item| item.into()) + .collect(), + ) + } +} + +impl From for Vec<(RevmB160, Vec)> { + fn from(list: AccessList) -> Vec<(RevmB160, Vec)> { + list.0.into_iter().map(|item| item.into()).collect() + } +} + +impl From for Log { + fn from(log: RevmLog) -> Self { + Log { + address: log.address.to_fixed_bytes().into(), + topics: log.topics.into_iter().map(from_revm_b256).collect(), + data: log.data.into(), + } + } +} diff --git a/primitives/src/signature.rs b/primitives/src/signature.rs new file mode 100644 index 000000000..b2dee35c5 --- /dev/null +++ b/primitives/src/signature.rs @@ -0,0 +1,85 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use alloy_primitives::{B160, U256}; +use alloy_rlp_derive::RlpEncodable; +use anyhow::Context; +use k256::{ + ecdsa::{RecoveryId, Signature as K256Signature, VerifyingKey as K256VerifyingKey}, + elliptic_curve::sec1::ToEncodedPoint, + PublicKey as K256PublicKey, +}; +use serde::{Deserialize, Serialize}; + +use crate::{ + keccak::keccak, + transaction::{Transaction, TxEssence, TxEssenceLegacy}, +}; + +/// A signature that can be used to recover the signing public key. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RlpEncodable)] +pub struct TxSignature { + pub v: u64, + pub r: U256, + pub s: U256, +} + +impl Transaction { + /// Recover the sending party of the transaction. + pub fn recover_from(&self) -> anyhow::Result { + let is_y_odd = self.is_y_odd().context("v invalid")?; + let signature = K256Signature::from_scalars( + self.signature.r.to_be_bytes(), + self.signature.s.to_be_bytes(), + ) + .context("r, s invalid")?; + + let verify_key = K256VerifyingKey::recover_from_prehash( + self.essence.signing_hash().as_slice(), + &signature, + RecoveryId::new(is_y_odd, false), + ) + .context("invalid signature")?; + + let public_key = K256PublicKey::from(&verify_key); + let public_key = public_key.to_encoded_point(false); + let public_key = public_key.as_bytes(); + debug_assert_eq!(public_key[0], 0x04); + let hash = keccak(&public_key[1..]); + + Ok(B160::from_slice(&hash[12..])) + } + + fn is_y_odd(&self) -> Option { + match &self.essence { + TxEssence::Legacy(TxEssenceLegacy { chain_id: None, .. }) => { + checked_bool(self.signature.v - 27) + } + TxEssence::Legacy(TxEssenceLegacy { + chain_id: Some(chain_id), + .. + }) => checked_bool(self.signature.v - 35 - 2 * chain_id), + _ => checked_bool(self.signature.v), + } + } +} + +#[inline] +fn checked_bool(v: u64) -> Option { + match v { + 0 => Some(false), + 1 => Some(true), + _ => None, + } +} diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs new file mode 100644 index 000000000..f7029b494 --- /dev/null +++ b/primitives/src/transaction.rs @@ -0,0 +1,528 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use alloy_primitives::{Bytes, ChainId, TxHash, TxNumber, B160, B256, U256}; +use alloy_rlp::{Encodable, EMPTY_STRING_CODE}; +use alloy_rlp_derive::RlpEncodable; +use bytes::{BufMut, BytesMut}; +use serde::{Deserialize, Serialize}; + +use crate::{access_list::AccessList, keccak::keccak, signature::TxSignature, RlpBytes}; + +/// Legacy transaction as described in [EIP-155](https://eips.ethereum.org/EIPS/eip-155). +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] +pub struct TxEssenceLegacy { + /// Network chain ID, added in EIP-155. + pub chain_id: Option, + /// A scalar value equal to the number of transactions sent by the sender. + pub nonce: TxNumber, + /// A scalar value equal to the number of Wei to be paid per unit of gas for all + /// computation costs. + pub gas_price: U256, + /// A scalar value equal to the maximum amount of gas that should be used in executing + /// this transaction. + pub gas_limit: U256, + /// The 160-bit address of the message call's recipient or, for a contract creation + /// transaction, ∅. + pub to: TransactionKind, + /// A scalar value equal to the number of Wei to be transferred to the message call's + /// recipient. + pub value: U256, + /// An unlimited size byte array specifying the transaction data. + pub data: Bytes, +} + +impl TxEssenceLegacy { + /// Length of the RLP payload in bytes. + fn payload_length(&self) -> usize { + self.nonce.length() + + self.gas_price.length() + + self.gas_limit.length() + + self.to.length() + + self.value.length() + + self.data.length() + } + + /// Encode the transaction into the `out` buffer, only for signing. + fn encode_signing(&self, out: &mut dyn alloy_rlp::BufMut) { + let mut payload_length = self.payload_length(); + // if a chain ID is present, append according to EIP-155 + if let Some(chain_id) = self.chain_id { + payload_length += chain_id.length() + 1 + 1; + } + alloy_rlp::Header { + list: true, + payload_length, + } + .encode(out); + self.nonce.encode(out); + self.gas_price.encode(out); + self.gas_limit.encode(out); + self.to.encode(out); + self.value.encode(out); + self.data.encode(out); + if let Some(chain_id) = self.chain_id { + chain_id.encode(out); + out.put_u8(alloy_rlp::EMPTY_STRING_CODE); + out.put_u8(alloy_rlp::EMPTY_STRING_CODE); + } + } +} + +// implement Encodable to always ignore the chain ID +impl Encodable for TxEssenceLegacy { + fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { + alloy_rlp::Header { + list: true, + payload_length: self.payload_length(), + } + .encode(out); + self.nonce.encode(out); + self.gas_price.encode(out); + self.gas_limit.encode(out); + self.to.encode(out); + self.value.encode(out); + self.data.encode(out); + } + + fn length(&self) -> usize { + let payload_length = self.payload_length(); + alloy_rlp::length_of_length(payload_length) + payload_length + } +} + +/// Transaction with an access list as described in [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930). +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable)] +pub struct TxEssenceEip2930 { + /// Network chain ID. + pub chain_id: ChainId, + /// A scalar value equal to the number of transactions sent by the sender. + pub nonce: TxNumber, + /// A scalar value equal to the number of Wei to be paid per unit of gas for all + /// computation costs. + pub gas_price: U256, + /// A scalar value equal to the maximum amount of gas that should be used in executing + /// this transaction. + pub gas_limit: U256, + /// The 160-bit address of the message call's recipient or, for a contract creation + /// transaction, ∅. + pub to: TransactionKind, + /// A scalar value equal to the number of Wei to be transferred to the message call's + /// recipient. + pub value: U256, + /// An unlimited size byte array specifying the transaction data. + pub data: Bytes, + /// List of access entries to warm up. + pub access_list: AccessList, +} + +/// A transaction with a priority fee as described in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable)] +pub struct TxEssenceEip1559 { + /// Network chain ID, added in EIP-155. + pub chain_id: ChainId, + /// A scalar value equal to the number of transactions sent by the sender. + pub nonce: TxNumber, + /// Maximum priority fee that transaction is paying to the miner. + pub max_priority_fee_per_gas: U256, + /// Maximum base and priority fee paid per unit of gas for all computation costs. + pub max_fee_per_gas: U256, + /// A scalar value equal to the maximum amount of gas that should be used in executing + /// this transaction. + pub gas_limit: U256, + /// The 160-bit address of the message call's recipient or, for a contract creation + /// transaction, ∅. + pub to: TransactionKind, + /// A scalar value equal to the number of Wei to be transferred to the message call's + /// recipient. + pub value: U256, + /// An unlimited size byte array specifying the transaction data. + pub data: Bytes, + /// List of access entries to warm up. + pub access_list: AccessList, +} + +/// Essence of a transaction, i.e. the signed part. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum TxEssence { + /// Legacy transaction. + Legacy(TxEssenceLegacy), + /// Transaction with an access list ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930)). + Eip2930(TxEssenceEip2930), + /// A transaction with a priority fee ([EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)). + Eip1559(TxEssenceEip1559), +} + +impl Encodable for TxEssence { + fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { + match self { + TxEssence::Legacy(tx) => tx.encode(out), + TxEssence::Eip2930(tx) => tx.encode(out), + TxEssence::Eip1559(tx) => tx.encode(out), + } + } + fn length(&self) -> usize { + match self { + TxEssence::Legacy(tx) => tx.length(), + TxEssence::Eip2930(tx) => tx.length(), + TxEssence::Eip1559(tx) => tx.length(), + } + } +} + +impl TxEssence { + /// Compute the signing hash. + pub(crate) fn signing_hash(&self) -> B256 { + keccak(self.signing_data()).into() + } + + fn signing_data(&self) -> Bytes { + let mut buf = BytesMut::new(); + match self { + TxEssence::Legacy(tx) => tx.encode_signing(&mut buf), + TxEssence::Eip2930(tx) => { + buf.put_u8(0x01); + tx.encode(&mut buf); + } + TxEssence::Eip1559(tx) => { + buf.put_u8(0x02); + tx.encode(&mut buf); + } + }; + + buf.freeze().into() + } +} + +/// Whether or not the transaction is a contract creation. +/// This cannot be an [Option] as options get RLP encoded into lists. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] +pub enum TransactionKind { + /// A contract creation transaction. + #[default] + Create, + /// The 160-bit address of the transaction call's recipient. + Call(B160), +} + +impl From for Option { + fn from(value: TransactionKind) -> Self { + match value { + TransactionKind::Create => None, + TransactionKind::Call(addr) => Some(addr), + } + } +} + +impl Encodable for TransactionKind { + fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { + match self { + TransactionKind::Call(addr) => addr.encode(out), + TransactionKind::Create => out.put_u8(EMPTY_STRING_CODE), + } + } + fn length(&self) -> usize { + match self { + TransactionKind::Call(addr) => addr.length(), + TransactionKind::Create => 1, + } + } +} + +/// A raw transaction including the signature. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct Transaction { + /// Transaction essence to be signed. + pub essence: TxEssence, + /// Signature of the transaction essence. + pub signature: TxSignature, +} + +impl Encodable for Transaction { + fn encode(&self, out: &mut dyn BufMut) { + // prepend the EIP-2718 transaction type + match self.tx_type() { + 0 => {} + tx_type => out.put_u8(tx_type), + } + + // join the essence lists and the signature list into one + // this allows to reuse as much of the generated RLP code as possible + rlp_join_lists(&self.essence, &self.signature, out); + } +} + +impl Transaction { + /// Calculates the transaction hash. + pub fn hash(&self) -> TxHash { + keccak(self.to_rlp()).into() + } + + pub fn tx_type(&self) -> u8 { + match &self.essence { + TxEssence::Legacy(_) => 0x00, + TxEssence::Eip2930(_) => 0x01, + TxEssence::Eip1559(_) => 0x02, + } + } + pub fn gas_limit(&self) -> U256 { + match &self.essence { + TxEssence::Legacy(tx) => tx.gas_limit, + TxEssence::Eip2930(tx) => tx.gas_limit, + TxEssence::Eip1559(tx) => tx.gas_limit, + } + } + pub fn to(&self) -> Option { + match &self.essence { + TxEssence::Legacy(tx) => tx.to.into(), + TxEssence::Eip2930(tx) => tx.to.into(), + TxEssence::Eip1559(tx) => tx.to.into(), + } + } +} + +/// Joins two RLP-encoded lists into one lists and outputs the result into the `out` +/// buffer. +fn rlp_join_lists(a: impl Encodable, b: impl Encodable, out: &mut dyn alloy_rlp::BufMut) { + let mut a_buf = Vec::new(); + a.encode(&mut a_buf); + let header = alloy_rlp::Header::decode(&mut &a_buf[..]).unwrap(); + if !header.list { + panic!("`a` not a list"); + } + let a_head_length = header.length(); + let a_payload_length = a_buf.len() - a_head_length; + + let mut b_buf = Vec::new(); + b.encode(&mut b_buf); + let header = alloy_rlp::Header::decode(&mut &b_buf[..]).unwrap(); + if !header.list { + panic!("`b` not a list"); + } + let b_head_length = header.length(); + let b_payload_length = b_buf.len() - b_head_length; + + alloy_rlp::Header { + list: true, + payload_length: a_payload_length + b_payload_length, + } + .encode(out); + out.put_slice(&a_buf[a_head_length..]); // skip the header + out.put_slice(&b_buf[b_head_length..]); // skip the header +} + +#[cfg(test)] +mod tests { + use serde_json::json; + + use super::*; + + #[test] + fn legacy() { + // Tx: 0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060 + let tx = json!({ + "Legacy": { + "nonce": 0, + "gas_price": "0x2d79883d2000", + "gas_limit": "0x5208", + "to": { "Call": "0x5df9b87991262f6ba471f09758cde1c0fc1de734" }, + "value": "0x7a69", + "data": "0x" + } + }); + let essence: TxEssence = serde_json::from_value(tx).unwrap(); + println!("signing data: {}", essence.signing_data()); + + let signature: TxSignature = serde_json::from_value(json!({ + "v": 28, + "r": "0x88ff6cf0fefd94db46111149ae4bfc179e9b94721fffd821d38d16464b3f71d0", + "s": "0x45e0aff800961cfce805daef7016b9b675c137a6a41a548f7b60a3484c06a33a" + })) + .unwrap(); + let transaction = Transaction { essence, signature }; + + // verify that bincode serialization works + let _: Transaction = + bincode::deserialize(&bincode::serialize(&transaction).unwrap()).unwrap(); + + assert_eq!( + "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060", + transaction.hash().to_string() + ); + let recovered = transaction.recover_from().unwrap(); + assert_eq!( + "0xa1e4380a3b1f749673e270229993ee55f35663b4", + recovered.to_string() + ); + } + + #[test] + fn eip155() { + // Tx: 0x4540eb9c46b1654c26353ac3c65e56451f711926982ce1b02f15c50e7459caf7 + let tx = json!({ + "Legacy": { + "nonce": 537760, + "gas_price": "0x03c49bfa04", + "gas_limit": "0x019a28", + "to": { "Call": "0xf0ee707731d1be239f9f482e1b2ea5384c0c426f" }, + "value": "0x06df842eaa9fb800", + "data": "0x", + "chain_id": 1 + } + }); + let essence: TxEssence = serde_json::from_value(tx).unwrap(); + println!("signing data: {}", essence.signing_data()); + + let signature: TxSignature = serde_json::from_value(json!({ + "v": 38, + "r": "0xcadd790a37b78e5613c8cf44dc3002e3d7f06a5325d045963c708efe3f9fdf7a", + "s": "0x1f63adb9a2d5e020c6aa0ff64695e25d7d9a780ed8471abe716d2dc0bf7d4259" + })) + .unwrap(); + let transaction = Transaction { essence, signature }; + + // verify that bincode serialization works + let _: Transaction = + bincode::deserialize(&bincode::serialize(&transaction).unwrap()).unwrap(); + + assert_eq!( + "0x4540eb9c46b1654c26353ac3c65e56451f711926982ce1b02f15c50e7459caf7", + transaction.hash().to_string() + ); + let recovered = transaction.recover_from().unwrap(); + assert_eq!( + "0x974caa59e49682cda0ad2bbe82983419a2ecc400", + recovered.to_string() + ); + } + + #[test] + fn eip2930() { + // Tx: 0xbe4ef1a2244e99b1ef518aec10763b61360be22e3b649dcdf804103719b1faef + let tx = json!({ + "Eip2930": { + "chain_id": 1, + "nonce": 93847, + "gas_price": "0xf46a5a9d8", + "gas_limit": "0x21670", + "to": { "Call": "0xc11ce44147c9f6149fbe54adb0588523c38718d7" }, + "value": "0x10d1471", + "data": "0x050000000002b8809aef26206090eafd7d5688615d48197d1c5ce09be6c30a33be4c861dee44d13f6dd33c2e8c5cad7e2725f88a8f0000000002d67ca5eb0e5fb6", + "access_list": [ + { + "address": "0xd6e64961ba13ba42858ad8a74ed9a9b051a4957d", + "storage_keys": [ + "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0b4b38935f88a7bddbe6be76893de2a04640a55799d6160729a82349aff1ffae", + "0xc59ee2ee2ba599569b2b1f06989dadbec5ee157c8facfe64f36a3e33c2b9d1bf" + ] + }, + { + "address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + "storage_keys": [ + "0x7635825e4f8dfeb20367f8742c8aac958a66caa001d982b3a864dcc84167be80", + "0x42555691810bdf8f236c31de88d2cc9407a8ff86cd230ba3b7029254168df92a", + "0x29ece5a5f4f3e7751868475502ab752b5f5fa09010960779bf7204deb72f5dde" + ] + }, + { + "address": "0x4c861dee44d13f6dd33c2e8c5cad7e2725f88a8f", + "storage_keys": [ + "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000007" + ] + }, + { + "address": "0x90eafd7d5688615d48197d1c5ce09be6c30a33be", + "storage_keys": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x9c04773acff4c5c42718bd0120c72761f458e43068a3961eb935577d1ed4effb", + "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000004" + ] + } + ] + } + }); + let essence: TxEssence = serde_json::from_value(tx).unwrap(); + println!("signing data: {}", essence.signing_data()); + + let signature: TxSignature = serde_json::from_value(json!({ + "v": 1, + "r": "0xf86aa2dfde99b0d6a41741e96cfcdee0c6271febd63be4056911db19ae347e66", + "s": "0x601deefbc4835cb15aa1af84af6436fc692dea3428d53e7ff3d34a314cefe7fc" + })) + .unwrap(); + let transaction = Transaction { essence, signature }; + + // verify that bincode serialization works + let _: Transaction = + bincode::deserialize(&bincode::serialize(&transaction).unwrap()).unwrap(); + + assert_eq!( + "0xbe4ef1a2244e99b1ef518aec10763b61360be22e3b649dcdf804103719b1faef", + transaction.hash().to_string() + ); + let recovered = transaction.recover_from().unwrap(); + assert_eq!( + "0x79b7a69d90c82e014bf0315e164208119b510fa0", + recovered.to_string() + ); + } + + #[test] + fn eip1559() { + // Tx: 0x2bcdc03343ca9c050f8dfd3c87f32db718c762ae889f56762d8d8bdb7c5d69ff + let tx = json!({ + "Eip1559": { + "chain_id": 1, + "nonce": 32, + "max_priority_fee_per_gas": "0x3b9aca00", + "max_fee_per_gas": "0x89d5f3200", + "gas_limit": "0x5b04", + "to": { "Call": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43" }, + "value": "0x1dd1f234f68cde2", + "data": "0x", + "access_list": [] + } + }); + let essence: TxEssence = serde_json::from_value(tx).unwrap(); + println!("signing data: {}", essence.signing_data()); + + let signature: TxSignature = serde_json::from_value(json!({ + "v": 0, + "r": "0x2bdf47562da5f2a09f09cce70aed35ec9ac62f5377512b6a04cc427e0fda1f4d", + "s": "0x28f9311b515a5f17aa3ad5ea8bafaecfb0958801f01ca11fd593097b5087121b" + })) + .unwrap(); + let transaction = Transaction { essence, signature }; + + // verify that bincode serialization works + let _: Transaction = + bincode::deserialize(&bincode::serialize(&transaction).unwrap()).unwrap(); + + assert_eq!( + "0x2bcdc03343ca9c050f8dfd3c87f32db718c762ae889f56762d8d8bdb7c5d69ff", + transaction.hash().to_string() + ); + let recovered = transaction.recover_from().unwrap(); + assert_eq!( + "0x4b9f4114d50e7907bff87728a060ce8d53bf4cf7", + recovered.to_string() + ); + } +} diff --git a/primitives/src/trie/account.rs b/primitives/src/trie/account.rs new file mode 100644 index 000000000..eca1d4868 --- /dev/null +++ b/primitives/src/trie/account.rs @@ -0,0 +1,43 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use alloy_primitives::{TxNumber, B256, U256}; +use alloy_rlp_derive::{RlpDecodable, RlpEncodable}; +use serde::{Deserialize, Serialize}; + +use crate::{keccak::KECCAK_EMPTY, trie::EMPTY_ROOT}; + +/// An Ethereum account as represented in the trie. +#[derive(Debug, Clone, Serialize, Deserialize, RlpEncodable, RlpDecodable)] +pub struct StateAccount { + /// Account nonce. + pub nonce: TxNumber, + /// Account balance. + pub balance: U256, + /// Account's storage root. + pub storage_root: B256, + /// Hash of the account's bytecode. + pub code_hash: B256, +} + +impl Default for StateAccount { + fn default() -> Self { + Self { + nonce: 0, + balance: U256::ZERO, + storage_root: EMPTY_ROOT, + code_hash: KECCAK_EMPTY, + } + } +} diff --git a/primitives/src/trie/mod.rs b/primitives/src/trie/mod.rs new file mode 100644 index 000000000..048bc3c1d --- /dev/null +++ b/primitives/src/trie/mod.rs @@ -0,0 +1,24 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub mod account; +pub mod mpt; + +use alloy_primitives::{b256, B256}; + +pub use self::{account::StateAccount, mpt::*}; + +/// Root hash of an empty trie. +pub const EMPTY_ROOT: B256 = + b256!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); diff --git a/primitives/src/trie/mpt.rs b/primitives/src/trie/mpt.rs new file mode 100644 index 000000000..cdaca27f3 --- /dev/null +++ b/primitives/src/trie/mpt.rs @@ -0,0 +1,786 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +extern crate alloc; + +use alloc::boxed::Box; +use core::{cell::RefCell, fmt::Debug, iter, mem}; + +use alloy_primitives::B256; +use alloy_rlp::Encodable; +use anyhow::{bail, Context, Result}; +use rlp::{Decodable, DecoderError, Prototype, Rlp}; +use serde::{Deserialize, Serialize}; + +use crate::{keccak::keccak, trie::EMPTY_ROOT, RlpBytes}; + +/// The type and data of a node in a Merkle Patricia trie. +#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize)] +pub enum MptNodeData { + /// Empty trie node. + Null, + /// Node with at most 16 children and a value. + Branch([Box; 16], Vec), // todo: take this away + /// Leaf node with a value. + Leaf(Vec, Vec), + /// Node with exactly one child. + Extension(Vec, Box), + /// Reference to a node by its hash. + Digest(B256), +} + +/// A node in a Merkle Patricia trie. +#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize)] +pub struct MptNode { + data: MptNodeData, + #[serde(skip)] + cached_reference: RefCell>, +} + +/// Reference of one node inside another node. +#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize)] +pub enum MptNodeReference { + /// Short encodings (less than 32 bytes). + Bytes(Vec), + /// Keccak hash of long encodings (not less than 32 bytes). + Digest(B256), +} + +impl From for MptNodeReference { + fn from(digest: B256) -> Self { + Self::Digest(digest) + } +} + +impl Default for MptNode { + fn default() -> Self { + Self { + data: MptNodeData::Null, + cached_reference: RefCell::new(None), + } + } +} + +impl From for MptNode { + fn from(value: MptNodeData) -> Self { + Self { + data: value, + cached_reference: RefCell::new(None), + } + } +} + +impl Encodable for MptNode { + /// Encode the node into the `out` buffer. + fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { + match &self.data { + MptNodeData::Null => { + out.put_u8(alloy_rlp::EMPTY_STRING_CODE); + } + MptNodeData::Branch(nodes, value) => { + let mut payload_length = 0; + for node in nodes { + payload_length += node.pointer_length(); + } + payload_length += value.as_slice().length(); + alloy_rlp::Header { + list: true, + payload_length, + } + .encode(out); + for node in nodes { + node.pointer_encode(out); + } + value.as_slice().encode(out); + } + MptNodeData::Leaf(prefix, value) => { + let payload_length = prefix.as_slice().length() + value.as_slice().length(); + alloy_rlp::Header { + list: true, + payload_length, + } + .encode(out); + prefix.as_slice().encode(out); + value.as_slice().encode(out); + } + MptNodeData::Extension(prefix, node) => { + let payload_length = prefix.as_slice().length() + node.pointer_length(); + alloy_rlp::Header { + list: true, + payload_length, + } + .encode(out); + prefix.as_slice().encode(out); + node.pointer_encode(out); + } + MptNodeData::Digest(digest) => { + digest.encode(out); + } + } + } +} + +// TODO: migrate to alloy_rlp +impl Decodable for MptNode { + fn decode(rlp: &Rlp) -> Result { + match rlp.prototype()? { + Prototype::Null | Prototype::Data(0) => Ok(MptNodeData::Null.into()), + Prototype::List(2) => { + let path: Vec = rlp.val_at(0)?; + let prefix = path[0]; + if (prefix & (2 << 4)) == 0 { + let node: MptNode = Decodable::decode(&rlp.at(1)?)?; + Ok(MptNodeData::Extension(path, Box::new(node)).into()) + } else { + Ok(MptNodeData::Leaf(path, rlp.val_at(1)?).into()) + } + } + Prototype::List(17) => { + let mut node_list = Vec::with_capacity(16); + for node_rlp in rlp.iter().take(16) { + node_list.push(Box::new(Decodable::decode(&node_rlp)?)); + } + let value = rlp.val_at(16)?; + Ok(MptNodeData::Branch(node_list.try_into().unwrap(), value).into()) + } + Prototype::Data(32) => { + let bytes: Vec = rlp.as_val()?; + Ok(MptNodeData::Digest(B256::from_slice(&bytes)).into()) + } + _ => Err(DecoderError::Custom("Unknown MPT Node format!")), + } + } +} + +impl MptNode { + /// Clears the trie, replacing it with [MptNodeData::NULL]. + pub fn clear(&mut self) { + self.data = MptNodeData::Null; + self.invalidate_ref_cache(); + } + + /// Decodes an RLP-encoded [MptNode]. + pub fn decode(bytes: impl AsRef<[u8]>) -> Result { + rlp::decode(bytes.as_ref()).context("rlp decode failed") + } + + /// Returns the type and data of the node. + pub fn as_data(&self) -> &MptNodeData { + &self.data + } + + /// Returns the 256-bit hash of the node. + pub fn hash(&self) -> B256 { + match self.data { + MptNodeData::Null => EMPTY_ROOT, + _ => match self.pointer() { + MptNodeReference::Digest(digest) => digest, + MptNodeReference::Bytes(bytes) => keccak(bytes).into(), + }, + } + } + + /// Returns the pointer of this node when referenced inside another node. + pub fn pointer(&self) -> MptNodeReference { + self.cached_reference + .borrow_mut() + .get_or_insert_with(|| self.calc_pointer()) + .clone() + } + + /// Encodes the pointer for this node into the `out` buffer. + fn pointer_encode(&self, out: &mut dyn alloy_rlp::BufMut) { + match self + .cached_reference + .borrow_mut() + .get_or_insert_with(|| self.calc_pointer()) + { + MptNodeReference::Bytes(bytes) => out.put_slice(bytes), + MptNodeReference::Digest(digest) => digest.encode(out), + } + } + + /// Returns the length of the encoded pointer for this node. + fn pointer_length(&self) -> usize { + match self + .cached_reference + .borrow_mut() + .get_or_insert_with(|| self.calc_pointer()) + { + MptNodeReference::Bytes(bytes) => bytes.len(), + MptNodeReference::Digest(digest) => digest.length(), + } + } + + fn calc_pointer(&self) -> MptNodeReference { + match &self.data { + MptNodeData::Null => MptNodeReference::Bytes(vec![alloy_rlp::EMPTY_STRING_CODE]), + MptNodeData::Digest(digest) => MptNodeReference::Digest(*digest), + _ => { + let encoded = self.to_rlp(); + if encoded.len() < 32 { + MptNodeReference::Bytes(encoded) + } else { + MptNodeReference::Digest(keccak(encoded).into()) + } + } + } + } + + /// Returns whether the trie is empty. + pub fn is_null(&self) -> bool { + matches!(&self.data, MptNodeData::Null) + } + + /// Returns whether the node is resolved or is the reference of another node. + pub fn is_resolved(&self) -> bool { + !matches!(&self.data, MptNodeData::Digest(_)) + } + + /// Returns the nibbles corresponding to the node's prefix. + pub fn nibs(&self) -> Vec { + match &self.data { + MptNodeData::Null | MptNodeData::Branch(_, _) | MptNodeData::Digest(_) => Vec::new(), + MptNodeData::Leaf(prefix, _) | MptNodeData::Extension(prefix, _) => { + let extension = prefix[0]; + // the first bit of the first nibble denotes the parity + let is_odd = extension & (1 << 4) != 0; + + let mut result = Vec::with_capacity(2 * prefix.len()); + // for odd lengths, the second nibble contains the first element + if is_odd { + result.push(extension & 0xf); + } + for nib in &prefix[1..] { + result.push(nib >> 4); + result.push(nib & 0xf); + } + result + } + } + } + + /// Returns the value of this node. + pub fn value(&self) -> Option<&[u8]> { + match &self.data { + MptNodeData::Null | MptNodeData::Extension(_, _) | MptNodeData::Digest(_) => None, + MptNodeData::Branch(_, value) | MptNodeData::Leaf(_, value) => Some(value), + } + } + + pub fn rlp_lookup(&self, trie_index: &[u8]) -> Result> { + match self.lookup(trie_index) { + Some(mut bytes) => Ok(Some(T::decode(&mut bytes).context("RLP decode failed")?)), + None => Ok(None), + } + } + + fn lookup_internal(&self, key_nibs: &[u8]) -> Result> { + match &self.data { + MptNodeData::Null => Ok(None), + MptNodeData::Branch(nodes, _) => { + if key_nibs.is_empty() { + Ok(self.value()) + } else { + nodes + .get(key_nibs[0] as usize) + .unwrap() + .lookup_internal(&key_nibs[1..]) + } + } + MptNodeData::Leaf(_, _) => { + if self.nibs() == key_nibs { + Ok(self.value()) + } else { + Ok(None) + } + } + MptNodeData::Extension(_, target) => { + let ext_nibs = self.nibs(); + let ext_len = ext_nibs.len(); + if key_nibs[..ext_len] != ext_nibs { + Ok(None) + } else { + target.lookup_internal(&key_nibs[ext_len..]) + } + } + MptNodeData::Digest(_) => bail!("Cannot descend pointer!"), + } + } + + pub fn lookup(&self, trie_index: &[u8]) -> Option<&[u8]> { + self.lookup_internal(&to_nibs(trie_index)) + .expect("Could not lookup value") + } + + fn invalidate_ref_cache(&mut self) { + self.cached_reference.borrow_mut().take(); + } + + fn delete_internal(&mut self, key_nibs: &[u8]) -> Result { + let self_nibs = self.nibs(); + let value_deleted = match &mut self.data { + MptNodeData::Null => false, + MptNodeData::Branch(children, _) => { + // note: we don't handle storing values at branches (key_nibs cannot be empty) + let child = children.get_mut(key_nibs[0] as usize).unwrap(); + if !child.delete_internal(&key_nibs[1..])? { + return Ok(false); + } + let orphan_index = children + .iter() + .position(|n| !n.is_null()) + .expect("Deleted last element of a branch!"); + let mut remaining_children: Vec<_> = + children.iter_mut().filter(|n| !n.is_null()).collect(); + if remaining_children.len() == 1 { + // convert to extension + let mut orphan = mem::take(remaining_children[0]); + + let self_nibs = vec![orphan_index as u8]; + let orphan_nibs = orphan.nibs(); + match &mut orphan.data { + MptNodeData::Null => { + // Dead-end, delete own data + self.data = MptNodeData::Null; + } + MptNodeData::Branch(_, _) => { + self.data = + MptNodeData::Extension(to_prefix(&self_nibs, false), orphan); + } + MptNodeData::Leaf(_, orphan_data) => { + // Replace own data with extended-prefix leaf + let new_nibs = [self_nibs, orphan_nibs].concat(); + self.data = MptNodeData::Leaf( + to_prefix(&new_nibs, true), + mem::take(orphan_data), + ); + } + MptNodeData::Extension(_, orphan_target) => { + // Extend own prefix with child's + let new_nibs = [self_nibs, orphan_nibs].concat(); + self.data = MptNodeData::Extension( + to_prefix(&new_nibs, false), + mem::take(orphan_target), + ); + } + MptNodeData::Digest(_) => { + self.data = + MptNodeData::Extension(to_prefix(&self_nibs, false), orphan); + } + } + } + true + } + MptNodeData::Leaf(_, _) => { + if self_nibs.len() != key_nibs.len() { + bail!( + "Unequal deletion key-lengths {}/{}", + self_nibs.len(), + key_nibs.len() + ); + } + // Our traversal has ended + if self_nibs == key_nibs { + self.data = MptNodeData::Null; + true + } else { + false + } + } + MptNodeData::Extension(_, child) => { + let ext_len = self_nibs.len(); + if key_nibs[..ext_len] != self_nibs { + return Ok(false); + } + let value_deleted = child.delete_internal(&key_nibs[ext_len..])?; + if value_deleted { + // Potentially collapse this branch + let child_nibs = child.nibs(); + match &mut child.data { + MptNodeData::Branch(_, _) | MptNodeData::Digest(_) => {} + MptNodeData::Null => { + // Dead-end, delete own data + self.data = MptNodeData::Null; + } + MptNodeData::Leaf(_, child_value) => { + // Replace own data with extended-prefix leaf + let new_nibs = [self_nibs, child_nibs].concat(); + self.data = MptNodeData::Leaf( + to_prefix(&new_nibs, true), + mem::take(child_value), + ); + } + MptNodeData::Extension(_, child_target) => { + // Extend own prefix with child's + let new_nibs = [self_nibs, child_nibs].concat(); + self.data = MptNodeData::Extension( + to_prefix(&new_nibs, false), + mem::take(child_target), + ); + } + } + } + value_deleted + } + MptNodeData::Digest(_) => bail!("Hit a pointer during deletion operation!"), + }; + + if value_deleted { + // invalidate the cache + self.invalidate_ref_cache(); + } + + Ok(value_deleted) + } + + pub fn delete(&mut self, trie_index: &[u8]) { + self.delete_internal(&to_nibs(trie_index)) + .expect("Could not delete value"); + } + + fn update_internal(&mut self, key_nibs: &[u8], value: Vec) -> Result { + let self_nibs = self.nibs(); + let value_updated = match &mut self.data { + MptNodeData::Null => { + self.data = MptNodeData::Leaf(to_prefix(key_nibs, true), value); + true + } + MptNodeData::Branch(children, stored_value) => { + if key_nibs.is_empty() { + // replace the branch data + *stored_value = value; + true + } else { + children + .get_mut(key_nibs[0] as usize) + .unwrap() + .update_internal(&key_nibs[1..], value)? + } + } + MptNodeData::Leaf(_, stored_value) => { + let cpl = lcp(&self_nibs, key_nibs); + if cpl == self_nibs.len() && cpl == key_nibs.len() { + // replace leaf data + let different_value = stored_value != &value; + if different_value { + *stored_value = value; + } + different_value + } else { + let split_point = cpl + 1; + // create a branch with two children + let mut new_branch_children: [Box; 16] = Default::default(); + let mut new_branch_value: Vec = Vec::new(); + // Insert existing leaf data + if cpl == self_nibs.len() { + new_branch_value = mem::take(stored_value); + } else { + new_branch_children[self_nibs[cpl] as usize] = Box::new( + MptNodeData::Leaf( + to_prefix(&self_nibs[split_point..], true), + mem::take(stored_value), + ) + .into(), + ); + } + if cpl == key_nibs.len() { + new_branch_value = value; + } else { + new_branch_children[key_nibs[cpl] as usize] = Box::new( + MptNodeData::Leaf(to_prefix(&key_nibs[split_point..], true), value) + .into(), + ); + } + let branch = MptNodeData::Branch(new_branch_children, new_branch_value); + + if cpl > 0 { + // Create parent extension for new branch + self.data = MptNodeData::Extension( + to_prefix(&self_nibs[..cpl], false), + Box::new(branch.into()), + ); + } else { + self.data = branch; + } + true + } + } + MptNodeData::Extension(_, existing_child) => { + let cpl = lcp(&self_nibs, key_nibs); + if cpl == self_nibs.len() { + // traverse down for update + existing_child.update_internal(&key_nibs[cpl..], value)? + } else { + let split_point = cpl + 1; + // create a branch with two children + let mut new_branch_children: [Box; 16] = Default::default(); + let mut new_branch_value: Vec = Vec::new(); + // Insert existing extension + new_branch_children[self_nibs[cpl] as usize] = if self_nibs.len() > split_point + { + Box::new( + MptNodeData::Extension( + to_prefix(&self_nibs[split_point..], false), + mem::take(existing_child), + ) + .into(), + ) + } else { + mem::take(existing_child) + }; + if cpl == key_nibs.len() { + new_branch_value = value; + } else { + new_branch_children[key_nibs[cpl] as usize] = Box::new( + MptNodeData::Leaf(to_prefix(&key_nibs[split_point..], true), value) + .into(), + ); + } + let branch = MptNodeData::Branch(new_branch_children, new_branch_value); + + if cpl > 0 { + // Create parent extension for new branch + self.data = MptNodeData::Extension( + to_prefix(&self_nibs[..cpl], false), + Box::new(branch.into()), + ); + } else { + self.data = branch; + } + true + } + } + MptNodeData::Digest(_) => bail!("Hit a pointer during update operation!"), + }; + + if value_updated { + // invalidate the cache + self.invalidate_ref_cache(); + } + + Ok(value_updated) + } + + pub fn rlp_update(&mut self, key: &[u8], value: impl Encodable) { + self.update(key, value.to_rlp()); + } + + pub fn update(&mut self, trie_index: &[u8], value: Vec) { + self.update_internal(&to_nibs(trie_index), value) + .expect("Could not update value"); + } + + /// Formats the trie as string list, where each line corresponds to a trie leaf. + pub fn rlp_debug(&self) -> Vec { + let nibs: String = self.nibs().iter().map(|n| format!("{:x}", n)).collect(); + match self.as_data() { + MptNodeData::Null => vec![format!("{:?}", MptNodeData::Null)], + MptNodeData::Branch(nodes, data) => { + let c = nodes.iter().enumerate().flat_map(|(i, n)| { + n.rlp_debug::() + .into_iter() + .map(move |s| format!("{:x} {}", i, s)) + }); + if data.is_empty() { + c.collect() + } else { + iter::once(format!("-> [{:?}]", T::decode(&mut &data[..]).unwrap())) + .chain(c) + .collect() + } + } + MptNodeData::Leaf(_, data) => { + vec![format!( + "{} -> [{:?}]", + nibs, + T::decode(&mut &data[..]).unwrap() + )] + } + MptNodeData::Extension(_, node) => node + .rlp_debug::() + .into_iter() + .map(|s| format!("{} {}", nibs, s)) + .collect(), + MptNodeData::Digest(digest) => vec![format!("#{:#}", digest)], + } + } +} + +fn lcp(a: &[u8], b: &[u8]) -> usize { + let mut res = 0; + while res < a.len() && res < b.len() { + if a[res] != b[res] { + break; + } + res += 1 + } + res +} + +pub fn to_nibs(slice: &[u8]) -> Vec { + let mut result = Vec::with_capacity(2 * slice.len()); + for nib in slice { + result.push(nib >> 4); + result.push(nib & 0xf); + } + result +} + +pub fn to_prefix(nibs: &[u8], is_leaf: bool) -> Vec { + let is_odd_nib_len = nibs.len() & 1 == 1; + let prefix = ((is_odd_nib_len as u8) + ((is_leaf as u8) << 1)) << 4; + let mut result = vec![prefix]; + for (i, nib) in nibs.iter().enumerate() { + let is_odd_nib_index = i & 1 == 1; + if is_odd_nib_len ^ is_odd_nib_index { + // append to last byte + *result.last_mut().unwrap() |= nib; + } else { + // append new byte + result.push(nib << 4); + } + } + result +} + +#[cfg(test)] +mod tests { + use hex_literal::hex; + + use super::*; + + #[test] + pub fn test_trie_pointer_no_keccak() { + let cases = [ + ("do", "verb"), + ("dog", "puppy"), + ("doge", "coin"), + ("horse", "stallion"), + ]; + for (k, v) in cases { + let node: MptNode = + MptNodeData::Leaf(k.as_bytes().to_vec(), v.as_bytes().to_vec()).into(); + assert!( + matches!(node.pointer(),MptNodeReference::Bytes(bytes) if bytes == node.to_rlp().to_vec()) + ); + } + } + + #[test] + pub fn test_lcp() { + let cases = [ + (vec![0xa, 0xb], vec![0xa, 0xc], 1), + (vec![0xa, 0xb], vec![0xa, 0xb], 2), + (vec![0xa, 0xb], vec![0xa, 0xb, 0xc], 2), + (vec![0xa, 0xb, 0xc], vec![0xa, 0xb, 0xc], 3), + (vec![0xa, 0xb, 0xc, 0xd], vec![0xa, 0xb, 0xc, 0xd], 4), + ]; + for (a, b, cpl) in cases { + assert_eq!(lcp(&a, &b), cpl) + } + } + + #[test] + pub fn test_empty() { + let trie = MptNode::default(); + let expected = hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); + assert_eq!(expected, trie.hash().0); + + // try RLP roundtrip + let decoded = MptNode::decode(trie.to_rlp()).unwrap(); + assert_eq!(trie.hash(), decoded.hash()); + } + + #[test] + pub fn test_tiny() { + let mut trie = MptNode::default(); + trie.update(b"dog", b"puppy".to_vec()); + + let expected = hex!("ed6e08740e4a267eca9d4740f71f573e9aabbcc739b16a2fa6c1baed5ec21278"); + assert_eq!(expected, trie.hash().0); + + // try RLP roundtrip + let decoded = MptNode::decode(trie.to_rlp()).unwrap(); + assert_eq!(trie.hash(), decoded.hash()); + } + + #[test] + pub fn test_update_branch_value() { + let mut trie = MptNode::default(); + let vals = [("do", "verb"), ("dog", "puppy")]; + for (key, value) in &vals { + trie.update(key.as_bytes(), value.as_bytes().to_vec()); + } + + let expected = hex!("779db3986dd4f38416bfde49750ef7b13c6ecb3e2221620bcad9267e94604d36"); + assert_eq!(expected, trie.hash().0); + + // try RLP roundtrip + let decoded = MptNode::decode(trie.to_rlp()).unwrap(); + assert_eq!(trie.hash(), decoded.hash()); + } + + #[test] + pub fn test_update() { + let mut trie = MptNode::default(); + let vals = vec![ + ("doe", "reindeer"), + ("dog", "puppy"), + ("dogglesworth", "cat"), + ]; + for (key, value) in &vals { + trie.update(key.as_bytes(), value.as_bytes().to_vec()); + } + let expected = hex!("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3"); + assert_eq!(expected, trie.hash().0); + + for (key, value) in &vals { + assert_eq!(trie.lookup(key.as_bytes()), Some(value.as_bytes())); + } + + // try RLP roundtrip + let decoded = MptNode::decode(trie.to_rlp()).unwrap(); + assert_eq!(trie.hash(), decoded.hash()); + } + + #[test] + pub fn test_delete() { + let mut trie = MptNode::default(); + let vals = vec![ + ("do", "verb"), + ("ether", "wookiedoo"), + ("horse", "stallion"), + ("shaman", "horse"), + ("doge", "coin"), + ("ether", ""), + ("dog", "puppy"), + ("shaman", ""), + ]; + for (key, value) in vals { + if value.is_empty() { + trie.delete(key.as_bytes()); + } else { + trie.update(key.as_bytes(), value.as_bytes().to_vec()); + } + } + + let expected = hex!("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84"); + assert_eq!(expected, trie.hash().0); + + // try RLP roundtrip + let decoded = MptNode::decode(trie.to_rlp()).unwrap(); + assert_eq!(trie.hash(), decoded.hash()); + } +} diff --git a/primitives/src/withdrawal.rs b/primitives/src/withdrawal.rs new file mode 100644 index 000000000..f71147ab7 --- /dev/null +++ b/primitives/src/withdrawal.rs @@ -0,0 +1,30 @@ +// Copyright 2023 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use alloy_primitives::B160; +use alloy_rlp_derive::RlpEncodable; +use serde::{Deserialize, Serialize}; + +/// A validator withdrawal from the consensus layer ([EIP-4895](https://eips.ethereum.org/EIPS/eip-4895)). +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, RlpEncodable)] +pub struct Withdrawal { + /// Monotonically increasing identifier assigned by consensus layer. + pub index: u64, + /// Index of validator associated with withdrawal. + pub validator_index: u64, + /// Target address for withdrawn ether. + pub address: B160, + /// Value of the withdrawal in gwei. + pub amount: u64, +} diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 000000000..bcfc7fa31 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2023-03-06" +components = [ "rustfmt", "rust-src" ] +profile = "minimal" diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 000000000..e5dee7203 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,5 @@ +comment_width = 90 +wrap_comments = true +normalize_comments = true +group_imports = "StdExternalCrate" +imports_granularity = "Crate"