1use bytes::{BufMut, Bytes};
2use ethrex_common::types::ForkId;
3use ethrex_common::{H256, H264, H512};
4use ethrex_crypto::keccak::keccak_hash;
5use ethrex_rlp::{
6 decode::RLPDecode,
7 encode::RLPEncode,
8 error::RLPDecodeError,
9 structs::{self, Decoder, Encoder},
10};
11use secp256k1::{PublicKey, SecretKey, ecdsa::Signature};
12use serde::{Deserialize, Serialize, ser::Serializer};
13use std::net::Ipv6Addr;
14use std::{
15 fmt::Display,
16 net::{IpAddr, Ipv4Addr, SocketAddr},
17 str::FromStr,
18 sync::OnceLock,
19};
20use thiserror::Error;
21
22use crate::utils::node_id;
23
24#[derive(Debug, Clone)]
30pub struct NetworkConfig {
31 pub bind_addr: IpAddr,
33 pub tcp_port: u16,
34 pub udp_port: u16,
35}
36
37impl NetworkConfig {
38 pub fn bind_tcp_addr(&self) -> SocketAddr {
40 SocketAddr::new(self.bind_addr, self.tcp_port)
41 }
42
43 pub fn bind_udp_addr(&self) -> SocketAddr {
45 SocketAddr::new(self.bind_addr, self.udp_port)
46 }
47
48 pub fn from_node(node: &Node) -> Self {
51 Self {
52 bind_addr: node.ip,
53 tcp_port: node.tcp_port,
54 udp_port: node.udp_port,
55 }
56 }
57}
58
59#[derive(Debug, Error)]
60pub enum NodeError {
61 #[error("Invalid format: {0}")]
62 InvalidFormat(String),
63 #[error("Parse error: {0}")]
64 ParseError(String),
65 #[error("RLP decode error: {0}")]
66 RLPDecodeError(#[from] RLPDecodeError),
67 #[error("Missing field: {0}")]
68 MissingField(String),
69 #[error("Signature error: {0}")]
70 SignatureError(String),
71}
72
73const MAX_NODE_RECORD_ENCODED_SIZE: usize = 300;
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76pub struct Endpoint {
77 pub ip: IpAddr,
78 pub udp_port: u16,
79 pub tcp_port: u16,
80}
81
82impl RLPEncode for Endpoint {
83 fn encode(&self, buf: &mut dyn BufMut) {
84 Encoder::new(buf)
85 .encode_field(&self.ip)
86 .encode_field(&self.udp_port)
87 .encode_field(&self.tcp_port)
88 .finish();
89 }
90}
91
92impl RLPDecode for Endpoint {
93 fn decode_unfinished(rlp: &[u8]) -> Result<(Self, &[u8]), RLPDecodeError> {
94 let decoder = Decoder::new(rlp)?;
95 let (ip, decoder) = decoder.decode_field("ip")?;
96 let (udp_port, decoder) = decoder.decode_field("udp_port")?;
97 let (tcp_port, decoder) = decoder.decode_field("tcp_port")?;
98 let remaining = decoder.finish()?;
99 let endpoint = Endpoint {
100 ip,
101 udp_port,
102 tcp_port,
103 };
104 Ok((endpoint, remaining))
105 }
106}
107
108#[derive(Debug, Clone, PartialEq, Eq)]
109pub struct Node {
110 pub ip: IpAddr,
111 pub udp_port: u16,
112 pub tcp_port: u16,
113 pub public_key: H512,
114 pub version: Option<String>,
115 node_id: OnceLock<H256>,
116}
117
118impl RLPDecode for Node {
119 fn decode_unfinished(rlp: &[u8]) -> Result<(Self, &[u8]), RLPDecodeError> {
120 let decoder = Decoder::new(rlp)?;
121 let (ip, decoder) = decoder.decode_field("ip")?;
122 let (udp_port, decoder) = decoder.decode_field("upd_port")?;
123 let (tcp_port, decoder) = decoder.decode_field("tcp_port")?;
124 let (public_key, decoder) = decoder.decode_field("public_key")?;
125 let remaining = decoder.finish_unchecked();
126
127 let node = Node::new(ip, udp_port, tcp_port, public_key);
128 Ok((node, remaining))
129 }
130}
131
132impl<'de> serde::de::Deserialize<'de> for Node {
133 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
134 where
135 D: serde::Deserializer<'de>,
136 {
137 Node::from_str(&<String>::deserialize(deserializer)?)
138 .map_err(|e| serde::de::Error::custom(format!("{}", e)))
139 }
140}
141
142impl serde::Serialize for Node {
143 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
144 where
145 S: Serializer,
146 {
147 serializer.serialize_str(&self.enode_url())
148 }
149}
150
151impl FromStr for Node {
152 type Err = NodeError;
153
154 fn from_str(s: &str) -> Result<Self, Self::Err> {
155 match s {
156 s if s.starts_with("enode://") => Self::from_enode_url(s),
157 s if s.starts_with("enr:") => Self::from_enr_url(s),
158 _ => Err(NodeError::InvalidFormat(
159 "Invalid network address format".into(),
160 )),
161 }
162 }
163}
164
165impl Node {
166 pub fn new(ip: IpAddr, udp_port: u16, tcp_port: u16, public_key: H512) -> Self {
167 Self {
168 ip,
169 udp_port,
170 tcp_port,
171 public_key,
172 version: None,
173 node_id: OnceLock::new(),
174 }
175 }
176
177 pub fn client_name(&self) -> &str {
178 self.version
179 .as_deref()
180 .and_then(|version| {
181 let base = version
182 .split_once('/')
183 .map(|(name, _)| name.trim())
184 .unwrap_or_else(|| version.trim());
185 if base.is_empty() { None } else { Some(base) }
186 })
187 .unwrap_or("unknown")
188 }
189
190 pub fn from_enode_url(enode: &str) -> Result<Self, NodeError> {
191 let public_key = H512::from_str(&enode[8..136])
192 .map_err(|_| NodeError::ParseError("Could not parse public_key".into()))?;
193
194 let address_start = 137;
195 let address_part = &enode[address_start..];
196
197 let address_part = match address_part.find('?') {
199 Some(pos) => &address_part[..pos],
200 None => address_part,
201 };
202
203 let socket_address: SocketAddr = address_part
204 .parse()
205 .map_err(|_| NodeError::ParseError("Could not parse socket address".into()))?;
206 let ip = socket_address.ip();
207 let port = socket_address.port();
208
209 let udp_port = match enode.find("?discport=") {
210 Some(pos) => enode[pos + 10..]
211 .parse()
212 .map_err(|_| NodeError::ParseError("Could not parse discport".into()))?,
213 None => port,
214 };
215
216 Ok(Self::new(ip, udp_port, port, public_key))
217 }
218
219 pub fn from_enr_url(enr: &str) -> Result<Self, NodeError> {
220 let base64_decoded = ethrex_common::base64::decode(&enr.as_bytes()[4..]);
221 let record = NodeRecord::decode(&base64_decoded).map_err(NodeError::from)?;
222 Node::from_enr(&record)
223 }
224
225 pub fn from_enr(record: &NodeRecord) -> Result<Self, NodeError> {
226 let pairs = record.pairs();
227 let public_key = pairs.secp256k1.ok_or(NodeError::MissingField(
228 "public key not found in record".into(),
229 ))?;
230 let verifying_key = PublicKey::from_slice(public_key.as_bytes()).map_err(|_| {
231 NodeError::ParseError("public key could not be built from msg pub key bytes".into())
232 })?;
233 let encoded = verifying_key.serialize_uncompressed();
234 let public_key = H512::from_slice(&encoded[1..]);
235
236 let ip: IpAddr = match (pairs.ip, pairs.ip6) {
237 (None, None) => {
238 return Err(NodeError::MissingField(
239 "Ip not found in record, can't construct node".into(),
240 ));
241 }
242 (None, Some(ipv6)) => IpAddr::from(ipv6),
243 (Some(ipv4), None) => IpAddr::from(ipv4),
244 (Some(ipv4), Some(_ipv6)) => IpAddr::from(ipv4),
245 };
246
247 let udp_port = pairs
250 .udp_port
251 .or(pairs.tcp_port)
252 .ok_or(NodeError::MissingField("No port found in record".into()))?;
253 let tcp_port = pairs
254 .tcp_port
255 .or(pairs.udp_port)
256 .ok_or(NodeError::MissingField("No port found in record".into()))?;
257
258 Ok(Self::new(ip, udp_port, tcp_port, public_key))
259 }
260
261 pub fn enode_url(&self) -> String {
262 let public_key = hex::encode(self.public_key);
263 let node_ip = self.ip;
264 let discovery_port = self.udp_port;
265 let listener_port = self.tcp_port;
266 if discovery_port != listener_port {
267 format!("enode://{public_key}@{node_ip}:{listener_port}?discport={discovery_port}")
268 } else {
269 format!("enode://{public_key}@{node_ip}:{listener_port}")
270 }
271 }
272
273 pub fn udp_addr(&self) -> SocketAddr {
274 SocketAddr::new(self.ip.to_canonical(), self.udp_port)
277 }
278
279 pub fn tcp_addr(&self) -> SocketAddr {
280 SocketAddr::new(self.ip, self.tcp_port)
281 }
282
283 pub fn node_id(&self) -> H256 {
284 *self.node_id.get_or_init(|| node_id(&self.public_key))
285 }
286}
287
288impl Display for Node {
289 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
290 f.write_str(&format!(
291 "{0} #{1}({2}:{3})",
292 self.client_name(),
293 self.node_id(),
294 self.ip,
295 self.tcp_port
296 ))
297 }
298}
299
300#[derive(Debug, Default, PartialEq, Eq, Clone, Serialize, Deserialize)]
302pub struct NodeRecordPairs {
303 pub id: Option<String>,
306 pub ip: Option<Ipv4Addr>,
307 pub ip6: Option<Ipv6Addr>,
308 pub tcp_port: Option<u16>,
312 pub udp_port: Option<u16>,
313 pub secp256k1: Option<H264>,
314 pub eth: Option<ForkId>,
316 pub snap: Option<Vec<u32>>,
318 pub other: Vec<(Bytes, Bytes)>,
319 }
321
322impl NodeRecordPairs {
323 pub fn try_from_raw_pairs(
324 pairs: Vec<(Bytes, Bytes)>,
325 ) -> Result<NodeRecordPairs, RLPDecodeError> {
326 let mut decoded_pairs = NodeRecordPairs::default();
327 for (key, value) in pairs {
328 match key.as_ref() {
329 b"id" => decoded_pairs.id = Some(String::decode(&value)?),
330 b"ip" => decoded_pairs.ip = Some(Ipv4Addr::decode(&value)?),
331 b"ip6" => decoded_pairs.ip6 = Some(Ipv6Addr::decode(&value)?),
332 b"tcp" => decoded_pairs.tcp_port = Some(u16::decode(&value)?),
333 b"udp" => decoded_pairs.udp_port = Some(u16::decode(&value)?),
334 b"secp256k1" => decoded_pairs.secp256k1 = Some(H264(<[u8; 33]>::decode(&value)?)),
335 b"snap" => decoded_pairs.snap = Some(Vec::<u32>::decode(&value)?),
336 b"eth" => {
337 let decoder = Decoder::new(&value)?;
340 let (fork_id, decoder) = decoder.decode_field("forkId")?;
342
343 decoder.finish_unchecked();
345 decoded_pairs.eth = Some(fork_id);
346 }
347 _ => {
349 decoded_pairs.other.push((key, value));
350 }
351 }
352 }
353
354 Ok(decoded_pairs)
355 }
356
357 pub fn encode_pairs(&self) -> Vec<(Bytes, Bytes)> {
359 let mut pairs = vec![];
361 if let Some(eth) = &self.eth {
362 let eth = vec![eth.clone()];
367 pairs.push(("eth".into(), eth.encode_to_vec().into()));
368 }
369 if let Some(id) = self.id.as_ref() {
370 pairs.push(("id".into(), id.encode_to_vec().into()));
371 }
372 if let Some(ip) = self.ip {
373 pairs.push(("ip".into(), ip.encode_to_vec().into()));
374 }
375 if let Some(ip6) = self.ip6 {
376 pairs.push(("ip6".into(), ip6.encode_to_vec().into()));
377 }
378 if let Some(secp256k1) = self.secp256k1 {
379 pairs.push(("secp256k1".into(), secp256k1.encode_to_vec().into()));
380 }
381 if let Some(snap) = self.snap.as_ref() {
382 pairs.push(("snap".into(), snap.encode_to_vec().into()));
383 }
384
385 if let Some(tcp) = self.tcp_port {
386 pairs.push(("tcp".into(), tcp.encode_to_vec().into()));
387 }
388 if let Some(udp) = self.udp_port {
389 pairs.push(("udp".into(), udp.encode_to_vec().into()));
390 }
391 pairs.extend(self.other.clone());
392 pairs.sort_by(|(left_key, _), (right_key, _)| left_key.cmp(right_key));
393 pairs
394 }
395}
396
397pub const INITIAL_ENR_SEQ: u64 = 1;
398
399#[derive(Debug, PartialEq, Clone, Eq, Default, Serialize, Deserialize)]
401pub struct NodeRecord {
402 pub signature: H512,
403 pub seq: u64,
404 pairs: NodeRecordPairs,
406}
407
408impl NodeRecord {
409 pub fn new(signature: H512, seq: u64, pairs: NodeRecordPairs) -> Self {
410 Self {
411 signature,
412 seq,
413 pairs,
414 }
415 }
416
417 pub fn enr_url(&self) -> Result<String, NodeError> {
418 let rlp_encoded = self.encode_to_vec();
419 let base64_encoded = ethrex_common::base64::encode(&rlp_encoded);
420 let mut result: String = "enr:".into();
421 let base64_encoded = String::from_utf8(base64_encoded)
422 .map_err(|_| NodeError::ParseError("Could not base 64 encode enr record".into()))?;
423 result.push_str(&base64_encoded);
424 Ok(result)
425 }
426
427 pub fn from_node(node: &Node, seq: u64, signer: &SecretKey) -> Result<Self, NodeError> {
428 let mut pairs = NodeRecordPairs {
429 id: Some("v4".to_string()),
430 secp256k1: Some(H264::from_slice(
431 &PublicKey::from_secret_key(secp256k1::SECP256K1, signer).serialize(),
432 )),
433 tcp_port: Some(node.tcp_port),
434 udp_port: Some(node.udp_port),
435 ..Default::default()
436 };
437 match node.ip.to_canonical() {
438 IpAddr::V4(ip) => pairs.ip = Some(ip),
439 IpAddr::V6(ip) => pairs.ip6 = Some(ip),
440 }
441
442 let mut record = NodeRecord {
443 seq,
444 pairs,
445 ..Default::default()
446 };
447 record.signature = record.sign_record(signer)?;
448
449 Ok(record)
450 }
451
452 pub fn set_fork_id(&mut self, fork_id: ForkId, signer: &SecretKey) -> Result<(), NodeError> {
453 self.pairs.eth = Some(fork_id);
454 self.update(signer)
455 }
456
457 pub fn get_fork_id(&self) -> Option<&ForkId> {
458 self.pairs.eth.as_ref()
459 }
460
461 fn update(&mut self, signer: &SecretKey) -> Result<(), NodeError> {
462 self.seq += 1;
463 self.signature = self.sign_record(signer)?;
464 Ok(())
465 }
466
467 pub fn sign_record(&self, signer: &SecretKey) -> Result<H512, NodeError> {
468 let digest = &self.get_signature_digest();
469 let msg = secp256k1::Message::from_digest_slice(digest)
470 .map_err(|_| NodeError::SignatureError("Invalid message digest".into()))?;
471 let (_recovery_id, signature_bytes) = secp256k1::SECP256K1
472 .sign_ecdsa_recoverable(&msg, signer)
473 .serialize_compact();
474
475 Ok(H512::from_slice(&signature_bytes))
476 }
477
478 pub fn get_signature_digest(&self) -> [u8; 32] {
479 let mut rlp = vec![];
480 structs::Encoder::new(&mut rlp)
481 .encode_field(&self.seq)
482 .encode_key_value_list::<Bytes>(&self.pairs.encode_pairs())
483 .finish();
484 keccak_hash(&rlp)
485 }
486
487 pub fn verify_signature(&self) -> bool {
490 let pairs = self.pairs();
491 let Some(pubkey_bytes) = pairs.secp256k1 else {
492 return false;
493 };
494
495 let Ok(pubkey) = PublicKey::from_slice(pubkey_bytes.as_bytes()) else {
496 return false;
497 };
498
499 let digest = self.get_signature_digest();
500 let Ok(message) = secp256k1::Message::from_digest_slice(&digest) else {
501 return false;
502 };
503
504 let Ok(signature) = Signature::from_compact(self.signature.as_bytes()) else {
505 return false;
506 };
507
508 secp256k1::SECP256K1
509 .verify_ecdsa(&message, &signature, &pubkey)
510 .is_ok()
511 }
512
513 pub fn pairs(&self) -> &NodeRecordPairs {
514 &self.pairs
515 }
516}
517
518impl RLPDecode for NodeRecord {
519 fn decode_unfinished(rlp: &[u8]) -> Result<(Self, &[u8]), RLPDecodeError> {
520 let decoder = Decoder::new(rlp)?;
521 if decoder.get_payload_len() > MAX_NODE_RECORD_ENCODED_SIZE {
522 return Err(RLPDecodeError::InvalidLength);
523 }
524 let (signature, decoder) = decoder.decode_field("signature")?;
525 let (seq, decoder) = decoder.decode_field("seq")?;
526 let (pairs, decoder) = decode_node_record_optional_fields(vec![], decoder)?;
527
528 let id_pair = pairs.iter().find(|(k, _v)| k.eq("id".as_bytes()));
530 if id_pair.is_some() {
531 let pairs = NodeRecordPairs::try_from_raw_pairs(pairs)?;
532 let node_record = NodeRecord {
533 signature,
534 seq,
535 pairs,
536 };
537 let remaining = decoder.finish()?;
538 Ok((node_record, remaining))
539 } else {
540 Err(RLPDecodeError::Custom(
541 "Invalid node record, 'id' field missing".into(),
542 ))
543 }
544 }
545}
546
547fn decode_node_record_optional_fields(
552 mut pairs: Vec<(Bytes, Bytes)>,
553 decoder: Decoder,
554) -> Result<(Vec<(Bytes, Bytes)>, Decoder), RLPDecodeError> {
555 let (key, decoder): (Option<Bytes>, Decoder) = decoder.decode_optional_field();
556 if let Some(k) = key {
557 let (value, decoder): (Vec<u8>, Decoder) = decoder.get_encoded_item()?;
558 pairs.push((k, Bytes::from(value)));
559 decode_node_record_optional_fields(pairs, decoder)
560 } else {
561 Ok((pairs, decoder))
562 }
563}
564
565impl RLPEncode for NodeRecord {
566 fn encode(&self, buf: &mut dyn BufMut) {
567 structs::Encoder::new(buf)
568 .encode_field(&self.signature)
569 .encode_field(&self.seq)
570 .encode_key_value_list::<Bytes>(&self.pairs.encode_pairs())
571 .finish();
572 }
573}
574
575impl RLPEncode for Node {
576 fn encode(&self, buf: &mut dyn BufMut) {
577 structs::Encoder::new(buf)
578 .encode_field(&self.ip)
579 .encode_field(&self.udp_port)
580 .encode_field(&self.tcp_port)
581 .encode_field(&self.public_key)
582 .finish();
583 }
584}