diff --git a/crates/networking/p2p/types.rs b/crates/networking/p2p/types.rs index 13705a0853..7d5a0ff6c2 100644 --- a/crates/networking/p2p/types.rs +++ b/crates/networking/p2p/types.rs @@ -6,10 +6,10 @@ use ethrex_rlp::{ error::RLPDecodeError, structs::{self, Decoder, Encoder}, }; -use k256::ecdsa::SigningKey; +use k256::ecdsa::{SigningKey, VerifyingKey}; use sha3::{Digest, Keccak256}; use std::{ - net::{IpAddr, SocketAddr}, + net::{IpAddr, Ipv4Addr, SocketAddr}, str::FromStr, }; @@ -96,7 +96,7 @@ impl FromStr for Node { fn from_str(s: &str) -> Result { match s { s if s.starts_with("enode://") => Self::from_enode_url(s), - // TODO implement enr strings, see #1757 + s if s.starts_with("enr:") => Self::from_enr_url(s), _ => Err("Invalid network address format".into()), } } @@ -136,6 +136,29 @@ impl Node { }) } + pub fn from_enr_url(enr: &str) -> Result { + let base64_decoded = ethrex_core::base64::decode(enr.as_bytes()); + let record = NodeRecord::decode(&base64_decoded).unwrap(); + let pairs = record.decode_pairs(); + let Some(public_key) = pairs.secp256k1 else { + return Err( + "signature could not be verified because public key was not provided".into(), + ); + }; + let Ok(verifying_key) = VerifyingKey::from_sec1_bytes(public_key.as_bytes()) else { + return Err("public key could no be built from msg pub key bytes".into()); + }; + let encoded = verifying_key.to_encoded_point(false); + let node_id = H512::from_slice(&encoded.as_bytes()[1..]); + + Ok(Self { + ip: IpAddr::from(Ipv4Addr::from_bits(pairs.ip.unwrap())), + node_id, + tcp_port: pairs.tcp_port.unwrap(), + udp_port: pairs.udp_port.unwrap(), + }) + } + pub fn enode_url(&self) -> String { let node_id = hex::encode(self.node_id); let node_ip = self.ip; @@ -209,6 +232,14 @@ impl NodeRecord { decoded_pairs } + pub fn enr_url(&self) -> String { + let rlp_encoded = self.encode_to_vec(); + let base64_encoded = ethrex_core::base64::encode(&rlp_encoded); + let mut result: String = "enr:".into(); + result.push_str(&String::from_utf8(base64_encoded).unwrap()); + result + } + pub fn from_node(node: Node, seq: u64, signer: &SigningKey) -> Result { let mut record = NodeRecord { seq,