diff --git a/Cargo.lock b/Cargo.lock index 5e22c9742a..b969f10c37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1334,9 +1334,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.21" +version = "1.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" +checksum = "32db95edf998450acc7881c932f94cd9b05c87b4b2599e8bab064753da4acfd1" dependencies = [ "jobserver", "libc", @@ -1462,9 +1462,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.37" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000" dependencies = [ "clap_builder", "clap_derive", @@ -1472,9 +1472,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120" dependencies = [ "anstream", "anstyle", @@ -2021,11 +2021,11 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.6" +version = "3.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697b5419f348fd5ae2478e8018cb016c00a5881c7f46c717de98ffd135a5651c" +checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73" dependencies = [ - "nix 0.29.0", + "nix 0.30.1", "windows-sys 0.59.0", ] @@ -2402,8 +2402,7 @@ dependencies = [ [[package]] name = "discv5" version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4b4e7798d2ff74e29cee344dc490af947ae657d6ab5273dde35d58ce06a4d71" +source = "git+https://github.com/sigp/discv5?branch=mallory#fd2441ca1fe430618eaeb0b7011dec175ee74fd1" dependencies = [ "aes 0.8.4", "aes-gcm", @@ -3732,9 +3731,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "js-sys", @@ -4399,21 +4398,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -4422,31 +4422,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -4454,67 +4434,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "2549ca8c7241c82f59c80ba2a6f415d931c5b58d24fb8412caa1a1f02c49139a" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" +checksum = "8197e866e47b68f8f7d95249e172903bec06004b18b2937f1095d40a0c57de04" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -4534,9 +4501,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -4845,7 +4812,7 @@ version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", "libc", ] @@ -5032,12 +4999,12 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.53.0", ] [[package]] @@ -5160,13 +5127,14 @@ dependencies = [ [[package]] name = "libp2p-gossipsub" version = "0.49.0" -source = "git+https://github.com/sigp/rust-libp2p.git?rev=61b2820#61b2820de7a3fab5ae5e1362c4dfa93bd7c41e98" +source = "git+https://github.com/sigp/rust-libp2p.git?branch=mallory-test#99360a194440d0d7d251d5971baabdbc675dd3be" dependencies = [ "async-channel 2.3.1", "asynchronous-codec", "base64 0.22.1", "byteorder", "bytes", + "delay_map", "either", "fnv", "futures", @@ -5634,9 +5602,9 @@ checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lmdb-rkv" @@ -5747,6 +5715,12 @@ dependencies = [ "hashbrown 0.15.3", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lru_cache" version = "0.1.0" @@ -6286,9 +6260,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.29.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ "bitflags 2.9.0", "cfg-if", @@ -6936,6 +6910,15 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -7281,9 +7264,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.7" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" dependencies = [ "bytes", "cfg_aliases", @@ -7302,12 +7285,13 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcbafbbdbb0f638fe3f35f3c56739f77a8a1d070cb25603226c83339b391472b" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" dependencies = [ "bytes", - "getrandom 0.3.2", + "getrandom 0.3.3", + "lru-slab", "rand 0.9.1", "ring", "rustc-hash 2.1.1", @@ -7445,7 +7429,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] @@ -7930,7 +7914,7 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.2", + "rustls-webpki 0.103.3", "subtle", "zeroize", ] @@ -7986,9 +7970,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.2" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7149975849f1abb3832b246010ef62ccc80d3a76169517ada7188252b9cfb437" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "ring", "rustls-pki-types", @@ -8987,12 +8971,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.19.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", - "getrandom 0.3.2", + "getrandom 0.3.3", "once_cell", "rustix 1.0.7", "windows-sys 0.59.0", @@ -9193,9 +9177,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -9769,12 +9753,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -9803,7 +9781,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] @@ -10569,13 +10547,29 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -10594,6 +10588,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -10612,6 +10612,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -10630,12 +10636,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -10654,6 +10672,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -10672,6 +10696,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -10690,6 +10720,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -10708,6 +10744,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.5.40" @@ -10753,17 +10795,11 @@ dependencies = [ "quote", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "ws_stream_wasm" @@ -10910,9 +10946,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -10922,9 +10958,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", @@ -10995,10 +11031,21 @@ dependencies = [ ] [[package]] -name = "zerovec" -version = "0.10.4" +name = "zerotrie" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -11007,9 +11054,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 6a7b2f610e..4e4a8b7f61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,9 +131,9 @@ deposit_contract = { path = "common/deposit_contract" } derivative = "2" directory = { path = "common/directory" } dirs = "3" -discv5 = { version = "0.9", features = ["libp2p"] } doppelganger_service = { path = "validator_client/doppelganger_service" } either = "1.9" +discv5 = { git= "https://github.com/sigp/discv5", features = ["libp2p"], branch = "mallory" } env_logger = "0.9" environment = { path = "lighthouse/environment" } eth2 = { path = "common/eth2" } @@ -159,8 +159,8 @@ fork_choice = { path = "consensus/fork_choice" } fs2 = "0.4" futures = "0.3" genesis = { path = "beacon_node/genesis" } -gossipsub = { package = "libp2p-gossipsub", git = "https://github.com/sigp/rust-libp2p.git", rev = "61b2820" } graffiti_file = { path = "validator_client/graffiti_file" } +gossipsub = { package = "libp2p-gossipsub", git = "https://github.com/sigp/rust-libp2p.git", branch = "mallory" } hashlink = "0.9.0" health_metrics = { path = "common/health_metrics" } hex = "0.4" diff --git a/beacon_node/lighthouse_network/src/config.rs b/beacon_node/lighthouse_network/src/config.rs index bd72a5d51a..66142991cf 100644 --- a/beacon_node/lighthouse_network/src/config.rs +++ b/beacon_node/lighthouse_network/src/config.rs @@ -35,7 +35,7 @@ pub struct Config { pub network_dir: PathBuf, /// IP addresses to listen on. - pub(crate) listen_addresses: ListenAddress, + pub listen_addresses: ListenAddress, /// The address to broadcast to peers about which address we are listening on. None indicates /// that no discovery address has been set in the CLI args. @@ -142,6 +142,9 @@ pub struct Config { /// Flag for advertising a fake CGC to peers for testing ONLY. pub advertise_false_custody_group_count: Option, + /// Extra configurations for Mallory. + #[serde(skip)] + pub attacker_config: crate::MalloryConfig, } impl Config { @@ -367,6 +370,7 @@ impl Default for Config { inbound_rate_limiter_config: None, idontwant_message_size_threshold: DEFAULT_IDONTWANT_MESSAGE_SIZE_THRESHOLD, advertise_false_custody_group_count: None, + attacker_config: Default::default(), } } } diff --git a/beacon_node/lighthouse_network/src/discovery/mod.rs b/beacon_node/lighthouse_network/src/discovery/mod.rs index ad4241c5b7..b8711bc97d 100644 --- a/beacon_node/lighthouse_network/src/discovery/mod.rs +++ b/beacon_node/lighthouse_network/src/discovery/mod.rs @@ -241,14 +241,8 @@ impl Discovery { quic = bootnode_enr.quic4(), "Adding node to routing table" ); - let repr = bootnode_enr.to_string(); - let _ = discv5.add_enr(bootnode_enr).map_err(|e| { - error!( - addr = repr, - error = e.to_string(), - "Could not add peer to the local routing table" - ) - }); + // Error is suppressed for mallory + let _ = discv5.add_enr(bootnode_enr); } // Start the discv5 service and obtain an event stream diff --git a/beacon_node/lighthouse_network/src/lib.rs b/beacon_node/lighthouse_network/src/lib.rs index 40fdd71b38..96cb055102 100644 --- a/beacon_node/lighthouse_network/src/lib.rs +++ b/beacon_node/lighthouse_network/src/lib.rs @@ -2,11 +2,12 @@ /// all required libp2p functionality. /// /// This crate builds and manages the libp2p services required by the beacon node. -mod config; +pub mod config; pub mod service; pub mod discovery; pub mod listen_addr; +mod mallory_config; pub mod metrics; pub mod peer_manager; pub mod rpc; @@ -38,6 +39,12 @@ impl FromStr for PeerIdSerialized { } } +impl From for PeerIdSerialized { + fn from(peer_id: PeerId) -> Self { + PeerIdSerialized(peer_id) + } +} + impl Serialize for PeerIdSerialized { fn serialize(&self, serializer: S) -> Result where @@ -111,8 +118,9 @@ pub use discovery::{CombinedKeyExt, EnrExt, Eth2Enr}; pub use discv5; pub use gossipsub::{IdentTopic, MessageAcceptance, MessageId, Topic, TopicHash}; pub use libp2p; -pub use libp2p::{core::ConnectedPoint, PeerId, Swarm}; +pub use libp2p::{core::ConnectedPoint, identity::Keypair, PeerId, Swarm}; pub use libp2p::{multiaddr, Multiaddr}; +pub use mallory_config::MalloryConfig; pub use metrics::scrape_discovery_metrics; pub use peer_manager::{ peerdb::client::Client, @@ -120,6 +128,7 @@ pub use peer_manager::{ peerdb::PeerDB, ConnectionDirection, PeerConnectionStatus, PeerInfo, PeerManager, SyncInfo, SyncStatus, }; +pub use service::Behaviour; // pub use service::{load_private_key, Context, Libp2pEvent, Service, NETWORK_KEY_FILENAME}; pub use service::api_types::Response; pub use service::utils::*; diff --git a/beacon_node/lighthouse_network/src/mallory_config.rs b/beacon_node/lighthouse_network/src/mallory_config.rs new file mode 100644 index 0000000000..450a40b72d --- /dev/null +++ b/beacon_node/lighthouse_network/src/mallory_config.rs @@ -0,0 +1,37 @@ +/// Every configuration needed for Mallory. +#[derive(Debug, Clone)] +pub struct MalloryConfig { + /* Peer manager stuff */ + /// Ping inbound peers this often (in seconds) instead of the default `PING_INTERVAL_INBOUND`. + pub inbound_peers_ping: Option, + /// Ping outbound peers this often (in seconds) instead of the default `PING_INTERVAL_OUTBOUND`. + pub outbound_peers_ping: Option, + /// Status peers this often (in seconds) instead of the default `STATUS_INTERVAL`. + pub status_interval: Option, + + /* RPC stuff */ + /// Duration in seconds after which an inbound connection with a peer times out instead of the + /// default `RESPONSE_TIMEOUT`. + pub inbound_rpc_timeout: Option, + + /// Duration in seconds after which an outbound connection with a peer times out instead of the + /// default `RESPONSE_TIMEOUT`. + pub outbound_rpc_timeout: Option, + + /* Behaviour Stuff */ + // Allow the user to handle a ping request + pub user_handle_ping: bool, +} + +impl Default for MalloryConfig { + fn default() -> Self { + Self { + inbound_peers_ping: None, + outbound_peers_ping: None, + status_interval: None, + inbound_rpc_timeout: None, + outbound_rpc_timeout: None, + user_handle_ping: false, + } + } +} diff --git a/beacon_node/lighthouse_network/src/peer_manager/peerdb/client.rs b/beacon_node/lighthouse_network/src/peer_manager/peerdb/client.rs index 9450584d6f..389572878a 100644 --- a/beacon_node/lighthouse_network/src/peer_manager/peerdb/client.rs +++ b/beacon_node/lighthouse_network/src/peer_manager/peerdb/client.rs @@ -3,11 +3,11 @@ //! Currently using identify to fingerprint. use libp2p::identify::Info as IdentifyInfo; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use strum::{AsRefStr, EnumIter, IntoStaticStr}; /// Various client and protocol information related to a node. -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Client { /// The client's name (Ex: lighthouse, prism, nimbus, etc) pub kind: ClientKind, @@ -21,7 +21,9 @@ pub struct Client { pub agent_string: Option, } -#[derive(Clone, Copy, Debug, Serialize, PartialEq, AsRefStr, IntoStaticStr, EnumIter)] +#[derive( + Clone, Copy, Debug, Serialize, PartialEq, AsRefStr, IntoStaticStr, EnumIter, Deserialize, +)] pub enum ClientKind { /// A lighthouse node (the best kind). Lighthouse, diff --git a/beacon_node/lighthouse_network/src/rpc/codec.rs b/beacon_node/lighthouse_network/src/rpc/codec.rs index f638dd5615..32789754b1 100644 --- a/beacon_node/lighthouse_network/src/rpc/codec.rs +++ b/beacon_node/lighthouse_network/src/rpc/codec.rs @@ -100,7 +100,7 @@ impl SSZSnappyInboundCodec { } } }, - RpcResponse::Error(_, err) => err.as_ssz_bytes(), + RpcResponse::Error(_, err) => err.as_bytes().to_vec().as_ssz_bytes(), RpcResponse::StreamTermination(_) => { unreachable!("Code error - attempting to encode a stream termination") } @@ -334,6 +334,14 @@ impl Encoder> for SSZSnappyOutboundCodec { type Error = RPCError; fn encode(&mut self, item: RequestType, dst: &mut BytesMut) -> Result<(), Self::Error> { + let compress = !matches!( + &item, + RequestType::Raw(RawRequest { + mode: RawMode::Raw, + .. + }) + ); + let bytes = match item { RequestType::Status(req) => { // Send the status message based on the negotiated protocol @@ -365,14 +373,25 @@ impl Encoder> for SSZSnappyOutboundCodec { RequestType::MetaData(_) | RequestType::LightClientOptimisticUpdate | RequestType::LightClientFinalityUpdate => return Ok(()), + RequestType::Raw(RawRequest { + bytes, + protocol: _, + mode, + }) => match mode { + RawMode::EncodeAndCompress => bytes.as_ssz_bytes(), + RawMode::Compress | RawMode::Raw => bytes, + }, }; + // Mallory doesn't care about inbound limits + /* // SSZ encoded bytes should be within `max_packet_size` if bytes.len() > self.max_packet_size { return Err(RPCError::InternalError( "attempting to encode data > max_packet_size", )); } + */ // Inserts the length prefix of the uncompressed bytes into dst // encoded as a unsigned varint @@ -380,12 +399,14 @@ impl Encoder> for SSZSnappyOutboundCodec { .encode(bytes.len(), dst) .map_err(RPCError::from)?; - let mut writer = FrameEncoder::new(Vec::new()); - writer.write_all(&bytes).map_err(RPCError::from)?; - writer.flush().map_err(RPCError::from)?; - - // Write compressed bytes to `dst` - dst.extend_from_slice(writer.get_ref()); + if compress { + let mut writer = FrameEncoder::new(Vec::new()); + writer.write_all(&bytes).map_err(RPCError::from)?; + writer.flush().map_err(RPCError::from)?; + dst.extend_from_slice(writer.get_ref()); + } else { + dst.extend_from_slice(&bytes); + } Ok(()) } } diff --git a/beacon_node/lighthouse_network/src/rpc/handler.rs b/beacon_node/lighthouse_network/src/rpc/handler.rs index 396d390b00..93b6a1335e 100644 --- a/beacon_node/lighthouse_network/src/rpc/handler.rs +++ b/beacon_node/lighthouse_network/src/rpc/handler.rs @@ -4,6 +4,7 @@ use super::methods::{GoodbyeReason, RpcErrorResponse, RpcResponse}; use super::outbound::OutboundRequestContainer; use super::protocol::{InboundOutput, Protocol, RPCError, RPCProtocol, RequestType}; +use super::MalloryLocalConfig; use super::{RPCReceived, RPCSend, ReqId}; use crate::rpc::outbound::OutboundFramed; use crate::rpc::protocol::InboundFramed; @@ -143,6 +144,9 @@ where /// Timeout that will be used for inbound and outbound responses. resp_timeout: Duration, + + /// Additional configurations for the RPC Handler + config: MalloryLocalConfig, } enum HandlerState { @@ -227,6 +231,7 @@ where resp_timeout: Duration, peer_id: PeerId, connection_id: ConnectionId, + config: MalloryLocalConfig, ) -> Self { RPCHandler { connection_id, @@ -247,6 +252,7 @@ where fork_context, waker: None, resp_timeout, + config, } } @@ -711,8 +717,10 @@ where request, }; substream_entry.max_remaining_chunks = Some(max_remaining_chunks); - self.outbound_substreams_delay - .reset(delay_key, self.resp_timeout); + self.outbound_substreams_delay.reset( + delay_key, + Duration::from_secs(self.config.outbound_timeout), + ); } } @@ -1031,9 +1039,10 @@ where Some(max_responses) }; // new outbound request. Store the stream and tag the output. - let delay_key = self - .outbound_substreams_delay - .insert(self.current_outbound_substream_id, self.resp_timeout); + let delay_key = self.outbound_substreams_delay.insert( + self.current_outbound_substream_id, + Duration::from_secs(self.config.outbound_timeout), + ); let awaiting_stream = OutboundSubstreamState::RequestPendingResponse { substream: Box::new(substream), request, diff --git a/beacon_node/lighthouse_network/src/rpc/methods.rs b/beacon_node/lighthouse_network/src/rpc/methods.rs index 74cfc6d198..c255244e38 100644 --- a/beacon_node/lighthouse_network/src/rpc/methods.rs +++ b/beacon_node/lighthouse_network/src/rpc/methods.rs @@ -1,5 +1,6 @@ //! Available RPC methods types and ids. +use super::protocol::SupportedProtocol; use crate::types::{EnrAttestationBitfield, EnrSyncCommitteeBitfield}; use regex::bytes::Regex; use serde::Serialize; @@ -11,6 +12,7 @@ use std::marker::PhantomData; use std::ops::Deref; use std::sync::Arc; use strum::IntoStaticStr; +use strum::{Display as StrumDisplay, EnumString}; use superstruct::superstruct; use types::blob_sidecar::BlobIdentifier; use types::light_client_update::MAX_REQUEST_LIGHT_CLIENT_UPDATES; @@ -129,6 +131,38 @@ pub struct Ping { pub data: u64, } +#[derive(Debug, Clone, PartialEq)] +pub struct RawRequest { + pub bytes: Vec, + pub protocol: SupportedProtocol, + pub mode: RawMode, +} + +#[derive(Debug, Clone, PartialEq, EnumString, StrumDisplay)] +pub enum RawMode { + /// SSZ encode, Snappy compress. + #[strum(serialize = "encode-compress")] + EncodeAndCompress, + /// Only Snappy compress. + #[strum(serialize = "compress")] + Compress, + /// Do not alter the bytes. + #[strum(serialize = "raw")] + Raw, +} + +impl Default for RawMode { + fn default() -> Self { + RawMode::EncodeAndCompress + } +} + +impl std::fmt::Display for RawRequest { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self) + } +} + /// The METADATA request structure. #[superstruct( variants(V1, V2, V3), @@ -411,6 +445,8 @@ impl DataColumnsByRangeRequest { } } +const MALLORY_MAX_REQUEST_BLOCKS: usize = 10000000000000000000; + /// Request a number of beacon block roots from a peer. #[superstruct( variants(V1, V2), @@ -496,6 +532,11 @@ impl BlocksByRootRequest { let block_roots = RuntimeVariableList::from_vec(block_roots, max_request_blocks); Self::V1(BlocksByRootRequestV1 { block_roots }) } + + pub fn mallory_new(block_roots: Vec) -> Self { + let block_roots = RuntimeVariableList::from_vec(block_roots, MALLORY_MAX_REQUEST_BLOCKS); + Self::V2(BlocksByRootRequestV2 { block_roots }) + } } /// Request a number of beacon blocks and blobs from a peer. @@ -653,10 +694,10 @@ impl ResponseTermination { /// and the contents of the response #[derive(Debug, Clone)] pub enum RpcResponse { - /// The response is a successful. + /// The response is successful. Success(RpcSuccessResponse), - Error(RpcErrorResponse, ErrorType), + Error(RpcErrorResponse, String), /// Received a stream termination indicating which response is being terminated. StreamTermination(ResponseTermination), @@ -706,7 +747,7 @@ impl RpcResponse { 140 => RpcErrorResponse::BlobsNotFoundForBlock, _ => RpcErrorResponse::Unknown, }; - RpcResponse::Error(code, err) + RpcResponse::Error(code, err.to_string()) } /// Returns true if this response always terminates the stream. diff --git a/beacon_node/lighthouse_network/src/rpc/mod.rs b/beacon_node/lighthouse_network/src/rpc/mod.rs index 0619908bb6..5876a735ec 100644 --- a/beacon_node/lighthouse_network/src/rpc/mod.rs +++ b/beacon_node/lighthouse_network/src/rpc/mod.rs @@ -29,12 +29,14 @@ use self::protocol::RPCProtocol; use self::self_limiter::SelfRateLimiter; use crate::rpc::rate_limiter::RateLimiterItem; use crate::rpc::response_limiter::ResponseLimiter; +use crate::MalloryConfig; pub use handler::SubstreamId; pub use methods::{ BlocksByRangeRequest, BlocksByRootRequest, GoodbyeReason, LightClientBootstrapRequest, ResponseTermination, RpcErrorResponse, StatusMessage, }; -pub use protocol::{Protocol, RPCError}; +pub use methods::{RawMode, RawRequest}; +pub use protocol::{Protocol, RPCError, SupportedProtocol}; pub(crate) mod codec; pub mod config; @@ -142,6 +144,16 @@ pub struct NetworkParams { pub resp_timeout: Duration, } +/// Additional configurations for the RPC Behaviour. +#[derive(Clone, Copy)] +pub struct MalloryLocalConfig { + /// Timeout in seconds for inbound connections. + pub inbound_timeout: u64, + /// Timeout for outbound connections. + pub outbound_timeout: u64, + pub self_handle_ping: bool, +} + /// Implements the libp2p `NetworkBehaviour` trait and therefore manages network-level /// logic. pub struct RPC { @@ -159,6 +171,9 @@ pub struct RPC { network_params: NetworkParams, /// A sequential counter indicating when data gets modified. seq_number: u64, + + /// Mallory Config + config: MalloryLocalConfig, } impl RPC { @@ -175,6 +190,7 @@ impl RPC { outbound_rate_limiter_config: Option, network_params: NetworkParams, seq_number: u64, + mallory_config: &MalloryConfig, ) -> Self { let response_limiter = inbound_rate_limiter_config.map(|config| { debug!(?config, "Using response rate limiting params"); @@ -186,6 +202,16 @@ impl RPC { SelfRateLimiter::new(outbound_rate_limiter_config, fork_context.clone()) .expect("Outbound limiter configuration parameters are valid"); + let mallory_config = MalloryLocalConfig { + inbound_timeout: mallory_config + .inbound_rpc_timeout + .unwrap_or(network_params.resp_timeout.as_secs()), + outbound_timeout: mallory_config + .outbound_rpc_timeout + .unwrap_or(network_params.resp_timeout.as_secs()), + self_handle_ping: mallory_config.user_handle_ping, + }; + RPC { response_limiter, outbound_request_limiter, @@ -195,6 +221,7 @@ impl RPC { enable_light_client_server, network_params, seq_number, + config: mallory_config, } } @@ -323,6 +350,15 @@ impl RPC { trace!(%peer_id, "Sending Ping"); self.send_request(peer_id, id, RequestType::Ping(ping)); } + + /// Sends a pong response + pub fn pong(&mut self, peer_id: PeerId, inbound_request_id: InboundRequestId, data: u64) { + self.send_response( + peer_id, + inbound_request_id, + RpcResponse::Success(RpcSuccessResponse::Pong(Ping { data })), + ); + } } impl NetworkBehaviour for RPC @@ -357,6 +393,7 @@ where self.network_params.resp_timeout, peer_id, connection_id, + self.config.clone(), ); Ok(handler) @@ -387,6 +424,7 @@ where self.network_params.resp_timeout, peer_id, connection_id, + self.config, ); Ok(handler) @@ -499,14 +537,16 @@ where // If we received a Ping, we queue a Pong response. if let RequestType::Ping(_) = request_type { - trace!(connection_id = %connection_id, %peer_id, "Received Ping, queueing Pong"); - self.send_response( - peer_id, - request_id, - RpcResponse::Success(RpcSuccessResponse::Pong(Ping { - data: self.seq_number, - })), - ); + if !self.config.self_handle_ping { + trace!(connection_id = %connection_id, %peer_id, "Received Ping, queueing Pong"); + self.send_response( + peer_id, + request_id, + RpcResponse::Success(RpcSuccessResponse::Pong(Ping { + data: self.seq_number, + })), + ); + } } self.events.push(ToSwarm::GenerateEvent(RPCMessage { diff --git a/beacon_node/lighthouse_network/src/rpc/protocol.rs b/beacon_node/lighthouse_network/src/rpc/protocol.rs index 8f613dcbf9..0d976ffe51 100644 --- a/beacon_node/lighthouse_network/src/rpc/protocol.rs +++ b/beacon_node/lighthouse_network/src/rpc/protocol.rs @@ -731,6 +731,7 @@ pub enum RequestType { LightClientUpdatesByRange(LightClientUpdatesByRangeRequest), Ping(Ping), MetaData(MetadataRequest), + Raw(RawRequest), } /// Implements the encoding per supported protocol for `RPCRequest`. @@ -757,6 +758,7 @@ impl RequestType { RequestType::LightClientOptimisticUpdate => 1, RequestType::LightClientFinalityUpdate => 1, RequestType::LightClientUpdatesByRange(req) => req.count, + RequestType::Raw(_) => 1, } } @@ -796,6 +798,7 @@ impl RequestType { RequestType::LightClientUpdatesByRange(_) => { SupportedProtocol::LightClientUpdatesByRangeV1 } + RequestType::Raw(r) => r.protocol, } } @@ -819,6 +822,7 @@ impl RequestType { RequestType::LightClientFinalityUpdate => unreachable!(), RequestType::LightClientOptimisticUpdate => unreachable!(), RequestType::LightClientUpdatesByRange(_) => unreachable!(), + RequestType::Raw(_) => unreachable!(), } } @@ -882,6 +886,7 @@ impl RequestType { SupportedProtocol::LightClientUpdatesByRangeV1, Encoding::SSZSnappy, )], + RequestType::Raw(req) => vec![ProtocolId::new(req.protocol, Encoding::SSZSnappy)], } } @@ -901,6 +906,7 @@ impl RequestType { RequestType::LightClientOptimisticUpdate => true, RequestType::LightClientFinalityUpdate => true, RequestType::LightClientUpdatesByRange(_) => true, + RequestType::Raw(_) => true, } } } @@ -1022,6 +1028,7 @@ impl std::fmt::Display for RequestType { RequestType::LightClientUpdatesByRange(_) => { write!(f, "Light client updates by range request") } + RequestType::Raw(raw) => write!(f, "Raw: {}", raw), } } } diff --git a/beacon_node/lighthouse_network/src/service/api_types.rs b/beacon_node/lighthouse_network/src/service/api_types.rs index b36f8cc215..e25017b388 100644 --- a/beacon_node/lighthouse_network/src/service/api_types.rs +++ b/beacon_node/lighthouse_network/src/service/api_types.rs @@ -1,6 +1,9 @@ -use crate::rpc::methods::{ResponseTermination, RpcResponse, RpcSuccessResponse, StatusMessage}; +use crate::rpc::methods::{ + Ping, ResponseTermination, RpcResponse, RpcSuccessResponse, StatusMessage, +}; use std::fmt::{Display, Formatter}; use std::sync::Arc; +use strum::IntoStaticStr; use types::{ BlobSidecar, DataColumnSidecar, Epoch, EthSpec, Hash256, LightClientBootstrap, LightClientFinalityUpdate, LightClientOptimisticUpdate, LightClientUpdate, SignedBeaconBlock, @@ -132,8 +135,9 @@ pub enum AppRequestId { // sent. The main difference is the absense of Pong and Metadata, which don't leave the // Behaviour. For all protocol reponses managed by RPC see `RPCResponse` and // `RPCCodedResponse`. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, IntoStaticStr)] pub enum Response { + Ping(u64), /// A Status message. Status(StatusMessage), /// A response to a get BLOCKS_BY_RANGE request. A None response signals the end of the batch. @@ -186,6 +190,7 @@ impl std::convert::From> for RpcResponse { None => RpcResponse::StreamTermination(ResponseTermination::DataColumnsByRange), }, Response::Status(s) => RpcResponse::Success(RpcSuccessResponse::Status(s)), + Response::Ping(data) => RpcResponse::Success(RpcSuccessResponse::Pong(Ping { data })), Response::LightClientBootstrap(b) => { RpcResponse::Success(RpcSuccessResponse::LightClientBootstrap(b)) } diff --git a/beacon_node/lighthouse_network/src/service/mallory.rs b/beacon_node/lighthouse_network/src/service/mallory.rs new file mode 100644 index 0000000000..1fc7b75c4d --- /dev/null +++ b/beacon_node/lighthouse_network/src/service/mallory.rs @@ -0,0 +1,187 @@ +use super::*; +use libp2p::core::transport::{ListenerId, TransportError}; +use libp2p::core::ConnectedPoint; +use libp2p::swarm::*; +use std::io; +/// Custom error that can be produced by the [`ConnectionHandler`] of the [`NetworkBehaviour`]. +#[derive(Debug)] +pub enum MallorySwarmEvent { + /// One of the listeners gracefully closed. + ListenerClosed { + /// The listener that closed. + listener_id: libp2p::core::transport::ListenerId, + /// The addresses that the listener was listening on. These addresses are now considered + /// expired, similar to if a [`ExpiredListenAddr`](SwarmEvent::ExpiredListenAddr) event + /// has been generated for each of them. + addresses: Vec, + /// Reason for the closure. Contains `Ok(())` if the stream produced `None`, or `Err` + /// if the stream produced an error. + reason: Result<(), std::io::Error>, + }, + /// One of the listeners reported a non-fatal error. + ListenerError { + /// The listener that errored. + listener_id: ListenerId, + /// The listener error. + error: io::Error, + }, + /// Outgoing connection attempt failed. + OutgoingConnectionError { + /// Identifier of the connection. + connection_id: ConnectionId, + /// If known, [`PeerId`] of the peer we tried to reach. + peer_id: Option, + /// Error that has been encountered. + error: DialError, + }, + IncomingConnection { + /// Identifier of the connection. + connection_id: ConnectionId, + /// Local connection address. + /// This address has been earlier reported with a [`NewListenAddr`](SwarmEvent::NewListenAddr) + /// event. + local_addr: Multiaddr, + /// Address used to send back data to the remote. + send_back_addr: Multiaddr, + }, + /// An error happened on a connection during its initial handshake. + /// + /// This can include, for example, an error during the handshake of the encryption layer, or + /// the connection unexpectedly closed. + IncomingConnectionError { + /// Identifier of the connection. + connection_id: ConnectionId, + /// Local connection address. + /// This address has been earlier reported with a [`NewListenAddr`](SwarmEvent::NewListenAddr) + /// event. + local_addr: Multiaddr, + /// Address used to send back data to the remote. + send_back_addr: Multiaddr, + /// The error that happened. + error: ListenError, + }, + Dialing { + /// Identity of the peer that we are connecting to. + peer_id: Option, + /// Identifier of the connection. + connection_id: ConnectionId, + }, + ConnectionClosed { + /// Identity of the peer that we have connected to. + peer_id: PeerId, + /// Identifier of the connection. + connection_id: ConnectionId, + /// Endpoint of the connection that has been closed. + endpoint: ConnectedPoint, + /// Number of other remaining connections to this same peer. + num_established: u32, + /// Reason for the disconnection, if it was not a successful + /// active close. + cause: Option, + }, + /// A connection to the given peer has been opened. + ConnectionEstablished { + /// Identity of the peer that we have connected to. + peer_id: PeerId, + /// Identifier of the connection. + connection_id: ConnectionId, + /// Endpoint of the connection that has been opened. + endpoint: ConnectedPoint, + /// Number of established connections to this peer, including the one that has just been + /// opened. + num_established: std::num::NonZeroU32, + /// [`Some`] when the new connection is an outgoing connection. + /// Addresses are dialed concurrently. Contains the addresses and errors + /// of dial attempts that failed before the one successful dial. + concurrent_dial_errors: Option)>>, + /// How long it took to establish this connection + established_in: std::time::Duration, + }, +} + +impl TryFrom> for MallorySwarmEvent { + type Error = SwarmEvent; + + fn try_from(event: SwarmEvent) -> Result { + match event { + SwarmEvent::ListenerClosed { + listener_id, + addresses, + reason, + } => Ok(MallorySwarmEvent::ListenerClosed { + listener_id, + addresses, + reason, + }), + SwarmEvent::ListenerError { listener_id, error } => { + Ok(MallorySwarmEvent::ListenerError { listener_id, error }) + } + SwarmEvent::OutgoingConnectionError { + connection_id, + peer_id, + error, + } => Ok(MallorySwarmEvent::OutgoingConnectionError { + connection_id, + peer_id, + error, + }), + SwarmEvent::IncomingConnection { + connection_id, + local_addr, + send_back_addr, + } => Ok(MallorySwarmEvent::IncomingConnection { + connection_id, + local_addr, + send_back_addr, + }), + SwarmEvent::IncomingConnectionError { + connection_id, + local_addr, + send_back_addr, + error, + } => Ok(MallorySwarmEvent::IncomingConnectionError { + connection_id, + local_addr, + send_back_addr, + error, + }), + SwarmEvent::Dialing { + peer_id, + connection_id, + } => Ok(MallorySwarmEvent::Dialing { + peer_id, + connection_id, + }), + SwarmEvent::ConnectionClosed { + peer_id, + connection_id, + endpoint, + num_established, + cause, + } => Ok(MallorySwarmEvent::ConnectionClosed { + peer_id, + connection_id, + endpoint, + num_established, + cause: cause.map(|v| format!("{:?}", v)), + }), + SwarmEvent::ConnectionEstablished { + peer_id, + connection_id, + endpoint, + num_established, + concurrent_dial_errors, + established_in, + } => Ok(MallorySwarmEvent::ConnectionEstablished { + peer_id, + connection_id, + endpoint, + num_established, + concurrent_dial_errors, + established_in, + }), + ev => Err(ev), // Don't pass other events up. + } + } +} +// Used for Mallory diff --git a/beacon_node/lighthouse_network/src/service/mod.rs b/beacon_node/lighthouse_network/src/service/mod.rs index e2c6f24405..328adf0ab5 100644 --- a/beacon_node/lighthouse_network/src/service/mod.rs +++ b/beacon_node/lighthouse_network/src/service/mod.rs @@ -24,8 +24,8 @@ use crate::{metrics, Enr, NetworkGlobals, PubsubMessage, TopicHash}; use api_types::{AppRequestId, Response}; use futures::stream::StreamExt; use gossipsub::{ - IdentTopic as Topic, MessageAcceptance, MessageAuthenticity, MessageId, PublishError, - TopicScoreParams, + Config as GossipsubConfig, IdentTopic as Topic, MessageAcceptance, MessageAuthenticity, + MessageId, PublishError, RawMessage, TopicScoreParams, }; use gossipsub_scoring_parameters::{lighthouse_gossip_thresholds, PeerScoreSettings}; use libp2p::multiaddr::{self, Multiaddr, Protocol as MProtocol}; @@ -49,7 +49,9 @@ use utils::{build_transport, strip_peer_id, Context as ServiceContext}; pub mod api_types; mod gossip_cache; pub mod gossipsub_scoring_parameters; +mod mallory; pub mod utils; +pub use mallory::*; /// The number of peers we target per subnet for discovery queries. pub const TARGET_SUBNET_PEERS: usize = 3; @@ -105,6 +107,10 @@ pub enum NetworkEvent { ZeroListeners, /// A peer has an updated custody group count from MetaData. PeerUpdatedCustodyGroupCount(PeerId), + /// Mallory: Identify has been received. + IdentifyReceived(PeerId), + /// Mallory: Pass swarm events to mallory to handle + MallorySwarmEvent(MallorySwarmEvent), } pub type Gossipsub = gossipsub::Behaviour; @@ -112,7 +118,7 @@ pub type SubscriptionFilter = gossipsub::MaxCountSubscriptionFilter; #[derive(NetworkBehaviour)] -pub(crate) struct Behaviour +pub struct Behaviour where E: EthSpec, { @@ -146,7 +152,7 @@ where /// This core behaviour is managed by `Behaviour` which adds peer management to all core /// behaviours. pub struct Network { - swarm: libp2p::swarm::Swarm>, + pub swarm: libp2p::swarm::Swarm>, /* Auxiliary Fields */ /// A collections of variables accessible outside the network service. network_globals: Arc>, @@ -161,9 +167,11 @@ pub struct Network { score_settings: PeerScoreSettings, /// The interval for updating gossipsub scores update_gossipsub_scores: tokio::time::Interval, - gossip_cache: GossipCache, + pub gossip_cache: GossipCache, /// This node's PeerId. pub local_peer_id: PeerId, + /// Mallory specific. User handles the ping requests. + user_handle_ping: bool, } /// Implements the combined behaviour for the libp2p service. @@ -178,11 +186,12 @@ impl Network { executor: task_executor::TaskExecutor, mut ctx: ServiceContext<'_>, custody_group_count: u64, + gs_config: Option, ) -> Result<(Self, Arc>), String> { let config = ctx.config.clone(); trace!("Libp2p Service starting"); // initialise the node's ID - let local_keypair = utils::load_private_key(&config); + let local_keypair = ctx.keypair; // Trusted peers will also be marked as explicit in GossipSub. // Cfr. https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#explicit-peering-agreements @@ -227,14 +236,18 @@ impl Network { message_domain_valid_snappy: ctx.chain_spec.message_domain_valid_snappy, gossipsub_max_transmit_size: ctx.chain_spec.max_message_size(), }; - let gs_config = gossipsub_config( - config.network_load, - ctx.fork_context.clone(), - gossipsub_config_params, - ctx.chain_spec.seconds_per_slot, - E::slots_per_epoch(), - config.idontwant_message_size_threshold, - ); + + let gs_config = match gs_config { + Some(config) => config, + None => gossipsub_config( + config.network_load, + ctx.fork_context.clone(), + gossipsub_config_params, + ctx.chain_spec.seconds_per_slot, + E::slots_per_epoch(), + config.idontwant_message_size_threshold, + ), + }; let score_settings = PeerScoreSettings::new(&ctx.chain_spec, gs_config.mesh_n()); @@ -380,6 +393,7 @@ impl Network { config.outbound_rate_limiter_config.clone(), network_params, seq_number, + &config.attacker_config, ); let discovery = { @@ -418,20 +432,35 @@ impl Network { quic_enabled: !config.disable_quic_support, metrics_enabled: config.metrics_enabled, target_peer_count: config.target_peers, + ping_interval_inbound: config + .attacker_config + .inbound_peers_ping + .unwrap_or(crate::peer_manager::config::DEFAULT_PING_INTERVAL_INBOUND), + ping_interval_outbound: config + .attacker_config + .outbound_peers_ping + .unwrap_or(crate::peer_manager::config::DEFAULT_PING_INTERVAL_OUTBOUND), + status_interval: config + .attacker_config + .status_interval + .unwrap_or(crate::peer_manager::config::DEFAULT_STATUS_INTERVAL), ..Default::default() }; PeerManager::new(peer_manager_cfg, network_globals.clone())? }; + let max_incomming = if let Some(connections) = ctx.incoming_connections.as_ref() { + *connections + } else { + (config.target_peers as f32 * (1.0 + PEER_EXCESS_FACTOR - MIN_OUTBOUND_ONLY_FACTOR)) + .ceil() as u32 + }; + let connection_limits = { let limits = libp2p::connection_limits::ConnectionLimits::default() - .with_max_pending_incoming(Some(5)) + .with_max_pending_incoming(Some(max_incomming)) .with_max_pending_outgoing(Some(16)) - .with_max_established_incoming(Some( - (config.target_peers as f32 - * (1.0 + PEER_EXCESS_FACTOR - MIN_OUTBOUND_ONLY_FACTOR)) - .ceil() as u32, - )) + .with_max_established_incoming(Some(max_incomming)) .with_max_established_outgoing(Some( (config.target_peers as f32 * (1.0 + PEER_EXCESS_FACTOR)).ceil() as u32, )) @@ -515,6 +544,7 @@ impl Network { update_gossipsub_scores, gossip_cache, local_peer_id, + user_handle_ping: config.attacker_config.user_handle_ping, }; network.start(&config).await?; @@ -1440,7 +1470,7 @@ impl Network { name = "libp2p", skip_all )] - fn send_meta_data_request(&mut self, peer_id: PeerId) { + pub fn send_meta_data_request(&mut self, peer_id: PeerId) { let event = if self.fork_context.spec.is_peer_das_scheduled() { // Nodes with higher custody will probably start advertising it // before peerdas is activated @@ -1757,9 +1787,24 @@ impl Network { /* Behaviour managed protocols: Ping and Metadata */ RequestType::Ping(ping) => { // inform the peer manager and send the response + if self.user_handle_ping { + return Some(NetworkEvent::RequestReceived { + peer_id, + inbound_request_id, + request_type, + }); + } self.peer_manager_mut().ping_request(&peer_id, ping.data); None } + RequestType::Raw(_) => { + // inform the peer manager and send the response + return Some(NetworkEvent::RequestReceived { + peer_id, + inbound_request_id, + request_type, + }); + } RequestType::MetaData(req) => { // send the requested meta-data self.send_meta_data_response(req, inbound_request_id, peer_id); @@ -2003,6 +2048,7 @@ impl Network { } // send peer info to the peer manager. self.peer_manager_mut().identify(&peer_id, &info); + return Some(NetworkEvent::IdentifyReceived(peer_id)); } identify::Event::Sent { .. } => {} identify::Event::Error { .. } => {} @@ -2132,7 +2178,15 @@ impl Network { // Poll the libp2p `Swarm`. // This will poll the swarm and do maintenance routines. Some(event) = self.swarm.next() => { - if let Some(event) = self.parse_swarm_event(event) { + // Try convert to mallory event.This just passes some swarm events up to mallory, + // rather than processing here. + // Attempt passing swarm events up to Mallory + let swarm_event = match MallorySwarmEvent::try_from(event) { + Ok(ev) => return NetworkEvent::MallorySwarmEvent(ev), + Err(ev) => ev, + }; + + if let Some(event) = self.parse_swarm_event(swarm_event) { return event; } }, @@ -2158,6 +2212,31 @@ impl Network { } } } + #[instrument(parent = None, + level = "trace", + fields(service = "libp2p"), + name = "libp2p", + skip_all + )] + /// Publish a raw gossipsub RPC message to a specific target. + pub fn publish_raw_targeted(&mut self, msg: RawMessage, target: PeerId) { + if let Err(e) = self.gossipsub_mut().raw_publish_targeted(target, msg) { + warn!("error" = ?e, "Could not publish message"); + } + } + + #[instrument(parent = None, + level = "trace", + fields(service = "libp2p"), + name = "libp2p", + skip_all + )] + /// Publish a raw gossipsub RPC message to a specific target. + pub fn publish_raw(&mut self, msg: RawMessage, topic: Topic) { + if let Err(e) = self.gossipsub_mut().raw_publish(topic, msg) { + warn!("error" = ?e, "Could not publish message"); + } + } #[instrument(parent = None, level = "trace", diff --git a/beacon_node/lighthouse_network/src/service/utils.rs b/beacon_node/lighthouse_network/src/service/utils.rs index 9a93936874..159d870651 100644 --- a/beacon_node/lighthouse_network/src/service/utils.rs +++ b/beacon_node/lighthouse_network/src/service/utils.rs @@ -30,6 +30,8 @@ pub struct Context<'a> { pub fork_context: Arc, pub chain_spec: Arc, pub libp2p_registry: Option<&'a mut Registry>, + pub keypair: Keypair, + pub incoming_connections: Option, } type BoxedTransport = Boxed<(PeerId, StreamMuxerBox)>; diff --git a/beacon_node/lighthouse_network/src/types/topics.rs b/beacon_node/lighthouse_network/src/types/topics.rs index 349bfe66a3..6b4bf7568e 100644 --- a/beacon_node/lighthouse_network/src/types/topics.rs +++ b/beacon_node/lighthouse_network/src/types/topics.rs @@ -1,7 +1,7 @@ use gossipsub::{IdentTopic as Topic, TopicHash}; use serde::{Deserialize, Serialize}; use std::collections::HashSet; -use strum::AsRefStr; +use strum::{AsRefStr, IntoStaticStr}; use types::{ChainSpec, DataColumnSubnetId, EthSpec, ForkName, SubnetId, SyncSubnetId, Unsigned}; use crate::Subnet; @@ -145,7 +145,7 @@ pub struct GossipTopic { /// Enum that brings these topics into the rust type system. // NOTE: There is intentionally no unknown type here. We only allow known gossipsub topics. -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, AsRefStr)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, AsRefStr, IntoStaticStr)] #[strum(serialize_all = "snake_case")] pub enum GossipKind { /// Topic for publishing beacon blocks. diff --git a/beacon_node/network/src/lib.rs b/beacon_node/network/src/lib.rs index 2a7fedb53e..a470271fc1 100644 --- a/beacon_node/network/src/lib.rs +++ b/beacon_node/network/src/lib.rs @@ -5,7 +5,7 @@ mod metrics; mod nat; mod network_beacon_processor; mod persisted_dht; -mod router; +pub mod router; mod status; mod subnet_service; mod sync; diff --git a/beacon_node/network/src/router.rs b/beacon_node/network/src/router.rs index 5d5daae4ae..7ec163bfb9 100644 --- a/beacon_node/network/src/router.rs +++ b/beacon_node/network/src/router.rs @@ -314,6 +314,7 @@ impl Router { Response::LightClientBootstrap(_) | Response::LightClientOptimisticUpdate(_) | Response::LightClientFinalityUpdate(_) + | Response::Ping(_) | Response::LightClientUpdatesByRange(_) => unreachable!(), } } diff --git a/beacon_node/network/src/service.rs b/beacon_node/network/src/service.rs index 0a6d515232..23e108b0ae 100644 --- a/beacon_node/network/src/service.rs +++ b/beacon_node/network/src/service.rs @@ -266,6 +266,8 @@ impl NetworkService { debug!(fork_name = ?fork_context.current_fork(), "Current fork"); + let keypair = lighthouse_network::load_private_key(&config); + // construct the libp2p service context let service_context = Context { config: config.clone(), @@ -273,6 +275,8 @@ impl NetworkService { fork_context: fork_context.clone(), chain_spec: beacon_chain.spec.clone(), libp2p_registry, + keypair, + incoming_connections: None, }; // launch libp2p service @@ -283,6 +287,7 @@ impl NetworkService { .data_availability_checker .custody_context() .custody_group_count_at_head(&beacon_chain.spec), + None, ) .await?; @@ -487,6 +492,11 @@ impl NetworkService { shutdown_sender: &mut Sender, ) { match ev { + // mallory event + NetworkEvent::MallorySwarmEvent(_) => {} + // mallory event + NetworkEvent::IdentifyReceived(_) => {} + NetworkEvent::PeerConnectedOutgoing(peer_id) => { self.send_to_router(RouterMessage::StatusPeer(peer_id)); } diff --git a/common/eth2_network_config/src/lib.rs b/common/eth2_network_config/src/lib.rs index ac488ed2a3..0c27857909 100644 --- a/common/eth2_network_config/src/lib.rs +++ b/common/eth2_network_config/src/lib.rs @@ -244,7 +244,7 @@ impl Eth2NetworkConfig { } } - fn get_genesis_state_from_bytes(&self) -> Result, String> { + pub fn get_genesis_state_from_bytes(&self) -> Result, String> { let spec = self.chain_spec::()?; self.genesis_state_bytes .as_ref()