pub use reth_rpc_types::NodeRecord; // /// Ethereum Foundation Go Bootnodes pub static MAINNET_BOOTNODES : [&str; 4] = [ "enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303", // bootnode-aws-ap-southeast-1-001 "enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303", // bootnode-aws-us-east-1-001 "enode://2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc@65.108.70.101:30303", // bootnode-hetzner-hel "enode://4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052@157.90.35.166:30303", // bootnode-hetzner-fsn ]; /// Ethereum Foundation SEPOLIA BOOTNODES pub static SEPOLIA_BOOTNODES : [&str; 5] = [ "enode://4e5e92199ee224a01932a377160aa432f31d0b351f84ab413a8e0a42f4f36476f8fb1cbe914af0d9aef0d51665c214cf653c651c4bbd9d5550a934f241f1682b@138.197.51.181:30303", // sepolia-bootnode-1-nyc3 "enode://143e11fb766781d22d92a2e33f8f104cddae4411a122295ed1fdb6638de96a6ce65f5b7c964ba3763bba27961738fef7d3ecc739268f3e5e771fb4c87b6234ba@146.190.1.103:30303", // sepolia-bootnode-1-sfo3 "enode://8b61dc2d06c3f96fddcbebb0efb29d60d3598650275dc469c22229d3e5620369b0d3dedafd929835fe7f489618f19f456fe7c0df572bf2d914a9f4e006f783a9@170.64.250.88:30303", // sepolia-bootnode-1-syd1 "enode://10d62eff032205fcef19497f35ca8477bea0eadfff6d769a147e895d8b2b8f8ae6341630c645c30f5df6e67547c03494ced3d9c5764e8622a26587b083b028e8@139.59.49.206:30303", // sepolia-bootnode-1-blr1 "enode://9e9492e2e8836114cc75f5b929784f4f46c324ad01daf87d956f98b3b6c5fcba95524d6e5cf9861dc96a2c8a171ea7105bb554a197455058de185fa870970c7c@138.68.123.152:30303", // sepolia-bootnode-1-ams3 ]; /// GOERLI bootnodes pub static GOERLI_BOOTNODES : [&str; 7] = [ // Upstream bootnodes "enode://011f758e6552d105183b1761c5e2dea0111bc20fd5f6422bc7f91e0fabbec9a6595caf6239b37feb773dddd3f87240d99d859431891e4a642cf2a0a9e6cbb98a@51.141.78.53:30303", "enode://176b9417f511d05b6b2cf3e34b756cf0a7096b3094572a8f6ef4cdcb9d1f9d00683bf0f83347eebdf3b81c3521c2332086d9592802230bf528eaf606a1d9677b@13.93.54.137:30303", "enode://46add44b9f13965f7b9875ac6b85f016f341012d84f975377573800a863526f4da19ae2c620ec73d11591fa9510e992ecc03ad0751f53cc02f7c7ed6d55c7291@94.237.54.114:30313", "enode://b5948a2d3e9d486c4d75bf32713221c2bd6cf86463302339299bd227dc2e276cd5a1c7ca4f43a0e9122fe9af884efed563bd2a1fd28661f3b5f5ad7bf1de5949@18.218.250.66:30303", // Ethereum Foundation bootnode "enode://a61215641fb8714a373c80edbfa0ea8878243193f57c96eeb44d0bc019ef295abd4e044fd619bfc4c59731a73fb79afe84e9ab6da0c743ceb479cbb6d263fa91@3.11.147.67:30303", // Goerli Initiative bootnodes "enode://d4f764a48ec2a8ecf883735776fdefe0a3949eb0ca476bd7bc8d0954a9defe8fea15ae5da7d40b5d2d59ce9524a99daedadf6da6283fca492cc80b53689fb3b3@46.4.99.122:32109", "enode://d2b720352e8216c9efc470091aa91ddafc53e222b32780f505c817ceef69e01d5b0b0797b69db254c586f493872352f5a022b4d8479a00fc92ec55f9ad46a27e@88.99.70.182:30303", ]; /// Ethereum Foundation Holesky BOOTNODES pub static HOLESKY_BOOTNODES : [&str; 2] = [ "enode://ac906289e4b7f12df423d654c5a962b6ebe5b3a74cc9e06292a85221f9a64a6f1cfdd6b714ed6dacef51578f92b34c60ee91e9ede9c7f8fadc4d347326d95e2b@146.190.13.128:30303", "enode://a3435a0155a3e837c02f5e7f5662a2f1fbc25b48e4dc232016e1c51b544cb5b4510ef633ea3278c0e970fa8ad8141e2d4d0f9f95456c537ff05fdf9b31c15072@178.128.136.233:30303", ]; /// Returns parsed mainnet nodes pub fn mainnet_nodes() -> Vec { parse_nodes(&MAINNET_BOOTNODES[..]) } /// Returns parsed goerli nodes pub fn goerli_nodes() -> Vec { parse_nodes(&GOERLI_BOOTNODES[..]) } /// Returns parsed sepolia nodes pub fn sepolia_nodes() -> Vec { parse_nodes(&SEPOLIA_BOOTNODES[..]) } /// Returns parsed holesky nodes pub fn holesky_nodes() -> Vec { parse_nodes(&HOLESKY_BOOTNODES[..]) } /// Parses all the nodes pub fn parse_nodes(nodes: impl IntoIterator>) -> Vec { nodes.into_iter().map(|s| s.as_ref().parse().unwrap()).collect() } #[cfg(test)] mod tests { use std::{ net::{IpAddr, Ipv4Addr}, str::FromStr, }; use super::*; use alloy_rlp::{Decodable, Encodable}; use bytes::BytesMut; use rand::{thread_rng, Rng, RngCore}; use reth_rpc_types::PeerId; #[test] fn test_mapped_ipv6() { let mut rng = thread_rng(); let v4: Ipv4Addr = "0.0.0.0".parse().unwrap(); let v6 = v4.to_ipv6_mapped(); let record = NodeRecord { address: v6.into(), tcp_port: rng.gen(), udp_port: rng.gen(), id: rng.gen(), }; assert!(record.clone().convert_ipv4_mapped()); assert_eq!(record.into_ipv4_mapped().address, IpAddr::from(v4)); } #[test] fn test_mapped_ipv4() { let mut rng = thread_rng(); let v4: Ipv4Addr = "0.0.0.0".parse().unwrap(); let record = NodeRecord { address: v4.into(), tcp_port: rng.gen(), udp_port: rng.gen(), id: rng.gen(), }; assert!(!record.clone().convert_ipv4_mapped()); assert_eq!(record.into_ipv4_mapped().address, IpAddr::from(v4)); } #[test] fn test_noderecord_codec_ipv4() { let mut rng = thread_rng(); for _ in 0..100 { let mut ip = [0u8; 4]; rng.fill_bytes(&mut ip); let record = NodeRecord { address: IpAddr::V4(ip.into()), tcp_port: rng.gen(), udp_port: rng.gen(), id: rng.gen(), }; let mut buf = BytesMut::new(); record.encode(&mut buf); let decoded = NodeRecord::decode(&mut buf.as_ref()).unwrap(); assert_eq!(record, decoded); } } #[test] fn test_noderecord_codec_ipv6() { let mut rng = thread_rng(); for _ in 0..100 { let mut ip = [0u8; 16]; rng.fill_bytes(&mut ip); let record = NodeRecord { address: IpAddr::V6(ip.into()), tcp_port: rng.gen(), udp_port: rng.gen(), id: rng.gen(), }; let mut buf = BytesMut::new(); record.encode(&mut buf); let decoded = NodeRecord::decode(&mut buf.as_ref()).unwrap(); assert_eq!(record, decoded); } } #[test] fn test_url_parse() { let url = "enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303?discport=30301"; let node: NodeRecord = url.parse().unwrap(); assert_eq!(node, NodeRecord { address: IpAddr::V4([10,3,58,6].into()), tcp_port: 30303, udp_port: 30301, id: "6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0".parse().unwrap(), }) } #[test] fn test_node_display() { let url = "enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303"; let node: NodeRecord = url.parse().unwrap(); assert_eq!(url, &format!("{node}")); } #[test] fn test_node_display_discport() { let url = "enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303?discport=30301"; let node: NodeRecord = url.parse().unwrap(); assert_eq!(url, &format!("{node}")); } #[test] fn test_node_serialize() { let node = NodeRecord{ address: IpAddr::V4([10, 3, 58, 6].into()), tcp_port: 30303u16, udp_port: 30301u16, id: PeerId::from_str("6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0").unwrap(), }; let ser = serde_json::to_string::(&node).expect("couldn't serialize"); assert_eq!(ser, "\"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303?discport=30301\"") } #[test] fn test_node_deserialize() { let url = "\"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303?discport=30301\""; let node: NodeRecord = serde_json::from_str(url).expect("couldn't deserialize"); assert_eq!(node, NodeRecord{ address: IpAddr::V4([10, 3, 58, 6].into()), tcp_port: 30303u16, udp_port: 30301u16, id: PeerId::from_str("6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0").unwrap(), }) } }