diff --git a/Cargo.lock b/Cargo.lock index fbbc39edb..1583bca5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -696,7 +696,7 @@ dependencies = [ "async-trait", "auto_impl", "either", - "elliptic-curve", + "elliptic-curve 0.13.8", "k256", "thiserror 2.0.12", ] @@ -795,7 +795,7 @@ checksum = "a712bdfeff42401a7dd9518f72f617574c36226a9b5414537fedc34350b73bf9" dependencies = [ "alloy-json-rpc", "alloy-primitives", - "base64", + "base64 0.22.1", "derive_more 2.0.1", "futures", "futures-utils-wasm", @@ -854,8 +854,8 @@ dependencies = [ "alloy-pubsub", "alloy-transport", "futures", - "http", - "rustls", + "http 1.3.1", + "rustls 0.23.27", "serde_json", "tokio", "tokio-tungstenite", @@ -1381,6 +1381,435 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "aws-config" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455e9fb7743c6f6267eb2830ccc08686fbb3d13c9a689369562fd4d4ef9ea462" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sdk-sso", + "aws-sdk-ssooidc", + "aws-sdk-sts", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "hex", + "http 1.3.1", + "ring", + "time", + "tokio", + "tracing", + "url", + "zeroize", +] + +[[package]] +name = "aws-credential-types" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687bc16bc431a8533fe0097c7f0182874767f920989d7260950172ae8e3c4465" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "zeroize", +] + +[[package]] +name = "aws-lc-rs" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" +dependencies = [ + "bindgen 0.69.5", + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "aws-runtime" +version = "1.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f6c68419d8ba16d9a7463671593c54f81ba58cab466e9b759418da606dcc2e2" +dependencies = [ + "aws-credential-types", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "http-body 0.4.6", + "percent-encoding", + "pin-project-lite", + "tracing", + "uuid", +] + +[[package]] +name = "aws-sdk-s3" +version = "1.93.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b9734dc8145b417a3c22eae8769a2879851690982dba718bdc52bd28ad04ce" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-checksums", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "bytes", + "fastrand", + "hex", + "hmac", + "http 0.2.12", + "http 1.3.1", + "http-body 0.4.6", + "lru 0.12.5", + "percent-encoding", + "regex-lite", + "sha2 0.10.9", + "tracing", + "url", +] + +[[package]] +name = "aws-sdk-sso" +version = "1.73.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ac1674cba7872061a29baaf02209fefe499ff034dfd91bd4cc59e4d7741489" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-ssooidc" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6a22f077f5fd3e3c0270d4e1a110346cddf6769e9433eb9e6daceb4ca3b149" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-sts" +version = "1.75.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3258fa707f2f585ee3049d9550954b959002abd59176975150a01d5cf38ae3f" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "fastrand", + "http 0.2.12", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sigv4" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfb9021f581b71870a17eac25b52335b82211cdc092e02b6876b2bcefa61666" +dependencies = [ + "aws-credential-types", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "crypto-bigint 0.5.5", + "form_urlencoded", + "hex", + "hmac", + "http 0.2.12", + "http 1.3.1", + "p256 0.11.1", + "percent-encoding", + "ring", + "sha2 0.10.9", + "subtle", + "time", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-async" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e190749ea56f8c42bf15dd76c65e14f8f765233e6df9b0506d9d934ebef867c" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "aws-smithy-checksums" +version = "0.63.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f77a921dbd2c78ebe70726799787c1d110a2245dd65e39b20923dfdfb2deee" +dependencies = [ + "aws-smithy-http", + "aws-smithy-types", + "bytes", + "crc-fast", + "hex", + "http 0.2.12", + "http-body 0.4.6", + "md-5", + "pin-project-lite", + "sha1", + "sha2 0.10.9", + "tracing", +] + +[[package]] +name = "aws-smithy-eventstream" +version = "0.60.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338a3642c399c0a5d157648426110e199ca7fd1c689cc395676b81aa563700c4" +dependencies = [ + "aws-smithy-types", + "bytes", + "crc32fast", +] + +[[package]] +name = "aws-smithy-http" +version = "0.62.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99335bec6cdc50a346fda1437f9fefe33abf8c99060739a546a16457f2862ca9" +dependencies = [ + "aws-smithy-eventstream", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http 1.3.1", + "http-body 0.4.6", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "aws-smithy-http-client" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f491388e741b7ca73b24130ff464c1478acc34d5b331b7dd0a2ee4643595a15" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "h2 0.3.26", + "h2 0.4.10", + "http 0.2.12", + "http 1.3.1", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper 1.6.0", + "hyper-rustls 0.24.2", + "hyper-rustls 0.27.7", + "hyper-util", + "pin-project-lite", + "rustls 0.21.12", + "rustls 0.23.27", + "rustls-native-certs 0.8.1", + "rustls-pki-types", + "tokio", + "tower", + "tracing", +] + +[[package]] +name = "aws-smithy-json" +version = "0.61.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a16e040799d29c17412943bdbf488fd75db04112d0c0d4b9290bacf5ae0014b9" +dependencies = [ + "aws-smithy-types", +] + +[[package]] +name = "aws-smithy-observability" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9364d5989ac4dd918e5cc4c4bdcc61c9be17dcd2586ea7f69e348fc7c6cab393" +dependencies = [ + "aws-smithy-runtime-api", +] + +[[package]] +name = "aws-smithy-query" +version = "0.60.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" +dependencies = [ + "aws-smithy-types", + "urlencoding", +] + +[[package]] +name = "aws-smithy-runtime" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14302f06d1d5b7d333fd819943075b13d27c7700b414f574c3c35859bfb55d5e" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-http-client", + "aws-smithy-observability", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "fastrand", + "http 0.2.12", + "http 1.3.1", + "http-body 0.4.6", + "http-body 1.0.1", + "pin-project-lite", + "pin-utils", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd8531b6d8882fd8f48f82a9754e682e29dd44cff27154af51fa3eb730f59efb" +dependencies = [ + "aws-smithy-async", + "aws-smithy-types", + "bytes", + "http 0.2.12", + "http 1.3.1", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-types" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d498595448e43de7f4296b7b7a18a8a02c61ec9349128c80a368f7c3b4ab11a8" +dependencies = [ + "base64-simd", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http 1.3.1", + "http-body 0.4.6", + "http-body 1.0.1", + "http-body-util", + "itoa", + "num-integer", + "pin-project-lite", + "pin-utils", + "ryu", + "serde", + "time", + "tokio", + "tokio-util", +] + +[[package]] +name = "aws-smithy-xml" +version = "0.60.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db87b96cb1b16c024980f133968d52882ca0daaee3a086c6decc500f6c99728" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "aws-types" +version = "1.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a322fec39e4df22777ed3ad8ea868ac2f94cd15e1a55f6ee8d8d6305057689a" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "rustc_version 0.4.1", + "tracing", +] + [[package]] name = "backon" version = "1.5.1" @@ -1412,18 +1841,40 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base16ct" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + [[package]] name = "base64ct" version = "1.8.0" @@ -1445,6 +1896,29 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.9.1", + "cexpr", + "clang-sys", + "itertools 0.10.5", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.102", + "which", +] + [[package]] name = "bindgen" version = "0.70.1" @@ -1816,6 +2290,16 @@ dependencies = [ "serde", ] +[[package]] +name = "bytes-utils" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" +dependencies = [ + "bytes", + "either", +] + [[package]] name = "c-kzg" version = "2.1.1" @@ -2006,6 +2490,15 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.4" @@ -2128,6 +2621,16 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -2177,6 +2680,19 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "crc-fast" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf62af4cc77d8fe1c22dde4e721d87f2f54056139d8c412e1366b740305f56f" +dependencies = [ + "crc", + "digest 0.10.7", + "libc", + "rand 0.9.1", + "regex", +] + [[package]] name = "crc32fast" version = "1.4.2" @@ -2257,6 +2773,18 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -2421,6 +2949,16 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "der" version = "0.7.10" @@ -2671,19 +3209,31 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", +] + [[package]] name = "ecdsa" version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der", + "der 0.7.10", "digest 0.10.7", - "elliptic-curve", - "rfc6979", + "elliptic-curve 0.13.8", + "rfc6979 0.4.0", "serdect", - "signature", - "spki", + "signature 2.2.0", + "spki 0.7.3", ] [[package]] @@ -2692,8 +3242,8 @@ version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "pkcs8", - "signature", + "pkcs8 0.10.2", + "signature 2.2.0", ] [[package]] @@ -2732,21 +3282,41 @@ dependencies = [ "serde", ] +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest 0.10.7", + "ff 0.12.1", + "generic-array", + "group 0.12.1", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1 0.3.0", + "subtle", + "zeroize", +] + [[package]] name = "elliptic-curve" version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base16ct", - "crypto-bigint", + "base16ct 0.2.0", + "crypto-bigint 0.5.5", "digest 0.10.7", - "ff", + "ff 0.13.1", "generic-array", - "group", - "pkcs8", + "group 0.13.0", + "pkcs8 0.10.2", "rand_core 0.6.4", - "sec1", + "sec1 0.7.3", "serdect", "subtle", "zeroize", @@ -2765,7 +3335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "851bd664a3d3a3c175cff92b2f0df02df3c541b4895d0ae307611827aae46152" dependencies = [ "alloy-rlp", - "base64", + "base64 0.22.1", "bytes", "ed25519-dalek", "hex", @@ -2940,6 +3510,16 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "ff" version = "0.13.1" @@ -3011,6 +3591,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "fsevent-sys" version = "4.1.0" @@ -3229,7 +3815,7 @@ dependencies = [ "futures-core", "futures-sink", "gloo-utils", - "http", + "http 1.3.1", "js-sys", "pin-project", "serde", @@ -3265,17 +3851,47 @@ dependencies = [ "web-sys", ] +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff 0.12.1", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff", + "ff 0.13.1", "rand_core 0.6.4", "subtle", ] +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.9.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "h2" version = "0.4.10" @@ -3287,7 +3903,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", + "http 1.3.1", "indexmap 2.9.0", "slab", "tokio", @@ -3449,6 +4065,26 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.3.1" @@ -3460,6 +4096,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -3467,7 +4114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.3.1", ] [[package]] @@ -3478,8 +4125,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "pin-project-lite", ] @@ -3523,6 +4170,30 @@ dependencies = [ "serde", ] +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "hyper" version = "1.6.0" @@ -3532,9 +4203,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2", - "http", - "http-body", + "h2 0.4.10", + "http 1.3.1", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -3544,21 +4215,37 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.32", + "log", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", + "tokio", + "tokio-rustls 0.24.1", +] + [[package]] name = "hyper-rustls" version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http", - "hyper", + "http 1.3.1", + "hyper 1.6.0", "hyper-util", "log", - "rustls", - "rustls-native-certs", + "rustls 0.23.27", + "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.2", "tower-service", "webpki-roots 1.0.0", ] @@ -3569,14 +4256,14 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-core", "futures-util", - "http", - "http-body", - "hyper", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.6.0", "ipnet", "libc", "percent-encoding", @@ -4126,20 +4813,20 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2a320a3f1464e4094f780c4d48413acd786ce5627aaaecfac9e9c7431d13ae1" dependencies = [ - "base64", + "base64 0.22.1", "futures-channel", "futures-util", "gloo-net", - "http", + "http 1.3.1", "jsonrpsee-core", "pin-project", - "rustls", + "rustls 0.23.27", "rustls-pki-types", "rustls-platform-verifier", "soketto", "thiserror 2.0.12", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.2", "tokio-util", "tracing", "url", @@ -4155,8 +4842,8 @@ dependencies = [ "bytes", "futures-timer", "futures-util", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", "jsonrpsee-types", "parking_lot", @@ -4179,14 +4866,14 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6962d2bd295f75e97dd328891e58fce166894b974c1f7ce2e7597f02eeceb791" dependencies = [ - "base64", - "http-body", - "hyper", - "hyper-rustls", + "base64 0.22.1", + "http-body 1.0.1", + "hyper 1.6.0", + "hyper-rustls 0.27.7", "hyper-util", "jsonrpsee-core", "jsonrpsee-types", - "rustls", + "rustls 0.23.27", "rustls-platform-verifier", "serde", "serde_json", @@ -4216,10 +4903,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38b0bcf407ac68d241f90e2d46041e6a06988f97fe1721fb80b91c42584fae6" dependencies = [ "futures-util", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.6.0", "hyper-util", "jsonrpsee-core", "jsonrpsee-types", @@ -4242,7 +4929,7 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66df7256371c45621b3b7d2fb23aea923d577616b9c0e9c0b950a6ea5c2be0ca" dependencies = [ - "http", + "http 1.3.1", "serde", "serde_json", "thiserror 2.0.12", @@ -4266,7 +4953,7 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da2694c9ff271a9d3ebfe520f6b36820e85133a51be77a3cb549fd615095261" dependencies = [ - "http", + "http 1.3.1", "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-types", @@ -4280,7 +4967,7 @@ version = "9.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" dependencies = [ - "base64", + "base64 0.22.1", "js-sys", "pem", "ring", @@ -4296,12 +4983,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "once_cell", "serdect", "sha2 0.10.9", - "signature", + "signature 2.2.0", ] [[package]] @@ -4349,6 +5036,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.172" @@ -4408,7 +5101,7 @@ version = "0.14.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78a09b56be5adbcad5aa1197371688dc6bb249a26da3bca2011ee2fb987ebfb" dependencies = [ - "bindgen", + "bindgen 0.70.1", "errno", "libc", ] @@ -4431,7 +5124,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e79019718125edc905a079a70cfa5f3820bc76139fc91d6f9abc27ea2a887139" dependencies = [ "arrayref", - "base64", + "base64 0.22.1", "digest 0.9.0", "libsecp256k1-core", "libsecp256k1-gen-ecmult", @@ -4633,6 +5326,16 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + [[package]] name = "memchr" version = "2.7.4" @@ -4685,7 +5388,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd7399781913e5393588a8d8c6a2867bf85fb38eaf2502fdce465aad2dc6f034" dependencies = [ - "base64", + "base64 0.22.1", "indexmap 2.9.0", "metrics", "metrics-util", @@ -5202,20 +5905,37 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "outref" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" + [[package]] name = "overload" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.9", +] + [[package]] name = "p256" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "primeorder", "sha2 0.10.9", ] @@ -5301,7 +6021,7 @@ version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" dependencies = [ - "base64", + "base64 0.22.1", "serde", ] @@ -5407,14 +6127,24 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der 0.6.1", + "spki 0.6.0", +] + [[package]] name = "pkcs8" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der", - "spki", + "der 0.7.10", + "spki 0.7.3", ] [[package]] @@ -5490,13 +6220,23 @@ dependencies = [ "yansi", ] +[[package]] +name = "prettyplease" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" +dependencies = [ + "proc-macro2", + "syn 2.0.102", +] + [[package]] name = "primeorder" version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ - "elliptic-curve", + "elliptic-curve 0.13.8", ] [[package]] @@ -5669,7 +6409,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.1.1", - "rustls", + "rustls 0.23.27", "socket2", "thiserror 2.0.12", "tokio", @@ -5689,7 +6429,7 @@ dependencies = [ "rand 0.9.1", "ring", "rustc-hash 2.1.1", - "rustls", + "rustls 0.23.27", "rustls-pki-types", "slab", "thiserror 2.0.12", @@ -5932,6 +6672,12 @@ dependencies = [ "regex-syntax 0.8.5", ] +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -5960,16 +6706,16 @@ version = "0.12.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2f8e5513d63f2e5b386eb5106dc67eaf3f84e95258e210489136b8b92ad6119" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-core", "futures-util", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", - "hyper", - "hyper-rustls", + "hyper 1.6.0", + "hyper-rustls 0.27.7", "hyper-util", "ipnet", "js-sys", @@ -5979,15 +6725,15 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls", - "rustls-native-certs", + "rustls 0.23.27", + "rustls-native-certs 0.8.1", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.2", "tokio-util", "tower", "tower-http", @@ -7160,7 +7906,7 @@ dependencies = [ name = "reth-mdbx-sys" version = "1.4.8" dependencies = [ - "bindgen", + "bindgen 0.70.1", "cc", ] @@ -7536,7 +8282,7 @@ name = "reth-node-metrics" version = "1.4.8" dependencies = [ "eyre", - "http", + "http 1.3.1", "jsonrpsee-server", "metrics", "metrics-exporter-prometheus", @@ -8068,9 +8814,9 @@ dependencies = [ "async-trait", "derive_more 2.0.1", "futures", - "http", - "http-body", - "hyper", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.6.0", "jsonrpsee", "jsonrpsee-types", "jsonwebtoken", @@ -8148,7 +8894,7 @@ version = "1.4.8" dependencies = [ "alloy-network", "alloy-provider", - "http", + "http 1.3.1", "jsonrpsee", "metrics", "pin-project", @@ -8296,7 +9042,7 @@ name = "reth-rpc-layer" version = "1.4.8" dependencies = [ "alloy-rpc-types-engine", - "http", + "http 1.3.1", "jsonrpsee-http-client", "pin-project", "tower", @@ -8717,6 +9463,8 @@ dependencies = [ "alloy-sol-types", "async-trait", "auto_impl", + "aws-config", + "aws-sdk-s3", "bytes", "cfg-if", "clap", @@ -8732,6 +9480,7 @@ dependencies = [ "once_cell", "parity-bytes", "parking_lot", + "rayon", "reth", "reth-basic-payload-builder", "reth-chainspec", @@ -8956,7 +9705,7 @@ dependencies = [ "k256", "libsecp256k1", "once_cell", - "p256", + "p256 0.13.2", "revm-primitives", "ripemd", "secp256k1 0.30.0", @@ -8986,6 +9735,17 @@ dependencies = [ "serde", ] +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac", + "zeroize", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -9196,21 +9956,46 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + [[package]] name = "rustls" version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.3", "subtle", "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework 2.11.1", +] + [[package]] name = "rustls-native-certs" version = "0.8.1" @@ -9220,7 +10005,16 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.2.0", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", ] [[package]] @@ -9248,16 +10042,16 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" dependencies = [ - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "jni", "log", "once_cell", - "rustls", - "rustls-native-certs", + "rustls 0.23.27", + "rustls-native-certs 0.8.1", "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", + "rustls-webpki 0.103.3", + "security-framework 3.2.0", "security-framework-sys", "webpki-root-certs 0.26.11", "windows-sys 0.59.0", @@ -9269,12 +10063,23 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustls-webpki" version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -9351,16 +10156,40 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct 0.1.1", + "der 0.6.1", + "generic-array", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + [[package]] name = "sec1" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "base16ct", - "der", + "base16ct 0.2.0", + "der 0.7.10", "generic-array", - "pkcs8", + "pkcs8 0.10.2", "serdect", "subtle", "zeroize", @@ -9406,6 +10235,19 @@ dependencies = [ "cc", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.9.1", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework" version = "3.2.0" @@ -9413,7 +10255,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ "bitflags 2.9.1", - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -9528,7 +10370,7 @@ version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ - "base64", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -9558,7 +10400,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" dependencies = [ - "base16ct", + "base16ct 0.2.0", "serde", ] @@ -9671,6 +10513,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "signature" version = "2.2.0" @@ -9782,16 +10634,26 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e859df029d160cb88608f5d7df7fb4753fd20fdfb4de5644f3d8b8440841721" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures", - "http", + "http 1.3.1", "httparse", "log", "rand 0.8.5", "sha1", ] +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.1", +] + [[package]] name = "spki" version = "0.7.3" @@ -9799,7 +10661,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der", + "der 0.7.10", ] [[package]] @@ -10182,13 +11044,23 @@ dependencies = [ "syn 2.0.102", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls", + "rustls 0.23.27", "tokio", ] @@ -10212,10 +11084,10 @@ checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", - "rustls", + "rustls 0.23.27", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.2", "tungstenite", "webpki-roots 0.26.11", ] @@ -10303,13 +11175,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ "async-compression", - "base64", + "base64 0.22.1", "bitflags 2.9.1", "bytes", "futures-core", "futures-util", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", "http-range-header", "httpdate", @@ -10525,11 +11397,11 @@ checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ "bytes", "data-encoding", - "http", + "http 1.3.1", "httparse", "log", "rand 0.9.1", - "rustls", + "rustls 0.23.27", "rustls-pki-types", "sha1", "thiserror 2.0.12", @@ -10663,12 +11535,12 @@ version = "3.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f0fde9bc91026e381155f8c67cb354bcd35260b2f4a29bcc84639f762760c39" dependencies = [ - "base64", + "base64 0.22.1", "flate2", "log", "percent-encoding", - "rustls", - "rustls-pemfile", + "rustls 0.23.27", + "rustls-pemfile 2.2.0", "rustls-pki-types", "ureq-proto", "utf-8", @@ -10681,8 +11553,8 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59db78ad1923f2b1be62b6da81fe80b173605ca0d57f85da2e005382adf693f7" dependencies = [ - "base64", - "http", + "base64 0.22.1", + "http 1.3.1", "httparse", "log", ] @@ -10699,6 +11571,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf-8" version = "0.7.6" @@ -10804,6 +11682,12 @@ dependencies = [ "syn 2.0.102", ] +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "wait-timeout" version = "0.2.1" @@ -11001,6 +11885,18 @@ 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.0" @@ -11628,6 +12524,12 @@ dependencies = [ "rustix 1.0.7", ] +[[package]] +name = "xmlparser" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + [[package]] name = "yansi" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 3361a30dc..b98fe9157 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,6 +94,9 @@ tracing = "0.1" rmp-serde = "1.0.0" lz4_flex = "0.11.3" ureq = "3.0.12" +aws-sdk-s3 = "1.93.0" +aws-config = "1.8.0" +rayon = "1.10.0" [target.'cfg(unix)'.dependencies] @@ -138,4 +141,4 @@ client = [ "jsonrpsee/client", "jsonrpsee/async-client", "reth-rpc-eth-api/client", -] \ No newline at end of file +] diff --git a/src/lib.rs b/src/lib.rs index 53d6494fb..1a2b3d4ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,4 +3,6 @@ pub mod consensus; mod evm; mod hardforks; pub mod node; +pub mod pseudo_peer; + pub use node::primitives::{HlBlock, HlBlockBody, HlPrimitives}; diff --git a/src/main.rs b/src/main.rs index c13f2b669..da86cdb6d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ -use clap::{Args, Parser}; +use clap::Parser; use reth::builder::NodeHandle; use reth_hl::{ chainspec::parser::HlChainSpecParser, - node::{cli::Cli, storage::tables::Tables, HlNode}, + node::{cli::{Cli, HlNodeArgs}, storage::tables::Tables, HlNode}, }; // We use jemalloc for performance reasons @@ -10,11 +10,6 @@ use reth_hl::{ #[global_allocator] static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; -/// No Additional arguments -#[derive(Debug, Clone, Copy, Default, Args)] -#[non_exhaustive] -struct NoArgs; - fn main() -> eyre::Result<()> { reth_cli_util::sigsegv_handler::install(); @@ -23,9 +18,9 @@ fn main() -> eyre::Result<()> { std::env::set_var("RUST_BACKTRACE", "1"); } - Cli::::parse().run(|builder, _| async move { + Cli::::parse().run(|builder, ext| async move { builder.builder.database.create_tables_for::()?; - let (node, engine_handle_tx) = HlNode::new(); + let (node, engine_handle_tx) = HlNode::new(ext.block_source_args.parse().await?); let NodeHandle { node, node_exit_future: exit_future } = builder.node(node).launch().await?; diff --git a/src/node/cli.rs b/src/node/cli.rs index 4bd14eb8e..b15be7b9b 100644 --- a/src/node/cli.rs +++ b/src/node/cli.rs @@ -3,8 +3,9 @@ use crate::{ node::{ consensus::HlConsensus, evm::config::HlEvmConfig, network::HlNetworkPrimitives, HlNode, }, + pseudo_peer::BlockSourceArgs, }; -use clap::Parser; +use clap::{Args, Parser}; use reth::{ args::LogArgs, builder::{NodeBuilder, WithLaunchContext}, @@ -15,7 +16,7 @@ use reth::{ }; use reth_chainspec::EthChainSpec; use reth_cli::chainspec::ChainSpecParser; -use reth_cli_commands::{launcher::FnLauncher, node::NoArgs}; +use reth_cli_commands::launcher::FnLauncher; use reth_db::DatabaseEnv; use reth_tracing::FileWorkerGuard; use std::{ @@ -25,12 +26,20 @@ use std::{ }; use tracing::info; +#[derive(Debug, Clone, Args)] +#[non_exhaustive] +pub struct HlNodeArgs { + #[command(flatten)] + pub block_source_args: BlockSourceArgs, +} + /// The main reth_hl cli interface. /// /// This is the entrypoint to the executable. #[derive(Debug, Parser)] #[command(author, version = SHORT_VERSION, long_version = LONG_VERSION, about = "Reth", long_about = None)] -pub struct Cli { +pub struct Cli +{ /// The command to run #[command(subcommand)] pub command: Commands, diff --git a/src/node/mod.rs b/src/node/mod.rs index 450783415..76cf29b15 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -12,6 +12,7 @@ use crate::{ }, storage::HlStorage, }, + pseudo_peer::BlockSourceConfig, }; use consensus::HlConsensusBuilder; use engine::HlPayloadServiceBuilder; @@ -49,12 +50,15 @@ pub type HlNodeAddOns = pub struct HlNode { engine_handle_rx: Arc>>>>, + block_source_config: BlockSourceConfig, } impl HlNode { - pub fn new() -> (Self, oneshot::Sender>) { + pub fn new( + block_source_config: BlockSourceConfig, + ) -> (Self, oneshot::Sender>) { let (tx, rx) = oneshot::channel(); - (Self { engine_handle_rx: Arc::new(Mutex::new(Some(rx))) }, tx) + (Self { engine_handle_rx: Arc::new(Mutex::new(Some(rx))), block_source_config }, tx) } } @@ -79,7 +83,10 @@ impl HlNode { .pool(HlPoolBuilder) .executor(HlExecutorBuilder::default()) .payload(HlPayloadServiceBuilder::default()) - .network(HlNetworkBuilder { engine_handle_rx: self.engine_handle_rx.clone() }) + .network(HlNetworkBuilder { + engine_handle_rx: self.engine_handle_rx.clone(), + block_source_config: self.block_source_config.clone(), + }) .consensus(HlConsensusBuilder::default()) } } diff --git a/src/node/network/mod.rs b/src/node/network/mod.rs index a3fd8d80c..63db98cce 100644 --- a/src/node/network/mod.rs +++ b/src/node/network/mod.rs @@ -8,6 +8,7 @@ use crate::{ types::ReadPrecompileCalls, HlNode, }, + pseudo_peer::{start_pseudo_peer, BlockSourceConfig}, HlBlock, }; use alloy_rlp::{Decodable, Encodable}; @@ -149,6 +150,8 @@ pub type HlNetworkPrimitives = pub struct HlNetworkBuilder { pub(crate) engine_handle_rx: Arc>>>>, + + pub(crate) block_source_config: BlockSourceConfig, } impl HlNetworkBuilder { @@ -162,7 +165,7 @@ impl HlNetworkBuilder { where Node: FullNodeTypes, { - let Self { engine_handle_rx } = self; + let Self { engine_handle_rx, .. } = self; let network_builder = ctx.network_config_builder()?; @@ -185,6 +188,8 @@ impl HlNetworkBuilder { }); let network_builder = network_builder + .disable_dns_discovery() + .disable_nat() .boot_nodes(boot_nodes()) .set_head(ctx.head()) .with_pow() @@ -216,10 +221,17 @@ where ctx: &BuilderContext, pool: Pool, ) -> eyre::Result { + let block_source_config = self.block_source_config.clone(); let network_config = self.network_config(ctx)?; let network = NetworkManager::builder(network_config).await?; let handle = ctx.start_network(network, pool); - info!(target: "reth::cli", enode=%handle.local_node_record(), "P2P networking initialized"); + let local_node_record = handle.local_node_record(); + info!(target: "reth::cli", enode=%local_node_record, "P2P networking initialized"); + + ctx.task_executor().spawn_critical("pseudo peer", async move { + let block_source = block_source_config.create_cached_block_source().await; + start_pseudo_peer(local_node_record.to_string(), block_source).await.unwrap(); + }); Ok(handle) } diff --git a/src/pseudo_peer/cli.rs b/src/pseudo_peer/cli.rs new file mode 100644 index 000000000..a5deb5394 --- /dev/null +++ b/src/pseudo_peer/cli.rs @@ -0,0 +1,54 @@ +use super::config::BlockSourceConfig; +use clap::{Args, Parser}; +use reth_node_core::args::LogArgs; + +#[derive(Debug, Clone, Args)] +pub struct BlockSourceArgs { + /// Block source to use for the benchmark. + /// Example: s3://hl-mainnet-evm-blocks + /// Example: /home/user/personal/evm-blocks + /// + /// For S3, you can use environment variables like AWS_PROFILE, etc. + #[arg(long)] + block_source: Option, + + /// Shorthand of --block-source=s3://hl-mainnet-evm-blocks + #[arg(long = "s3", default_value_t = false)] + s3: bool, +} + +impl BlockSourceArgs { + pub async fn parse(&self) -> eyre::Result { + if self.s3 { + return Ok(BlockSourceConfig::s3_default().await); + } + + let Some(value) = self.block_source.as_ref() else { + return Err(eyre::eyre!( + "You need to specify a block source e.g., --s3 or --block-source=/path/to/blocks" + )); + }; + + let config = if let Some(bucket) = value.strip_prefix("s3://") { + BlockSourceConfig::s3(bucket.to_string()).await + } else { + BlockSourceConfig::local(value.to_string()) + }; + + Ok(config) + } +} + +#[derive(Debug, Parser)] +pub struct PseudoPeerCommand { + #[command(flatten)] + pub logs: LogArgs, + + #[command(flatten)] + pub source: BlockSourceArgs, + + /// Destination peer to connect to. + /// Example: enode://412...1a@0.0.0.0:30304 + #[arg(long)] + pub destination_peer: String, +} diff --git a/src/pseudo_peer/config.rs b/src/pseudo_peer/config.rs new file mode 100644 index 000000000..63f1fa04d --- /dev/null +++ b/src/pseudo_peer/config.rs @@ -0,0 +1,56 @@ +use aws_config::BehaviorVersion; + +use super::{ + consts::DEFAULT_S3_BUCKET, + sources::{BlockSourceBoxed, LocalBlockSource, S3BlockSource}, +}; +use std::sync::Arc; + +#[derive(Debug, Clone)] +pub struct BlockSourceConfig { + pub source_type: BlockSourceType, +} + +#[derive(Debug, Clone)] +pub enum BlockSourceType { + S3 { bucket: String }, + Local { path: String }, +} + +impl BlockSourceConfig { + pub async fn s3_default() -> Self { + Self { source_type: BlockSourceType::S3 { bucket: DEFAULT_S3_BUCKET.to_string() } } + } + + pub async fn s3(bucket: String) -> Self { + Self { source_type: BlockSourceType::S3 { bucket } } + } + + pub fn local(path: String) -> Self { + Self { source_type: BlockSourceType::Local { path } } + } + + pub async fn create_block_source(&self) -> BlockSourceBoxed { + match &self.source_type { + BlockSourceType::S3 { bucket } => { + let client = aws_sdk_s3::Client::new( + &aws_config::defaults(BehaviorVersion::latest()) + .region("ap-northeast-1") + .load() + .await, + ); + let block_source = S3BlockSource::new(client, bucket.clone()); + Arc::new(Box::new(block_source)) + } + BlockSourceType::Local { path } => { + let block_source = LocalBlockSource::new(path.clone()); + Arc::new(Box::new(block_source)) + } + } + } + + pub async fn create_cached_block_source(&self) -> BlockSourceBoxed { + let block_source = self.create_block_source().await; + Arc::new(Box::new(block_source)) + } +} diff --git a/src/pseudo_peer/consts.rs b/src/pseudo_peer/consts.rs new file mode 100644 index 000000000..e98d7a5fc --- /dev/null +++ b/src/pseudo_peer/consts.rs @@ -0,0 +1,2 @@ +pub const MAX_CONCURRENCY: usize = 100; +pub const DEFAULT_S3_BUCKET: &str = "hl-mainnet-evm-blocks"; diff --git a/src/pseudo_peer/error.rs b/src/pseudo_peer/error.rs new file mode 100644 index 000000000..ad4344ca3 --- /dev/null +++ b/src/pseudo_peer/error.rs @@ -0,0 +1,36 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum PseudoPeerError { + #[error("Block source error: {0}")] + BlockSource(String), + + #[error("Network error: {0}")] + Network(#[from] reth_network::error::NetworkError), + + #[error("Configuration error: {0}")] + Config(String), + + #[error("AWS S3 error: {0}")] + S3(#[from] aws_sdk_s3::Error), + + #[error("IO error: {0}")] + Io(#[from] std::io::Error), + + #[error("Serialization error: {0}")] + Serialization(#[from] rmp_serde::encode::Error), + + #[error("Deserialization error: {0}")] + Deserialization(#[from] rmp_serde::decode::Error), + + #[error("Compression error: {0}")] + Compression(String), +} + +impl From for PseudoPeerError { + fn from(err: eyre::Error) -> Self { + PseudoPeerError::Config(err.to_string()) + } +} + +pub type Result = std::result::Result; diff --git a/src/pseudo_peer/main.rs b/src/pseudo_peer/main.rs new file mode 100644 index 000000000..7e46eb197 --- /dev/null +++ b/src/pseudo_peer/main.rs @@ -0,0 +1,16 @@ +use clap::Parser; +use reth_my_p2p::cli::PseudoPeerCommand; + +#[tokio::main] +async fn main() -> eyre::Result<()> { + let cli = PseudoPeerCommand::parse(); + cli.logs.init_tracing()?; + + // Parse and create block source configuration + let block_source_config = cli.source.parse().await?; + let block_source = block_source_config.create_cached_block_source().await; + + // Start the worker + reth_my_p2p::start_pseudo_peer(cli.destination_peer, block_source).await?; + Ok(()) +} diff --git a/src/pseudo_peer/mod.rs b/src/pseudo_peer/mod.rs new file mode 100644 index 000000000..a1b80283c --- /dev/null +++ b/src/pseudo_peer/mod.rs @@ -0,0 +1,89 @@ +//! A pseudo peer library that ingests multiple block sources to reth +//! +//! This library exposes `start_pseudo_peer` to support reth-side NetworkState/StateFetcher +//! to fetch blocks and feed it to its stages + +pub mod cli; +pub mod config; +pub mod consts; +pub mod error; +pub mod network; +pub mod service; +pub mod sources; +pub mod utils; + +pub use cli::*; +pub use config::*; +pub use error::*; +pub use network::*; +pub use service::*; +pub use sources::*; + +#[cfg(test)] +mod tests; + +use tokio::sync::mpsc; +use tracing::info; + +/// Re-export commonly used types +pub mod prelude { + pub use super::{ + config::BlockSourceConfig, + error::{PseudoPeerError, Result}, + service::{BlockPoller, PseudoPeer}, + sources::{BlockSource, CachedBlockSource, LocalBlockSource, S3BlockSource}, + }; +} + +use reth_network::{NetworkEvent, NetworkEventListenerProvider}; + +/// Main function that starts the network manager and processes eth requests +pub async fn start_pseudo_peer( + destination_peer: String, + block_source: BlockSourceBoxed, +) -> eyre::Result<()> { + let blockhash_cache = new_blockhash_cache(); + + // Create network manager + let (mut network, start_tx) = create_network_manager::( + destination_peer, + block_source.clone(), + blockhash_cache.clone(), + ) + .await?; + + // Create the channels for receiving eth messages + let (eth_tx, mut eth_rx) = mpsc::channel(32); + let (transaction_tx, mut transaction_rx) = mpsc::unbounded_channel(); + + network.set_eth_request_handler(eth_tx); + network.set_transactions(transaction_tx); + + let network_handle = network.handle().clone(); + let mut network_events = network_handle.event_listener(); + info!("Starting network manager..."); + + let mut service = PseudoPeer::new(block_source, blockhash_cache.clone()); + tokio::spawn(network); + let mut first = true; + + // Main event loop + loop { + tokio::select! { + Some(event) = tokio_stream::StreamExt::next(&mut network_events) => { + info!("Network event: {:?}", event); + if matches!(event, NetworkEvent::ActivePeerSession { .. }) && first { + start_tx.send(()).await?; + first = false; + } + } + + _ = transaction_rx.recv() => {} + + Some(eth_req) = eth_rx.recv() => { + service.process_eth_request(eth_req).await?; + info!("Processed eth request"); + } + } + } +} diff --git a/src/pseudo_peer/network.rs b/src/pseudo_peer/network.rs new file mode 100644 index 000000000..98e0efdf1 --- /dev/null +++ b/src/pseudo_peer/network.rs @@ -0,0 +1,91 @@ +use super::service::{BlockHashCache, BlockPoller}; +use crate::{ + chainspec::{parser::chain_value_parser, HlChainSpec}, + node::network::HlNetworkPrimitives, + HlPrimitives, +}; +use reth_network::{ + config::{rng_secret_key, SecretKey}, + NetworkConfig, NetworkManager, PeersConfig, +}; +use reth_network_peers::TrustedPeer; +use reth_provider::test_utils::NoopProvider; +use std::{str::FromStr, sync::Arc}; +use tokio::sync::mpsc; + +pub struct NetworkBuilder { + secret: SecretKey, + peer_config: PeersConfig, + boot_nodes: Vec, + discovery_port: u16, + listener_port: u16, +} + +impl Default for NetworkBuilder { + fn default() -> Self { + Self { + secret: rng_secret_key(), + peer_config: PeersConfig::default().with_max_outbound(1).with_max_inbound(1), + boot_nodes: vec![], + discovery_port: 0, + listener_port: 0, + } + } +} + +impl NetworkBuilder { + pub fn with_secret(mut self, secret: SecretKey) -> Self { + self.secret = secret; + self + } + + pub fn with_peer_config(mut self, peer_config: PeersConfig) -> Self { + self.peer_config = peer_config; + self + } + + pub fn with_boot_nodes(mut self, boot_nodes: Vec) -> Self { + self.boot_nodes = boot_nodes; + self + } + + pub fn with_ports(mut self, discovery_port: u16, listener_port: u16) -> Self { + self.discovery_port = discovery_port; + self.listener_port = listener_port; + self + } + + pub async fn build( + self, + block_source: Arc>, + blockhash_cache: BlockHashCache, + ) -> eyre::Result<(NetworkManager, mpsc::Sender<()>)> { + let builder = NetworkConfig::<(), HlNetworkPrimitives>::builder(self.secret) + .boot_nodes(self.boot_nodes) + .peer_config(self.peer_config) + .discovery_port(self.discovery_port) + .listener_port(self.listener_port); + + let (block_poller, start_tx) = BlockPoller::new_suspended(block_source, blockhash_cache); + let config = builder.block_import(Box::new(block_poller)).build(Arc::new(NoopProvider::< + HlChainSpec, + HlPrimitives, + >::new( + chain_value_parser("mainnet").unwrap(), + ))); + + let network = NetworkManager::new(config).await.map_err(|e| eyre::eyre!(e))?; + Ok((network, start_tx)) + } +} + +pub async fn create_network_manager( + destination_peer: String, + block_source: Arc>, + blockhash_cache: BlockHashCache, +) -> eyre::Result<(NetworkManager, mpsc::Sender<()>)> { + NetworkBuilder::default() + .with_boot_nodes(vec![TrustedPeer::from_str(&destination_peer).unwrap()]) + .build::(block_source, blockhash_cache) + .await +} diff --git a/src/pseudo_peer/service.rs b/src/pseudo_peer/service.rs new file mode 100644 index 000000000..d3e4c2fb4 --- /dev/null +++ b/src/pseudo_peer/service.rs @@ -0,0 +1,373 @@ +use super::{sources::BlockSource, utils::LruBiMap}; +use crate::node::{ + network::{HlNetworkPrimitives, HlNewBlock}, + types::BlockAndReceipts, +}; +use alloy_eips::HashOrNumber; +use alloy_primitives::{B256, U128}; +use alloy_rpc_types::Block; +use futures::StreamExt as _; +use parking_lot::RwLock; +use rayon::prelude::*; +use reth_eth_wire::{ + BlockBodies, BlockHeaders, GetBlockBodies, GetBlockHeaders, HeadersDirection, NewBlock, +}; +use reth_network::{ + eth_requests::IncomingEthRequest, + import::{BlockImport, BlockImportEvent, BlockValidation, NewBlockEvent}, + message::NewBlockMessage, +}; +use reth_network_peers::PeerId; +use std::{ + collections::{HashMap, HashSet}, + pin::Pin, + sync::{Arc, Mutex}, + task::{Context, Poll}, + time::Duration, +}; +use tokio::{sync::mpsc, task::JoinHandle}; +use tracing::{debug, info}; + +/// A cache of block hashes to block numbers. +pub type BlockHashCache = Arc>>; +const BLOCKHASH_CACHE_LIMIT: u32 = 1000000; + +pub fn new_blockhash_cache() -> BlockHashCache { + Arc::new(RwLock::new(LruBiMap::new(BLOCKHASH_CACHE_LIMIT))) +} + +/// A block poller that polls blocks from `BlockSource` and sends them to the `block_tx` +#[derive(Debug)] +pub struct BlockPoller { + block_rx: mpsc::Receiver<(u64, BlockAndReceipts)>, + task: JoinHandle>, + blockhash_cache: BlockHashCache, +} + +impl BlockPoller { + const POLL_INTERVAL: Duration = Duration::from_millis(25); + + pub fn new_suspended( + block_source: BS, + blockhash_cache: BlockHashCache, + ) -> (Self, mpsc::Sender<()>) { + let block_source = Arc::new(block_source); + let (start_tx, start_rx) = mpsc::channel(1); + let (block_tx, block_rx) = mpsc::channel(100); + let block_tx_clone = block_tx.clone(); + let task = tokio::spawn(Self::task(start_rx, block_source, block_tx_clone)); + (Self { block_rx, task, blockhash_cache: blockhash_cache.clone() }, start_tx) + } + + #[allow(unused)] + pub fn task_handle(&self) -> &JoinHandle> { + &self.task + } + + async fn task( + mut start_rx: mpsc::Receiver<()>, + block_source: Arc, + block_tx_clone: mpsc::Sender<(u64, BlockAndReceipts)>, + ) -> eyre::Result<()> { + start_rx.recv().await.ok_or(eyre::eyre!("Failed to receive start signal"))?; + info!("Starting block poller"); + + let latest_block_number = block_source + .find_latest_block_number() + .await + .ok_or(eyre::eyre!("Failed to find latest block number"))?; + + let mut next_block_number = latest_block_number; + loop { + let Ok(block) = block_source.collect_block(next_block_number).await else { + tokio::time::sleep(Self::POLL_INTERVAL).await; + continue; + }; + block_tx_clone.send((next_block_number, block)).await?; + next_block_number += 1; + } + } +} + +impl BlockImport for BlockPoller { + fn poll(&mut self, _cx: &mut Context<'_>) -> Poll> { + debug!("(receiver) Polling"); + match Pin::new(&mut self.block_rx).poll_recv(_cx) { + Poll::Ready(Some((number, block))) => { + debug!("Polled block: {}", number); + let reth_block = block.to_reth_block(); + let hash = reth_block.header.hash_slow(); + self.blockhash_cache.write().insert(hash, number); + let td = U128::from(reth_block.header.difficulty); + Poll::Ready(BlockImportEvent::Announcement(BlockValidation::ValidHeader { + block: NewBlockMessage { + block: HlNewBlock(NewBlock { block: reth_block, td }).into(), + hash, + }, + })) + } + Poll::Ready(None) => Poll::Pending, + Poll::Pending => Poll::Pending, + } + } + + fn on_new_block(&mut self, _peer_id: PeerId, _incoming_block: NewBlockEvent) {} +} + +/// A pseudo peer that can process eth requests and feed blocks to reth +pub struct PseudoPeer { + block_source: BS, + blockhash_cache: BlockHashCache, + warm_cache_size: u64, + if_hit_then_warm_around: Arc>>, + + /// This is used to avoid calling `find_latest_block_number` too often. + /// Only used for cache warmup. + known_latest_block_number: u64, +} + +impl PseudoPeer { + pub fn new(block_source: BS, blockhash_cache: BlockHashCache) -> Self { + Self { + block_source, + blockhash_cache, + warm_cache_size: 1000, // reth default chunk size for GetBlockBodies + if_hit_then_warm_around: Arc::new(Mutex::new(HashSet::new())), + known_latest_block_number: 0, + } + } + + async fn collect_block(&self, height: u64) -> eyre::Result { + self.block_source.collect_block(height).await + } + + async fn collect_blocks( + &self, + block_numbers: impl IntoIterator, + ) -> Vec { + let block_numbers = block_numbers.into_iter().collect::>(); + let blocks = futures::stream::iter(block_numbers) + .map(async |number| self.collect_block(number).await.unwrap()) + .buffered(self.block_source.recommended_chunk_size() as usize) + .collect::>() + .await; + blocks + } + + pub async fn process_eth_request( + &mut self, + eth_req: IncomingEthRequest, + ) -> eyre::Result<()> { + match eth_req { + IncomingEthRequest::GetBlockHeaders { + peer_id: _, + request: GetBlockHeaders { start_block, limit, skip, direction }, + response, + } => { + info!( + "GetBlockHeaders request: {start_block:?}, {limit:?}, {skip:?}, {direction:?}" + ); + + let number = match start_block { + HashOrNumber::Hash(hash) => self.hash_to_block_number(hash).await, + HashOrNumber::Number(number) => number, + }; + + let block_headers = match direction { + HeadersDirection::Rising => self.collect_blocks(number..number + limit).await, + HeadersDirection::Falling => { + self.collect_blocks((number + 1 - limit..number + 1).rev()).await + } + } + .into_par_iter() + .map(|block| block.to_reth_block().header.clone()) + .collect::>(); + + let _ = response.send(Ok(BlockHeaders(block_headers))); + } + IncomingEthRequest::GetBlockBodies { peer_id: _, request, response } => { + let GetBlockBodies(hashes) = request; + info!("GetBlockBodies request: {}", hashes.len()); + + let mut numbers = Vec::new(); + for hash in hashes { + numbers.push(self.hash_to_block_number(hash).await); + } + + let block_bodies = self + .collect_blocks(numbers) + .await + .into_iter() + .map(|block| block.to_reth_block().body) + .collect::>(); + + let _ = response.send(Ok(BlockBodies(block_bodies))); + } + IncomingEthRequest::GetNodeData { .. } => { + info!("GetNodeData request: {:?}", eth_req); + } + eth_req => { + info!("New eth protocol request: {:?}", eth_req); + } + } + Ok(()) + } + + async fn hash_to_block_number(&mut self, hash: B256) -> u64 { + // First, try to find the hash in our cache + if let Some(block_number) = self.try_get_cached_block_number(hash).await { + return block_number; + } + + let latest = self.block_source.find_latest_block_number().await.unwrap(); + self.known_latest_block_number = latest; + + // These constants are quite arbitrary but works well in practice + const BACKFILL_RETRY_LIMIT: u64 = 10; + + for _ in 0..BACKFILL_RETRY_LIMIT { + // If not found, backfill the cache and retry + if let Ok(Some(block_number)) = self.backfill_cache_for_hash(hash, latest).await { + return block_number; + } + } + + panic!("Hash not found: {:?}", hash); + } + + async fn fallback_to_official_rpc(&self, hash: B256) -> eyre::Result { + // This is tricky because Raw EVM files (BlockSource) does not have hash to number mapping + // so we can either enumerate all blocks to get hash to number mapping, or fallback to an + // official RPC. The latter is much easier but has 300/day rate limit. + + use jsonrpsee::http_client::HttpClientBuilder; + use jsonrpsee_core::client::ClientT; + + info!("Fallback to official RPC: {:?}", hash); + let client = HttpClientBuilder::default().build("https://rpc.hyperliquid.xyz/evm").unwrap(); + let target_block: Block = client.request("eth_getBlockByHash", (hash, false)).await?; + + info!("From official RPC: {:?} for {hash:?}", target_block.header.number); + self.cache_blocks([(hash, target_block.header.number)]); + Ok(target_block.header.number) + } + + /// Try to get a block number from the cache for the given hash + async fn try_get_cached_block_number(&mut self, hash: B256) -> Option { + let maybe_block_number = self.blockhash_cache.read().get_by_left(&hash).copied(); + if let Some(block_number) = maybe_block_number { + if self.if_hit_then_warm_around.lock().unwrap().contains(&block_number) { + self.warm_cache_around_blocks(block_number, self.warm_cache_size).await; + } + return Some(block_number); + } + None + } + + /// Backfill the cache with blocks to find the target hash + async fn backfill_cache_for_hash( + &mut self, + target_hash: B256, + latest: u64, + ) -> eyre::Result> { + let chunk_size = self.block_source.recommended_chunk_size(); + info!("Hash not found, backfilling... {:?}", target_hash); + + const TRY_OFFICIAL_RPC_THRESHOLD: usize = 20; + for (iteration, end) in (1..=latest).rev().step_by(chunk_size as usize).enumerate() { + // Calculate the range to backfill + let start = std::cmp::max(end.saturating_sub(chunk_size), 1); + + // Backfill this chunk + if let Ok(Some(block_number)) = + self.try_block_range_for_hash(start, end, target_hash).await + { + return Ok(Some(block_number)); + } + + // If not found, first fallback to an official RPC + if iteration >= TRY_OFFICIAL_RPC_THRESHOLD { + match self.fallback_to_official_rpc(target_hash).await { + Ok(block_number) => { + self.warm_cache_around_blocks(block_number, self.warm_cache_size).await; + return Ok(Some(block_number)); + } + Err(e) => { + info!("Fallback to official RPC failed: {:?}", e); + } + } + } + } + + info!("Hash not found: {:?}, retrying from the latest block...", target_hash); + Ok(None) // Not found + } + + async fn warm_cache_around_blocks(&mut self, block_number: u64, chunk_size: u64) { + let start = std::cmp::max(block_number.saturating_sub(chunk_size), 1); + let end = std::cmp::min(block_number + chunk_size, self.known_latest_block_number); + + self.if_hit_then_warm_around.lock().unwrap().insert(start); + self.if_hit_then_warm_around.lock().unwrap().insert(end); + + const IMPOSSIBLE_HASH: B256 = B256::ZERO; + let _ = self.try_block_range_for_hash(start, end, IMPOSSIBLE_HASH).await; + } + + /// Backfill a specific range of block numbers into the cache + async fn try_block_range_for_hash( + &mut self, + start_number: u64, + end_number: u64, + target_hash: B256, + ) -> eyre::Result> { + // Get block numbers that are already cached + let (cached_block_hashes, uncached_block_numbers) = + self.get_cached_block_hashes(start_number, end_number); + + if let Some(&block_number) = cached_block_hashes.get(&target_hash) { + return Ok(Some(block_number)); + } + + if uncached_block_numbers.is_empty() { + info!("All blocks are cached, returning None"); + return Ok(None); + } + + info!("Backfilling from {} to {}", start_number, end_number); + + // Collect blocks and cache them + let blocks = self.collect_blocks(uncached_block_numbers).await; + let block_map: HashMap = + blocks.into_iter().map(|block| (block.hash(), block.number())).collect(); + + let maybe_block_number = block_map.get(&target_hash).copied(); + self.cache_blocks(block_map); + + Ok(maybe_block_number) + } + + /// Get block numbers in the range that are already cached + fn get_cached_block_hashes( + &self, + start_number: u64, + end_number: u64, + ) -> (HashMap, Vec) { + let map = self.blockhash_cache.read(); + let (cached, uncached): (Vec, Vec) = + (start_number..=end_number).partition(|number| map.get_by_right(number).is_some()); + let cached_block_hashes = cached + .into_iter() + .filter_map(|number| map.get_by_right(&number).map(|&hash| (hash, number))) + .collect(); + (cached_block_hashes, uncached) + } + + /// Cache a collection of blocks in the hash-to-number mapping + fn cache_blocks(&self, blocks: impl IntoIterator) { + let mut map = self.blockhash_cache.write(); + for (hash, number) in blocks { + map.insert(hash, number); + } + } +} diff --git a/src/pseudo_peer/sources.rs b/src/pseudo_peer/sources.rs new file mode 100644 index 000000000..68ba69ec5 --- /dev/null +++ b/src/pseudo_peer/sources.rs @@ -0,0 +1,266 @@ +use crate::node::types::BlockAndReceipts; +use aws_sdk_s3::types::RequestPayer; +use eyre::Context; +use futures::{future::BoxFuture, FutureExt}; +use reth_network::cache::LruMap; +use std::{ + path::PathBuf, + sync::{Arc, RwLock}, +}; +use tracing::info; + +pub trait BlockSource: Send + Sync + std::fmt::Debug + Unpin + 'static { + fn collect_block(&self, height: u64) -> BoxFuture>; + fn find_latest_block_number(&self) -> BoxFuture>; + fn recommended_chunk_size(&self) -> u64; +} + +pub type BlockSourceBoxed = Arc>; + +fn name_with_largest_number(files: &[String], is_dir: bool) -> Option<(u64, String)> { + let mut files = files + .iter() + .filter_map(|file_raw| { + let file = file_raw.strip_suffix("/").unwrap_or(file_raw).split("/").last().unwrap(); + let stem = if is_dir { file } else { file.strip_suffix(".rmp.lz4")? }; + stem.parse::().ok().map(|number| (number, file_raw.to_string())) + }) + .collect::>(); + if files.is_empty() { + return None; + } + files.sort_by_key(|(number, _)| *number); + files.last().cloned() +} + +#[derive(Debug, Clone)] +pub struct S3BlockSource { + client: aws_sdk_s3::Client, + bucket: String, +} + +impl S3BlockSource { + pub fn new(client: aws_sdk_s3::Client, bucket: String) -> Self { + Self { client, bucket } + } + + async fn pick_path_with_highest_number( + client: aws_sdk_s3::Client, + bucket: String, + dir: String, + is_dir: bool, + ) -> Option<(u64, String)> { + let request = client + .list_objects() + .bucket(&bucket) + .prefix(dir) + .delimiter("/") + .request_payer(RequestPayer::Requester); + let response = request.send().await.ok()?; + let files: Vec = if is_dir { + response + .common_prefixes + .unwrap() + .iter() + .map(|object| object.prefix.as_ref().unwrap().to_string()) + .collect() + } else { + response + .contents + .unwrap() + .iter() + .map(|object| object.key.as_ref().unwrap().to_string()) + .collect() + }; + name_with_largest_number(&files, is_dir) + } +} + +impl BlockSource for S3BlockSource { + fn collect_block(&self, height: u64) -> BoxFuture> { + let client = self.client.clone(); + let bucket = self.bucket.clone(); + async move { + let path = rmp_path(height); + let request = client + .get_object() + .request_payer(RequestPayer::Requester) + .bucket(&bucket) + .key(path); + let response = request.send().await?; + let bytes = response.body.collect().await?.into_bytes(); + let mut decoder = lz4_flex::frame::FrameDecoder::new(&bytes[..]); + let blocks: Vec = rmp_serde::from_read(&mut decoder)?; + Ok(blocks[0].clone()) + } + .boxed() + } + + fn find_latest_block_number(&self) -> BoxFuture> { + let client = self.client.clone(); + let bucket = self.bucket.clone(); + async move { + let (_, first_level) = Self::pick_path_with_highest_number( + client.clone(), + bucket.clone(), + "".to_string(), + true, + ) + .await?; + let (_, second_level) = Self::pick_path_with_highest_number( + client.clone(), + bucket.clone(), + first_level, + true, + ) + .await?; + let (block_number, third_level) = Self::pick_path_with_highest_number( + client.clone(), + bucket.clone(), + second_level, + false, + ) + .await?; + + info!("Latest block number: {} with path {}", block_number, third_level); + Some(block_number) + } + .boxed() + } + + fn recommended_chunk_size(&self) -> u64 { + 100 + } +} + +impl BlockSource for LocalBlockSource { + fn collect_block(&self, height: u64) -> BoxFuture> { + let dir = self.dir.clone(); + async move { + let path = dir.join(rmp_path(height)); + let file = tokio::fs::read(&path) + .await + .wrap_err_with(|| format!("Failed to read block from {path:?}"))?; + let mut decoder = lz4_flex::frame::FrameDecoder::new(&file[..]); + let blocks: Vec = rmp_serde::from_read(&mut decoder)?; + Ok(blocks[0].clone()) + } + .boxed() + } + + fn find_latest_block_number(&self) -> BoxFuture> { + let dir = self.dir.clone(); + async move { + let (_, first_level) = Self::pick_path_with_highest_number(dir.clone(), true).await?; + let (_, second_level) = + Self::pick_path_with_highest_number(dir.join(first_level), true).await?; + let (block_number, third_level) = + Self::pick_path_with_highest_number(dir.join(second_level), false).await?; + + info!("Latest block number: {} with path {}", block_number, third_level); + Some(block_number) + } + .boxed() + } + + fn recommended_chunk_size(&self) -> u64 { + 1000 + } +} + +#[derive(Debug, Clone)] +pub struct LocalBlockSource { + dir: PathBuf, +} + +impl LocalBlockSource { + pub fn new(dir: impl Into) -> Self { + Self { dir: dir.into() } + } + + fn name_with_largest_number_static(files: &[String], is_dir: bool) -> Option<(u64, String)> { + let mut files = files + .iter() + .filter_map(|file_raw| { + let file = file_raw.strip_suffix("/").unwrap_or(file_raw); + let file = file.split("/").last().unwrap(); + let stem = if is_dir { file } else { file.strip_suffix(".rmp.lz4")? }; + stem.parse::().ok().map(|number| (number, file_raw.to_string())) + }) + .collect::>(); + if files.is_empty() { + return None; + } + files.sort_by_key(|(number, _)| *number); + files.last().map(|(number, file)| (*number, file.to_string())) + } + + async fn pick_path_with_highest_number(dir: PathBuf, is_dir: bool) -> Option<(u64, String)> { + let files = std::fs::read_dir(&dir).unwrap().collect::>(); + let files = files + .into_iter() + .filter(|path| path.as_ref().unwrap().path().is_dir() == is_dir) + .map(|entry| entry.unwrap().path().to_string_lossy().to_string()) + .collect::>(); + + Self::name_with_largest_number_static(&files, is_dir) + } +} + +fn rmp_path(height: u64) -> String { + let f = ((height - 1) / 1_000_000) * 1_000_000; + let s = ((height - 1) / 1_000) * 1_000; + let path = format!("{f}/{s}/{height}.rmp.lz4"); + path +} + +impl BlockSource for BlockSourceBoxed { + fn collect_block(&self, height: u64) -> BoxFuture> { + self.as_ref().collect_block(height) + } + + fn find_latest_block_number(&self) -> BoxFuture> { + self.as_ref().find_latest_block_number() + } + + fn recommended_chunk_size(&self) -> u64 { + self.as_ref().recommended_chunk_size() + } +} + +#[derive(Debug, Clone)] +pub struct CachedBlockSource { + block_source: BlockSourceBoxed, + cache: Arc>>, +} + +impl CachedBlockSource { + const CACHE_LIMIT: u32 = 100000; + pub fn new(block_source: BlockSourceBoxed) -> Self { + Self { block_source, cache: Arc::new(RwLock::new(LruMap::new(Self::CACHE_LIMIT))) } + } +} + +impl BlockSource for CachedBlockSource { + fn collect_block(&self, height: u64) -> BoxFuture> { + let block_source = self.block_source.clone(); + let cache = self.cache.clone(); + async move { + if let Some(block) = cache.write().unwrap().get(&height) { + return Ok(block.clone()); + } + let block = block_source.collect_block(height).await?; + cache.write().unwrap().insert(height, block.clone()); + Ok(block) + } + .boxed() + } + + fn find_latest_block_number(&self) -> BoxFuture> { + self.block_source.find_latest_block_number() + } + + fn recommended_chunk_size(&self) -> u64 { + self.block_source.recommended_chunk_size() + } +} diff --git a/src/pseudo_peer/tests.rs b/src/pseudo_peer/tests.rs new file mode 100644 index 000000000..8a0f625be --- /dev/null +++ b/src/pseudo_peer/tests.rs @@ -0,0 +1,26 @@ +use crate::pseudo_peer::{prelude::*, BlockSourceType}; + +#[tokio::test] +async fn test_block_source_config_s3() { + let config = BlockSourceConfig::s3("test-bucket".to_string()).await; + assert!( + matches!(config.source_type, BlockSourceType::S3 { bucket } if bucket == "test-bucket") + ); +} + +#[tokio::test] +async fn test_block_source_config_local() { + let config = BlockSourceConfig::local("/test/path".to_string()); + assert!(matches!(config.source_type, BlockSourceType::Local { path } if path == "/test/path")); +} + +#[test] +fn test_error_types() { + let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found"); + let benchmark_error: PseudoPeerError = io_error.into(); + + match benchmark_error { + PseudoPeerError::Io(_) => (), + _ => panic!("Expected Io error"), + } +} diff --git a/src/pseudo_peer/utils.rs b/src/pseudo_peer/utils.rs new file mode 100644 index 000000000..31b2c6ad7 --- /dev/null +++ b/src/pseudo_peer/utils.rs @@ -0,0 +1,43 @@ +use std::{collections::HashMap, fmt::Debug, hash::Hash}; + +use reth_network::cache::LruCache; + +/// A naive implementation of a bi-directional LRU cache. +#[derive(Debug)] +pub struct LruBiMap { + left_to_right: HashMap, + right_to_left: HashMap, + lru_keys: LruCache, +} + +impl LruBiMap { + pub fn new(limit: u32) -> Self { + Self { + left_to_right: HashMap::new(), + right_to_left: HashMap::new(), + lru_keys: LruCache::new(limit), + } + } + + pub fn insert(&mut self, key: K, value: V) { + if let (true, Some(evicted)) = self.lru_keys.insert_and_get_evicted(key.clone()) { + self.evict(&evicted); + } + self.left_to_right.insert(key.clone(), value.clone()); + self.right_to_left.insert(value.clone(), key.clone()); + } + + pub fn get_by_left(&self, key: &K) -> Option<&V> { + self.left_to_right.get(key) + } + + pub fn get_by_right(&self, value: &V) -> Option<&K> { + self.right_to_left.get(value) + } + + fn evict(&mut self, key: &K) { + if let Some(value) = self.left_to_right.remove(key) { + self.right_to_left.remove(&value); + } + } +}