diff --git a/Cargo.lock b/Cargo.lock index 55ce62b..7af1efd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,16 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - [[package]] name = "addchain" version = "0.2.0" @@ -38,17 +28,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - [[package]] name = "ahash" version = "0.8.12" @@ -608,7 +587,7 @@ checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" dependencies = [ "alloy-sol-macro-input", "const-hex", - "heck 0.5.0", + "heck", "indexmap 2.12.1", "proc-macro-error2", "proc-macro2", @@ -626,7 +605,7 @@ checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" dependencies = [ "const-hex", "dunce", - "heck 0.5.0", + "heck", "macro-string", "proc-macro2", "quote", @@ -707,7 +686,7 @@ dependencies = [ "rustls 0.23.35", "serde_json", "tokio", - "tokio-tungstenite 0.26.2", + "tokio-tungstenite", "tracing", "ws_stream_wasm", ] @@ -1090,12 +1069,15 @@ dependencies = [ ] [[package]] -name = "ascii-canvas" -version = "3.0.0" +name = "async-compression" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +checksum = "ee19bd99b43e3691acbad4e840420a4881cea6c0b66a208125a824f8fd53f5a1" dependencies = [ - "term", + "compression-codecs", + "compression-core", + "pin-project-lite", + "tokio", ] [[package]] @@ -1297,12 +1279,6 @@ 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.7" @@ -1321,12 +1297,6 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" -[[package]] -name = "bech32" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" - [[package]] name = "bimap" version = "0.6.3" @@ -1353,7 +1323,7 @@ dependencies = [ "clang-sys", "itertools 0.13.0", "log", - "prettyplease 0.2.37", + "prettyplease", "proc-macro2", "quote", "regex", @@ -1362,30 +1332,15 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec 0.6.3", -] - [[package]] name = "bit-set" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ - "bit-vec 0.8.0", + "bit-vec", ] -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - [[package]] name = "bit-vec" version = "0.8.0" @@ -1456,6 +1411,19 @@ dependencies = [ "constant_time_eq 0.3.1", ] +[[package]] +name = "blake3" +version = "1.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae" +dependencies = [ + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq 0.4.2", + "cpufeatures 0.3.1", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -1536,16 +1504,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "bs58" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" -dependencies = [ - "sha2", - "tinyvec", -] - [[package]] name = "bumpalo" version = "3.19.0" @@ -1593,26 +1551,6 @@ 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.13+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "c-kzg" version = "2.1.5" @@ -1720,16 +1658,6 @@ dependencies = [ "windows-link", ] -[[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 = "clang-sys" version = "1.8.1" @@ -1769,7 +1697,7 @@ version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.111", @@ -1791,62 +1719,27 @@ dependencies = [ ] [[package]] -name = "coins-bip32" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" -dependencies = [ - "bs58", - "coins-core", - "digest 0.10.7", - "hmac", - "k256", - "serde", - "sha2", - "thiserror 1.0.69", -] - -[[package]] -name = "coins-bip39" -version = "0.8.7" +name = "colorchoice" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" -dependencies = [ - "bitvec", - "coins-bip32", - "hmac", - "once_cell", - "pbkdf2 0.12.2", - "rand 0.8.5", - "sha2", - "thiserror 1.0.69", -] +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] -name = "coins-core" -version = "0.8.7" +name = "compression-codecs" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" +checksum = "98fc98460ba0ad5317075d3632b8dfc45d0be8c4a49347c2a38272019717614a" dependencies = [ - "base64 0.21.7", - "bech32", - "bs58", - "digest 0.10.7", - "generic-array 0.14.7", - "hex", - "ripemd", - "serde", - "serde_derive", - "sha2", - "sha3", - "thiserror 1.0.69", + "compression-core", + "flate2", + "memchr", ] [[package]] -name = "colorchoice" -version = "1.0.4" +name = "compression-core" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "6e8ccc4ea9f6acc32d102c0f6d471d11d913ad15f20c04de743374861fa1d414" [[package]] name = "console" @@ -1868,7 +1761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "proptest", "serde_core", ] @@ -1901,15 +1794,15 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.1.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "convert_case" @@ -1945,6 +1838,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.4.0" @@ -2049,15 +1951,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - [[package]] name = "ctrlc" version = "3.5.1" @@ -2076,7 +1969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", "fiat-crypto", "rustc_version 0.4.1", @@ -2345,16 +2238,6 @@ dependencies = [ "dirs-sys", ] -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - [[package]] name = "dirs-sys" version = "0.4.1" @@ -2367,17 +2250,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dispatch2" version = "0.3.0" @@ -2431,6 +2303,33 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "dynasm" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33dc03612f42465a8ed7f5e354bc2b79ba54cedefa81d5bd3a064f1835adaba8" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "lazy_static", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dynasmrt" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7dccc31a678058996aef614f6bd418ced384da70f284e83e2b7bf29b27b6a28" +dependencies = [ + "byteorder", + "dynasm", + "fnv", + "memmap2 0.5.10", +] + [[package]] name = "ecdsa" version = "0.16.9" @@ -2494,15 +2393,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ena" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" -dependencies = [ - "log", -] - [[package]] name = "encode_unicode" version = "1.0.0" @@ -2518,31 +2408,13 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "enr" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" -dependencies = [ - "base64 0.21.7", - "bytes", - "hex", - "k256", - "log", - "rand 0.8.5", - "rlp", - "serde", - "sha3", - "zeroize", -] - [[package]] name = "enum-as-inner" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.111", @@ -2628,28 +2500,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "eth-keystore" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" -dependencies = [ - "aes", - "ctr", - "digest 0.10.7", - "hex", - "hmac", - "pbkdf2 0.11.0", - "rand 0.8.5", - "scrypt", - "serde", - "serde_json", - "sha2", - "sha3", - "thiserror 1.0.69", - "uuid 0.8.2", -] - [[package]] name = "eth-proofs" version = "0.1.0" @@ -2660,12 +2510,16 @@ dependencies = [ "alloy-transport", "alloy-transport-ws", "base64 0.22.1", + "bincode", "clap", "dotenv", "eyre", + "fs2", "futures", "guest-executor", + "hex", "host-executor", + "libc", "primitives", "provider", "reqwest 0.12.25", @@ -2673,354 +2527,62 @@ dependencies = [ "reqwest-retry", "serde", "serde_json", + "sha2", + "tempfile", "time", "tokio", "tracing", "tracing-subscriber", "url", "zkm-build", + "zkm-cuda", + "zkm-prover", "zkm-sdk", ] [[package]] -name = "ethabi" -version = "18.0.0" +name = "eyre" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ - "ethereum-types", - "hex", + "indenter", "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror 1.0.69", - "uint", ] [[package]] -name = "ethbloom" -version = "0.13.0" +name = "fastrand" +version = "2.3.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", -] +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "ethereum-types" -version = "0.14.1" +name = "fastrlp" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "scale-info", - "uint", + "arrayvec", + "auto_impl", + "bytes", ] [[package]] -name = "ethers" -version = "2.0.14" +name = "fastrlp" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816841ea989f0c69e459af1cf23a6b0033b19a55424a1ea3a30099becdb8dec0" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" dependencies = [ - "ethers-addressbook", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-middleware", - "ethers-providers", - "ethers-signers", - "ethers-solc", + "arrayvec", + "auto_impl", + "bytes", ] [[package]] -name = "ethers-addressbook" -version = "2.0.14" +name = "ff" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5495afd16b4faa556c3bba1f21b98b4983e53c1755022377051a975c3b021759" -dependencies = [ - "ethers-core", - "once_cell", - "serde", - "serde_json", -] - -[[package]] -name = "ethers-contract" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fceafa3578c836eeb874af87abacfb041f92b4da0a78a5edd042564b8ecdaaa" -dependencies = [ - "const-hex", - "ethers-contract-abigen", - "ethers-contract-derive", - "ethers-core", - "ethers-providers", - "futures-util", - "once_cell", - "pin-project", - "serde", - "serde_json", - "thiserror 1.0.69", -] - -[[package]] -name = "ethers-contract-abigen" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04ba01fbc2331a38c429eb95d4a570166781f14290ef9fdb144278a90b5a739b" -dependencies = [ - "Inflector", - "const-hex", - "dunce", - "ethers-core", - "ethers-etherscan", - "eyre", - "prettyplease 0.2.37", - "proc-macro2", - "quote", - "regex", - "reqwest 0.11.27", - "serde", - "serde_json", - "syn 2.0.111", - "toml", - "walkdir", -] - -[[package]] -name = "ethers-contract-derive" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87689dcabc0051cde10caaade298f9e9093d65f6125c14575db3fd8c669a168f" -dependencies = [ - "Inflector", - "const-hex", - "ethers-contract-abigen", - "ethers-core", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.111", -] - -[[package]] -name = "ethers-core" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" -dependencies = [ - "arrayvec", - "bytes", - "cargo_metadata", - "chrono", - "const-hex", - "elliptic-curve", - "ethabi", - "generic-array 0.14.7", - "k256", - "num_enum", - "once_cell", - "open-fastrlp", - "rand 0.8.5", - "rlp", - "serde", - "serde_json", - "strum 0.26.3", - "syn 2.0.111", - "tempfile", - "thiserror 1.0.69", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "ethers-etherscan" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79e5973c26d4baf0ce55520bd732314328cabe53193286671b47144145b9649" -dependencies = [ - "chrono", - "ethers-core", - "reqwest 0.11.27", - "semver 1.0.27", - "serde", - "serde_json", - "thiserror 1.0.69", - "tracing", -] - -[[package]] -name = "ethers-middleware" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f9fdf09aec667c099909d91908d5eaf9be1bd0e2500ba4172c1d28bfaa43de" -dependencies = [ - "async-trait", - "auto_impl", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-providers", - "ethers-signers", - "futures-channel", - "futures-locks", - "futures-util", - "instant", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tracing", - "tracing-futures", - "url", -] - -[[package]] -name = "ethers-providers" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6434c9a33891f1effc9c75472e12666db2fa5a0fec4b29af6221680a6fe83ab2" -dependencies = [ - "async-trait", - "auto_impl", - "base64 0.21.7", - "bytes", - "const-hex", - "enr", - "ethers-core", - "futures-core", - "futures-timer", - "futures-util", - "hashers", - "http 0.2.12", - "instant", - "jsonwebtoken", - "once_cell", - "pin-project", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tokio-tungstenite 0.20.1", - "tracing", - "tracing-futures", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "ws_stream_wasm", -] - -[[package]] -name = "ethers-signers" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "228875491c782ad851773b652dd8ecac62cda8571d3bc32a5853644dd26766c2" -dependencies = [ - "async-trait", - "coins-bip32", - "coins-bip39", - "const-hex", - "elliptic-curve", - "eth-keystore", - "ethers-core", - "rand 0.8.5", - "sha2", - "thiserror 1.0.69", - "tracing", -] - -[[package]] -name = "ethers-solc" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66244a771d9163282646dbeffe0e6eca4dda4146b6498644e678ac6089b11edd" -dependencies = [ - "cfg-if", - "const-hex", - "dirs", - "dunce", - "ethers-core", - "glob", - "home", - "md-5", - "num_cpus", - "once_cell", - "path-slash", - "rayon", - "regex", - "semver 1.0.27", - "serde", - "serde_json", - "solang-parser", - "svm-rs", - "thiserror 1.0.69", - "tiny-keccak", - "tokio", - "tracing", - "walkdir", - "yansi", -] - -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[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 = "fastrlp" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ "bitvec", "rand_core 0.6.4", @@ -3061,6 +2623,16 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "filetime" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +dependencies = [ + "cfg-if", + "libc", +] + [[package]] name = "find-msvc-tools" version = "0.1.5" @@ -3207,16 +2779,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" -[[package]] -name = "futures-locks" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" -dependencies = [ - "futures-channel", - "futures-task", -] - [[package]] name = "futures-macro" version = "0.3.31" @@ -3240,16 +2802,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" -dependencies = [ - "gloo-timers", - "send_wrapper 0.4.0", -] - [[package]] name = "futures-util" version = "0.3.31" @@ -3274,21 +2826,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "gcd" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" - [[package]] name = "generic-array" version = "0.14.7" @@ -3363,18 +2900,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" -[[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.12.1" @@ -3498,50 +3023,6 @@ dependencies = [ "rayon", ] -[[package]] -name = "halo2curves" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d380afeef3f1d4d3245b76895172018cfb087d9976a7cabcd5597775b2933e07" -dependencies = [ - "blake2", - "digest 0.10.7", - "ff 0.13.1", - "group 0.13.0", - "halo2derive", - "hex", - "lazy_static", - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "pairing 0.23.0", - "pasta_curves 0.5.1", - "paste", - "rand 0.8.5", - "rand_core 0.6.4", - "rayon", - "serde", - "serde_arrays 0.1.0", - "sha2", - "static_assertions", - "subtle", - "unroll", -] - -[[package]] -name = "halo2derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb99e7492b4f5ff469d238db464131b86c2eaac814a78715acba369f64d2c76" -dependencies = [ - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -3581,21 +3062,6 @@ dependencies = [ "serde_core", ] -[[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 = "heck" version = "0.5.0" @@ -3613,9 +3079,6 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] [[package]] name = "hex-conservative" @@ -3695,15 +3158,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "home" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "host" version = "0.1.0" @@ -3983,7 +3437,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2 0.6.1", - "system-configuration 0.6.1", + "system-configuration", "tokio", "tower-service", "tracing", @@ -4131,24 +3585,6 @@ 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.3" @@ -4202,15 +3638,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array 0.14.7", -] - [[package]] name = "instant" version = "0.1.13" @@ -4343,20 +3770,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonwebtoken" -version = "8.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" -dependencies = [ - "base64 0.21.7", - "pem", - "ring 0.16.20", - "serde", - "serde_json", - "simple_asn1", -] - [[package]] name = "jubjub" version = "0.9.0" @@ -4393,7 +3806,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -4414,41 +3827,11 @@ dependencies = [ "bls12_381 0.8.0", "ff 0.13.1", "hex", - "serde_arrays 0.2.0", + "serde_arrays", "sha2", "spin 0.9.8", ] -[[package]] -name = "lalrpop" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" -dependencies = [ - "ascii-canvas", - "bit-set 0.5.3", - "ena", - "itertools 0.11.0", - "lalrpop-util", - "petgraph 0.6.5", - "regex", - "regex-syntax", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", - "walkdir", -] - -[[package]] -name = "lalrpop-util" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" -dependencies = [ - "regex-automata", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -4494,11 +3877,10 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" dependencies = [ - "bitflags 2.10.0", "libc", ] @@ -4523,12 +3905,6 @@ dependencies = [ "serde", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -4635,20 +4011,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] -name = "md-5" -version = "0.10.6" +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memfd" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +checksum = "57804b2c9b69967f1536a56f86297e367a33b19e98852ed624b84551cdbc0d90" dependencies = [ - "cfg-if", - "digest 0.10.7", + "rustix", +] + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", ] [[package]] -name = "memchr" -version = "2.7.6" +name = "memmap2" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", +] [[package]] name = "memuse" @@ -4725,12 +4118,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - [[package]] name = "multimap" version = "0.10.1" @@ -4754,12 +4141,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - [[package]] name = "nix" version = "0.30.1" @@ -4790,9 +4171,9 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" dependencies = [ "winapi", ] @@ -4839,7 +4220,6 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", - "rand 0.8.5", ] [[package]] @@ -4960,18 +4340,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" -[[package]] -name = "nums" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3c74f925fb8cfc49a8022f2afce48a0683b70f9e439885594e84c5edbf5b01" -dependencies = [ - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "rand 0.8.5", -] - [[package]] name = "nybbles" version = "0.4.6" @@ -5106,31 +4474,6 @@ dependencies = [ "revm", ] -[[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.75" @@ -5196,47 +4539,48 @@ dependencies = [ [[package]] name = "p3-air" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ "p3-field", "p3-matrix", + "tracing", ] [[package]] -name = "p3-bn254-fr" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +name = "p3-bn254" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "ff 0.13.1", - "halo2curves", "num-bigint 0.4.6", "p3-field", "p3-poseidon2", "p3-symmetric", - "rand 0.8.5", + "p3-util", + "paste", + "rand 0.10.3", "serde", ] [[package]] name = "p3-challenger" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ "p3-field", "p3-maybe-rayon", + "p3-monty-31", "p3-symmetric", "p3-util", - "serde", "tracing", ] [[package]] name = "p3-circle" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-challenger", "p3-commit", "p3-dft", @@ -5246,59 +4590,61 @@ dependencies = [ "p3-maybe-rayon", "p3-util", "serde", + "thiserror 2.0.17", "tracing", ] [[package]] name = "p3-commit" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-challenger", "p3-dft", "p3-field", + "p3-interpolation", "p3-matrix", + "p3-multilinear-util", "p3-util", "serde", ] [[package]] name = "p3-dft" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-field", "p3-matrix", "p3-maybe-rayon", "p3-util", + "spin 0.10.1", "tracing", ] [[package]] name = "p3-field" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "num-bigint 0.4.6", - "num-integer", - "num-traits", - "nums", "p3-maybe-rayon", "p3-util", - "rand 0.8.5", + "paste", + "rand 0.10.3", "serde", "tracing", ] [[package]] name = "p3-fri" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-challenger", "p3-commit", "p3-dft", @@ -5307,15 +4653,17 @@ dependencies = [ "p3-matrix", "p3-maybe-rayon", "p3-util", - "rand 0.8.5", + "rand 0.10.3", "serde", + "spin 0.10.1", + "thiserror 2.0.17", "tracing", ] [[package]] name = "p3-interpolation" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ "p3-field", "p3-matrix", @@ -5325,11 +4673,9 @@ dependencies = [ [[package]] name = "p3-keccak" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", - "p3-field", "p3-symmetric", "p3-util", "tiny-keccak", @@ -5337,174 +4683,202 @@ dependencies = [ [[package]] name = "p3-keccak-air" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ "p3-air", "p3-field", "p3-matrix", "p3-maybe-rayon", "p3-util", + "rand 0.10.3", "tracing", ] [[package]] name = "p3-koala-bear" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ + "p3-challenger", "p3-field", "p3-mds", "p3-monty-31", + "p3-poseidon1", "p3-poseidon2", "p3-symmetric", - "rand 0.8.5", - "serde", + "rand 0.10.3", ] [[package]] name = "p3-matrix" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-field", "p3-maybe-rayon", "p3-util", - "rand 0.8.5", + "rand 0.10.3", "serde", "tracing", - "transpose", ] [[package]] name = "p3-maybe-rayon" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ "rayon", ] [[package]] name = "p3-mds" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", "p3-dft", "p3-field", - "p3-matrix", "p3-symmetric", "p3-util", - "rand 0.8.5", + "rand 0.10.3", ] [[package]] name = "p3-merkle-tree" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-commit", "p3-field", "p3-matrix", "p3-maybe-rayon", "p3-symmetric", "p3-util", - "rand 0.8.5", + "rand 0.10.3", "serde", + "thiserror 2.0.17", "tracing", ] [[package]] name = "p3-mersenne-31" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "num-bigint 0.4.6", + "p3-challenger", "p3-dft", "p3-field", "p3-matrix", - "p3-maybe-rayon", "p3-mds", + "p3-poseidon1", "p3-poseidon2", "p3-symmetric", "p3-util", - "rand 0.8.5", + "paste", + "rand 0.10.3", "serde", ] [[package]] name = "p3-monty-31" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "num-bigint 0.4.6", "p3-dft", "p3-field", "p3-matrix", "p3-maybe-rayon", "p3-mds", + "p3-poseidon1", "p3-poseidon2", "p3-symmetric", "p3-util", - "rand 0.8.5", + "paste", + "rand 0.10.3", "serde", - "serde_json", + "spin 0.10.1", "tracing", - "transpose", +] + +[[package]] +name = "p3-multilinear-util" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" +dependencies = [ + "itertools 0.14.0", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "rand 0.10.3", + "serde", + "tracing", +] + +[[package]] +name = "p3-poseidon1" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" +dependencies = [ + "p3-field", + "p3-symmetric", + "rand 0.10.3", ] [[package]] name = "p3-poseidon2" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "gcd", "p3-field", "p3-mds", "p3-symmetric", - "rand 0.8.5", - "serde", + "p3-util", + "rand 0.10.3", ] [[package]] name = "p3-symmetric" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-field", + "p3-util", "serde", ] [[package]] name = "p3-uni-stark" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-air", "p3-challenger", "p3-commit", - "p3-dft", "p3-field", "p3-matrix", "p3-maybe-rayon", "p3-util", "serde", + "thiserror 2.0.17", "tracing", ] [[package]] name = "p3-util" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "lock_api", "serde", + "transpose", ] [[package]] @@ -5601,17 +4975,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "pasta_curves" version = "0.4.1" @@ -5636,10 +4999,8 @@ dependencies = [ "blake2b_simd", "ff 0.13.1", "group 0.13.0", - "hex", "lazy_static", "rand 0.8.5", - "serde", "static_assertions", "subtle", ] @@ -5650,43 +5011,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "path-slash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" - -[[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 = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac", -] - -[[package]] -name = "pem" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" -dependencies = [ - "base64 0.13.1", -] - [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -5742,37 +5066,17 @@ dependencies = [ "rustc_version 0.4.1", ] -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_macros 0.11.3", - "phf_shared 0.11.3", -] - [[package]] name = "phf" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ - "phf_macros 0.13.1", - "phf_shared 0.13.1", + "phf_macros", + "phf_shared", "serde", ] -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared 0.11.3", - "rand 0.8.5", -] - [[package]] name = "phf_generator" version = "0.13.1" @@ -5780,20 +5084,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ "fastrand", - "phf_shared 0.13.1", -] - -[[package]] -name = "phf_macros" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" -dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", - "proc-macro2", - "quote", - "syn 2.0.111", + "phf_shared", ] [[package]] @@ -5802,22 +5093,13 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ - "phf_generator 0.13.1", - "phf_shared 0.13.1", + "phf_generator", + "phf_shared", "proc-macro2", "quote", "syn 2.0.111", ] -[[package]] -name = "phf_shared" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" -dependencies = [ - "siphasher", -] - [[package]] name = "phf_shared" version = "0.13.1" @@ -5883,9 +5165,9 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] @@ -5911,23 +5193,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy", -] - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[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", + "zerocopy", ] [[package]] @@ -5956,9 +5222,6 @@ checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", "uint", ] @@ -5985,7 +5248,31 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.23.9", + "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]] @@ -6025,8 +5312,8 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" dependencies = [ - "bit-set 0.8.0", - "bit-vec 0.8.0", + "bit-set", + "bit-vec", "bitflags 2.10.0", "num-traits", "rand 0.9.2", @@ -6040,12 +5327,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.11.9", + "prost-derive 0.12.6", ] [[package]] @@ -6060,24 +5347,23 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.4.1", - "itertools 0.10.5", - "lazy_static", + "heck", + "itertools 0.11.0", "log", - "multimap 0.8.3", + "multimap", + "once_cell", "petgraph 0.6.5", - "prettyplease 0.1.25", - "prost 0.11.9", - "prost-types 0.11.9", + "prettyplease", + "prost 0.12.6", + "prost-types 0.12.6", "regex", - "syn 1.0.109", + "syn 2.0.111", "tempfile", - "which", ] [[package]] @@ -6086,13 +5372,13 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.5.0", + "heck", "itertools 0.14.0", "log", - "multimap 0.10.1", + "multimap", "once_cell", "petgraph 0.7.1", - "prettyplease 0.2.37", + "prettyplease", "prost 0.13.5", "prost-types 0.13.5", "regex", @@ -6102,15 +5388,15 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.11.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.111", ] [[package]] @@ -6128,11 +5414,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ - "prost 0.11.9", + "prost 0.12.6", ] [[package]] @@ -6152,6 +5438,7 @@ dependencies = [ "alloy-provider", "alloy-rpc-client", "alloy-transport", + "reqwest 0.12.25", "url", ] @@ -6201,7 +5488,7 @@ dependencies = [ "getrandom 0.3.4", "lru-slab", "rand 0.9.2", - "ring 0.17.14", + "ring", "rustc-hash 2.1.1", "rustls 0.23.35", "rustls-pki-types", @@ -6270,6 +5557,15 @@ dependencies = [ "serde", ] +[[package]] +name = "rand" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" +dependencies = [ + "rand_core 0.10.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -6309,6 +5605,12 @@ dependencies = [ "serde", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rand_xorshift" version = "0.4.0" @@ -6320,9 +5622,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -6455,7 +5757,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration 0.5.1", + "system-configuration", "tokio", "tokio-rustls 0.24.1", "tokio-util", @@ -7073,7 +6375,7 @@ name = "reth-zstd-compressors" version = "1.9.3" source = "git+https://github.com/paradigmxyz/reth?tag=v1.9.3#27a8c0f5a6dfb27dea84c5751776ecabdd069646" dependencies = [ - "zstd 0.13.3", + "zstd", ] [[package]] @@ -7111,7 +6413,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2c6b5e6e8dd1e28a4a60e5f46615d4ef0809111c9e63208e55b5c7058200fb0" dependencies = [ "bitvec", - "phf 0.13.1", + "phf", "revm-primitives", "serde", ] @@ -7280,21 +6582,6 @@ dependencies = [ "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 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.14" @@ -7305,7 +6592,7 @@ dependencies = [ "cfg-if", "getrandom 0.2.16", "libc", - "untrusted 0.9.0", + "untrusted", "windows-sys 0.52.0", ] @@ -7325,19 +6612,26 @@ 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" +name = "rmp" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "num-traits", +] + +[[package]] +name = "rmp-serde" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155" +dependencies = [ + "rmp", + "serde", ] [[package]] @@ -7345,9 +6639,12 @@ name = "rpc-db" version = "0.1.0" dependencies = [ "alloy-consensus", + "alloy-eips", "alloy-primitives", "alloy-provider", "alloy-rlp", + "alloy-rpc-types", + "alloy-rpc-types-debug", "alloy-transport", "alloy-trie", "async-trait", @@ -7358,6 +6655,8 @@ dependencies = [ "revm-database-interface", "revm-primitives", "revm-state", + "serde", + "serde_json", "thiserror 1.0.69", "tokio", "tracing", @@ -7439,19 +6738,6 @@ dependencies = [ "semver 1.0.27", ] -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.10.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - [[package]] name = "rustix" version = "1.1.2" @@ -7461,22 +6747,10 @@ dependencies = [ "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.11.0", + "linux-raw-sys", "windows-sys 0.61.2", ] -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", -] - [[package]] name = "rustls" version = "0.21.12" @@ -7484,7 +6758,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.14", + "ring", "rustls-webpki 0.101.7", "sct", ] @@ -7496,7 +6770,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "once_cell", - "ring 0.17.14", + "ring", "rustls-pki-types", "rustls-webpki 0.103.8", "subtle", @@ -7540,8 +6814,8 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -7550,9 +6824,9 @@ version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ - "ring 0.17.14", + "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] @@ -7579,24 +6853,6 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "scale-info" version = "2.11.6" @@ -7660,26 +6916,14 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "scrypt" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" -dependencies = [ - "hmac", - "pbkdf2 0.11.0", - "salsa20", - "sha2", -] - [[package]] name = "sct" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -7769,12 +7013,6 @@ 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" @@ -7791,15 +7029,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde_arrays" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38636132857f68ec3d5f3eb121166d2af33cb55174c4d5ff645db6165cbef0fd" -dependencies = [ - "serde", -] - [[package]] name = "serde_arrays" version = "0.2.0" @@ -7853,15 +7082,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -7934,7 +7154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -7944,7 +7164,7 @@ version = "0.10.9" source = "git+https://github.com/ziren-patches/RustCrypto-hashes?branch=patch-sha2-0.10.9#dbfdbd088ac7b55e03c0b9eb192278efe35d67dc" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -8008,18 +7228,6 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" -[[package]] -name = "simple_asn1" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" -dependencies = [ - "num-bigint 0.4.6", - "num-traits", - "thiserror 2.0.17", - "time", -] - [[package]] name = "siphasher" version = "1.0.1" @@ -8077,31 +7285,20 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "solang-parser" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c425ce1c59f4b154717592f0bdf4715c3a1d55058883622d3157e1f0908a5b26" -dependencies = [ - "itertools 0.11.0", - "lalrpop", - "lalrpop-util", - "phf 0.11.3", - "thiserror 1.0.69", - "unicode-xid", -] - [[package]] name = "spin" -version = "0.5.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spin" -version = "0.9.8" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -8131,18 +7328,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" -[[package]] -name = "string_cache" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" -dependencies = [ - "new_debug_unreachable", - "parking_lot 0.12.5", - "phf_shared 0.11.3", - "precomputed-hash", -] - [[package]] name = "strsim" version = "0.10.0" @@ -8179,7 +7364,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "rustversion", @@ -8192,7 +7377,7 @@ version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.111", @@ -8220,26 +7405,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "svm-rs" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11297baafe5fa0c99d5722458eac6a5e25c01eb1b8e5cd137f54079093daa7a4" -dependencies = [ - "dirs", - "fs2", - "hex", - "once_cell", - "reqwest 0.11.27", - "semver 1.0.27", - "serde", - "serde_json", - "sha2", - "thiserror 1.0.69", - "url", - "zip", -] - [[package]] name = "syn" version = "1.0.109" @@ -8323,18 +7488,7 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", - "system-configuration-sys 0.5.0", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.10.0", - "core-foundation", - "system-configuration-sys 0.6.0", + "system-configuration-sys", ] [[package]] @@ -8347,22 +7501,23 @@ dependencies = [ "libc", ] -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tar" +version = "0.4.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "tempfile" version = "3.23.0" @@ -8372,21 +7527,10 @@ dependencies = [ "fastrand", "getrandom 0.3.4", "once_cell", - "rustix 1.1.2", + "rustix", "windows-sys 0.61.2", ] -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -8566,17 +7710,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.9", - "tokio", - "webpki", -] - [[package]] name = "tokio-rustls" version = "0.24.1" @@ -8609,21 +7742,6 @@ dependencies = [ "tokio-util", ] -[[package]] -name = "tokio-tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" -dependencies = [ - "futures-util", - "log", - "rustls 0.21.12", - "tokio", - "tokio-rustls 0.24.1", - "tungstenite 0.20.1", - "webpki-roots 0.25.4", -] - [[package]] name = "tokio-tungstenite" version = "0.26.2" @@ -8636,7 +7754,7 @@ dependencies = [ "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", - "tungstenite 0.26.2", + "tungstenite", "webpki-roots 0.26.11", ] @@ -8646,32 +7764,11 @@ version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime 0.6.11", - "toml_edit 0.22.27", -] - -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", ] [[package]] @@ -8683,20 +7780,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap 2.12.1", - "serde", - "serde_spanned", - "toml_datetime 0.6.11", - "toml_write", - "winnow", -] - [[package]] name = "toml_edit" version = "0.23.9" @@ -8704,7 +7787,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832" dependencies = [ "indexmap 2.12.1", - "toml_datetime 0.7.3", + "toml_datetime", "toml_parser", "winnow", ] @@ -8718,25 +7801,17 @@ dependencies = [ "winnow", ] -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - [[package]] name = "tonic" -version = "0.8.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" +checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" dependencies = [ "async-stream", "async-trait", "axum 0.6.20", - "base64 0.13.1", + "base64 0.21.7", "bytes", - "futures-core", - "futures-util", "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", @@ -8744,32 +7819,30 @@ dependencies = [ "hyper-timeout", "percent-encoding", "pin-project", - "prost 0.11.9", - "prost-derive 0.11.9", + "prost 0.12.6", + "rustls 0.21.12", "rustls-native-certs", "rustls-pemfile", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls 0.24.1", "tokio-stream", - "tokio-util", "tower 0.4.13", "tower-layer", "tower-service", "tracing", - "tracing-futures", ] [[package]] name = "tonic-build" -version = "0.8.4" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4" +checksum = "9d021fc044c18582b9a2408cd0dd05b1596e3ecdb5c4df822bb0183545683889" dependencies = [ - "prettyplease 0.1.25", + "prettyplease", "proc-macro2", - "prost-build 0.11.9", + "prost-build 0.12.6", "quote", - "syn 1.0.109", + "syn 2.0.111", ] [[package]] @@ -8814,13 +7887,18 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ + "async-compression", "bitflags 2.10.0", "bytes", + "futures-core", "futures-util", "http 1.4.0", "http-body 1.0.1", + "http-body-util", "iri-string", "pin-project-lite", + "tokio", + "tokio-util", "tower 0.5.2", "tower-layer", "tower-service", @@ -8840,9 +7918,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -8863,9 +7941,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -8884,16 +7962,6 @@ dependencies = [ "tracing-subscriber", ] -[[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 = "tracing-log" version = "0.2.0" @@ -8939,26 +8007,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 0.2.12", - "httparse", - "log", - "rand 0.8.5", - "rustls 0.21.12", - "sha1", - "thiserror 1.0.69", - "url", - "utf-8", -] - [[package]] name = "tungstenite" version = "0.26.2" @@ -9063,22 +8111,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "unroll" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad948c1cb799b1a70f836077721a92a35ac177d4daddf4c20a633786d4cf618" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -9115,16 +8147,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -dependencies = [ - "getrandom 0.2.16", - "serde", -] - [[package]] name = "uuid" version = "1.19.0" @@ -9198,16 +8220,6 @@ dependencies = [ "libc", ] -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "want" version = "0.3.1" @@ -9352,16 +8364,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", -] - [[package]] name = "webpki-roots" version = "0.25.4" @@ -9386,18 +8388,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.44", -] - [[package]] name = "widestring" version = "1.2.1" @@ -9420,15 +8410,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -9810,7 +8791,7 @@ dependencies = [ "log", "pharos", "rustc_version 0.4.1", - "send_wrapper 0.6.0", + "send_wrapper", "thiserror 2.0.17", "wasm-bindgen", "wasm-bindgen-futures", @@ -9826,6 +8807,16 @@ dependencies = [ "tap", ] +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -9835,12 +8826,6 @@ dependencies = [ "linked-hash-map", ] -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - [[package]] name = "yoke" version = "0.8.1" @@ -9964,18 +8949,10 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ - "aes", "byteorder", - "bzip2", - "constant_time_eq 0.1.5", "crc32fast", "crossbeam-utils", "flate2", - "hmac", - "pbkdf2 0.11.0", - "sha1", - "time", - "zstd 0.11.2+zstd.1.5.2", ] [[package]] @@ -10007,8 +8984,8 @@ dependencies = [ [[package]] name = "zkm-build" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "anyhow", "cargo_metadata", @@ -10018,8 +8995,8 @@ dependencies = [ [[package]] name = "zkm-core-executor" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "anyhow", "bincode", @@ -10031,6 +9008,7 @@ dependencies = [ "hashbrown 0.14.5", "hex", "itertools 0.13.0", + "libc", "log", "nohash-hasher", "num", @@ -10041,6 +9019,7 @@ dependencies = [ "p3-symmetric", "rand 0.8.5", "rayon-scan", + "rustc-hash 2.1.1", "serde", "serde_json", "sha2", @@ -10052,15 +9031,33 @@ dependencies = [ "tracing-subscriber", "typenum", "vec_map", + "zkm-core-jit", "zkm-curves", + "zkm-pcs", "zkm-primitives", - "zkm-stark", +] + +[[package]] +name = "zkm-core-jit" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" +dependencies = [ + "dynasmrt", + "hashbrown 0.14.5", + "libc", + "memfd", + "memmap2 0.9.11", + "p3-field", + "p3-koala-bear", + "serde", + "thiserror 1.0.69", + "tracing", ] [[package]] name = "zkm-core-machine" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "bincode", "cfg-if", @@ -10105,14 +9102,14 @@ dependencies = [ "zkm-core-executor", "zkm-curves", "zkm-derive", + "zkm-pcs", "zkm-primitives", - "zkm-stark", ] [[package]] name = "zkm-cuda" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "bincode", "ctrlc", @@ -10129,8 +9126,8 @@ dependencies = [ [[package]] name = "zkm-curves" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "cfg-if", "curve25519-dalek", @@ -10147,14 +9144,14 @@ dependencies = [ "thiserror 1.0.69", "tracing", "typenum", + "zkm-poly", "zkm-primitives", - "zkm-stark", ] [[package]] name = "zkm-derive" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "proc-macro2", "quote", @@ -10163,8 +9160,8 @@ dependencies = [ [[package]] name = "zkm-lib" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "bincode", "cfg-if", @@ -10174,12 +9171,67 @@ dependencies = [ "zkm-primitives", ] +[[package]] +name = "zkm-pcs" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" +dependencies = [ + "arrayref", + "bincode", + "hashbrown 0.14.5", + "itertools 0.13.0", + "num-bigint 0.4.6", + "num-traits", + "p3-air", + "p3-challenger", + "p3-circle", + "p3-commit", + "p3-dft", + "p3-field", + "p3-fri", + "p3-keccak", + "p3-koala-bear", + "p3-matrix", + "p3-maybe-rayon", + "p3-merkle-tree", + "p3-mersenne-31", + "p3-poseidon2", + "p3-symmetric", + "p3-uni-stark", + "p3-util", + "rand 0.8.5", + "rayon", + "rayon-scan", + "rmp-serde", + "serde", + "strum 0.26.3", + "strum_macros 0.26.4", + "sysinfo", + "tracing", + "tracing-forest", + "tracing-subscriber", + "zkm-derive", + "zkm-poly", + "zkm-primitives", + "zkm-zkvm", +] + +[[package]] +name = "zkm-poly" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" +dependencies = [ + "itertools 0.13.0", + "p3-field", +] + [[package]] name = "zkm-primitives" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "bincode", + "blake3", "hex", "lazy_static", "num-bigint 0.4.6", @@ -10190,28 +9242,32 @@ dependencies = [ "p3-symmetric", "serde", "sha2", + "tracing", ] [[package]] name = "zkm-prover" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "anyhow", "bincode", "clap", "dirs", "eyre", + "hex", "itertools 0.13.0", "lru 0.12.5", "num-bigint 0.4.6", - "p3-bn254-fr", + "p3-air", + "p3-bn254", "p3-challenger", "p3-commit", "p3-field", "p3-koala-bear", "p3-matrix", "p3-symmetric", + "p3-uni-stark", "p3-util", "rayon", "serde", @@ -10221,24 +9277,24 @@ dependencies = [ "tracing-subscriber", "zkm-core-executor", "zkm-core-machine", + "zkm-pcs", "zkm-primitives", "zkm-recursion-circuit", "zkm-recursion-compiler", "zkm-recursion-core", "zkm-recursion-gnark-ffi", - "zkm-stark", ] [[package]] name = "zkm-recursion-circuit" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "hashbrown 0.14.5", "itertools 0.13.0", "num-traits", "p3-air", - "p3-bn254-fr", + "p3-bn254", "p3-challenger", "p3-commit", "p3-dft", @@ -10255,21 +9311,21 @@ dependencies = [ "zkm-core-executor", "zkm-core-machine", "zkm-derive", + "zkm-pcs", "zkm-primitives", "zkm-recursion-compiler", "zkm-recursion-core", "zkm-recursion-gnark-ffi", - "zkm-stark", ] [[package]] name = "zkm-recursion-compiler" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "backtrace", "itertools 0.13.0", - "p3-bn254-fr", + "p3-bn254", "p3-field", "p3-koala-bear", "p3-symmetric", @@ -10277,23 +9333,24 @@ dependencies = [ "tracing", "vec_map", "zkm-core-machine", + "zkm-pcs", "zkm-primitives", "zkm-recursion-core", "zkm-recursion-derive", - "zkm-stark", ] [[package]] name = "zkm-recursion-core" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "backtrace", + "bincode", "ff 0.13.1", "hashbrown 0.14.5", "itertools 0.13.0", "p3-air", - "p3-bn254-fr", + "p3-bn254", "p3-challenger", "p3-commit", "p3-dft", @@ -10309,6 +9366,7 @@ dependencies = [ "p3-util", "rand 0.8.5", "serde", + "sha2", "static_assertions", "thiserror 1.0.69", "tracing", @@ -10316,14 +9374,14 @@ dependencies = [ "zkhash", "zkm-core-machine", "zkm-derive", + "zkm-pcs", "zkm-primitives", - "zkm-stark", ] [[package]] name = "zkm-recursion-derive" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "quote", "syn 1.0.109", @@ -10331,8 +9389,8 @@ dependencies = [ [[package]] name = "zkm-recursion-gnark-ffi" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "anyhow", "bincode", @@ -10349,23 +9407,22 @@ dependencies = [ "sha2", "tempfile", "zkm-core-machine", + "zkm-pcs", "zkm-recursion-compiler", - "zkm-stark", ] [[package]] name = "zkm-sdk" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "alloy-primitives", - "alloy-signer", "anyhow", "async-trait", "bincode", "cfg-if", "dirs", - "ethers", + "flate2", "futures", "hashbrown 0.14.5", "hex", @@ -10376,12 +9433,13 @@ dependencies = [ "p3-field", "p3-fri", "p3-koala-bear", - "prost 0.11.9", + "prost 0.12.6", "reqwest 0.11.27", "serde", "serde_json", "strum 0.26.3", "strum_macros 0.26.4", + "tar", "tempfile", "thiserror 1.0.69", "tokio", @@ -10389,63 +9447,21 @@ dependencies = [ "tonic-build", "tracing", "twirp-rs", - "uuid 1.19.0", + "uuid", "vergen", "zkm-build", "zkm-core-executor", "zkm-core-machine", "zkm-cuda", + "zkm-pcs", "zkm-primitives", "zkm-prover", - "zkm-stark", -] - -[[package]] -name = "zkm-stark" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" -dependencies = [ - "arrayref", - "hashbrown 0.14.5", - "itertools 0.13.0", - "num-bigint 0.4.6", - "num-traits", - "p3-air", - "p3-challenger", - "p3-circle", - "p3-commit", - "p3-dft", - "p3-field", - "p3-fri", - "p3-keccak", - "p3-koala-bear", - "p3-matrix", - "p3-maybe-rayon", - "p3-mds", - "p3-merkle-tree", - "p3-mersenne-31", - "p3-poseidon2", - "p3-symmetric", - "p3-uni-stark", - "p3-util", - "rand 0.8.5", - "rayon-scan", - "serde", - "strum 0.26.3", - "strum_macros 0.26.4", - "sysinfo", - "tracing", - "tracing-forest", - "tracing-subscriber", - "zkm-derive", - "zkm-primitives", - "zkm-zkvm", ] [[package]] name = "zkm-zkvm" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "bincode", "cfg-if", @@ -10459,32 +9475,13 @@ dependencies = [ "zkm-primitives", ] -[[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 5.0.2+zstd.1.5.2", -] - [[package]] name = "zstd" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ - "zstd-safe 7.2.4", -] - -[[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", + "zstd-safe", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1f7fb48..8c9332b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ provider = { path = "./crates/provider" } zkm-build = { git = "https://github.com/ProjectZKM/Ziren" } zkm-core-executor = { git = "https://github.com/ProjectZKM/Ziren" } zkm-prover = { git = "https://github.com/ProjectZKM/Ziren" } +zkm-cuda = { git = "https://github.com/ProjectZKM/Ziren" } zkm-sdk = { git = "https://github.com/ProjectZKM/Ziren" } # reth diff --git a/bin/eth-proofs/Cargo.toml b/bin/eth-proofs/Cargo.toml index bd8a843..99b5c92 100644 --- a/bin/eth-proofs/Cargo.toml +++ b/bin/eth-proofs/Cargo.toml @@ -4,7 +4,7 @@ name = "eth-proofs" edition = "2021" [dependencies] -tokio.workspace = true +tokio = { workspace = true, features = ["signal"] } url.workspace = true tracing.workspace = true serde_json.workspace = true @@ -13,6 +13,11 @@ tracing-subscriber = "0.3.18" dotenv = "0.15.0" clap = { version = "4.5.7", features = ["derive", "env"] } eyre = "0.6.12" +bincode = "1.3.3" +sha2 = "0.10.8" +hex = "0.4.3" +fs2 = "0.4.3" +libc = "0.2" reqwest = { workspace = true, features = ["json"] } reqwest-middleware = { version = "0.3.3", features = ["json"] } reqwest-retry = "0.6.1" @@ -28,6 +33,8 @@ provider.workspace = true # Ziren zkm-sdk.workspace = true +zkm-cuda.workspace = true +zkm-prover.workspace = true # alloy alloy-chains.workspace = true @@ -41,3 +48,6 @@ zkm-build.workspace = true [features] test = [] + +[dev-dependencies] +tempfile = "3" diff --git a/bin/eth-proofs/build.rs b/bin/eth-proofs/build.rs index dcfa0c5..5029151 100644 --- a/bin/eth-proofs/build.rs +++ b/bin/eth-proofs/build.rs @@ -1,5 +1,12 @@ -use zkm_build::build_program; +use zkm_build::{build_program_with_args, BuildArgs}; fn main() { - build_program("../guest"); + println!("cargo:rerun-if-env-changed=ETH_PROOFS_BUILD_ELF"); + if let Ok(path) = std::env::var("ETH_PROOFS_BUILD_ELF") { + let path = std::fs::canonicalize(path).expect("ETH_PROOFS_BUILD_ELF must exist"); + println!("cargo:rerun-if-changed={}", path.display()); + println!("cargo:rustc-env=ZKM_ELF_reth={}", path.display()); + } else { + build_program_with_args("../guest", BuildArgs { locked: true, ..Default::default() }); + } } diff --git a/bin/eth-proofs/src/cli.rs b/bin/eth-proofs/src/cli.rs index 03ef128..b92b76d 100644 --- a/bin/eth-proofs/src/cli.rs +++ b/bin/eth-proofs/src/cli.rs @@ -14,7 +14,7 @@ pub struct Args { /// The WS rpc url used to fetch data about the block. #[clap(long, env)] - pub ws_rpc_url: Url, + pub ws_rpc_url: Option, /// The debug HTTP rpc url used to fetch data about the block trace. #[clap(long, env)] @@ -28,6 +28,29 @@ pub struct Args { #[clap(long, default_value_t = 100)] pub block_interval: u64, + /// Which residue class of `block_interval` this instance proves: blocks + /// with `number % block_interval == block_residue`. Two instances with + /// `--block-interval 2` and residues 0 and 1 split the chain between two + /// provers and prove two blocks at a time. + #[clap(long, default_value_t = 0)] + pub block_residue: u64, + + /// How many prepared blocks (fetched + natively executed) may wait for the + /// prover. The fetch of block N+1 always overlaps the proof of block N; + /// this bounds how far ahead the fetcher runs. + #[clap(long, default_value_t = 1)] + pub prefetch_depth: usize, + + /// Skip a block when it is more than this many blocks behind the newest + /// header seen (0 = never skip: prove every block the stream delivers). + #[clap(long, default_value_t = 0)] + pub max_lag: u64, + + /// In local mode, select the latest eligible head before each preparation. + /// Prepare ahead of proving; retain only the newest completed witness. + #[clap(long)] + pub latest_block: bool, + /// ETH proofs endpoint. #[clap(long, env)] pub eth_proofs_endpoint: String, @@ -44,6 +67,34 @@ pub struct Args { #[clap(long, env)] pub pager_duty_integration_key: Option, + /// Direct local GPU server, set by Fleet for an integrated app worker. + #[clap(long, env = "FLEET_GPU_ENDPOINT")] + pub local_gpu_endpoint: Option, + + /// Persistent local worker state. Required with --local-gpu-endpoint. + #[clap(long, env = "FLEET_APP_STORAGE_ROOT", requires = "local_gpu_endpoint")] + pub state_dir: Option, + + /// Use an existing production guest instead of the embedded ELF. + #[clap(long, env = "ETH_PROOFS_ELF_FILE")] + pub elf_file: Option, + + /// Reject a guest whose digest differs from this app's configured program. + #[clap(long, env = "FLEET_APP_ELF_ID")] + pub expected_elf_id: Option, + + /// First block for a new durable stream; restarts resume persisted progress. + #[clap(long)] + pub start_block: Option, + + /// Witness preparation concurrency (1 or 2 in latest mode; GPU proving remains serial). + #[clap(long, default_value_t = 1)] + pub prepare_concurrency: usize, + + /// Pause proving when this many completed reports await acknowledgment. + #[clap(long, default_value_t = 128)] + pub max_pending_reports: usize, + /// Moongate server endpoint. #[clap(long, env)] pub moongate_endpoint: Option, diff --git a/bin/eth-proofs/src/eth_proofs.rs b/bin/eth-proofs/src/eth_proofs.rs index 327437d..208f44e 100644 --- a/bin/eth-proofs/src/eth_proofs.rs +++ b/bin/eth-proofs/src/eth_proofs.rs @@ -1,29 +1,154 @@ -use std::time::Duration; +use crate::state::State; +use std::{sync::Arc, time::Duration}; use base64::{engine::general_purpose::STANDARD, Engine}; use eyre::eyre; use host_executor::ExecutionHooks; use reqwest_middleware::{ClientBuilder, ClientWithMiddleware}; use reqwest_retry::{policies::ExponentialBackoff, RetryTransientMiddleware}; -use tracing::error; +use tracing::{error, info}; use zkm_sdk::{HashableKey, ZKMVerifyingKey}; -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct EthProofsClient { cluster_id: u64, endpoint: String, api_token: String, client: ClientWithMiddleware, + state: Option>, } impl EthProofsClient { pub fn new(cluster_id: u64, endpoint: String, api_token: String) -> Self { let retry_policy = ExponentialBackoff::builder().build_with_max_retries(3); - let client = ClientBuilder::new(reqwest::Client::new()) - .with(RetryTransientMiddleware::new_with_policy(retry_policy)) - .build(); + let client = ClientBuilder::new( + reqwest::Client::builder().timeout(Duration::from_secs(60)).build().unwrap(), + ) + .with(RetryTransientMiddleware::new_with_policy(retry_policy)) + .build(); - Self { cluster_id, endpoint, api_token, client } + Self { cluster_id, endpoint, api_token, client, state: None } + } + + pub fn with_state(mut self, state: Arc) -> Self { + self.state = Some(state); + self + } + + pub fn start_reporter(&self) -> tokio::task::JoinHandle<()> { + let this = self.clone(); + tokio::spawn(async move { + let Some(state) = &this.state else { + return; + }; + loop { + match state.pending() { + Ok(pending) => { + for (block, payload) in pending { + let result = this + .client + .post(format!("{}/proofs/proved", this.endpoint)) + .header("Authorization", format!("Bearer {}", this.api_token)) + .json(&payload) + .send() + .await; + match result { + Ok(response) if response.status().is_success() => { + if let Err(err) = state.acknowledge(block) { + error!(block, %err, "report accepted but acknowledgment persistence failed"); + } else { + info!(block, "durable EthProofs report acknowledged"); + } + } + Ok(response) + if response.status() == reqwest::StatusCode::CONFLICT => + { + match this.already_published(block, &payload).await { + Ok(true) => { + if let Err(err) = state.acknowledge(block) { + error!(block, %err, "duplicate acknowledgment persistence failed"); + } else { + info!( + block, + duplicate = true, + "durable EthProofs report acknowledged" + ); + } + } + Ok(false) => error!( + block, + "conflicting API proof differs; report remains pending" + ), + Err(err) => { + error!(block, %err, "duplicate proof lookup failed; report remains pending") + } + } + } + Ok(response) => { + error!(block, status = %response.status(), "EthProofs report remains pending") + } + Err(err) => error!(block, %err, "EthProofs report remains pending"), + } + } + } + Err(err) => error!(%err, "reading persistent reporting outbox failed"), + } + tokio::select! { + _ = state.report_ready() => {}, + _ = tokio::time::sleep(Duration::from_secs(3)) => {}, + } + } + }) + } + + /// A lost local acknowledgment can turn a successful retry into HTTP 409. + /// Only accept it after checking the cluster, block, and exact published bytes. + async fn already_published( + &self, + block: u64, + payload: &serde_json::Value, + ) -> eyre::Result { + let rows: serde_json::Value = self + .client + .get(format!("{}/proofs?block={block}&limit=100", self.endpoint)) + .header("Authorization", format!("Bearer {}", self.api_token)) + .send() + .await? + .error_for_status()? + .json() + .await?; + let expected = STANDARD + .decode(payload["proof"].as_str().ok_or_else(|| eyre!("missing proof bytes"))?)?; + let proofs = rows["proofs"].as_array().ok_or_else(|| eyre!("invalid proof listing"))?; + for proof in proofs { + if proof["block_number"].as_u64() != Some(block) || + proof["proof_status"].as_str() != Some("proved") || + proof["cluster_version"]["cluster"]["index"].as_u64() != Some(self.cluster_id) + { + continue; + } + let id = match &proof["proof_id"] { + serde_json::Value::Number(id) => id.to_string(), + serde_json::Value::String(id) => id.clone(), + _ => continue, + }; + if id.is_empty() || !id.chars().all(|c| c.is_ascii_alphanumeric() || c == '-') { + continue; + } + let published = self + .client + .get(format!("{}/proofs/download/{id}", self.endpoint)) + .header("Authorization", format!("Bearer {}", self.api_token)) + .send() + .await? + .error_for_status()? + .bytes() + .await?; + if published.as_ref() == expected.as_slice() { + return Ok(true); + } + } + Ok(false) } pub async fn queued(&self, block_number: u64) { @@ -113,8 +238,12 @@ impl EthProofsClient { .map_err(|e| eyre!(e)) .and_then(|r| r.error_for_status().map_err(|e| eyre!(e))); - if let Err(err) = response { - error!("Failed to report proof proving: {}", err) + match response { + Ok(_) => info!( + "Reported proved block {} to eth-proofs: {} cycles, {:.1} s", + block_number, cycles, elapsed + ), + Err(err) => error!("Failed to report proof proved: {}", err), } }); } @@ -145,9 +274,170 @@ impl ExecutionHooks for EthProofsClient { cycles: u64, proving_duration: Duration, ) -> eyre::Result<()> { - #[cfg(not(feature = "test"))] - self.proved(proof_bytes, block_number, cycles, proving_duration.as_secs_f32(), vk).await; + if let Some(state) = &self.state { + let payload = serde_json::json!({ + "proof": STANDARD.encode(proof_bytes), "block_number": block_number, + "proving_cycles": cycles, "proving_time": proving_duration.as_millis() as u64, + "verifier_id": vk.bytes32(), "cluster_id": self.cluster_id, + }); + // Commit the output and its retryable report before the cursor advances. + state.commit(block_number, proof_bytes, _public_values_bytes, payload)?; + } else { + #[cfg(not(feature = "test"))] + self.proved(proof_bytes, block_number, cycles, proving_duration.as_secs_f32(), vk) + .await; + } Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::state::Identity; + use tokio::io::{AsyncReadExt, AsyncWriteExt}; + + #[tokio::test] + async fn duplicate_lookup_requires_the_same_cluster_block_and_bytes() { + for (cluster, block, bytes, expected) in [ + (8, 10, b"proof".as_slice(), true), + (9, 10, b"proof".as_slice(), false), + (8, 11, b"proof".as_slice(), false), + (8, 10, b"different".as_slice(), false), + ] { + let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); + let client = EthProofsClient::new( + 8, + format!("http://{}", listener.local_addr().unwrap()), + "test".into(), + ); + let server = tokio::spawn(async move { + let listing = serde_json::json!({"proofs":[{ + "block_number":block,"proof_status":"proved","proof_id":123, + "cluster_version":{"cluster":{"index":cluster}} + }]}) + .to_string(); + let count = if cluster == 8 && block == 10 { 2 } else { 1 }; + for i in 0..count { + let (mut socket, _) = listener.accept().await.unwrap(); + let mut request = vec![0; 4096]; + let n = socket.read(&mut request).await.unwrap(); + let request = String::from_utf8_lossy(&request[..n]); + assert!(request.starts_with(if i == 0 { + "GET /proofs?block=10&limit=100 " + } else { + "GET /proofs/download/123 " + })); + let body = if i == 0 { listing.as_bytes() } else { bytes }; + socket.write_all(format!("HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n",body.len()).as_bytes()).await.unwrap(); + socket.write_all(body).await.unwrap(); + } + }); + let actual = tokio::time::timeout( + Duration::from_secs(5), + client + .already_published(10, &serde_json::json!({"proof":STANDARD.encode(b"proof")})), + ) + .await + .unwrap() + .unwrap(); + assert_eq!(actual, expected); + server.await.unwrap(); + } + } + + #[tokio::test] + async fn report_is_retained_until_http_success() { + let root = tempfile::tempdir().unwrap(); + let state = Arc::new( + State::open( + root.path(), + Identity { + namespace: "test".into(), + tenant: "ethproofs".into(), + chain_id: 1, + cluster_id: 8, + elf_id: "elf".into(), + interval: 1, + residue: 0, + }, + Some(10), + ) + .unwrap(), + ); + let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); + let client = EthProofsClient::new( + 8, + format!("http://{}", listener.local_addr().unwrap()), + "test".into(), + ) + .with_state(state.clone()); + let reporter = client.start_reporter(); + // Let the reporter enter its idle wait, then commit a new output. + tokio::time::sleep(Duration::from_millis(50)).await; + state.commit(10, b"proof", b"values", serde_json::json!({"block_number":10})).unwrap(); + for status in ["401 Unauthorized", "200 OK"] { + let timeout = if status.starts_with("401") { 1 } else { 10 }; + let (mut socket, _) = + tokio::time::timeout(Duration::from_secs(timeout), listener.accept()) + .await + .unwrap() + .unwrap(); + let mut request = Vec::new(); + loop { + let mut bytes = [0; 2048]; + let n = socket.read(&mut bytes).await.unwrap(); + request.extend_from_slice(&bytes[..n]); + if let Some(end) = request.windows(4).position(|w| w == b"\r\n\r\n") { + let headers = String::from_utf8_lossy(&request[..end]).to_ascii_lowercase(); + let length = headers + .lines() + .find_map(|line| line.strip_prefix("content-length: ")) + .unwrap() + .parse::() + .unwrap(); + if request.len() >= end + 4 + length { + break; + } + } + assert!(n > 0); + } + assert!(String::from_utf8_lossy(&request).starts_with("POST /proofs/proved")); + assert_eq!(state.pending_count().unwrap(), 1); + socket + .write_all( + format!("HTTP/1.1 {status}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n") + .as_bytes(), + ) + .await + .unwrap(); + } + tokio::time::timeout(Duration::from_secs(5), async { + while state.pending_count().unwrap() != 0 { + tokio::time::sleep(Duration::from_millis(10)).await; + } + }) + .await + .unwrap(); + reporter.abort(); + let _ = reporter.await; + drop(client); + drop(state); + let restored = State::open( + root.path(), + Identity { + namespace: "test".into(), + tenant: "ethproofs".into(), + chain_id: 1, + cluster_id: 8, + elf_id: "elf".into(), + interval: 1, + residue: 0, + }, + None, + ) + .unwrap(); + assert_eq!(restored.pending_count().unwrap(), 0); + } +} diff --git a/bin/eth-proofs/src/latest.rs b/bin/eth-proofs/src/latest.rs new file mode 100644 index 0000000..5b45bac --- /dev/null +++ b/bin/eth-proofs/src/latest.rs @@ -0,0 +1,233 @@ +//! A bounded latest-head preparation pool. The prover consumes a single slot; +//! older completions cannot replace newer ones, even when RPCs finish out of order. +use futures::{stream::FuturesUnordered, StreamExt}; +use std::{ + collections::HashSet, + future::Future, + sync::Arc, + time::{Duration, Instant}, +}; +use tokio::sync::watch; +use tracing::{info, warn}; + +pub type Prepared = (u64, Arc>); + +pub async fn run( + concurrency: usize, + minimum: u64, + interval: u64, + residue: u64, + output: watch::Sender>, + mut shutdown: watch::Receiver, + mut head: H, + mut prepare: P, +) -> eyre::Result<()> +where + H: FnMut() -> HF, + HF: Future>, + P: FnMut(u64) -> PF, + PF: Future>>>, +{ + eyre::ensure!(concurrency > 0 && interval > 0, "invalid preparation limits"); + let mut running = FuturesUnordered::new(); + let mut selected = None; + let mut published = None; + let mut active_blocks = HashSet::new(); + let mut retry_after = None; + let mut poll = tokio::time::interval(Duration::from_millis(500)); + poll.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + loop { + if *shutdown.borrow() || output.is_closed() { + break; + } + tokio::select! { + _ = shutdown.changed() => break, + result = running.next(), if !running.is_empty() => { + if let Some((number, result)) = result { + active_blocks.remove(&number); + match result { + Ok(bytes) if published.is_none_or(|previous| number > previous) => { + info!(number, "latest-head witness ready"); + published = Some(number); + output.send_replace(Some((number, bytes))); + }, + Ok(_) => {}, // A slower older witness must never replace a newer one. + Err(err) => { + warn!(number, %err, "latest-head witness preparation failed"); + if selected == Some(number) { + retry_after = Some((number, Instant::now() + Duration::from_secs(2))); + } + }, + } + } + }, + head_result = async { poll.tick().await; head().await }, if running.len() < concurrency => { + let newest = match head_result { + Ok(head) => super::latest_selected_block(head, interval, residue), + Err(err) => { + warn!(%err, "latest head lookup failed; retrying"); + continue; + } + }; + if let Some(number) = newest.filter(|number| { + *number >= minimum && selected.is_none_or(|previous| *number >= previous) + && published.is_none_or(|previous| *number > previous) + && !active_blocks.contains(number) + && retry_after.is_none_or(|(failed, until)| *number != failed || Instant::now() >= until) + }) { + selected = Some(number); + active_blocks.insert(number); + let future = prepare(number); + running.push(async move { (number, future.await) }); + info!(number, active = running.len(), "latest-head witness preparation started"); + } + }, + } + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; + use tokio::sync::Semaphore; + + #[tokio::test] + async fn overlaps_two_preparations_and_keeps_newest_out_of_order_completion() { + let head = Arc::new(AtomicU64::new(100)); + let active = Arc::new(AtomicUsize::new(0)); + let first = Arc::new(Semaphore::new(0)); + let second = Arc::new(Semaphore::new(0)); + let (output, mut ready) = watch::channel(None); + let (stop, shutdown) = watch::channel(false); + let task = tokio::spawn({ + let head = head.clone(); + let active = active.clone(); + let first = first.clone(); + let second = second.clone(); + async move { + run( + 2, + 100, + 1, + 0, + output, + shutdown, + || std::future::ready(Ok(head.load(Ordering::SeqCst))), + |number| { + let active = active.clone(); + let gate = if number == 100 { first.clone() } else { second.clone() }; + async move { + active.fetch_add(1, Ordering::SeqCst); + let _permit = gate.acquire().await.unwrap(); + active.fetch_sub(1, Ordering::SeqCst); + Ok(Arc::new(vec![number as u8])) + } + }, + ) + .await + } + }); + tokio::time::timeout(Duration::from_secs(3), async { + while active.load(Ordering::SeqCst) != 1 { + tokio::task::yield_now().await; + } + head.store(101, Ordering::SeqCst); + while active.load(Ordering::SeqCst) != 2 { + tokio::task::yield_now().await; + } + // Both slots are occupied. Advancing the head must not start a third job. + head.store(102, Ordering::SeqCst); + tokio::time::sleep(Duration::from_millis(550)).await; + assert_eq!(active.load(Ordering::SeqCst), 2); + head.store(101, Ordering::SeqCst); + second.add_permits(1); + ready.changed().await.unwrap(); + assert_eq!(ready.borrow_and_update().as_ref().unwrap().0, 101); + first.add_permits(1); + while active.load(Ordering::SeqCst) != 0 { + tokio::task::yield_now().await; + } + tokio::time::sleep(Duration::from_millis(20)).await; + assert_eq!(ready.borrow().as_ref().unwrap().0, 101); + assert!(!ready.has_changed().unwrap()); + }) + .await + .unwrap(); + stop.send(true).unwrap(); + task.await.unwrap().unwrap(); + } + + #[tokio::test] + async fn replaces_waiting_witness_instead_of_building_a_backlog() { + let head = Arc::new(AtomicU64::new(100)); + let (output, mut ready) = watch::channel(None); + let (stop, shutdown) = watch::channel(false); + let task = tokio::spawn({ + let head = head.clone(); + async move { + run( + 2, + 100, + 1, + 0, + output, + shutdown, + || std::future::ready(Ok(head.load(Ordering::SeqCst))), + |number| std::future::ready(Ok(Arc::new(vec![number as u8]))), + ) + .await + } + }); + tokio::time::timeout(Duration::from_secs(3), async { + ready.changed().await.unwrap(); + assert_eq!(ready.borrow_and_update().as_ref().unwrap().0, 100); + // Simulate a busy prover: no receive while new heads are prepared. + head.store(105, Ordering::SeqCst); + ready.changed().await.unwrap(); + assert_eq!(ready.borrow_and_update().as_ref().unwrap().0, 105); + head.store(110, Ordering::SeqCst); + ready.changed().await.unwrap(); + assert_eq!(ready.borrow_and_update().as_ref().unwrap().0, 110); + }) + .await + .unwrap(); + stop.send(true).unwrap(); + task.await.unwrap().unwrap(); + } + #[tokio::test] + async fn retries_an_announced_head_until_its_witness_is_available() { + let attempts = Arc::new(AtomicUsize::new(0)); + let (output, mut ready) = watch::channel(None); + let (stop, shutdown) = watch::channel(false); + let task = tokio::spawn({ + let attempts = attempts.clone(); + async move { + run( + 2, + 100, + 1, + 0, + output, + shutdown, + || std::future::ready(Ok(100)), + |_| { + let attempt = attempts.fetch_add(1, Ordering::SeqCst); + std::future::ready(if attempt == 0 { + Err(eyre::eyre!("witness RPC has not received this head yet")) + } else { + Ok(Arc::new(vec![1])) + }) + }, + ) + .await + } + }); + tokio::time::timeout(Duration::from_secs(4), ready.changed()).await.unwrap().unwrap(); + assert_eq!(ready.borrow().as_ref().unwrap().0, 100); + assert_eq!(attempts.load(Ordering::SeqCst), 2); + stop.send(true).unwrap(); + task.await.unwrap().unwrap(); + } +} diff --git a/bin/eth-proofs/src/main.rs b/bin/eth-proofs/src/main.rs index 688a05b..6cf9658 100644 --- a/bin/eth-proofs/src/main.rs +++ b/bin/eth-proofs/src/main.rs @@ -1,25 +1,33 @@ -use std::{env, sync::Arc}; +use sha2::{Digest, Sha256}; +use state::{Identity, State}; +use std::{env, sync::Arc, time::Duration}; +use zkm_cuda::ZKMGpuServer; +use zkm_prover::ZKMProver; +use zkm_sdk::provers::CudaProver; use alloy_provider::{Provider, ProviderBuilder, WsConnect}; use clap::Parser; use cli::Args; use eth_proofs::EthProofsClient; -use futures::{future::ready, StreamExt}; +use futures::{channel::mpsc, future::ready, FutureExt, SinkExt, StreamExt}; use host_executor::{ - alerting::AlertingClient, create_eth_block_execution_strategy_factory, BlockExecutor, - EthExecutorComponents, FullExecutor, + alerting::AlertingClient, create_eth_block_execution_strategy_factory, EthExecutorComponents, + FullExecutor, }; use provider::create_provider; -use tracing::{error, info}; +use tracing::{error, info, warn}; use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; use zkm_sdk::{include_elf, ProverClient}; mod cli; +mod latest; +mod state; mod eth_proofs; #[tokio::main] async fn main() -> eyre::Result<()> { + exit_with_parent()?; // Initialize the environment variables. dotenv::dotenv().ok(); @@ -43,7 +51,61 @@ async fn main() -> eyre::Result<()> { let args = Args::parse(); let config = args.as_config().await?; - let elf = include_elf!("reth").to_vec(); + eyre::ensure!(args.block_interval > 0, "block interval must be positive"); + eyre::ensure!(args.max_pending_reports > 0, "pending report limit must be positive"); + eyre::ensure!( + (1..=2).contains(&args.prepare_concurrency) && args.prefetch_depth > 0, + "preparation concurrency must be 1 or 2 and queue depth must be positive" + ); + eyre::ensure!( + args.latest_block || args.prepare_concurrency == 1, + "parallel preparation requires --latest-block" + ); + let elf = match &args.elf_file { + Some(path) => std::fs::read(path)?, + None => include_elf!("reth").to_vec(), + }; + let elf_id = hex::encode(Sha256::digest(&elf)); + if let Some(expected) = &args.expected_elf_id { + eyre::ensure!(*expected == elf_id, "guest ELF differs from the app's configured digest"); + } + let state = if let Some(endpoint) = &args.local_gpu_endpoint { + eyre::ensure!( + endpoint.scheme() == "http" && + matches!(endpoint.host_str(), Some("127.0.0.1" | "localhost" | "[::1]")), + "local GPU endpoint must be loopback HTTP" + ); + eyre::ensure!( + !args.execute_only && args.max_lag == 0, + "durable local mode requires proving and never skips lagging blocks" + ); + let root = args + .state_dir + .as_ref() + .ok_or_else(|| eyre::eyre!("local proving requires --state-dir"))?; + eyre::ensure!(args.expected_elf_id.is_some(), "local proving requires --expected-elf-id"); + let state = Arc::new(State::open( + root, + Identity { + namespace: std::env::var("FLEET_APP_NAMESPACE")?, + tenant: std::env::var("FLEET_APP_TENANT")?, + chain_id: 1, + cluster_id: args.eth_proofs_cluster_id, + elf_id: elf_id.clone(), + interval: args.block_interval, + residue: args.block_residue % args.block_interval, + }, + args.start_block, + )?); + // FullExecutor's verification-key file belongs to this replica's storage. + std::env::set_current_dir(std::fs::canonicalize(root)?)?; + Some(state) + } else { + eyre::ensure!(args.state_dir.is_none(), "durable worker state requires local proving"); + None + }; + eyre::ensure!(!args.latest_block || state.is_some(), "--latest-block requires local mode"); + info!(%elf_id, local = state.is_some(), "starting EthProofs app pipeline"); let block_execution_strategy_factory = create_eth_block_execution_strategy_factory(&config.genesis, None); @@ -52,25 +114,102 @@ async fn main() -> eyre::Result<()> { args.eth_proofs_endpoint, args.eth_proofs_api_token, ); + let eth_proofs_client = match &state { + Some(state) => eth_proofs_client.with_state(state.clone()), + None => eth_proofs_client, + }; + let reporter = eth_proofs_client.start_reporter(); + let (shutdown_tx, mut shutdown) = tokio::sync::watch::channel(false); + if state.is_some() { + tokio::spawn(async move { + #[cfg(unix)] + { + let mut terminate = + tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) + .unwrap(); + tokio::select! { _ = terminate.recv() => {}, _ = tokio::signal::ctrl_c() => {} } + } + #[cfg(not(unix))] + { + let _ = tokio::signal::ctrl_c().await; + } + info!("draining EthProofs worker; finish the current proof and persist its cursor"); + let _ = shutdown_tx.send(true); + }); + } + let alerting_client = args.pager_duty_integration_key.map(AlertingClient::new); - let ws = WsConnect::new(args.ws_rpc_url); - #[allow(deprecated)] - let ws_provider = ProviderBuilder::new().on_ws(ws).await?; let http_provider = create_provider(args.http_rpc_url); let debug_http_provider = create_provider(args.debug_http_rpc_url); - - // Subscribe to block headers. - let subscription = ws_provider.subscribe_blocks().await?; - let mut stream = - subscription.into_stream().filter(|h| ready(h.number % args.block_interval == 0)); - - // let mut builder = ProverClient::builder().cuda(); - if let Some(_endpoint) = &args.moongate_endpoint { - // builder = builder.with_moongate_endpoint(endpoint) - } - - let client = Arc::new(ProverClient::new()); + eyre::ensure!( + http_provider.get_chain_id().await? == 1, + "EthProofs worker requires Ethereum mainnet RPC" + ); + let block_interval = args.block_interval; + let block_residue = args.block_residue % block_interval; + // Local mode uses HTTP head polling: a WS disconnect cannot discard the cursor. + let ws_provider = if state.is_none() { + #[allow(deprecated)] + let provider = ProviderBuilder::new() + .on_ws(WsConnect::new( + args.ws_rpc_url + .ok_or_else(|| eyre::eyre!("network proving requires --ws-rpc-url"))?, + )) + .await?; + Some(provider) + } else { + None + }; + let head_shutdown = shutdown.clone(); + let mut stream = if state.is_some() { + futures::stream::unfold( + (http_provider.clone(), None, head_shutdown), + |(provider, mut previous, shutdown)| async move { + loop { + if *shutdown.borrow() { + return None; + } + match provider.get_block_number().await { + Ok(head) if previous != Some(head) => { + previous = Some(head); + return Some((head, (provider, previous, shutdown))); + } + Ok(_) => {} + Err(err) => { + warn!(%err, "head RPC failed; retrying without advancing cursor") + } + } + tokio::time::sleep(Duration::from_secs(2)).await; + } + }, + ) + .boxed() + } else { + ws_provider + .as_ref() + .unwrap() + .subscribe_blocks() + .await? + .into_stream() + .filter(move |h| ready(h.number % block_interval == block_residue)) + .map(|h| h.number) + .boxed() + }; + let client = if let Some(endpoint) = args.local_gpu_endpoint { + let endpoint = endpoint.to_string(); + Arc::new( + tokio::task::spawn_blocking(move || ProverClient { + prover: Box::new(CudaProver::new( + ZKMProver::new(), + ZKMGpuServer::External { endpoint }, + )), + }) + .await?, + ) + } else { + Arc::new(ProverClient::new()) + }; let executor = FullExecutor::, _>::try_new( http_provider.clone(), @@ -85,19 +224,299 @@ async fn main() -> eyre::Result<()> { info!("Latest block number: {}", http_provider.get_block_number().await?); - while let Some(header) = stream.next().await { - // Wait for the block to be avaliable in the HTTP provider - executor.wait_for_block(header.number).await?; + // Two-stage pipeline. The fetcher pulls headers off the subscription, + // fetches the block + witness and runs the native execution; the prover + // loop below consumes the prepared inputs one at a time. Block N+1's + // fetch therefore overlaps block N's proof instead of leaving the cards + // idle for the RPC round trips. + let executor = Arc::new(executor); + let alerting_client = Arc::new(alerting_client); + let (mut tx, mut rx) = mpsc::channel(args.prefetch_depth.max(1)); + let (latest_tx, mut latest_rx) = tokio::sync::watch::channel(None); + // Recover a completed proof before choosing a fresh head. Only this prover + // owns the durable cursor; preparations never advance or delete its inputs. + if args.latest_block { + let state = state.as_ref().unwrap(); + if let Some(number) = state.next_block() { + if state.is_committed(number)? { + state.advance(number, true)?; + } + } + } + let fetcher = { + let executor = executor.clone(); + let alerting_client = alerting_client.clone(); + let max_lag = args.max_lag; + let state = state.clone(); + let preparation_shutdown = shutdown.clone(); + let latest_block = args.latest_block; + let head_provider = http_provider.clone(); + let prepare_concurrency = args.prepare_concurrency; + tokio::spawn(async move { + if latest_block { + let minimum = state.as_ref().unwrap().next_block().unwrap_or(0); + return latest::run( + prepare_concurrency, + minimum, + block_interval, + block_residue, + latest_tx, + preparation_shutdown, + || { + let provider = head_provider.clone(); + async move { Ok(provider.get_block_number().await?) } + }, + |number| { + let executor = executor.clone(); + async move { + executor.wait_for_block(number).await?; + let input = executor.prepare(number).await?; + Ok(Arc::new(bincode::serialize(&input)?)) + } + }, + ) + .await; + } + // The subscription is only a wake-up: it says how far the chain + // is. Which block to prepare next is a cursor that advances by + // `block_interval`, so falling behind never skips a block — the + // backlog is worked through in order (unless `max_lag` says to + // drop it). A header stream that lags drops headers; the cursor + // does not. + let mut head = 0u64; + let mut next = state.as_ref().and_then(|s| s.next_block()).unwrap_or(0); + loop { + if *preparation_shutdown.borrow() { + break; + } + if next == 0 || next > head { + match stream.next().await { + Some(header) => { + head = head.max(header); + if next == 0 { + // The stream only delivers this instance's + // residue class, so the cursor starts aligned. + next = header - + ((header + block_interval - block_residue) % block_interval); + if let Some(state) = &state { + state.initialize(next)?; + } + } + continue; + } + None => break, + } + } + // Absorb whatever headers are already queued so `head` is fresh. + while let Some(Some(header)) = stream.next().now_or_never() { + head = head.max(header); + } - if let Err(err) = executor.execute(header.number).await { - let error_message = format!("Error handling block {}: {err}", header.number); - error!(error_message); + let number = next; + next += block_interval; + if max_lag > 0 && head - number > max_lag { + warn!("skipping block {number}: {} behind the newest header", head - number); + continue; + } - if let Some(alerting_client) = &alerting_client { - alerting_client.send_alert(error_message).await; + if let Some(state) = &state { + if state.is_committed(number)? { + if tx.send((number, None)).await.is_err() { + break; + } + continue; + } + } + // Retry the same block; a transient preparation failure must not skip it. + loop { + let prepared = match executor.wait_for_block(number).await { + Ok(()) => { + if let Some(state) = &state { + match state.input(number)? { + Some(bytes) => Ok(bincode::deserialize(&bytes)?), + None => executor.prepare(number).await, + } + } else { + executor.prepare(number).await + } + } + Err(err) => Err(err), + }; + match prepared { + Ok(client_input) => { + if let Some(state) = &state { + state.save_input(number, &bincode::serialize(&client_input)?)?; + } + if tx.send((number, Some(client_input))).await.is_err() { + return Ok::<(), eyre::Report>(()); + } + break; + } + Err(err) => { + report_error(&alerting_client, number, err).await; + tokio::time::sleep(Duration::from_secs(5)).await; + } + } + } } + Ok::<(), eyre::Report>(()) + }) + }; + + // NOT pipelined, deliberately. Sending block N+1's request early is + // worth ~0.3 s of transfer per block, but the server parks a session + // guard between a block's core and its compress and a new core request + // drops it: a request that lands in that window lets two blocks + // interleave on one card, which is what the guard is there to stop. + 'worker: loop { + if *shutdown.borrow() { + break; } + let next = if args.latest_block { + loop { + let prepared = latest_rx.borrow_and_update().clone(); + if let Some((number, bytes)) = prepared { + let state = state.as_ref().unwrap(); + if state.next_block().is_none_or(|next| number >= next) { + state.initialize(number)?; + let next = state.next_block().unwrap(); + if number > next { + warn!( + from = next, + to = number, + "skipping lagging blocks to newest prepared head" + ); + state.skip_to(number)?; + } + state.save_input(number, &bytes)?; + break Some((number, Some(bincode::deserialize(&bytes)?))); + } + } + tokio::select! { + changed = latest_rx.changed() => { + if changed.is_err() { break None; } + }, + _ = shutdown.changed() => break None, + } + } + } else { + tokio::select! { + next = rx.next() => next, + _ = shutdown.changed(), if state.is_some() => None, + } + }; + let Some((number, client_input)) = next else { + break; + }; + if let Some(state) = &state { + while state.pending_count()? >= args.max_pending_reports { + warn!(number, "report outbox full; waiting before starting another proof"); + tokio::select! { + _ = tokio::time::sleep(Duration::from_secs(3)) => {}, + _ = shutdown.changed() => break, + } + } + if *shutdown.borrow() { + break; + } + } + if let Some(client_input) = client_input { + let committed = + state.as_ref().map(|s| s.is_committed(number)).transpose()?.unwrap_or(false); + if !committed { + if let Some(state) = &state { + let block = loop { + let result = tokio::select! { + block = http_provider.get_block_by_number(number.into()) => block, + _ = shutdown.changed() => break 'worker, + }; + match result { + Ok(Some(block)) => break block, + Ok(None) => warn!(number, "waiting for prepared block to be available"), + Err(err) => { + warn!(number, %err, "canonical block lookup failed; retrying") + } + } + tokio::time::sleep(Duration::from_secs(3)).await; + }; + if block.header.hash != client_input.current_block.header.hash_slow() { + state.discard_inputs_from(number)?; + eyre::bail!( + "prepared inputs invalidated by a reorg; restart from durable cursor" + ); + } + } + if let Err(err) = executor.prove_prepared(client_input).await { + report_error(&alerting_client, number, err).await; + // The replica lifecycle recovers failed GPU servers; input stays durable. + if state.is_some() { + return Err(eyre::eyre!( + "local proof failed; durable input retained for restart" + )); + } + } + } + } + if let Some(state) = &state { + state.advance(number, true)?; + } + } + if *shutdown.borrow() { + fetcher.abort(); + } else { + fetcher.await??; + } + reporter.abort(); + if state.is_some() && !*shutdown.borrow() { + eyre::bail!("local worker preparation stream ended unexpectedly"); + } + + Ok(()) +} + +fn latest_selected_block(head: u64, interval: u64, residue: u64) -> Option { + let remainder = head % interval; + let distance = + if remainder >= residue { remainder - residue } else { interval - (residue - remainder) }; + head.checked_sub(distance) +} + +#[cfg(test)] +mod selection_tests { + use super::latest_selected_block; + + #[test] + fn newest_selection_aligns_to_the_stream_and_handles_early_heads() { + assert_eq!(latest_selected_block(123, 1, 0), Some(123)); + assert_eq!(latest_selected_block(100, 10, 2), Some(92)); + assert_eq!(latest_selected_block(103, 10, 2), Some(102)); + assert_eq!(latest_selected_block(1, 10, 2), None); + assert_eq!(latest_selected_block(u64::MAX, u64::MAX, u64::MAX - 1), Some(u64::MAX - 1)); } +} + +async fn report_error(alerting_client: &Option, number: u64, err: eyre::Report) { + let error_message = format!("Error handling block {number}: {err}"); + error!(error_message); + if let Some(alerting_client) = alerting_client { + alerting_client.send_alert(error_message).await; + } +} + +/// Actor death must not leave an orphan holding the durable stream lock. +fn exit_with_parent() -> eyre::Result<()> { + if env::var("FLEET_EXIT_WITH_PARENT").as_deref() != Ok("true") { + return Ok(()); + } + #[cfg(target_os = "linux")] + unsafe { + let parent = libc::getppid(); + eyre::ensure!(parent > 1, "Fleet worker has no live parent"); + if libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGTERM) != 0 { + return Err(std::io::Error::last_os_error().into()); + } + eyre::ensure!(libc::getppid() == parent, "Fleet parent exited during startup"); + } Ok(()) } diff --git a/bin/eth-proofs/src/state.rs b/bin/eth-proofs/src/state.rs new file mode 100644 index 0000000..571aaad --- /dev/null +++ b/bin/eth-proofs/src/state.rs @@ -0,0 +1,386 @@ +//! Restart-safe state for a single, machine-pinned EthProofs stream. +use eyre::{bail, Context}; +use fs2::FileExt; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use sha2::{Digest, Sha256}; +use std::{ + fs::{self, File, OpenOptions}, + io::Write, + path::{Path, PathBuf}, + sync::Mutex, +}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct Identity { + pub namespace: String, + pub tenant: String, + pub chain_id: u64, + pub cluster_id: u64, + pub elf_id: String, + pub interval: u64, + pub residue: u64, +} +#[derive(Debug, Clone, Serialize, Deserialize)] +struct Checkpoint { + version: u32, + identity: Identity, + next_block: Option, + last_proved: Option, +} +#[derive(Debug, Serialize, Deserialize)] +struct Committed { + block: u64, + proof_hash: String, + public_values_hash: String, + report: Value, +} +pub struct State { + root: PathBuf, + _lock: File, + checkpoint: Mutex, + report_ready: tokio::sync::Notify, +} +impl State { + pub fn open(root: &Path, identity: Identity, start: Option) -> eyre::Result { + if identity.interval == 0 || identity.residue >= identity.interval { + bail!("invalid block interval or residue"); + } + if start.is_some_and(|n| n % identity.interval != identity.residue) { + bail!("start block does not belong to this stream's residue"); + } + fs::create_dir_all(root)?; + let lock = OpenOptions::new() + .create(true) + .truncate(false) + .read(true) + .write(true) + .open(root.join("worker.lock"))?; + lock.try_lock_exclusive().wrap_err("another worker owns this storage root")?; + for name in ["inputs", "outputs", "outbox", "reported"] { + fs::create_dir_all(root.join(name))?; + } + let path = root.join("checkpoint.json"); + let checkpoint = if path.exists() { + let checkpoint: Checkpoint = serde_json::from_slice(&fs::read(path)?)?; + if checkpoint.version != 1 || checkpoint.identity != identity { + bail!("worker state identity differs from configured chain, cluster, program or stream"); + } + checkpoint + } else { + Checkpoint { version: 1, identity, next_block: start, last_proved: None } + }; + let state = Self { + root: fs::canonicalize(root)?, + _lock: lock, + checkpoint: Mutex::new(checkpoint), + report_ready: tokio::sync::Notify::new(), + }; + state.save_checkpoint()?; + state.recover_reports()?; + Ok(state) + } + fn save_checkpoint(&self) -> eyre::Result<()> { + atomic_write( + &self.root.join("checkpoint.json"), + &serde_json::to_vec(&*self.checkpoint.lock().unwrap())?, + ) + } + pub fn next_block(&self) -> Option { + self.checkpoint.lock().unwrap().next_block + } + pub fn initialize(&self, block: u64) -> eyre::Result<()> { + { + let mut c = self.checkpoint.lock().unwrap(); + if c.next_block.is_none() { + c.next_block = Some(block); + } + } + self.save_checkpoint() + } + pub fn advance(&self, block: u64, proved: bool) -> eyre::Result<()> { + { + let mut c = self.checkpoint.lock().unwrap(); + if c.next_block != Some(block) { + bail!("refusing to advance out of order"); + } + c.next_block = Some( + block + .checked_add(c.identity.interval) + .ok_or_else(|| eyre::eyre!("block cursor overflow"))?, + ); + if proved { + c.last_proved = Some(block); + } + } + self.save_checkpoint()?; + let input = self.root.join("inputs").join(format!("{block}.bin")); + if input.exists() { + fs::remove_file(input)?; + } + let hash = self.root.join("inputs").join(format!("{block}.sha256")); + if hash.exists() { + fs::remove_file(hash)?; + } + sync_dir(&self.root.join("inputs"))?; + Ok(()) + } + + /// Skip unproved input backlog without changing completed outputs or reports. + pub fn skip_to(&self, block: u64) -> eyre::Result<()> { + { + let mut c = self.checkpoint.lock().unwrap(); + let next = c.next_block.ok_or_else(|| eyre::eyre!("cursor is not initialized"))?; + if block < next || block % c.identity.interval != c.identity.residue { + bail!("refusing to skip backwards or outside the selected residue"); + } + c.next_block = Some(block); + } + self.save_checkpoint()?; + for entry in fs::read_dir(self.root.join("inputs"))? { + let path = entry?.path(); + if path + .file_stem() + .and_then(|s| s.to_str()) + .and_then(|s| s.parse::().ok()) + .is_some_and(|number| number < block) + { + fs::remove_file(path)?; + } + } + sync_dir(&self.root.join("inputs")) + } + pub fn input(&self, block: u64) -> eyre::Result>> { + let p = self.root.join("inputs").join(format!("{block}.bin")); + if !p.exists() { + return Ok(None); + } + let bytes = fs::read(p)?; + let hash = fs::read_to_string(self.root.join("inputs").join(format!("{block}.sha256")))?; + if digest(&bytes) != hash { + bail!("prepared input checksum mismatch"); + } + Ok(Some(bytes)) + } + pub fn save_input(&self, block: u64, bytes: &[u8]) -> eyre::Result<()> { + // A partial write can always be prepared again; the binary is published last. + atomic_write( + &self.root.join("inputs").join(format!("{block}.sha256")), + digest(bytes).as_bytes(), + )?; + atomic_write(&self.root.join("inputs").join(format!("{block}.bin")), bytes) + } + pub fn commit( + &self, + block: u64, + proof: &[u8], + public_values: &[u8], + report: Value, + ) -> eyre::Result<()> { + let dir = self.root.join("outputs").join(block.to_string()); + fs::create_dir_all(&dir)?; + sync_dir(&self.root.join("outputs"))?; + atomic_write(&dir.join("proof.bin"), proof)?; + atomic_write(&dir.join("public_values.bin"), public_values)?; + let committed = Committed { + block, + proof_hash: digest(proof), + public_values_hash: digest(public_values), + report, + }; + atomic_write(&dir.join("manifest.json"), &serde_json::to_vec(&committed)?)?; + self.ensure_report(&committed)?; + self.report_ready.notify_one(); + Ok(()) + } + pub fn is_committed(&self, block: u64) -> eyre::Result { + let dir = self.root.join("outputs").join(block.to_string()); + if !dir.join("manifest.json").exists() { + return Ok(false); + } + let m: Committed = serde_json::from_slice(&fs::read(dir.join("manifest.json"))?)?; + if m.block != block || + digest(&fs::read(dir.join("proof.bin"))?) != m.proof_hash || + digest(&fs::read(dir.join("public_values.bin"))?) != m.public_values_hash + { + bail!("committed output checksum mismatch"); + } + self.ensure_report(&m)?; + Ok(true) + } + fn ensure_report(&self, m: &Committed) -> eyre::Result<()> { + if !self.root.join("reported").join(format!("{}.json", m.block)).exists() { + let path = self.root.join("outbox").join(format!("{}.json", m.block)); + if !path.exists() { + atomic_write(&path, &serde_json::to_vec(&m.report)?)?; + } + } + Ok(()) + } + fn recover_reports(&self) -> eyre::Result<()> { + // Only the current block can be committed before its outbox/cursor write. + // Earlier blocks advanced only after both were persisted. + if let Some(block) = self.next_block() { + self.is_committed(block)?; + } + Ok(()) + } + pub fn discard_inputs_from(&self, block: u64) -> eyre::Result<()> { + for entry in fs::read_dir(self.root.join("inputs"))? { + let path = entry?.path(); + if path + .file_stem() + .and_then(|s| s.to_str()) + .and_then(|s| s.parse::().ok()) + .is_some_and(|n| n >= block) + { + fs::remove_file(path)?; + } + } + sync_dir(&self.root.join("inputs")) + } + pub async fn report_ready(&self) { + self.report_ready.notified().await; + } + pub fn pending_count(&self) -> eyre::Result { + Ok(fs::read_dir(self.root.join("outbox"))? + .filter_map(Result::ok) + .filter(|e| e.path().extension().and_then(|s| s.to_str()) == Some("json")) + .count()) + } + pub fn pending(&self) -> eyre::Result> { + let mut blocks = Vec::new(); + for entry in fs::read_dir(self.root.join("outbox"))? { + let path = entry?.path(); + if path.extension().and_then(|s| s.to_str()) != Some("json") { + continue; + } + blocks.push(path.file_stem().unwrap().to_str().unwrap().parse::()?); + } + blocks.sort_unstable(); + let mut pending = Vec::new(); + // Load one proof at a time so an API outage cannot inflate reporter memory. + if let Some(block) = blocks.first() { + pending.push(( + *block, + serde_json::from_slice(&fs::read( + self.root.join("outbox").join(format!("{block}.json")), + )?)?, + )); + } + Ok(pending) + } + pub fn acknowledge(&self, block: u64) -> eyre::Result<()> { + let source = self.root.join("outbox").join(format!("{block}.json")); + if source.exists() { + fs::rename(source, self.root.join("reported").join(format!("{block}.json")))?; + sync_dir(&self.root.join("reported"))?; + sync_dir(&self.root.join("outbox"))?; + } + Ok(()) + } +} +pub fn atomic_write(path: &Path, bytes: &[u8]) -> eyre::Result<()> { + let temp = path.with_extension("tmp"); + let mut file = OpenOptions::new().create(true).truncate(true).write(true).open(&temp)?; + file.write_all(bytes)?; + file.sync_all()?; + fs::rename(&temp, path)?; + sync_dir(path.parent().unwrap()) +} +fn sync_dir(path: &Path) -> eyre::Result<()> { + File::open(path)?.sync_all()?; + Ok(()) +} +fn digest(bytes: &[u8]) -> String { + hex::encode(Sha256::digest(bytes)) +} + +#[cfg(test)] +mod tests { + use super::*; + fn identity() -> Identity { + Identity { + namespace: "test".into(), + tenant: "ethproofs".into(), + chain_id: 1, + cluster_id: 8, + elf_id: "abc".into(), + interval: 1, + residue: 0, + } + } + #[test] + fn skip_preserves_completed_proofs_reports_and_restart_cursor() { + let root = tempfile::tempdir().unwrap(); + let state = State::open(root.path(), identity(), Some(10)).unwrap(); + state.commit(10, b"proof", b"values", serde_json::json!({"block_number":10})).unwrap(); + state.advance(10, true).unwrap(); + state.save_input(11, b"stale").unwrap(); + state.save_input(20, b"latest").unwrap(); + state.skip_to(20).unwrap(); + assert!(state.input(11).unwrap().is_none()); + assert_eq!(state.input(20).unwrap().unwrap(), b"latest"); + assert!(state.is_committed(10).unwrap()); + assert_eq!(state.pending_count().unwrap(), 1); + assert!(state.skip_to(19).is_err()); + drop(state); + let state = State::open(root.path(), identity(), None).unwrap(); + assert_eq!(state.next_block(), Some(20)); + assert_eq!(state.checkpoint.lock().unwrap().last_proved, Some(10)); + assert_eq!(state.pending_count().unwrap(), 1); + } + + #[test] + fn skip_rejects_a_block_outside_the_stream_residue() { + let root = tempfile::tempdir().unwrap(); + let mut scope = identity(); + scope.interval = 2; + scope.residue = 1; + let state = State::open(root.path(), scope, Some(11)).unwrap(); + assert!(state.skip_to(20).is_err()); + assert_eq!(state.next_block(), Some(11)); + } + #[test] + fn restart_recovers_proof_and_pending_report_without_reproving() { + let root = tempfile::tempdir().unwrap(); + let state = State::open(root.path(), identity(), Some(10)).unwrap(); + state.save_input(10, b"input").unwrap(); + state.commit(10, b"proof", b"values", serde_json::json!({"block_number":10})).unwrap(); + // Simulate the window after output commit, before cursor advancement. + fs::remove_file(root.path().join("outbox/10.json")).unwrap(); + drop(state); + let state = State::open(root.path(), identity(), None).unwrap(); + assert!(state.is_committed(10).unwrap()); + assert_eq!(state.pending().unwrap().len(), 1); + state.advance(10, true).unwrap(); + state.acknowledge(10).unwrap(); + drop(state); + let state = State::open(root.path(), identity(), None).unwrap(); + assert_eq!(state.next_block(), Some(11)); + assert!(state.pending().unwrap().is_empty()); + assert!(state.input(10).unwrap().is_none()); + } + #[test] + fn duplicate_owner_and_changed_program_are_rejected() { + let root = tempfile::tempdir().unwrap(); + let state = State::open(root.path(), identity(), Some(10)).unwrap(); + assert!(State::open(root.path(), identity(), None).is_err()); + drop(state); + let mut changed = identity(); + changed.elf_id = "other".into(); + assert!(State::open(root.path(), changed, None).is_err()); + } + #[test] + fn corrupted_input_or_output_is_not_reused() { + let root = tempfile::tempdir().unwrap(); + let state = State::open(root.path(), identity(), Some(10)).unwrap(); + state.save_input(10, b"input").unwrap(); + fs::write(root.path().join("inputs/10.bin"), b"bad").unwrap(); + assert!(state.input(10).is_err()); + state.commit(10, b"proof", b"values", Value::Null).unwrap(); + fs::write(root.path().join("outputs/10/proof.bin"), b"bad").unwrap(); + assert!(state.is_committed(10).is_err()); + assert!(state.advance(11, true).is_err()); + } +} diff --git a/bin/guest/Cargo.lock b/bin/guest/Cargo.lock index 00f6f4c..489896c 100644 --- a/bin/guest/Cargo.lock +++ b/bin/guest/Cargo.lock @@ -921,6 +921,19 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake3" +version = "1.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae" +dependencies = [ + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures 0.3.1", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -1094,7 +1107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20d9a563d167a9cce0f94153382b33cb6eded6dfabff03c69ad65a28ea1514e0" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "proptest", "serde_core", ] @@ -1126,6 +1139,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + [[package]] name = "convert_case" version = "0.10.0" @@ -1150,6 +1169,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.4.0" @@ -1606,12 +1634,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" -[[package]] -name = "gcd" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" - [[package]] name = "generic-array" version = "0.14.9" @@ -2061,7 +2083,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -2099,7 +2121,7 @@ dependencies = [ "hex", "serde_arrays", "sha2", - "spin", + "spin 0.9.8", ] [[package]] @@ -2108,7 +2130,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin", + "spin 0.9.8", ] [[package]] @@ -2241,7 +2263,6 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", - "rand 0.8.6", ] [[package]] @@ -2331,18 +2352,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "nums" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3c74f925fb8cfc49a8022f2afce48a0683b70f9e439885594e84c5edbf5b01" -dependencies = [ - "num-bigint 0.4.6", - "num-integer", - "num-traits", - "rand 0.8.6", -] - [[package]] name = "nybbles" version = "0.4.8" @@ -2397,136 +2406,157 @@ dependencies = [ "zkm-lib", ] +[[package]] +name = "p3-challenger" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" +dependencies = [ + "p3-field", + "p3-maybe-rayon", + "p3-monty-31", + "p3-symmetric", + "p3-util", + "tracing", +] + [[package]] name = "p3-dft" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-field", "p3-matrix", "p3-maybe-rayon", "p3-util", + "spin 0.10.1", "tracing", ] [[package]] name = "p3-field" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "num-bigint 0.4.6", - "num-integer", - "num-traits", - "nums", "p3-maybe-rayon", "p3-util", - "rand 0.8.6", + "paste", + "rand 0.10.3", "serde", "tracing", ] [[package]] name = "p3-koala-bear" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ + "p3-challenger", "p3-field", "p3-mds", "p3-monty-31", + "p3-poseidon1", "p3-poseidon2", "p3-symmetric", - "rand 0.8.6", - "serde", + "rand 0.10.3", ] [[package]] name = "p3-matrix" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-field", "p3-maybe-rayon", "p3-util", - "rand 0.8.6", + "rand 0.10.3", "serde", "tracing", - "transpose", ] [[package]] name = "p3-maybe-rayon" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" [[package]] name = "p3-mds" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", "p3-dft", "p3-field", - "p3-matrix", "p3-symmetric", "p3-util", - "rand 0.8.6", + "rand 0.10.3", ] [[package]] name = "p3-monty-31" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "num-bigint 0.4.6", "p3-dft", "p3-field", "p3-matrix", "p3-maybe-rayon", "p3-mds", + "p3-poseidon1", "p3-poseidon2", "p3-symmetric", "p3-util", - "rand 0.8.6", + "paste", + "rand 0.10.3", "serde", - "serde_json", + "spin 0.10.1", "tracing", - "transpose", +] + +[[package]] +name = "p3-poseidon1" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" +dependencies = [ + "p3-field", + "p3-symmetric", + "rand 0.10.3", ] [[package]] name = "p3-poseidon2" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "gcd", "p3-field", "p3-mds", "p3-symmetric", - "rand 0.8.6", - "serde", + "p3-util", + "rand 0.10.3", ] [[package]] name = "p3-symmetric" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "p3-field", + "p3-util", "serde", ] [[package]] name = "p3-util" -version = "0.1.0" -source = "git+https://github.com/ProjectZKM/Plonky3#faa24ca4597eebeecbf71b194b71c7d1a99b3f01" +version = "0.5.1" +source = "git+https://github.com/ProjectZKM/Plonky3?rev=4dd0d47a8176503fbaa7293c9f0e3b20004e16b2#4dd0d47a8176503fbaa7293c9f0e3b20004e16b2" dependencies = [ - "lock_api", "serde", + "transpose", ] [[package]] @@ -2842,6 +2872,15 @@ dependencies = [ "serde", ] +[[package]] +name = "rand" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" +dependencies = [ + "rand_core 0.10.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -2881,6 +2920,12 @@ dependencies = [ "serde", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rand_xorshift" version = "0.4.0" @@ -3826,7 +3871,7 @@ version = "0.10.9" source = "git+https://github.com/ziren-patches/RustCrypto-hashes?branch=patch-sha2-0.10.9#dbfdbd088ac7b55e03c0b9eb192278efe35d67dc" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -3893,6 +3938,15 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spin" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" +dependencies = [ + "lock_api", +] + [[package]] name = "spki" version = "0.7.3" @@ -4722,8 +4776,8 @@ dependencies = [ [[package]] name = "zkm-lib" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#7c2071eaa8d43d9d0cb76077ec94b9d98f33073e" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "bincode", "cfg-if", @@ -4735,10 +4789,11 @@ dependencies = [ [[package]] name = "zkm-primitives" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#7c2071eaa8d43d9d0cb76077ec94b9d98f33073e" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "bincode", + "blake3", "hex", "lazy_static", "num-bigint 0.4.6", @@ -4749,12 +4804,13 @@ dependencies = [ "p3-symmetric", "serde", "sha2", + "tracing", ] [[package]] name = "zkm-zkvm" -version = "1.2.5" -source = "git+https://github.com/ProjectZKM/Ziren#7c2071eaa8d43d9d0cb76077ec94b9d98f33073e" +version = "2.0.0" +source = "git+https://github.com/ProjectZKM/Ziren#0dd65a15db3d7bad5cf582c5dbc7492440ea2830" dependencies = [ "bincode", "cfg-if", diff --git a/bin/host/tests/cycle_count_diff.rs b/bin/host/tests/cycle_count_diff.rs index cf8c5e9..91285d8 100644 --- a/bin/host/tests/cycle_count_diff.rs +++ b/bin/host/tests/cycle_count_diff.rs @@ -39,7 +39,7 @@ async fn test_in_zkvm() { }; let rpc_url = Url::parse(env::var("RPC_1").unwrap().as_str()).expect("invalid rpc url"); - let elf = include_elf!("guest").to_vec(); + let elf = include_elf!("reth").to_vec(); let block_execution_strategy_factory = create_eth_block_execution_strategy_factory(&config.genesis, config.custom_beneficiary); diff --git a/crates/executor/guest/src/io.rs b/crates/executor/guest/src/io.rs index 1054f17..110f7f4 100644 --- a/crates/executor/guest/src/io.rs +++ b/crates/executor/guest/src/io.rs @@ -147,11 +147,22 @@ impl DatabaseRef for TrieDB<'_> { let hashed_address = keccak256(address); let hashed_address = hashed_address.as_slice(); - let storage_trie = self - .inner - .storage_tries - .get(hashed_address) - .expect("A storage trie must be provided for each account"); + let storage_trie = match self.inner.storage_tries.get(hashed_address) { + Some(trie) => trie, + None => { + // A witness may omit storage for an absent account or an account + // whose authenticated storage root is empty. Never substitute + // zero for an unresolved account proof or non-empty storage. + let account = self.inner.state_trie.get_rlp::(hashed_address) + .map_err(|err| ProviderError::TrieWitnessError(err.to_string()))?; + if account.map_or(EMPTY_ROOT_HASH, |a| a.storage_root) == EMPTY_ROOT_HASH { + return Ok(U256::ZERO); + } + return Err(ProviderError::TrieWitnessError(format!( + "missing non-empty storage trie for {address}" + ))); + } + }; Ok(storage_trie .get_rlp::(keccak256(index.to_be_bytes::<32>()).as_slice()) @@ -235,3 +246,38 @@ pub trait WitnessInput { Ok(TrieDB::new(state, block_hashes, bytecodes_by_hash)) } } + +#[cfg(test)] +mod tests { + use super::*; + + fn state() -> EthereumState { + EthereumState { state_trie: Default::default(), storage_tries: HashMap::default() } + } + + #[test] + fn omitted_storage_for_absent_account_is_zero() { + let state = state(); + let db = TrieDB::new(&state, HashMap::default(), HashMap::default()); + assert_eq!(db.storage_ref(Address::repeat_byte(1), U256::from(7)).unwrap(), U256::ZERO); + } + + #[test] + fn omitted_storage_with_authenticated_empty_root_is_zero() { + let mut state = state(); + let address = Address::repeat_byte(2); + state.state_trie.insert_rlp(keccak256(address).as_slice(), TrieAccount::default()).unwrap(); + let db = TrieDB::new(&state, HashMap::default(), HashMap::default()); + assert_eq!(db.storage_ref(address, U256::from(7)).unwrap(), U256::ZERO); + } + + #[test] + fn omitted_non_empty_storage_is_rejected() { + let mut state = state(); + let address = Address::repeat_byte(3); + let account = TrieAccount { storage_root: B256::repeat_byte(4), ..Default::default() }; + state.state_trie.insert_rlp(keccak256(address).as_slice(), account).unwrap(); + let db = TrieDB::new(&state, HashMap::default(), HashMap::default()); + assert!(db.storage_ref(address, U256::from(7)).is_err()); + } +} diff --git a/crates/executor/host/src/full_executor.rs b/crates/executor/host/src/full_executor.rs index 2785c03..72c810a 100644 --- a/crates/executor/host/src/full_executor.rs +++ b/crates/executor/host/src/full_executor.rs @@ -271,14 +271,12 @@ where } Ok(()) } -} -impl BlockExecutor for FullExecutor -where - C: ExecutorComponents, - P: Provider + Clone + std::fmt::Debug, -{ - async fn execute(&self, block_number: u64) -> eyre::Result<()> { + /// Fetch the block and witness and execute natively, without starting GPU proving. + pub async fn prepare( + &self, + block_number: u64, + ) -> eyre::Result> { self.hooks.on_execution_start(block_number).await?; let client_input_from_cache = self.config.cache_dir.as_ref().and_then(|cache_dir| { @@ -333,9 +331,25 @@ where }; info!("Block {} executed in {:?}", block_number, now.elapsed()); - self.process_client(client_input, &self.hooks, self.config.prove_mode).await?; + Ok(client_input) + } - Ok(()) + /// Prove a prepared input; callers serialize core and compression together. + pub async fn prove_prepared( + &self, + client_input: ClientExecutorInput, + ) -> eyre::Result<()> { + self.process_client(client_input, &self.hooks, self.config.prove_mode).await + } +} + +impl BlockExecutor for FullExecutor +where + C: ExecutorComponents, + P: Provider + Clone + std::fmt::Debug, +{ + async fn execute(&self, block_number: u64) -> eyre::Result<()> { + self.prove_prepared(self.prepare(block_number).await?).await } fn client(&self) -> Arc { diff --git a/crates/mpt/src/lib.rs b/crates/mpt/src/lib.rs index d9f9d1d..3f3415b 100644 --- a/crates/mpt/src/lib.rs +++ b/crates/mpt/src/lib.rs @@ -2,7 +2,7 @@ use alloy_primitives::{keccak256, map::HashMap, Address, B256}; use alloy_rpc_types::EIP1186AccountProofResponse; -use reth_trie::{AccountProof, HashedPostState, HashedStorage, TrieAccount}; +use reth_trie::{AccountProof, HashedPostState, HashedStorage, TrieAccount, EMPTY_ROOT_HASH}; use serde::{Deserialize, Serialize}; #[cfg(feature = "execution-witness")] @@ -93,24 +93,14 @@ impl EthereumState { .get(hashed_address) .cloned() .unwrap_or_else(|| HashedStorage::new(false)); - let storage_root = { - let storage_trie = self.storage_tries.entry(*hashed_address).or_default(); - - if state_storage.wiped { - storage_trie.clear(); - } - - for (key, value) in state_storage.storage.iter() { - let key = key.as_slice(); - if value.is_zero() { - storage_trie.delete(key).unwrap(); - } else { - storage_trie.insert_rlp(key, *value).unwrap(); - } - } - - storage_trie.hash() - }; + let storage_root = + self.storage_root_after_update(*hashed_address, state_storage); + + if account.is_empty() && storage_root == EMPTY_ROOT_HASH { + self.state_trie.delete(hashed_address.as_slice()).unwrap(); + self.storage_tries.remove(hashed_address); + continue; + } let state_account = TrieAccount { nonce: account.nonce, @@ -122,11 +112,48 @@ impl EthereumState { } None => { self.state_trie.delete(hashed_address.as_slice()).unwrap(); + self.storage_tries.remove(hashed_address); } } } } + fn storage_root_after_update( + &mut self, + hashed_address: B256, + state_storage: &HashedStorage, + ) -> B256 { + if state_storage.is_empty() { + if let Some(storage_trie) = self.storage_tries.get(&hashed_address) { + return storage_trie.hash() + } + + return self + .state_trie + .get_rlp::(hashed_address.as_slice()) + .unwrap() + .map(|account| account.storage_root) + .unwrap_or(EMPTY_ROOT_HASH) + } + + let storage_trie = self.storage_tries.entry(hashed_address).or_default(); + + if state_storage.wiped { + storage_trie.clear(); + } + + for (key, value) in state_storage.storage.iter() { + let key = key.as_slice(); + if value.is_zero() { + storage_trie.delete(key).unwrap(); + } else { + storage_trie.insert_rlp(key, *value).unwrap(); + } + } + + storage_trie.hash() + } + /// Computes the state root. pub fn state_root(&self) -> B256 { self.state_trie.hash() @@ -149,3 +176,57 @@ pub enum FromProofError { #[error("Error decoding proofs from bytes, {}", .0)] DecodingError(#[from] Error), } + +#[cfg(test)] +mod tests { + use alloy_primitives::{b256, U256}; + + use super::*; + + #[test] + fn update_removes_empty_account_with_empty_storage_root() { + let hashed_address = B256::repeat_byte(0x11); + let post_state = + HashedPostState::default().with_accounts([(hashed_address, Some(Default::default()))]); + let mut state = + EthereumState { state_trie: MptNode::default(), storage_tries: HashMap::default() }; + + state.update(&post_state); + + assert!(state.state_trie.get(hashed_address.as_slice()).unwrap().is_none()); + assert_eq!(state.state_root(), EMPTY_ROOT_HASH); + assert!(!state.storage_tries.contains_key(&hashed_address)); + } + + #[test] + fn update_preserves_storage_root_when_storage_trie_is_not_revealed() { + let hashed_address = B256::repeat_byte(0x22); + let storage_root = + b256!("3333333333333333333333333333333333333333333333333333333333333333"); + let mut state = + EthereumState { state_trie: MptNode::default(), storage_tries: HashMap::default() }; + state + .state_trie + .insert_rlp( + hashed_address.as_slice(), + TrieAccount { + nonce: 0, + balance: U256::from(1), + storage_root, + code_hash: TrieAccount::default().code_hash, + }, + ) + .unwrap(); + let mut post_state = HashedPostState::default() + .with_accounts([(hashed_address, Some(Default::default()))]); + post_state.accounts.get_mut(&hashed_address).unwrap().as_mut().unwrap().balance = + U256::from(2); + + state.update(&post_state); + + let account = + state.state_trie.get_rlp::(hashed_address.as_slice()).unwrap().unwrap(); + assert_eq!(account.balance, U256::from(2)); + assert_eq!(account.storage_root, storage_root); + } +} diff --git a/crates/provider/Cargo.toml b/crates/provider/Cargo.toml index 9ca4a47..623a66f 100644 --- a/crates/provider/Cargo.toml +++ b/crates/provider/Cargo.toml @@ -9,9 +9,11 @@ workspace = true [dependencies] url.workspace = true +# Alloy shares this client; decode gzip responses for large execution witnesses. +reqwest = { workspace = true, features = ["gzip"] } # alloy alloy-provider.workspace = true alloy-json-rpc.workspace = true alloy-rpc-client.workspace = true -alloy-transport.workspace = true \ No newline at end of file +alloy-transport.workspace = true diff --git a/crates/storage/rpc-db/Cargo.toml b/crates/storage/rpc-db/Cargo.toml index 4f098c8..3d27261 100644 --- a/crates/storage/rpc-db/Cargo.toml +++ b/crates/storage/rpc-db/Cargo.toml @@ -21,20 +21,32 @@ revm-state.workspace = true # alloy alloy-consensus = { workspace = true, optional = true } +alloy-eips = { workspace = true, optional = true } alloy-primitives.workspace = true alloy-provider.workspace = true +alloy-rpc-types = { workspace = true, optional = true } +alloy-rpc-types-debug = { workspace = true, optional = true } alloy-transport.workspace = true alloy-rlp = { workspace = true, optional = true } alloy-trie = { workspace = true, optional = true, features = ["ethereum"] } +serde = { workspace = true, optional = true } + mpt.workspace = true primitives.workspace = true +[dev-dependencies] +serde_json.workspace = true + [features] default = ["execution-witness"] execution-witness = [ - "dep:alloy-consensus", + "dep:alloy-consensus", + "dep:alloy-eips", + "dep:alloy-rpc-types", + "dep:alloy-rpc-types-debug", "dep:alloy-rlp", "dep:alloy-trie", + "dep:serde", "alloy-provider/debug-api" ] diff --git a/crates/storage/rpc-db/src/execution_witness.rs b/crates/storage/rpc-db/src/execution_witness.rs index 60c24c1..8e1c2e4 100644 --- a/crates/storage/rpc-db/src/execution_witness.rs +++ b/crates/storage/rpc-db/src/execution_witness.rs @@ -1,16 +1,20 @@ -use std::{collections::BTreeMap, marker::PhantomData}; +use std::{collections::BTreeMap, marker::PhantomData, sync::RwLock}; use alloy_consensus::Header; +use alloy_eips::BlockNumberOrTag; use alloy_primitives::{map::HashMap, Address, B256}; -use alloy_provider::{ext::DebugApi, Network, Provider}; -use alloy_rlp::Decodable; +use alloy_provider::{Network, Provider}; +use alloy_rlp::{Decodable, Encodable}; +use alloy_rpc_types::Header as RpcHeader; +use alloy_rpc_types_debug::ExecutionWitness; use alloy_trie::TrieAccount; use async_trait::async_trait; use mpt::EthereumState; -use reth_storage_errors::ProviderError; +use reth_storage_errors::{db::DatabaseError, ProviderError}; use revm_database::{BundleState, DatabaseRef}; -use revm_primitives::{keccak256, ruint::aliases::U256, StorageKey, StorageValue}; +use revm_primitives::{keccak256, ruint::aliases::U256, StorageKey, StorageValue, KECCAK_EMPTY}; use revm_state::{AccountInfo, Bytecode}; +use serde::Deserialize; use crate::{RpcDb, RpcDbError}; @@ -18,10 +22,12 @@ use crate::{RpcDb, RpcDbError}; pub struct ExecutionWitnessRpcDb { /// The provider which fetches data. pub provider: P, + /// Parent block used to fetch bytecode omitted from the execution witness. + pub state_block_number: u64, /// The cached state. pub state: EthereumState, /// The cached bytecodes. - pub codes: HashMap, + pub codes: RwLock>, pub ancestor_headers: BTreeMap, @@ -32,7 +38,7 @@ impl + Clone, N: Network> ExecutionWitnessRpcDb { /// Create a new [`ExecutionWitnessRpcDb`]. pub async fn new(provider: P, block_number: u64, state_root: B256) -> Result { tracing::info!("Fetching execution witness for block {}", block_number); - let execution_witness = provider.debug_execution_witness(block_number.into()).await?; + let execution_witness = fetch_execution_witness(&provider, block_number).await?; tracing::info!("Fetched execution witness for block done {}", block_number); let state = EthereumState::from_execution_witness(&execution_witness, state_root); @@ -50,10 +56,120 @@ impl + Clone, N: Network> ExecutionWitnessRpcDb { .map(|h| (h.number, h)) .collect(); - let db = Self { provider, state, codes, ancestor_headers, phantom: PhantomData }; + let db = Self { + provider, + state_block_number: block_number.saturating_sub(1), + state, + codes: RwLock::new(codes), + ancestor_headers, + phantom: PhantomData, + }; Ok(db) } + + fn account_code( + &self, + address: Address, + expected_hash: B256, + ) -> Result, ProviderError> { + if expected_hash == KECCAK_EMPTY || expected_hash == B256::ZERO { + return Ok(None) + } + if let Some(code) = self + .codes + .read() + .map_err(|_| ProviderError::TrieWitnessError("bytecode cache lock poisoned".into()))? + .get(&expected_hash) + .cloned() + { + return Ok(Some(code)) + } + + tracing::warn!(%address, %expected_hash, block = self.state_block_number, + "Fetching bytecode omitted from execution witness"); + let handle = tokio::runtime::Handle::try_current().map_err(|_| { + ProviderError::Database(DatabaseError::Other("no tokio runtime found".into())) + })?; + let code = tokio::task::block_in_place(|| { + handle.block_on(async { + self.provider.get_code_at(address).number(self.state_block_number).await + }) + }) + .map_err(|err| ProviderError::Database(DatabaseError::Other(err.to_string())))?; + let actual_hash = keccak256(&code); + if actual_hash != expected_hash { + return Err(ProviderError::TrieWitnessError(format!( + "Fetched code hash mismatch for {address}: expected {expected_hash}, got {actual_hash}" + ))) + } + let bytecode = Bytecode::new_raw(code); + self.codes + .write() + .map_err(|_| ProviderError::TrieWitnessError("bytecode cache lock poisoned".into()))? + .insert(expected_hash, bytecode.clone()); + Ok(Some(bytecode)) + } +} + +async fn fetch_execution_witness( + provider: &P, + block_number: u64, +) -> Result +where + P: Provider, + N: Network, +{ + let witness = provider + .client() + .request("debug_executionWitness", (BlockNumberOrTag::Number(block_number),)) + .await?; + + Ok(FlexibleExecutionWitness::into_execution_witness(witness)) +} + +#[derive(Debug, Deserialize)] +struct FlexibleExecutionWitness { + state: Vec, + codes: Vec, + #[serde(default)] + keys: Option>, + headers: Vec, +} + +impl FlexibleExecutionWitness { + fn into_execution_witness(self) -> ExecutionWitness { + ExecutionWitness { + state: self.state, + codes: self.codes, + keys: self.keys.unwrap_or_default(), + headers: self + .headers + .into_iter() + .map(FlexibleExecutionWitnessHeader::into_rlp_bytes) + .collect(), + } + } +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +enum FlexibleExecutionWitnessHeader { + Rlp(alloy_primitives::Bytes), + Rpc(RpcHeader
), +} + +impl FlexibleExecutionWitnessHeader { + fn into_rlp_bytes(self) -> alloy_primitives::Bytes { + match self { + Self::Rlp(bytes) => bytes, + Self::Rpc(header) => { + let mut out = Vec::new(); + header.into_consensus().encode(&mut out); + out.into() + } + } + } } const SYSTEM_ADDRESS: Address = @@ -79,7 +195,7 @@ impl + Clone, N: Network> DatabaseRef for ExecutionWitnessRpcDb

