From 0ec1d267762feb874f859995f2ee149a9a8fa91a Mon Sep 17 00:00:00 2001 From: Will Qiu Date: Tue, 31 Oct 2023 17:10:18 +0800 Subject: [PATCH] feat: add p2p crate --- Cargo.lock | 2691 +++++++++++++++--- Cargo.toml | 5 + P2P.md | 20 + bin/silius/Cargo.toml | 2 + bin/silius/src/bundler.rs | 3 + bin/silius/src/cli/args.rs | 91 +- bin/silius/src/cli/commands.rs | 12 +- bin/silius/src/utils.rs | 6 + crates/contracts/Cargo.toml | 3 +- crates/contracts/src/entry_point.rs | 8 + crates/contracts/src/tracer.rs | 4 +- crates/grpc/Cargo.toml | 4 + crates/grpc/src/network.rs | 31 + crates/grpc/src/uopool.rs | 141 +- crates/p2p/Cargo.toml | 40 + crates/p2p/src/behaviour.rs | 74 + crates/p2p/src/config.rs | 105 + crates/p2p/src/discovery.rs | 180 ++ crates/p2p/src/enr.rs | 96 + crates/p2p/src/gossipsub.rs | 118 + crates/p2p/src/lib.rs | 10 + crates/p2p/src/network.rs | 378 +++ crates/p2p/src/peer_manager/mod.rs | 141 + crates/p2p/src/peer_manager/peerdb.rs | 39 + crates/p2p/src/request_response/behaviour.rs | 497 ++++ crates/p2p/src/request_response/handler.rs | 225 ++ crates/p2p/src/request_response/inbound.rs | 104 + crates/p2p/src/request_response/mod.rs | 9 + crates/p2p/src/request_response/models.rs | 244 ++ crates/p2p/src/request_response/outbound.rs | 103 + crates/p2p/src/request_response/protocol.rs | 120 + crates/p2p/src/tests/enr.rs | 13 + crates/p2p/src/tests/mod.rs | 99 + crates/p2p/src/tests/pubsub.rs | 58 + crates/p2p/src/tests/req_rep.rs | 127 + crates/p2p/src/utils.rs | 0 crates/primitives/Cargo.toml | 6 +- crates/primitives/src/chain.rs | 21 + crates/primitives/src/lib.rs | 2 + crates/primitives/src/p2p.rs | 60 + crates/primitives/src/user_operation.rs | 164 +- crates/uopool/Cargo.toml | 1 + crates/uopool/src/builder.rs | 6 + crates/uopool/src/uopool.rs | 10 +- crates/uopool/src/validate/mod.rs | 2 + crates/uopool/src/validate/validator.rs | 23 +- examples/storage/Cargo.toml | 1 + examples/storage/examples/database.rs | 8 +- examples/storage/examples/memory.rs | 8 +- tests/Cargo.toml | 3 + tests/src/simulation_tests.rs | 4 +- 51 files changed, 5548 insertions(+), 572 deletions(-) create mode 100644 P2P.md create mode 100644 crates/grpc/src/network.rs create mode 100644 crates/p2p/Cargo.toml create mode 100644 crates/p2p/src/behaviour.rs create mode 100644 crates/p2p/src/config.rs create mode 100644 crates/p2p/src/discovery.rs create mode 100644 crates/p2p/src/enr.rs create mode 100644 crates/p2p/src/gossipsub.rs create mode 100644 crates/p2p/src/lib.rs create mode 100644 crates/p2p/src/network.rs create mode 100644 crates/p2p/src/peer_manager/mod.rs create mode 100644 crates/p2p/src/peer_manager/peerdb.rs create mode 100644 crates/p2p/src/request_response/behaviour.rs create mode 100644 crates/p2p/src/request_response/handler.rs create mode 100644 crates/p2p/src/request_response/inbound.rs create mode 100644 crates/p2p/src/request_response/mod.rs create mode 100644 crates/p2p/src/request_response/models.rs create mode 100644 crates/p2p/src/request_response/outbound.rs create mode 100644 crates/p2p/src/request_response/protocol.rs create mode 100644 crates/p2p/src/tests/enr.rs create mode 100644 crates/p2p/src/tests/mod.rs create mode 100644 crates/p2p/src/tests/pubsub.rs create mode 100644 crates/p2p/src/tests/req_rep.rs create mode 100644 crates/p2p/src/utils.rs create mode 100644 crates/primitives/src/p2p.rs diff --git a/Cargo.lock b/Cargo.lock index 901206cd..4f724577 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,6 +27,28 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher 0.3.0", + "cpufeatures", + "ctr 0.8.0", + "opaque-debug", +] + [[package]] name = "aes" version = "0.8.3" @@ -34,15 +56,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" dependencies = [ "cfg-if", - "cipher", + "cipher 0.4.4", "cpufeatures", ] +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead", + "aes 0.7.5", + "cipher 0.3.0", + "ctr 0.8.0", + "ghash", + "subtle", +] + [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ "getrandom", "once_cell", @@ -51,24 +87,31 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "alloy-primitives" version = "0.2.0" @@ -134,7 +177,7 @@ checksum = "5bd2b0c6299738585f1bfa9720bb8df0e57750be8cf83269093d425bc919039b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", "syn-solidity 0.2.0", "tiny-keccak", ] @@ -149,7 +192,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", "syn-solidity 0.3.2", "tiny-keccak", ] @@ -195,9 +238,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.5.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", @@ -209,15 +252,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] @@ -233,9 +276,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "2.1.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys", @@ -401,6 +444,71 @@ dependencies = [ "term", ] +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "asn1_der" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + [[package]] name = "async-lock" version = "2.8.0" @@ -418,7 +526,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -440,18 +548,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -465,6 +573,19 @@ dependencies = [ "rustc_version 0.4.0", ] +[[package]] +name = "asynchronous-codec" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568" +dependencies = [ + "bytes", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite", +] + [[package]] name = "atomic-polyfill" version = "0.1.11" @@ -474,6 +595,17 @@ dependencies = [ "critical-section", ] +[[package]] +name = "attohttpc" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" +dependencies = [ + "http", + "log", + "url", +] + [[package]] name = "auto_impl" version = "1.1.0" @@ -561,6 +693,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + [[package]] name = "base16ct" version = "0.2.0" @@ -575,9 +713,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -643,9 +781,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "bitvec" @@ -660,6 +798,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -693,15 +840,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" dependencies = [ - "sha2 0.10.7", + "sha2 0.10.8", "tinyvec", ] [[package]] name = "bstr" -version = "1.6.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" +checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" dependencies = [ "memchr", "serde", @@ -727,9 +874,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -772,9 +919,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" dependencies = [ "serde", ] @@ -787,7 +934,7 @@ checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592" dependencies = [ "camino", "cargo-platform", - "semver 1.0.19", + "semver 1.0.20", "serde", "serde_json", "thiserror", @@ -818,6 +965,31 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" +dependencies = [ + "cfg-if", + "cipher 0.3.0", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" +dependencies = [ + "aead", + "chacha20", + "cipher 0.3.0", + "poly1305", + "zeroize", +] + [[package]] name = "chrono" version = "0.4.31" @@ -833,6 +1005,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "cipher" version = "0.4.4" @@ -856,9 +1037,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.4" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", @@ -866,9 +1047,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.4" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -878,21 +1059,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "cobs" @@ -910,7 +1091,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -922,10 +1103,10 @@ dependencies = [ "bs58", "coins-core", "digest 0.10.7", - "hmac", + "hmac 0.12.1", "k256", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] @@ -937,11 +1118,11 @@ checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" dependencies = [ "bitvec", "coins-bip32", - "hmac", + "hmac 0.12.1", "once_cell", "pbkdf2 0.12.2", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] @@ -951,7 +1132,7 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bech32", "bs58", "digest 0.10.7", @@ -960,7 +1141,7 @@ dependencies = [ "ripemd", "serde", "serde_derive", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "thiserror", ] @@ -971,15 +1152,25 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "concurrent-queue" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const-hex" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa72a10d0e914cad6bcad4e7409e68d230c1c2db67896e19a37f758b1fcbdab5" +checksum = "a5104de16b218eddf8e34ffe2f86f74bfa4e61e95a1b89732fccf6325efd0557" dependencies = [ "cfg-if", "cpufeatures", "hex", + "proptest", "serde", ] @@ -1026,11 +1217,20 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -1126,13 +1326,60 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher 0.3.0", +] + [[package]] name = "ctr" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "cipher", + "cipher 0.4.4", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version 0.4.0", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] @@ -1156,7 +1403,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -1167,7 +1414,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -1177,10 +1424,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.0", + "hashbrown 0.14.2", "lock_api", "once_cell", - "parking_lot_core", + "parking_lot_core 0.9.9", ] [[package]] @@ -1189,6 +1436,36 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +[[package]] +name = "data-encoding-macro" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c904b33cc60130e1aeea4956ab803d08a3f4a0ca82d64ed757afac3891f2bb99" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fdf3fce3ce863539ec1d7fd1b6dcc3c645663376b43ed376bbf887733e4f772" +dependencies = [ + "data-encoding", + "syn 1.0.109", +] + +[[package]] +name = "delay_map" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4355c25cbf99edcb6b4a0e906f6bdc6956eda149e84455bea49696429b2f8e8" +dependencies = [ + "futures", + "tokio-util", +] + [[package]] name = "der" version = "0.7.8" @@ -1199,12 +1476,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "der-parser" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + [[package]] name = "deranged" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" dependencies = [ + "powerfmt", "serde", ] @@ -1322,18 +1614,68 @@ dependencies = [ ] [[package]] -name = "dotenv" -version = "0.15.0" +name = "discv5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +checksum = "98c05fa26996c6141f78ac4fafbe297a7fa69690565ba4e0d1f2e60bde5ce501" +dependencies = [ + "aes 0.7.5", + "aes-gcm", + "arrayvec", + "delay_map", + "enr", + "fnv", + "futures", + "hashlink", + "hex", + "hkdf", + "lazy_static", + "libp2p-core", + "libp2p-identity", + "lru 0.7.8", + "more-asserts", + "parking_lot 0.11.2", + "rand 0.8.5", + "rlp", + "smallvec 1.11.1", + "socket2 0.4.10", + "tokio", + "tracing", + "tracing-subscriber", + "uint", + "zeroize", +] [[package]] -name = "dunce" -version = "1.0.4" +name = "displaydoc" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" - -[[package]] +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + +[[package]] name = "ecdsa" version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1347,6 +1689,30 @@ dependencies = [ "spki", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.6.4", + "serde", + "sha2 0.10.8", + "zeroize", +] + [[package]] name = "educe" version = "0.4.23" @@ -1367,9 +1733,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" -version = "0.13.5" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" dependencies = [ "base16ct", "crypto-bigint", @@ -1384,6 +1750,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + [[package]] name = "ena" version = "0.14.2" @@ -1408,8 +1780,9 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe81b5c06ecfdbc71dd845216f225f53b62a10cb8a16c946836a3467f701d05b" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bytes", + "ed25519-dalek", "hex", "k256", "log", @@ -1420,17 +1793,41 @@ dependencies = [ "zeroize", ] +[[package]] +name = "enum-as-inner" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "enum-ordinalize" -version = "3.1.13" +version = "3.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4f76552f53cefc9a7f64987c3701b99d982f7690606fd67de1d09712fbf52f1" +checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee" dependencies = [ "num-bigint", "num-traits", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -1441,14 +1838,14 @@ checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] name = "enumset" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e875f1719c16de097dee81ed675e2d9bb63096823ed3f0ca827b7dea3028bbbb" +checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" dependencies = [ "enumset_derive", ] @@ -1462,7 +1859,20 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", ] [[package]] @@ -1473,42 +1883,31 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "eth-keystore" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" dependencies = [ - "aes", - "ctr", + "aes 0.8.3", + "ctr 0.9.2", "digest 0.10.7", "hex", - "hmac", + "hmac 0.12.1", "pbkdf2 0.11.0", "rand 0.8.5", "scrypt", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "thiserror", "uuid", @@ -1672,7 +2071,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.37", + "syn 2.0.38", "toml", "walkdir", ] @@ -1696,7 +2095,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.37", + "syn 2.0.38", "toml", "walkdir", ] @@ -1713,7 +2112,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -1729,7 +2128,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -1754,7 +2153,7 @@ dependencies = [ "serde", "serde_json", "strum 0.25.0", - "syn 2.0.37", + "syn 2.0.38", "tempfile", "thiserror", "tiny-keccak", @@ -1784,7 +2183,7 @@ dependencies = [ "serde", "serde_json", "strum 0.25.0", - "syn 2.0.37", + "syn 2.0.38", "tempfile", "thiserror", "tiny-keccak", @@ -1794,7 +2193,7 @@ dependencies = [ [[package]] name = "ethers-core" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#08bcb67c36d9a2869950e51ecf76124c9febe035" +source = "git+https://github.com/gakonst/ethers-rs#17c008e915f22686bfdc769e7140e8c50e6b8a61" dependencies = [ "arrayvec", "bytes", @@ -1824,7 +2223,7 @@ source = "git+https://github.com/Vid201/ethers-rs?branch=chore/ws#d9c2bafd0c462a dependencies = [ "ethers-core 2.0.8", "reqwest", - "semver 1.0.19", + "semver 1.0.20", "serde", "serde_json", "thiserror", @@ -1839,7 +2238,7 @@ checksum = "0e53451ea4a8128fbce33966da71132cf9e1040dcfd2a2084fd7733ada7b2045" dependencies = [ "ethers-core 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest", - "semver 1.0.19", + "semver 1.0.20", "serde", "serde_json", "thiserror", @@ -1943,7 +2342,7 @@ dependencies = [ "async-recursion", "async-trait", "auto_impl", - "base64 0.21.4", + "base64 0.21.5", "bytes", "const-hex", "enr", @@ -1981,7 +2380,7 @@ checksum = "6838fa110e57d572336178b7c79e94ff88ef976306852d8cb87d9e5b1fc7c0b5" dependencies = [ "async-trait", "auto_impl", - "base64 0.21.4", + "base64 0.21.5", "bytes", "const-hex", "enr", @@ -2023,7 +2422,7 @@ dependencies = [ "eth-keystore", "ethers-core 2.0.8", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "tracing", ] @@ -2042,7 +2441,7 @@ dependencies = [ "eth-keystore", "ethers-core 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "tracing", ] @@ -2066,10 +2465,10 @@ dependencies = [ "path-slash", "rayon", "regex", - "semver 1.0.19", + "semver 1.0.20", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "solang-parser", "svm-rs", "svm-rs-builds", @@ -2100,7 +2499,7 @@ dependencies = [ "path-slash", "rayon", "regex", - "semver 1.0.19", + "semver 1.0.20", "serde", "serde_json", "solang-parser", @@ -2142,6 +2541,7 @@ version = "0.3.0-alpha" dependencies = [ "ethers 2.0.8", "eyre", + "futures", "silius-primitives", "silius-uopool", "tempdir", @@ -2181,9 +2581,18 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fastrlp" @@ -2206,6 +2615,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "fiat-crypto" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a481586acf778f1b1455424c343f71124b048ffa5f4fc3f8f6ae9dc432dcb3c7" + [[package]] name = "fixed-hash" version = "0.8.0" @@ -2226,9 +2641,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -2288,9 +2703,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -2301,11 +2716,21 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-bounded" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b07bbbe7d7e78809544c6f718d875627addc73a7c3582447abc052cd3dc67e0" +dependencies = [ + "futures-timer", + "futures-util", +] + [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -2313,26 +2738,42 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", "futures-util", + "num_cpus", ] [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" + +[[package]] +name = "futures-lite" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] [[package]] name = "futures-locks" @@ -2346,26 +2787,47 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", +] + +[[package]] +name = "futures-rustls" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd3cf68c183738046838e300353e4716c674dc5e56890de4826801a6622a28" +dependencies = [ + "futures-io", + "rustls", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" + +[[package]] +name = "futures-ticker" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "9763058047f713632a52e916cc7f6a4b3fc6e9fc1ff8c5b1dc49e5a89041682e" +dependencies = [ + "futures", + "futures-timer", + "instant", +] [[package]] name = "futures-timer" @@ -2379,9 +2841,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -2426,6 +2888,16 @@ dependencies = [ "wasi", ] +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gimli" version = "0.28.0" @@ -2597,11 +3069,23 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.7", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.7", +] [[package]] name = "hashbrown" @@ -2609,15 +3093,19 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.6", "serde", ] [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +dependencies = [ + "ahash 0.8.6", + "allocator-api2", +] [[package]] name = "hashers" @@ -2628,6 +3116,15 @@ dependencies = [ "fxhash", ] +[[package]] +name = "hashlink" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +dependencies = [ + "hashbrown 0.11.2", +] + [[package]] name = "heapless" version = "0.7.16" @@ -2675,6 +3172,31 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hex_fmt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac 0.12.1", +] + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + [[package]] name = "hmac" version = "0.12.1" @@ -2684,6 +3206,17 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + [[package]] name = "home" version = "0.5.5" @@ -2693,6 +3226,17 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + [[package]] name = "http" version = "0.2.9" @@ -2733,6 +3277,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.27" @@ -2750,7 +3300,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -2759,9 +3309,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", @@ -2800,16 +3350,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -2827,6 +3377,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "idna" version = "0.4.0" @@ -2837,6 +3398,54 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "if-addrs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "if-watch" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb892e5777fe09e16f3d44de7802f4daa7267ecbe8c466f19d94e25bb0c303e" +dependencies = [ + "async-io", + "core-foundation", + "fnv", + "futures", + "if-addrs", + "ipnet", + "log", + "rtnetlink", + "system-configuration", + "tokio", + "windows", +] + +[[package]] +name = "igd-next" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e065e90a518ab5fedf79aa1e4b784e10f8e484a834f6bda85c42633a2cb7af" +dependencies = [ + "async-trait", + "attohttpc", + "bytes", + "futures", + "http", + "hyper", + "log", + "rand 0.8.5", + "tokio", + "url", + "xmltree", +] + [[package]] name = "impl-codec" version = "0.6.0" @@ -2894,12 +3503,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.2", ] [[package]] @@ -2922,19 +3531,42 @@ dependencies = [ ] [[package]] -name = "ipnet" -version = "2.8.0" +name = "io-lifetimes" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" - -[[package]] -name = "is-terminal" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2 0.5.5", + "widestring", + "windows-sys", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is-terminal" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", - "rustix", + "rustix 0.38.21", "windows-sys", ] @@ -2955,9 +3587,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] @@ -2990,18 +3622,18 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad9b31183a8bcbe843e32ca8554ad2936633548d95a7bb6a8e14c767dea6b05" +checksum = "affdc52f7596ccb2d7645231fc6163bb314630c989b64998f3699a28b4d5d4dc" dependencies = [ - "jsonrpsee-client-transport 0.20.1", - "jsonrpsee-core 0.20.1", - "jsonrpsee-http-client 0.20.1", - "jsonrpsee-proc-macros 0.20.1", - "jsonrpsee-server 0.20.1", - "jsonrpsee-types 0.20.1", - "jsonrpsee-wasm-client 0.20.1", - "jsonrpsee-ws-client 0.20.1", + "jsonrpsee-client-transport 0.20.3", + "jsonrpsee-core 0.20.3", + "jsonrpsee-http-client 0.20.3", + "jsonrpsee-proc-macros 0.20.3", + "jsonrpsee-server 0.20.3", + "jsonrpsee-types 0.20.3", + "jsonrpsee-wasm-client 0.20.3", + "jsonrpsee-ws-client 0.20.3", "tokio", "tracing", ] @@ -3030,15 +3662,15 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97f2743cad51cc86b0dbfe316309eeb87a9d96a3d7f4dd7a99767c4b5f065335" +checksum = "b5b005c793122d03217da09af68ba9383363caa950b90d3436106df8cabce935" dependencies = [ "futures-channel", "futures-util", "gloo-net 0.4.0", "http", - "jsonrpsee-core 0.20.1", + "jsonrpsee-core 0.20.3", "pin-project", "rustls-native-certs", "soketto", @@ -3066,7 +3698,7 @@ dependencies = [ "globset", "hyper", "jsonrpsee-types 0.18.2", - "parking_lot", + "parking_lot 0.12.1", "rand 0.8.5", "rustc-hash", "serde", @@ -3081,9 +3713,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35dc957af59ce98373bcdde0c1698060ca6c2d2e9ae357b459c7158b6df33330" +checksum = "da2327ba8df2fdbd5e897e2b5ed25ce7f299d345b9736b6828814c3dbd1fd47b" dependencies = [ "anyhow", "async-lock", @@ -3092,8 +3724,8 @@ dependencies = [ "futures-timer", "futures-util", "hyper", - "jsonrpsee-types 0.20.1", - "parking_lot", + "jsonrpsee-types 0.20.3", + "parking_lot 0.12.1", "rand 0.8.5", "rustc-hash", "serde", @@ -3126,15 +3758,15 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd865d0072764cb937b0110a92b5f53e995f7101cb346beca03d93a2dea79de" +checksum = "5f80c17f62c7653ce767e3d7288b793dfec920f97067ceb189ebdd3570f2bc20" dependencies = [ "async-trait", "hyper", "hyper-rustls", - "jsonrpsee-core 0.20.1", - "jsonrpsee-types 0.20.1", + "jsonrpsee-core 0.20.3", + "jsonrpsee-types 0.20.3", "serde", "serde_json", "thiserror", @@ -3151,7 +3783,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6027ac0b197ce9543097d02a290f550ce1d9432bf301524b013053c0b75cc94" dependencies = [ "heck", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -3159,12 +3791,12 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef91b1017a4edb63f65239381c18de39f88d0e0760ab626d806e196f7f51477" +checksum = "29110019693a4fa2dbda04876499d098fa16d70eba06b1e6e2b3f1b251419515" dependencies = [ "heck", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -3192,15 +3824,15 @@ dependencies = [ [[package]] name = "jsonrpsee-server" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f4e2f3d223d810e363fb8b5616ec4c6254243ee7f452d05ac281cdc9cf76b2" +checksum = "82c39a00449c9ef3f50b84fc00fc4acba20ef8f559f07902244abf4c15c5ab9c" dependencies = [ "futures-util", "http", "hyper", - "jsonrpsee-core 0.20.1", - "jsonrpsee-types 0.20.1", + "jsonrpsee-core 0.20.3", + "jsonrpsee-types 0.20.3", "route-recognizer", "serde", "serde_json", @@ -3243,9 +3875,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9e25aec855b2a7d3ed90fded6c41e8c3fb72b63f071e1be3f0004eba19b625" +checksum = "5be0be325642e850ed0bdff426674d2e66b2b7117c9be23a7caef68a2902b7d9" dependencies = [ "anyhow", "beef", @@ -3268,13 +3900,13 @@ dependencies = [ [[package]] name = "jsonrpsee-wasm-client" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "010306151579898dc1000bab239ef7a73a73f04cb8ef267ee28b9a000267e813" +checksum = "7c7cbb3447cf14fd4d2f407c3cc96e6c9634d5440aa1fbed868a31f3c02b27f0" dependencies = [ - "jsonrpsee-client-transport 0.20.1", - "jsonrpsee-core 0.20.1", - "jsonrpsee-types 0.20.1", + "jsonrpsee-client-transport 0.20.3", + "jsonrpsee-core 0.20.3", + "jsonrpsee-types 0.20.3", ] [[package]] @@ -3291,14 +3923,14 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88e35e9dfa89248ae3e92f689c1f0a190ce12d377eba7d2d08e5a7f6cc5694a" +checksum = "bca9cb3933ccae417eb6b08c3448eb1cb46e39834e5b503e395e5e5bd08546c0" dependencies = [ "http", - "jsonrpsee-client-transport 0.20.1", - "jsonrpsee-core 0.20.1", - "jsonrpsee-types 0.20.1", + "jsonrpsee-client-transport 0.20.3", + "jsonrpsee-core 0.20.3", + "jsonrpsee-types 0.20.3", "url", ] @@ -3308,9 +3940,9 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -3326,7 +3958,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "sha2 0.10.7", + "sha2 0.10.8", "signature", ] @@ -3381,9 +4013,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.148" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libloading" @@ -3397,21 +4029,482 @@ dependencies = [ [[package]] name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libp2p" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94495eb319a85b70a68b85e2389a95bb3555c71c49025b78c691a854a7e6464" +dependencies = [ + "bytes", + "either", + "futures", + "futures-timer", + "getrandom", + "instant", + "libp2p-allow-block-list", + "libp2p-connection-limits", + "libp2p-core", + "libp2p-dns", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-identity", + "libp2p-mdns", + "libp2p-metrics", + "libp2p-noise", + "libp2p-quic", + "libp2p-request-response", + "libp2p-swarm", + "libp2p-tcp", + "libp2p-upnp", + "libp2p-yamux", + "multiaddr", + "pin-project", + "rw-stream-sink", + "thiserror", +] + +[[package]] +name = "libp2p-allow-block-list" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55b46558c5c0bf99d3e2a1a38fd54ff5476ca66dd1737b12466a1824dd219311" +dependencies = [ + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "void", +] + +[[package]] +name = "libp2p-connection-limits" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f5107ad45cb20b2f6c3628c7b6014b996fcb13a88053f4569c872c6e30abf58" +dependencies = [ + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "void", +] + +[[package]] +name = "libp2p-core" +version = "0.40.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd44289ab25e4c9230d9246c475a22241e301b23e8f4061d3bdef304a1a99713" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "libp2p-identity", + "log", + "multiaddr", + "multihash", + "multistream-select", + "once_cell", + "parking_lot 0.12.1", + "pin-project", + "quick-protobuf", + "rand 0.8.5", + "rw-stream-sink", + "smallvec 1.11.1", + "thiserror", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-dns" +version = "0.40.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6a18db73084b4da2871438f6239fef35190b05023de7656e877c18a00541a3b" +dependencies = [ + "async-trait", + "futures", + "libp2p-core", + "libp2p-identity", + "log", + "parking_lot 0.12.1", + "smallvec 1.11.1", + "trust-dns-resolver", +] + +[[package]] +name = "libp2p-gossipsub" +version = "0.45.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f9624e2a843b655f1c1b8262b8d5de6f309413fca4d66f01bb0662429f84dc" +dependencies = [ + "asynchronous-codec", + "base64 0.21.5", + "byteorder", + "bytes", + "either", + "fnv", + "futures", + "futures-ticker", + "getrandom", + "hex_fmt", + "instant", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "log", + "prometheus-client", + "quick-protobuf", + "quick-protobuf-codec", + "rand 0.8.5", + "regex", + "sha2 0.10.8", + "smallvec 1.11.1", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-identify" +version = "0.43.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a96638a0a176bec0a4bcaebc1afa8cf909b114477209d7456ade52c61cd9cd" +dependencies = [ + "asynchronous-codec", + "either", + "futures", + "futures-bounded", + "futures-timer", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "log", + "lru 0.12.0", + "quick-protobuf", + "quick-protobuf-codec", + "smallvec 1.11.1", + "thiserror", + "void", +] + +[[package]] +name = "libp2p-identity" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "cdd6317441f361babc74c2989c6484eb0726045399b6648de039e1805ea96972" +dependencies = [ + "asn1_der", + "bs58", + "ed25519-dalek", + "hkdf", + "libsecp256k1", + "log", + "multihash", + "quick-protobuf", + "rand 0.8.5", + "sha2 0.10.8", + "thiserror", + "zeroize", +] + +[[package]] +name = "libp2p-mdns" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a2567c305232f5ef54185e9604579a894fd0674819402bb0ac0246da82f52a" +dependencies = [ + "data-encoding", + "futures", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "log", + "rand 0.8.5", + "smallvec 1.11.1", + "socket2 0.5.5", + "tokio", + "trust-dns-proto 0.22.0", + "void", +] + +[[package]] +name = "libp2p-metrics" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239ba7d28f8d0b5d77760dc6619c05c7e88e74ec8fbbe97f856f20a56745e620" +dependencies = [ + "instant", + "libp2p-core", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-identity", + "libp2p-swarm", + "once_cell", + "prometheus-client", +] + +[[package]] +name = "libp2p-mplex" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93959ed08b6caf9810e067655e25f1362098797fef7c44d3103e63dcb6f0fabe" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures", + "libp2p-core", + "libp2p-identity", + "log", + "nohash-hasher", + "parking_lot 0.12.1", + "rand 0.8.5", + "smallvec 1.11.1", + "unsigned-varint", +] + +[[package]] +name = "libp2p-noise" +version = "0.43.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2eeec39ad3ad0677551907dd304b2f13f17208ccebe333bef194076cd2e8921" +dependencies = [ + "bytes", + "curve25519-dalek", + "futures", + "libp2p-core", + "libp2p-identity", + "log", + "multiaddr", + "multihash", + "once_cell", + "quick-protobuf", + "rand 0.8.5", + "sha2 0.10.8", + "snow", + "static_assertions", + "thiserror", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "libp2p-quic" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "130d451d83f21b81eb7b35b360bc7972aeafb15177784adc56528db082e6b927" +dependencies = [ + "bytes", + "futures", + "futures-timer", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-tls", + "log", + "parking_lot 0.12.1", + "quinn", + "rand 0.8.5", + "ring 0.16.20", + "rustls", + "socket2 0.5.5", + "thiserror", + "tokio", +] + +[[package]] +name = "libp2p-request-response" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e3b4d67870478db72bac87bfc260ee6641d0734e0e3e275798f089c3fecfd4" +dependencies = [ + "async-trait", + "futures", + "instant", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "log", + "rand 0.8.5", + "smallvec 1.11.1", + "void", +] + +[[package]] +name = "libp2p-swarm" +version = "0.43.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "580189e0074af847df90e75ef54f3f30059aedda37ea5a1659e8b9fca05c0141" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm-derive", + "log", + "multistream-select", + "once_cell", + "rand 0.8.5", + "smallvec 1.11.1", + "tokio", + "void", +] + +[[package]] +name = "libp2p-swarm-derive" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4d5ec2a3df00c7836d7696c136274c9c59705bac69133253696a6c932cd1d74" +dependencies = [ + "heck", + "proc-macro-warning", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "libp2p-tcp" +version = "0.40.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b558dd40d1bcd1aaaed9de898e9ec6a436019ecc2420dd0016e712fbb61c5508" +dependencies = [ + "futures", + "futures-timer", + "if-watch", + "libc", + "libp2p-core", + "libp2p-identity", + "log", + "socket2 0.5.5", + "tokio", +] + +[[package]] +name = "libp2p-tls" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8218d1d5482b122ccae396bbf38abdcb283ecc96fa54760e1dfd251f0546ac61" +dependencies = [ + "futures", + "futures-rustls", + "libp2p-core", + "libp2p-identity", + "rcgen", + "ring 0.16.20", + "rustls", + "rustls-webpki 0.101.7", + "thiserror", + "x509-parser", + "yasna", +] + +[[package]] +name = "libp2p-upnp" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82775a47b34f10f787ad3e2a22e2c1541e6ebef4fe9f28f3ac553921554c94c1" +dependencies = [ + "futures", + "futures-timer", + "igd-next", + "libp2p-core", + "libp2p-swarm", + "log", + "tokio", + "void", +] + +[[package]] +name = "libp2p-yamux" +version = "0.44.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eedcb62824c4300efb9cfd4e2a6edaf3ca097b9e68b36dabe45a44469fd6a85" +dependencies = [ + "futures", + "libp2p-core", + "log", + "thiserror", + "yamux", +] + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] -name = "lock_api" +name = "linux-raw-sys" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -3423,6 +4516,15 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "lru" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +dependencies = [ + "hashbrown 0.12.3", +] + [[package]] name = "lru" version = "0.9.0" @@ -3432,6 +4534,30 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "lru" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efa59af2ddfad1854ae27d75009d538d0998b4b2fd47083e743ac1a10e46c60" +dependencies = [ + "hashbrown 0.14.2", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matchers" version = "0.1.0" @@ -3441,6 +4567,12 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + [[package]] name = "matchit" version = "0.7.3" @@ -3465,9 +4597,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.3" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -3484,7 +4616,7 @@ version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", "metrics-macros", "portable-atomic 0.3.20", ] @@ -3523,9 +4655,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "wasi", @@ -3553,12 +4685,72 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "more-asserts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" + +[[package]] +name = "multiaddr" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92a651988b3ed3ad1bc8c87d016bb92f6f395b84ed1db9b926b32b1fc5a2c8b5" +dependencies = [ + "arrayref", + "byteorder", + "data-encoding", + "libp2p-identity", + "multibase", + "multihash", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint", + "url", +] + +[[package]] +name = "multibase" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" +dependencies = [ + "base-x", + "data-encoding", + "data-encoding-macro", +] + +[[package]] +name = "multihash" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" +dependencies = [ + "core2", + "unsigned-varint", +] + [[package]] name = "multimap" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +[[package]] +name = "multistream-select" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0df8e5eec2298a62b326ee4f0d7fe1a6b90a09dfcf9df37b38f947a8c42f19" +dependencies = [ + "bytes", + "futures", + "log", + "pin-project", + "smallvec 1.11.1", + "unsigned-varint", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -3577,18 +4769,101 @@ dependencies = [ "tempfile", ] +[[package]] +name = "netlink-packet-core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297" +dependencies = [ + "anyhow", + "byteorder", + "libc", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "byteorder", + "libc", + "netlink-packet-core", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-utils" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +dependencies = [ + "anyhow", + "byteorder", + "paste", + "thiserror", +] + +[[package]] +name = "netlink-proto" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" +dependencies = [ + "bytes", + "futures", + "log", + "netlink-packet-core", + "netlink-sys", + "thiserror", + "tokio", +] + +[[package]] +name = "netlink-sys" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" +dependencies = [ + "bytes", + "futures", + "libc", + "log", + "tokio", +] + [[package]] name = "new_debug_unreachable" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + [[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "nom" version = "7.1.3" @@ -3632,9 +4907,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", "libm", @@ -3652,23 +4927,23 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" +checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" +checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -3680,6 +4955,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -3723,7 +5007,7 @@ version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -3740,7 +5024,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -3814,12 +5098,29 @@ version = "3.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -3827,18 +5128,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.9", ] [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec 1.11.1", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "smallvec 1.11.1", "windows-targets", ] @@ -3873,9 +5188,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ "digest 0.10.7", - "hmac", + "hmac 0.12.1", "password-hash", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -3885,7 +5200,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", - "hmac", + "hmac 0.12.1", ] [[package]] @@ -3911,9 +5226,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.3" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a4d085fd991ac8d5b05a147b437791b4260b76326baf0fc60cf7c9c27ecd33" +checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" dependencies = [ "memchr", "thiserror", @@ -3927,7 +5242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.0.0", + "indexmap 2.0.2", ] [[package]] @@ -3970,7 +5285,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -4008,7 +5323,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -4048,32 +5363,84 @@ dependencies = [ "crunchy", ] +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys", +] + +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" dependencies = [ - "portable-atomic 1.4.3", + "portable-atomic 1.5.1", ] [[package]] name = "portable-atomic" -version = "1.4.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" +checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" [[package]] name = "postcard" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d534c6e61df1c7166e636ca612d9820d486fe96ddad37f7abc671517b297488e" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" dependencies = [ "cobs", + "embedded-io", "heapless", "serde", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -4103,14 +5470,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] name = "primitive-types" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", @@ -4127,7 +5494,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +dependencies = [ + "toml_edit 0.20.7", ] [[package]] @@ -4160,30 +5536,64 @@ version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" +[[package]] +name = "proc-macro-warning" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] +[[package]] +name = "prometheus-client" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c99afa9a01501019ac3a14d71d9f94050346f55ca471ce90c799a15c58f61e2" +dependencies = [ + "dtoa", + "itoa", + "parking_lot 0.12.1", + "prometheus-client-derive-encode", +] + +[[package]] +name = "prometheus-client-derive-encode" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "proptest" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" dependencies = [ "bit-set", - "bitflags 1.3.2", - "byteorder", + "bit-vec", + "bitflags 2.4.1", "lazy_static", "num-traits", "rand 0.8.5", "rand_chacha", "rand_xorshift", - "regex-syntax 0.6.29", + "regex-syntax 0.7.5", "rusty-fork", "tempfile", "unarray", @@ -4258,6 +5668,76 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quick-protobuf" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f" +dependencies = [ + "byteorder", +] + +[[package]] +name = "quick-protobuf-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ededb1cd78531627244d51dd0c7139fbe736c7d57af0092a76f0ffb2f56e98" +dependencies = [ + "asynchronous-codec", + "bytes", + "quick-protobuf", + "thiserror", + "unsigned-varint", +] + +[[package]] +name = "quinn" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75" +dependencies = [ + "bytes", + "futures-io", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c78e758510582acc40acb90458401172d41f1016f8c9dde89e49677afb7eec1" +dependencies = [ + "bytes", + "rand 0.8.5", + "ring 0.16.20", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" +dependencies = [ + "bytes", + "libc", + "socket2 0.5.5", + "tracing", + "windows-sys", +] + [[package]] name = "quote" version = "1.0.33" @@ -4360,6 +5840,18 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rcgen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +dependencies = [ + "pem", + "ring 0.16.20", + "time", + "yasna", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -4380,9 +5872,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] @@ -4400,14 +5892,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.6" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.9", - "regex-syntax 0.7.5", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -4421,13 +5913,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax 0.8.2", ] [[package]] @@ -4442,6 +5934,12 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -4453,11 +5951,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.20" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -4481,6 +5979,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls", @@ -4493,6 +5992,16 @@ dependencies = [ "winreg", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "reth-codecs" version = "0.1.0" @@ -4531,23 +6040,23 @@ name = "reth-ecies" version = "0.1.0" source = "git+https://github.com/paradigmxyz/reth.git?rev=aa6f2cb0610fb4fa0926b42cfed7f8ff51e0db8a#aa6f2cb0610fb4fa0926b42cfed7f8ff51e0db8a" dependencies = [ - "aes", + "aes 0.8.3", "block-padding", "byteorder", - "cipher", - "ctr", + "cipher 0.4.4", + "ctr 0.9.2", "digest 0.10.7", "educe", "futures", "generic-array", - "hmac", + "hmac 0.12.1", "pin-project", "rand 0.8.5", "reth-net-common", "reth-primitives", "reth-rlp", "secp256k1", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "thiserror", "tokio", @@ -4614,7 +6123,7 @@ dependencies = [ "derive_more", "indexmap 1.9.3", "libc", - "parking_lot", + "parking_lot 0.12.1", "reth-mdbx-sys", "thiserror", ] @@ -4707,7 +6216,7 @@ source = "git+https://github.com/paradigmxyz/reth.git?rev=aa6f2cb0610fb4fa0926b4 dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -4716,7 +6225,7 @@ version = "0.1.0" source = "git+https://github.com/paradigmxyz/reth.git?rev=aa6f2cb0610fb4fa0926b42cfed7f8ff51e0db8a#aa6f2cb0610fb4fa0926b42cfed7f8ff51e0db8a" dependencies = [ "jsonrpsee-types 0.16.3", - "lru", + "lru 0.9.0", "reth-network-api", "reth-primitives", "reth-rlp", @@ -4753,7 +6262,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "hmac", + "hmac 0.12.1", "subtle", ] @@ -4767,11 +6276,25 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +dependencies = [ + "cc", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -4809,6 +6332,21 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" +[[package]] +name = "rtnetlink" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322c53fd76a18698f1c27381d58091de3a043d356aa5bd0d510608b565f469a0" +dependencies = [ + "futures", + "log", + "netlink-packet-route", + "netlink-proto", + "nix", + "thiserror", + "tokio", +] + [[package]] name = "ruint" version = "1.10.1" @@ -4889,31 +6427,54 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.19", + "semver 1.0.20", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys", ] [[package]] name = "rustix" -version = "0.38.14" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.10", "windows-sys", ] [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" dependencies = [ "log", - "ring", - "rustls-webpki 0.101.6", + "ring 0.17.5", + "rustls-webpki 0.101.7", "sct", ] @@ -4935,7 +6496,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", ] [[package]] @@ -4944,18 +6505,18 @@ version = "0.100.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6a5fc258f1c1276dfe3016516945546e2d5383911efc0fc4f1cdc5df3a4ae3" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] name = "rustls-webpki" -version = "0.101.6" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", + "ring 0.17.5", + "untrusted 0.9.0", ] [[package]] @@ -4976,6 +6537,17 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "rw-stream-sink" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8c9026ff5d2f23da5e45bbc283f156383001bfb09c4e44256d02c1a685fe9a1" +dependencies = [ + "futures", + "pin-project", + "static_assertions", +] + [[package]] name = "ryu" version = "1.0.15" @@ -4988,7 +6560,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" dependencies = [ - "cipher", + "cipher 0.4.4", ] [[package]] @@ -5002,9 +6574,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" +checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" dependencies = [ "cfg-if", "derive_more", @@ -5014,11 +6586,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" +checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -5045,20 +6617,20 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" dependencies = [ - "hmac", + "hmac 0.12.1", "pbkdf2 0.11.0", "salsa20", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.5", + "untrusted 0.9.0", ] [[package]] @@ -5128,9 +6700,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ "serde", ] @@ -5158,9 +6730,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] @@ -5178,13 +6750,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -5200,9 +6772,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -5244,7 +6816,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -5286,9 +6858,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -5307,9 +6879,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -5354,6 +6926,7 @@ version = "0.3.0-alpha" dependencies = [ "clap", "dirs 4.0.0", + "discv5", "ethers 2.0.8", "expanded-pathbuf", "eyre", @@ -5361,6 +6934,7 @@ dependencies = [ "pin-utils", "silius-bundler", "silius-grpc", + "silius-p2p", "silius-primitives", "silius-rpc", "tokio", @@ -5381,7 +6955,7 @@ dependencies = [ "ethers-flashbots", "ethers-flashbots-test", "eyre", - "jsonrpsee 0.20.1", + "jsonrpsee 0.20.3", "serde", "serde_json", "silius-contracts", @@ -5415,16 +6989,20 @@ dependencies = [ "arrayref", "async-trait", "dashmap", + "discv5", "ethers 2.0.8", "expanded-pathbuf", "eyre", - "parking_lot", + "futures", + "libp2p-identity", + "parking_lot 0.12.1", "prost", "prost-build", "protobuf-src", "serde_json", "silius-bundler", "silius-contracts", + "silius-p2p", "silius-primitives", "silius-uopool", "tokio", @@ -5433,6 +7011,31 @@ dependencies = [ "tracing", ] +[[package]] +name = "silius-p2p" +version = "0.1.0" +dependencies = [ + "async-trait", + "delay_map", + "discv5", + "env_logger", + "ethers 2.0.8", + "eyre", + "futures", + "lazy_static", + "libp2p", + "libp2p-mplex", + "silius-primitives", + "snap", + "ssz_rs", + "ssz_rs_derive", + "test-log", + "thiserror", + "tokio", + "tracing", + "tracing-subscriber", +] + [[package]] name = "silius-primitives" version = "0.3.0-alpha" @@ -5483,6 +7086,7 @@ version = "0.3.0-alpha" dependencies = [ "ethers 2.0.8", "eyre", + "futures", "silius-contracts", "silius-primitives", "silius-uopool", @@ -5499,9 +7103,10 @@ dependencies = [ "enumset", "ethers 2.0.8", "eyre", + "futures", "futures-util", "page_size 0.5.0", - "parking_lot", + "parking_lot 0.12.1", "prost", "reth-db", "reth-libmdbx", @@ -5580,11 +7185,28 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" +[[package]] +name = "snow" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9d1425eb528a21de2755c75af4c9b5d57f50a0d4c3b7f1828a4cd03f8ba155" +dependencies = [ + "aes-gcm", + "blake2", + "chacha20poly1305", + "curve25519-dalek", + "rand_core 0.6.4", + "ring 0.16.20", + "rustc_version 0.4.0", + "sha2 0.10.8", + "subtle", +] + [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -5592,9 +7214,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys", @@ -5657,9 +7279,8 @@ dependencies = [ [[package]] name = "ssz_rs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f923762d556417668b192ac2fdc9827ea21e6df011d8a0a7e68f3d5da095a675" +version = "0.9.0" +source = "git+https://github.com/ralexstokes/ssz-rs.git?rev=8640128ec83071094d24fb4511147d6b9dd029bb#8640128ec83071094d24fb4511147d6b9dd029bb" dependencies = [ "bitvec", "hex", @@ -5667,14 +7288,12 @@ dependencies = [ "serde", "sha2 0.9.9", "ssz_rs_derive", - "thiserror", ] [[package]] name = "ssz_rs_derive" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c679ebd9c1ceeb0f9e5b839952b4a71bfe35a791b431ef7b3ee0b71b7588b565" +version = "0.9.0" +source = "git+https://github.com/ralexstokes/ssz-rs.git?rev=8640128ec83071094d24fb4511147d6b9dd029bb#8640128ec83071094d24fb4511147d6b9dd029bb" dependencies = [ "proc-macro2", "quote", @@ -5701,7 +7320,7 @@ checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ "new_debug_unreachable", "once_cell", - "parking_lot", + "parking_lot 0.12.1", "phf_shared 0.10.0", "precomputed-hash", ] @@ -5727,7 +7346,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" dependencies = [ - "strum_macros 0.25.2", + "strum_macros 0.25.3", ] [[package]] @@ -5745,22 +7364,22 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "sucds" @@ -5782,10 +7401,10 @@ dependencies = [ "hex", "once_cell", "reqwest", - "semver 1.0.19", + "semver 1.0.20", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "url", "zip", @@ -5799,7 +7418,7 @@ checksum = "2271abd7d01895a3e5bfa4b578e32f09155002ce1ec239532e297f82aafad06b" dependencies = [ "build_const", "hex", - "semver 1.0.19", + "semver 1.0.20", "serde_json", "svm-rs", ] @@ -5817,9 +7436,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.37" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -5834,7 +7453,7 @@ checksum = "c93e348d6f105577df7bb5e8ad835d8f0f8ecbd709da24e711bb107a048d8000" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -5846,7 +7465,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -5855,6 +7474,39 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tap" version = "1.0.1" @@ -5873,14 +7525,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", - "fastrand", - "redox_syscall 0.3.5", - "rustix", + "fastrand 2.0.1", + "redox_syscall 0.4.1", + "rustix 0.38.21", "windows-sys", ] @@ -5895,24 +7547,44 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "test-log" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f66edd6b6cd810743c0c71e1d085e92b01ce6a72782032e3f794c8284fe4bcdd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "thiserror" -version = "1.0.48" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -5927,12 +7599,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", "itoa", + "powerfmt", "serde", "time-core", "time-macros", @@ -5979,19 +7652,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ "backtrace", "bytes", "libc", "mio", "num_cpus", - "parking_lot", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.4", + "socket2 0.5.5", "tokio-macros", "windows-sys", ] @@ -6014,7 +7687,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -6081,15 +7754,16 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", "futures-io", "futures-sink", "pin-project-lite", + "slab", "tokio", "tracing", ] @@ -6103,14 +7777,14 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] @@ -6121,13 +7795,24 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.2", "serde", "serde_spanned", "toml_datetime", "winnow", ] +[[package]] +name = "toml_edit" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +dependencies = [ + "indexmap 2.0.2", + "toml_datetime", + "winnow", +] + [[package]] name = "tonic" version = "0.8.3" @@ -6199,7 +7884,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "bytes", "futures-core", "futures-util", @@ -6225,11 +7910,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -6238,20 +7922,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -6269,12 +7953,12 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] @@ -6306,6 +7990,78 @@ dependencies = [ "rlp", ] +[[package]] +name = "trust-dns-proto" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner 0.5.1", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.2.3", + "ipnet", + "lazy_static", + "rand 0.8.5", + "smallvec 1.11.1", + "socket2 0.4.10", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "trust-dns-proto" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner 0.6.0", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand 0.8.5", + "smallvec 1.11.1", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" +dependencies = [ + "cfg-if", + "futures-util", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot 0.12.1", + "rand 0.8.5", + "resolv-conf", + "smallvec 1.11.1", + "thiserror", + "tokio", + "tracing", + "trust-dns-proto 0.23.2", +] + [[package]] name = "try-lock" version = "0.2.4" @@ -6417,12 +8173,38 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "unsigned-varint" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" +dependencies = [ + "asynchronous-codec", + "bytes", +] + [[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.4.1" @@ -6430,7 +8212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", - "idna", + "idna 0.4.0", "percent-encoding", ] @@ -6474,6 +8256,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + [[package]] name = "wait-timeout" version = "0.2.0" @@ -6483,6 +8271,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" + [[package]] name = "walkdir" version = "2.4.0" @@ -6529,7 +8323,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", "wasm-bindgen-shared", ] @@ -6563,7 +8357,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6586,12 +8380,12 @@ dependencies = [ [[package]] name = "webpki" -version = "0.22.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e74f82d49d545ad128049b7e88f6576df2da6b02e9ce565c6f533be576957e" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring", - "untrusted", + "ring 0.17.5", + "untrusted 0.9.0", ] [[package]] @@ -6618,9 +8412,15 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.21", ] +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + [[package]] name = "winapi" version = "0.3.9" @@ -6654,9 +8454,19 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.48.0" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ "windows-targets", ] @@ -6729,9 +8539,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.15" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" dependencies = [ "memchr", ] @@ -6774,12 +8584,100 @@ dependencies = [ "tap", ] +[[package]] +name = "x25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" +dependencies = [ + "curve25519-dalek", + "rand_core 0.6.4", + "serde", + "zeroize", +] + +[[package]] +name = "x509-parser" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "xml-rs" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" + +[[package]] +name = "xmltree" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" +dependencies = [ + "xml-rs", +] + +[[package]] +name = "yamux" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0329ef377816896f014435162bb3711ea7a07729c23d0960e6f8048b21b8fe91" +dependencies = [ + "futures", + "log", + "nohash-hasher", + "parking_lot 0.12.1", + "pin-project", + "rand 0.8.5", + "static_assertions", +] + [[package]] name = "yansi" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + +[[package]] +name = "zerocopy" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd66a62464e3ffd4e37bd09950c2b9dd6c4f8767380fabba0d523f9a775bc85a" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "255c4596d41e6916ced49cfafea18727b24d67878fa180ddfd69b9df34fd1726" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "zeroize" version = "1.6.0" @@ -6797,7 +8695,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -6806,14 +8704,14 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ - "aes", + "aes 0.8.3", "byteorder", "bzip2", "constant_time_eq", "crc32fast", "crossbeam-utils", "flate2", - "hmac", + "hmac 0.12.1", "pbkdf2 0.11.0", "sha1", "time", @@ -6841,11 +8739,10 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" +version = "2.0.9+zstd.1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" dependencies = [ "cc", - "libc", "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index 4a5123ba..d7023070 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "crates/bundler", "crates/contracts", "crates/grpc", + "crates/p2p", "crates/primitives", "crates/rpc", "crates/uopool", @@ -27,14 +28,18 @@ rust-version = "1.73.0" [workspace.dependencies] async-stream = "0.3.5" async-trait = "0.1" +discv5 = { version = "0.3.0", features = ["libp2p"] } ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "fa3017715a298728d9fb341933818a5d0d84c2dc", features = [ "ws", ] } expanded-pathbuf = "0.1" eyre = "0.6.8" futures-util = "0.3.28" +lazy_static = "1.4.0" parking_lot = "0.12" serde_json = "1" +ssz_rs = { git = "https://github.com/ralexstokes/ssz-rs.git", rev = "8640128ec83071094d24fb4511147d6b9dd029bb" } +ssz_rs_derive = { git = "https://github.com/ralexstokes/ssz-rs.git", rev = "8640128ec83071094d24fb4511147d6b9dd029bb" } tokio = { version = "1.18", features = ["full"] } tracing = "0.1" diff --git a/P2P.md b/P2P.md new file mode 100644 index 00000000..4cbfac9f --- /dev/null +++ b/P2P.md @@ -0,0 +1,20 @@ +# Prerequirements for building + +1. Install rust +2. make fetch-thirdparty +3. make setup-thirdparty + +# How to run silius with p2p enabled + +## Run silius with bootnodes + +``` +cargo run -- bundler --eth-client-address http://localhost:8545 --mnemonic-file ./bundler-spec-tests/keys/0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --beneficiary 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --entry-points 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 --http --http.port 4000 --eth-client-proxy-address http://localhost:8545 --p2p-broadcast-address 127.0.0.1 --bootnodes "enr:-Iu4QBh2tesC8BokO61v1w43MnbfHF5H95ZJNHVEQaRq_MjFFuxmeVQnoEXxUDk5qKJCHM944gC72Xg4dYwRkGt9zA4BgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQKRdyIA8OvArCcZbt3hoJHu4nVe6CblqjO0CnrbGACi-IN0Y3CCEPGDdWRwghDx" --enable-p2p --tcp4-port 4338 --udp4-port 4338 --datadir ./.local/data +``` + + +## Run silius as bootnodes + +``` +cargo run -- bundler --eth-client-address http://localhost:8545 --mnemonic-file ./bundler-spec-tests/keys/0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --beneficiary 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --entry-points 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 --http --http.port 4000 --eth-client-proxy-address http://localhost:8545 --p2p-broadcast-address 127.0.0.1 --enable-p2p +``` \ No newline at end of file diff --git a/bin/silius/Cargo.toml b/bin/silius/Cargo.toml index fac357c0..184816be 100644 --- a/bin/silius/Cargo.toml +++ b/bin/silius/Cargo.toml @@ -13,6 +13,7 @@ AA (ERC-4337) bundler - Silius [dependencies] clap = { version = "4", features = ["derive"] } dirs = "4.0" +discv5 = { workspace = true } ethers = { workspace = true } expanded-pathbuf = { workspace = true } eyre = { workspace = true } @@ -20,6 +21,7 @@ log = "0.4.19" pin-utils = "0.1" silius-bundler = { path = "../../crates/bundler" } silius-grpc = { path = "../../crates/grpc" } +silius-p2p = { path = "../../crates/p2p" } silius-primitives = { path = "../../crates/primitives" } silius-rpc = { path = "../../crates/rpc" } tokio = { workspace = true } diff --git a/bin/silius/src/bundler.rs b/bin/silius/src/bundler.rs index 93667dab..fede2786 100644 --- a/bin/silius/src/bundler.rs +++ b/bin/silius/src/bundler.rs @@ -165,6 +165,9 @@ where args.min_priority_fee_per_gas, args.whitelist, args.uopool_mode, + args.p2p_opts.enable_p2p, + args.p2p_opts.to_config(), + args.p2p_opts.bootnodes, ) .await?; diff --git a/bin/silius/src/cli/args.rs b/bin/silius/src/cli/args.rs index 8bccd252..c31fb238 100644 --- a/bin/silius/src/cli/args.rs +++ b/bin/silius/src/cli/args.rs @@ -1,7 +1,11 @@ -use crate::utils::{parse_address, parse_send_bundle_mode, parse_u256, parse_uopool_mode}; +use crate::utils::{ + parse_address, parse_enr, parse_send_bundle_mode, parse_u256, parse_uopool_mode, +}; use clap::Parser; +use discv5::Enr; use ethers::types::{Address, U256}; use expanded_pathbuf::ExpandedPathBuf; +use silius_p2p::config::{Config, ListenAddr}; use silius_primitives::{ bundler::SendBundleMode, chain::SUPPORTED_CHAINS, @@ -88,6 +92,9 @@ pub struct UoPoolArgs { /// User operation mempool mode #[clap(long, default_value = "standard", value_parser=parse_uopool_mode)] pub uopool_mode: UoPoolMode, + + #[clap(flatten)] + pub p2p_opts: P2POpts, } /// Common CLI args for bundler and uopool @@ -211,8 +218,53 @@ pub struct CreateWalletArgs { pub flashbots_key: bool, } +#[derive(Clone, Debug, Parser, PartialEq)] +pub struct P2POpts { + /// enable p2p + #[clap(long)] + pub enable_p2p: bool, + + /// Sets the p2p listen address. + #[clap(long, default_value = "0.0.0.0")] + pub p2p_listen_address: Ipv4Addr, + + /// The ipv4 address to broadcast to peers about which address we are listening on. + #[clap(long)] + pub p2p_broadcast_address: Option, + + /// The udp4 port to broadcast to peers in order to reach back for discovery. + #[clap(long, default_value = "4337")] + pub udp4_port: u16, + + #[clap(long, default_value = "4337")] + pub tcp4_port: u16, + + #[clap(long, value_delimiter = ',', value_parser=parse_enr)] + pub bootnodes: Vec, +} + +impl P2POpts { + pub fn to_config(&self) -> Config { + // TODO: support ipv6 + Config { + listen_addr: silius_p2p::config::ListenAddress::Ipv4(ListenAddr { + addr: self.p2p_listen_address, + udp_port: self.udp4_port, + tcp_port: self.tcp4_port, + }), + ipv4_addr: self.p2p_broadcast_address, + ipv6_addr: None, + enr_udp4_port: Some(self.udp4_port), + enr_tcp4_port: Some(self.tcp4_port), + enr_udp6_port: None, + enr_tcp6_port: None, + } + } +} #[cfg(test)] mod tests { + use discv5::enr::{CombinedKey, EnrBuilder}; + use super::*; use std::{ net::{IpAddr, Ipv4Addr}, @@ -512,4 +564,41 @@ mod tests { false ); } + + #[test] + fn p2p_opts() { + let key = CombinedKey::secp256k1_from_bytes([1; 32].as_mut()).unwrap(); + let enr = EnrBuilder::new("v4") + .ip4(Ipv4Addr::new(8, 8, 8, 8)) + .tcp4(4337) + .udp4(4337) + .build(&key) + .unwrap(); + let binding = enr.clone().to_base64(); + let args = vec![ + "p2popts", + "--enable-p2p", + "--p2p-listen-address", + "0.0.0.0", + "--p2p-broadcast-address", + "127.0.0.1", + "--tcp4-port", + "4337", + "--udp4-port", + "4337", + "--bootnodes", + &binding, + ]; + assert_eq!( + P2POpts { + enable_p2p: true, + p2p_listen_address: Ipv4Addr::new(0, 0, 0, 0), + p2p_broadcast_address: Some(Ipv4Addr::new(127, 0, 0, 1)), + tcp4_port: 4337, + udp4_port: 4337, + bootnodes: vec![enr] + }, + P2POpts::try_parse_from(args).unwrap() + ) + } } diff --git a/bin/silius/src/cli/commands.rs b/bin/silius/src/cli/commands.rs index 95d302b0..369243cc 100644 --- a/bin/silius/src/cli/commands.rs +++ b/bin/silius/src/cli/commands.rs @@ -31,8 +31,7 @@ impl BundlerCommand { pub async fn execute(self) -> eyre::Result<()> { if self.common.eth_client_address.clone().starts_with("http") { let eth_client = Arc::new(create_http_provider(&self.common.eth_client_address).await?); - let block_streams = - create_http_block_streams(eth_client.clone(), self.common.entry_points.len()).await; + let block_streams = create_http_block_streams(eth_client.clone(), 1).await; launch_bundler( self.bundler, self.uopool, @@ -44,8 +43,7 @@ impl BundlerCommand { .await?; } else { let eth_client = Arc::new(create_ws_provider(&self.common.eth_client_address).await?); - let block_streams = - create_ws_block_streams(eth_client.clone(), self.common.entry_points.len()).await; + let block_streams = create_ws_block_streams(eth_client.clone(), 1).await; launch_bundler( self.bundler, self.uopool, @@ -123,8 +121,7 @@ impl UoPoolCommand { pub async fn execute(self) -> eyre::Result<()> { if self.common.eth_client_address.clone().starts_with("http") { let eth_client = Arc::new(create_http_provider(&self.common.eth_client_address).await?); - let block_streams = - create_http_block_streams(eth_client.clone(), self.common.entry_points.len()).await; + let block_streams = create_http_block_streams(eth_client.clone(), 1).await; launch_uopool( self.uopool, eth_client, @@ -135,8 +132,7 @@ impl UoPoolCommand { .await?; } else { let eth_client = Arc::new(create_ws_provider(&self.common.eth_client_address).await?); - let block_streams = - create_ws_block_streams(eth_client.clone(), self.common.entry_points.len()).await; + let block_streams = create_ws_block_streams(eth_client.clone(), 1).await; launch_uopool( self.uopool, eth_client, diff --git a/bin/silius/src/utils.rs b/bin/silius/src/utils.rs index ff34145b..e41f3c29 100644 --- a/bin/silius/src/utils.rs +++ b/bin/silius/src/utils.rs @@ -1,4 +1,5 @@ use dirs::home_dir; +use discv5::Enr; use ethers::types::{Address, U256}; use expanded_pathbuf::ExpandedPathBuf; use pin_utils::pin_mut; @@ -38,6 +39,11 @@ pub fn parse_uopool_mode(s: &str) -> Result { UoPoolMode::from_str(s).map_err(|_| format!("String {s} is not a valid UoPoolMode")) } +/// Parse ENR record +pub fn parse_enr(enr: &str) -> Result { + Enr::from_str(enr).map_err(|_| format!("Enr {enr} is not a valid enr.")) +} + /// Runs the future to completion or until: /// - `ctrl-c` is received. /// - `SIGTERM` is received (unix only). diff --git a/crates/contracts/Cargo.toml b/crates/contracts/Cargo.toml index cb1b4181..21751253 100644 --- a/crates/contracts/Cargo.toml +++ b/crates/contracts/Cargo.toml @@ -11,9 +11,10 @@ AA (ERC-4337) bundler smart contract interfaces """ [dependencies] + ethers = { workspace = true } eyre = { workspace = true } -lazy_static = "1.4.0" +lazy_static = { workspace = true } regex = "1.9.6" serde = "1" serde_json = "1" diff --git a/crates/contracts/src/entry_point.rs b/crates/contracts/src/entry_point.rs index 921f4b81..0e44728a 100644 --- a/crates/contracts/src/entry_point.rs +++ b/crates/contracts/src/entry_point.rs @@ -451,4 +451,12 @@ mod tests { ); Ok(()) } + + #[test] + fn deserialize_failedop() -> eyre::Result<()> { + let err_msg = Bytes::from_str("0x220266b600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001e41413430206f76657220766572696669636174696f6e4761734c696d69740000")?; + let res = EntryPointAPIErrors::decode(err_msg)?; + println!("res: {:?}", res); + Ok(()) + } } diff --git a/crates/contracts/src/tracer.rs b/crates/contracts/src/tracer.rs index fd441686..574e1185 100644 --- a/crates/contracts/src/tracer.rs +++ b/crates/contracts/src/tracer.rs @@ -19,8 +19,8 @@ impl TryFrom for JsTracerFrame { fn try_from(val: GethTrace) -> Result { match val { GethTrace::Known(val) => Err(format_err!("Invalid geth trace: {val:?}")), - GethTrace::Unknown(val) => serde_json::from_value(val) - .map_err(|error| format_err!("Failed to parse geth trace: {error}")), + GethTrace::Unknown(val) => serde_json::from_value(val.clone()) + .map_err(|error| format_err!("Failed to parse geth trace: {error}, {val:#}")), } } } diff --git a/crates/grpc/Cargo.toml b/crates/grpc/Cargo.toml index 73ae2cd0..d1f33d39 100644 --- a/crates/grpc/Cargo.toml +++ b/crates/grpc/Cargo.toml @@ -14,14 +14,18 @@ AA (ERC-4337) bundler gRPC interfaces arrayref = "0.3" async-trait = { workspace = true } dashmap = "5.4.0" +discv5 = { workspace = true } ethers = { workspace = true } expanded-pathbuf = { workspace = true } eyre = { workspace = true } +futures = "0.3.28" +libp2p-identity = "0.2.3" parking_lot = { workspace = true } prost = "0.11" serde_json = { workspace = true } silius-bundler = { path = "../bundler" } silius-contracts = { path = "../contracts" } +silius-p2p = { path = "../p2p" } silius-primitives = { path = "../primitives" } silius-uopool = { path = "../uopool" } tokio = { workspace = true } diff --git a/crates/grpc/src/network.rs b/crates/grpc/src/network.rs new file mode 100644 index 00000000..0ce9261c --- /dev/null +++ b/crates/grpc/src/network.rs @@ -0,0 +1,31 @@ +use ethers::providers::Middleware; +use silius_p2p::network::Network; +use silius_primitives::reputation::ReputationEntry; +use silius_uopool::{Mempool, Reputation, VecCh, VecUo}; + +use crate::builder::UoPoolBuilder; + +/// The Integrator is for the integrations between p2p network and the uopool +pub struct NetworkIntegrator +where + M: Middleware + Clone + 'static, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, +{ + network: Network, + uopool_builder: UoPoolBuilder, +} + +impl NetworkIntegrator +where + M: Middleware + Clone + 'static, + P: Mempool + Send + Sync, + R: Reputation, Error = E> + Send + Sync, +{ + pub fn new(network: Network, uopool_builder: UoPoolBuilder) -> Self { + Self { + network, + uopool_builder, + } + } +} diff --git a/crates/grpc/src/uopool.rs b/crates/grpc/src/uopool.rs index cf4290d6..36e80bff 100644 --- a/crates/grpc/src/uopool.rs +++ b/crates/grpc/src/uopool.rs @@ -5,14 +5,21 @@ use crate::{ }; use async_trait::async_trait; use dashmap::DashMap; +use discv5::Enr; use ethers::{ providers::Middleware, types::{Address, U256}, }; use expanded_pathbuf::ExpandedPathBuf; use eyre::Result; +use futures::channel::mpsc::unbounded; +use futures::StreamExt; +use libp2p_identity::Keypair; +use silius_p2p::config::Config; +use silius_p2p::network::{EntrypointChannels, Network}; use silius_primitives::provider::BlockStream; use silius_primitives::reputation::ReputationEntry; +use silius_primitives::UserOperation; use silius_primitives::{uopool::AddError, Chain, UoPoolMode}; use silius_uopool::{ init_env, DBError, DatabaseMempool, DatabaseReputation, Mempool, VecCh, VecUo, WriteMap, @@ -24,6 +31,10 @@ use silius_uopool::{ use std::fmt::{Debug, Display}; use std::{net::SocketAddr, sync::Arc, time::Duration}; use tonic::{Code, Request, Response, Status}; +use tracing::{error, info}; + +pub const DB_FOLDER_NAME: &str = "db"; +pub const DISCOVERY_SECRET_FILE_NAME: &str = "discovery-secret"; type StandardUserPool = UserOperationPool, P, R, E>; @@ -357,6 +368,9 @@ pub async fn uopool_service_run( min_priority_fee_per_gas: U256, whitelist: Vec
, upool_mode: UoPoolMode, + p2p_enabled: bool, + config: Config, + bootnodes: Vec, ) -> Result<()> where M: Middleware + Clone + 'static, @@ -369,31 +383,116 @@ where UoPoolBuilder, DatabaseReputation, DBError>, >::new()); - let env = Arc::new(init_env::(datadir.join("db")).expect("Init mdbx failed")); + let env = + Arc::new(init_env::(datadir.join(DB_FOLDER_NAME)).expect("Init mdbx failed")); env.create_tables() .expect("Create mdbx database tables failed"); - for (ep, block_stream) in eps.into_iter().zip(block_streams.into_iter()) { - let id = mempool_id(&ep, &U256::from(chain.id())); - let builder = UoPoolBuilder::new( - upool_mode == UoPoolMode::Unsafe, - eth_client.clone(), - ep, - chain, - max_verification_gas, - min_stake, - min_priority_fee_per_gas, - whitelist.clone(), - DatabaseMempool::new(env.clone()), - DatabaseReputation::new(env.clone()), - ); - - builder.register_block_updates(block_stream); - builder.register_reputation_updates(); - - m_map.insert(id, builder); - } + let mut entrypoint_channels: EntrypointChannels = Vec::new(); + + if p2p_enabled { + for (ep, block_stream) in eps.into_iter().zip(block_streams.into_iter()) { + let id = mempool_id(&ep, &U256::from(chain.id())); + let (waiting_to_pub_sd, waiting_to_pub_rv) = unbounded::<(UserOperation, U256)>(); + let uo_builder = UoPoolBuilder::new( + upool_mode == UoPoolMode::Unsafe, + eth_client.clone(), + ep, + chain, + max_verification_gas, + min_stake, + min_priority_fee_per_gas, + whitelist.clone(), + DatabaseMempool::new(env.clone()), + DatabaseReputation::new(env.clone()), + Some(waiting_to_pub_sd), + ); + uo_builder.register_block_updates(block_stream); + uo_builder.register_reputation_updates(); + + let (p2p_userop_sd, mut p2p_userop_rv) = unbounded::(); + let mut uo_pool = uo_builder.uopool(); + // spawn a task which would consume the userop received from p2p network + tokio::spawn(async move { + while let Some(user_op) = p2p_userop_rv.next().await { + let res = uo_pool.validate_user_operation(&user_op).await; + match uo_pool.add_user_operation(user_op, res).await { + Ok(_) => {} + Err(e) => error!("Failed to add user operation: {:?} from p2p", e), + } + } + }); + m_map.insert(id, uo_builder); + entrypoint_channels.push((chain, ep, waiting_to_pub_rv, p2p_userop_sd)) + } + let discovery_secret_file = datadir.join(DISCOVERY_SECRET_FILE_NAME); + let discovery_secret = if discovery_secret_file.exists() { + let content = + std::fs::read(discovery_secret_file).expect("discovery secret file currupted"); + Keypair::from_protobuf_encoding(&content).expect("discovery secret file currupted") + } else { + let keypair = Keypair::generate_secp256k1(); + std::fs::write( + discovery_secret_file, + keypair + .to_protobuf_encoding() + .expect("discovery secret encode failed"), + ) + .expect("write discoveray secret file failed"); + keypair + }; + let listen_addrs = config.listen_addr.to_multi_addr(); + let mut p2p_network = Network::new( + discovery_secret, + config, + entrypoint_channels, + Duration::from_secs(10), + 30, + ) + .expect("p2p network init failed"); + info!("Enr: {}", p2p_network.local_enr().to_base64()); + for listen_addr in listen_addrs.into_iter() { + info!("P2P node listened on {}", listen_addr); + p2p_network + .listen_on(listen_addr) + .expect("Listen on p2p network failed"); + } + + if bootnodes.is_empty() { + info!("Start p2p mode without bootnodes"); + } + for enr in bootnodes { + info!("Trying to dial p2p node {enr:}"); + p2p_network.dial(enr).expect("Dial bootnode failed"); + } + + tokio::spawn(async move { + loop { + p2p_network.next_event().await; + } + }); + } else { + for (ep, block_stream) in eps.into_iter().zip(block_streams.into_iter()) { + let id = mempool_id(&ep, &U256::from(chain.id())); + let uo_builder = UoPoolBuilder::new( + upool_mode == UoPoolMode::Unsafe, + eth_client.clone(), + ep, + chain, + max_verification_gas, + min_stake, + min_priority_fee_per_gas, + whitelist.clone(), + DatabaseMempool::new(env.clone()), + DatabaseReputation::new(env.clone()), + None, + ); + uo_builder.register_block_updates(block_stream); + uo_builder.register_reputation_updates(); + m_map.insert(id, uo_builder); + } + }; let svc = uo_pool_server::UoPoolServer::new(UoPoolService::< M, DatabaseMempool, diff --git a/crates/p2p/Cargo.toml b/crates/p2p/Cargo.toml new file mode 100644 index 00000000..3536b95a --- /dev/null +++ b/crates/p2p/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "silius-p2p" +version = "0.1.0" +authors = ["Vid Kersic "] +edition = "2021" +license = "MIT OR Apache-2.0" +repository = "https://github.com/Vid201/aa-bundler" +readme = "README.md" +description = """ +AA (ERC-4337) Bundler p2p components +""" +rust-version = "1.69.0" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = "0.1" +delay_map = "0.3.0" +discv5 = { workspace = true } +ethers = { workspace = true } +eyre = "0.6.8" +futures = "0.3.28" +lazy_static = { workspace = true } +libp2p-mplex = { version = "0.40.0" } +silius-primitives = { path = "../primitives" } +snap = "1" +ssz_rs = { workspace = true } +ssz_rs_derive = { workspace = true } +thiserror = "1" +tokio = { workspace = true } +tracing = { workspace = true } + +[dependencies.libp2p] +version = "0.52.3" +features = ["identify", "yamux", "noise", "gossipsub", "dns", "tcp", "tokio", "secp256k1", "macros", "request-response"] + +[dev-dependencies] +env_logger = "*" +ethers = { workspace = true } +test-log = "0.2.12" +tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } diff --git a/crates/p2p/src/behaviour.rs b/crates/p2p/src/behaviour.rs new file mode 100644 index 00000000..ba2b0d52 --- /dev/null +++ b/crates/p2p/src/behaviour.rs @@ -0,0 +1,74 @@ +use std::time::Duration; + +use crate::config::Config; +use crate::discovery::{self, Discovery}; +use crate::enr::build_enr; +use crate::gossipsub::{create_gossisub, Gossipsub}; +use crate::peer_manager::{PeerManager, PeerManagerEvent}; +use crate::request_response; +use discv5::enr::CombinedKey; +use libp2p::gossipsub; +use libp2p::swarm::NetworkBehaviour; + +#[derive(NetworkBehaviour)] +#[behaviour(to_swarm = "Event", event_process = false)] +pub struct Behaviour { + pub gossipsub: Gossipsub, + pub reqrep: request_response::Behaviour, + pub discv5: Discovery, + pub peer_manager: PeerManager, +} + +impl Behaviour { + pub fn new( + key: CombinedKey, + config: Config, + p2p_mempool_id: Vec, + ping_interval: Duration, + target_peers: usize, + ) -> eyre::Result { + let enr = build_enr(&key, &config)?; + let gossipsub = create_gossisub(p2p_mempool_id).map_err(|e| eyre::anyhow!(e))?; + let reqrep = request_response::Behaviour::new(Default::default()); + let discovery = Discovery::new(enr, key, config)?; + let peer_manager = PeerManager::new(ping_interval, target_peers); + Ok(Self { + gossipsub, + reqrep, + discv5: discovery, + peer_manager, + }) + } +} + +impl From for Event { + fn from(value: gossipsub::Event) -> Self { + Event::GossipSub(Box::new(value)) + } +} + +impl From for Event { + fn from(value: request_response::Event) -> Self { + Event::Reqrep(value) + } +} + +impl From for Event { + fn from(value: discovery::DiscoverPeers) -> Self { + Event::Discovery(value) + } +} + +impl From for Event { + fn from(value: PeerManagerEvent) -> Self { + Event::PeerManager(value) + } +} + +#[derive(Debug)] +pub enum Event { + GossipSub(Box), + Reqrep(request_response::Event), + Discovery(discovery::DiscoverPeers), + PeerManager(PeerManagerEvent), +} diff --git a/crates/p2p/src/config.rs b/crates/p2p/src/config.rs new file mode 100644 index 00000000..1e6b8011 --- /dev/null +++ b/crates/p2p/src/config.rs @@ -0,0 +1,105 @@ +use std::net::{Ipv4Addr, Ipv6Addr}; + +use discv5::ListenConfig; +use libp2p::{multiaddr::Protocol, Multiaddr}; + +const DEFAULT_UDP_PORT: u16 = 9000; +const DEFAULT_TCP_PORT: u16 = 9000; +#[derive(Clone, Debug)] +pub struct ListenAddr { + pub addr: Ip, + pub udp_port: u16, + pub tcp_port: u16, +} + +pub enum ListenAddress { + Ipv4(ListenAddr), + Ipv6(ListenAddr), + Dual(ListenAddr, ListenAddr), +} + +impl ListenAddress { + pub fn to_multi_addr(&self) -> Vec { + match self { + ListenAddress::Ipv4(v) => vec![Multiaddr::from(v.addr).with(Protocol::Tcp(v.tcp_port))], + ListenAddress::Ipv6(v) => vec![Multiaddr::from(v.addr).with(Protocol::Tcp(v.tcp_port))], + ListenAddress::Dual(ipv4, ipv6) => { + vec![ + Multiaddr::from(ipv4.addr).with(Protocol::Tcp(ipv4.tcp_port)), + Multiaddr::from(ipv6.addr).with(Protocol::Tcp(ipv6.tcp_port)), + ] + } + } + } +} + +impl Default for ListenAddress { + fn default() -> Self { + Self::Ipv4(ListenAddr { + addr: Ipv4Addr::UNSPECIFIED, + udp_port: DEFAULT_UDP_PORT, + tcp_port: DEFAULT_TCP_PORT, + }) + } +} + +pub struct Config { + pub listen_addr: ListenAddress, + + /// The ipv4 address to broadcast to peers about which address we are listening on. + pub ipv4_addr: Option, + + /// The ipv6 address to broadcast to peers about which address we are listening on. + pub ipv6_addr: Option, + + /// The udp4 port to broadcast to peers in order to reach back for discovery. + pub enr_udp4_port: Option, + + /// The tcp4 port to broadcast to peers in order to reach back for libp2p services. + pub enr_tcp4_port: Option, + + /// The udp6 port to broadcast to peers in order to reach back for discovery. + pub enr_udp6_port: Option, + + /// The tcp6 port to broadcast to peers in order to reach back for libp2p services. + pub enr_tcp6_port: Option, +} + +impl Default for Config { + fn default() -> Self { + Self { + listen_addr: ListenAddress::Ipv4(ListenAddr { + addr: Ipv4Addr::UNSPECIFIED, + udp_port: DEFAULT_UDP_PORT, + tcp_port: DEFAULT_TCP_PORT, + }), + ipv4_addr: Some(Ipv4Addr::UNSPECIFIED), + ipv6_addr: None, + enr_udp4_port: Some(DEFAULT_UDP_PORT), + enr_tcp4_port: None, + enr_udp6_port: None, + enr_tcp6_port: None, + } + } +} + +impl Config { + pub fn to_listen_config(&self) -> ListenConfig { + match &self.listen_addr { + ListenAddress::Ipv4(v) => ListenConfig::Ipv4 { + ip: v.addr, + port: v.udp_port, + }, + ListenAddress::Ipv6(v) => ListenConfig::Ipv6 { + ip: v.addr, + port: v.udp_port, + }, + ListenAddress::Dual(ipv4, ipv6) => ListenConfig::DualStack { + ipv4: ipv4.addr, + ipv4_port: ipv4.udp_port, + ipv6: ipv6.addr, + ipv6_port: ipv6.udp_port, + }, + } + } +} diff --git a/crates/p2p/src/discovery.rs b/crates/p2p/src/discovery.rs new file mode 100644 index 00000000..13f3635d --- /dev/null +++ b/crates/p2p/src/discovery.rs @@ -0,0 +1,180 @@ +use std::{collections::HashSet, pin::Pin, task::Poll}; + +use discv5::{ + enr::{CombinedKey, NodeId}, + Discv5, Discv5ConfigBuilder, Discv5Event, Enr, +}; +use futures::{stream::FuturesUnordered, Future, FutureExt, StreamExt}; +use libp2p::swarm::{dummy::ConnectionHandler, NetworkBehaviour}; +use tokio::sync::mpsc; +use tracing::{debug, warn}; + +use crate::config::Config; + +type QueryResult = Result, discv5::QueryError>; + +pub struct Discovery { + pub discovery: Discv5, + + /// Active discovery queries. + active_queries: FuturesUnordered + Send>>>, + + cached_enrs: HashSet, + + event_stream: EventStream, +} + +pub enum EventStream { + /// Awaiting an event stream to be generated. This is required due to the poll nature of + /// `Discovery` + Awaiting( + Pin< + Box< + dyn Future, discv5::Discv5Error>> + + Send, + >, + >, + ), + /// The future has completed. + Present(mpsc::Receiver), + // The future has failed or discv5 has been disabled. There are no events from discv5. + InActive, +} + +impl Discovery { + pub fn new(enr: Enr, key: CombinedKey, config: Config) -> eyre::Result { + let config = Discv5ConfigBuilder::new(config.to_listen_config()).build(); + let discovery: Discv5<_> = Discv5::new(enr, key, config).map_err(|e| eyre::anyhow!(e))?; + + let event_stream_fut = discovery.event_stream().boxed(); + Ok(Self { + discovery, + active_queries: Default::default(), + cached_enrs: HashSet::new(), + event_stream: EventStream::Awaiting(event_stream_fut), + }) + } + + /// Return the nodes local ENR. + pub fn local_enr(&self) -> Enr { + self.discovery.local_enr() + } + + pub fn discover_peers(&mut self, target_peers: usize) { + debug!("Starting a peer discovery request target_peers {target_peers:}"); + // Generate a random target node id. + let random_node = NodeId::random(); + let predicate: Box bool + Send> = + Box::new(move |enr: &Enr| enr.tcp4().is_some() || enr.tcp6().is_some()); + + // Build the future + let query_future = self + .discovery + .find_node_predicate(random_node, predicate, target_peers); + + self.active_queries.push(Box::pin(query_future)); + } +} + +#[derive(Debug)] +pub struct DiscoverPeers { + pub peers: Vec, +} + +impl NetworkBehaviour for Discovery { + type ConnectionHandler = ConnectionHandler; + type ToSwarm = DiscoverPeers; + + fn poll( + &mut self, + cx: &mut std::task::Context<'_>, + _params: &mut impl libp2p::swarm::PollParameters, + ) -> Poll>> { + while let Poll::Ready(Some(query_result)) = self.active_queries.poll_next_unpin(cx) { + match query_result { + Ok(enrs) => { + for enr in enrs.into_iter() { + self.cached_enrs.insert(enr); + } + } + Err(e) => warn!("Discovery query failed: {:?}", e), + } + } + + match self.event_stream { + EventStream::Awaiting(ref mut fut) => { + if let Poll::Ready(event_stream) = fut.poll_unpin(cx) { + match event_stream { + Ok(stream) => self.event_stream = EventStream::Present(stream), + Err(err) => { + warn!("Discovery event stream failed: {:?}", err); + self.event_stream = EventStream::InActive; + } + } + } + } + EventStream::Present(ref mut stream) => { + while let Poll::Ready(Some(event)) = stream.poll_recv(cx) { + match event { + Discv5Event::Discovered(_) => {} + Discv5Event::EnrAdded { .. } + | Discv5Event::NodeInserted { .. } + | Discv5Event::SessionEstablished(_, _) + | Discv5Event::SocketUpdated(_) + | Discv5Event::TalkRequest(_) => {} + } + } + } + EventStream::InActive => {} + }; + Poll::Pending + } + fn on_swarm_event(&mut self, _event: libp2p::swarm::FromSwarm) {} + + fn on_connection_handler_event( + &mut self, + _peer_id: libp2p::PeerId, + _connection_id: libp2p::swarm::ConnectionId, + _event: libp2p::swarm::THandlerOutEvent, + ) { + } + + fn handle_established_inbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + _peer: libp2p::PeerId, + _local_addr: &libp2p::Multiaddr, + _remote_addr: &libp2p::Multiaddr, + ) -> Result, libp2p::swarm::ConnectionDenied> { + Ok(ConnectionHandler) + } + + fn handle_established_outbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + _peer: libp2p::PeerId, + _addr: &libp2p::Multiaddr, + _role_override: libp2p::core::Endpoint, + ) -> Result, libp2p::swarm::ConnectionDenied> { + Ok(ConnectionHandler) + } + + fn handle_pending_inbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + _local_addr: &libp2p::Multiaddr, + _remote_addr: &libp2p::Multiaddr, + ) -> Result<(), libp2p::swarm::ConnectionDenied> { + Ok(()) + } + + fn handle_pending_outbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + _maybe_peer: Option, + _addresses: &[libp2p::Multiaddr], + _effective_role: libp2p::core::Endpoint, + ) -> Result, libp2p::swarm::ConnectionDenied> { + Ok(Vec::new()) + } +} diff --git a/crates/p2p/src/enr.rs b/crates/p2p/src/enr.rs new file mode 100644 index 00000000..0f91efe5 --- /dev/null +++ b/crates/p2p/src/enr.rs @@ -0,0 +1,96 @@ +use discv5::{ + enr::{ + k256::{ecdsa::VerifyingKey, CompressedPoint}, + CombinedKey, CombinedPublicKey, EnrBuilder, + }, + Enr, +}; +use libp2p::{ + identity::{secp256k1, Keypair, PublicKey}, + multiaddr::Protocol, + Multiaddr, PeerId, +}; + +use crate::config::Config; + +pub fn keypair_to_combine(keypair: Keypair) -> eyre::Result { + match keypair.try_into_secp256k1() { + Ok(key) => { + let secret = + discv5::enr::k256::ecdsa::SigningKey::from_bytes(&key.secret().to_bytes().into()) + .expect("libp2p key must be valid"); + Ok(CombinedKey::Secp256k1(secret)) + } + Err(_) => eyre::bail!("libp2p key must be either secp256k1"), + } +} + +pub fn build_enr(enr_key: &CombinedKey, config: &Config) -> eyre::Result { + let mut enr_builder = EnrBuilder::new("v4"); + if let Some(ip) = config.ipv4_addr { + enr_builder.ip4(ip); + } + if let Some(ip) = config.ipv6_addr { + enr_builder.ip6(ip); + } + if let Some(port) = config.enr_tcp4_port { + enr_builder.tcp4(port); + } + if let Some(port) = config.enr_tcp6_port { + enr_builder.tcp6(port); + } + if let Some(port) = config.enr_udp4_port { + enr_builder.udp4(port); + } + if let Some(port) = config.enr_udp6_port { + enr_builder.udp6(port); + } + + let enr = enr_builder.build(enr_key)?; + Ok(enr) +} + +pub trait EnrExt { + fn peer_id(&self) -> eyre::Result; + + /// Multiaddr used for dialing + fn multiaddr(&self) -> eyre::Result>; +} + +impl EnrExt for Enr { + fn peer_id(&self) -> eyre::Result { + self.public_key().to_peer_id() + } + + fn multiaddr(&self) -> eyre::Result> { + let mut multiaddrs: Vec = Vec::new(); + if let Some(ipv4) = self.ip4() { + let mut addr: Multiaddr = ipv4.into(); + + if let Some(tcp4) = self.tcp4() { + addr.push(Protocol::Tcp(tcp4)); + } + multiaddrs.push(addr); + } + + Ok(multiaddrs) + } +} + +pub trait CombineKeyPubExt { + fn to_peer_id(&self) -> eyre::Result; +} + +impl CombineKeyPubExt for CombinedPublicKey { + fn to_peer_id(&self) -> eyre::Result { + let pub_key: PublicKey = match self { + CombinedPublicKey::Secp256k1(pk) => { + PublicKey::from(secp256k1::PublicKey::try_from_bytes( + <&VerifyingKey as Into>::into(pk).as_slice(), + )?) + } + _ => eyre::bail!("Only secp256k1 is supported"), + }; + Ok(PeerId::from_public_key(&pub_key)) + } +} diff --git a/crates/p2p/src/gossipsub.rs b/crates/p2p/src/gossipsub.rs new file mode 100644 index 00000000..8105b178 --- /dev/null +++ b/crates/p2p/src/gossipsub.rs @@ -0,0 +1,118 @@ +use std::{ + collections::HashSet, + io::{Error, ErrorKind}, +}; + +use libp2p::gossipsub::{ + Behaviour, ConfigBuilder, DataTransform, IdentTopic, Message, MessageAuthenticity, RawMessage, + TopicHash, ValidationMode, WhitelistSubscriptionFilter, +}; +use snap::raw::{decompress_len, Decoder, Encoder}; + +pub type Gossipsub = Behaviour; + +const TOPIC_PREFIX: &str = "account_abstraction"; +const USER_OPS_WITH_ENTRY_POINT_TOPIC: &str = "user_ops_with_entry_point"; +const SSZ_SNAPPY_ENCODING: &str = "ssz_snappy"; +const MAX_GOSSIP_SNAP_SIZE: usize = 1048576; // bytes + +// Highly inspired by https://github.com/sigp/lighthouse/blob/stable/beacon_node/lighthouse_network/src/types/pubsub.rs#L45-L103 +// Implements the `DataTransform` trait of gossipsub to employ snappy compression +pub struct SnappyTransform { + /// Sets the maximum size we allow gossipsub messages to decompress to. + max_size_per_message: usize, +} + +impl SnappyTransform { + pub fn new(max_size_per_message: usize) -> Self { + SnappyTransform { + max_size_per_message, + } + } +} +impl Default for SnappyTransform { + fn default() -> Self { + SnappyTransform { + max_size_per_message: MAX_GOSSIP_SNAP_SIZE, + } + } +} + +impl DataTransform for SnappyTransform { + // Provides the snappy decompression from RawGossipsubMessages + fn inbound_transform(&self, raw_message: RawMessage) -> Result { + // check the length of the raw bytes + let len = decompress_len(&raw_message.data)?; + if len > self.max_size_per_message { + return Err(Error::new( + ErrorKind::InvalidData, + "ssz_snappy decoded data > GOSSIP_MAX_SIZE", + )); + } + + let mut decoder = Decoder::new(); + let decompressed_data = decoder.decompress_vec(&raw_message.data)?; + + // Build the GossipsubMessage struct + Ok(Message { + source: raw_message.source, + data: decompressed_data, + sequence_number: raw_message.sequence_number, + topic: raw_message.topic, + }) + } + + /// Provides the snappy compression logic to gossipsub. + fn outbound_transform( + &self, + _topic: &TopicHash, + data: Vec, + ) -> Result, std::io::Error> { + // Currently we are not employing topic-based compression. Everything is expected to be + // snappy compressed. + if data.len() > self.max_size_per_message { + return Err(Error::new( + ErrorKind::InvalidData, + "ssz_snappy Encoded data > GOSSIP_MAX_SIZE", + )); + } + let mut encoder = Encoder::new(); + encoder.compress_vec(&data).map_err(Into::into) + } +} + +pub fn create_whitelist_filter(mempool_ids: Vec) -> WhitelistSubscriptionFilter { + let mut possible_hashes: HashSet = HashSet::new(); + for mempool_id in mempool_ids { + let topic = topic(&mempool_id); + possible_hashes.insert(topic.into()); + } + WhitelistSubscriptionFilter(possible_hashes) +} + +pub fn topic(mempool_id: &str) -> IdentTopic { + IdentTopic::new(format!( + "/{TOPIC_PREFIX:}/{mempool_id}/{USER_OPS_WITH_ENTRY_POINT_TOPIC:}/{SSZ_SNAPPY_ENCODING:}" + )) +} + +pub fn create_gossisub(mempool_ids: Vec) -> Result { + let filter = create_whitelist_filter(mempool_ids.clone()); + let gs_config = ConfigBuilder::default() + .validation_mode(ValidationMode::Anonymous) + .build()?; + let snappy_transform = SnappyTransform::new(MAX_GOSSIP_SNAP_SIZE); + let mut gossipsub = Gossipsub::new_with_subscription_filter_and_transform( + MessageAuthenticity::Anonymous, + gs_config, + None, + filter, + snappy_transform, + )?; + for mempool_id in mempool_ids { + let _ = gossipsub + .subscribe(&topic(&mempool_id)) + .map_err(|_| "subscribe error")?; + } + Ok(gossipsub) +} diff --git a/crates/p2p/src/lib.rs b/crates/p2p/src/lib.rs new file mode 100644 index 00000000..b42b58d8 --- /dev/null +++ b/crates/p2p/src/lib.rs @@ -0,0 +1,10 @@ +pub mod behaviour; +pub mod config; +pub mod discovery; +pub mod enr; +pub mod gossipsub; +pub mod network; +pub mod peer_manager; +pub mod request_response; +#[cfg(test)] +mod tests; diff --git a/crates/p2p/src/network.rs b/crates/p2p/src/network.rs new file mode 100644 index 00000000..2ca19f6d --- /dev/null +++ b/crates/p2p/src/network.rs @@ -0,0 +1,378 @@ +use std::{ + io, + task::{Context, Poll}, + time::Duration, +}; + +use discv5::Enr; +use ethers::types::{Address, U256}; +use futures::channel::{ + mpsc::{UnboundedReceiver, UnboundedSender}, + oneshot, +}; +use libp2p::{ + core::{transport::ListenerId, upgrade}, + futures::StreamExt, + gossipsub::{self, MessageId, PublishError, SubscriptionError, TopicHash}, + identity::Keypair, + noise, + swarm::SwarmEvent, + Multiaddr, PeerId, Swarm, SwarmBuilder, TransportError, +}; +use libp2p_mplex::{MaxBufferBehaviour, MplexConfig}; +use silius_primitives::{Chain, UserOperation, UserOperationsWithEntryPoint}; +use ssz_rs::{Deserialize, Serialize}; +use tracing::{debug, error, info, warn}; + +use crate::{ + behaviour::Behaviour, + config::Config, + discovery, + enr::{keypair_to_combine, EnrExt}, + gossipsub::topic, + peer_manager::PeerManagerEvent, + request_response::{self, Ping, Request, RequestId, Response}, +}; + +struct TokioExecutor; +impl libp2p::swarm::Executor for TokioExecutor { + fn exec(&self, future: std::pin::Pin + Send>>) { + tokio::spawn(future); + } +} + +#[derive(Debug, PartialEq)] +pub enum PubsubMessage { + UserOps(UserOperationsWithEntryPoint), +} + +#[derive(Debug)] +pub enum NetworkEvent { + /// A peer successfully connected with us. + PeerConnected(PeerId), + /// Gossipsub message from the network + PubsubMessage { + /// The peer that forwarded us this message. + source_peer: PeerId, + /// The gossipsub message id. Used when propagating blocks after validation. + id: MessageId, + /// The message itself. + message: PubsubMessage, + }, + /// Request or response message from the network + RequestMessage { + /// The peer that sent the request. + peer_id: PeerId, + /// Request the peer sent. + request: Request, + /// response sender + response_sender: oneshot::Sender, + }, + ResponseMessage { + /// The peer that sent the request. + peer_id: PeerId, + /// Request the peer sent. + response: Response, + }, + /// Describe a peer is subscribe on something + Subscribe { + /// The peer that subscribe + peer_id: PeerId, + /// The topic which peer is subscribing + topic: TopicHash, + }, + /// Network listens to address successfully + NewListenAddr(Multiaddr), +} + +pub type EntrypointChannels = Vec<( + Chain, + Address, + UnboundedReceiver<(UserOperation, U256)>, + UnboundedSender, +)>; +/// P2P network struct that holds the libp2p Swarm +/// Other components should interact with Network directly instead of behaviour +pub struct Network { + swarm: Swarm, + entrypoint_channels: EntrypointChannels, +} + +impl From for Swarm { + fn from(value: Network) -> Self { + value.swarm + } +} + +impl Network { + #[allow(clippy::too_many_arguments)] + pub fn new( + key: Keypair, + config: Config, + entrypoint_channels: EntrypointChannels, + ping_interval: Duration, + target_peers: usize, + ) -> eyre::Result { + let combine_key = keypair_to_combine(key.clone())?; + let behaviour = Behaviour::new( + combine_key, + config, + entrypoint_channels + .iter() + .map(|(c, _, _, _)| c.p2p_mempool_id()) + .collect(), + ping_interval, + target_peers, + )?; + + // mplex config + let mut mplex_config = MplexConfig::new(); + mplex_config.set_max_buffer_size(256); + mplex_config.set_max_buffer_behaviour(MaxBufferBehaviour::Block); + + // yamux config + let mut yamux_config = libp2p::yamux::Config::default(); + yamux_config.set_window_update_mode(libp2p::yamux::WindowUpdateMode::on_read()); + let swarm = SwarmBuilder::with_existing_identity(key) + .with_tokio() + .with_tcp( + libp2p::tcp::Config::default().nodelay(true), + noise::Config::new, + || upgrade::SelectUpgrade::new(yamux_config, mplex_config), + ) + .expect("building p2p transport failed") + .with_behaviour(|_| behaviour) + .expect("building p2p behaviour failed") + .build(); + Ok(Self { + swarm, + entrypoint_channels, + }) + } + + fn handle_gossipsub_event(&self, event: Box) -> Option { + match *event { + gossipsub::Event::Message { + propagation_source, + message_id, + message, + } => { + let userops = match UserOperationsWithEntryPoint::deserialize(message.data.as_ref()) + { + Ok(userops) => userops, + Err(e) => { + debug!("Failed to deserialize userops: {:?}", e); + return None; + } + }; + self.entrypoint_channels + .iter() + .find_map(|(_, ep, _, new_coming_uos_ch)| { + if *ep == userops.entrypoint_address() { + for user_op in userops.clone().user_ops().into_iter() { + new_coming_uos_ch + .unbounded_send(user_op) + .expect("new useop channel should be open all the time"); + } + Some(()) + } else { + warn!("Received unsupported entrypoint userops {ep:?} from p2p"); + None + } + }); + let message = PubsubMessage::UserOps(userops); + + Some(NetworkEvent::PubsubMessage { + source_peer: propagation_source, + id: message_id, + message, + }) + } + gossipsub::Event::Subscribed { peer_id, topic } => { + debug!("Peer {:?} subscribed to {:?}", peer_id, topic); + Some(NetworkEvent::Subscribe { peer_id, topic }) + } + msg => { + debug!("{msg:?}"); + None + } + } + } + + fn handle_reqrep_event(&self, event: request_response::Event) -> Option { + match event { + request_response::Event::Request { + peer_id, + request, + response_sender, + .. + } => Some(NetworkEvent::RequestMessage { + peer_id, + request, + response_sender, + }), + request_response::Event::Response { + peer_id, response, .. + } => Some(NetworkEvent::ResponseMessage { peer_id, response }), + _ => None, + } + } + + // TODO: discovery peer connect + fn handle_discovery_event(&self, _event: discovery::DiscoverPeers) -> Option { + None + } + + /// handle peer manager event + fn handler_peer_manager_event(&mut self, event: PeerManagerEvent) -> Option { + match event { + PeerManagerEvent::Ping(peer) => { + // FIXME: seq number should be a counter + self.send_request(&peer, Request::Ping(Ping::new(1))); + None + } + PeerManagerEvent::PeerConnectedIncoming(peer) + | PeerManagerEvent::PeerConnectedOutgoing(peer) => { + self.swarm + .behaviour_mut() + .gossipsub + .add_explicit_peer(&peer); + + Some(NetworkEvent::PeerConnected(peer)) + } + PeerManagerEvent::PeerDisconnected(_) => None, + PeerManagerEvent::DiscoverPeers(_) => None, + } + } + + pub fn poll_network(&mut self, cx: &mut Context) -> Poll { + let mut msg_to_publich = Vec::new(); + for (chain, ep, waiting_to_publish_ch, _) in self.entrypoint_channels.iter_mut() { + while let Ok(Some((pub_userop, verified_block))) = waiting_to_publish_ch.try_next() { + info!("Got userop {pub_userop:?} from ep {ep:} verified in {verified_block:?} to publish to p2p network!"); + let pub_msg = UserOperationsWithEntryPoint::new( + *ep, + verified_block, + chain.id().into(), + vec![pub_userop], + ); + msg_to_publich.push(pub_msg); + } + } + + for pub_msg in msg_to_publich.into_iter() { + match self.publish(pub_msg) { + Ok(_) => {} + Err(err) => match err { + PublishError::InsufficientPeers => { + warn!("Currently no peers to publish message"); + self.swarm.behaviour_mut().discv5.discover_peers(16usize); + } + e => error!("Error in publish message {e:?}"), + }, + } + } + + while let Poll::Ready(Some(swarm_event)) = self.swarm.poll_next_unpin(cx) { + info!("Swarm get event {swarm_event:?}"); + let event_opt = match swarm_event { + SwarmEvent::Behaviour(e) => match e { + crate::behaviour::Event::GossipSub(event) => self.handle_gossipsub_event(event), + crate::behaviour::Event::Reqrep(event) => self.handle_reqrep_event(event), + crate::behaviour::Event::Discovery(event) => self.handle_discovery_event(event), + crate::behaviour::Event::PeerManager(event) => { + self.handler_peer_manager_event(event) + } + }, + + SwarmEvent::NewListenAddr { address, .. } => { + Some(NetworkEvent::NewListenAddr(address)) + } + event => { + { + debug!("unhandled swarn event: {event:?}"); + } + None + } + }; + if let Some(event) = event_opt { + return Poll::Ready(event); + } + } + Poll::Pending + } + + pub fn listen_on(&mut self, addr: Multiaddr) -> Result> { + self.swarm.listen_on(addr) + } + + pub async fn next_event(&mut self) -> NetworkEvent { + futures::future::poll_fn(|cx| self.poll_network(cx)).await + } + + pub fn local_peer_id(&self) -> &PeerId { + self.swarm.local_peer_id() + } + + pub fn publish( + &mut self, + user_ops: UserOperationsWithEntryPoint, + ) -> Result { + let mut buf = Vec::new(); + let _ = user_ops + .serialize(&mut buf) + .expect("ssz of user ops serialization failed"); + let topic_hash: TopicHash = topic(user_ops.chain().p2p_mempool_id().as_str()).into(); + self.swarm + .behaviour_mut() + .gossipsub + .publish(topic_hash, buf) + } + + pub fn dial(&mut self, enr: Enr) -> eyre::Result<()> { + let addrs = enr.multiaddr()?; + for addr in addrs { + self.swarm.dial(addr)?; + } + self.swarm + .behaviour_mut() + .discv5 + .discovery + .add_enr(enr) + .map_err(|e| eyre::eyre!(e.to_string()))?; + Ok(()) + } + + pub fn subscribe(&mut self, mempool_id: &str) -> Result { + self.swarm + .behaviour_mut() + .gossipsub + .subscribe(&topic(mempool_id)) + } + + pub fn listened_addrs(&self) -> Vec<&Multiaddr> { + self.swarm.listeners().collect() + } + + pub fn local_enr(&self) -> Enr { + self.swarm.behaviour().discv5.local_enr() + } + + pub fn send_request(&mut self, peer: &PeerId, request: Request) -> RequestId { + self.swarm + .behaviour_mut() + .reqrep + .send_request(peer, request) + } + + pub fn send_response( + &mut self, + response_channel: oneshot::Sender, + response: Response, + ) -> Result<(), Response> { + self.swarm + .behaviour_mut() + .reqrep + .send_response(response_channel, response) + } +} diff --git a/crates/p2p/src/peer_manager/mod.rs b/crates/p2p/src/peer_manager/mod.rs new file mode 100644 index 00000000..83cfd966 --- /dev/null +++ b/crates/p2p/src/peer_manager/mod.rs @@ -0,0 +1,141 @@ +pub mod peerdb; + +use std::{collections::VecDeque, task::Poll, time::Duration}; + +use delay_map::HashSetDelay; +use futures::StreamExt; +use libp2p::{ + swarm::{dummy::ConnectionHandler, NetworkBehaviour, ToSwarm}, + PeerId, +}; +use tracing::error; + +use self::peerdb::PeerDB; + +/// The events that the `PeerManager` outputs (requests). +#[derive(Debug)] +pub enum PeerManagerEvent { + /// A peer has dialed us. + PeerConnectedIncoming(PeerId), + /// A peer has been dialed. + PeerConnectedOutgoing(PeerId), + /// A peer has disconnected. + PeerDisconnected(PeerId), + /// Sends a PING to a peer. + Ping(PeerId), + /// Request the behaviour to discover more peers and the amount of peers to discover. + DiscoverPeers(usize), +} + +pub struct PeerManager { + /// A list of peers that we need to ping. + ping_peers: HashSetDelay, + /// the target peers we want to connect + _target_peers: usize, + /// Peer database + peer_db: PeerDB, + /// Events that the `PeerManager` outputs. + events: VecDeque, +} + +impl PeerManager { + pub fn new(ping_interval: Duration, target_peers: usize) -> Self { + Self { + ping_peers: HashSetDelay::new(ping_interval), + _target_peers: target_peers, + peer_db: Default::default(), + events: Default::default(), + } + } +} + +impl NetworkBehaviour for PeerManager { + type ConnectionHandler = ConnectionHandler; + type ToSwarm = PeerManagerEvent; + fn on_swarm_event(&mut self, event: libp2p::swarm::FromSwarm) { + if let libp2p::swarm::FromSwarm::ConnectionClosed(close_info) = event { + self.peer_db.disconnect(close_info.peer_id); + self.events + .push_back(PeerManagerEvent::PeerDisconnected(close_info.peer_id)); + } + } + + fn on_connection_handler_event( + &mut self, + _peer_id: PeerId, + _connection_id: libp2p::swarm::ConnectionId, + _event: libp2p::swarm::THandlerOutEvent, + ) { + } + + fn handle_established_inbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + peer: PeerId, + _local_addr: &libp2p::Multiaddr, + _remote_addr: &libp2p::Multiaddr, + ) -> Result, libp2p::swarm::ConnectionDenied> { + self.peer_db.new_connected(peer); + self.ping_peers.insert(peer); + self.events + .push_back(PeerManagerEvent::PeerConnectedIncoming(peer)); + Ok(ConnectionHandler) + } + + fn handle_established_outbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + peer: PeerId, + _addr: &libp2p::Multiaddr, + _role_override: libp2p::core::Endpoint, + ) -> Result, libp2p::swarm::ConnectionDenied> { + self.peer_db.new_connected(peer); + self.ping_peers.insert(peer); + self.events + .push_back(PeerManagerEvent::PeerConnectedOutgoing(peer)); + Ok(ConnectionHandler) + } + + fn handle_pending_inbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + _local_addr: &libp2p::Multiaddr, + _remote_addr: &libp2p::Multiaddr, + ) -> Result<(), libp2p::swarm::ConnectionDenied> { + Ok(()) + } + + fn handle_pending_outbound_connection( + &mut self, + _connection_id: libp2p::swarm::ConnectionId, + _maybe_peer: Option, + _addresses: &[libp2p::Multiaddr], + _effective_role: libp2p::core::Endpoint, + ) -> Result, libp2p::swarm::ConnectionDenied> { + Ok(vec![]) + } + + fn poll( + &mut self, + cx: &mut std::task::Context<'_>, + _params: &mut impl libp2p::swarm::PollParameters, + ) -> Poll>> { + loop { + match self.ping_peers.poll_next_unpin(cx) { + Poll::Ready(Some(Ok(peer))) => { + self.events.push_back(PeerManagerEvent::Ping(peer)); + self.ping_peers.insert(peer); + } + Poll::Ready(Some(Err(e))) => { + error!("Failed to check ping peer with {e:?}") + } + _ => break, + }; + } + + match self.events.pop_front() { + Some(event) => Poll::Ready(ToSwarm::GenerateEvent(event)), + _ => Poll::Pending, + } + } +} diff --git a/crates/p2p/src/peer_manager/peerdb.rs b/crates/p2p/src/peer_manager/peerdb.rs new file mode 100644 index 00000000..167801d3 --- /dev/null +++ b/crates/p2p/src/peer_manager/peerdb.rs @@ -0,0 +1,39 @@ +use std::collections::HashMap; + +use libp2p::PeerId; + +pub enum ConnectionStatus { + Connected, + Disconnected, +} +pub struct PeerInfo { + connection_status: ConnectionStatus, +} + +#[derive(Default)] +pub struct PeerDB { + peers: HashMap, +} + +impl PeerDB { + pub fn new() -> Self { + Self { + peers: HashMap::new(), + } + } + + pub fn new_connected(&mut self, peer_id: PeerId) { + self.peers + .entry(peer_id) + .and_modify(|info| info.connection_status = ConnectionStatus::Connected) + .or_insert(PeerInfo { + connection_status: ConnectionStatus::Connected, + }); + } + + pub fn disconnect(&mut self, peer_id: PeerId) { + self.peers + .entry(peer_id) + .and_modify(|info| info.connection_status = ConnectionStatus::Disconnected); + } +} diff --git a/crates/p2p/src/request_response/behaviour.rs b/crates/p2p/src/request_response/behaviour.rs new file mode 100644 index 00000000..6f30253f --- /dev/null +++ b/crates/p2p/src/request_response/behaviour.rs @@ -0,0 +1,497 @@ +use std::{ + collections::{HashMap, HashSet, VecDeque}, + sync::{atomic::AtomicU64, Arc}, + task::Poll, + time::Duration, +}; + +use futures::channel::oneshot; +use libp2p::{ + swarm::{ + dial_opts::DialOpts, ConnectionClosed, ConnectionDenied, ConnectionId, DialFailure, + FromSwarm, NetworkBehaviour, NotifyHandler, PollParameters, THandler, THandlerInEvent, + THandlerOutEvent, ToSwarm, + }, + PeerId, +}; + +use super::{ + handler::{Handler, HandlerEvent}, + models::{Request, RequestId, Response}, + outbound::OutboundContainer, +}; + +#[derive(Debug)] +pub enum Event { + Request { + peer_id: PeerId, + request: Request, + request_id: RequestId, + response_sender: oneshot::Sender, + }, + Response { + peer_id: PeerId, + request_id: RequestId, + response: Response, + }, + OutboundFailure { + peer_id: PeerId, + request_id: RequestId, + error: OutboundFailure, + }, + InboundFailure { + peer_id: PeerId, + request_id: RequestId, + error: InboundFailure, + }, + ResponseSent { + peer_id: PeerId, + request_id: RequestId, + }, +} + +#[derive(Debug)] +pub enum OutboundFailure { + /// A dialing attempt failed. + DialFailure, + /// The request timed out before a response was received. + /// + /// It is not known whether the request may have been + /// received (and processed) by the remote peer. + Timeout, + /// The connection closed before a response was received. + /// + /// It is not known whether the request may have been + /// received (and processed) by the remote peer. + ConnectionClosed, + /// The remote supports none of the requested protocols. + UnsupportedProtocols, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum InboundFailure { + /// The inbound request timed out, either while reading the + /// incoming request or before a response is sent, e.g. if + /// [`Behaviour::send_response`] is not called in a + /// timely manner. + Timeout, + /// The connection closed before a response could be send. + ConnectionClosed, + /// The local peer supports none of the protocols requested + /// by the remote. + UnsupportedProtocols, + /// The local peer failed to respond to an inbound request + /// due to the [`ResponseChannel`] being dropped instead of + /// being passed to [`Behaviour::send_response`]. + ResponseOmission, +} +#[derive(Debug)] +pub struct Config { + pub request_timeout: Duration, +} + +impl Default for Config { + fn default() -> Self { + Self { + request_timeout: Duration::from_secs(10), + } + } +} +pub struct Behaviour { + config: Config, + /// The next (local) request ID. + next_request_id: RequestId, + /// The next (inbound) request ID. + next_inbound_id: Arc, + /// pending events to return from `Poll` + pending_events: VecDeque>, + connected: HashMap>, + pending_outbound_requests: HashMap>, +} + +impl Behaviour { + pub fn new(config: Config) -> Self { + Self { + config, + next_request_id: RequestId(1), + next_inbound_id: Arc::new(AtomicU64::new(1)), + pending_events: VecDeque::new(), + connected: HashMap::new(), + pending_outbound_requests: HashMap::new(), + } + } + /// Returns the next request ID. + fn next_request_id(&mut self) -> RequestId { + let request_id = self.next_request_id; + self.next_request_id.0 += 1; + request_id + } + + pub fn send_request(&mut self, peer: &PeerId, request: Request) -> RequestId { + let request_id = self.next_request_id(); + let request = OutboundContainer { + request, + request_id, + }; + + if let Some(request) = self.try_send_request(peer, request) { + self.pending_events.push_back(ToSwarm::Dial { + opts: DialOpts::peer_id(*peer).build(), + }); + self.pending_outbound_requests + .entry(*peer) + .or_default() + .push(request); + } + + request_id + } + + pub fn send_response( + &mut self, + sender: oneshot::Sender, + response: Response, + ) -> Result<(), Response> { + sender.send(response) + } + + fn try_send_request( + &mut self, + peer: &PeerId, + request: OutboundContainer, + ) -> Option { + if let Some(connections) = self.connected.get_mut(peer) { + if connections.is_empty() { + return Some(request); + } + let ix = (request.request_id.0 as usize) % connections.len(); + let conn = &mut connections[ix]; + conn.pending_inbound_responses.insert(request.request_id); + self.pending_events.push_back(ToSwarm::NotifyHandler { + peer_id: *peer, + handler: NotifyHandler::One(conn.id), + event: request, + }); + None + } else { + Some(request) + } + } + /// Remove pending outbound response for the given peer and connection. + /// + /// Returns `true` if the provided connection to the given peer is still + /// alive and the [`RequestId`] was previously present and is now removed. + /// Returns `false` otherwise. + fn remove_pending_outbound_response( + &mut self, + peer: &PeerId, + connection: ConnectionId, + request: RequestId, + ) -> bool { + self.get_connection_mut(peer, connection) + .map(|c| c.pending_outbound_responses.remove(&request)) + .unwrap_or(false) + } + + /// Remove pending inbound response for the given peer and connection. + /// + /// Returns `true` if the provided connection to the given peer is still + /// alive and the [`RequestId`] was previously present and is now removed. + /// Returns `false` otherwise. + fn remove_pending_inbound_response( + &mut self, + peer: &PeerId, + connection: ConnectionId, + request: &RequestId, + ) -> bool { + self.get_connection_mut(peer, connection) + .map(|c| c.pending_inbound_responses.remove(request)) + .unwrap_or(false) + } + + /// Returns a mutable reference to the connection in `self.connected` + /// corresponding to the given [`PeerId`] and [`ConnectionId`]. + fn get_connection_mut( + &mut self, + peer: &PeerId, + connection: ConnectionId, + ) -> Option<&mut Connection> { + self.connected + .get_mut(peer) + .and_then(|connections| connections.iter_mut().find(|c| c.id == connection)) + } + + fn on_connection_closed( + &mut self, + ConnectionClosed { + peer_id, + connection_id, + remaining_established, + .. + }: ConnectionClosed<::ConnectionHandler>, + ) { + let connections = self + .connected + .get_mut(&peer_id) + .expect("Expected some established connection to peer before closing."); + + let connection = connections + .iter() + .position(|c| c.id == connection_id) + .map(|p: usize| connections.remove(p)) + .expect("Expected connection to be established before closing."); + + debug_assert_eq!(connections.is_empty(), remaining_established == 0); + if connections.is_empty() { + self.connected.remove(&peer_id); + } + + for request_id in connection.pending_outbound_responses { + self.pending_events + .push_back(ToSwarm::GenerateEvent(Event::InboundFailure { + peer_id, + request_id, + error: InboundFailure::ConnectionClosed, + })); + } + + for request_id in connection.pending_inbound_responses { + self.pending_events + .push_back(ToSwarm::GenerateEvent(Event::OutboundFailure { + peer_id, + request_id, + error: OutboundFailure::ConnectionClosed, + })); + } + } + + fn on_dial_failure(&mut self, DialFailure { peer_id, .. }: DialFailure) { + if let Some(peer_id) = peer_id { + // If there are pending outgoing requests when a dial failure occurs, + // it is implied that we are not connected to the peer, since pending + // outgoing requests are drained when a connection is established and + // only created when a peer is not connected when a request is made. + // Thus these requests must be considered failed, even if there is + // another, concurrent dialing attempt ongoing. + if let Some(pending) = self.pending_outbound_requests.remove(&peer_id) { + for request in pending { + self.pending_events + .push_back(ToSwarm::GenerateEvent(Event::OutboundFailure { + peer_id, + request_id: request.request_id, + error: OutboundFailure::DialFailure, + })); + } + } + } + } +} + +impl NetworkBehaviour for Behaviour { + type ConnectionHandler = Handler; + type ToSwarm = Event; + fn handle_established_inbound_connection( + &mut self, + connection_id: ConnectionId, + _peer: libp2p::PeerId, + _local_addr: &libp2p::Multiaddr, + _remote_addr: &libp2p::Multiaddr, + ) -> Result, ConnectionDenied> { + Ok(Handler::new( + connection_id, + self.config.request_timeout, + self.next_inbound_id.clone(), + )) + } + + fn handle_established_outbound_connection( + &mut self, + connection_id: ConnectionId, + _peer: libp2p::PeerId, + _addr: &libp2p::Multiaddr, + _role_override: libp2p::core::Endpoint, + ) -> Result, ConnectionDenied> { + Ok(Handler::new( + connection_id, + self.config.request_timeout, + self.next_inbound_id.clone(), + )) + } + + fn handle_pending_inbound_connection( + &mut self, + _connection_id: ConnectionId, + _local_addr: &libp2p::Multiaddr, + _remote_addr: &libp2p::Multiaddr, + ) -> Result<(), ConnectionDenied> { + Ok(()) + } + + fn handle_pending_outbound_connection( + &mut self, + _connection_id: ConnectionId, + _maybe_peer: Option, + _addresses: &[libp2p::Multiaddr], + _effective_role: libp2p::core::Endpoint, + ) -> Result, ConnectionDenied> { + Ok(vec![]) + } + + fn on_connection_handler_event( + &mut self, + peer_id: PeerId, + connection_id: ConnectionId, + event: THandlerOutEvent, + ) { + match event { + HandlerEvent::Request { + request, + request_id, + response_sender, + } => { + let message = Event::Request { + peer_id, + request_id, + request, + response_sender, + }; + self.pending_events + .push_back(ToSwarm::GenerateEvent(message)); + + match self.get_connection_mut(&peer_id, connection_id) { + Some(connection) => { + connection.pending_outbound_responses.insert(request_id); + } + // Connection closed after `Event::Request` has been emitted. + None => { + self.pending_events.push_back(ToSwarm::GenerateEvent( + Event::InboundFailure { + peer_id, + request_id, + error: InboundFailure::ConnectionClosed, + }, + )); + } + } + } + HandlerEvent::Response { + response, + request_id, + } => { + self.remove_pending_inbound_response(&peer_id, connection_id, &request_id); + + self.pending_events + .push_back(ToSwarm::GenerateEvent(Event::Response { + peer_id, + request_id, + response, + })); + } + HandlerEvent::ResponseSent(request_id) => { + self.remove_pending_outbound_response(&peer_id, connection_id, request_id); + + self.pending_events + .push_back(ToSwarm::GenerateEvent(Event::ResponseSent { + peer_id, + request_id, + })); + } + HandlerEvent::ResponseOmission(request_id) => { + self.remove_pending_outbound_response(&peer_id, connection_id, request_id); + + self.pending_events + .push_back(ToSwarm::GenerateEvent(Event::InboundFailure { + peer_id, + request_id, + error: InboundFailure::ResponseOmission, + })); + } + HandlerEvent::OutboundTimeout(request_id) => { + self.remove_pending_inbound_response(&peer_id, connection_id, &request_id); + + self.pending_events + .push_back(ToSwarm::GenerateEvent(Event::OutboundFailure { + peer_id, + request_id, + error: OutboundFailure::Timeout, + })); + } + HandlerEvent::OutboundUnsurpportedProtocol(request_id) => { + let removed = + self.remove_pending_inbound_response(&peer_id, connection_id, &request_id); + debug_assert!( + removed, + "Expect request_id to be pending before failing to connect.", + ); + + self.pending_events + .push_back(ToSwarm::GenerateEvent(Event::OutboundFailure { + peer_id, + request_id, + error: OutboundFailure::UnsupportedProtocols, + })); + } + } + } + + fn on_swarm_event(&mut self, event: FromSwarm) { + match event { + FromSwarm::ConnectionEstablished(connection_established) => { + self.connected + .entry(connection_established.peer_id) + .or_default() + .push(Connection::new(connection_established.connection_id)); + + if connection_established.other_established == 0 { + if let Some(pending) = self + .pending_outbound_requests + .remove(&connection_established.peer_id) + { + for request in pending { + let request = + self.try_send_request(&connection_established.peer_id, request); + assert!(request.is_none()); + } + } + } + } + FromSwarm::ConnectionClosed(connection_closed) => { + self.on_connection_closed(connection_closed) + } + FromSwarm::DialFailure(dial_failure) => self.on_dial_failure(dial_failure), + _ => {} + } + } + + fn poll( + &mut self, + _cx: &mut std::task::Context<'_>, + _params: &mut impl PollParameters, + ) -> std::task::Poll>> { + if let Some(ev) = self.pending_events.pop_front() { + return Poll::Ready(ev); + } + Poll::Pending + } +} + +struct Connection { + id: ConnectionId, + /// Pending outbound responses where corresponding inbound requests have + /// been received on this connection and emitted via `poll` but have not yet + /// been answered. + pending_outbound_responses: HashSet, + /// Pending inbound responses for previously sent requests on this + /// connection. + pending_inbound_responses: HashSet, +} + +impl Connection { + fn new(id: ConnectionId) -> Self { + Self { + id, + pending_outbound_responses: Default::default(), + pending_inbound_responses: Default::default(), + } + } +} diff --git a/crates/p2p/src/request_response/handler.rs b/crates/p2p/src/request_response/handler.rs new file mode 100644 index 00000000..08a908ee --- /dev/null +++ b/crates/p2p/src/request_response/handler.rs @@ -0,0 +1,225 @@ +use std::{ + collections::VecDeque, + sync::{ + atomic::{AtomicU64, Ordering}, + Arc, + }, + task::Poll, + time::Duration, +}; + +use futures::{ + channel::oneshot, future::BoxFuture, stream::FuturesUnordered, FutureExt, StreamExt, + TryFutureExt, +}; +use libp2p::swarm::{ + handler::{ConnectionEvent, FullyNegotiatedInbound, FullyNegotiatedOutbound}, + ConnectionHandler, ConnectionId, KeepAlive, StreamUpgradeError, SubstreamProtocol, +}; +use tracing::warn; + +use super::{ + inbound::InboundContainer, + models::{Request, RequestId, Response}, + outbound::OutboundContainer, +}; +#[derive(Debug)] +pub enum HandlerEvent { + Request { + request: Request, + request_id: RequestId, + response_sender: oneshot::Sender, + }, + Response { + response: Response, + request_id: RequestId, + }, + ResponseSent(RequestId), + ResponseOmission(RequestId), + OutboundTimeout(RequestId), + OutboundUnsurpportedProtocol(RequestId), +} + +#[derive(Debug, thiserror::Error)] +pub enum Error {} + +struct RequestContainer { + request: Request, + request_id: RequestId, + response_sender: oneshot::Sender, +} + +/// A handler for inbound and outbound substreams. +pub struct Handler { + inbound_request_id: Arc, + /// The connection id the handler holds. + _connection_id: ConnectionId, + /// The timeout for inbound and outbound substreams (i.e. request + /// and response processing). + substream_timeout: Duration, + /// Queue of events to emit in `poll()`. + pending_events: VecDeque, + /// Outbound upgrades waiting to be emitted as an `OutboundSubstreamRequest`. + outbound: VecDeque, + /// Inbound upgrades waiting for the incoming request. + inbound: FuturesUnordered>>, +} + +impl Handler { + pub fn new( + connection_id: ConnectionId, + substream_timeout: Duration, + inbound_request_id: Arc, + ) -> Self { + Self { + _connection_id: connection_id, + substream_timeout, + pending_events: VecDeque::new(), + outbound: VecDeque::new(), + inbound: FuturesUnordered::new(), + inbound_request_id, + } + } +} + +impl ConnectionHandler for Handler { + type Error = Error; + type FromBehaviour = OutboundContainer; + type ToBehaviour = HandlerEvent; + type InboundOpenInfo = RequestId; + type InboundProtocol = InboundContainer; + type OutboundOpenInfo = RequestId; + type OutboundProtocol = OutboundContainer; + fn connection_keep_alive(&self) -> libp2p::swarm::KeepAlive { + KeepAlive::Yes + } + fn listen_protocol( + &self, + ) -> libp2p::swarm::SubstreamProtocol { + // A channel for notifying the handler when the inbound + // upgrade received the request. + let (rq_send, rq_recv) = oneshot::channel(); + + // A channel for notifying the inbound upgrade when the + // response is sent. + let (rs_send, rs_recv) = oneshot::channel(); + + let request_id = RequestId(self.inbound_request_id.fetch_add(1, Ordering::Relaxed)); + + let protocol = InboundContainer { + request_sender: rq_send, + response_receiver: rs_recv, + }; + + self.inbound.push( + rq_recv + .map_ok(move |rq| RequestContainer { + request: rq, + request_id, + response_sender: rs_send, + }) + .boxed(), + ); + + SubstreamProtocol::new(protocol, request_id) + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + self.outbound.push_back(event) + } + + fn on_connection_event( + &mut self, + event: libp2p::swarm::handler::ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { protocol, info }) => { + if protocol { + self.pending_events + .push_back(HandlerEvent::ResponseSent(info)) + } else { + self.pending_events + .push_back(HandlerEvent::ResponseOmission(info)) + } + } + ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { + protocol, + info, + }) => self.pending_events.push_back(HandlerEvent::Response { + response: protocol, + request_id: info, + }), + ConnectionEvent::DialUpgradeError(error) => match error.error { + StreamUpgradeError::Timeout => self + .pending_events + .push_back(HandlerEvent::OutboundTimeout(error.info)), + StreamUpgradeError::NegotiationFailed => self + .pending_events + .push_back(HandlerEvent::OutboundUnsurpportedProtocol(error.info)), + dial_error => warn!( + "outbount stream with {:?} failed with {dial_error:?}", + error.info + ), + }, + ConnectionEvent::ListenUpgradeError(_) + | ConnectionEvent::LocalProtocolsChange(_) + | ConnectionEvent::RemoteProtocolsChange(_) + | ConnectionEvent::AddressChange(_) => {} + } + } + + #[allow(deprecated)] + fn poll( + &mut self, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll< + libp2p::swarm::ConnectionHandlerEvent< + Self::OutboundProtocol, + Self::OutboundOpenInfo, + Self::ToBehaviour, + Self::Error, + >, + > { + if let Some(event) = self.pending_events.pop_front() { + return Poll::Ready(libp2p::swarm::ConnectionHandlerEvent::NotifyBehaviour( + event, + )); + }; + + while let Poll::Ready(Some(result)) = self.inbound.poll_next_unpin(cx) { + match result { + Ok(RequestContainer { + request, + request_id, + response_sender, + }) => { + return Poll::Ready(libp2p::swarm::ConnectionHandlerEvent::NotifyBehaviour( + HandlerEvent::Request { + request, + response_sender, + request_id, + }, + )); + } + Err(oneshot::Canceled) => {} + } + } + + if let Some(request) = self.outbound.pop_front() { + let request_id = request.request_id; + return Poll::Ready( + libp2p::swarm::ConnectionHandlerEvent::OutboundSubstreamRequest { + protocol: SubstreamProtocol::new(request, request_id) + .with_timeout(self.substream_timeout), + }, + ); + }; + + Poll::Pending + } +} diff --git a/crates/p2p/src/request_response/inbound.rs b/crates/p2p/src/request_response/inbound.rs new file mode 100644 index 00000000..88d64afe --- /dev/null +++ b/crates/p2p/src/request_response/inbound.rs @@ -0,0 +1,104 @@ +use std::io::{self, Read, Write}; + +use futures::channel::oneshot; +use futures::future::BoxFuture; +use futures::{AsyncReadExt, AsyncWriteExt, FutureExt}; +use libp2p::swarm::Stream; +use libp2p::{core::UpgradeInfo, InboundUpgrade}; +use ssz_rs::Deserialize; +use tracing::trace; + +use super::models::{ + BoundError, GetMetaData, GoodbyeReason, Ping, PooledUserOpHashesReq, PooledUserOpsByHashReq, + Status, +}; +use super::protocol::{Protocol, SUPPORTED_PROTOCOL}; +use super::{ + models::{Request, Response}, + protocol::ProtocolId, +}; +/// Max request size in bytes +const REQUEST_SIZE_MAXIMUM: u64 = 1024 * 1024; + +pub struct InboundContainer { + pub(crate) request_sender: oneshot::Sender, + pub(crate) response_receiver: oneshot::Receiver, +} + +impl UpgradeInfo for InboundContainer { + type Info = ProtocolId; + type InfoIter = Vec; + fn protocol_info(&self) -> Self::InfoIter { + SUPPORTED_PROTOCOL.clone() + } +} + +impl InboundUpgrade for InboundContainer { + type Error = BoundError; + type Output = bool; + type Future = BoxFuture<'static, Result>; + fn upgrade_inbound(self, mut socket: Stream, info: Self::Info) -> Self::Future { + async move { + let mut data = Vec::new(); + let socket_mut = &mut socket; + socket_mut + .take(REQUEST_SIZE_MAXIMUM) + .read_to_end(&mut data) + .await?; + trace!("Inbound Received {} bytes", data.len()); + // MetaData request would send empty content. + // https://github.com/eth-infinitism/bundler-spec/blob/main/p2p-specs/p2p-interface.md#getmetadata + if data.is_empty() && !matches!(info.message_name, Protocol::MetaData) { + Err(BoundError::IoError(io::Error::new( + std::io::ErrorKind::UnexpectedEof, + "No data received", + ))) + } else { + let mut decompressed_data = vec![]; + snap::read::FrameDecoder::new(data.as_slice()) + .read_to_end(&mut decompressed_data) + .map_err(BoundError::IoError)?; + let request = match info.message_name { + Protocol::Status => Request::Status(Status::deserialize(&decompressed_data)?), + Protocol::Goodbye => { + Request::GoodbyeReason(GoodbyeReason::deserialize(&decompressed_data)?) + } + Protocol::Ping => Request::Ping(Ping::deserialize(&decompressed_data)?), + Protocol::MetaData => { + Request::GetMetaData(GetMetaData::deserialize(&decompressed_data)?) + } + Protocol::PooledUserOpHashes => Request::PooledUserOpHashesReq( + PooledUserOpHashesReq::deserialize(&decompressed_data)?, + ), + Protocol::PooledUserOpsByHash => Request::PooledUserOpsByHashReq( + PooledUserOpsByHashReq::deserialize(&decompressed_data)?, + ), + }; + match self.request_sender.send(request) { + Ok(()) => {} + // It should not happen. There must be something wrong with the codes. + Err(_) => panic!( + "Expect request receiver to be alive i.e. protocol handler to be alive.", + ), + } + if let Ok(response) = self.response_receiver.await { + let ssz_encoded = response.serialize()?; + let mut wtr = snap::write::FrameEncoder::new(vec![]); + wtr.write_all(&ssz_encoded)?; + let compressed_data = wtr + .into_inner() + .map_err(|e| BoundError::IoError(e.into_error()))?; + socket_mut.write_all(&compressed_data).await?; + + socket_mut.close().await?; + // Response was sent. Indicate to handler to emit a `ResponseSent` event. + Ok(true) + } else { + socket_mut.close().await?; + Ok(false) + } + } + } + .boxed() + } +} diff --git a/crates/p2p/src/request_response/mod.rs b/crates/p2p/src/request_response/mod.rs new file mode 100644 index 00000000..ca97f56d --- /dev/null +++ b/crates/p2p/src/request_response/mod.rs @@ -0,0 +1,9 @@ +mod behaviour; +mod handler; +mod inbound; +mod models; +mod outbound; +mod protocol; + +pub use behaviour::{Behaviour, Event}; +pub use models::*; diff --git a/crates/p2p/src/request_response/models.rs b/crates/p2p/src/request_response/models.rs new file mode 100644 index 00000000..82239148 --- /dev/null +++ b/crates/p2p/src/request_response/models.rs @@ -0,0 +1,244 @@ +use std::io; + +use silius_primitives::UserOperation; +use ssz_rs::{Bitvector, List, Serialize, Vector}; + +#[derive(Debug, Clone, PartialEq)] +pub enum Request { + Status(Status), + GoodbyeReason(GoodbyeReason), + Ping(Ping), + GetMetaData(GetMetaData), + PooledUserOpHashesReq(PooledUserOpHashesReq), + PooledUserOpsByHashReq(PooledUserOpsByHashReq), +} + +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] +pub struct Status { + supported_mempool: List<[u8; 32], 1024>, +} + +#[derive(Clone, Debug, PartialEq, Default)] +pub enum GoodbyeReason { + #[default] + ClientShutdown, + IrrelevantNetwork, + Error, + Unknown(u64), +} + +impl ssz_rs::Deserialize for GoodbyeReason { + fn deserialize(reader: &[u8]) -> Result { + let value = ::deserialize(reader)?; + Ok(value.into()) + } +} + +impl ssz_rs::Serialize for GoodbyeReason { + fn serialize(&self, buffer: &mut Vec) -> Result { + let value: u64 = self.clone().into(); + value.serialize(buffer) + } +} + +impl ssz_rs::Serializable for GoodbyeReason { + fn is_variable_size() -> bool { + false + } + fn size_hint() -> usize { + ::size_hint() + } +} + +impl From for GoodbyeReason { + fn from(value: u64) -> Self { + match value { + 1 => GoodbyeReason::ClientShutdown, + 2 => GoodbyeReason::IrrelevantNetwork, + 3 => GoodbyeReason::Error, + _ => GoodbyeReason::Unknown(value), + } + } +} +impl From for u64 { + fn from(value: GoodbyeReason) -> Self { + match value { + GoodbyeReason::ClientShutdown => 1, + GoodbyeReason::IrrelevantNetwork => 2, + GoodbyeReason::Error => 3, + GoodbyeReason::Unknown(v) => v, + } + } +} + +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] +pub struct Ping { + data: u64, +} + +impl Ping { + pub fn new(data: u64) -> Self { + Self { data } + } +} + +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] +pub struct Pong { + data: u64, +} +impl Pong { + pub fn new(data: u64) -> Self { + Self { data } + } +} + +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] +pub struct PooledUserOpHashesReq { + mempool: [u8; 32], + offset: u64, +} + +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] +pub struct PooledUserOpsByHashReq { + hashes: List, 1024>, +} + +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] +pub struct MetaData { + seq_number: u64, + mempool_nets: Bitvector<32>, +} + +#[derive(Clone, Debug, PartialEq, Default)] +pub struct GetMetaData; + +impl ssz_rs::Serializable for GetMetaData { + fn is_variable_size() -> bool { + false + } + fn size_hint() -> usize { + 0 + } +} + +impl ssz_rs::Serialize for GetMetaData { + fn serialize(&self, _buffer: &mut Vec) -> Result { + Ok(0) + } +} + +impl ssz_rs::Deserialize for GetMetaData { + fn deserialize(_encoding: &[u8]) -> Result + where + Self: Sized, + { + Ok(GetMetaData) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Response { + Status(Status), + GoodbyeReason(GoodbyeReason), + Pong(Pong), + MetaData(MetaData), + PooledUserOpHashes(PooledUserOpHashes), + PooledUserOpsByHash(PooledUserOpsByHash), +} + +impl Response { + pub fn serialize(self) -> Result, ssz_rs::SerializeError> { + let mut buffer = Vec::new(); + match self { + Response::Status(status) => status.serialize(&mut buffer), + Response::GoodbyeReason(reason) => reason.serialize(&mut buffer), + Response::Pong(pong) => pong.serialize(&mut buffer), + Response::MetaData(metadata) => metadata.serialize(&mut buffer), + Response::PooledUserOpHashes(pooled_user_op_hashes) => { + pooled_user_op_hashes.serialize(&mut buffer) + } + Response::PooledUserOpsByHash(pooled_user_ops_by_hash) => { + pooled_user_ops_by_hash.serialize(&mut buffer) + } + }?; + Ok(buffer) + } +} + +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] + +pub struct PooledUserOpHashes { + more_flag: u64, + hashes: List<[u8; 32], 1024>, +} + +#[derive(ssz_rs_derive::Serializable, Clone, Debug, PartialEq, Default)] +pub struct PooledUserOpsByHash { + hashes: List, +} + +#[derive(Clone, Default)] +pub struct SSZSnappyCodec { + phantom: std::marker::PhantomData<(Req, Res)>, +} + +#[derive(Debug)] +pub enum BoundError { + IoError(io::Error), + SSZError(snap::Error), + DeserializeError(ssz_rs::DeserializeError), + SerializeError(ssz_rs::SerializeError), +} + +impl From for BoundError { + fn from(value: io::Error) -> Self { + BoundError::IoError(value) + } +} + +impl From for BoundError { + fn from(value: snap::Error) -> Self { + BoundError::SSZError(value) + } +} + +impl From for BoundError { + fn from(value: ssz_rs::DeserializeError) -> Self { + BoundError::DeserializeError(value) + } +} + +impl From for BoundError { + fn from(value: ssz_rs::SerializeError) -> Self { + BoundError::SerializeError(value) + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct RequestId(pub(crate) u64); + +#[cfg(test)] +mod tests { + use std::io::Write; + + use ssz_rs::Serialize; + + use super::Ping; + + #[test] + fn serilize() { + let ping = Ping::new(1); + let mut buffer = Vec::new(); + ping.serialize(&mut buffer).unwrap(); + let mut wtr = snap::write::FrameEncoder::new(vec![]); + wtr.write_all(&buffer).unwrap(); + let compress = wtr.into_inner().unwrap(); + let number: u64 = 1; + let mut buffer2 = Vec::new(); + number.serialize(&mut buffer2).unwrap(); + let mut wtr = snap::write::FrameEncoder::new(vec![]); + wtr.write_all(&buffer).unwrap(); + let compress2 = wtr.into_inner().unwrap(); + assert_eq!(compress, compress2); + } +} diff --git a/crates/p2p/src/request_response/outbound.rs b/crates/p2p/src/request_response/outbound.rs new file mode 100644 index 00000000..b35c9301 --- /dev/null +++ b/crates/p2p/src/request_response/outbound.rs @@ -0,0 +1,103 @@ +use std::io::{Read, Write}; + +use futures::{future::BoxFuture, AsyncReadExt, AsyncWriteExt, FutureExt}; +use libp2p::{core::UpgradeInfo, OutboundUpgrade, Stream}; +use ssz_rs::{Deserialize, Serialize}; +use tracing::{debug, trace}; + +use super::{ + models::{ + BoundError, GoodbyeReason, MetaData, Pong, PooledUserOpHashes, PooledUserOpsByHash, + Request, RequestId, Response, Status, + }, + protocol::{Protocol, ProtocolId}, +}; + +/// Max response size in bytes +const RESPONSE_SIZE_MAXIMUM: u64 = 10 * 1024 * 1024; + +#[derive(Debug)] +pub struct OutboundContainer { + pub request: Request, + pub request_id: RequestId, +} + +impl UpgradeInfo for OutboundContainer { + type Info = ProtocolId; + type InfoIter = Vec; + fn protocol_info(&self) -> Self::InfoIter { + debug!("protocol_info {:?}", self.request); + match self.request { + Request::Status(_) => vec![ProtocolId::new(Protocol::Status)], + Request::GoodbyeReason(_) => vec![ProtocolId::new(Protocol::Goodbye)], + Request::Ping(_) => vec![ProtocolId::new(Protocol::Ping)], + Request::GetMetaData(_) => vec![ProtocolId::new(Protocol::MetaData)], + Request::PooledUserOpHashesReq(_) => { + vec![ProtocolId::new(Protocol::PooledUserOpHashes)] + } + Request::PooledUserOpsByHashReq(_) => { + vec![ProtocolId::new(Protocol::PooledUserOpsByHash)] + } + } + } +} + +impl OutboundUpgrade for OutboundContainer { + type Error = BoundError; + type Output = Response; + type Future = BoxFuture<'static, Result>; + fn upgrade_outbound(self, mut socket: Stream, info: Self::Info) -> Self::Future { + async move { + trace!("Outbound {:?}!!!", self.request); + let mut buffer = Vec::new(); + let socket_mut = &mut socket; + match self.request { + Request::Status(status) => status.serialize(&mut buffer)?, + Request::GoodbyeReason(reason) => reason.serialize(&mut buffer)?, + Request::Ping(ping) => ping.serialize(&mut buffer)?, + Request::GetMetaData(meta_data) => meta_data.serialize(&mut buffer)?, + Request::PooledUserOpHashesReq(pooled_user_op_hashes_req) => { + pooled_user_op_hashes_req.serialize(&mut buffer)? + } + + Request::PooledUserOpsByHashReq(pooled_user_ops_by_hash_req) => { + pooled_user_ops_by_hash_req.serialize(&mut buffer)? + } + }; + trace!("Outbound buffer {:?}", buffer); + let mut wtr = snap::write::FrameEncoder::new(vec![]); + wtr.write_all(&buffer)?; + let compressed = wtr + .into_inner() + .map_err(|e| BoundError::IoError(e.into_error()))?; + trace!("Sending {:?} bytes", compressed.len()); + socket_mut.write_all(compressed.as_ref()).await?; + socket_mut.close().await?; + let mut comressed_response = Vec::new(); + socket_mut + .take(RESPONSE_SIZE_MAXIMUM) + .read_to_end(&mut comressed_response) + .await?; + trace!("Outbound received {:?}!!!", comressed_response); + let mut decompressed = vec![]; + snap::read::FrameDecoder::<&[u8]>::new(comressed_response.as_ref()) + .read_to_end(&mut decompressed)?; + let response = match info.message_name { + Protocol::Status => Response::Status(Status::deserialize(&decompressed)?), + Protocol::Goodbye => { + Response::GoodbyeReason(GoodbyeReason::deserialize(&decompressed)?) + } + Protocol::Ping => Response::Pong(Pong::deserialize(&decompressed)?), + Protocol::MetaData => Response::MetaData(MetaData::deserialize(&decompressed)?), + Protocol::PooledUserOpHashes => { + Response::PooledUserOpHashes(PooledUserOpHashes::deserialize(&decompressed)?) + } + Protocol::PooledUserOpsByHash => { + Response::PooledUserOpsByHash(PooledUserOpsByHash::deserialize(&decompressed)?) + } + }; + Ok(response) + } + .boxed() + } +} diff --git a/crates/p2p/src/request_response/protocol.rs b/crates/p2p/src/request_response/protocol.rs new file mode 100644 index 00000000..43e0877f --- /dev/null +++ b/crates/p2p/src/request_response/protocol.rs @@ -0,0 +1,120 @@ +use lazy_static::lazy_static; +use std::fmt::Display; +const PROTOCOL_PREFIX: &str = "/account_abstraction/req"; + +lazy_static! { + pub static ref SUPPORTED_PROTOCOL: Vec = vec![ + ProtocolId::new(Protocol::Status), + ProtocolId::new(Protocol::Goodbye), + ProtocolId::new(Protocol::Ping), + ProtocolId::new(Protocol::MetaData), + ProtocolId::new(Protocol::PooledUserOpHashes), + ProtocolId::new(Protocol::PooledUserOpsByHash), + ]; +} + +#[derive(Clone, Debug, Copy)] +pub enum Protocol { + Status, + Goodbye, + Ping, + MetaData, + PooledUserOpHashes, + PooledUserOpsByHash, +} + +impl Display for Protocol { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let result = match self { + Protocol::Status => "status", + Protocol::Goodbye => "goodbye", + Protocol::Ping => "ping", + Protocol::MetaData => "metadata", + Protocol::PooledUserOpHashes => "pooled_user_ops_hashes", + Protocol::PooledUserOpsByHash => "pooled_user_ops_by_hash", + }; + f.write_str(result) + } +} + +#[derive(Clone, Debug)] +pub struct ProtocolId { + /// The RPC message type/name. + pub message_name: Protocol, + + /// The version of the RPC. + pub version: Version, + + /// The encoding of the RPC. + pub encoding: Encoding, + + protocol_id: String, +} + +impl ProtocolId { + pub fn new(message_name: Protocol) -> Self { + let protocol_id = format!( + "{PROTOCOL_PREFIX}/{message_name}/{}/{}", + Version::V1, + Encoding::SSZSnappy + ); + Self { + message_name, + version: Version::V1, + encoding: Encoding::SSZSnappy, + protocol_id, + } + } +} + +#[derive(Clone, Debug)] +pub enum Version { + V1, +} + +impl Display for Version { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("1") + } +} + +#[derive(Clone, Debug)] +pub enum Encoding { + SSZSnappy, +} + +impl Display for Encoding { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("ssz_snappy") + } +} + +impl AsRef for ProtocolId { + fn as_ref(&self) -> &str { + &self.protocol_id + } +} + +#[cfg(test)] +mod test { + use super::SUPPORTED_PROTOCOL; + + #[test] + fn test_protoco() { + let protocols = SUPPORTED_PROTOCOL + .iter() + .map(|protocol_id| protocol_id.protocol_id.clone()) + .collect::>(); + assert_eq!( + protocols, + vec![ + "/account_abstraction/req/status/1/ssz_snappy", + "/account_abstraction/req/goodbye/1/ssz_snappy", + "/account_abstraction/req/ping/1/ssz_snappy", + "/account_abstraction/req/metadata/1/ssz_snappy", + "/account_abstraction/req/pooled_user_ops_hashes/1/ssz_snappy", + "/account_abstraction/req/pooled_user_ops_by_hash/1/ssz_snappy" + ] + ) + } +} diff --git a/crates/p2p/src/tests/enr.rs b/crates/p2p/src/tests/enr.rs new file mode 100644 index 00000000..67b9c4e2 --- /dev/null +++ b/crates/p2p/src/tests/enr.rs @@ -0,0 +1,13 @@ +use discv5::Enr; +use std::str::FromStr; + +use crate::enr::EnrExt; + +#[test] +fn enr_decoding() { + let enr_base64 = "enr:-KS4QOtEMvaUU7jVXuSONPateohOK2YfHsvLbA9S_PIaCw5HHct5Xl16mGg_JYndJEyyRwhvwwCTaFyOlyRLxscJybcFgmlkgnY0gmlwhCOy3eCPbWVtcG9vbF9zdWJuZXRziAAAAAAAAAAAiXNlY3AyNTZrMaECIuI8j36QBhWxb2DwNCdbDF3vpeKQ_CbaUpYJ9ltqfvyDdGNwghDxg3VkcIIQ8Q"; + let enr = ::from_str(enr_base64).unwrap(); + let binding = enr.multiaddr().unwrap(); + let addr = binding.first().unwrap(); + assert_eq!(format!("{addr:?}"), "\"/ip4/35.178.221.224/tcp/4337\""); +} diff --git a/crates/p2p/src/tests/mod.rs b/crates/p2p/src/tests/mod.rs new file mode 100644 index 00000000..33b204ab --- /dev/null +++ b/crates/p2p/src/tests/mod.rs @@ -0,0 +1,99 @@ +use std::{ + net::{Ipv4Addr, TcpListener}, + time::Duration, +}; + +use futures::channel::mpsc::unbounded; +use libp2p::identity::Keypair; +use silius_primitives::Chain; + +use crate::{ + config::{Config, ListenAddr}, + network::{Network, NetworkEvent}, +}; +mod enr; +mod pubsub; +mod req_rep; + +pub fn get_available_port() -> Option { + let unused_port: u16; + loop { + let socket_addr = std::net::SocketAddr::new(std::net::Ipv4Addr::LOCALHOST.into(), 0); + match TcpListener::bind(socket_addr) { + Ok(listener) => match listener.local_addr().map(|s| s.port()) { + Ok(p) => { + unused_port = p; + break; + } + Err(_) => {} + }, + Err(_) => {} + } + } + Some(unused_port) +} + +fn build_p2p_instance() -> eyre::Result { + let key = Keypair::generate_secp256k1(); + let available_port = get_available_port().unwrap(); + let config = Config { + listen_addr: crate::config::ListenAddress::Ipv4(ListenAddr { + addr: Ipv4Addr::LOCALHOST, + udp_port: available_port, + tcp_port: available_port, + }), + ipv4_addr: Some(Ipv4Addr::LOCALHOST), + ipv6_addr: None, + enr_udp4_port: Some(available_port), + enr_tcp4_port: Some(available_port), + enr_udp6_port: None, + enr_tcp6_port: None, + }; + let listen_addrs = config.listen_addr.to_multi_addr(); + let (_, rv) = unbounded(); + let (sd, _) = unbounded(); + let mut network = Network::new( + key, + config, + vec![(Chain::from(5), Default::default(), rv, sd)], + Duration::from_secs(10), + 30, + )?; + for listen_addr in listen_addrs { + println!("listen on {listen_addr:?}"); + network.listen_on(listen_addr)?; + } + Ok(network) +} + +pub async fn build_connnected_p2p_pair() -> eyre::Result<(Network, Network)> { + let mut peer1 = build_p2p_instance()?; + let mut peer2 = build_p2p_instance()?; + // let the two nodes set up listeners + let peer1_fut = async { + loop { + if let NetworkEvent::NewListenAddr(_) = peer1.next_event().await { + return; + } + } + }; + let peer2_fut = async { + loop { + if let NetworkEvent::NewListenAddr(_) = peer2.next_event().await { + return; + } + } + }; + + let joined = futures::future::join(peer1_fut, peer2_fut); + + // wait for either both nodes to listen or a timeout + tokio::select! { + _ = tokio::time::sleep(Duration::from_millis(500)) => {} + _ = joined => {} + } + let peer2_enr = peer2.local_enr(); + println!("peer1 dial peer2"); + peer1.dial(peer2_enr)?; + Ok((peer1, peer2)) +} diff --git a/crates/p2p/src/tests/pubsub.rs b/crates/p2p/src/tests/pubsub.rs new file mode 100644 index 00000000..952e3af6 --- /dev/null +++ b/crates/p2p/src/tests/pubsub.rs @@ -0,0 +1,58 @@ +use std::time::Duration; + +use silius_primitives::{Chain, UserOperationsWithEntryPoint}; + +use crate::{ + network::{NetworkEvent, PubsubMessage}, + tests::build_connnected_p2p_pair, +}; + +#[tokio::test] +async fn pubsub_msg() -> eyre::Result<()> { + let chain: Chain = 5.into(); + let (mut peer1, mut peer2) = build_connnected_p2p_pair().await?; + let mempool_id = chain.p2p_mempool_id(); + let _ = peer1.subscribe(&mempool_id)?; + let res = peer2.subscribe(&mempool_id)?; + println!("{mempool_id}, {res:?}"); + + let peer1_id = peer1.local_peer_id().clone(); + let uo_entrypoint = + UserOperationsWithEntryPoint::new(Default::default(), Default::default(), 5.into(), vec![]); + let sender_fut = async { + loop { + match peer1.next_event().await { + NetworkEvent::Subscribe { .. } => { + peer1.publish(uo_entrypoint.clone()).unwrap(); + } + _ => {} + } + } + }; + + let receiver_fut = async { + loop { + match peer2.next_event().await { + NetworkEvent::PubsubMessage { + source_peer, + message, + .. + } => { + assert_eq!(source_peer, peer1_id); + assert_eq!(message, PubsubMessage::UserOps(uo_entrypoint.clone())); + return; + } + _ => {} + } + } + }; + + tokio::select! { + _ = sender_fut => {} + _ = receiver_fut => {} + _ = tokio::time::sleep(Duration::from_secs(30)) => { + panic!("Future timed out"); + } + } + Ok(()) +} diff --git a/crates/p2p/src/tests/req_rep.rs b/crates/p2p/src/tests/req_rep.rs new file mode 100644 index 00000000..78ec5516 --- /dev/null +++ b/crates/p2p/src/tests/req_rep.rs @@ -0,0 +1,127 @@ +use std::time::Duration; + +use crate::{ + network::NetworkEvent, + request_response::{GetMetaData, Request, Response, Status}, + tests::build_connnected_p2p_pair, +}; + +async fn reqrep_case(request_case: Request, response_case: Response) -> eyre::Result<()> { + let (mut peer1, mut peer2) = build_connnected_p2p_pair().await?; + let peer1_id = peer1.local_peer_id().clone(); + let peer2_id = peer2.local_peer_id().clone(); + + let sender_fut = async { + loop { + match peer1.next_event().await { + NetworkEvent::PeerConnected(_) => { + println!("Send request "); + peer1.send_request(&peer2_id, request_case.clone()); + } + NetworkEvent::RequestMessage { .. } => { + panic!("Unexpected request") + } + NetworkEvent::ResponseMessage { peer_id, response } => { + println!("receive response"); + assert_eq!(peer2_id, peer_id); + assert_eq!(response, response_case.clone()); + return; + } + + _ => {} + } + } + }; + + let receiver_fut = async { + loop { + match peer2.next_event().await { + NetworkEvent::RequestMessage { + request, + response_sender, + peer_id, + } => { + println!("received request"); + assert_eq!(request, request_case.clone()); + assert_eq!(peer1_id, peer_id); + peer2 + .send_response(response_sender, response_case.clone()) + .unwrap(); + } + NetworkEvent::ResponseMessage { .. } => { + panic!("Unexpected response") + } + _ => {} + } + } + }; + + tokio::select! { + _ = sender_fut => {} + _ = receiver_fut => {} + _ = tokio::time::sleep(Duration::from_secs(20)) => { + panic!("Future timed out"); + } + } + Ok(()) +} + +#[tokio::test] +async fn reqrep_status() -> eyre::Result<()> { + reqrep_case( + Request::Status(Status::default()), + Response::Status(Status::default()), + ) + .await?; + Ok(()) +} + +#[tokio::test] +async fn reqrep_goodbye() -> eyre::Result<()> { + reqrep_case( + Request::GoodbyeReason(Default::default()), + Response::GoodbyeReason(Default::default()), + ) + .await?; + Ok(()) +} + +#[tokio::test] +async fn reqrep_ping_pong() -> eyre::Result<()> { + reqrep_case( + Request::Ping(Default::default()), + Response::Pong(Default::default()), + ) + .await?; + Ok(()) +} + +#[tokio::test] +async fn reqrep_metadata() -> eyre::Result<()> { + reqrep_case( + Request::GetMetaData(GetMetaData), + Response::MetaData(Default::default()), + ) + .await?; + Ok(()) +} + +#[tokio::test] +async fn reqrep_pooled_userops() -> eyre::Result<()> { + reqrep_case( + Request::PooledUserOpHashesReq(Default::default()), + Response::PooledUserOpHashes(Default::default()), + ) + .await?; + Ok(()) +} + +#[tokio::test] +async fn reqrep_pooled_userops_by_hash() -> eyre::Result<()> { + reqrep_case( + Request::PooledUserOpsByHashReq(Default::default()), + Response::PooledUserOpsByHash(Default::default()), + ) + .await?; + Ok(()) +} diff --git a/crates/p2p/src/utils.rs b/crates/p2p/src/utils.rs new file mode 100644 index 00000000..e69de29b diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 64ba0fc2..71966679 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -17,13 +17,13 @@ ethers = { workspace = true } expanded-pathbuf = { workspace = true } eyre = { workspace = true } futures-util = { workspace = true } -lazy_static = "1.4.0" +lazy_static = { workspace = true } rustc-hex = "^2.0.1" serde = "1" serde-hex = "0.1.0" serde_json = { workspace = true } -ssz_rs = "0.8.0" -ssz_rs_derive = "0.8.0" +ssz_rs = { workspace = true } +ssz_rs_derive = { workspace = true } strum = "0.24" strum_macros = "0.24" tokio = { workspace = true } diff --git a/crates/primitives/src/chain.rs b/crates/primitives/src/chain.rs index 51fcd1e5..ce487c11 100644 --- a/crates/primitives/src/chain.rs +++ b/crates/primitives/src/chain.rs @@ -30,6 +30,27 @@ impl Chain { Chain::Custom(_) => "custom".to_string(), } } + + pub fn p2p_mempool_id(&self) -> String { + match self { + Chain::Named(chain) => match chain { + ethers::types::Chain::Goerli => { + "QmTmj4cizhWpEFCCqk5dP67yws7R2PPgCtb2bd2RgVPCbF".to_string() + } + ethers::types::Chain::Sepolia => { + "QmdDwVFoEEcgv5qnaTB8ncnXGMnqrhnA5nYpRr4ouWe4AT".to_string() + } + ethers::types::Chain::PolygonMumbai => { + "QmQfRyE9iVTBqZ17hPSP4tuMzaez83Y5wD874ymyRtj9VE".to_string() + } + ethers::types::Chain::Dev => { + "Qmf7P3CuhzSbpJa8LqXPwRzfPqsvoQ6RG7aXvthYTzGxb2".to_string() + } + _ => panic!("chain {chain:?} p2p mempool id is not supported"), + }, + Chain::Custom(id) => panic!("custom chain {id:?} p2p mempool id is not supported"), + } + } } impl From for Chain { diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 04f5edaa..bf6e5917 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -3,6 +3,7 @@ pub mod bundler; pub mod chain; pub mod consts; +mod p2p; pub mod provider; pub mod reputation; pub mod sanity; @@ -14,6 +15,7 @@ mod wallet; pub use bundler::Mode as BundlerMode; pub use chain::Chain; +pub use p2p::{PooledUserOps, UserOperationsWithEntryPoint}; pub use uopool::Mode as UoPoolMode; pub use user_operation::{ UserOperation, UserOperationByHash, UserOperationGasEstimation, UserOperationHash, diff --git a/crates/primitives/src/p2p.rs b/crates/primitives/src/p2p.rs new file mode 100644 index 00000000..e38c4477 --- /dev/null +++ b/crates/primitives/src/p2p.rs @@ -0,0 +1,60 @@ +use ethers::types::{Address, U256 as EthersU256}; +use ssz_rs::{List, Vector, U256}; +use ssz_rs_derive::Serializable; + +use crate::{Chain, UserOperation}; + +#[derive(Clone, Debug, Default, Serializable, PartialEq)] +pub struct UserOperationsWithEntryPoint { + // entrypoint address + entrypoint_contract: Vector, + verified_at_block_hash: U256, + chain_id: U256, + user_operations: List, +} + +impl UserOperationsWithEntryPoint { + pub fn new( + entrypoint_address: Address, + verified_at_block_hash: EthersU256, + chain_id: EthersU256, + user_operations: Vec, + ) -> Self { + let mut buf: [u8; 32] = [0; 32]; + verified_at_block_hash.to_little_endian(&mut buf); + let verified_at_block_hash = U256::from_bytes_le(buf); + let mut buf: [u8; 32] = [0; 32]; + chain_id.to_little_endian(&mut buf); + let chain_id = U256::from_bytes_le(buf); + Self { + entrypoint_contract: >::try_from(entrypoint_address.as_bytes().to_vec()) + .expect("entrypoint address is valid"), + verified_at_block_hash, + chain_id, + // FIXME: should have a bound check here or return Err + user_operations: >::try_from(user_operations) + .expect("Too many user operations"), + } + } + + pub fn user_ops(self) -> Vec { + self.user_operations.to_vec() + } + + pub fn entrypoint_address(&self) -> Address { + Address::from_slice(&self.entrypoint_contract) + } + + pub fn chain(&self) -> Chain { + Chain::from(EthersU256::from_little_endian( + self.chain_id.to_bytes_le().as_ref(), + )) + } +} + +#[derive(Clone, Debug, Default, Serializable)] +pub struct PooledUserOps { + mempool_id: Vector, + more_flag: u64, + user_operations: List, +} diff --git a/crates/primitives/src/user_operation.rs b/crates/primitives/src/user_operation.rs index 3e5896cd..abe2f147 100644 --- a/crates/primitives/src/user_operation.rs +++ b/crates/primitives/src/user_operation.rs @@ -7,13 +7,11 @@ use ethers::{ }; use rustc_hex::FromHexError; use serde::{Deserialize, Serialize}; -use ssz_rs::Sized; -use std::{ - ops::{AddAssign, Deref}, - slice::Windows, - str::FromStr, -}; - +use ssz_rs::List; +use std::{ops::Deref, slice::Windows, str::FromStr}; +const BYTES_PER_LENGTH_OFFSET: usize = 4; +/// This could be increased if we found bigger bytes, the propper value is not sure right now. +const MAXIMUM_SSZ_BYTES_LENGTH: usize = 1024; /// Transaction type for ERC-4337 account abstraction #[derive( Clone, @@ -418,131 +416,29 @@ pub struct UserOperationGasEstimation { pub call_gas_limit: U256, } -fn ssz_pack_u256( - fixed: &mut Vec>>, - fixed_lengths_sum: &mut usize, - variable_lengths: &mut Vec, - value: U256, -) -> Result<(), ssz_rs::SerializeError> { - let mut element_buffer = Vec::with_capacity(32); - <[u64; 4] as ssz_rs::Serialize>::serialize(&value.0, &mut element_buffer)?; - fixed_lengths_sum.add_assign(32); - fixed.push(Some(element_buffer)); - variable_lengths.push(0); - Ok(()) -} - -fn ssz_pack_bytes( - fixed: &mut Vec>>, - fixed_lengths_sum: &mut usize, - variable: &mut Vec>, - variable_lengths: &mut Vec, - value: Bytes, -) { - let size = value.len(); - let mut element: Vec = Vec::with_capacity(size); - element.extend(value.iter()); - fixed.push(None); - fixed_lengths_sum.add_assign(4); - variable_lengths.push(size); - variable.push(element); -} - -impl ssz_rs::Sized for UserOperation { - fn is_variable_size() -> bool { - true - } - fn size_hint() -> usize { - 0 - } +fn btyes_to_list( + value: &Bytes, +) -> Result, ssz_rs::SerializeError> { + let data = value.to_vec(); + List::::try_from(data) + .map_err(|(data, _)| ssz_rs::SerializeError::MaximumEncodedLengthReached(data.len())) } impl ssz_rs::Serialize for UserOperation { fn serialize(&self, buffer: &mut Vec) -> Result { - let mut fixed = Vec::new(); - let mut variable = Vec::new(); - let mut variable_lengths = Vec::new(); - let mut fixed_lengths_sum = 0usize; - - // sender - let mut element_buffer = Vec::with_capacity(20); - <[u8; 20] as ssz_rs::Serialize>::serialize(&self.sender.0, &mut element_buffer)?; - fixed_lengths_sum += element_buffer.len(); - fixed.push(Some(element_buffer)); - variable_lengths.push(0); - - ssz_pack_u256( - &mut fixed, - &mut fixed_lengths_sum, - &mut variable_lengths, - self.nonce, - )?; - ssz_pack_bytes( - &mut fixed, - &mut fixed_lengths_sum, - &mut variable, - &mut variable_lengths, - self.init_code.clone(), - ); - ssz_pack_bytes( - &mut fixed, - &mut fixed_lengths_sum, - &mut variable, - &mut variable_lengths, - self.call_data.clone(), - ); - ssz_pack_u256( - &mut fixed, - &mut fixed_lengths_sum, - &mut variable_lengths, - self.call_gas_limit, - )?; - ssz_pack_u256( - &mut fixed, - &mut fixed_lengths_sum, - &mut variable_lengths, - self.verification_gas_limit, - )?; - ssz_pack_u256( - &mut fixed, - &mut fixed_lengths_sum, - &mut variable_lengths, - self.pre_verification_gas, - )?; - ssz_pack_u256( - &mut fixed, - &mut fixed_lengths_sum, - &mut variable_lengths, - self.max_fee_per_gas, - )?; - ssz_pack_u256( - &mut fixed, - &mut fixed_lengths_sum, - &mut variable_lengths, - self.max_priority_fee_per_gas, - )?; - ssz_pack_bytes( - &mut fixed, - &mut fixed_lengths_sum, - &mut variable, - &mut variable_lengths, - self.paymaster_and_data.clone(), - ); - ssz_pack_bytes( - &mut fixed, - &mut fixed_lengths_sum, - &mut variable, - &mut variable_lengths, - self.signature.clone(), - ); - - ssz_rs::__internal::serialize_composite_from_components( - fixed, - variable, - variable_lengths, - fixed_lengths_sum, - buffer, - ) + let mut serializer = ssz_rs::__internal::Serializer::default(); + serializer.with_element(&self.sender.0)?; + serializer.with_element(&self.nonce.0)?; + serializer.with_element(&btyes_to_list(&self.init_code)?)?; + serializer.with_element(&btyes_to_list(&self.call_data)?)?; + serializer.with_element(&self.call_gas_limit.0)?; + serializer.with_element(&self.verification_gas_limit.0)?; + serializer.with_element(&self.pre_verification_gas.0)?; + serializer.with_element(&self.max_fee_per_gas.0)?; + serializer.with_element(&self.max_priority_fee_per_gas.0)?; + serializer.with_element(&btyes_to_list(&self.paymaster_and_data)?)?; + serializer.with_element(&btyes_to_list(&self.signature)?)?; + serializer.serialize(buffer) } } @@ -583,6 +479,7 @@ fn ssz_unpack_bytes( let bytes_data = Bytes::from_iter(encoding[start..end].iter()); Ok((bytes_data, end - start)) } + impl ssz_rs::Deserialize for UserOperation { fn deserialize(encoding: &[u8]) -> Result where @@ -593,7 +490,7 @@ impl ssz_rs::Deserialize for UserOperation { let mut container = Self::default(); let byte_read = { - let encoded_length = <[u8; 20] as ssz_rs::Sized>::size_hint(); + let encoded_length = <[u8; 20] as ssz_rs::Serializable>::size_hint(); let end = start + encoded_length; let target = encoding @@ -686,6 +583,15 @@ impl ssz_rs::Deserialize for UserOperation { } } +impl ssz_rs::Serializable for UserOperation { + fn is_variable_size() -> bool { + true + } + + fn size_hint() -> usize { + 0 + } +} #[cfg(test)] mod tests { diff --git a/crates/uopool/Cargo.toml b/crates/uopool/Cargo.toml index fbad6289..af71b7b0 100644 --- a/crates/uopool/Cargo.toml +++ b/crates/uopool/Cargo.toml @@ -16,6 +16,7 @@ educe = { version = "0.4", features = ["Debug", "Default"] } enumset = "1.1.2" ethers = { workspace = true } eyre = { workspace = true } +futures = "0.3.28" futures-util = { workspace = true } page_size = "0.5.0" parking_lot = { workspace = true } diff --git a/crates/uopool/src/builder.rs b/crates/uopool/src/builder.rs index 4c233a40..8f1ba696 100644 --- a/crates/uopool/src/builder.rs +++ b/crates/uopool/src/builder.rs @@ -7,6 +7,7 @@ use ethers::{ types::{Address, H256, U256}, }; use eyre::format_err; +use futures::channel::mpsc::UnboundedSender; use futures_util::StreamExt; use silius_contracts::EntryPoint; use silius_primitives::{ @@ -41,6 +42,8 @@ where whitelist: Vec
, mempool: MempoolBox, reputation: ReputationBox, R, E>, + // It would be None if p2p is not enabled + publish_sd: Option>, } impl UoPoolBuilder @@ -62,6 +65,7 @@ where whitelist: Vec
, mempool: P, reputation: R, + publish_sd: Option>, ) -> Self { // sets mempool let mempool = MempoolBox::::new(mempool); @@ -90,6 +94,7 @@ where whitelist, mempool, reputation, + publish_sd, } } @@ -215,6 +220,7 @@ where self.reputation.clone(), self.max_verification_gas, self.chain, + self.publish_sd.as_ref().cloned(), ) } } diff --git a/crates/uopool/src/uopool.rs b/crates/uopool/src/uopool.rs index 6fd950df..59701207 100644 --- a/crates/uopool/src/uopool.rs +++ b/crates/uopool/src/uopool.rs @@ -14,6 +14,7 @@ use ethers::{ types::{Address, BlockNumber, U256}, }; use eyre::format_err; +use futures::channel::mpsc::UnboundedSender; use silius_contracts::{ entry_point::{EntryPointErr, UserOperationEventFilter}, utils::parse_from_input_data, @@ -58,6 +59,8 @@ where pub max_verification_gas: U256, // The [EIP-155](https://eips.ethereum.org/EIPS/eip-155) chain ID pub chain: Chain, + // It would be None if p2p is not enabled + publish_sd: Option>, } impl, P, R, E> UoPool @@ -87,6 +90,7 @@ where reputation: ReputationBox, R, E>, max_verification_gas: U256, chain: Chain, + publish_sd: Option>, ) -> Self { Self { id: mempool_id(&entry_point.address(), &chain.id().into()), @@ -96,6 +100,7 @@ where reputation, max_verification_gas, chain, + publish_sd, } } @@ -213,7 +218,10 @@ where if let Some(uo_hash) = res.prev_hash { self.remove_user_operation(&uo_hash); } - + if let Some(ref sd) = self.publish_sd { + sd.unbounded_send((uo.clone(), res.verified_block)) + .expect("Failed to send user operation to publish channel") + }; match self.mempool.add( uo.clone(), &self.entry_point.address(), diff --git a/crates/uopool/src/validate/mod.rs b/crates/uopool/src/validate/mod.rs index c32c59ad..adfab6b7 100644 --- a/crates/uopool/src/validate/mod.rs +++ b/crates/uopool/src/validate/mod.rs @@ -34,6 +34,8 @@ pub struct UserOperationValidationOutcome { // Simulation trace pub code_hashes: Option>, pub storage_map: Option, + // the block which the user operation is verified on + pub verified_block: U256, } /// The mode in which the user operation validator is running. diff --git a/crates/uopool/src/validate/validator.rs b/crates/uopool/src/validate/validator.rs index d78405ba..90a534e9 100644 --- a/crates/uopool/src/validate/validator.rs +++ b/crates/uopool/src/validate/validator.rs @@ -22,7 +22,7 @@ use crate::{ use enumset::EnumSet; use ethers::{ providers::Middleware, - types::{GethTrace, U256}, + types::{BlockNumber, GethTrace, U256}, }; use silius_contracts::{ entry_point::{EntryPointErr, SimulateValidationResult}, @@ -30,10 +30,11 @@ use silius_contracts::{ EntryPoint, }; use silius_primitives::{ - reputation::ReputationEntry, simulation::SimulationCheckError, uopool::ValidationError, Chain, - UserOperation, + reputation::ReputationEntry, sanity::SanityCheckError, simulation::SimulationCheckError, + uopool::ValidationError, Chain, UserOperation, }; use std::fmt::{Debug, Display}; +use tracing::debug; /// Standard implementation of [UserOperationValidator](UserOperationValidator). pub struct StandardUserOperationValidator @@ -294,7 +295,7 @@ where if let Some(uo) = mempool.get_prev_by_sender(uo) { out.prev_hash = Some(uo.hash(&self.entry_point.address(), &self.chain.id().into())); } - + debug!("Simulate user operation from {:?}", uo.sender); let sim_res = self.simulate_validation(uo).await?; if !self.simulation_checks.is_empty() @@ -315,9 +316,23 @@ where out.pre_fund = extract_pre_fund(&sim_res); out.verification_gas_limit = extract_verification_gas_limit(&sim_res); + let block_number = self + .entry_point + .eth_client() + .get_block(BlockNumber::Latest) + .await + .map_err(|e| { + ValidationError::Sanity(SanityCheckError::MiddlewareError { + message: e.to_string(), + }) + })? + .expect("block should exist"); + out.verified_block = U256::from(block_number.hash.expect("block hash should exist").0); + if !self.simulation_trace_checks.is_empty() && mode.contains(UserOperationValidatorMode::SimulationTrace) { + debug!("Simulate user operation with trace from {:?}", uo.sender); let geth_trace = self.simulate_validation_trace(uo).await?; let js_trace: JsTracerFrame = JsTracerFrame::try_from(geth_trace).map_err(|error| { SimulationCheckError::Validation { diff --git a/examples/storage/Cargo.toml b/examples/storage/Cargo.toml index be857998..1594e693 100644 --- a/examples/storage/Cargo.toml +++ b/examples/storage/Cargo.toml @@ -13,6 +13,7 @@ AA (ERC-4337) bundler examples - storage [dependencies] ethers = { workspace = true } eyre = { workspace = true } +futures = "0.3.28" silius-primitives = { path = "../../crates/primitives" } silius-uopool = { path = "../../crates/uopool" } tempdir = "0.3.7" diff --git a/examples/storage/examples/database.rs b/examples/storage/examples/database.rs index 5fcc407f..5583c415 100644 --- a/examples/storage/examples/database.rs +++ b/examples/storage/examples/database.rs @@ -1,5 +1,8 @@ use ethers::types::{Address, U256}; -use silius_primitives::{consts::entry_point::ADDRESS, provider::create_http_provider, Chain}; +use futures::channel::mpsc::unbounded; +use silius_primitives::{ + consts::entry_point::ADDRESS, provider::create_http_provider, Chain, UserOperation, +}; use silius_uopool::{init_env, DatabaseMempool, DatabaseReputation, UoPoolBuilder, WriteMap}; use std::{env, str::FromStr, sync::Arc}; use tempdir::TempDir; @@ -14,7 +17,7 @@ async fn main() -> eyre::Result<()> { let env = Arc::new(init_env::(dir.into_path()).expect("Init mdbx failed")); env.create_tables() .expect("Create mdbx database tables failed"); - + let (waiting_to_pub_sd, _) = unbounded::<(UserOperation, U256)>(); // creating uopool with builder let builder = UoPoolBuilder::new( false, // whether uoppol is in unsafe mode @@ -27,6 +30,7 @@ async fn main() -> eyre::Result<()> { vec![], // whitelisted entities DatabaseMempool::new(env.clone()), // database mempool of user operations DatabaseReputation::new(env), // database reputation + Some(waiting_to_pub_sd), // waiting to publish user operations, for p2p part ); // optional: subscription to block updates and reputation updates diff --git a/examples/storage/examples/memory.rs b/examples/storage/examples/memory.rs index a0e50129..3b25cf6e 100644 --- a/examples/storage/examples/memory.rs +++ b/examples/storage/examples/memory.rs @@ -1,5 +1,8 @@ use ethers::types::{Address, U256}; -use silius_primitives::{consts::entry_point::ADDRESS, provider::create_http_provider, Chain}; +use futures::channel::mpsc::unbounded; +use silius_primitives::{ + consts::entry_point::ADDRESS, provider::create_http_provider, Chain, UserOperation, +}; use silius_uopool::{MemoryMempool, MemoryReputation, UoPoolBuilder}; use std::{env, str::FromStr, sync::Arc}; @@ -7,7 +10,7 @@ use std::{env, str::FromStr, sync::Arc}; async fn main() -> eyre::Result<()> { // uopool needs connection to the execution client let provider_url = env::var("PROVIDER_URL").unwrap(); - + let (waiting_to_pub_sd, _) = unbounded::<(UserOperation, U256)>(); // creating uopool with builder let builder = UoPoolBuilder::new( false, // whether uoppol is in unsafe mode @@ -20,6 +23,7 @@ async fn main() -> eyre::Result<()> { vec![], // whitelisted entities MemoryMempool::default(), // in-memory mempool of user operations MemoryReputation::default(), // in-memory reputation + Some(waiting_to_pub_sd), // waiting to publish user operations, for p2p part ); // optional: subscription to block updates and reputation updates diff --git a/tests/Cargo.toml b/tests/Cargo.toml index d4eeb43d..2d1e5783 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -19,5 +19,8 @@ silius-uopool = { path = "../crates/uopool" } tempdir = "0.3.7" tokio = { workspace = true } +[dev-dependencies] +futures = "0.3.28" + [package.metadata.cargo-udeps.ignore] normal = ["silius-contracts", "silius-primitives", "silius-uopool"] diff --git a/tests/src/simulation_tests.rs b/tests/src/simulation_tests.rs index 1f945a63..d355d81f 100644 --- a/tests/src/simulation_tests.rs +++ b/tests/src/simulation_tests.rs @@ -19,6 +19,7 @@ use ethers::{ providers::Middleware, types::{Bytes, U256}, }; +use futures::channel::mpsc::unbounded; use silius_contracts::EntryPoint; use silius_primitives::consts::entities::{FACTORY, PAYMASTER, SENDER}; use silius_primitives::reputation::ReputationEntry; @@ -144,7 +145,7 @@ async fn setup() -> eyre::Result { .with_simulation_trace_check(StorageAccess) .with_simulation_trace_check(CallStack) .with_simulation_trace_check(CodeHashes); - + let (waiting_to_pub_sd, _) = unbounded::<(UserOperation, U256)>(); let pool = UoPool::< ClientType, StandardUserOperationValidator< @@ -163,6 +164,7 @@ async fn setup() -> eyre::Result { ReputationBox::new(reputation), 3000000_u64.into(), c, + Some(waiting_to_pub_sd), ); Ok(Context {