discv5_cli/server/
enr_build.rs

1use std::net::IpAddr;
2
3use discv5::enr;
4
5/// Builds an Enr from Server input cli args.
6pub fn build(
7    server: &super::command::Server,
8    enr_key: &enr::CombinedKey,
9) -> eyre::Result<enr::Enr<enr::CombinedKey>> {
10    let mut builder = enr::Builder::default();
11
12    // Extract params from server config
13    let mut ipv4_address = None;
14    let mut ipv6_address = None;
15    for address in server.listen_addresses.split(',') {
16        match address
17            .parse::<IpAddr>()
18            .expect("Invalid listening address")
19        {
20            IpAddr::V4(ip) => ipv4_address = Some(ip),
21            IpAddr::V6(ip) => ipv6_address = Some(ip),
22        }
23    }
24
25    let listen_port = server.listen_port;
26    let listen_port_v6 = server.listen_port_v6;
27
28    // if the -w switch is used, use the listen_address and port for the ENR
29    if server.enr_default {
30        if let Some(listen_address) = ipv4_address {
31            builder.ip4(listen_address);
32            builder.udp4(listen_port);
33        }
34        if let Some(listen_address) = ipv6_address {
35            builder.ip6(listen_address);
36            builder.udp6(listen_port_v6.unwrap_or(listen_port));
37        }
38    } else {
39        // Logic for the ports. If the enr-port field is not set, use the listening port for both
40        // v4 and v6 addresses.
41        // If the enr-v4-port is set, use that for v4
42        // If the enr-v6-port is set, use that for v6.
43        if let Some(address_string) = &server.enr_addresses {
44            for address in address_string.split(',') {
45                match address
46                    .parse::<IpAddr>()
47                    .expect("Invalid listening address")
48                {
49                    IpAddr::V4(ip) => {
50                        builder.ip4(ip);
51                        builder.udp4(listen_port);
52                    }
53                    IpAddr::V6(ip) => {
54                        builder.ip6(ip);
55                        builder.udp6(listen_port_v6.unwrap_or(listen_port));
56                    }
57                }
58            }
59        }
60
61        if let Some(udp4) = &server.enr_v4_port {
62            builder.udp4(*udp4);
63        }
64
65        if let Some(udp6) = &server.enr_v6_port {
66            builder.udp6(*udp6);
67        }
68    }
69
70    // Set the server sequence number.
71    if let Some(seq_no_string) = &server.enr_seq_no {
72        let seq_no = seq_no_string
73            .parse::<u64>()
74            .expect("Invalid sequence number, must be a uint");
75        builder.seq(seq_no);
76    }
77
78    // Set the eth2 enr field.
79    if let Some(eth2_string) = &server.enr_eth2 {
80        let ssz_bytes = hex::decode(eth2_string).expect("Invalid eth2 hex bytes");
81        builder.add_value("eth2", &ssz_bytes);
82    }
83
84    // Build
85    let enr = builder.build(enr_key)?;
86
87    // If the ENR is useful print it
88    log::info!("Node Id: {}", enr.node_id());
89    if enr.udp4_socket().is_some() {
90        log::info!("Base64 ENR: {}", enr.to_base64());
91        log::info!(
92            "ip: {}, udp port:{}",
93            enr.ip4().unwrap(),
94            enr.udp4().unwrap()
95        );
96    } else {
97        log::warn!("ENR is not printed as no IP:PORT was specified");
98    }
99
100    Ok(enr)
101}