+ Clone, N: Network> DatabaseRef for ExecutionWitnessRpcDb

Result { self.codes + .read() + .map_err(|_| ProviderError::TrieWitnessError("bytecode cache lock poisoned".into()))? .get(&code_hash) .ok_or_else(|| { ProviderError::TrieWitnessError(format!("Code not found for {code_hash}")) @@ -137,10 +255,216 @@ where } fn bytecodes(&self) -> Vec { - self.codes.values().cloned().collect() + self.codes.read().expect("bytecode cache lock poisoned").values().cloned().collect() } async fn ancestor_headers(&self) -> Result, RpcDbError> { Ok(self.ancestor_headers.values().cloned().collect()) } } + +#[cfg(test)] +mod tests { + use std::{ + io::{Read, Write}, + net::TcpListener, + thread, + time::{Duration, Instant}, + }; + + use alloy_consensus::Header; + use alloy_primitives::hex::FromHex; + use alloy_rlp::Decodable; + + use super::*; + + fn code_rpc(code: &str) -> (String, thread::JoinHandle) { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let url = format!("http://{}", listener.local_addr().unwrap()); + listener.set_nonblocking(true).unwrap(); + let code = code.to_string(); + let worker = thread::spawn(move || { + let deadline = Instant::now() + Duration::from_secs(5); + let mut stream = loop { + match listener.accept() { + Ok((stream, _)) => break stream, + Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { + assert!(Instant::now() < deadline, "no bytecode RPC request received"); + thread::sleep(Duration::from_millis(5)); + } + Err(err) => panic!("{err}"), + } + }; + stream.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); + let mut bytes = Vec::new(); + let request = loop { + let mut buffer = [0u8; 1024]; + let count = stream.read(&mut buffer).unwrap(); + assert!(count > 0); + bytes.extend_from_slice(&buffer[..count]); + if let Some(end) = bytes.windows(4).position(|w| w == b"\r\n\r\n") { + let headers = String::from_utf8_lossy(&bytes[..end]); + let length: usize = headers + .lines() + .find_map(|line| { + line.to_ascii_lowercase() + .strip_prefix("content-length:") + .map(|value| value.trim().parse().unwrap()) + }) + .unwrap(); + if bytes.len() >= end + 4 + length { + break serde_json::from_slice::( + &bytes[end + 4..end + 4 + length], + ) + .unwrap() + } + } + }; + let response = + serde_json::json!({"jsonrpc": "2.0", "id": request["id"], "result": code}) + .to_string(); + write!(stream, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}", response.len(), response).unwrap(); + request + }); + (url, worker) + } + + #[tokio::test(flavor = "multi_thread")] + async fn missing_code_uses_parent_block_and_is_cached_for_guest_input() { + let (url, worker) = code_rpc("0x6000"); + let code = Bytecode::new_raw(alloy_primitives::bytes!("6000")); + let hash = code.hash_slow(); + let address = Address::repeat_byte(0x11); + let mut db = ExecutionWitnessRpcDb { + provider: alloy_provider::ProviderBuilder::new().connect_http(url.parse().unwrap()), + state_block_number: 26_167_641, + state: EthereumState { + state_trie: Default::default(), + storage_tries: HashMap::default(), + }, + codes: RwLock::new(HashMap::default()), + ancestor_headers: BTreeMap::new(), + phantom: PhantomData, + }; + db.state + .state_trie + .insert_rlp( + keccak256(address).as_slice(), + TrieAccount { + nonce: 1, + balance: U256::from(1), + code_hash: hash, + ..Default::default() + }, + ) + .unwrap(); + + assert_eq!(db.basic_ref(address).unwrap().unwrap().code, Some(code.clone())); + let request = worker.join().unwrap(); + assert_eq!(request["method"], "eth_getCode"); + assert_eq!(request["params"], serde_json::json!([address, "0x18f4959"])); + // The RPC listener is gone: both paths must use the verified cache. + assert_eq!(db.basic_ref(address).unwrap().unwrap().code, Some(code.clone())); + assert_eq!(db.code_by_hash_ref(hash).unwrap(), code.clone()); + assert_eq!(db.bytecodes(), vec![code]); + assert!(db.basic_ref(Address::repeat_byte(0x22)).unwrap().is_none()); + assert!(db.account_code(address, KECCAK_EMPTY).unwrap().is_none()); + } + + #[tokio::test(flavor = "multi_thread")] + async fn wrong_fallback_code_is_rejected_and_not_exported() { + let (url, worker) = code_rpc("0x6001"); + let expected_hash = keccak256(alloy_primitives::bytes!("6000")); + let address = Address::repeat_byte(0x11); + let mut db = ExecutionWitnessRpcDb { + provider: alloy_provider::ProviderBuilder::new().connect_http(url.parse().unwrap()), + state_block_number: 26_167_641, + state: EthereumState { + state_trie: Default::default(), + storage_tries: HashMap::default(), + }, + codes: RwLock::new(HashMap::default()), + ancestor_headers: BTreeMap::new(), + phantom: PhantomData, + }; + db.state + .state_trie + .insert_rlp( + keccak256(address).as_slice(), + TrieAccount { + nonce: 1, + balance: U256::from(1), + code_hash: expected_hash, + ..Default::default() + }, + ) + .unwrap(); + + let error = db.basic_ref(address).unwrap_err(); + worker.join().unwrap(); + assert!(error.to_string().contains("Fetched code hash mismatch")); + assert!(db.bytecodes().is_empty()); + assert!(db.code_by_hash_ref(expected_hash).is_err()); + } + + #[test] + fn execution_witness_accepts_rpc_header_objects_and_null_keys() { + let json = r#"{ + "headers": [{ + "parentHash": "0xddcb9640c370c7914ccf303924421b257f05a676fc8d3c9c33ef8476194d98bd", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97", + "stateRoot": "0x043ef1fafb089e28e171f777d22845c2bdbf89e6b767857b02dcf9308de92b5c", + "transactionsRoot": "0x751ee8f2d2893940e2b8287a72fb451ca382e5e515e8de266686e057f8cb41a7", + "receiptsRoot": "0xc0bf6c67ff3ab702758b903204bf3f054ce68ca48dc55f8fd40e5e912b34f782", + "logsBloom": "0xdc7d77b6e8cfcb93b6be74bdc368dba1dfecc4fdef2447324c1d84facd5cdeb2fd5e0196e6fdd5bdff93e3f9ea46adcf76bf89f8bf0e6141b5de26c0bbbf14f7cdbeb0abfedaebf95b7e7a48a5e877fd5c7ef11fb8cc9baa83445c55b8e5ffc8dee2fb19ab7e61dbcc1b9357fe0aecee5e1f7769d396fed9fef5c455bf2fff4de072397a939a5768bd69a73b3587832ab8b3c7ef653dc1de147b3973fbbb8fbfcf157d67a4d5ee5c7df5cd87dcc017a8ffd58b4d9f4c71d85dee3b2e6a1f69ffdfa75f0ef9e83edbbfe32ab7d274eedbd8cc71ff8f7e689bede5331bb0626bd6f4dde9cac72714b43eefb36df28baee2ffe36e2967fd02e2573ef7995503e7cf", + "difficulty": "0x0", + "number": "0x17e8a77", + "gasLimit": "0x3938700", + "gasUsed": "0x19aacd0", + "timestamp": "0x6a017d13", + "extraData": "0x546974616e2028746974616e6275696c6465722e78797a29", + "mixHash": "0xd0d37c7118b2221b8ec1c4940be1689108309c9837a0359d41be16acdc7e546e", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x115394a1", + "withdrawalsRoot": "0x978b9471e9087c6f967aaa08f757abd7280dbb7aa3310320cdd4d3fb4ecb9e5e", + "blobGasUsed": "0x0", + "excessBlobGas": "0xb503bd8", + "parentBeaconBlockRoot": "0xc2b892804ed1f1f3cfeefbbc0fffd0e298bab43a7773409154a0e6ea306b794a", + "requestsHash": "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "slotNumber": null, + "hash": "0x190299f2eee1493723cc749ff9148663c5202f9b3479ed0da8d99ba62f882c23" + }], + "codes": ["0x6000"], + "state": ["0x80"], + "keys": null + }"#; + + let witness = serde_json::from_str::(json) + .unwrap() + .into_execution_witness(); + let header = Header::decode(&mut witness.headers[0].as_ref()).unwrap(); + + assert_eq!(header.number, 25_070_199); + assert_eq!(witness.codes.len(), 1); + assert_eq!(witness.state.len(), 1); + assert!(witness.keys.is_empty()); + } + + #[test] + fn execution_witness_preserves_rlp_header_bytes_and_keys() { + let json = r#"{ + "headers": ["0x010203"], + "codes": [], + "state": [], + "keys": ["0x04"] + }"#; + + let witness = serde_json::from_str::(json) + .unwrap() + .into_execution_witness(); + + assert_eq!(witness.headers[0].as_ref(), Vec::::from_hex("010203").unwrap()); + assert_eq!(witness.keys[0].as_ref(), Vec::::from_hex("04").unwrap()); + } +}