fedimint_core/net/
iroh.rs1use std::net::SocketAddr;
2
3use fedimint_core::util::SafeUrl;
4use fedimint_logging::LOG_NET_IROH;
5use iroh::defaults::DEFAULT_STUN_PORT;
6use iroh::discovery::pkarr::{PkarrPublisher, PkarrResolver};
7use iroh::{Endpoint, RelayMode, RelayNode, RelayUrl, SecretKey};
8use iroh_relay::RelayQuicConfig;
9use tracing::{info, warn};
10
11use crate::envs::{
12 FM_IROH_DHT_ENABLE_ENV, FM_IROH_N0_DISCOVERY_ENABLE_ENV, FM_IROH_PKARR_PUBLISHER_ENABLE_ENV,
13 FM_IROH_PKARR_RESOLVER_ENABLE_ENV, is_env_var_set, is_env_var_set_opt,
14};
15
16pub async fn build_iroh_endpoint(
17 secret_key: SecretKey,
18 bind_addr: SocketAddr,
19 iroh_dns: Option<SafeUrl>,
20 iroh_relays: Vec<SafeUrl>,
21 alpn: &[u8],
22) -> Result<Endpoint, anyhow::Error> {
23 let relay_mode = if iroh_relays.is_empty() {
24 RelayMode::Default
25 } else {
26 RelayMode::Custom(
27 iroh_relays
28 .into_iter()
29 .map(|url| RelayNode {
30 url: RelayUrl::from(url.to_unsafe()),
31 stun_only: false,
32 stun_port: DEFAULT_STUN_PORT,
33 quic: Some(RelayQuicConfig::default()),
34 })
35 .collect(),
36 )
37 };
38
39 let mut builder = Endpoint::builder();
40
41 if let Some(iroh_dns) = iroh_dns.map(SafeUrl::to_unsafe) {
42 if is_env_var_set_opt(FM_IROH_PKARR_PUBLISHER_ENABLE_ENV).unwrap_or(true) {
43 builder = builder.add_discovery({
44 let iroh_dns = iroh_dns.clone();
45 move |sk: &SecretKey| Some(PkarrPublisher::new(sk.clone(), iroh_dns))
46 });
47 } else {
48 warn!(
49 target: LOG_NET_IROH,
50 "Iroh pkarr publisher is disabled"
51 );
52 }
53
54 if is_env_var_set_opt(FM_IROH_PKARR_RESOLVER_ENABLE_ENV).unwrap_or(true) {
55 builder = builder.add_discovery(|_| Some(PkarrResolver::new(iroh_dns)));
56 } else {
57 warn!(
58 target: LOG_NET_IROH,
59 "Iroh pkarr resolver is disabled"
60 );
61 }
62 }
63
64 if is_env_var_set(FM_IROH_DHT_ENABLE_ENV) {
66 #[cfg(not(target_family = "wasm"))]
67 {
68 builder = builder.discovery_dht();
69 }
70 } else {
71 info!(
72 target: LOG_NET_IROH,
73 "Iroh DHT is disabled"
74 );
75 }
76
77 if is_env_var_set_opt(FM_IROH_N0_DISCOVERY_ENABLE_ENV).unwrap_or(true) {
78 builder = builder.discovery_n0();
79 } else {
80 warn!(
81 target: LOG_NET_IROH,
82 "Iroh n0 discovery is disabled"
83 );
84 }
85
86 let builder = builder
87 .relay_mode(relay_mode)
88 .secret_key(secret_key)
89 .alpns(vec![alpn.to_vec()]);
90
91 let builder = match bind_addr {
92 SocketAddr::V4(addr_v4) => builder.bind_addr_v4(addr_v4),
93 SocketAddr::V6(addr_v6) => builder.bind_addr_v6(addr_v6),
94 };
95
96 let endpoint = builder.bind().await.expect("Could not bind to port");
97
98 info!(
99 target: LOG_NET_IROH,
100 %bind_addr,
101 node_id = %endpoint.node_id(),
102 node_id_pkarr = %z32::encode(endpoint.node_id().as_bytes()),
103 "Iroh p2p server endpoint"
104 );
105
106 Ok(endpoint)
107}