Update discv5 to expand ipv6 support (#4319)

Done in different PRs so that they can reviewed independently, as it's likely this won't be merged before I leave

Includes resolution for #4080 
- [ ] #4299
- [ ] #4318
- [ ] #4320 

Co-authored-by: Diva M <divma@protonmail.com>
Co-authored-by: Age Manning <Age@AgeManning.com>
This commit is contained in:
Divma 2023-06-13 01:25:05 +00:00
parent 62a2413ade
commit 2639e67e90
12 changed files with 425 additions and 170 deletions

294
Cargo.lock generated
View File

@ -566,6 +566,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
[[package]]
name = "base16ct"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
name = "base64"
version = "0.13.1"
@ -1377,6 +1383,18 @@ dependencies = [
"zeroize",
]
[[package]]
name = "crypto-bigint"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15"
dependencies = [
"generic-array",
"rand_core 0.6.4",
"subtle",
"zeroize",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
@ -1472,11 +1490,12 @@ dependencies = [
[[package]]
name = "curve25519-dalek"
version = "4.0.0-rc.1"
version = "4.0.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d4ba9852b42210c7538b75484f9daa0655e9a3ac04f693747bb0f02cf3cfe16"
checksum = "03d928d978dbec61a1167414f5ec534f24bea0d7a0d24dd9b6233d3d8223e585"
dependencies = [
"cfg-if",
"digest 0.10.7",
"fiat-crypto",
"packed_simd_2",
"platforms 3.0.2",
@ -1659,6 +1678,16 @@ dependencies = [
"zeroize",
]
[[package]]
name = "der"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56acb310e15652100da43d130af8d97b509e95af61aab1c5a7939ef24337ee17"
dependencies = [
"const-oid",
"zeroize",
]
[[package]]
name = "der-parser"
version = "7.0.0"
@ -1805,6 +1834,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer 0.10.4",
"const-oid",
"crypto-common",
"subtle",
]
@ -1861,15 +1891,15 @@ dependencies = [
[[package]]
name = "discv5"
version = "0.2.2"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b009a99b85b58900df46435307fc5c4c845af7e182582b1fbf869572fa9fce69"
checksum = "77f32d27968ba86689e3f0eccba0383414348a6fc5918b0a639c98dd81e20ed6"
dependencies = [
"aes 0.7.5",
"aes-gcm 0.9.4",
"arrayvec",
"delay_map",
"enr 0.7.0",
"enr 0.8.1",
"fnv",
"futures",
"hashlink 0.7.0",
@ -1885,8 +1915,6 @@ dependencies = [
"smallvec",
"socket2 0.4.9",
"tokio",
"tokio-stream",
"tokio-util 0.6.10",
"tracing",
"tracing-subscriber",
"uint",
@ -1922,10 +1950,24 @@ version = "0.14.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
dependencies = [
"der",
"elliptic-curve",
"rfc6979",
"signature",
"der 0.6.1",
"elliptic-curve 0.12.3",
"rfc6979 0.3.1",
"signature 1.6.4",
]
[[package]]
name = "ecdsa"
version = "0.16.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428"
dependencies = [
"der 0.7.6",
"digest 0.10.7",
"elliptic-curve 0.13.5",
"rfc6979 0.4.0",
"signature 2.1.0",
"spki 0.7.2",
]
[[package]]
@ -1934,7 +1976,17 @@ version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7"
dependencies = [
"signature",
"signature 1.6.4",
]
[[package]]
name = "ed25519"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fb04eee5d9d907f29e80ee6b0e78f7e2c82342c63e3580d8c4f69d9d5aad963"
dependencies = [
"pkcs8 0.10.2",
"signature 2.1.0",
]
[[package]]
@ -1944,13 +1996,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
dependencies = [
"curve25519-dalek 3.2.0",
"ed25519",
"ed25519 1.5.3",
"rand 0.7.3",
"serde",
"sha2 0.9.9",
"zeroize",
]
[[package]]
name = "ed25519-dalek"
version = "2.0.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "798f704d128510932661a3489b08e3f4c934a01d61c5def59ae7b8e48f19665a"
dependencies = [
"curve25519-dalek 4.0.0-rc.2",
"ed25519 2.2.1",
"rand_core 0.6.4",
"serde",
"sha2 0.10.6",
"zeroize",
]
[[package]]
name = "ef_tests"
version = "0.2.0"
@ -1994,18 +2060,37 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
dependencies = [
"base16ct",
"crypto-bigint",
"der",
"base16ct 0.1.1",
"crypto-bigint 0.4.9",
"der 0.6.1",
"digest 0.10.7",
"ff",
"ff 0.12.1",
"generic-array",
"group",
"group 0.12.1",
"hkdf",
"pem-rfc7468",
"pkcs8",
"pkcs8 0.9.0",
"rand_core 0.6.4",
"sec1",
"sec1 0.3.0",
"subtle",
"zeroize",
]
[[package]]
name = "elliptic-curve"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b"
dependencies = [
"base16ct 0.2.0",
"crypto-bigint 0.5.2",
"digest 0.10.7",
"ff 0.13.0",
"generic-array",
"group 0.13.0",
"pkcs8 0.10.2",
"rand_core 0.6.4",
"sec1 0.7.2",
"subtle",
"zeroize",
]
@ -2029,7 +2114,7 @@ dependencies = [
"bs58",
"bytes",
"hex",
"k256",
"k256 0.11.6",
"log",
"rand 0.8.5",
"rlp",
@ -2040,16 +2125,15 @@ dependencies = [
[[package]]
name = "enr"
version = "0.7.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "492a7e5fc2504d5fdce8e124d3e263b244a68b283cac67a69eda0cd43e0aebad"
checksum = "cf56acd72bb22d2824e66ae8e9e5ada4d0de17a69c7fd35569dde2ada8ec9116"
dependencies = [
"base64 0.13.1",
"bs58",
"bytes",
"ed25519-dalek",
"ed25519-dalek 2.0.0-rc.2",
"hex",
"k256",
"k256 0.13.1",
"log",
"rand 0.8.5",
"rlp",
@ -2545,11 +2629,11 @@ dependencies = [
"bytes",
"cargo_metadata",
"chrono",
"elliptic-curve",
"elliptic-curve 0.12.3",
"ethabi 18.0.0",
"generic-array",
"hex",
"k256",
"k256 0.11.6",
"once_cell",
"open-fastrlp",
"rand 0.8.5",
@ -2731,6 +2815,16 @@ dependencies = [
"subtle",
]
[[package]]
name = "ff"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
dependencies = [
"rand_core 0.6.4",
"subtle",
]
[[package]]
name = "ffi-opaque"
version = "2.0.1"
@ -3009,6 +3103,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
"zeroize",
]
[[package]]
@ -3118,7 +3213,18 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
dependencies = [
"ff",
"ff 0.12.1",
"rand_core 0.6.4",
"subtle",
]
[[package]]
name = "group"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
dependencies = [
"ff 0.13.0",
"rand_core 0.6.4",
"subtle",
]
@ -3855,12 +3961,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b"
dependencies = [
"cfg-if",
"ecdsa",
"elliptic-curve",
"ecdsa 0.14.8",
"elliptic-curve 0.12.3",
"sha2 0.10.6",
"sha3 0.10.8",
]
[[package]]
name = "k256"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc"
dependencies = [
"cfg-if",
"ecdsa 0.16.7",
"elliptic-curve 0.13.5",
"once_cell",
"sha2 0.10.6",
"signature 2.1.0",
]
[[package]]
name = "keccak"
version = "0.1.4"
@ -4059,7 +4179,7 @@ checksum = "b1fff5bd889c82a0aec668f2045edd066f559d4e5c40354e5a4c77ac00caac38"
dependencies = [
"asn1_der",
"bs58",
"ed25519-dalek",
"ed25519-dalek 1.0.1",
"either",
"fnv",
"futures",
@ -4094,7 +4214,7 @@ checksum = "b6a8fcd392ff67af6cc3f03b1426c41f7f26b6b9aff2dc632c1c56dd649e571f"
dependencies = [
"asn1_der",
"bs58",
"ed25519-dalek",
"ed25519-dalek 1.0.1",
"either",
"fnv",
"futures",
@ -4113,7 +4233,7 @@ dependencies = [
"prost-build",
"rand 0.8.5",
"rw-stream-sink",
"sec1",
"sec1 0.3.0",
"sha2 0.10.6",
"smallvec",
"thiserror",
@ -4222,7 +4342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e2d584751cecb2aabaa56106be6be91338a60a0f4e420cf2af639204f596fc1"
dependencies = [
"bs58",
"ed25519-dalek",
"ed25519-dalek 1.0.1",
"log",
"multiaddr 0.17.1",
"multihash 0.17.0",
@ -5654,8 +5774,8 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594"
dependencies = [
"ecdsa",
"elliptic-curve",
"ecdsa 0.14.8",
"elliptic-curve 0.12.3",
"sha2 0.10.6",
]
@ -5665,8 +5785,8 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa"
dependencies = [
"ecdsa",
"elliptic-curve",
"ecdsa 0.14.8",
"elliptic-curve 0.12.3",
"sha2 0.10.6",
]
@ -5922,8 +6042,18 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
dependencies = [
"der",
"spki",
"der 0.6.1",
"spki 0.6.0",
]
[[package]]
name = "pkcs8"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
"der 0.7.6",
"spki 0.7.2",
]
[[package]]
@ -6666,11 +6796,21 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
dependencies = [
"crypto-bigint",
"crypto-bigint 0.4.9",
"hmac 0.12.1",
"zeroize",
]
[[package]]
name = "rfc6979"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
dependencies = [
"hmac 0.12.1",
"subtle",
]
[[package]]
name = "ring"
version = "0.16.20"
@ -7047,10 +7187,24 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
dependencies = [
"base16ct",
"der",
"base16ct 0.1.1",
"der 0.6.1",
"generic-array",
"pkcs8",
"pkcs8 0.9.0",
"subtle",
"zeroize",
]
[[package]]
name = "sec1"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e"
dependencies = [
"base16ct 0.2.0",
"der 0.7.6",
"generic-array",
"pkcs8 0.10.2",
"subtle",
"zeroize",
]
@ -7339,6 +7493,16 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "signature"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
dependencies = [
"digest 0.10.7",
"rand_core 0.6.4",
]
[[package]]
name = "simple_asn1"
version = "0.6.2"
@ -7576,14 +7740,14 @@ checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831"
[[package]]
name = "snow"
version = "0.9.2"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ccba027ba85743e09d15c03296797cad56395089b832b48b5a5217880f57733"
checksum = "774d05a3edae07ce6d68ea6984f3c05e9bba8927e3dd591e3b479e5b03213d0d"
dependencies = [
"aes-gcm 0.9.4",
"blake2",
"chacha20poly1305",
"curve25519-dalek 4.0.0-rc.1",
"curve25519-dalek 4.0.0-rc.2",
"rand_core 0.6.4",
"ring",
"rustc_version 0.4.0",
@ -7640,7 +7804,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
dependencies = [
"base64ct",
"der",
"der 0.6.1",
]
[[package]]
name = "spki"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a"
dependencies = [
"base64ct",
"der 0.7.6",
]
[[package]]
@ -9358,9 +9532,9 @@ dependencies = [
[[package]]
name = "webrtc-dtls"
version = "0.7.1"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "942be5bd85f072c3128396f6e5a9bfb93ca8c1939ded735d177b7bcba9a13d05"
checksum = "c4a00f4242f2db33307347bd5be53263c52a0331c96c14292118c9a6bb48d267"
dependencies = [
"aes 0.6.0",
"aes-gcm 0.10.2",
@ -9371,29 +9545,28 @@ dependencies = [
"ccm",
"curve25519-dalek 3.2.0",
"der-parser 8.2.0",
"elliptic-curve",
"elliptic-curve 0.12.3",
"hkdf",
"hmac 0.12.1",
"log",
"oid-registry 0.6.1",
"p256",
"p384",
"rand 0.8.5",
"rand_core 0.6.4",
"rcgen 0.9.3",
"rcgen 0.10.0",
"ring",
"rustls 0.19.1",
"sec1",
"sec1 0.3.0",
"serde",
"sha1",
"sha2 0.10.6",
"signature",
"signature 1.6.4",
"subtle",
"thiserror",
"tokio",
"webpki 0.21.4",
"webrtc-util",
"x25519-dalek 2.0.0-pre.1",
"x25519-dalek 2.0.0-rc.2",
"x509-parser 0.13.2",
]
@ -9836,12 +10009,13 @@ dependencies = [
[[package]]
name = "x25519-dalek"
version = "2.0.0-pre.1"
version = "2.0.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5da623d8af10a62342bcbbb230e33e58a63255a58012f8653c578e54bab48df"
checksum = "fabd6e16dd08033932fc3265ad4510cc2eab24656058a6dcb107ffe274abcc95"
dependencies = [
"curve25519-dalek 3.2.0",
"curve25519-dalek 4.0.0-rc.2",
"rand_core 0.6.4",
"serde",
"zeroize",
]

View File

@ -5,7 +5,7 @@ authors = ["Sigma Prime <contact@sigmaprime.io>"]
edition = "2021"
[dependencies]
discv5 = { version = "0.2.2", features = ["libp2p"] }
discv5 = { version = "0.3.0", features = ["libp2p"]}
unsigned-varint = { version = "0.6.0", features = ["codec"] }
types = { path = "../../consensus/types" }
ssz_types = "0.5.0"

View File

@ -163,7 +163,7 @@ impl Config {
udp_port,
tcp_port,
});
self.discv5_config.ip_mode = discv5::IpMode::Ip4;
self.discv5_config.listen_config = discv5::ListenConfig::from_ip(addr.into(), udp_port);
self.discv5_config.table_filter = |enr| enr.ip4().as_ref().map_or(false, is_global_ipv4)
}
@ -176,9 +176,8 @@ impl Config {
udp_port,
tcp_port,
});
self.discv5_config.ip_mode = discv5::IpMode::Ip6 {
enable_mapped_addresses: false,
};
self.discv5_config.listen_config = discv5::ListenConfig::from_ip(addr.into(), udp_port);
self.discv5_config.table_filter = |enr| enr.ip6().as_ref().map_or(false, is_global_ipv6)
}
@ -206,10 +205,10 @@ impl Config {
tcp_port: tcp6_port,
},
);
self.discv5_config.listen_config = discv5::ListenConfig::default()
.with_ipv4(v4_addr, udp4_port)
.with_ipv6(v6_addr, udp6_port);
self.discv5_config.ip_mode = discv5::IpMode::Ip6 {
enable_mapped_addresses: true,
};
self.discv5_config.table_filter = |enr| match (&enr.ip4(), &enr.ip6()) {
(None, None) => false,
(None, Some(ip6)) => is_global_ipv6(ip6),
@ -279,9 +278,17 @@ impl Default for Config {
.build()
.expect("The total rate limit has been specified"),
);
let listen_addresses = ListenAddress::V4(ListenAddr {
addr: Ipv4Addr::UNSPECIFIED,
udp_port: 9000,
tcp_port: 9000,
});
let discv5_listen_config =
discv5::ListenConfig::from_ip(Ipv4Addr::UNSPECIFIED.into(), 9000);
// discv5 configuration
let discv5_config = Discv5ConfigBuilder::new()
let discv5_config = Discv5ConfigBuilder::new(discv5_listen_config)
.enable_packet_filter()
.session_cache_capacity(5000)
.request_timeout(Duration::from_secs(1))
@ -304,12 +311,9 @@ impl Default for Config {
// NOTE: Some of these get overridden by the corresponding CLI default values.
Config {
network_dir,
listen_addresses: ListenAddress::V4(ListenAddr {
addr: Ipv4Addr::UNSPECIFIED,
udp_port: 9000,
tcp_port: 9000,
}),
listen_addresses,
enr_address: (None, None),
enr_udp4_port: None,
enr_tcp4_port: None,
enr_udp6_port: None,

View File

@ -198,7 +198,7 @@ impl CombinedKeyPublicExt for CombinedPublicKey {
fn as_peer_id(&self) -> PeerId {
match self {
Self::Secp256k1(pk) => {
let pk_bytes = pk.to_bytes();
let pk_bytes = pk.to_sec1_bytes();
let libp2p_pk = libp2p::core::PublicKey::Secp256k1(
libp2p::core::identity::secp256k1::PublicKey::decode(&pk_bytes)
.expect("valid public key"),
@ -222,14 +222,16 @@ impl CombinedKeyExt for CombinedKey {
match key {
Keypair::Secp256k1(key) => {
let secret =
discv5::enr::k256::ecdsa::SigningKey::from_bytes(&key.secret().to_bytes())
discv5::enr::k256::ecdsa::SigningKey::from_slice(&key.secret().to_bytes())
.expect("libp2p key must be valid");
Ok(CombinedKey::Secp256k1(secret))
}
Keypair::Ed25519(key) => {
let ed_keypair =
discv5::enr::ed25519_dalek::SecretKey::from_bytes(&key.encode()[..32])
.expect("libp2p key must be valid");
let ed_keypair = discv5::enr::ed25519_dalek::SigningKey::from_bytes(
&(key.encode()[..32])
.try_into()
.expect("libp2p key must be valid"),
);
Ok(CombinedKey::from(ed_keypair))
}
Keypair::Ecdsa(_) => Err("Ecdsa keypairs not supported"),
@ -281,7 +283,7 @@ mod tests {
fn test_secp256k1_peer_id_conversion() {
let sk_hex = "df94a73d528434ce2309abb19c16aedb535322797dbd59c157b1e04095900f48";
let sk_bytes = hex::decode(sk_hex).unwrap();
let secret_key = discv5::enr::k256::ecdsa::SigningKey::from_bytes(&sk_bytes).unwrap();
let secret_key = discv5::enr::k256::ecdsa::SigningKey::from_slice(&sk_bytes).unwrap();
let libp2p_sk = libp2p::identity::secp256k1::SecretKey::from_bytes(sk_bytes).unwrap();
let secp256k1_kp: libp2p::identity::secp256k1::Keypair = libp2p_sk.into();
@ -300,16 +302,18 @@ mod tests {
fn test_ed25519_peer_conversion() {
let sk_hex = "4dea8a5072119927e9d243a7d953f2f4bc95b70f110978e2f9bc7a9000e4b261";
let sk_bytes = hex::decode(sk_hex).unwrap();
let secret = discv5::enr::ed25519_dalek::SecretKey::from_bytes(&sk_bytes).unwrap();
let public = discv5::enr::ed25519_dalek::PublicKey::from(&secret);
let keypair = discv5::enr::ed25519_dalek::Keypair { secret, public };
let secret_key = discv5::enr::ed25519_dalek::SigningKey::from_bytes(
&sk_bytes.clone().try_into().unwrap(),
);
let libp2p_sk = libp2p::identity::ed25519::SecretKey::from_bytes(sk_bytes).unwrap();
let ed25519_kp: libp2p::identity::ed25519::Keypair = libp2p_sk.into();
let libp2p_kp = Keypair::Ed25519(ed25519_kp);
let secp256k1_kp: libp2p::identity::ed25519::Keypair = libp2p_sk.into();
let libp2p_kp = Keypair::Ed25519(secp256k1_kp);
let peer_id = libp2p_kp.public().to_peer_id();
let enr = discv5::enr::EnrBuilder::new("v4").build(&keypair).unwrap();
let enr = discv5::enr::EnrBuilder::new("v4")
.build(&secret_key)
.unwrap();
let node_id = peer_id_to_node_id(&peer_id).unwrap();
assert_eq!(enr.node_id(), node_id);

View File

@ -209,13 +209,6 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
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()
);
let listen_socket = match config.listen_addrs() {
crate::listen_addr::ListenAddress::V4(v4_addr) => v4_addr.udp_socket_addr(),
crate::listen_addr::ListenAddress::V6(v6_addr) => v6_addr.udp_socket_addr(),
crate::listen_addr::ListenAddress::DualStack(_v4_addr, v6_addr) => {
v6_addr.udp_socket_addr()
}
};
// convert the keypair into an ENR key
let enr_key: CombinedKey = CombinedKey::from_libp2p(local_key)?;
@ -251,10 +244,7 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
// Start the discv5 service and obtain an event stream
let event_stream = if !config.disable_discovery {
discv5
.start(listen_socket)
.map_err(|e| e.to_string())
.await?;
discv5.start().map_err(|e| e.to_string()).await?;
debug!(log, "Discovery service started");
EventStream::Awaiting(Box::pin(discv5.event_stream()))
} else {
@ -413,7 +403,7 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
/// If the external address needs to be modified, use `update_enr_udp_socket.
pub fn update_enr_tcp_port(&mut self, port: u16) -> Result<(), String> {
self.discv5
.enr_insert("tcp", &port.to_be_bytes())
.enr_insert("tcp", &port)
.map_err(|e| format!("{:?}", e))?;
// replace the global version
@ -428,29 +418,12 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
/// This is with caution. Discovery should automatically maintain this. This should only be
/// used when automatic discovery is disabled.
pub fn update_enr_udp_socket(&mut self, socket_addr: SocketAddr) -> Result<(), String> {
match socket_addr {
SocketAddr::V4(socket) => {
self.discv5
.enr_insert("ip", &socket.ip().octets())
.map_err(|e| format!("{:?}", e))?;
self.discv5
.enr_insert("udp", &socket.port().to_be_bytes())
.map_err(|e| format!("{:?}", e))?;
}
SocketAddr::V6(socket) => {
self.discv5
.enr_insert("ip6", &socket.ip().octets())
.map_err(|e| format!("{:?}", e))?;
self.discv5
.enr_insert("udp6", &socket.port().to_be_bytes())
.map_err(|e| format!("{:?}", e))?;
}
}
// replace the global version
*self.network_globals.local_enr.write() = self.discv5.local_enr();
const IS_TCP: bool = false;
if self.discv5.update_local_enr_socket(socket_addr, IS_TCP) {
// persist modified enr to disk
enr::save_enr_to_disk(Path::new(&self.enr_dir), &self.local_enr(), &self.log);
}
*self.network_globals.local_enr.write() = self.discv5.local_enr();
Ok(())
}

View File

@ -116,7 +116,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.value_name("PORT")
.help("The UDP port that discovery will listen on over IpV6 if listening over \
both Ipv4 and IpV6. Defaults to `port6`")
.hidden(true) // TODO: implement dual stack via two sockets in discv5.
.takes_value(true),
)
.arg(
@ -198,7 +197,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
discovery. Set this only if you are sure other nodes can connect to your \
local node on this address. This will update the `ip4` or `ip6` ENR fields \
accordingly. To update both, set this flag twice with the different values.")
.requires("enr-udp-port")
.multiple(true)
.max_values(2)
.takes_value(true),

View File

@ -38,7 +38,6 @@ large peer count will not speed up sync.
For these reasons, we recommend users do not modify the `--target-peers` count
drastically and use the (recommended) default.
### NAT Traversal (Port Forwarding)
Lighthouse, by default, uses port 9000 for both TCP and UDP. Lighthouse will
@ -107,3 +106,78 @@ Modifying the ENR settings can degrade the discovery of your node, making it
harder for peers to find you or potentially making it harder for other peers to
find each other. We recommend not touching these settings unless for a more
advanced use case.
### IPv6 support
As noted in the previous sections, two fundamental parts to ensure good
connectivity are: The parameters that configure the sockets over which
Lighthouse listens for connections, and the parameters used to tell other peers
how to connect to your node. This distinction is relevant and applies to most
nodes that do not run directly on a public network.
#### Configuring Lighthouse to listen over IPv4/IPv6/Dual stack
To listen over only IPv6 use the same parameters as done when listening over
IPv4 only:
- `--listen-addresses :: --port 9909` will listen over IPv6 using port `9909` for
TCP and UDP.
- `--listen-addresses :: --port 9909 --discovery-port 9999` will listen over
IPv6 using port `9909` for TCP and port `9999` for UDP.
To listen over both IPv4 and IPv6:
- Set two listening addresses using the `--listen-addresses` flag twice ensuring
the two addresses are one IPv4, and the other IPv6. When doing so, the
`--port` and `--discovery-port` flags will apply exclusively to IPv4. Note
that this behaviour differs from the Ipv6 only case described above.
- If necessary, set the `--port6` flag to configure the port used for TCP and
UDP over IPv6. This flag has no effect when listening over IPv6 only.
- If necessary, set the `--discovery-port6` flag to configure the IPv6 UDP
port. This will default to the value given to `--port6` if not set. This flag
has no effect when listening over IPv6 only.
##### Configuration Examples
- `--listen-addresses :: --listen-addresses 0.0.0.0 --port 9909` will listen
over IPv4 using port `9909` for TCP and UDP. It will also listen over IPv6 but
using the default value for `--port6` for UDP and TCP (`9090`).
- `--listen-addresses :: --listen-addresses --port 9909 --discovery-port6 9999`
will have the same configuration as before except for the IPv6 UDP socket,
which will use port `9999`.
#### Configuring Lighthouse to advertise IPv6 reachable addresses
Lighthouse supports IPv6 to connect to other nodes both over IPv6 exclusively,
and dual stack using one socket for IPv6 and another socket for IPv6. In both
scenarios, the previous sections still apply. In summary:
> Beacon nodes must advertise their publicly reachable socket address
In order to do so, lighthouse provides the following CLI options/parameters.
- `--enr-udp-port` Use this to advertise the port that is publicly reachable
over UDP with a publicly reachable IPv4 address. This might differ from the
IPv4 port used to listen.
- `--enr-udp6-port` Use this to advertise the port that is publicly reachable
over UDP with a publicly reachable IPv6 address. This might differ from the
IPv6 port used to listen.
- `--enr-tcp-port` Use this to advertise the port that is publicly reachable
over TCP with a publicly reachable IPv4 address. This might differ from the
IPv4 port used to listen.
- `--enr-tcp6-port` Use this to advertise the port that is publicly reachable
over TCP with a publicly reachable IPv6 address. This might differ from the
IPv6 port used to listen.
- `--enr-addresses` Use this to advertise publicly reachable addresses. Takes at
most two values, one for IPv4 and one for IPv6. Note that a beacon node that
advertises some address, must be
reachable both over UDP and TCP.
In the general case, an user will not require to set these explicitly. Update
these options only if you can guarantee your node is reachable with these
values.
#### Known caveats
IPv6 link local addresses are likely to have poor connectivity if used in
topologies with more than one interface. Use global addresses for the general
case.

View File

@ -13,13 +13,19 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.settings(&[clap::AppSettings::ColoredHelp])
.arg(
Arg::with_name("enr-address")
.value_name("IP-ADDRESS")
.help("The external IP address/ DNS address to broadcast to other peers on how to reach this node. \
If a DNS address is provided, the enr-address is set to the IP address it resolves to and \
does not auto-update based on PONG responses in discovery.")
.long("enr-address")
.value_name("ADDRESS")
.help("The IP address/ DNS address to broadcast to other peers on how to reach \
this node. If a DNS address is provided, the enr-address is set to the IP \
address it resolves to and does not auto-update based on PONG responses in \
discovery. Set this only if you are sure other nodes can connect to your \
local node on this address. This will update the `ip4` or `ip6` ENR fields \
accordingly. To update both, set this flag twice with the different values.")
.multiple(true)
.max_values(2)
.required(true)
.takes_value(true)
.conflicts_with("network-dir")
.takes_value(true),
)
.arg(
Arg::with_name("port")
@ -29,11 +35,29 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.default_value("9000")
.takes_value(true)
)
.arg(
Arg::with_name("port6")
.long("port6")
.value_name("PORT")
.help("The UDP port to listen on over IpV6 when listening over both Ipv4 and \
Ipv6. Defaults to 9090 when required.")
.default_value("9090")
.takes_value(true),
)
.arg(
Arg::with_name("listen-address")
.long("listen-address")
.value_name("ADDRESS")
.help("The address the bootnode will listen for UDP connections.")
.help("The address the bootnode will listen for UDP communications. To listen \
over IpV4 and IpV6 set this flag twice with the different values.\n\
Examples:\n\
- --listen-address '0.0.0.0' will listen over Ipv4.\n\
- --listen-address '::' will listen over Ipv6.\n\
- --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, \
multiple Ipv4, or multiple Ipv6 addresses will not be accepted.")
.multiple(true)
.max_values(2)
.default_value("0.0.0.0")
.takes_value(true)
)
@ -59,6 +83,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.value_name("PORT")
.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.")
.conflicts_with("network-dir")
.takes_value(true),
)
.arg(

View File

@ -2,7 +2,6 @@ use beacon_node::{get_data_dir, set_network_config};
use clap::ArgMatches;
use eth2_network_config::Eth2NetworkConfig;
use lighthouse_network::discovery::create_enr_builder_from_config;
use lighthouse_network::discv5::IpMode;
use lighthouse_network::discv5::{enr::CombinedKey, Discv5Config, Enr};
use lighthouse_network::{
discovery::{load_enr_from_disk, use_or_load_enr},
@ -10,13 +9,12 @@ use lighthouse_network::{
};
use serde_derive::{Deserialize, Serialize};
use ssz::Encode;
use std::net::SocketAddr;
use std::net::{SocketAddrV4, SocketAddrV6};
use std::{marker::PhantomData, path::PathBuf};
use types::EthSpec;
/// A set of configuration parameters for the bootnode, established from CLI arguments.
pub struct BootNodeConfig<T: EthSpec> {
pub listen_socket: SocketAddr,
// TODO: Generalise to multiaddr
pub boot_nodes: Vec<Enr>,
pub local_enr: Enr,
@ -81,31 +79,6 @@ impl<T: EthSpec> BootNodeConfig<T> {
network_config.discv5_config.enr_update = false;
}
// the address to listen on
let listen_socket = match network_config.listen_addrs().clone() {
lighthouse_network::ListenAddress::V4(v4_addr) => {
// Set explicitly as ipv4 otherwise
network_config.discv5_config.ip_mode = IpMode::Ip4;
v4_addr.udp_socket_addr()
}
lighthouse_network::ListenAddress::V6(v6_addr) => {
// create ipv6 sockets and enable ipv4 mapped addresses.
network_config.discv5_config.ip_mode = IpMode::Ip6 {
enable_mapped_addresses: false,
};
v6_addr.udp_socket_addr()
}
lighthouse_network::ListenAddress::DualStack(_v4_addr, v6_addr) => {
// create ipv6 sockets and enable ipv4 mapped addresses.
network_config.discv5_config.ip_mode = IpMode::Ip6 {
enable_mapped_addresses: true,
};
v6_addr.udp_socket_addr()
}
};
let private_key = load_private_key(&network_config, &logger);
let local_key = CombinedKey::from_libp2p(&private_key)?;
@ -143,7 +116,7 @@ impl<T: EthSpec> BootNodeConfig<T> {
let mut builder = create_enr_builder_from_config(&network_config, enable_tcp);
// If we know of the ENR field, add it to the initial construction
if let Some(enr_fork_bytes) = enr_fork {
builder.add_value("eth2", enr_fork_bytes.as_slice());
builder.add_value("eth2", &enr_fork_bytes);
}
builder
.build(&local_key)
@ -155,7 +128,6 @@ impl<T: EthSpec> BootNodeConfig<T> {
};
Ok(BootNodeConfig {
listen_socket,
boot_nodes,
local_enr,
local_key,
@ -170,7 +142,8 @@ impl<T: EthSpec> BootNodeConfig<T> {
/// Its fields are a subset of the fields of `BootNodeConfig`, some of them are copied from `Discv5Config`.
#[derive(Serialize, Deserialize)]
pub struct BootNodeConfigSerialization {
pub listen_socket: SocketAddr,
pub ipv4_listen_socket: Option<SocketAddrV4>,
pub ipv6_listen_socket: Option<SocketAddrV6>,
// TODO: Generalise to multiaddr
pub boot_nodes: Vec<Enr>,
pub local_enr: Enr,
@ -183,7 +156,6 @@ impl BootNodeConfigSerialization {
/// relevant fields of `config`
pub fn from_config_ref<T: EthSpec>(config: &BootNodeConfig<T>) -> Self {
let BootNodeConfig {
listen_socket,
boot_nodes,
local_enr,
local_key: _,
@ -191,8 +163,27 @@ impl BootNodeConfigSerialization {
phantom: _,
} = config;
let (ipv4_listen_socket, ipv6_listen_socket) = match discv5_config.listen_config {
lighthouse_network::discv5::ListenConfig::Ipv4 { ip, port } => {
(Some(SocketAddrV4::new(ip, port)), None)
}
lighthouse_network::discv5::ListenConfig::Ipv6 { ip, port } => {
(None, Some(SocketAddrV6::new(ip, port, 0, 0)))
}
lighthouse_network::discv5::ListenConfig::DualStack {
ipv4,
ipv4_port,
ipv6,
ipv6_port,
} => (
Some(SocketAddrV4::new(ipv4, ipv4_port)),
Some(SocketAddrV6::new(ipv6, ipv6_port, 0, 0)),
),
};
BootNodeConfigSerialization {
listen_socket: *listen_socket,
ipv4_listen_socket,
ipv6_listen_socket,
boot_nodes: boot_nodes.clone(),
local_enr: local_enr.clone(),
disable_packet_filter: !discv5_config.enable_packet_filter,

View File

@ -10,7 +10,6 @@ use types::EthSpec;
pub async fn run<T: EthSpec>(config: BootNodeConfig<T>, log: slog::Logger) {
let BootNodeConfig {
listen_socket,
boot_nodes,
local_enr,
local_key,
@ -31,7 +30,7 @@ pub async fn run<T: EthSpec>(config: BootNodeConfig<T>, log: slog::Logger) {
let pretty_v6_socket = enr_v6_socket.as_ref().map(|addr| addr.to_string());
info!(
log, "Configuration parameters";
"listening_address" => %listen_socket,
"listening_address" => ?discv5_config.listen_config,
"advertised_v4_address" => ?pretty_v4_socket,
"advertised_v6_address" => ?pretty_v6_socket,
"eth2" => eth2_field
@ -41,6 +40,7 @@ pub async fn run<T: EthSpec>(config: BootNodeConfig<T>, log: slog::Logger) {
// build the contactable multiaddr list, adding the p2p protocol
info!(log, "Contact information"; "enr" => local_enr.to_base64());
info!(log, "Enr details"; "enr" => ?local_enr);
info!(log, "Contact information"; "multiaddrs" => ?local_enr.multiaddr_p2p());
// construct the discv5 server
@ -64,7 +64,7 @@ pub async fn run<T: EthSpec>(config: BootNodeConfig<T>, log: slog::Logger) {
}
// start the server
if let Err(e) = discv5.start(listen_socket).await {
if let Err(e) = discv5.start().await {
slog::crit!(log, "Could not start discv5 server"; "error" => %e);
return;
}

View File

@ -18,4 +18,4 @@ serde_yaml = "0.8.13"
types = { path = "../../consensus/types"}
ethereum_ssz = "0.5.0"
eth2_config = { path = "../eth2_config"}
discv5 = "0.2.2"
discv5 = "0.3.0"

View File

@ -39,7 +39,7 @@ impl CommandLineTest {
}
fn run_with_ip(&mut self) -> CompletedTest<BootNodeConfigSerialization> {
self.cmd.arg(IP_ADDRESS);
self.cmd.arg("--enr-address").arg(IP_ADDRESS);
self.run()
}
}
@ -67,7 +67,13 @@ fn port_flag() {
.flag("port", Some(port.to_string().as_str()))
.run_with_ip()
.with_config(|config| {
assert_eq!(config.listen_socket.port(), port);
assert_eq!(
config
.ipv4_listen_socket
.expect("Bootnode should be listening on IPv4")
.port(),
port
);
})
}
@ -78,7 +84,13 @@ fn listen_address_flag() {
.flag("listen-address", Some("127.0.0.2"))
.run_with_ip()
.with_config(|config| {
assert_eq!(config.listen_socket.ip(), addr);
assert_eq!(
config
.ipv4_listen_socket
.expect("Bootnode should be listening on IPv4")
.ip(),
&addr
);
});
}