Add Experimental QUIC support (#4577)

## Issue Addressed

#4402 

## Proposed Changes

This PR adds QUIC support to Lighthouse. As this is not officially spec'd this will only work between lighthouse <-> lighthouse connections. We attempt a QUIC connection (if the node advertises it) and if it fails we fallback to TCP. 

This should be a backwards compatible modification. We want to test this functionality on live networks to observe any improvements in bandwidth/latency.

NOTE: This also removes the websockets transport as I believe no one is really using it. It should be mentioned in our release however.


Co-authored-by: João Oliveira <hello@jxs.pt>
This commit is contained in:
Age Manning 2023-09-15 03:07:24 +00:00
parent 35f47f454f
commit e4ed317b76
35 changed files with 1161 additions and 752 deletions

351
Cargo.lock generated
View File

@ -63,9 +63,9 @@ dependencies = [
[[package]] [[package]]
name = "addr2line" name = "addr2line"
version = "0.20.0" version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [ dependencies = [
"gimli", "gimli",
] ]
@ -328,7 +328,7 @@ checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
dependencies = [ dependencies = [
"async-stream-impl", "async-stream-impl",
"futures-core", "futures-core",
"pin-project-lite 0.2.12", "pin-project-lite",
] ]
[[package]] [[package]]
@ -374,7 +374,7 @@ dependencies = [
"futures-sink", "futures-sink",
"futures-util", "futures-util",
"memchr", "memchr",
"pin-project-lite 0.2.12", "pin-project-lite",
] ]
[[package]] [[package]]
@ -446,7 +446,7 @@ dependencies = [
"memchr", "memchr",
"mime", "mime",
"percent-encoding", "percent-encoding",
"pin-project-lite 0.2.12", "pin-project-lite",
"rustversion", "rustversion",
"serde", "serde",
"serde_json", "serde_json",
@ -478,9 +478,9 @@ dependencies = [
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.68" version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"cc", "cc",
@ -517,9 +517,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.21.2" version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53"
[[package]] [[package]]
name = "base64ct" name = "base64ct"
@ -959,9 +959,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.82" version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [ dependencies = [
"jobserver", "jobserver",
"libc", "libc",
@ -1391,7 +1391,7 @@ version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e" checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e"
dependencies = [ dependencies = [
"nix 0.26.2", "nix 0.26.3",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -1602,9 +1602,9 @@ dependencies = [
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.3.7" version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
[[package]] [[package]]
name = "derivative" name = "derivative"
@ -1643,9 +1643,9 @@ dependencies = [
[[package]] [[package]]
name = "diesel" name = "diesel"
version = "2.1.0" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7a532c1f99a0f596f6960a60d1e119e91582b24b39e2d83a190e61262c3ef0c" checksum = "d98235fdc2f355d330a8244184ab6b4b33c28679c0b4158f63138e51d6cf7e88"
dependencies = [ dependencies = [
"bitflags 2.4.0", "bitflags 2.4.0",
"byteorder", "byteorder",
@ -1657,9 +1657,9 @@ dependencies = [
[[package]] [[package]]
name = "diesel_derives" name = "diesel_derives"
version = "2.1.0" version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74398b79d81e52e130d991afeed9c86034bb1b7735f46d2f5bf7deb261d80303" checksum = "e054665eaf6d97d1e7125512bb2d35d07c73ac86cc6920174cb42d1ab697a554"
dependencies = [ dependencies = [
"diesel_table_macro_syntax", "diesel_table_macro_syntax",
"proc-macro2", "proc-macro2",
@ -1943,9 +1943,9 @@ dependencies = [
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.8.32" version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
] ]
@ -1975,7 +1975,7 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0be7b2ac146c1f99fe245c02d16af0696450d8e06c135db75e10eeb9e642c20d" checksum = "0be7b2ac146c1f99fe245c02d16af0696450d8e06c135db75e10eeb9e642c20d"
dependencies = [ dependencies = [
"base64 0.21.2", "base64 0.21.3",
"bytes", "bytes",
"ed25519-dalek", "ed25519-dalek",
"hex", "hex",
@ -2889,7 +2889,7 @@ dependencies = [
"futures-io", "futures-io",
"memchr", "memchr",
"parking", "parking",
"pin-project-lite 0.2.12", "pin-project-lite",
"waker-fn", "waker-fn",
] ]
@ -2956,7 +2956,7 @@ dependencies = [
"futures-sink", "futures-sink",
"futures-task", "futures-task",
"memchr", "memchr",
"pin-project-lite 0.2.12", "pin-project-lite",
"pin-utils", "pin-utils",
"slab", "slab",
] ]
@ -3040,9 +3040,9 @@ dependencies = [
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.27.3" version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
[[package]] [[package]]
name = "git-version" name = "git-version"
@ -3096,9 +3096,9 @@ dependencies = [
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.3.20" version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833"
dependencies = [ dependencies = [
"bytes", "bytes",
"fnv", "fnv",
@ -3335,7 +3335,7 @@ checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [ dependencies = [
"bytes", "bytes",
"http", "http",
"pin-project-lite 0.2.12", "pin-project-lite",
] ]
[[package]] [[package]]
@ -3441,7 +3441,7 @@ dependencies = [
"httparse", "httparse",
"httpdate", "httpdate",
"itoa", "itoa",
"pin-project-lite 0.2.12", "pin-project-lite",
"socket2 0.4.9", "socket2 0.4.9",
"tokio", "tokio",
"tower-service", "tower-service",
@ -3730,7 +3730,7 @@ dependencies = [
"socket2 0.5.3", "socket2 0.5.3",
"widestring 1.0.2", "widestring 1.0.2",
"windows-sys 0.48.0", "windows-sys 0.48.0",
"winreg 0.50.0", "winreg",
] ]
[[package]] [[package]]
@ -3809,7 +3809,7 @@ version = "8.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378"
dependencies = [ dependencies = [
"base64 0.21.2", "base64 0.21.3",
"pem", "pem",
"ring", "ring",
"serde", "serde",
@ -4021,7 +4021,6 @@ dependencies = [
"libp2p-quic", "libp2p-quic",
"libp2p-swarm", "libp2p-swarm",
"libp2p-tcp", "libp2p-tcp",
"libp2p-websocket",
"libp2p-yamux", "libp2p-yamux",
"multiaddr 0.18.0", "multiaddr 0.18.0",
"pin-project", "pin-project",
@ -4101,7 +4100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d157562dba6017193e5285acf6b1054759e83540bfd79f75b69d6ce774c88da" checksum = "2d157562dba6017193e5285acf6b1054759e83540bfd79f75b69d6ce774c88da"
dependencies = [ dependencies = [
"asynchronous-codec", "asynchronous-codec",
"base64 0.21.2", "base64 0.21.3",
"byteorder", "byteorder",
"bytes", "bytes",
"either", "either",
@ -4362,26 +4361,6 @@ dependencies = [
"yasna", "yasna",
] ]
[[package]]
name = "libp2p-websocket"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3facf0691bab65f571bc97c6c65ffa836248ca631d631b7691ac91deb7fceb5f"
dependencies = [
"either",
"futures",
"futures-rustls",
"libp2p-core",
"libp2p-identity",
"log",
"parking_lot 0.12.1",
"quicksink",
"rw-stream-sink",
"soketto",
"url",
"webpki-roots 0.25.2",
]
[[package]] [[package]]
name = "libp2p-yamux" name = "libp2p-yamux"
version = "0.44.1" version = "0.44.1"
@ -4534,6 +4513,7 @@ dependencies = [
"lazy_static", "lazy_static",
"libp2p", "libp2p",
"libp2p-mplex", "libp2p-mplex",
"libp2p-quic",
"lighthouse_metrics", "lighthouse_metrics",
"lighthouse_version", "lighthouse_version",
"lru 0.7.8", "lru 0.7.8",
@ -5240,14 +5220,13 @@ dependencies = [
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.26.2" version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" checksum = "abbbc55ad7b13aac85f9401c796dcda1b864e07fcad40ad47792eaa8932ea502"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 2.4.0",
"cfg-if", "cfg-if",
"libc", "libc",
"static_assertions",
] ]
[[package]] [[package]]
@ -5309,9 +5288,9 @@ dependencies = [
[[package]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.4.3" version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [ dependencies = [
"autocfg 1.1.0", "autocfg 1.1.0",
"num-integer", "num-integer",
@ -5388,9 +5367,9 @@ dependencies = [
[[package]] [[package]]
name = "object" name = "object"
version = "0.31.1" version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -5456,11 +5435,11 @@ dependencies = [
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.56" version = "0.10.57"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 2.4.0",
"cfg-if", "cfg-if",
"foreign-types", "foreign-types",
"libc", "libc",
@ -5497,9 +5476,9 @@ dependencies = [
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.91" version = "0.9.92"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@ -5653,7 +5632,7 @@ dependencies = [
"libc", "libc",
"redox_syscall 0.3.5", "redox_syscall 0.3.5",
"smallvec 1.11.0", "smallvec 1.11.0",
"windows-targets 0.48.3", "windows-targets 0.48.5",
] ]
[[package]] [[package]]
@ -5783,15 +5762,9 @@ dependencies = [
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.1.12" version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-project-lite"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05"
[[package]] [[package]]
name = "pin-utils" name = "pin-utils"
@ -5877,7 +5850,7 @@ dependencies = [
"concurrent-queue", "concurrent-queue",
"libc", "libc",
"log", "log",
"pin-project-lite 0.2.12", "pin-project-lite",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -5906,11 +5879,11 @@ dependencies = [
[[package]] [[package]]
name = "postgres-protocol" name = "postgres-protocol"
version = "0.6.5" version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b7fa9f396f51dffd61546fd8573ee20592287996568e6175ceb0f8699ad75d" checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520"
dependencies = [ dependencies = [
"base64 0.21.2", "base64 0.21.3",
"byteorder", "byteorder",
"bytes", "bytes",
"fallible-iterator", "fallible-iterator",
@ -5924,9 +5897,9 @@ dependencies = [
[[package]] [[package]]
name = "postgres-types" name = "postgres-types"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f028f05971fe20f512bcc679e2c10227e57809a3af86a7606304435bc8896cd6" checksum = "8d2234cdee9408b523530a9b6d2d6b373d1db34f6a8e51dc03ded1828d7fb67c"
dependencies = [ dependencies = [
"bytes", "bytes",
"fallible-iterator", "fallible-iterator",
@ -6195,17 +6168,6 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "quicksink"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858"
dependencies = [
"futures-core",
"futures-sink",
"pin-project-lite 0.1.12",
]
[[package]] [[package]]
name = "quinn" name = "quinn"
version = "0.10.2" version = "0.10.2"
@ -6214,7 +6176,7 @@ checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-io", "futures-io",
"pin-project-lite 0.2.12", "pin-project-lite",
"quinn-proto", "quinn-proto",
"quinn-udp", "quinn-udp",
"rustc-hash", "rustc-hash",
@ -6441,14 +6403,14 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.9.3" version = "1.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-automata 0.3.6", "regex-automata 0.3.7",
"regex-syntax 0.7.4", "regex-syntax 0.7.5",
] ]
[[package]] [[package]]
@ -6462,13 +6424,13 @@ dependencies = [
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-syntax 0.7.4", "regex-syntax 0.7.5",
] ]
[[package]] [[package]]
@ -6479,17 +6441,17 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.11.18" version = "0.11.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
dependencies = [ dependencies = [
"base64 0.21.2", "base64 0.21.3",
"bytes", "bytes",
"encoding_rs", "encoding_rs",
"futures-core", "futures-core",
@ -6507,7 +6469,7 @@ dependencies = [
"native-tls", "native-tls",
"once_cell", "once_cell",
"percent-encoding", "percent-encoding",
"pin-project-lite 0.2.12", "pin-project-lite",
"rustls 0.21.6", "rustls 0.21.6",
"rustls-pemfile", "rustls-pemfile",
"serde", "serde",
@ -6523,8 +6485,8 @@ dependencies = [
"wasm-bindgen-futures", "wasm-bindgen-futures",
"wasm-streams", "wasm-streams",
"web-sys", "web-sys",
"webpki-roots 0.22.6", "webpki-roots 0.25.2",
"winreg 0.10.1", "winreg",
] ]
[[package]] [[package]]
@ -6705,9 +6667,9 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.8" version = "0.38.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" checksum = "9bfe0f2582b4931a45d1fa608f8a8722e8b3c7ac54dd6d5f3b3212791fedef49"
dependencies = [ dependencies = [
"bitflags 2.4.0", "bitflags 2.4.0",
"errno", "errno",
@ -6746,7 +6708,7 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2"
dependencies = [ dependencies = [
"base64 0.21.2", "base64 0.21.3",
] ]
[[package]] [[package]]
@ -6956,9 +6918,9 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.183" version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@ -6996,9 +6958,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.183" version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -7092,19 +7054,6 @@ dependencies = [
"yaml-rust", "yaml-rust",
] ]
[[package]]
name = "sha-1"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
dependencies = [
"block-buffer 0.9.0",
"cfg-if",
"cpufeatures",
"digest 0.9.0",
"opaque-debug",
]
[[package]] [[package]]
name = "sha-1" name = "sha-1"
version = "0.10.1" version = "0.10.1"
@ -7249,15 +7198,15 @@ dependencies = [
[[package]] [[package]]
name = "siphasher" name = "siphasher"
version = "0.3.10" version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.8" version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [ dependencies = [
"autocfg 1.1.0", "autocfg 1.1.0",
] ]
@ -7339,9 +7288,9 @@ checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06"
[[package]] [[package]]
name = "slog-async" name = "slog-async"
version = "2.7.0" version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "766c59b252e62a34651412870ff55d8c4e6d04df19b43eecb2703e417b097ffe" checksum = "72c8038f898a2c79507940990f05386455b3a317d8f18d4caea7cbc3d5096b84"
dependencies = [ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"slog", "slog",
@ -7498,21 +7447,6 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "soketto"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2"
dependencies = [
"base64 0.13.1",
"bytes",
"futures",
"httparse",
"log",
"rand 0.8.5",
"sha-1 0.9.8",
]
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.5.2" version = "0.5.2"
@ -7874,14 +7808,14 @@ dependencies = [
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.7.1" version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"fastrand 2.0.0", "fastrand 2.0.0",
"redox_syscall 0.3.5", "redox_syscall 0.3.5",
"rustix 0.38.8", "rustix 0.38.9",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -7987,9 +7921,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.25" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48"
dependencies = [ dependencies = [
"deranged", "deranged",
"itoa", "itoa",
@ -8008,9 +7942,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.11" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572"
dependencies = [ dependencies = [
"time-core", "time-core",
] ]
@ -8091,7 +8025,7 @@ dependencies = [
"mio", "mio",
"num_cpus", "num_cpus",
"parking_lot 0.12.1", "parking_lot 0.12.1",
"pin-project-lite 0.2.12", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2 0.5.3", "socket2 0.5.3",
"tokio-macros", "tokio-macros",
@ -8104,7 +8038,7 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
dependencies = [ dependencies = [
"pin-project-lite 0.2.12", "pin-project-lite",
"tokio", "tokio",
] ]
@ -8131,9 +8065,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-postgres" name = "tokio-postgres"
version = "0.7.8" version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e89f6234aa8fd43779746012fcf53603cdb91fdd8399aa0de868c2d56b6dde1" checksum = "d340244b32d920260ae7448cb72b6e238bddc3d4f7603394e7dd46ed8e48f5b8"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"byteorder", "byteorder",
@ -8145,12 +8079,14 @@ dependencies = [
"parking_lot 0.12.1", "parking_lot 0.12.1",
"percent-encoding", "percent-encoding",
"phf", "phf",
"pin-project-lite 0.2.12", "pin-project-lite",
"postgres-protocol", "postgres-protocol",
"postgres-types", "postgres-types",
"rand 0.8.5",
"socket2 0.5.3", "socket2 0.5.3",
"tokio", "tokio",
"tokio-util 0.7.8", "tokio-util 0.7.8",
"whoami",
] ]
[[package]] [[package]]
@ -8181,7 +8117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"pin-project-lite 0.2.12", "pin-project-lite",
"tokio", "tokio",
"tokio-util 0.7.8", "tokio-util 0.7.8",
] ]
@ -8225,7 +8161,7 @@ dependencies = [
"futures-io", "futures-io",
"futures-sink", "futures-sink",
"log", "log",
"pin-project-lite 0.2.12", "pin-project-lite",
"slab", "slab",
"tokio", "tokio",
] ]
@ -8239,7 +8175,7 @@ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"pin-project-lite 0.2.12", "pin-project-lite",
"slab", "slab",
"tokio", "tokio",
"tracing", "tracing",
@ -8297,7 +8233,7 @@ dependencies = [
"futures-core", "futures-core",
"futures-util", "futures-util",
"pin-project", "pin-project",
"pin-project-lite 0.2.12", "pin-project-lite",
"tokio", "tokio",
"tower-layer", "tower-layer",
"tower-service", "tower-service",
@ -8324,7 +8260,7 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"log", "log",
"pin-project-lite 0.2.12", "pin-project-lite",
"tracing-attributes", "tracing-attributes",
"tracing-core", "tracing-core",
] ]
@ -8506,7 +8442,7 @@ dependencies = [
"log", "log",
"rand 0.8.5", "rand 0.8.5",
"rustls 0.20.8", "rustls 0.20.8",
"sha-1 0.10.1", "sha-1",
"thiserror", "thiserror",
"url", "url",
"utf-8", "utf-8",
@ -8612,9 +8548,9 @@ checksum = "ccb97dac3243214f8d8507998906ca3e2e0b900bf9bf4870477f125b82e68f6e"
[[package]] [[package]]
name = "unicase" name = "unicase"
version = "2.6.0" version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [ dependencies = [
"version_check", "version_check",
] ]
@ -9007,9 +8943,9 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]] [[package]]
name = "wasm-streams" name = "wasm-streams"
version = "0.2.3" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"js-sys", "js-sys",
@ -9130,6 +9066,16 @@ version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
[[package]]
name = "whoami"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50"
dependencies = [
"wasm-bindgen",
"web-sys",
]
[[package]] [[package]]
name = "widestring" name = "widestring"
version = "0.4.3" version = "0.4.3"
@ -9198,7 +9144,7 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [ dependencies = [
"windows-targets 0.48.3", "windows-targets 0.48.5",
] ]
[[package]] [[package]]
@ -9228,7 +9174,7 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [ dependencies = [
"windows-targets 0.48.3", "windows-targets 0.48.5",
] ]
[[package]] [[package]]
@ -9248,17 +9194,17 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.48.3" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27f51fb4c64f8b770a823c043c7fad036323e1c48f55287b7bbb7987b2fcdf3b" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.48.3", "windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.3", "windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.3", "windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.3", "windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.3", "windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.3", "windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.3", "windows_x86_64_msvc 0.48.5",
] ]
[[package]] [[package]]
@ -9269,9 +9215,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.48.3" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fde1bb55ae4ce76a597a8566d82c57432bc69c039449d61572a7a353da28f68c" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
@ -9287,9 +9233,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.48.3" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1513e8d48365a78adad7322fd6b5e4c4e99d92a69db8df2d435b25b1f1f286d4" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
@ -9305,9 +9251,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.48.3" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60587c0265d2b842298f5858e1a5d79d146f9ee0c37be5782e92a6eb5e1d7a83" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
@ -9323,9 +9269,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.48.3" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224fe0e0ffff5d2ea6a29f82026c8f43870038a0ffc247aa95a52b47df381ac4" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
@ -9341,9 +9287,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.48.3" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62fc52a0f50a088de499712cbc012df7ebd94e2d6eb948435449d76a6287e7ad" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
@ -9353,9 +9299,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.48.3" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2093925509d91ea3d69bcd20238f4c2ecdb1a29d3c281d026a09705d0dd35f3d" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
@ -9371,28 +9317,19 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.48.3" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6ade45bc8bf02ae2aa34a9d54ba660a1a58204da34ba793c00d83ca3730b5f1" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.5.14" version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d09770118a7eb1ccaf4a594a221334119a44a814fcb0d31c5b85e83e97227a97" checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "winreg"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "winreg" name = "winreg"
version = "0.50.0" version = "0.50.0"

View File

@ -46,20 +46,6 @@ impl<T: BeaconChainTypes> Client<T> {
self.http_metrics_listen_addr self.http_metrics_listen_addr
} }
/// Returns the ipv4 port of the client's libp2p stack, if it was started.
pub fn libp2p_listen_ipv4_port(&self) -> Option<u16> {
self.network_globals
.as_ref()
.and_then(|n| n.listen_port_tcp4())
}
/// Returns the ipv6 port of the client's libp2p stack, if it was started.
pub fn libp2p_listen_ipv6_port(&self) -> Option<u16> {
self.network_globals
.as_ref()
.and_then(|n| n.listen_port_tcp6())
}
/// Returns the list of libp2p addresses the client is listening to. /// Returns the list of libp2p addresses the client is listening to.
pub fn libp2p_listen_addresses(&self) -> Option<Vec<Multiaddr>> { pub fn libp2p_listen_addresses(&self) -> Option<Vec<Multiaddr>> {
self.network_globals.as_ref().map(|n| n.listen_multiaddrs()) self.network_globals.as_ref().map(|n| n.listen_multiaddrs())

View File

@ -2825,12 +2825,8 @@ pub fn serve<T: BeaconChainTypes>(
})?; })?;
if let Some(peer_info) = network_globals.peers.read().peer_info(&peer_id) { if let Some(peer_info) = network_globals.peers.read().peer_info(&peer_id) {
let address = if let Some(socket_addr) = peer_info.seen_addresses().next() { let address = if let Some(multiaddr) = peer_info.seen_multiaddrs().next() {
let mut addr = lighthouse_network::Multiaddr::from(socket_addr.ip()); multiaddr.to_string()
addr.push(lighthouse_network::multiaddr::Protocol::Tcp(
socket_addr.port(),
));
addr.to_string()
} else if let Some(addr) = peer_info.listening_addresses().first() { } else if let Some(addr) = peer_info.listening_addresses().first() {
addr.to_string() addr.to_string()
} else { } else {
@ -2878,13 +2874,8 @@ pub fn serve<T: BeaconChainTypes>(
.peers() .peers()
.for_each(|(peer_id, peer_info)| { .for_each(|(peer_id, peer_info)| {
let address = let address =
if let Some(socket_addr) = peer_info.seen_addresses().next() { if let Some(multiaddr) = peer_info.seen_multiaddrs().next() {
let mut addr = multiaddr.to_string()
lighthouse_network::Multiaddr::from(socket_addr.ip());
addr.push(lighthouse_network::multiaddr::Protocol::Tcp(
socket_addr.port(),
));
addr.to_string()
} else if let Some(addr) = peer_info.listening_addresses().first() { } else if let Some(addr) = peer_info.listening_addresses().first() {
addr.to_string() addr.to_string()
} else { } else {

View File

@ -152,8 +152,6 @@ pub async fn create_api_server_on_port<T: BeaconChainTypes>(
let enr = EnrBuilder::new("v4").build(&enr_key).unwrap(); let enr = EnrBuilder::new("v4").build(&enr_key).unwrap();
let network_globals = Arc::new(NetworkGlobals::new( let network_globals = Arc::new(NetworkGlobals::new(
enr.clone(), enr.clone(),
Some(TCP_PORT),
None,
meta_data, meta_data,
vec![], vec![],
false, false,

View File

@ -44,12 +44,13 @@ prometheus-client = "0.21.0"
unused_port = { path = "../../common/unused_port" } unused_port = { path = "../../common/unused_port" }
delay_map = "0.3.0" delay_map = "0.3.0"
void = "1" void = "1"
libp2p-quic= { version = "0.9.2", features=["tokio"]}
libp2p-mplex = "0.40.0" libp2p-mplex = "0.40.0"
[dependencies.libp2p] [dependencies.libp2p]
version = "0.52" version = "0.52"
default-features = false default-features = false
features = ["websocket", "identify", "yamux", "noise", "gossipsub", "dns", "tcp", "tokio", "plaintext", "secp256k1", "macros", "ecdsa"] features = ["identify", "yamux", "noise", "gossipsub", "dns", "tcp", "tokio", "plaintext", "secp256k1", "macros", "ecdsa"]
[dev-dependencies] [dev-dependencies]
slog-term = "2.6.0" slog-term = "2.6.0"
@ -59,6 +60,3 @@ exit-future = "0.2.0"
void = "1" void = "1"
quickcheck = "0.9.2" quickcheck = "0.9.2"
quickcheck_macros = "0.9.1" quickcheck_macros = "0.9.1"
[features]
libp2p-websocket = []

View File

@ -58,18 +58,24 @@ pub struct Config {
/// that no discovery address has been set in the CLI args. /// that no discovery address has been set in the CLI args.
pub enr_address: (Option<Ipv4Addr>, Option<Ipv6Addr>), pub enr_address: (Option<Ipv4Addr>, Option<Ipv6Addr>),
/// The udp4 port to broadcast to peers in order to reach back for discovery. /// The udp ipv4 port to broadcast to peers in order to reach back for discovery.
pub enr_udp4_port: Option<u16>, pub enr_udp4_port: Option<u16>,
/// The tcp4 port to broadcast to peers in order to reach back for libp2p services. /// The quic ipv4 port to broadcast to peers in order to reach back for libp2p services.
pub enr_quic4_port: Option<u16>,
/// The tcp ipv4 port to broadcast to peers in order to reach back for libp2p services.
pub enr_tcp4_port: Option<u16>, pub enr_tcp4_port: Option<u16>,
/// The udp6 port to broadcast to peers in order to reach back for discovery. /// The udp ipv6 port to broadcast to peers in order to reach back for discovery.
pub enr_udp6_port: Option<u16>, pub enr_udp6_port: Option<u16>,
/// The tcp6 port to broadcast to peers in order to reach back for libp2p services. /// The tcp ipv6 port to broadcast to peers in order to reach back for libp2p services.
pub enr_tcp6_port: Option<u16>, pub enr_tcp6_port: Option<u16>,
/// The quic ipv6 port to broadcast to peers in order to reach back for libp2p services.
pub enr_quic6_port: Option<u16>,
/// Target number of connected peers. /// Target number of connected peers.
pub target_peers: usize, pub target_peers: usize,
@ -102,6 +108,9 @@ pub struct Config {
/// Disables the discovery protocol from starting. /// Disables the discovery protocol from starting.
pub disable_discovery: bool, pub disable_discovery: bool,
/// Disables quic support.
pub disable_quic_support: bool,
/// Attempt to construct external port mappings with UPnP. /// Attempt to construct external port mappings with UPnP.
pub upnp_enabled: bool, pub upnp_enabled: bool,
@ -149,57 +158,76 @@ impl Config {
/// Sets the listening address to use an ipv4 address. The discv5 ip_mode and table filter are /// Sets the listening address to use an ipv4 address. The discv5 ip_mode and table filter are
/// adjusted accordingly to ensure addresses that are present in the enr are globally /// adjusted accordingly to ensure addresses that are present in the enr are globally
/// reachable. /// reachable.
pub fn set_ipv4_listening_address(&mut self, addr: Ipv4Addr, tcp_port: u16, udp_port: u16) { pub fn set_ipv4_listening_address(
&mut self,
addr: Ipv4Addr,
tcp_port: u16,
disc_port: u16,
quic_port: u16,
) {
self.listen_addresses = ListenAddress::V4(ListenAddr { self.listen_addresses = ListenAddress::V4(ListenAddr {
addr, addr,
udp_port, disc_port,
quic_port,
tcp_port, tcp_port,
}); });
self.discv5_config.listen_config = discv5::ListenConfig::from_ip(addr.into(), udp_port); self.discv5_config.listen_config = discv5::ListenConfig::from_ip(addr.into(), disc_port);
self.discv5_config.table_filter = |enr| enr.ip4().as_ref().map_or(false, is_global_ipv4) self.discv5_config.table_filter = |enr| enr.ip4().as_ref().map_or(false, is_global_ipv4)
} }
/// Sets the listening address to use an ipv6 address. The discv5 ip_mode and table filter is /// Sets the listening address to use an ipv6 address. The discv5 ip_mode and table filter is
/// adjusted accordingly to ensure addresses that are present in the enr are globally /// adjusted accordingly to ensure addresses that are present in the enr are globally
/// reachable. /// reachable.
pub fn set_ipv6_listening_address(&mut self, addr: Ipv6Addr, tcp_port: u16, udp_port: u16) { pub fn set_ipv6_listening_address(
&mut self,
addr: Ipv6Addr,
tcp_port: u16,
disc_port: u16,
quic_port: u16,
) {
self.listen_addresses = ListenAddress::V6(ListenAddr { self.listen_addresses = ListenAddress::V6(ListenAddr {
addr, addr,
udp_port, disc_port,
quic_port,
tcp_port, tcp_port,
}); });
self.discv5_config.listen_config = discv5::ListenConfig::from_ip(addr.into(), udp_port); self.discv5_config.listen_config = discv5::ListenConfig::from_ip(addr.into(), disc_port);
self.discv5_config.table_filter = |enr| enr.ip6().as_ref().map_or(false, is_global_ipv6) self.discv5_config.table_filter = |enr| enr.ip6().as_ref().map_or(false, is_global_ipv6)
} }
/// Sets the listening address to use both an ipv4 and ipv6 address. The discv5 ip_mode and /// Sets the listening address to use both an ipv4 and ipv6 address. The discv5 ip_mode and
/// table filter is adjusted accordingly to ensure addresses that are present in the enr are /// table filter is adjusted accordingly to ensure addresses that are present in the enr are
/// globally reachable. /// globally reachable.
#[allow(clippy::too_many_arguments)]
pub fn set_ipv4_ipv6_listening_addresses( pub fn set_ipv4_ipv6_listening_addresses(
&mut self, &mut self,
v4_addr: Ipv4Addr, v4_addr: Ipv4Addr,
tcp4_port: u16, tcp4_port: u16,
udp4_port: u16, disc4_port: u16,
quic4_port: u16,
v6_addr: Ipv6Addr, v6_addr: Ipv6Addr,
tcp6_port: u16, tcp6_port: u16,
udp6_port: u16, disc6_port: u16,
quic6_port: u16,
) { ) {
self.listen_addresses = ListenAddress::DualStack( self.listen_addresses = ListenAddress::DualStack(
ListenAddr { ListenAddr {
addr: v4_addr, addr: v4_addr,
udp_port: udp4_port, disc_port: disc4_port,
quic_port: quic4_port,
tcp_port: tcp4_port, tcp_port: tcp4_port,
}, },
ListenAddr { ListenAddr {
addr: v6_addr, addr: v6_addr,
udp_port: udp6_port, disc_port: disc6_port,
quic_port: quic6_port,
tcp_port: tcp6_port, tcp_port: tcp6_port,
}, },
); );
self.discv5_config.listen_config = discv5::ListenConfig::default() self.discv5_config.listen_config = discv5::ListenConfig::default()
.with_ipv4(v4_addr, udp4_port) .with_ipv4(v4_addr, disc4_port)
.with_ipv6(v6_addr, udp6_port); .with_ipv6(v6_addr, disc6_port);
self.discv5_config.table_filter = |enr| match (&enr.ip4(), &enr.ip6()) { self.discv5_config.table_filter = |enr| match (&enr.ip4(), &enr.ip6()) {
(None, None) => false, (None, None) => false,
@ -213,27 +241,32 @@ impl Config {
match listen_addr { match listen_addr {
ListenAddress::V4(ListenAddr { ListenAddress::V4(ListenAddr {
addr, addr,
udp_port, disc_port,
quic_port,
tcp_port, tcp_port,
}) => self.set_ipv4_listening_address(addr, tcp_port, udp_port), }) => self.set_ipv4_listening_address(addr, tcp_port, disc_port, quic_port),
ListenAddress::V6(ListenAddr { ListenAddress::V6(ListenAddr {
addr, addr,
udp_port, disc_port,
quic_port,
tcp_port, tcp_port,
}) => self.set_ipv6_listening_address(addr, tcp_port, udp_port), }) => self.set_ipv6_listening_address(addr, tcp_port, disc_port, quic_port),
ListenAddress::DualStack( ListenAddress::DualStack(
ListenAddr { ListenAddr {
addr: ip4addr, addr: ip4addr,
udp_port: udp4_port, disc_port: disc4_port,
quic_port: quic4_port,
tcp_port: tcp4_port, tcp_port: tcp4_port,
}, },
ListenAddr { ListenAddr {
addr: ip6addr, addr: ip6addr,
udp_port: udp6_port, disc_port: disc6_port,
quic_port: quic6_port,
tcp_port: tcp6_port, tcp_port: tcp6_port,
}, },
) => self.set_ipv4_ipv6_listening_addresses( ) => self.set_ipv4_ipv6_listening_addresses(
ip4addr, tcp4_port, udp4_port, ip6addr, tcp6_port, udp6_port, ip4addr, tcp4_port, disc4_port, quic4_port, ip6addr, tcp6_port, disc6_port,
quic6_port,
), ),
} }
} }
@ -272,7 +305,8 @@ impl Default for Config {
); );
let listen_addresses = ListenAddress::V4(ListenAddr { let listen_addresses = ListenAddress::V4(ListenAddr {
addr: Ipv4Addr::UNSPECIFIED, addr: Ipv4Addr::UNSPECIFIED,
udp_port: 9000, disc_port: 9000,
quic_port: 9001,
tcp_port: 9000, tcp_port: 9000,
}); });
@ -305,10 +339,11 @@ impl Default for Config {
network_dir, network_dir,
listen_addresses, listen_addresses,
enr_address: (None, None), enr_address: (None, None),
enr_udp4_port: None, enr_udp4_port: None,
enr_quic4_port: None,
enr_tcp4_port: None, enr_tcp4_port: None,
enr_udp6_port: None, enr_udp6_port: None,
enr_quic6_port: None,
enr_tcp6_port: None, enr_tcp6_port: None,
target_peers: 50, target_peers: 50,
gs_config, gs_config,
@ -320,6 +355,7 @@ impl Default for Config {
disable_peer_scoring: false, disable_peer_scoring: false,
client_version: lighthouse_version::version_with_platform(), client_version: lighthouse_version::version_with_platform(),
disable_discovery: false, disable_discovery: false,
disable_quic_support: false,
upnp_enabled: true, upnp_enabled: true,
network_load: 3, network_load: 3,
private: false, private: false,

View File

@ -17,6 +17,8 @@ use std::path::Path;
use std::str::FromStr; use std::str::FromStr;
use types::{EnrForkId, EthSpec}; use types::{EnrForkId, EthSpec};
use super::enr_ext::{EnrExt, QUIC6_ENR_KEY, QUIC_ENR_KEY};
/// The ENR field specifying the fork id. /// The ENR field specifying the fork id.
pub const ETH2_ENR_KEY: &str = "eth2"; pub const ETH2_ENR_KEY: &str = "eth2";
/// The ENR field specifying the attestation subnet bitfield. /// The ENR field specifying the attestation subnet bitfield.
@ -142,7 +144,7 @@ pub fn build_or_load_enr<T: EthSpec>(
pub fn create_enr_builder_from_config<T: EnrKey>( pub fn create_enr_builder_from_config<T: EnrKey>(
config: &NetworkConfig, config: &NetworkConfig,
enable_tcp: bool, enable_libp2p: bool,
) -> EnrBuilder<T> { ) -> EnrBuilder<T> {
let mut builder = EnrBuilder::new("v4"); let mut builder = EnrBuilder::new("v4");
let (maybe_ipv4_address, maybe_ipv6_address) = &config.enr_address; let (maybe_ipv4_address, maybe_ipv6_address) = &config.enr_address;
@ -163,7 +165,28 @@ pub fn create_enr_builder_from_config<T: EnrKey>(
builder.udp6(udp6_port); builder.udp6(udp6_port);
} }
if enable_tcp { if enable_libp2p {
// Add QUIC fields to the ENR.
// Since QUIC is used as an alternative transport for the libp2p protocols,
// the related fields should only be added when both QUIC and libp2p are enabled
if !config.disable_quic_support {
// If we are listening on ipv4, add the quic ipv4 port.
if let Some(quic4_port) = config
.enr_quic4_port
.or_else(|| config.listen_addrs().v4().map(|v4_addr| v4_addr.quic_port))
{
builder.add_value(QUIC_ENR_KEY, &quic4_port);
}
// If we are listening on ipv6, add the quic ipv6 port.
if let Some(quic6_port) = config
.enr_quic6_port
.or_else(|| config.listen_addrs().v6().map(|v6_addr| v6_addr.quic_port))
{
builder.add_value(QUIC6_ENR_KEY, &quic6_port);
}
}
// If the ENR port is not set, and we are listening over that ip version, use the listening port instead. // If the ENR port is not set, and we are listening over that ip version, use the listening port instead.
let tcp4_port = config let tcp4_port = config
.enr_tcp4_port .enr_tcp4_port
@ -218,6 +241,9 @@ fn compare_enr(local_enr: &Enr, disk_enr: &Enr) -> bool {
// tcp ports must match // tcp ports must match
&& local_enr.tcp4() == disk_enr.tcp4() && local_enr.tcp4() == disk_enr.tcp4()
&& local_enr.tcp6() == disk_enr.tcp6() && local_enr.tcp6() == disk_enr.tcp6()
// quic ports must match
&& local_enr.quic4() == disk_enr.quic4()
&& local_enr.quic6() == disk_enr.quic6()
// must match on the same fork // must match on the same fork
&& local_enr.get(ETH2_ENR_KEY) == disk_enr.get(ETH2_ENR_KEY) && local_enr.get(ETH2_ENR_KEY) == disk_enr.get(ETH2_ENR_KEY)
// take preference over disk udp port if one is not specified // take preference over disk udp port if one is not specified

View File

@ -6,12 +6,15 @@ use libp2p::core::multiaddr::Protocol;
use libp2p::identity::{ed25519, secp256k1, KeyType, Keypair, PublicKey}; use libp2p::identity::{ed25519, secp256k1, KeyType, Keypair, PublicKey};
use tiny_keccak::{Hasher, Keccak}; use tiny_keccak::{Hasher, Keccak};
pub const QUIC_ENR_KEY: &str = "quic";
pub const QUIC6_ENR_KEY: &str = "quic6";
/// Extend ENR for libp2p types. /// Extend ENR for libp2p types.
pub trait EnrExt { pub trait EnrExt {
/// The libp2p `PeerId` for the record. /// The libp2p `PeerId` for the record.
fn peer_id(&self) -> PeerId; fn peer_id(&self) -> PeerId;
/// Returns a list of multiaddrs if the ENR has an `ip` and either a `tcp` or `udp` key **or** an `ip6` and either a `tcp6` or `udp6`. /// Returns a list of multiaddrs if the ENR has an `ip` and one of [`tcp`,`udp`,`quic`] key **or** an `ip6` and one of [`tcp6`,`udp6`,`quic6`].
/// The vector remains empty if these fields are not defined. /// The vector remains empty if these fields are not defined.
fn multiaddr(&self) -> Vec<Multiaddr>; fn multiaddr(&self) -> Vec<Multiaddr>;
@ -26,6 +29,15 @@ pub trait EnrExt {
/// Returns any multiaddrs that contain the TCP protocol. /// Returns any multiaddrs that contain the TCP protocol.
fn multiaddr_tcp(&self) -> Vec<Multiaddr>; fn multiaddr_tcp(&self) -> Vec<Multiaddr>;
/// Returns any QUIC multiaddrs that are registered in this ENR.
fn multiaddr_quic(&self) -> Vec<Multiaddr>;
/// Returns the quic port if one is set.
fn quic4(&self) -> Option<u16>;
/// Returns the quic6 port if one is set.
fn quic6(&self) -> Option<u16>;
} }
/// Extend ENR CombinedPublicKey for libp2p types. /// Extend ENR CombinedPublicKey for libp2p types.
@ -49,7 +61,17 @@ impl EnrExt for Enr {
self.public_key().as_peer_id() self.public_key().as_peer_id()
} }
/// Returns a list of multiaddrs if the ENR has an `ip` and either a `tcp` or `udp` key **or** an `ip6` and either a `tcp6` or `udp6`. /// Returns the quic port if one is set.
fn quic4(&self) -> Option<u16> {
self.get_decodable(QUIC_ENR_KEY).and_then(Result::ok)
}
/// Returns the quic6 port if one is set.
fn quic6(&self) -> Option<u16> {
self.get_decodable(QUIC6_ENR_KEY).and_then(Result::ok)
}
/// Returns a list of multiaddrs if the ENR has an `ip` and either a `tcp`, `quic` or `udp` key **or** an `ip6` and either a `tcp6` `quic6` or `udp6`.
/// The vector remains empty if these fields are not defined. /// The vector remains empty if these fields are not defined.
fn multiaddr(&self) -> Vec<Multiaddr> { fn multiaddr(&self) -> Vec<Multiaddr> {
let mut multiaddrs: Vec<Multiaddr> = Vec::new(); let mut multiaddrs: Vec<Multiaddr> = Vec::new();
@ -59,6 +81,12 @@ impl EnrExt for Enr {
multiaddr.push(Protocol::Udp(udp)); multiaddr.push(Protocol::Udp(udp));
multiaddrs.push(multiaddr); multiaddrs.push(multiaddr);
} }
if let Some(quic) = self.quic4() {
let mut multiaddr: Multiaddr = ip.into();
multiaddr.push(Protocol::Udp(quic));
multiaddr.push(Protocol::QuicV1);
multiaddrs.push(multiaddr);
}
if let Some(tcp) = self.tcp4() { if let Some(tcp) = self.tcp4() {
let mut multiaddr: Multiaddr = ip.into(); let mut multiaddr: Multiaddr = ip.into();
@ -73,6 +101,13 @@ impl EnrExt for Enr {
multiaddrs.push(multiaddr); multiaddrs.push(multiaddr);
} }
if let Some(quic6) = self.quic6() {
let mut multiaddr: Multiaddr = ip6.into();
multiaddr.push(Protocol::Udp(quic6));
multiaddr.push(Protocol::QuicV1);
multiaddrs.push(multiaddr);
}
if let Some(tcp6) = self.tcp6() { if let Some(tcp6) = self.tcp6() {
let mut multiaddr: Multiaddr = ip6.into(); let mut multiaddr: Multiaddr = ip6.into();
multiaddr.push(Protocol::Tcp(tcp6)); multiaddr.push(Protocol::Tcp(tcp6));
@ -174,8 +209,30 @@ impl EnrExt for Enr {
multiaddrs multiaddrs
} }
/// Returns a list of multiaddrs if the ENR has an `ip` and a `quic` key **or** an `ip6` and a `quic6`.
fn multiaddr_quic(&self) -> Vec<Multiaddr> {
let mut multiaddrs: Vec<Multiaddr> = Vec::new();
if let Some(quic_port) = self.quic4() {
if let Some(ip) = self.ip4() {
let mut multiaddr: Multiaddr = ip.into();
multiaddr.push(Protocol::Udp(quic_port));
multiaddr.push(Protocol::QuicV1);
multiaddrs.push(multiaddr);
}
}
if let Some(quic6_port) = self.quic6() {
if let Some(ip6) = self.ip6() {
let mut multiaddr: Multiaddr = ip6.into();
multiaddr.push(Protocol::Udp(quic6_port));
multiaddr.push(Protocol::QuicV1);
multiaddrs.push(multiaddr);
}
}
multiaddrs
}
/// Returns a list of multiaddrs if the ENR has an `ip` and either a `tcp` or `udp` key **or** an `ip6` and either a `tcp6` or `udp6`. /// Returns a list of multiaddrs if the ENR has an `ip` and either a `tcp` or `udp` key **or** an `ip6` and either a `tcp6` or `udp6`.
/// The vector remains empty if these fields are not defined.
fn multiaddr_tcp(&self) -> Vec<Multiaddr> { fn multiaddr_tcp(&self) -> Vec<Multiaddr> {
let mut multiaddrs: Vec<Multiaddr> = Vec::new(); let mut multiaddrs: Vec<Multiaddr> = Vec::new();
if let Some(ip) = self.ip4() { if let Some(ip) = self.ip4() {

View File

@ -21,7 +21,6 @@ pub use libp2p::identity::{Keypair, PublicKey};
use enr::{ATTESTATION_BITFIELD_ENR_KEY, ETH2_ENR_KEY, SYNC_COMMITTEE_BITFIELD_ENR_KEY}; use enr::{ATTESTATION_BITFIELD_ENR_KEY, ETH2_ENR_KEY, SYNC_COMMITTEE_BITFIELD_ENR_KEY};
use futures::prelude::*; use futures::prelude::*;
use futures::stream::FuturesUnordered; use futures::stream::FuturesUnordered;
use libp2p::multiaddr::Protocol;
use libp2p::swarm::behaviour::{DialFailure, FromSwarm}; use libp2p::swarm::behaviour::{DialFailure, FromSwarm};
use libp2p::swarm::THandlerInEvent; use libp2p::swarm::THandlerInEvent;
pub use libp2p::{ pub use libp2p::{
@ -75,7 +74,7 @@ const DURATION_DIFFERENCE: Duration = Duration::from_millis(1);
/// of the peer if it is specified. /// of the peer if it is specified.
#[derive(Debug)] #[derive(Debug)]
pub struct DiscoveredPeers { pub struct DiscoveredPeers {
pub peers: HashMap<PeerId, Option<Instant>>, pub peers: HashMap<Enr, Option<Instant>>,
} }
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
@ -208,7 +207,8 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
let local_node_id = local_enr.node_id(); let local_node_id = local_enr.node_id();
info!(log, "ENR Initialised"; "enr" => local_enr.to_base64(), "seq" => local_enr.seq(), "id"=> %local_enr.node_id(), info!(log, "ENR Initialised"; "enr" => local_enr.to_base64(), "seq" => local_enr.seq(), "id"=> %local_enr.node_id(),
"ip4" => ?local_enr.ip4(), "udp4"=> ?local_enr.udp4(), "tcp4" => ?local_enr.tcp4(), "tcp6" => ?local_enr.tcp6(), "udp6" => ?local_enr.udp6() "ip4" => ?local_enr.ip4(), "udp4"=> ?local_enr.udp4(), "tcp4" => ?local_enr.tcp4(), "tcp6" => ?local_enr.tcp6(), "udp6" => ?local_enr.udp6(),
"quic4" => ?local_enr.quic4(), "quic6" => ?local_enr.quic6()
); );
// convert the keypair into an ENR key // convert the keypair into an ENR key
@ -230,7 +230,8 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
"peer_id" => %bootnode_enr.peer_id(), "peer_id" => %bootnode_enr.peer_id(),
"ip" => ?bootnode_enr.ip4(), "ip" => ?bootnode_enr.ip4(),
"udp" => ?bootnode_enr.udp4(), "udp" => ?bootnode_enr.udp4(),
"tcp" => ?bootnode_enr.tcp4() "tcp" => ?bootnode_enr.tcp4(),
"quic" => ?bootnode_enr.quic4()
); );
let repr = bootnode_enr.to_string(); let repr = bootnode_enr.to_string();
let _ = discv5.add_enr(bootnode_enr).map_err(|e| { let _ = discv5.add_enr(bootnode_enr).map_err(|e| {
@ -281,7 +282,8 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
"peer_id" => %enr.peer_id(), "peer_id" => %enr.peer_id(),
"ip" => ?enr.ip4(), "ip" => ?enr.ip4(),
"udp" => ?enr.udp4(), "udp" => ?enr.udp4(),
"tcp" => ?enr.tcp4() "tcp" => ?enr.tcp4(),
"quic" => ?enr.quic4()
); );
let _ = discv5.add_enr(enr).map_err(|e| { let _ = discv5.add_enr(enr).map_err(|e| {
error!( error!(
@ -383,20 +385,6 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
self.discv5.table_entries_enr() self.discv5.table_entries_enr()
} }
/// Returns the ENR of a known peer if it exists.
pub fn enr_of_peer(&mut self, peer_id: &PeerId) -> Option<Enr> {
// first search the local cache
if let Some(enr) = self.cached_enrs.get(peer_id) {
return Some(enr.clone());
}
// not in the local cache, look in the routing table
if let Ok(node_id) = enr_ext::peer_id_to_node_id(peer_id) {
self.discv5.find_enr(&node_id)
} else {
None
}
}
/// Updates the local ENR TCP port. /// Updates the local ENR TCP port.
/// There currently isn't a case to update the address here. We opt for discovery to /// There currently isn't a case to update the address here. We opt for discovery to
/// automatically update the external address. /// automatically update the external address.
@ -414,6 +402,23 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
Ok(()) Ok(())
} }
// TODO: Group these functions here once the ENR is shared across discv5 and lighthouse and
// Lighthouse can modify the ENR directly.
// This currently doesn't support ipv6. All of these functions should be removed and
// addressed properly in the following issue.
// https://github.com/sigp/lighthouse/issues/4706
pub fn update_enr_quic_port(&mut self, port: u16) -> Result<(), String> {
self.discv5
.enr_insert("quic", &port)
.map_err(|e| format!("{:?}", e))?;
// replace the global version
*self.network_globals.local_enr.write() = self.discv5.local_enr();
// persist modified enr to disk
enr::save_enr_to_disk(Path::new(&self.enr_dir), &self.local_enr(), &self.log);
Ok(())
}
/// Updates the local ENR UDP socket. /// Updates the local ENR UDP socket.
/// ///
/// This is with caution. Discovery should automatically maintain this. This should only be /// This is with caution. Discovery should automatically maintain this. This should only be
@ -733,23 +738,6 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
target_peers: usize, target_peers: usize,
additional_predicate: impl Fn(&Enr) -> bool + Send + 'static, additional_predicate: impl Fn(&Enr) -> bool + Send + 'static,
) { ) {
// Make sure there are subnet queries included
let contains_queries = match &query {
QueryType::Subnet(queries) => !queries.is_empty(),
QueryType::FindPeers => true,
};
if !contains_queries {
debug!(
self.log,
"No subnets included in this request. Skipping discovery request."
);
return;
}
// Generate a random target node id.
let random_node = NodeId::random();
let enr_fork_id = match self.local_enr().eth2() { let enr_fork_id = match self.local_enr().eth2() {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(e) => {
@ -773,7 +761,8 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
// Build the future // Build the future
let query_future = self let query_future = self
.discv5 .discv5
.find_node_predicate(random_node, predicate, target_peers) // Generate a random target node id.
.find_node_predicate(NodeId::random(), predicate, target_peers)
.map(|v| QueryResult { .map(|v| QueryResult {
query_type: query, query_type: query,
result: v, result: v,
@ -787,7 +776,7 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
fn process_completed_queries( fn process_completed_queries(
&mut self, &mut self,
query: QueryResult, query: QueryResult,
) -> Option<HashMap<PeerId, Option<Instant>>> { ) -> Option<HashMap<Enr, Option<Instant>>> {
match query.query_type { match query.query_type {
QueryType::FindPeers => { QueryType::FindPeers => {
self.find_peer_active = false; self.find_peer_active = false;
@ -797,12 +786,14 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
} }
Ok(r) => { Ok(r) => {
debug!(self.log, "Discovery query completed"; "peers_found" => r.len()); debug!(self.log, "Discovery query completed"; "peers_found" => r.len());
let mut results: HashMap<_, Option<Instant>> = HashMap::new(); let results = r
r.iter().for_each(|enr| { .into_iter()
.map(|enr| {
// cache the found ENR's // cache the found ENR's
self.cached_enrs.put(enr.peer_id(), enr.clone()); self.cached_enrs.put(enr.peer_id(), enr.clone());
results.insert(enr.peer_id(), None); (enr, None)
}); })
.collect();
return Some(results); return Some(results);
} }
Err(e) => { Err(e) => {
@ -850,17 +841,17 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
let subnet_predicate = let subnet_predicate =
subnet_predicate::<TSpec>(vec![query.subnet], &self.log); subnet_predicate::<TSpec>(vec![query.subnet], &self.log);
r.iter() r.clone()
.into_iter()
.filter(|enr| subnet_predicate(enr)) .filter(|enr| subnet_predicate(enr))
.map(|enr| enr.peer_id()) .for_each(|enr| {
.for_each(|peer_id| {
if let Some(v) = metrics::get_int_counter( if let Some(v) = metrics::get_int_counter(
&metrics::SUBNET_PEERS_FOUND, &metrics::SUBNET_PEERS_FOUND,
&[query_str], &[query_str],
) { ) {
v.inc(); v.inc();
} }
let other_min_ttl = mapped_results.get_mut(&peer_id); let other_min_ttl = mapped_results.get_mut(&enr);
// map peer IDs to the min_ttl furthest in the future // map peer IDs to the min_ttl furthest in the future
match (query.min_ttl, other_min_ttl) { match (query.min_ttl, other_min_ttl) {
@ -878,15 +869,11 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
} }
// update the mapping if we have a specified min_ttl // update the mapping if we have a specified min_ttl
(Some(min_ttl), Some(None)) => { (Some(min_ttl), Some(None)) => {
mapped_results.insert(peer_id, Some(min_ttl)); mapped_results.insert(enr, Some(min_ttl));
} }
// first seen min_ttl for this enr // first seen min_ttl for this enr
(Some(min_ttl), None) => { (min_ttl, None) => {
mapped_results.insert(peer_id, Some(min_ttl)); mapped_results.insert(enr, min_ttl);
}
// first seen min_ttl for this enr
(None, None) => {
mapped_results.insert(peer_id, None);
} }
(None, Some(Some(_))) => {} // Don't replace the existing specific min_ttl (None, Some(Some(_))) => {} // Don't replace the existing specific min_ttl
(None, Some(None)) => {} // No-op because this is a duplicate (None, Some(None)) => {} // No-op because this is a duplicate
@ -910,7 +897,7 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
} }
/// Drives the queries returning any results from completed queries. /// Drives the queries returning any results from completed queries.
fn poll_queries(&mut self, cx: &mut Context) -> Option<HashMap<PeerId, Option<Instant>>> { fn poll_queries(&mut self, cx: &mut Context) -> Option<HashMap<Enr, Option<Instant>>> {
while let Poll::Ready(Some(query_result)) = self.active_queries.poll_next_unpin(cx) { while let Poll::Ready(Some(query_result)) = self.active_queries.poll_next_unpin(cx) {
let result = self.process_completed_queries(query_result); let result = self.process_completed_queries(query_result);
if result.is_some() { if result.is_some() {
@ -957,23 +944,6 @@ impl<TSpec: EthSpec> NetworkBehaviour for Discovery<TSpec> {
) { ) {
} }
fn handle_pending_outbound_connection(
&mut self,
_connection_id: ConnectionId,
maybe_peer: Option<PeerId>,
_addresses: &[Multiaddr],
_effective_role: libp2p::core::Endpoint,
) -> Result<Vec<Multiaddr>, libp2p::swarm::ConnectionDenied> {
if let Some(enr) = maybe_peer.and_then(|peer_id| self.enr_of_peer(&peer_id)) {
// ENR's may have multiple Multiaddrs. The multi-addr associated with the UDP
// port is removed, which is assumed to be associated with the discv5 protocol (and
// therefore irrelevant for other libp2p components).
Ok(enr.multiaddr_tcp())
} else {
Ok(vec![])
}
}
// Main execution loop to drive the behaviour // Main execution loop to drive the behaviour
fn poll( fn poll(
&mut self, &mut self,
@ -1047,25 +1017,8 @@ impl<TSpec: EthSpec> NetworkBehaviour for Discovery<TSpec> {
// update network globals // update network globals
*self.network_globals.local_enr.write() = enr; *self.network_globals.local_enr.write() = enr;
// A new UDP socket has been detected. // A new UDP socket has been detected.
// Build a multiaddr to report to libp2p // NOTE: We assume libp2p itself can keep track of IP changes and we do
let addr = match socket_addr.ip() { // not inform it about IP changes found via discovery.
IpAddr::V4(v4_addr) => {
self.network_globals.listen_port_tcp4().map(|tcp4_port| {
Multiaddr::from(v4_addr).with(Protocol::Tcp(tcp4_port))
})
}
IpAddr::V6(v6_addr) => {
self.network_globals.listen_port_tcp6().map(|tcp6_port| {
Multiaddr::from(v6_addr).with(Protocol::Tcp(tcp6_port))
})
}
};
if let Some(address) = addr {
// NOTE: This doesn't actually track the external TCP port. More sophisticated NAT handling
// should handle this.
return Poll::Ready(ToSwarm::NewExternalAddrCandidate(address));
}
} }
Discv5Event::EnrAdded { .. } Discv5Event::EnrAdded { .. }
| Discv5Event::TalkRequest(_) | Discv5Event::TalkRequest(_)
@ -1152,8 +1105,6 @@ mod tests {
let log = build_log(slog::Level::Debug, false); let log = build_log(slog::Level::Debug, false);
let globals = NetworkGlobals::new( let globals = NetworkGlobals::new(
enr, enr,
Some(9000),
None,
MetaData::V2(MetaDataV2 { MetaData::V2(MetaDataV2 {
seq_number: 0, seq_number: 0,
attnets: Default::default(), attnets: Default::default(),
@ -1261,6 +1212,6 @@ mod tests {
assert_eq!(results.len(), 2); assert_eq!(results.len(), 2);
// when a peer belongs to multiple subnet ids, we use the highest ttl. // when a peer belongs to multiple subnet ids, we use the highest ttl.
assert_eq!(results.get(&enr1.peer_id()).unwrap(), &instant1); assert_eq!(results.get(&enr1).unwrap(), &instant1);
} }
} }

View File

@ -6,14 +6,23 @@ use serde::{Deserialize, Serialize};
/// A listening address composed by an Ip, an UDP port and a TCP port. /// A listening address composed by an Ip, an UDP port and a TCP port.
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ListenAddr<Ip> { pub struct ListenAddr<Ip> {
/// The IP address we will listen on.
pub addr: Ip, pub addr: Ip,
pub udp_port: u16, /// The UDP port that discovery will listen on.
pub disc_port: u16,
/// The UDP port that QUIC will listen on.
pub quic_port: u16,
/// The TCP port that libp2p will listen on.
pub tcp_port: u16, pub tcp_port: u16,
} }
impl<Ip: Into<IpAddr> + Clone> ListenAddr<Ip> { impl<Ip: Into<IpAddr> + Clone> ListenAddr<Ip> {
pub fn udp_socket_addr(&self) -> SocketAddr { pub fn discovery_socket_addr(&self) -> SocketAddr {
(self.addr.clone().into(), self.udp_port).into() (self.addr.clone().into(), self.disc_port).into()
}
pub fn quic_socket_addr(&self) -> SocketAddr {
(self.addr.clone().into(), self.quic_port).into()
} }
pub fn tcp_socket_addr(&self) -> SocketAddr { pub fn tcp_socket_addr(&self) -> SocketAddr {
@ -46,22 +55,41 @@ impl ListenAddress {
} }
} }
/// Returns the TCP addresses. /// Returns the addresses the Swarm will listen on, given the setup.
pub fn tcp_addresses(&self) -> impl Iterator<Item = Multiaddr> + '_ { pub fn libp2p_addresses(&self) -> impl Iterator<Item = Multiaddr> {
let v4_multiaddr = self let v4_tcp_multiaddr = self
.v4() .v4()
.map(|v4_addr| Multiaddr::from(v4_addr.addr).with(Protocol::Tcp(v4_addr.tcp_port))); .map(|v4_addr| Multiaddr::from(v4_addr.addr).with(Protocol::Tcp(v4_addr.tcp_port)));
let v6_multiaddr = self
let v4_quic_multiaddr = self.v4().map(|v4_addr| {
Multiaddr::from(v4_addr.addr)
.with(Protocol::Udp(v4_addr.quic_port))
.with(Protocol::QuicV1)
});
let v6_quic_multiaddr = self.v6().map(|v6_addr| {
Multiaddr::from(v6_addr.addr)
.with(Protocol::Udp(v6_addr.quic_port))
.with(Protocol::QuicV1)
});
let v6_tcp_multiaddr = self
.v6() .v6()
.map(|v6_addr| Multiaddr::from(v6_addr.addr).with(Protocol::Tcp(v6_addr.tcp_port))); .map(|v6_addr| Multiaddr::from(v6_addr.addr).with(Protocol::Tcp(v6_addr.tcp_port)));
v4_multiaddr.into_iter().chain(v6_multiaddr)
v4_tcp_multiaddr
.into_iter()
.chain(v4_quic_multiaddr)
.chain(v6_quic_multiaddr)
.chain(v6_tcp_multiaddr)
} }
#[cfg(test)] #[cfg(test)]
pub fn unused_v4_ports() -> Self { pub fn unused_v4_ports() -> Self {
ListenAddress::V4(ListenAddr { ListenAddress::V4(ListenAddr {
addr: Ipv4Addr::UNSPECIFIED, addr: Ipv4Addr::UNSPECIFIED,
udp_port: unused_port::unused_udp4_port().unwrap(), disc_port: unused_port::unused_udp4_port().unwrap(),
quic_port: unused_port::unused_udp4_port().unwrap(),
tcp_port: unused_port::unused_tcp4_port().unwrap(), tcp_port: unused_port::unused_tcp4_port().unwrap(),
}) })
} }
@ -70,7 +98,8 @@ impl ListenAddress {
pub fn unused_v6_ports() -> Self { pub fn unused_v6_ports() -> Self {
ListenAddress::V6(ListenAddr { ListenAddress::V6(ListenAddr {
addr: Ipv6Addr::UNSPECIFIED, addr: Ipv6Addr::UNSPECIFIED,
udp_port: unused_port::unused_udp6_port().unwrap(), disc_port: unused_port::unused_udp6_port().unwrap(),
quic_port: unused_port::unused_udp6_port().unwrap(),
tcp_port: unused_port::unused_tcp6_port().unwrap(), tcp_port: unused_port::unused_tcp6_port().unwrap(),
}) })
} }
@ -84,12 +113,14 @@ impl slog::KV for ListenAddress {
) -> slog::Result { ) -> slog::Result {
if let Some(v4_addr) = self.v4() { if let Some(v4_addr) = self.v4() {
serializer.emit_arguments("ip4_address", &format_args!("{}", v4_addr.addr))?; serializer.emit_arguments("ip4_address", &format_args!("{}", v4_addr.addr))?;
serializer.emit_u16("udp4_port", v4_addr.udp_port)?; serializer.emit_u16("disc4_port", v4_addr.disc_port)?;
serializer.emit_u16("quic4_port", v4_addr.quic_port)?;
serializer.emit_u16("tcp4_port", v4_addr.tcp_port)?; serializer.emit_u16("tcp4_port", v4_addr.tcp_port)?;
} }
if let Some(v6_addr) = self.v6() { if let Some(v6_addr) = self.v6() {
serializer.emit_arguments("ip6_address", &format_args!("{}", v6_addr.addr))?; serializer.emit_arguments("ip6_address", &format_args!("{}", v6_addr.addr))?;
serializer.emit_u16("udp6_port", v6_addr.udp_port)?; serializer.emit_u16("disc6_port", v6_addr.disc_port)?;
serializer.emit_u16("quic6_port", v6_addr.quic_port)?;
serializer.emit_u16("tcp6_port", v6_addr.tcp_port)?; serializer.emit_u16("tcp6_port", v6_addr.tcp_port)?;
} }
slog::Result::Ok(()) slog::Result::Ok(())

View File

@ -14,6 +14,16 @@ lazy_static! {
"Count of libp2p peers currently connected" "Count of libp2p peers currently connected"
); );
pub static ref TCP_PEERS_CONNECTED: Result<IntGauge> = try_create_int_gauge(
"libp2p_tcp_peers",
"Count of libp2p peers currently connected via TCP"
);
pub static ref QUIC_PEERS_CONNECTED: Result<IntGauge> = try_create_int_gauge(
"libp2p_quic_peers",
"Count of libp2p peers currently connected via QUIC"
);
pub static ref PEER_CONNECT_EVENT_COUNT: Result<IntCounter> = try_create_int_counter( pub static ref PEER_CONNECT_EVENT_COUNT: Result<IntCounter> = try_create_int_counter(
"libp2p_peer_connect_event_total", "libp2p_peer_connect_event_total",
"Count of libp2p peer connect events (not the current number of connected peers)" "Count of libp2p peer connect events (not the current number of connected peers)"

View File

@ -1,5 +1,6 @@
//! Implementation of Lighthouse's peer management system. //! Implementation of Lighthouse's peer management system.
use crate::discovery::enr_ext::EnrExt;
use crate::rpc::{GoodbyeReason, MetaData, Protocol, RPCError, RPCResponseErrorCode}; use crate::rpc::{GoodbyeReason, MetaData, Protocol, RPCError, RPCResponseErrorCode};
use crate::service::TARGET_SUBNET_PEERS; use crate::service::TARGET_SUBNET_PEERS;
use crate::{error, metrics, Gossipsub}; use crate::{error, metrics, Gossipsub};
@ -13,7 +14,6 @@ use peerdb::{client::ClientKind, BanOperation, BanResult, ScoreUpdateResult};
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use slog::{debug, error, trace, warn}; use slog::{debug, error, trace, warn};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::collections::BTreeMap;
use std::{ use std::{
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
@ -78,7 +78,7 @@ pub struct PeerManager<TSpec: EthSpec> {
/// The target number of peers we would like to connect to. /// The target number of peers we would like to connect to.
target_peers: usize, target_peers: usize,
/// Peers queued to be dialed. /// Peers queued to be dialed.
peers_to_dial: BTreeMap<PeerId, Option<Enr>>, peers_to_dial: Vec<Enr>,
/// The number of temporarily banned peers. This is used to prevent instantaneous /// The number of temporarily banned peers. This is used to prevent instantaneous
/// reconnection. /// reconnection.
// NOTE: This just prevents re-connections. The state of the peer is otherwise unaffected. A // NOTE: This just prevents re-connections. The state of the peer is otherwise unaffected. A
@ -312,16 +312,12 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
/// Peers that have been returned by discovery requests that are suitable for dialing are /// Peers that have been returned by discovery requests that are suitable for dialing are
/// returned here. /// returned here.
/// ///
/// NOTE: By dialing `PeerId`s and not multiaddrs, libp2p requests the multiaddr associated /// This function decides whether or not to dial these peers.
/// with a new `PeerId` which involves a discovery routing table lookup. We could dial the
/// multiaddr here, however this could relate to duplicate PeerId's etc. If the lookup
/// proves resource constraining, we should switch to multiaddr dialling here.
#[allow(clippy::mutable_key_type)] #[allow(clippy::mutable_key_type)]
pub fn peers_discovered(&mut self, results: HashMap<PeerId, Option<Instant>>) -> Vec<PeerId> { pub fn peers_discovered(&mut self, results: HashMap<Enr, Option<Instant>>) {
let mut to_dial_peers = Vec::with_capacity(4); let mut to_dial_peers = 0;
let connected_or_dialing = self.network_globals.connected_or_dialing_peers(); let connected_or_dialing = self.network_globals.connected_or_dialing_peers();
for (peer_id, min_ttl) in results { for (enr, min_ttl) in results {
// There are two conditions in deciding whether to dial this peer. // There are two conditions in deciding whether to dial this peer.
// 1. If we are less than our max connections. Discovery queries are executed to reach // 1. If we are less than our max connections. Discovery queries are executed to reach
// our target peers, so its fine to dial up to our max peers (which will get pruned // our target peers, so its fine to dial up to our max peers (which will get pruned
@ -330,10 +326,8 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
// considered a priority. We have pre-allocated some extra priority slots for these // considered a priority. We have pre-allocated some extra priority slots for these
// peers as specified by PRIORITY_PEER_EXCESS. Therefore we dial these peers, even // peers as specified by PRIORITY_PEER_EXCESS. Therefore we dial these peers, even
// if we are already at our max_peer limit. // if we are already at our max_peer limit.
if (min_ttl.is_some() if min_ttl.is_some() && connected_or_dialing + to_dial_peers < self.max_priority_peers()
&& connected_or_dialing + to_dial_peers.len() < self.max_priority_peers() || connected_or_dialing + to_dial_peers < self.max_peers()
|| connected_or_dialing + to_dial_peers.len() < self.max_peers())
&& self.network_globals.peers.read().should_dial(&peer_id)
{ {
// This should be updated with the peer dialing. In fact created once the peer is // This should be updated with the peer dialing. In fact created once the peer is
// dialed // dialed
@ -341,16 +335,16 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
self.network_globals self.network_globals
.peers .peers
.write() .write()
.update_min_ttl(&peer_id, min_ttl); .update_min_ttl(&enr.peer_id(), min_ttl);
} }
to_dial_peers.push(peer_id); debug!(self.log, "Dialing discovered peer"; "peer_id" => %enr.peer_id());
self.dial_peer(enr);
to_dial_peers += 1;
} }
} }
// Queue another discovery if we need to // Queue another discovery if we need to
self.maintain_peer_count(to_dial_peers.len()); self.maintain_peer_count(to_dial_peers);
to_dial_peers
} }
/// A STATUS message has been received from a peer. This resets the status timer. /// A STATUS message has been received from a peer. This resets the status timer.
@ -406,9 +400,16 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
/* Notifications from the Swarm */ /* Notifications from the Swarm */
// A peer is being dialed. /// A peer is being dialed.
pub fn dial_peer(&mut self, peer_id: &PeerId, enr: Option<Enr>) { pub fn dial_peer(&mut self, peer: Enr) {
self.peers_to_dial.insert(*peer_id, enr); if self
.network_globals
.peers
.read()
.should_dial(&peer.peer_id())
{
self.peers_to_dial.push(peer);
}
} }
/// Reports if a peer is banned or not. /// Reports if a peer is banned or not.

View File

@ -3,7 +3,7 @@
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use futures::StreamExt; use futures::StreamExt;
use libp2p::core::ConnectedPoint; use libp2p::core::{multiaddr, ConnectedPoint};
use libp2p::identity::PeerId; use libp2p::identity::PeerId;
use libp2p::swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm}; use libp2p::swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm};
use libp2p::swarm::dial_opts::{DialOpts, PeerCondition}; use libp2p::swarm::dial_opts::{DialOpts, PeerCondition};
@ -12,6 +12,7 @@ use libp2p::swarm::{ConnectionId, NetworkBehaviour, PollParameters, ToSwarm};
use slog::{debug, error}; use slog::{debug, error};
use types::EthSpec; use types::EthSpec;
use crate::discovery::enr_ext::EnrExt;
use crate::rpc::GoodbyeReason; use crate::rpc::GoodbyeReason;
use crate::types::SyncState; use crate::types::SyncState;
use crate::{metrics, ClearDialError}; use crate::{metrics, ClearDialError};
@ -95,11 +96,23 @@ impl<TSpec: EthSpec> NetworkBehaviour for PeerManager<TSpec> {
self.events.shrink_to_fit(); self.events.shrink_to_fit();
} }
if let Some((peer_id, maybe_enr)) = self.peers_to_dial.pop_first() { if let Some(enr) = self.peers_to_dial.pop() {
self.inject_peer_connection(&peer_id, ConnectingType::Dialing, maybe_enr); let peer_id = enr.peer_id();
self.inject_peer_connection(&peer_id, ConnectingType::Dialing, Some(enr.clone()));
let quic_multiaddrs = enr.multiaddr_quic();
if !quic_multiaddrs.is_empty() {
debug!(self.log, "Dialing QUIC supported peer"; "peer_id"=> %peer_id, "quic_multiaddrs" => ?quic_multiaddrs);
}
// Prioritize Quic connections over Tcp ones.
let multiaddrs = quic_multiaddrs
.into_iter()
.chain(enr.multiaddr_tcp())
.collect();
return Poll::Ready(ToSwarm::Dial { return Poll::Ready(ToSwarm::Dial {
opts: DialOpts::peer_id(peer_id) opts: DialOpts::peer_id(peer_id)
.condition(PeerCondition::Disconnected) .condition(PeerCondition::Disconnected)
.addresses(multiaddrs)
.build(), .build(),
}); });
} }
@ -124,9 +137,11 @@ impl<TSpec: EthSpec> NetworkBehaviour for PeerManager<TSpec> {
} }
FromSwarm::ConnectionClosed(ConnectionClosed { FromSwarm::ConnectionClosed(ConnectionClosed {
peer_id, peer_id,
endpoint,
remaining_established, remaining_established,
.. ..
}) => self.on_connection_closed(peer_id, remaining_established), }) => self.on_connection_closed(peer_id, endpoint, remaining_established),
FromSwarm::DialFailure(DialFailure { FromSwarm::DialFailure(DialFailure {
peer_id, peer_id,
error, error,
@ -184,7 +199,11 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
endpoint: &ConnectedPoint, endpoint: &ConnectedPoint,
other_established: usize, other_established: usize,
) { ) {
debug!(self.log, "Connection established"; "peer_id" => %peer_id, "connection" => ?endpoint.to_endpoint()); debug!(self.log, "Connection established"; "peer_id" => %peer_id,
"multiaddr" => %endpoint.get_remote_address(),
"connection" => ?endpoint.to_endpoint()
);
if other_established == 0 { if other_established == 0 {
self.events.push(PeerManagerEvent::MetaData(peer_id)); self.events.push(PeerManagerEvent::MetaData(peer_id));
} }
@ -194,6 +213,34 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
metrics::check_nat(); metrics::check_nat();
} }
// increment prometheus metrics
if self.metrics_enabled {
let remote_addr = match endpoint {
ConnectedPoint::Dialer { address, .. } => address,
ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr,
};
match remote_addr.iter().find(|proto| {
matches!(
proto,
multiaddr::Protocol::QuicV1 | multiaddr::Protocol::Tcp(_)
)
}) {
Some(multiaddr::Protocol::QuicV1) => {
metrics::inc_gauge(&metrics::QUIC_PEERS_CONNECTED);
}
Some(multiaddr::Protocol::Tcp(_)) => {
metrics::inc_gauge(&metrics::TCP_PEERS_CONNECTED);
}
Some(_) => unreachable!(),
None => {
error!(self.log, "Connection established via unknown transport"; "addr" => %remote_addr)
}
};
self.update_connected_peer_metrics();
metrics::inc_counter(&metrics::PEER_CONNECT_EVENT_COUNT);
}
// Check to make sure the peer is not supposed to be banned // Check to make sure the peer is not supposed to be banned
match self.ban_status(&peer_id) { match self.ban_status(&peer_id) {
// TODO: directly emit the ban event? // TODO: directly emit the ban event?
@ -245,14 +292,15 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
self.events self.events
.push(PeerManagerEvent::PeerConnectedOutgoing(peer_id)); .push(PeerManagerEvent::PeerConnectedOutgoing(peer_id));
} }
};
} }
// increment prometheus metrics fn on_connection_closed(
self.update_connected_peer_metrics(); &mut self,
metrics::inc_counter(&metrics::PEER_CONNECT_EVENT_COUNT); peer_id: PeerId,
} endpoint: &ConnectedPoint,
remaining_established: usize,
fn on_connection_closed(&mut self, peer_id: PeerId, remaining_established: usize) { ) {
if remaining_established > 0 { if remaining_established > 0 {
return; return;
} }
@ -278,10 +326,32 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
// reference so that peer manager can track this peer. // reference so that peer manager can track this peer.
self.inject_disconnect(&peer_id); self.inject_disconnect(&peer_id);
let remote_addr = match endpoint {
ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr,
ConnectedPoint::Dialer { address, .. } => address,
};
// Update the prometheus metrics // Update the prometheus metrics
if self.metrics_enabled {
match remote_addr.iter().find(|proto| {
matches!(
proto,
multiaddr::Protocol::QuicV1 | multiaddr::Protocol::Tcp(_)
)
}) {
Some(multiaddr::Protocol::QuicV1) => {
metrics::dec_gauge(&metrics::QUIC_PEERS_CONNECTED);
}
Some(multiaddr::Protocol::Tcp(_)) => {
metrics::dec_gauge(&metrics::TCP_PEERS_CONNECTED);
}
// If it's an unknown protocol we already logged when connection was established.
_ => {}
};
self.update_connected_peer_metrics(); self.update_connected_peer_metrics();
metrics::inc_counter(&metrics::PEER_DISCONNECT_EVENT_COUNT); metrics::inc_counter(&metrics::PEER_DISCONNECT_EVENT_COUNT);
} }
}
/// A dial attempt has failed. /// A dial attempt has failed.
/// ///

View File

@ -1,16 +1,11 @@
use crate::{ use crate::{metrics, multiaddr::Multiaddr, types::Subnet, Enr, Gossipsub, PeerId};
metrics,
multiaddr::{Multiaddr, Protocol},
types::Subnet,
Enr, Gossipsub, PeerId,
};
use peer_info::{ConnectionDirection, PeerConnectionStatus, PeerInfo}; use peer_info::{ConnectionDirection, PeerConnectionStatus, PeerInfo};
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use score::{PeerAction, ReportSource, Score, ScoreState}; use score::{PeerAction, ReportSource, Score, ScoreState};
use slog::{crit, debug, error, trace, warn}; use slog::{crit, debug, error, trace, warn};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::net::{IpAddr, SocketAddr}; use std::net::IpAddr;
use std::time::Instant; use std::time::Instant;
use sync_status::SyncStatus; use sync_status::SyncStatus;
use types::EthSpec; use types::EthSpec;
@ -764,28 +759,10 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
| PeerConnectionStatus::Dialing { .. } => {} | PeerConnectionStatus::Dialing { .. } => {}
} }
// Add the seen ip address and port to the peer's info
let socket_addr = match seen_address.iter().fold(
(None, None),
|(found_ip, found_port), protocol| match protocol {
Protocol::Ip4(ip) => (Some(ip.into()), found_port),
Protocol::Ip6(ip) => (Some(ip.into()), found_port),
Protocol::Tcp(port) => (found_ip, Some(port)),
_ => (found_ip, found_port),
},
) {
(Some(ip), Some(port)) => Some(SocketAddr::new(ip, port)),
(Some(_ip), None) => {
crit!(self.log, "Connected peer has an IP but no TCP port"; "peer_id" => %peer_id);
None
}
_ => None,
};
// Update the connection state // Update the connection state
match direction { match direction {
ConnectionDirection::Incoming => info.connect_ingoing(socket_addr), ConnectionDirection::Incoming => info.connect_ingoing(Some(seen_address)),
ConnectionDirection::Outgoing => info.connect_outgoing(socket_addr), ConnectionDirection::Outgoing => info.connect_outgoing(Some(seen_address)),
} }
} }
@ -1274,6 +1251,7 @@ impl BannedPeersCount {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use libp2p::core::multiaddr::Protocol;
use libp2p::core::Multiaddr; use libp2p::core::Multiaddr;
use slog::{o, Drain}; use slog::{o, Drain};
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr};

View File

@ -2,15 +2,15 @@ use super::client::Client;
use super::score::{PeerAction, Score, ScoreState}; use super::score::{PeerAction, Score, ScoreState};
use super::sync_status::SyncStatus; use super::sync_status::SyncStatus;
use crate::discovery::Eth2Enr; use crate::discovery::Eth2Enr;
use crate::Multiaddr;
use crate::{rpc::MetaData, types::Subnet}; use crate::{rpc::MetaData, types::Subnet};
use discv5::Enr; use discv5::Enr;
use libp2p::core::multiaddr::{Multiaddr, Protocol};
use serde::{ use serde::{
ser::{SerializeStruct, Serializer}, ser::{SerializeStruct, Serializer},
Serialize, Serialize,
}; };
use std::collections::HashSet; use std::collections::HashSet;
use std::net::{IpAddr, SocketAddr}; use std::net::IpAddr;
use std::time::Instant; use std::time::Instant;
use strum::AsRefStr; use strum::AsRefStr;
use types::EthSpec; use types::EthSpec;
@ -29,9 +29,9 @@ pub struct PeerInfo<T: EthSpec> {
/// The known listening addresses of this peer. This is given by identify and can be arbitrary /// The known listening addresses of this peer. This is given by identify and can be arbitrary
/// (including local IPs). /// (including local IPs).
listening_addresses: Vec<Multiaddr>, listening_addresses: Vec<Multiaddr>,
/// This is addresses we have physically seen and this is what we use for banning/un-banning /// These are the multiaddrs we have physically seen and is what we use for banning/un-banning
/// peers. /// peers.
seen_addresses: HashSet<SocketAddr>, seen_multiaddrs: HashSet<Multiaddr>,
/// The current syncing state of the peer. The state may be determined after it's initial /// The current syncing state of the peer. The state may be determined after it's initial
/// connection. /// connection.
sync_status: SyncStatus, sync_status: SyncStatus,
@ -60,7 +60,7 @@ impl<TSpec: EthSpec> Default for PeerInfo<TSpec> {
client: Client::default(), client: Client::default(),
connection_status: Default::default(), connection_status: Default::default(),
listening_addresses: Vec::new(), listening_addresses: Vec::new(),
seen_addresses: HashSet::new(), seen_multiaddrs: HashSet::new(),
subnets: HashSet::new(), subnets: HashSet::new(),
sync_status: SyncStatus::Unknown, sync_status: SyncStatus::Unknown,
meta_data: None, meta_data: None,
@ -227,15 +227,21 @@ impl<T: EthSpec> PeerInfo<T> {
} }
/// Returns the seen addresses of the peer. /// Returns the seen addresses of the peer.
pub fn seen_addresses(&self) -> impl Iterator<Item = &SocketAddr> + '_ { pub fn seen_multiaddrs(&self) -> impl Iterator<Item = &Multiaddr> + '_ {
self.seen_addresses.iter() self.seen_multiaddrs.iter()
} }
/// Returns a list of seen IP addresses for the peer. /// Returns a list of seen IP addresses for the peer.
pub fn seen_ip_addresses(&self) -> impl Iterator<Item = IpAddr> + '_ { pub fn seen_ip_addresses(&self) -> impl Iterator<Item = IpAddr> + '_ {
self.seen_addresses self.seen_multiaddrs.iter().filter_map(|multiaddr| {
.iter() multiaddr.iter().find_map(|protocol| {
.map(|socket_addr| socket_addr.ip()) match protocol {
Protocol::Ip4(ip) => Some(ip.into()),
Protocol::Ip6(ip) => Some(ip.into()),
_ => None, // Only care for IP addresses
}
})
})
} }
/// Returns the connection status of the peer. /// Returns the connection status of the peer.
@ -415,7 +421,7 @@ impl<T: EthSpec> PeerInfo<T> {
/// Modifies the status to Connected and increases the number of ingoing /// Modifies the status to Connected and increases the number of ingoing
/// connections by one /// connections by one
pub(super) fn connect_ingoing(&mut self, seen_address: Option<SocketAddr>) { pub(super) fn connect_ingoing(&mut self, seen_multiaddr: Option<Multiaddr>) {
match &mut self.connection_status { match &mut self.connection_status {
Connected { n_in, .. } => *n_in += 1, Connected { n_in, .. } => *n_in += 1,
Disconnected { .. } Disconnected { .. }
@ -428,14 +434,14 @@ impl<T: EthSpec> PeerInfo<T> {
} }
} }
if let Some(socket_addr) = seen_address { if let Some(multiaddr) = seen_multiaddr {
self.seen_addresses.insert(socket_addr); self.seen_multiaddrs.insert(multiaddr);
} }
} }
/// Modifies the status to Connected and increases the number of outgoing /// Modifies the status to Connected and increases the number of outgoing
/// connections by one /// connections by one
pub(super) fn connect_outgoing(&mut self, seen_address: Option<SocketAddr>) { pub(super) fn connect_outgoing(&mut self, seen_multiaddr: Option<Multiaddr>) {
match &mut self.connection_status { match &mut self.connection_status {
Connected { n_out, .. } => *n_out += 1, Connected { n_out, .. } => *n_out += 1,
Disconnected { .. } Disconnected { .. }
@ -447,8 +453,8 @@ impl<T: EthSpec> PeerInfo<T> {
self.connection_direction = Some(ConnectionDirection::Outgoing); self.connection_direction = Some(ConnectionDirection::Outgoing);
} }
} }
if let Some(ip_addr) = seen_address { if let Some(multiaddr) = seen_multiaddr {
self.seen_addresses.insert(ip_addr); self.seen_multiaddrs.insert(multiaddr);
} }
} }

View File

@ -156,8 +156,6 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
let meta_data = utils::load_or_build_metadata(&config.network_dir, &log); let meta_data = utils::load_or_build_metadata(&config.network_dir, &log);
let globals = NetworkGlobals::new( let globals = NetworkGlobals::new(
enr, enr,
config.listen_addrs().v4().map(|v4_addr| v4_addr.tcp_port),
config.listen_addrs().v6().map(|v6_addr| v6_addr.tcp_port),
meta_data, meta_data,
config config
.trusted_peers .trusted_peers
@ -355,7 +353,8 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
let (swarm, bandwidth) = { let (swarm, bandwidth) = {
// Set up the transport - tcp/ws with noise and mplex // Set up the transport - tcp/ws with noise and mplex
let (transport, bandwidth) = build_transport(local_keypair.clone()) let (transport, bandwidth) =
build_transport(local_keypair.clone(), !config.disable_quic_support)
.map_err(|e| format!("Failed to build transport: {:?}", e))?; .map_err(|e| format!("Failed to build transport: {:?}", e))?;
// use the executor for libp2p // use the executor for libp2p
@ -411,9 +410,16 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
async fn start(&mut self, config: &crate::NetworkConfig) -> error::Result<()> { async fn start(&mut self, config: &crate::NetworkConfig) -> error::Result<()> {
let enr = self.network_globals.local_enr(); let enr = self.network_globals.local_enr();
info!(self.log, "Libp2p Starting"; "peer_id" => %enr.peer_id(), "bandwidth_config" => format!("{}-{}", config.network_load, NetworkLoad::from(config.network_load).name)); info!(self.log, "Libp2p Starting"; "peer_id" => %enr.peer_id(), "bandwidth_config" => format!("{}-{}", config.network_load, NetworkLoad::from(config.network_load).name));
debug!(self.log, "Attempting to open listening ports"; config.listen_addrs(), "discovery_enabled" => !config.disable_discovery); debug!(self.log, "Attempting to open listening ports"; config.listen_addrs(), "discovery_enabled" => !config.disable_discovery, "quic_enabled" => !config.disable_quic_support);
for listen_multiaddr in config.listen_addrs().libp2p_addresses() {
// If QUIC is disabled, ignore listening on QUIC ports
if config.disable_quic_support
&& listen_multiaddr.iter().any(|v| v == MProtocol::QuicV1)
{
continue;
}
for listen_multiaddr in config.listen_addrs().tcp_addresses() {
match self.swarm.listen_on(listen_multiaddr.clone()) { match self.swarm.listen_on(listen_multiaddr.clone()) {
Ok(_) => { Ok(_) => {
let mut log_address = listen_multiaddr; let mut log_address = listen_multiaddr;
@ -454,6 +460,20 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
boot_nodes.dedup(); boot_nodes.dedup();
for bootnode_enr in boot_nodes { for bootnode_enr in boot_nodes {
// If QUIC is enabled, attempt QUIC connections first
if !config.disable_quic_support {
for quic_multiaddr in &bootnode_enr.multiaddr_quic() {
if !self
.network_globals
.peers
.read()
.is_connected_or_dialing(&bootnode_enr.peer_id())
{
dial(quic_multiaddr.clone());
}
}
}
for multiaddr in &bootnode_enr.multiaddr() { for multiaddr in &bootnode_enr.multiaddr() {
// ignore udp multiaddr if it exists // ignore udp multiaddr if it exists
let components = multiaddr.iter().collect::<Vec<_>>(); let components = multiaddr.iter().collect::<Vec<_>>();
@ -1036,30 +1056,27 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
} }
} }
/// Dial cached enrs in discovery service that are in the given `subnet_id` and aren't /// Dial cached Enrs in discovery service that are in the given `subnet_id` and aren't
/// in Connected, Dialing or Banned state. /// in Connected, Dialing or Banned state.
fn dial_cached_enrs_in_subnet(&mut self, subnet: Subnet) { fn dial_cached_enrs_in_subnet(&mut self, subnet: Subnet) {
let predicate = subnet_predicate::<TSpec>(vec![subnet], &self.log); let predicate = subnet_predicate::<TSpec>(vec![subnet], &self.log);
let peers_to_dial: Vec<PeerId> = self let peers_to_dial: Vec<Enr> = self
.discovery() .discovery()
.cached_enrs() .cached_enrs()
.filter_map(|(peer_id, enr)| { .filter_map(|(_peer_id, enr)| {
let peers = self.network_globals.peers.read(); if predicate(enr) {
if predicate(enr) && peers.should_dial(peer_id) { Some(enr.clone())
Some(*peer_id)
} else { } else {
None None
} }
}) })
.collect(); .collect();
for peer_id in peers_to_dial {
debug!(self.log, "Dialing cached ENR peer"; "peer_id" => %peer_id);
// Remove the ENR from the cache to prevent continual re-dialing on disconnects
self.discovery_mut().remove_cached_enr(&peer_id); // Remove the ENR from the cache to prevent continual re-dialing on disconnects
// For any dial event, inform the peer manager for enr in peers_to_dial {
let enr = self.discovery_mut().enr_of_peer(&peer_id); debug!(self.log, "Dialing cached ENR peer"; "peer_id" => %enr.peer_id());
self.peer_manager_mut().dial_peer(&peer_id, enr); self.discovery_mut().remove_cached_enr(&enr.peer_id());
self.peer_manager_mut().dial_peer(enr);
} }
} }
@ -1345,22 +1362,6 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
} }
} }
/// Handle a discovery event.
fn inject_discovery_event(
&mut self,
event: DiscoveredPeers,
) -> Option<NetworkEvent<AppReqId, TSpec>> {
let DiscoveredPeers { peers } = event;
let to_dial_peers = self.peer_manager_mut().peers_discovered(peers);
for peer_id in to_dial_peers {
debug!(self.log, "Dialing discovered peer"; "peer_id" => %peer_id);
// For any dial event, inform the peer manager
let enr = self.discovery_mut().enr_of_peer(&peer_id);
self.peer_manager_mut().dial_peer(&peer_id, enr);
}
None
}
/// Handle an identify event. /// Handle an identify event.
fn inject_identify_event( fn inject_identify_event(
&mut self, &mut self,
@ -1461,7 +1462,14 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
BehaviourEvent::BannedPeers(void) => void::unreachable(void), BehaviourEvent::BannedPeers(void) => void::unreachable(void),
BehaviourEvent::Gossipsub(ge) => self.inject_gs_event(ge), BehaviourEvent::Gossipsub(ge) => self.inject_gs_event(ge),
BehaviourEvent::Eth2Rpc(re) => self.inject_rpc_event(re), BehaviourEvent::Eth2Rpc(re) => self.inject_rpc_event(re),
BehaviourEvent::Discovery(de) => self.inject_discovery_event(de), // Inform the peer manager about discovered peers.
//
// The peer manager will subsequently decide which peers need to be dialed and then dial
// them.
BehaviourEvent::Discovery(DiscoveredPeers { peers }) => {
self.peer_manager_mut().peers_discovered(peers);
None
}
BehaviourEvent::Identify(ie) => self.inject_identify_event(ie), BehaviourEvent::Identify(ie) => self.inject_identify_event(ie),
BehaviourEvent::PeerManager(pe) => self.inject_pm_event(pe), BehaviourEvent::PeerManager(pe) => self.inject_pm_event(pe),
BehaviourEvent::ConnectionLimits(le) => void::unreachable(le), BehaviourEvent::ConnectionLimits(le) => void::unreachable(le),
@ -1493,7 +1501,7 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
format!("Dialing local peer id {endpoint:?}") format!("Dialing local peer id {endpoint:?}")
} }
libp2p::swarm::ListenError::Denied { cause } => { libp2p::swarm::ListenError::Denied { cause } => {
format!("Connection was denied with cause {cause}") format!("Connection was denied with cause: {cause:?}")
} }
libp2p::swarm::ListenError::Transport(t) => match t { libp2p::swarm::ListenError::Transport(t) => match t {
libp2p::TransportError::MultiaddrNotSupported(m) => { libp2p::TransportError::MultiaddrNotSupported(m) => {
@ -1543,13 +1551,7 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
None None
} }
} }
SwarmEvent::Dialing { SwarmEvent::Dialing { .. } => None,
peer_id,
connection_id: _,
} => {
debug!(self.log, "Swarm Dialing"; "peer_id" => ?peer_id);
None
}
}; };
if let Some(ev) = maybe_event { if let Some(ev) = maybe_event {

View File

@ -4,11 +4,13 @@ use crate::types::{
error, EnrAttestationBitfield, EnrSyncCommitteeBitfield, GossipEncoding, GossipKind, error, EnrAttestationBitfield, EnrSyncCommitteeBitfield, GossipEncoding, GossipKind,
}; };
use crate::{GossipTopic, NetworkConfig}; use crate::{GossipTopic, NetworkConfig};
use futures::future::Either;
use libp2p::bandwidth::BandwidthSinks; use libp2p::bandwidth::BandwidthSinks;
use libp2p::core::{multiaddr::Multiaddr, muxing::StreamMuxerBox, transport::Boxed}; use libp2p::core::{multiaddr::Multiaddr, muxing::StreamMuxerBox, transport::Boxed};
use libp2p::gossipsub; use libp2p::gossipsub;
use libp2p::identity::{secp256k1, Keypair}; use libp2p::identity::{secp256k1, Keypair};
use libp2p::{core, noise, yamux, PeerId, Transport, TransportExt}; use libp2p::{core, noise, yamux, PeerId, Transport, TransportExt};
use libp2p_quic;
use prometheus_client::registry::Registry; use prometheus_client::registry::Registry;
use slog::{debug, warn}; use slog::{debug, warn};
use ssz::Decode; use ssz::Decode;
@ -37,19 +39,12 @@ pub struct Context<'a> {
type BoxedTransport = Boxed<(PeerId, StreamMuxerBox)>; type BoxedTransport = Boxed<(PeerId, StreamMuxerBox)>;
/// The implementation supports TCP/IP, WebSockets over TCP/IP, noise as the encryption layer, and /// The implementation supports TCP/IP, QUIC (experimental) over UDP, noise as the encryption layer, and
/// mplex as the multiplexing layer. /// mplex/yamux as the multiplexing layer (when using TCP).
pub fn build_transport( pub fn build_transport(
local_private_key: Keypair, local_private_key: Keypair,
quic_support: bool,
) -> std::io::Result<(BoxedTransport, Arc<BandwidthSinks>)> { ) -> std::io::Result<(BoxedTransport, Arc<BandwidthSinks>)> {
let tcp = libp2p::tcp::tokio::Transport::new(libp2p::tcp::Config::default().nodelay(true));
let transport = libp2p::dns::TokioDnsConfig::system(tcp)?;
#[cfg(feature = "libp2p-websocket")]
let transport = {
let trans_clone = transport.clone();
transport.or_transport(libp2p::websocket::WsConfig::new(trans_clone))
};
// mplex config // mplex config
let mut mplex_config = libp2p_mplex::MplexConfig::new(); let mut mplex_config = libp2p_mplex::MplexConfig::new();
mplex_config.set_max_buffer_size(256); mplex_config.set_max_buffer_size(256);
@ -58,18 +53,34 @@ pub fn build_transport(
// yamux config // yamux config
let mut yamux_config = yamux::Config::default(); let mut yamux_config = yamux::Config::default();
yamux_config.set_window_update_mode(yamux::WindowUpdateMode::on_read()); yamux_config.set_window_update_mode(yamux::WindowUpdateMode::on_read());
let (transport, bandwidth) = transport
// Creates the TCP transport layer
let tcp = libp2p::tcp::tokio::Transport::new(libp2p::tcp::Config::default().nodelay(true))
.upgrade(core::upgrade::Version::V1) .upgrade(core::upgrade::Version::V1)
.authenticate(generate_noise_config(&local_private_key)) .authenticate(generate_noise_config(&local_private_key))
.multiplex(core::upgrade::SelectUpgrade::new( .multiplex(core::upgrade::SelectUpgrade::new(
yamux_config, yamux_config,
mplex_config, mplex_config,
)) ))
.timeout(Duration::from_secs(10)) .timeout(Duration::from_secs(10));
.boxed()
.with_bandwidth_logging(); let (transport, bandwidth) = if quic_support {
// Enables Quic
// The default quic configuration suits us for now.
let quic_config = libp2p_quic::Config::new(&local_private_key);
tcp.or_transport(libp2p_quic::tokio::Transport::new(quic_config))
.map(|either_output, _| match either_output {
Either::Left((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
Either::Right((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
})
.with_bandwidth_logging()
} else {
tcp.with_bandwidth_logging()
};
// // Enables DNS over the transport.
let transport = libp2p::dns::TokioDnsConfig::system(transport)?.boxed();
// Authentication
Ok((transport, bandwidth)) Ok((transport, bandwidth))
} }

View File

@ -16,10 +16,6 @@ pub struct NetworkGlobals<TSpec: EthSpec> {
pub peer_id: RwLock<PeerId>, pub peer_id: RwLock<PeerId>,
/// Listening multiaddrs. /// Listening multiaddrs.
pub listen_multiaddrs: RwLock<Vec<Multiaddr>>, pub listen_multiaddrs: RwLock<Vec<Multiaddr>>,
/// The TCP port that the libp2p service is listening on over Ipv4.
listen_port_tcp4: Option<u16>,
/// The TCP port that the libp2p service is listening on over Ipv6.
listen_port_tcp6: Option<u16>,
/// The collection of known peers. /// The collection of known peers.
pub peers: RwLock<PeerDB<TSpec>>, pub peers: RwLock<PeerDB<TSpec>>,
// The local meta data of our node. // The local meta data of our node.
@ -35,8 +31,6 @@ pub struct NetworkGlobals<TSpec: EthSpec> {
impl<TSpec: EthSpec> NetworkGlobals<TSpec> { impl<TSpec: EthSpec> NetworkGlobals<TSpec> {
pub fn new( pub fn new(
enr: Enr, enr: Enr,
listen_port_tcp4: Option<u16>,
listen_port_tcp6: Option<u16>,
local_metadata: MetaData<TSpec>, local_metadata: MetaData<TSpec>,
trusted_peers: Vec<PeerId>, trusted_peers: Vec<PeerId>,
disable_peer_scoring: bool, disable_peer_scoring: bool,
@ -46,8 +40,6 @@ impl<TSpec: EthSpec> NetworkGlobals<TSpec> {
local_enr: RwLock::new(enr.clone()), local_enr: RwLock::new(enr.clone()),
peer_id: RwLock::new(enr.peer_id()), peer_id: RwLock::new(enr.peer_id()),
listen_multiaddrs: RwLock::new(Vec::new()), listen_multiaddrs: RwLock::new(Vec::new()),
listen_port_tcp4,
listen_port_tcp6,
local_metadata: RwLock::new(local_metadata), local_metadata: RwLock::new(local_metadata),
peers: RwLock::new(PeerDB::new(trusted_peers, disable_peer_scoring, log)), peers: RwLock::new(PeerDB::new(trusted_peers, disable_peer_scoring, log)),
gossipsub_subscriptions: RwLock::new(HashSet::new()), gossipsub_subscriptions: RwLock::new(HashSet::new()),
@ -72,16 +64,6 @@ impl<TSpec: EthSpec> NetworkGlobals<TSpec> {
self.listen_multiaddrs.read().clone() self.listen_multiaddrs.read().clone()
} }
/// Returns the libp2p TCP port that this node has been configured to listen on.
pub fn listen_port_tcp4(&self) -> Option<u16> {
self.listen_port_tcp4
}
/// Returns the UDP discovery port that this node has been configured to listen on.
pub fn listen_port_tcp6(&self) -> Option<u16> {
self.listen_port_tcp6
}
/// Returns the number of libp2p connected peers. /// Returns the number of libp2p connected peers.
pub fn connected_peers(&self) -> usize { pub fn connected_peers(&self) -> usize {
self.peers.read().connected_peer_ids().count() self.peers.read().connected_peer_ids().count()
@ -139,8 +121,6 @@ impl<TSpec: EthSpec> NetworkGlobals<TSpec> {
let enr = discv5::enr::EnrBuilder::new("v4").build(&enr_key).unwrap(); let enr = discv5::enr::EnrBuilder::new("v4").build(&enr_key).unwrap();
NetworkGlobals::new( NetworkGlobals::new(
enr, enr,
Some(9000),
None,
MetaData::V2(MetaDataV2 { MetaData::V2(MetaDataV2 {
seq_number: 0, seq_number: 0,
attnets: Default::default(), attnets: Default::default(),

View File

@ -67,15 +67,19 @@ pub fn build_log(level: slog::Level, enabled: bool) -> slog::Logger {
} }
} }
pub fn build_config(port: u16, mut boot_nodes: Vec<Enr>) -> NetworkConfig { pub fn build_config(mut boot_nodes: Vec<Enr>) -> NetworkConfig {
let mut config = NetworkConfig::default(); let mut config = NetworkConfig::default();
// Find unused ports by using the 0 port.
let port = 0;
let random_path: u16 = rand::random();
let path = TempBuilder::new() let path = TempBuilder::new()
.prefix(&format!("libp2p_test{}", port)) .prefix(&format!("libp2p_test_{}", random_path))
.tempdir() .tempdir()
.unwrap(); .unwrap();
config.set_ipv4_listening_address(std::net::Ipv4Addr::UNSPECIFIED, port, port); config.set_ipv4_listening_address(std::net::Ipv4Addr::UNSPECIFIED, port, port, port);
config.enr_udp4_port = if port == 0 { None } else { Some(port) };
config.enr_address = (Some(std::net::Ipv4Addr::LOCALHOST), None); config.enr_address = (Some(std::net::Ipv4Addr::LOCALHOST), None);
config.boot_nodes_enr.append(&mut boot_nodes); config.boot_nodes_enr.append(&mut boot_nodes);
config.network_dir = path.into_path(); config.network_dir = path.into_path();
@ -95,8 +99,7 @@ pub async fn build_libp2p_instance(
fork_name: ForkName, fork_name: ForkName,
spec: &ChainSpec, spec: &ChainSpec,
) -> Libp2pInstance { ) -> Libp2pInstance {
let port = 0; let config = build_config(boot_nodes);
let config = build_config(port, boot_nodes);
// launch libp2p service // launch libp2p service
let (signal, exit) = exit_future::signal(); let (signal, exit) = exit_future::signal();
@ -123,6 +126,12 @@ pub fn get_enr(node: &LibP2PService<ReqId, E>) -> Enr {
node.local_enr() node.local_enr()
} }
// Protocol for the node pair connection.
pub enum Protocol {
Tcp,
Quic,
}
// Constructs a pair of nodes with separate loggers. The sender dials the receiver. // Constructs a pair of nodes with separate loggers. The sender dials the receiver.
// This returns a (sender, receiver) pair. // This returns a (sender, receiver) pair.
#[allow(dead_code)] #[allow(dead_code)]
@ -131,6 +140,7 @@ pub async fn build_node_pair(
log: &slog::Logger, log: &slog::Logger,
fork_name: ForkName, fork_name: ForkName,
spec: &ChainSpec, spec: &ChainSpec,
protocol: Protocol,
) -> (Libp2pInstance, Libp2pInstance) { ) -> (Libp2pInstance, Libp2pInstance) {
let sender_log = log.new(o!("who" => "sender")); let sender_log = log.new(o!("who" => "sender"));
let receiver_log = log.new(o!("who" => "receiver")); let receiver_log = log.new(o!("who" => "receiver"));
@ -142,16 +152,47 @@ pub async fn build_node_pair(
let sender_fut = async { let sender_fut = async {
loop { loop {
if let NetworkEvent::NewListenAddr(addr) = sender.next_event().await { if let NetworkEvent::NewListenAddr(addr) = sender.next_event().await {
// Only end once we've listened on the protocol we care about
match protocol {
Protocol::Tcp => {
if addr.iter().any(|multiaddr_proto| {
matches!(multiaddr_proto, libp2p::multiaddr::Protocol::Tcp(_))
}) {
return addr; return addr;
} }
} }
Protocol::Quic => {
if addr.iter().any(|multiaddr_proto| {
matches!(multiaddr_proto, libp2p::multiaddr::Protocol::QuicV1)
}) {
return addr;
}
}
}
}
}
}; };
let receiver_fut = async { let receiver_fut = async {
loop { loop {
if let NetworkEvent::NewListenAddr(addr) = receiver.next_event().await { if let NetworkEvent::NewListenAddr(addr) = receiver.next_event().await {
match protocol {
Protocol::Tcp => {
if addr.iter().any(|multiaddr_proto| {
matches!(multiaddr_proto, libp2p::multiaddr::Protocol::Tcp(_))
}) {
return addr; return addr;
} }
} }
Protocol::Quic => {
if addr.iter().any(|multiaddr_proto| {
matches!(multiaddr_proto, libp2p::multiaddr::Protocol::QuicV1)
}) {
return addr;
}
}
}
}
}
}; };
let joined = futures::future::join(sender_fut, receiver_fut); let joined = futures::future::join(sender_fut, receiver_fut);

View File

@ -1,4 +1,8 @@
#![cfg(test)] #![cfg(test)]
mod common;
use common::Protocol;
use lighthouse_network::rpc::methods::*; use lighthouse_network::rpc::methods::*;
use lighthouse_network::{rpc::max_rpc_size, NetworkEvent, ReportSource, Request, Response}; use lighthouse_network::{rpc::max_rpc_size, NetworkEvent, ReportSource, Request, Response};
use slog::{debug, warn, Level}; use slog::{debug, warn, Level};
@ -14,8 +18,6 @@ use types::{
Slot, Slot,
}; };
mod common;
type E = MinimalEthSpec; type E = MinimalEthSpec;
/// Merge block with length < max_rpc_size. /// Merge block with length < max_rpc_size.
@ -49,7 +51,7 @@ fn merge_block_large(fork_context: &ForkContext, spec: &ChainSpec) -> BeaconBloc
// Tests the STATUS RPC message // Tests the STATUS RPC message
#[test] #[test]
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
fn test_status_rpc() { fn test_tcp_status_rpc() {
// set up the logging. The level and enabled logging or not // set up the logging. The level and enabled logging or not
let log_level = Level::Debug; let log_level = Level::Debug;
let enable_logging = false; let enable_logging = false;
@ -62,8 +64,14 @@ fn test_status_rpc() {
rt.block_on(async { rt.block_on(async {
// get sender/receiver // get sender/receiver
let (mut sender, mut receiver) = let (mut sender, mut receiver) = common::build_node_pair(
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Base, &spec).await; Arc::downgrade(&rt),
&log,
ForkName::Base,
&spec,
Protocol::Tcp,
)
.await;
// Dummy STATUS RPC message // Dummy STATUS RPC message
let rpc_request = Request::Status(StatusMessage { let rpc_request = Request::Status(StatusMessage {
@ -141,7 +149,7 @@ fn test_status_rpc() {
// Tests a streamed BlocksByRange RPC Message // Tests a streamed BlocksByRange RPC Message
#[test] #[test]
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
fn test_blocks_by_range_chunked_rpc() { fn test_tcp_blocks_by_range_chunked_rpc() {
// set up the logging. The level and enabled logging or not // set up the logging. The level and enabled logging or not
let log_level = Level::Debug; let log_level = Level::Debug;
let enable_logging = false; let enable_logging = false;
@ -156,8 +164,14 @@ fn test_blocks_by_range_chunked_rpc() {
rt.block_on(async { rt.block_on(async {
// get sender/receiver // get sender/receiver
let (mut sender, mut receiver) = let (mut sender, mut receiver) = common::build_node_pair(
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Merge, &spec).await; Arc::downgrade(&rt),
&log,
ForkName::Merge,
&spec,
Protocol::Tcp,
)
.await;
// BlocksByRange Request // BlocksByRange Request
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send)); let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send));
@ -267,7 +281,7 @@ fn test_blocks_by_range_chunked_rpc() {
// Tests rejection of blocks over `MAX_RPC_SIZE`. // Tests rejection of blocks over `MAX_RPC_SIZE`.
#[test] #[test]
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
fn test_blocks_by_range_over_limit() { fn test_tcp_blocks_by_range_over_limit() {
// set up the logging. The level and enabled logging or not // set up the logging. The level and enabled logging or not
let log_level = Level::Debug; let log_level = Level::Debug;
let enable_logging = false; let enable_logging = false;
@ -282,8 +296,14 @@ fn test_blocks_by_range_over_limit() {
rt.block_on(async { rt.block_on(async {
// get sender/receiver // get sender/receiver
let (mut sender, mut receiver) = let (mut sender, mut receiver) = common::build_node_pair(
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Merge, &spec).await; Arc::downgrade(&rt),
&log,
ForkName::Merge,
&spec,
Protocol::Tcp,
)
.await;
// BlocksByRange Request // BlocksByRange Request
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send)); let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send));
@ -350,7 +370,7 @@ fn test_blocks_by_range_over_limit() {
// Tests that a streamed BlocksByRange RPC Message terminates when all expected chunks were received // Tests that a streamed BlocksByRange RPC Message terminates when all expected chunks were received
#[test] #[test]
fn test_blocks_by_range_chunked_rpc_terminates_correctly() { fn test_tcp_blocks_by_range_chunked_rpc_terminates_correctly() {
// set up the logging. The level and enabled logging or not // set up the logging. The level and enabled logging or not
let log_level = Level::Debug; let log_level = Level::Debug;
let enable_logging = false; let enable_logging = false;
@ -366,8 +386,14 @@ fn test_blocks_by_range_chunked_rpc_terminates_correctly() {
rt.block_on(async { rt.block_on(async {
// get sender/receiver // get sender/receiver
let (mut sender, mut receiver) = let (mut sender, mut receiver) = common::build_node_pair(
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Base, &spec).await; Arc::downgrade(&rt),
&log,
ForkName::Base,
&spec,
Protocol::Tcp,
)
.await;
// BlocksByRange Request // BlocksByRange Request
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send)); let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send));
@ -476,7 +502,7 @@ fn test_blocks_by_range_chunked_rpc_terminates_correctly() {
// Tests an empty response to a BlocksByRange RPC Message // Tests an empty response to a BlocksByRange RPC Message
#[test] #[test]
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
fn test_blocks_by_range_single_empty_rpc() { fn test_tcp_blocks_by_range_single_empty_rpc() {
// set up the logging. The level and enabled logging or not // set up the logging. The level and enabled logging or not
let log_level = Level::Trace; let log_level = Level::Trace;
let enable_logging = false; let enable_logging = false;
@ -488,8 +514,14 @@ fn test_blocks_by_range_single_empty_rpc() {
rt.block_on(async { rt.block_on(async {
// get sender/receiver // get sender/receiver
let (mut sender, mut receiver) = let (mut sender, mut receiver) = common::build_node_pair(
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Base, &spec).await; Arc::downgrade(&rt),
&log,
ForkName::Base,
&spec,
Protocol::Tcp,
)
.await;
// BlocksByRange Request // BlocksByRange Request
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, 10)); let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, 10));
@ -576,7 +608,7 @@ fn test_blocks_by_range_single_empty_rpc() {
// serves to test the snappy framing format as well. // serves to test the snappy framing format as well.
#[test] #[test]
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
fn test_blocks_by_root_chunked_rpc() { fn test_tcp_blocks_by_root_chunked_rpc() {
// set up the logging. The level and enabled logging or not // set up the logging. The level and enabled logging or not
let log_level = Level::Debug; let log_level = Level::Debug;
let enable_logging = false; let enable_logging = false;
@ -589,8 +621,14 @@ fn test_blocks_by_root_chunked_rpc() {
let rt = Arc::new(Runtime::new().unwrap()); let rt = Arc::new(Runtime::new().unwrap());
// get sender/receiver // get sender/receiver
rt.block_on(async { rt.block_on(async {
let (mut sender, mut receiver) = let (mut sender, mut receiver) = common::build_node_pair(
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Merge, &spec).await; Arc::downgrade(&rt),
&log,
ForkName::Merge,
&spec,
Protocol::Tcp,
)
.await;
// BlocksByRoot Request // BlocksByRoot Request
let rpc_request = let rpc_request =
@ -702,7 +740,7 @@ fn test_blocks_by_root_chunked_rpc() {
// Tests a streamed, chunked BlocksByRoot RPC Message terminates when all expected reponses have been received // Tests a streamed, chunked BlocksByRoot RPC Message terminates when all expected reponses have been received
#[test] #[test]
fn test_blocks_by_root_chunked_rpc_terminates_correctly() { fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() {
// set up the logging. The level and enabled logging or not // set up the logging. The level and enabled logging or not
let log_level = Level::Debug; let log_level = Level::Debug;
let enable_logging = false; let enable_logging = false;
@ -716,8 +754,14 @@ fn test_blocks_by_root_chunked_rpc_terminates_correctly() {
let rt = Arc::new(Runtime::new().unwrap()); let rt = Arc::new(Runtime::new().unwrap());
// get sender/receiver // get sender/receiver
rt.block_on(async { rt.block_on(async {
let (mut sender, mut receiver) = let (mut sender, mut receiver) = common::build_node_pair(
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Base, &spec).await; Arc::downgrade(&rt),
&log,
ForkName::Base,
&spec,
Protocol::Tcp,
)
.await;
// BlocksByRoot Request // BlocksByRoot Request
let rpc_request = let rpc_request =
@ -833,14 +877,9 @@ fn test_blocks_by_root_chunked_rpc_terminates_correctly() {
}) })
} }
// Tests a Goodbye RPC message /// Establishes a pair of nodes and disconnects the pair based on the selected protocol via an RPC
#[test] /// Goodbye message.
#[allow(clippy::single_match)] fn goodbye_test(log_level: Level, enable_logging: bool, protocol: Protocol) {
fn test_goodbye_rpc() {
// set up the logging. The level and enabled logging or not
let log_level = Level::Trace;
let enable_logging = false;
let log = common::build_log(log_level, enable_logging); let log = common::build_log(log_level, enable_logging);
let rt = Arc::new(Runtime::new().unwrap()); let rt = Arc::new(Runtime::new().unwrap());
@ -850,7 +889,8 @@ fn test_goodbye_rpc() {
// get sender/receiver // get sender/receiver
rt.block_on(async { rt.block_on(async {
let (mut sender, mut receiver) = let (mut sender, mut receiver) =
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Base, &spec).await; common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Base, &spec, protocol)
.await;
// build the sender future // build the sender future
let sender_future = async { let sender_future = async {
@ -876,13 +916,10 @@ fn test_goodbye_rpc() {
// build the receiver future // build the receiver future
let receiver_future = async { let receiver_future = async {
loop { loop {
match receiver.next_event().await { if let NetworkEvent::PeerDisconnected(_) = receiver.next_event().await {
NetworkEvent::PeerDisconnected(_) => {
// Should receive sent RPC request // Should receive sent RPC request
return; return;
} }
_ => {} // Ignore other events
}
} }
}; };
@ -896,3 +933,23 @@ fn test_goodbye_rpc() {
} }
}) })
} }
// Tests a Goodbye RPC message
#[test]
#[allow(clippy::single_match)]
fn tcp_test_goodbye_rpc() {
// set up the logging. The level and enabled logging or not
let log_level = Level::Debug;
let enable_logging = true;
goodbye_test(log_level, enable_logging, Protocol::Tcp);
}
// Tests a Goodbye RPC message
#[test]
#[allow(clippy::single_match)]
fn quic_test_goodbye_rpc() {
// set up the logging. The level and enabled logging or not
let log_level = Level::Debug;
let enable_logging = true;
goodbye_test(log_level, enable_logging, Protocol::Quic);
}

View File

@ -12,20 +12,49 @@ use types::EthSpec;
/// Configuration required to construct the UPnP port mappings. /// Configuration required to construct the UPnP port mappings.
pub struct UPnPConfig { pub struct UPnPConfig {
/// The local tcp port. /// The local TCP port.
tcp_port: u16, tcp_port: u16,
/// The local udp port. /// The local UDP discovery port.
udp_port: u16, disc_port: u16,
/// The local UDP quic port.
quic_port: u16,
/// Whether discovery is enabled or not. /// Whether discovery is enabled or not.
disable_discovery: bool, disable_discovery: bool,
/// Whether quic is enabled or not.
disable_quic_support: bool,
}
/// Contains mappings that managed to be established.
#[derive(Default, Debug)]
pub struct EstablishedUPnPMappings {
/// A TCP port mapping for libp2p.
pub tcp_port: Option<u16>,
/// A UDP port for the QUIC libp2p transport.
pub udp_quic_port: Option<u16>,
/// A UDP port for discv5.
pub udp_disc_port: Option<u16>,
}
impl EstablishedUPnPMappings {
/// Returns true if at least one value is set.
pub fn is_some(&self) -> bool {
self.tcp_port.is_some() || self.udp_quic_port.is_some() || self.udp_disc_port.is_some()
}
// Iterator over the UDP ports
pub fn udp_ports(&self) -> impl Iterator<Item = &u16> {
self.udp_quic_port.iter().chain(self.udp_disc_port.iter())
}
} }
impl UPnPConfig { impl UPnPConfig {
pub fn from_config(config: &NetworkConfig) -> Option<Self> { pub fn from_config(config: &NetworkConfig) -> Option<Self> {
config.listen_addrs().v4().map(|v4_addr| UPnPConfig { config.listen_addrs().v4().map(|v4_addr| UPnPConfig {
tcp_port: v4_addr.tcp_port, tcp_port: v4_addr.tcp_port,
udp_port: v4_addr.udp_port, disc_port: v4_addr.disc_port,
quic_port: v4_addr.quic_port,
disable_discovery: config.disable_discovery, disable_discovery: config.disable_discovery,
disable_quic_support: config.disable_quic_support,
}) })
} }
} }
@ -68,6 +97,8 @@ pub fn construct_upnp_mappings<T: EthSpec>(
debug!(log, "UPnP Local IP Discovered"; "ip" => ?local_ip); debug!(log, "UPnP Local IP Discovered"; "ip" => ?local_ip);
let mut mappings = EstablishedUPnPMappings::default();
match local_ip { match local_ip {
IpAddr::V4(address) => { IpAddr::V4(address) => {
let libp2p_socket = SocketAddrV4::new(address, config.tcp_port); let libp2p_socket = SocketAddrV4::new(address, config.tcp_port);
@ -76,40 +107,47 @@ pub fn construct_upnp_mappings<T: EthSpec>(
// one. // one.
// I've found this to be more reliable. If multiple users are behind a single // I've found this to be more reliable. If multiple users are behind a single
// router, they should ideally try to set different port numbers. // router, they should ideally try to set different port numbers.
let tcp_socket = add_port_mapping( mappings.tcp_port = add_port_mapping(
&gateway, &gateway,
igd::PortMappingProtocol::TCP, igd::PortMappingProtocol::TCP,
libp2p_socket, libp2p_socket,
"tcp", "tcp",
&log, &log,
).and_then(|_| { ).map(|_| {
let external_socket = external_ip.as_ref().map(|ip| SocketAddr::new((*ip).into(), config.tcp_port)).map_err(|_| ()); let external_socket = external_ip.as_ref().map(|ip| SocketAddr::new((*ip).into(), config.tcp_port)).map_err(|_| ());
info!(log, "UPnP TCP route established"; "external_socket" => format!("{}:{}", external_socket.as_ref().map(|ip| ip.to_string()).unwrap_or_else(|_| "".into()), config.tcp_port)); info!(log, "UPnP TCP route established"; "external_socket" => format!("{}:{}", external_socket.as_ref().map(|ip| ip.to_string()).unwrap_or_else(|_| "".into()), config.tcp_port));
external_socket config.tcp_port
}).ok(); }).ok();
let udp_socket = if !config.disable_discovery { let set_udp_mapping = |udp_port| {
let discovery_socket = SocketAddrV4::new(address, config.udp_port); let udp_socket = SocketAddrV4::new(address, udp_port);
add_port_mapping( add_port_mapping(
&gateway, &gateway,
igd::PortMappingProtocol::UDP, igd::PortMappingProtocol::UDP,
discovery_socket, udp_socket,
"udp", "udp",
&log, &log,
).and_then(|_| { ).map(|_| {
let external_socket = external_ip info!(log, "UPnP UDP route established"; "external_socket" => format!("{}:{}", external_ip.as_ref().map(|ip| ip.to_string()).unwrap_or_else(|_| "".into()), udp_port));
.map(|ip| SocketAddr::new(ip.into(), config.udp_port)).map_err(|_| ()); })
info!(log, "UPnP UDP route established"; "external_socket" => format!("{}:{}", external_socket.as_ref().map(|ip| ip.to_string()).unwrap_or_else(|_| "".into()), config.udp_port));
external_socket
}).ok()
} else {
None
}; };
// Set the discovery UDP port mapping
if !config.disable_discovery && set_udp_mapping(config.disc_port).is_ok() {
mappings.udp_disc_port = Some(config.disc_port);
}
// Set the quic UDP port mapping
if !config.disable_quic_support && set_udp_mapping(config.quic_port).is_ok() {
mappings.udp_quic_port = Some(config.quic_port);
}
// report any updates to the network service. // report any updates to the network service.
network_send.send(NetworkMessage::UPnPMappingEstablished{ tcp_socket, udp_socket }) if mappings.is_some() {
network_send.send(NetworkMessage::UPnPMappingEstablished{ mappings })
.unwrap_or_else(|e| debug!(log, "Could not send message to the network service"; "error" => %e)); .unwrap_or_else(|e| debug!(log, "Could not send message to the network service"; "error" => %e));
} }
}
_ => debug!(log, "UPnP no routes constructed. IPv6 not supported"), _ => debug!(log, "UPnP no routes constructed. IPv6 not supported"),
} }
} }
@ -161,12 +199,12 @@ fn add_port_mapping(
} }
/// Removes the specified TCP and UDP port mappings. /// Removes the specified TCP and UDP port mappings.
pub fn remove_mappings(tcp_port: Option<u16>, udp_port: Option<u16>, log: &slog::Logger) { pub fn remove_mappings(mappings: &EstablishedUPnPMappings, log: &slog::Logger) {
if tcp_port.is_some() || udp_port.is_some() { if mappings.is_some() {
debug!(log, "Removing UPnP port mappings"); debug!(log, "Removing UPnP port mappings");
match igd::search_gateway(Default::default()) { match igd::search_gateway(Default::default()) {
Ok(gateway) => { Ok(gateway) => {
if let Some(tcp_port) = tcp_port { if let Some(tcp_port) = mappings.tcp_port {
match gateway.remove_port(igd::PortMappingProtocol::TCP, tcp_port) { match gateway.remove_port(igd::PortMappingProtocol::TCP, tcp_port) {
Ok(()) => debug!(log, "UPnP Removed TCP port mapping"; "port" => tcp_port), Ok(()) => debug!(log, "UPnP Removed TCP port mapping"; "port" => tcp_port),
Err(e) => { Err(e) => {
@ -174,8 +212,8 @@ pub fn remove_mappings(tcp_port: Option<u16>, udp_port: Option<u16>, log: &slog:
} }
} }
} }
if let Some(udp_port) = udp_port { for udp_port in mappings.udp_ports() {
match gateway.remove_port(igd::PortMappingProtocol::UDP, udp_port) { match gateway.remove_port(igd::PortMappingProtocol::UDP, *udp_port) {
Ok(()) => debug!(log, "UPnP Removed UDP port mapping"; "port" => udp_port), Ok(()) => debug!(log, "UPnP Removed UDP port mapping"; "port" => udp_port),
Err(e) => { Err(e) => {
debug!(log, "UPnP Failed to remove UDP port mapping"; "port" => udp_port, "error" => %e) debug!(log, "UPnP Failed to remove UDP port mapping"; "port" => udp_port, "error" => %e)

View File

@ -37,7 +37,6 @@ const VALIDATOR_COUNT: usize = SLOTS_PER_EPOCH as usize;
const SMALL_CHAIN: u64 = 2; const SMALL_CHAIN: u64 = 2;
const LONG_CHAIN: u64 = SLOTS_PER_EPOCH * 2; const LONG_CHAIN: u64 = SLOTS_PER_EPOCH * 2;
const TCP_PORT: u16 = 42;
const SEQ_NUMBER: u64 = 0; const SEQ_NUMBER: u64 = 0;
/// The default time to wait for `BeaconProcessor` events. /// The default time to wait for `BeaconProcessor` events.
@ -195,15 +194,7 @@ impl TestRig {
}); });
let enr_key = CombinedKey::generate_secp256k1(); let enr_key = CombinedKey::generate_secp256k1();
let enr = EnrBuilder::new("v4").build(&enr_key).unwrap(); let enr = EnrBuilder::new("v4").build(&enr_key).unwrap();
let network_globals = Arc::new(NetworkGlobals::new( let network_globals = Arc::new(NetworkGlobals::new(enr, meta_data, vec![], false, &log));
enr,
Some(TCP_PORT),
None,
meta_data,
vec![],
false,
&log,
));
let executor = harness.runtime.task_executor.clone(); let executor = harness.runtime.task_executor.clone();

View File

@ -1,4 +1,5 @@
use super::sync::manager::RequestId as SyncId; use super::sync::manager::RequestId as SyncId;
use crate::nat::EstablishedUPnPMappings;
use crate::network_beacon_processor::InvalidBlockStorage; use crate::network_beacon_processor::InvalidBlockStorage;
use crate::persisted_dht::{clear_dht, load_dht, persist_dht}; use crate::persisted_dht::{clear_dht, load_dht, persist_dht};
use crate::router::{Router, RouterMessage}; use crate::router::{Router, RouterMessage};
@ -26,7 +27,7 @@ use lighthouse_network::{
MessageId, NetworkEvent, NetworkGlobals, PeerId, MessageId, NetworkEvent, NetworkGlobals, PeerId,
}; };
use slog::{crit, debug, error, info, o, trace, warn}; use slog::{crit, debug, error, info, o, trace, warn};
use std::{collections::HashSet, net::SocketAddr, pin::Pin, sync::Arc, time::Duration}; use std::{collections::HashSet, pin::Pin, sync::Arc, time::Duration};
use store::HotColdDB; use store::HotColdDB;
use strum::IntoStaticStr; use strum::IntoStaticStr;
use task_executor::ShutdownReason; use task_executor::ShutdownReason;
@ -93,12 +94,10 @@ pub enum NetworkMessage<T: EthSpec> {
/// The result of the validation /// The result of the validation
validation_result: MessageAcceptance, validation_result: MessageAcceptance,
}, },
/// Called if a known external TCP socket address has been updated. /// Called if UPnP managed to establish an external port mapping.
UPnPMappingEstablished { UPnPMappingEstablished {
/// The external TCP address has been updated. /// The mappings that were established.
tcp_socket: Option<SocketAddr>, mappings: EstablishedUPnPMappings,
/// The external UDP address has been updated.
udp_socket: Option<SocketAddr>,
}, },
/// Reports a peer to the peer manager for performing an action. /// Reports a peer to the peer manager for performing an action.
ReportPeer { ReportPeer {
@ -190,11 +189,8 @@ pub struct NetworkService<T: BeaconChainTypes> {
/// A collection of global variables, accessible outside of the network service. /// A collection of global variables, accessible outside of the network service.
network_globals: Arc<NetworkGlobals<T::EthSpec>>, network_globals: Arc<NetworkGlobals<T::EthSpec>>,
/// Stores potentially created UPnP mappings to be removed on shutdown. (TCP port and UDP /// Stores potentially created UPnP mappings to be removed on shutdown. (TCP port and UDP
/// port). /// ports).
upnp_mappings: (Option<u16>, Option<u16>), upnp_mappings: EstablishedUPnPMappings,
/// Keeps track of if discovery is auto-updating or not. This is used to inform us if we should
/// update the UDP socket of discovery if the UPnP mappings get established.
discovery_auto_update: bool,
/// A delay that expires when a new fork takes place. /// A delay that expires when a new fork takes place.
next_fork_update: Pin<Box<OptionFuture<Sleep>>>, next_fork_update: Pin<Box<OptionFuture<Sleep>>>,
/// A delay that expires when we need to subscribe to a new fork's topics. /// A delay that expires when we need to subscribe to a new fork's topics.
@ -359,8 +355,7 @@ impl<T: BeaconChainTypes> NetworkService<T> {
router_send, router_send,
store, store,
network_globals: network_globals.clone(), network_globals: network_globals.clone(),
upnp_mappings: (None, None), upnp_mappings: EstablishedUPnPMappings::default(),
discovery_auto_update: config.discv5_config.enr_update,
next_fork_update, next_fork_update,
next_fork_subscriptions, next_fork_subscriptions,
next_unsubscribe, next_unsubscribe,
@ -616,35 +611,21 @@ impl<T: BeaconChainTypes> NetworkService<T> {
} => { } => {
self.libp2p.send_error_reponse(peer_id, id, error, reason); self.libp2p.send_error_reponse(peer_id, id, error, reason);
} }
NetworkMessage::UPnPMappingEstablished { NetworkMessage::UPnPMappingEstablished { mappings } => {
tcp_socket, self.upnp_mappings = mappings;
udp_socket,
} => {
self.upnp_mappings = (tcp_socket.map(|s| s.port()), udp_socket.map(|s| s.port()));
// If there is an external TCP port update, modify our local ENR. // If there is an external TCP port update, modify our local ENR.
if let Some(tcp_socket) = tcp_socket { if let Some(tcp_port) = self.upnp_mappings.tcp_port {
if let Err(e) = self if let Err(e) = self.libp2p.discovery_mut().update_enr_tcp_port(tcp_port) {
.libp2p
.discovery_mut()
.update_enr_tcp_port(tcp_socket.port())
{
warn!(self.log, "Failed to update ENR"; "error" => e); warn!(self.log, "Failed to update ENR"; "error" => e);
} }
} }
// if the discovery service is not auto-updating, update it with the // If there is an external QUIC port update, modify our local ENR.
// UPnP mappings if let Some(quic_port) = self.upnp_mappings.udp_quic_port {
if !self.discovery_auto_update { if let Err(e) = self.libp2p.discovery_mut().update_enr_quic_port(quic_port) {
if let Some(udp_socket) = udp_socket {
if let Err(e) = self
.libp2p
.discovery_mut()
.update_enr_udp_socket(udp_socket)
{
warn!(self.log, "Failed to update ENR"; "error" => e); warn!(self.log, "Failed to update ENR"; "error" => e);
} }
} }
} }
}
NetworkMessage::ValidationResult { NetworkMessage::ValidationResult {
propagation_source, propagation_source,
message_id, message_id,
@ -994,7 +975,7 @@ impl<T: BeaconChainTypes> Drop for NetworkService<T> {
} }
// attempt to remove port mappings // attempt to remove port mappings
crate::nat::remove_mappings(self.upnp_mappings.0, self.upnp_mappings.1, &self.log); crate::nat::remove_mappings(&self.upnp_mappings, &self.log);
info!(self.log, "Network service shutdown"); info!(self.log, "Network service shutdown");
} }

View File

@ -60,7 +60,7 @@ mod tests {
); );
let mut config = NetworkConfig::default(); let mut config = NetworkConfig::default();
config.set_ipv4_listening_address(std::net::Ipv4Addr::UNSPECIFIED, 21212, 21212); config.set_ipv4_listening_address(std::net::Ipv4Addr::UNSPECIFIED, 21212, 21212, 21213);
config.discv5_config.table_filter = |_| true; // Do not ignore local IPs config.discv5_config.table_filter = |_| true; // Do not ignore local IPs
config.upnp_enabled = false; config.upnp_enabled = false;
config.boot_nodes_enr = enrs.clone(); config.boot_nodes_enr = enrs.clone();

View File

@ -75,11 +75,11 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.help("The address lighthouse will listen for UDP and TCP connections. To listen \ .help("The address lighthouse will listen for UDP and TCP connections. To listen \
over IpV4 and IpV6 set this flag twice with the different values.\n\ over IpV4 and IpV6 set this flag twice with the different values.\n\
Examples:\n\ Examples:\n\
- --listen-address '0.0.0.0' will listen over Ipv4.\n\ - --listen-address '0.0.0.0' will listen over IPv4.\n\
- --listen-address '::' will listen over Ipv6.\n\ - --listen-address '::' will listen over IPv6.\n\
- --listen-address '0.0.0.0' --listen-address '::' will listen over both \ - --listen-address '0.0.0.0' --listen-address '::' will listen over both \
Ipv4 and Ipv6. The order of the given addresses is not relevant. However, \ IPv4 and IPv6. The order of the given addresses is not relevant. However, \
multiple Ipv4, or multiple Ipv6 addresses will not be accepted.") multiple IPv4, or multiple IPv6 addresses will not be accepted.")
.multiple(true) .multiple(true)
.max_values(2) .max_values(2)
.default_value("0.0.0.0") .default_value("0.0.0.0")
@ -89,9 +89,10 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
Arg::with_name("port") Arg::with_name("port")
.long("port") .long("port")
.value_name("PORT") .value_name("PORT")
.help("The TCP/UDP port to listen on. The UDP port can be modified by the \ .help("The TCP/UDP ports to listen on. There are two UDP ports. \
--discovery-port flag. If listening over both Ipv4 and Ipv6 the --port flag \ The discovery UDP port will be set to this value and the Quic UDP port will be set to this value + 1. The discovery port can be modified by the \
will apply to the Ipv4 address and --port6 to the Ipv6 address.") --discovery-port flag and the quic port can be modified by the --quic-port flag. If listening over both IPv4 and IPv6 the --port flag \
will apply to the IPv4 address and --port6 to the IPv6 address.")
.default_value("9000") .default_value("9000")
.takes_value(true), .takes_value(true),
) )
@ -99,8 +100,8 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
Arg::with_name("port6") Arg::with_name("port6")
.long("port6") .long("port6")
.value_name("PORT") .value_name("PORT")
.help("The TCP/UDP port to listen on over IpV6 when listening over both Ipv4 and \ .help("The TCP/UDP ports to listen on over IPv6 when listening over both IPv4 and \
Ipv6. Defaults to 9090 when required.") IPv6. Defaults to 9090 when required. The Quic UDP port will be set to this value + 1.")
.default_value("9090") .default_value("9090")
.takes_value(true), .takes_value(true),
) )
@ -111,12 +112,27 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.help("The UDP port that discovery will listen on. Defaults to `port`") .help("The UDP port that discovery will listen on. Defaults to `port`")
.takes_value(true), .takes_value(true),
) )
.arg(
Arg::with_name("quic-port")
.long("quic-port")
.value_name("PORT")
.help("The UDP port that quic will listen on. Defaults to `port` + 1")
.takes_value(true),
)
.arg( .arg(
Arg::with_name("discovery-port6") Arg::with_name("discovery-port6")
.long("discovery-port6") .long("discovery-port6")
.value_name("PORT") .value_name("PORT")
.help("The UDP port that discovery will listen on over IpV6 if listening over \ .help("The UDP port that discovery will listen on over IPv6 if listening over \
both Ipv4 and IpV6. Defaults to `port6`") both IPv4 and IPv6. Defaults to `port6`")
.takes_value(true),
)
.arg(
Arg::with_name("quic-port6")
.long("quic-port6")
.value_name("PORT")
.help("The UDP port that quic will listen on over IPv6 if listening over \
both IPv4 and IPv6. Defaults to `port6` + 1")
.takes_value(true), .takes_value(true),
) )
.arg( .arg(
@ -159,7 +175,15 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.long("enr-udp-port") .long("enr-udp-port")
.value_name("PORT") .value_name("PORT")
.help("The UDP4 port of the local ENR. Set this only if you are sure other nodes \ .help("The UDP4 port of the local ENR. Set this only if you are sure other nodes \
can connect to your local node on this port over IpV4.") can connect to your local node on this port over IPv4.")
.takes_value(true),
)
.arg(
Arg::with_name("enr-quic-port")
.long("enr-quic-port")
.value_name("PORT")
.help("The quic UDP4 port that will be set on the local ENR. Set this only if you are sure other nodes \
can connect to your local node on this port over IPv4.")
.takes_value(true), .takes_value(true),
) )
.arg( .arg(
@ -167,7 +191,15 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.long("enr-udp6-port") .long("enr-udp6-port")
.value_name("PORT") .value_name("PORT")
.help("The UDP6 port of the local ENR. Set this only if you are sure other nodes \ .help("The UDP6 port of the local ENR. Set this only if you are sure other nodes \
can connect to your local node on this port over IpV6.") can connect to your local node on this port over IPv6.")
.takes_value(true),
)
.arg(
Arg::with_name("enr-quic6-port")
.long("enr-quic6-port")
.value_name("PORT")
.help("The quic UDP6 port that will be set on the local ENR. Set this only if you are sure other nodes \
can connect to your local node on this port over IPv6.")
.takes_value(true), .takes_value(true),
) )
.arg( .arg(
@ -175,7 +207,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.long("enr-tcp-port") .long("enr-tcp-port")
.value_name("PORT") .value_name("PORT")
.help("The TCP4 port of the local ENR. Set this only if you are sure other nodes \ .help("The TCP4 port of the local ENR. Set this only if you are sure other nodes \
can connect to your local node on this port over IpV4. The --port flag is \ can connect to your local node on this port over IPv4. The --port flag is \
used if this is not set.") used if this is not set.")
.takes_value(true), .takes_value(true),
) )
@ -184,7 +216,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.long("enr-tcp6-port") .long("enr-tcp6-port")
.value_name("PORT") .value_name("PORT")
.help("The TCP6 port of the local ENR. Set this only if you are sure other nodes \ .help("The TCP6 port of the local ENR. Set this only if you are sure other nodes \
can connect to your local node on this port over IpV6. The --port6 flag is \ can connect to your local node on this port over IPv6. The --port6 flag is \
used if this is not set.") used if this is not set.")
.takes_value(true), .takes_value(true),
) )
@ -225,11 +257,18 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
without an ENR.") without an ENR.")
.takes_value(true), .takes_value(true),
) )
// NOTE: This is hidden because it is primarily a developer feature for testnets and
// debugging. We remove it from the list to avoid clutter.
.arg( .arg(
Arg::with_name("disable-discovery") Arg::with_name("disable-discovery")
.long("disable-discovery") .long("disable-discovery")
.help("Disables the discv5 discovery protocol. The node will not search for new peers or participate in the discovery protocol.") .help("Disables the discv5 discovery protocol. The node will not search for new peers or participate in the discovery protocol.")
.takes_value(false), .hidden(true)
)
.arg(
Arg::with_name("disable-quic")
.long("disable-quic")
.help("Disables the quic transport. The node will rely solely on the TCP transport for libp2p connections.")
) )
.arg( .arg(
Arg::with_name("disable-peer-scoring") Arg::with_name("disable-peer-scoring")

View File

@ -914,15 +914,15 @@ pub fn parse_listening_addresses(
.map_err(|parse_error| format!("Failed to parse --port6 as an integer: {parse_error}"))? .map_err(|parse_error| format!("Failed to parse --port6 as an integer: {parse_error}"))?
.unwrap_or(9090); .unwrap_or(9090);
// parse the possible udp ports // parse the possible discovery ports.
let maybe_udp_port = cli_args let maybe_disc_port = cli_args
.value_of("discovery-port") .value_of("discovery-port")
.map(str::parse::<u16>) .map(str::parse::<u16>)
.transpose() .transpose()
.map_err(|parse_error| { .map_err(|parse_error| {
format!("Failed to parse --discovery-port as an integer: {parse_error}") format!("Failed to parse --discovery-port as an integer: {parse_error}")
})?; })?;
let maybe_udp6_port = cli_args let maybe_disc6_port = cli_args
.value_of("discovery-port6") .value_of("discovery-port6")
.map(str::parse::<u16>) .map(str::parse::<u16>)
.transpose() .transpose()
@ -930,6 +930,24 @@ pub fn parse_listening_addresses(
format!("Failed to parse --discovery-port6 as an integer: {parse_error}") format!("Failed to parse --discovery-port6 as an integer: {parse_error}")
})?; })?;
// parse the possible quic port.
let maybe_quic_port = cli_args
.value_of("quic-port")
.map(str::parse::<u16>)
.transpose()
.map_err(|parse_error| {
format!("Failed to parse --quic-port as an integer: {parse_error}")
})?;
// parse the possible quic port.
let maybe_quic6_port = cli_args
.value_of("quic-port6")
.map(str::parse::<u16>)
.transpose()
.map_err(|parse_error| {
format!("Failed to parse --quic6-port as an integer: {parse_error}")
})?;
// Now put everything together // Now put everything together
let listening_addresses = match (maybe_ipv4, maybe_ipv6) { let listening_addresses = match (maybe_ipv4, maybe_ipv6) {
(None, None) => { (None, None) => {
@ -940,7 +958,7 @@ pub fn parse_listening_addresses(
// A single ipv6 address was provided. Set the ports // A single ipv6 address was provided. Set the ports
if cli_args.is_present("port6") { if cli_args.is_present("port6") {
warn!(log, "When listening only over IpV6, use the --port flag. The value of --port6 will be ignored.") warn!(log, "When listening only over IPv6, use the --port flag. The value of --port6 will be ignored.")
} }
// use zero ports if required. If not, use the given port. // use zero ports if required. If not, use the given port.
let tcp_port = use_zero_ports let tcp_port = use_zero_ports
@ -948,20 +966,32 @@ pub fn parse_listening_addresses(
.transpose()? .transpose()?
.unwrap_or(port); .unwrap_or(port);
if maybe_udp6_port.is_some() { if maybe_disc6_port.is_some() {
warn!(log, "When listening only over IpV6, use the --discovery-port flag. The value of --discovery-port6 will be ignored.") warn!(log, "When listening only over IPv6, use the --discovery-port flag. The value of --discovery-port6 will be ignored.")
} }
if maybe_quic6_port.is_some() {
warn!(log, "When listening only over IPv6, use the --quic-port flag. The value of --quic-port6 will be ignored.")
}
// use zero ports if required. If not, use the specific udp port. If none given, use // use zero ports if required. If not, use the specific udp port. If none given, use
// the tcp port. // the tcp port.
let udp_port = use_zero_ports let disc_port = use_zero_ports
.then(unused_port::unused_udp6_port) .then(unused_port::unused_udp6_port)
.transpose()? .transpose()?
.or(maybe_udp_port) .or(maybe_disc_port)
.unwrap_or(port); .unwrap_or(port);
let quic_port = use_zero_ports
.then(unused_port::unused_udp6_port)
.transpose()?
.or(maybe_quic_port)
.unwrap_or(port + 1);
ListenAddress::V6(lighthouse_network::ListenAddr { ListenAddress::V6(lighthouse_network::ListenAddr {
addr: ipv6, addr: ipv6,
udp_port, quic_port,
disc_port,
tcp_port, tcp_port,
}) })
} }
@ -973,16 +1003,25 @@ pub fn parse_listening_addresses(
.then(unused_port::unused_tcp4_port) .then(unused_port::unused_tcp4_port)
.transpose()? .transpose()?
.unwrap_or(port); .unwrap_or(port);
// use zero ports if required. If not, use the specific udp port. If none given, use // use zero ports if required. If not, use the specific discovery port. If none given, use
// the tcp port. // the tcp port.
let udp_port = use_zero_ports let disc_port = use_zero_ports
.then(unused_port::unused_udp4_port) .then(unused_port::unused_udp4_port)
.transpose()? .transpose()?
.or(maybe_udp_port) .or(maybe_disc_port)
.unwrap_or(port); .unwrap_or(port);
// use zero ports if required. If not, use the specific quic port. If none given, use
// the tcp port + 1.
let quic_port = use_zero_ports
.then(unused_port::unused_udp4_port)
.transpose()?
.or(maybe_quic_port)
.unwrap_or(port + 1);
ListenAddress::V4(lighthouse_network::ListenAddr { ListenAddress::V4(lighthouse_network::ListenAddr {
addr: ipv4, addr: ipv4,
udp_port, disc_port,
quic_port,
tcp_port, tcp_port,
}) })
} }
@ -991,31 +1030,44 @@ pub fn parse_listening_addresses(
.then(unused_port::unused_tcp4_port) .then(unused_port::unused_tcp4_port)
.transpose()? .transpose()?
.unwrap_or(port); .unwrap_or(port);
let ipv4_udp_port = use_zero_ports let ipv4_disc_port = use_zero_ports
.then(unused_port::unused_udp4_port) .then(unused_port::unused_udp4_port)
.transpose()? .transpose()?
.or(maybe_udp_port) .or(maybe_disc_port)
.unwrap_or(ipv4_tcp_port); .unwrap_or(ipv4_tcp_port);
let ipv4_quic_port = use_zero_ports
.then(unused_port::unused_udp4_port)
.transpose()?
.or(maybe_quic_port)
.unwrap_or(port + 1);
// Defaults to 9090 when required // Defaults to 9090 when required
let ipv6_tcp_port = use_zero_ports let ipv6_tcp_port = use_zero_ports
.then(unused_port::unused_tcp6_port) .then(unused_port::unused_tcp6_port)
.transpose()? .transpose()?
.unwrap_or(port6); .unwrap_or(port6);
let ipv6_udp_port = use_zero_ports let ipv6_disc_port = use_zero_ports
.then(unused_port::unused_udp6_port) .then(unused_port::unused_udp6_port)
.transpose()? .transpose()?
.or(maybe_udp6_port) .or(maybe_disc6_port)
.unwrap_or(ipv6_tcp_port); .unwrap_or(ipv6_tcp_port);
let ipv6_quic_port = use_zero_ports
.then(unused_port::unused_udp6_port)
.transpose()?
.or(maybe_quic6_port)
.unwrap_or(ipv6_tcp_port + 1);
ListenAddress::DualStack( ListenAddress::DualStack(
lighthouse_network::ListenAddr { lighthouse_network::ListenAddr {
addr: ipv4, addr: ipv4,
udp_port: ipv4_udp_port, disc_port: ipv4_disc_port,
quic_port: ipv4_quic_port,
tcp_port: ipv4_tcp_port, tcp_port: ipv4_tcp_port,
}, },
lighthouse_network::ListenAddr { lighthouse_network::ListenAddr {
addr: ipv6, addr: ipv6,
udp_port: ipv6_udp_port, disc_port: ipv6_disc_port,
quic_port: ipv6_quic_port,
tcp_port: ipv6_tcp_port, tcp_port: ipv6_tcp_port,
}, },
) )
@ -1131,6 +1183,14 @@ pub fn set_network_config(
); );
} }
if let Some(enr_quic_port_str) = cli_args.value_of("enr-quic-port") {
config.enr_quic4_port = Some(
enr_quic_port_str
.parse::<u16>()
.map_err(|_| format!("Invalid quic port: {}", enr_quic_port_str))?,
);
}
if let Some(enr_tcp_port_str) = cli_args.value_of("enr-tcp-port") { if let Some(enr_tcp_port_str) = cli_args.value_of("enr-tcp-port") {
config.enr_tcp4_port = Some( config.enr_tcp4_port = Some(
enr_tcp_port_str enr_tcp_port_str
@ -1147,6 +1207,14 @@ pub fn set_network_config(
); );
} }
if let Some(enr_quic_port_str) = cli_args.value_of("enr-quic6-port") {
config.enr_quic6_port = Some(
enr_quic_port_str
.parse::<u16>()
.map_err(|_| format!("Invalid quic port: {}", enr_quic_port_str))?,
);
}
if let Some(enr_tcp_port_str) = cli_args.value_of("enr-tcp6-port") { if let Some(enr_tcp_port_str) = cli_args.value_of("enr-tcp6-port") {
config.enr_tcp6_port = Some( config.enr_tcp6_port = Some(
enr_tcp_port_str enr_tcp_port_str
@ -1156,9 +1224,9 @@ pub fn set_network_config(
} }
if cli_args.is_present("enr-match") { if cli_args.is_present("enr-match") {
// Match the Ip and UDP port in the enr. // Match the IP and UDP port in the ENR.
// set the enr address to localhost if the address is unspecified // Set the ENR address to localhost if the address is unspecified.
if let Some(ipv4_addr) = config.listen_addrs().v4().cloned() { if let Some(ipv4_addr) = config.listen_addrs().v4().cloned() {
let ipv4_enr_addr = if ipv4_addr.addr == Ipv4Addr::UNSPECIFIED { let ipv4_enr_addr = if ipv4_addr.addr == Ipv4Addr::UNSPECIFIED {
Ipv4Addr::LOCALHOST Ipv4Addr::LOCALHOST
@ -1166,7 +1234,7 @@ pub fn set_network_config(
ipv4_addr.addr ipv4_addr.addr
}; };
config.enr_address.0 = Some(ipv4_enr_addr); config.enr_address.0 = Some(ipv4_enr_addr);
config.enr_udp4_port = Some(ipv4_addr.udp_port); config.enr_udp4_port = Some(ipv4_addr.disc_port);
} }
if let Some(ipv6_addr) = config.listen_addrs().v6().cloned() { if let Some(ipv6_addr) = config.listen_addrs().v6().cloned() {
@ -1176,7 +1244,7 @@ pub fn set_network_config(
ipv6_addr.addr ipv6_addr.addr
}; };
config.enr_address.1 = Some(ipv6_enr_addr); config.enr_address.1 = Some(ipv6_enr_addr);
config.enr_udp6_port = Some(ipv6_addr.udp_port); config.enr_udp6_port = Some(ipv6_addr.disc_port);
} }
} }
@ -1209,11 +1277,11 @@ pub fn set_network_config(
// actually matters. Just use the udp port. // actually matters. Just use the udp port.
let port = match config.listen_addrs() { let port = match config.listen_addrs() {
ListenAddress::V4(v4_addr) => v4_addr.udp_port, ListenAddress::V4(v4_addr) => v4_addr.disc_port,
ListenAddress::V6(v6_addr) => v6_addr.udp_port, ListenAddress::V6(v6_addr) => v6_addr.disc_port,
ListenAddress::DualStack(v4_addr, _v6_addr) => { ListenAddress::DualStack(v4_addr, _v6_addr) => {
// NOTE: slight preference for ipv4 that I don't think is of importance. // NOTE: slight preference for ipv4 that I don't think is of importance.
v4_addr.udp_port v4_addr.disc_port
} }
}; };
@ -1272,6 +1340,10 @@ pub fn set_network_config(
warn!(log, "Discovery is disabled. New peers will not be found"); warn!(log, "Discovery is disabled. New peers will not be found");
} }
if cli_args.is_present("disable-quic") {
config.disable_quic_support = true;
}
if cli_args.is_present("disable-upnp") { if cli_args.is_present("disable-upnp") {
config.upnp_enabled = false; config.upnp_enabled = false;
} }

View File

@ -56,3 +56,4 @@
* [Contributing](./contributing.md) * [Contributing](./contributing.md)
* [Development Environment](./setup.md) * [Development Environment](./setup.md)
* [FAQs](./faq.md) * [FAQs](./faq.md)
* [Protocol Developers](./developers.md)

51
book/src/developers.md Normal file
View File

@ -0,0 +1,51 @@
# For Protocol Developers
_Documentation for protocol developers._
This section lists Lighthouse-specific decisions that are not strictly spec'd and may be useful for
other protocol developers wishing to interact with lighthouse.
## Custom ENR Fields
Lighthouse currently uses the following ENR fields:
### Ethereum Consensus Specified
| Field | Description |
| ---- | ---- |
| `eth2` | The `ENRForkId` in SSZ bytes specifying which fork the node is on |
| `attnets` | An SSZ bitfield which indicates which of the 64 subnets the node is subscribed to for an extended period of time |
| `syncnets` | An SSZ bitfield which indicates which of the sync committee subnets the node is subscribed to |
### Lighthouse Custom Fields
Lighthouse is currently using the following custom ENR fields.
| Field | Description |
| ---- | ---- |
| `quic` | The UDP port on which the QUIC transport is listening on IPv4 |
| `quic6` | The UDP port on which the QUIC transport is listening on IPv6 |
## Custom RPC Messages
The specification leaves room for implementation-specific errors. Lighthouse uses the following
custom RPC error messages.
### Goodbye Reason Codes
| Code | Message | Description |
| ---- | ---- | ---- |
| 128 | Unable to Verify Network | Teku uses this, so we adopted it. It relates to having a fork mismatch |
| 129 | Too Many Peers | Lighthouse can close a connection because it has reached its peer-limit and pruned excess peers |
| 250 | Bad Score | The node has been dropped due to having a bad peer score |
| 251 | Banned | The peer has been banned and disconnected |
| 252 | Banned IP | The IP the node is connected to us with has been banned |
### Error Codes
| Code | Message | Description |
| ---- | ---- | ---- |
| 139 | Rate Limited | The peer has been rate limited so we return this error as a response |

View File

@ -58,12 +58,12 @@ impl<T: EthSpec> BootNodeConfig<T> {
set_network_config(&mut network_config, matches, &data_dir, &logger)?; set_network_config(&mut network_config, matches, &data_dir, &logger)?;
// Set the Enr UDP ports to the listening ports if not present. // Set the Enr Discovery ports to the listening ports if not present.
if let Some(listening_addr_v4) = network_config.listen_addrs().v4() { if let Some(listening_addr_v4) = network_config.listen_addrs().v4() {
network_config.enr_udp4_port = Some( network_config.enr_udp4_port = Some(
network_config network_config
.enr_udp4_port .enr_udp4_port
.unwrap_or(listening_addr_v4.udp_port), .unwrap_or(listening_addr_v4.disc_port),
) )
}; };
@ -71,7 +71,7 @@ impl<T: EthSpec> BootNodeConfig<T> {
network_config.enr_udp6_port = Some( network_config.enr_udp6_port = Some(
network_config network_config
.enr_udp6_port .enr_udp6_port
.unwrap_or(listening_addr_v6.udp_port), .unwrap_or(listening_addr_v6.disc_port),
) )
}; };

View File

@ -1010,12 +1010,12 @@ fn network_port_flag_over_ipv4() {
.run() .run()
.with_config(|config| { .with_config(|config| {
assert_eq!( assert_eq!(
config config.network.listen_addrs().v4().map(|listen_addr| (
.network listen_addr.disc_port,
.listen_addrs() listen_addr.quic_port,
.v4() listen_addr.tcp_port
.map(|listen_addr| (listen_addr.udp_port, listen_addr.tcp_port)), )),
Some((port, port)) Some((port, port + 1, port))
); );
}); });
} }
@ -1028,22 +1028,22 @@ fn network_port_flag_over_ipv6() {
.run() .run()
.with_config(|config| { .with_config(|config| {
assert_eq!( assert_eq!(
config config.network.listen_addrs().v6().map(|listen_addr| (
.network listen_addr.disc_port,
.listen_addrs() listen_addr.quic_port,
.v6() listen_addr.tcp_port
.map(|listen_addr| (listen_addr.udp_port, listen_addr.tcp_port)), )),
Some((port, port)) Some((port, port + 1, port))
); );
}); });
} }
#[test] #[test]
fn network_port_and_discovery_port_flags_over_ipv4() { fn network_port_and_discovery_port_flags_over_ipv4() {
let tcp4_port = unused_tcp4_port().expect("Unable to find unused port."); let tcp4_port = unused_tcp4_port().expect("Unable to find unused port.");
let udp4_port = unused_udp4_port().expect("Unable to find unused port."); let disc4_port = unused_udp4_port().expect("Unable to find unused port.");
CommandLineTest::new() CommandLineTest::new()
.flag("port", Some(tcp4_port.to_string().as_str())) .flag("port", Some(tcp4_port.to_string().as_str()))
.flag("discovery-port", Some(udp4_port.to_string().as_str())) .flag("discovery-port", Some(disc4_port.to_string().as_str()))
.run() .run()
.with_config(|config| { .with_config(|config| {
assert_eq!( assert_eq!(
@ -1051,19 +1051,19 @@ fn network_port_and_discovery_port_flags_over_ipv4() {
.network .network
.listen_addrs() .listen_addrs()
.v4() .v4()
.map(|listen_addr| (listen_addr.tcp_port, listen_addr.udp_port)), .map(|listen_addr| (listen_addr.tcp_port, listen_addr.disc_port)),
Some((tcp4_port, udp4_port)) Some((tcp4_port, disc4_port))
); );
}); });
} }
#[test] #[test]
fn network_port_and_discovery_port_flags_over_ipv6() { fn network_port_and_discovery_port_flags_over_ipv6() {
let tcp6_port = unused_tcp6_port().expect("Unable to find unused port."); let tcp6_port = unused_tcp6_port().expect("Unable to find unused port.");
let udp6_port = unused_udp6_port().expect("Unable to find unused port."); let disc6_port = unused_udp6_port().expect("Unable to find unused port.");
CommandLineTest::new() CommandLineTest::new()
.flag("listen-address", Some("::1")) .flag("listen-address", Some("::1"))
.flag("port", Some(tcp6_port.to_string().as_str())) .flag("port", Some(tcp6_port.to_string().as_str()))
.flag("discovery-port", Some(udp6_port.to_string().as_str())) .flag("discovery-port", Some(disc6_port.to_string().as_str()))
.run() .run()
.with_config(|config| { .with_config(|config| {
assert_eq!( assert_eq!(
@ -1071,24 +1071,24 @@ fn network_port_and_discovery_port_flags_over_ipv6() {
.network .network
.listen_addrs() .listen_addrs()
.v6() .v6()
.map(|listen_addr| (listen_addr.tcp_port, listen_addr.udp_port)), .map(|listen_addr| (listen_addr.tcp_port, listen_addr.disc_port)),
Some((tcp6_port, udp6_port)) Some((tcp6_port, disc6_port))
); );
}); });
} }
#[test] #[test]
fn network_port_and_discovery_port_flags_over_ipv4_and_ipv6() { fn network_port_and_discovery_port_flags_over_ipv4_and_ipv6() {
let tcp4_port = unused_tcp4_port().expect("Unable to find unused port."); let tcp4_port = unused_tcp4_port().expect("Unable to find unused port.");
let udp4_port = unused_udp4_port().expect("Unable to find unused port."); let disc4_port = unused_udp4_port().expect("Unable to find unused port.");
let tcp6_port = unused_tcp6_port().expect("Unable to find unused port."); let tcp6_port = unused_tcp6_port().expect("Unable to find unused port.");
let udp6_port = unused_udp6_port().expect("Unable to find unused port."); let disc6_port = unused_udp6_port().expect("Unable to find unused port.");
CommandLineTest::new() CommandLineTest::new()
.flag("listen-address", Some("::1")) .flag("listen-address", Some("::1"))
.flag("listen-address", Some("127.0.0.1")) .flag("listen-address", Some("127.0.0.1"))
.flag("port", Some(tcp4_port.to_string().as_str())) .flag("port", Some(tcp4_port.to_string().as_str()))
.flag("discovery-port", Some(udp4_port.to_string().as_str())) .flag("discovery-port", Some(disc4_port.to_string().as_str()))
.flag("port6", Some(tcp6_port.to_string().as_str())) .flag("port6", Some(tcp6_port.to_string().as_str()))
.flag("discovery-port6", Some(udp6_port.to_string().as_str())) .flag("discovery-port6", Some(disc6_port.to_string().as_str()))
.run() .run()
.with_config(|config| { .with_config(|config| {
assert_eq!( assert_eq!(
@ -1096,8 +1096,8 @@ fn network_port_and_discovery_port_flags_over_ipv4_and_ipv6() {
.network .network
.listen_addrs() .listen_addrs()
.v4() .v4()
.map(|listen_addr| (listen_addr.tcp_port, listen_addr.udp_port)), .map(|listen_addr| (listen_addr.tcp_port, listen_addr.disc_port)),
Some((tcp4_port, udp4_port)) Some((tcp4_port, disc4_port))
); );
assert_eq!( assert_eq!(
@ -1105,8 +1105,47 @@ fn network_port_and_discovery_port_flags_over_ipv4_and_ipv6() {
.network .network
.listen_addrs() .listen_addrs()
.v6() .v6()
.map(|listen_addr| (listen_addr.tcp_port, listen_addr.udp_port)), .map(|listen_addr| (listen_addr.tcp_port, listen_addr.disc_port)),
Some((tcp6_port, udp6_port)) Some((tcp6_port, disc6_port))
);
});
}
#[test]
fn network_port_discovery_quic_port_flags_over_ipv4_and_ipv6() {
let tcp4_port = unused_tcp4_port().expect("Unable to find unused port.");
let disc4_port = unused_udp4_port().expect("Unable to find unused port.");
let quic4_port = unused_udp4_port().expect("Unable to find unused port.");
let tcp6_port = unused_tcp6_port().expect("Unable to find unused port.");
let disc6_port = unused_udp6_port().expect("Unable to find unused port.");
let quic6_port = unused_udp6_port().expect("Unable to find unused port.");
CommandLineTest::new()
.flag("listen-address", Some("::1"))
.flag("listen-address", Some("127.0.0.1"))
.flag("port", Some(tcp4_port.to_string().as_str()))
.flag("discovery-port", Some(disc4_port.to_string().as_str()))
.flag("quic-port", Some(quic4_port.to_string().as_str()))
.flag("port6", Some(tcp6_port.to_string().as_str()))
.flag("discovery-port6", Some(disc6_port.to_string().as_str()))
.flag("quic-port6", Some(quic6_port.to_string().as_str()))
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v4().map(|listen_addr| (
listen_addr.tcp_port,
listen_addr.disc_port,
listen_addr.quic_port
)),
Some((tcp4_port, disc4_port, quic4_port))
);
assert_eq!(
config.network.listen_addrs().v6().map(|listen_addr| (
listen_addr.tcp_port,
listen_addr.disc_port,
listen_addr.quic_port
)),
Some((tcp6_port, disc6_port, quic6_port))
); );
}); });
} }
@ -1118,6 +1157,14 @@ fn disable_discovery_flag() {
.run_with_zero_port() .run_with_zero_port()
.with_config(|config| assert!(config.network.disable_discovery)); .with_config(|config| assert!(config.network.disable_discovery));
} }
#[test]
fn disable_quic_flag() {
CommandLineTest::new()
.flag("disable-quic", None)
.run_with_zero_port()
.with_config(|config| assert!(config.network.disable_quic_support));
}
#[test] #[test]
fn disable_peer_scoring_flag() { fn disable_peer_scoring_flag() {
CommandLineTest::new() CommandLineTest::new()
@ -1224,6 +1271,14 @@ fn enr_udp_port_flag() {
.with_config(|config| assert_eq!(config.network.enr_udp4_port, Some(port))); .with_config(|config| assert_eq!(config.network.enr_udp4_port, Some(port)));
} }
#[test] #[test]
fn enr_quic_port_flag() {
let port = unused_udp4_port().expect("Unable to find unused port.");
CommandLineTest::new()
.flag("enr-quic-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.network.enr_quic4_port, Some(port)));
}
#[test]
fn enr_tcp_port_flag() { fn enr_tcp_port_flag() {
let port = unused_tcp4_port().expect("Unable to find unused port."); let port = unused_tcp4_port().expect("Unable to find unused port.");
CommandLineTest::new() CommandLineTest::new()
@ -1240,6 +1295,14 @@ fn enr_udp6_port_flag() {
.with_config(|config| assert_eq!(config.network.enr_udp6_port, Some(port))); .with_config(|config| assert_eq!(config.network.enr_udp6_port, Some(port)));
} }
#[test] #[test]
fn enr_quic6_port_flag() {
let port = unused_udp6_port().expect("Unable to find unused port.");
CommandLineTest::new()
.flag("enr-quic6-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.network.enr_quic6_port, Some(port)));
}
#[test]
fn enr_tcp6_port_flag() { fn enr_tcp6_port_flag() {
let port = unused_tcp6_port().expect("Unable to find unused port."); let port = unused_tcp6_port().expect("Unable to find unused port.");
CommandLineTest::new() CommandLineTest::new()
@ -1262,7 +1325,7 @@ fn enr_match_flag_over_ipv4() {
assert_eq!( assert_eq!(
config.network.listen_addrs().v4().map(|listen_addr| ( config.network.listen_addrs().v4().map(|listen_addr| (
listen_addr.addr, listen_addr.addr,
listen_addr.udp_port, listen_addr.disc_port,
listen_addr.tcp_port listen_addr.tcp_port
)), )),
Some((addr, udp4_port, tcp4_port)) Some((addr, udp4_port, tcp4_port))
@ -1287,7 +1350,7 @@ fn enr_match_flag_over_ipv6() {
assert_eq!( assert_eq!(
config.network.listen_addrs().v6().map(|listen_addr| ( config.network.listen_addrs().v6().map(|listen_addr| (
listen_addr.addr, listen_addr.addr,
listen_addr.udp_port, listen_addr.disc_port,
listen_addr.tcp_port listen_addr.tcp_port
)), )),
Some((addr, udp6_port, tcp6_port)) Some((addr, udp6_port, tcp6_port))
@ -1319,7 +1382,7 @@ fn enr_match_flag_over_ipv4_and_ipv6() {
assert_eq!( assert_eq!(
config.network.listen_addrs().v6().map(|listen_addr| ( config.network.listen_addrs().v6().map(|listen_addr| (
listen_addr.addr, listen_addr.addr,
listen_addr.udp_port, listen_addr.disc_port,
listen_addr.tcp_port listen_addr.tcp_port
)), )),
Some((ipv6_addr, udp6_port, tcp6_port)) Some((ipv6_addr, udp6_port, tcp6_port))
@ -1327,7 +1390,7 @@ fn enr_match_flag_over_ipv4_and_ipv6() {
assert_eq!( assert_eq!(
config.network.listen_addrs().v4().map(|listen_addr| ( config.network.listen_addrs().v4().map(|listen_addr| (
listen_addr.addr, listen_addr.addr,
listen_addr.udp_port, listen_addr.disc_port,
listen_addr.tcp_port listen_addr.tcp_port
)), )),
Some((ipv4_addr, udp4_port, tcp4_port)) Some((ipv4_addr, udp4_port, tcp4_port))

View File

@ -39,10 +39,11 @@ done
# Get positional arguments # Get positional arguments
data_dir=${@:$OPTIND+0:1} data_dir=${@:$OPTIND+0:1}
network_port=${@:$OPTIND+1:1} tcp_port=${@:$OPTIND+1:1}
http_port=${@:$OPTIND+2:1} quic_port=${@:$OPTIND+2:1}
execution_endpoint=${@:$OPTIND+3:1} http_port=${@:$OPTIND+3:1}
execution_jwt=${@:$OPTIND+4:1} execution_endpoint=${@:$OPTIND+4:1}
execution_jwt=${@:$OPTIND+5:1}
lighthouse_binary=lighthouse lighthouse_binary=lighthouse
@ -56,9 +57,11 @@ exec $lighthouse_binary \
--disable-peer-scoring \ --disable-peer-scoring \
--staking \ --staking \
--enr-address 127.0.0.1 \ --enr-address 127.0.0.1 \
--enr-udp-port $network_port \ --enr-udp-port $tcp_port \
--enr-tcp-port $network_port \ --enr-tcp-port $tcp_port \
--port $network_port \ --enr-quic-port $quic_port \
--port $tcp_port \
--quic-port $quic_port \
--http-port $http_port \ --http-port $http_port \
--disable-packet-filter \ --disable-packet-filter \
--target-peers $((BN_COUNT - 1)) \ --target-peers $((BN_COUNT - 1)) \

View File

@ -139,7 +139,7 @@ sed -i 's/"shanghaiTime".*$/"shanghaiTime": 0,/g' $genesis_file
for (( bn=1; bn<=$BN_COUNT; bn++ )); do for (( bn=1; bn<=$BN_COUNT; bn++ )); do
secret=$DATADIR/geth_datadir$bn/geth/jwtsecret secret=$DATADIR/geth_datadir$bn/geth/jwtsecret
echo $secret echo $secret
execute_command_add_PID beacon_node_$bn.log ./beacon_node.sh $SAS -d $DEBUG_LEVEL $DATADIR/node_$bn $((BN_udp_tcp_base + $bn)) $((BN_http_port_base + $bn)) http://localhost:$((EL_base_auth_http + $bn)) $secret execute_command_add_PID beacon_node_$bn.log ./beacon_node.sh $SAS -d $DEBUG_LEVEL $DATADIR/node_$bn $((BN_udp_tcp_base + $bn)) $((BN_udp_tcp_base + $bn + 100)) $((BN_http_port_base + $bn)) http://localhost:$((EL_base_auth_http + $bn)) $secret
done done
# Start requested number of validator clients # Start requested number of validator clients

View File

@ -43,23 +43,23 @@ sleep 10
echo "Starting local execution nodes" echo "Starting local execution nodes"
exit_if_fails ../local_testnet/geth.sh $HOME/.lighthouse/local-testnet/geth_datadir1 7000 6000 5000 $genesis_file &> geth.log & exit_if_fails ../local_testnet/geth.sh $HOME/.lighthouse/local-testnet/geth_datadir1 6000 5000 4000 $genesis_file &> geth.log &
exit_if_fails ../local_testnet/geth.sh $HOME/.lighthouse/local-testnet/geth_datadir2 7100 6100 5100 $genesis_file &> /dev/null & exit_if_fails ../local_testnet/geth.sh $HOME/.lighthouse/local-testnet/geth_datadir2 6100 5100 4100 $genesis_file &> /dev/null &
exit_if_fails ../local_testnet/geth.sh $HOME/.lighthouse/local-testnet/geth_datadir3 7200 6200 5200 $genesis_file &> /dev/null & exit_if_fails ../local_testnet/geth.sh $HOME/.lighthouse/local-testnet/geth_datadir3 6200 5200 4200 $genesis_file &> /dev/null &
sleep 20 sleep 20
echo "Starting local beacon nodes" echo "Starting local beacon nodes"
exit_if_fails ../local_testnet/beacon_node.sh -d debug $HOME/.lighthouse/local-testnet/node_1 9000 8000 http://localhost:5000 $HOME/.lighthouse/local-testnet/geth_datadir1/geth/jwtsecret &> beacon1.log & exit_if_fails ../local_testnet/beacon_node.sh -d debug $HOME/.lighthouse/local-testnet/node_1 8000 7000 9000 http://localhost:4000 $HOME/.lighthouse/local-testnet/geth_datadir1/geth/jwtsecret &> /dev/null &
exit_if_fails ../local_testnet/beacon_node.sh $HOME/.lighthouse/local-testnet/node_2 9100 8100 http://localhost:5100 $HOME/.lighthouse/local-testnet/geth_datadir2/geth/jwtsecret &> /dev/null & exit_if_fails ../local_testnet/beacon_node.sh $HOME/.lighthouse/local-testnet/node_2 8100 7100 9100 http://localhost:4100 $HOME/.lighthouse/local-testnet/geth_datadir2/geth/jwtsecret &> /dev/null &
exit_if_fails ../local_testnet/beacon_node.sh $HOME/.lighthouse/local-testnet/node_3 9200 8200 http://localhost:5200 $HOME/.lighthouse/local-testnet/geth_datadir3/geth/jwtsecret &> /dev/null & exit_if_fails ../local_testnet/beacon_node.sh $HOME/.lighthouse/local-testnet/node_3 8200 7200 9200 http://localhost:4200 $HOME/.lighthouse/local-testnet/geth_datadir3/geth/jwtsecret &> /dev/null &
echo "Starting local validator clients" echo "Starting local validator clients"
exit_if_fails ../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_1 http://localhost:8000 &> /dev/null & exit_if_fails ../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_1 http://localhost:9000 &> /dev/null &
exit_if_fails ../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_2 http://localhost:8100 &> /dev/null & exit_if_fails ../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_2 http://localhost:9100 &> /dev/null &
exit_if_fails ../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_3 http://localhost:8200 &> /dev/null & exit_if_fails ../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_3 http://localhost:9200 &> /dev/null &
echo "Waiting an epoch before starting the next validator client" echo "Waiting an epoch before starting the next validator client"
sleep $(( $SECONDS_PER_SLOT * 32 )) sleep $(( $SECONDS_PER_SLOT * 32 ))
@ -70,7 +70,7 @@ if [[ "$BEHAVIOR" == "failure" ]]; then
# Use same keys as keys from VC1 and connect to BN2 # Use same keys as keys from VC1 and connect to BN2
# This process should not last longer than 2 epochs # This process should not last longer than 2 epochs
timeout $(( $SECONDS_PER_SLOT * 32 * 2 )) ../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_1_doppelganger http://localhost:8100 timeout $(( $SECONDS_PER_SLOT * 32 * 2 )) ../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_1_doppelganger http://localhost:9100
DOPPELGANGER_EXIT=$? DOPPELGANGER_EXIT=$?
echo "Shutting down" echo "Shutting down"
@ -96,7 +96,7 @@ if [[ "$BEHAVIOR" == "success" ]]; then
echo "Starting the last validator client" echo "Starting the last validator client"
../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_4 http://localhost:8100 & ../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_4 http://localhost:9100 &
DOPPELGANGER_FAILURE=0 DOPPELGANGER_FAILURE=0
# Sleep three epochs, then make sure all validators were active in epoch 2. Use # Sleep three epochs, then make sure all validators were active in epoch 2. Use
@ -110,7 +110,7 @@ if [[ "$BEHAVIOR" == "success" ]]; then
cd $HOME/.lighthouse/local-testnet/node_4/validators cd $HOME/.lighthouse/local-testnet/node_4/validators
for val in 0x*; do for val in 0x*; do
[[ -e $val ]] || continue [[ -e $val ]] || continue
curl -s localhost:8100/lighthouse/validator_inclusion/3/$val | jq | grep -q '"is_previous_epoch_target_attester": false' curl -s localhost:9100/lighthouse/validator_inclusion/3/$val | jq | grep -q '"is_previous_epoch_target_attester": false'
IS_ATTESTER=$? IS_ATTESTER=$?
if [[ $IS_ATTESTER -eq 0 ]]; then if [[ $IS_ATTESTER -eq 0 ]]; then
echo "$val did not attest in epoch 2." echo "$val did not attest in epoch 2."
@ -128,7 +128,7 @@ if [[ "$BEHAVIOR" == "success" ]]; then
sleep $(( $SECONDS_PER_SLOT * 32 * 2 )) sleep $(( $SECONDS_PER_SLOT * 32 * 2 ))
for val in 0x*; do for val in 0x*; do
[[ -e $val ]] || continue [[ -e $val ]] || continue
curl -s localhost:8100/lighthouse/validator_inclusion/5/$val | jq | grep -q '"is_previous_epoch_target_attester": true' curl -s localhost:9100/lighthouse/validator_inclusion/5/$val | jq | grep -q '"is_previous_epoch_target_attester": true'
IS_ATTESTER=$? IS_ATTESTER=$?
if [[ $IS_ATTESTER -eq 0 ]]; then if [[ $IS_ATTESTER -eq 0 ]]; then
echo "$val attested in epoch 4." echo "$val attested in epoch 4."

View File

@ -98,7 +98,7 @@ pub fn testing_client_config() -> ClientConfig {
// Setting ports to `0` means that the OS will choose some available port. // Setting ports to `0` means that the OS will choose some available port.
client_config client_config
.network .network
.set_ipv4_listening_address(std::net::Ipv4Addr::UNSPECIFIED, 0, 0); .set_ipv4_listening_address(std::net::Ipv4Addr::UNSPECIFIED, 0, 0, 0);
client_config.network.upnp_enabled = false; client_config.network.upnp_enabled = false;
client_config.http_api.enabled = true; client_config.http_api.enabled = true;
client_config.http_api.listen_port = 0; client_config.http_api.listen_port = 0;

View File

@ -14,6 +14,7 @@ use std::{sync::Arc, time::Duration};
use types::{Epoch, EthSpec}; use types::{Epoch, EthSpec};
const BOOTNODE_PORT: u16 = 42424; const BOOTNODE_PORT: u16 = 42424;
const QUIC_PORT: u16 = 43424;
pub const INVALID_ADDRESS: &str = "http://127.0.0.1:42423"; pub const INVALID_ADDRESS: &str = "http://127.0.0.1:42423";
pub const EXECUTION_PORT: u16 = 4000; pub const EXECUTION_PORT: u16 = 4000;
@ -63,6 +64,7 @@ impl<E: EthSpec> LocalNetwork<E> {
std::net::Ipv4Addr::UNSPECIFIED, std::net::Ipv4Addr::UNSPECIFIED,
BOOTNODE_PORT, BOOTNODE_PORT,
BOOTNODE_PORT, BOOTNODE_PORT,
QUIC_PORT,
); );
beacon_config.network.enr_udp4_port = Some(BOOTNODE_PORT); beacon_config.network.enr_udp4_port = Some(BOOTNODE_PORT);
beacon_config.network.enr_tcp4_port = Some(BOOTNODE_PORT); beacon_config.network.enr_tcp4_port = Some(BOOTNODE_PORT);
@ -154,6 +156,7 @@ impl<E: EthSpec> LocalNetwork<E> {
std::net::Ipv4Addr::UNSPECIFIED, std::net::Ipv4Addr::UNSPECIFIED,
BOOTNODE_PORT + count, BOOTNODE_PORT + count,
BOOTNODE_PORT + count, BOOTNODE_PORT + count,
QUIC_PORT + count,
); );
beacon_config.network.enr_udp4_port = Some(BOOTNODE_PORT + count); beacon_config.network.enr_udp4_port = Some(BOOTNODE_PORT + count);
beacon_config.network.enr_tcp4_port = Some(BOOTNODE_PORT + count); beacon_config.network.enr_tcp4_port = Some(BOOTNODE_PORT + count);