|
1 | 1 | use anyhow::{Result, anyhow}; |
2 | 2 | use async_trait::async_trait; |
3 | 3 | use celestia_types::nmt::Namespace; |
| 4 | +use libp2p::Multiaddr; |
4 | 5 | use lumina_node::{Node, NodeBuilder}; |
5 | | -#[cfg(target_arch = "wasm32")] |
6 | | -use lumina_node::{blockstore::IndexedDbBlockstore, store::IndexedDbStore}; |
7 | 6 | use prism_errors::DataAvailabilityError; |
8 | 7 | use prism_events::{EventChannel, EventPublisher}; |
| 8 | +use std::{self, str::FromStr, sync::Arc, time::Duration}; |
| 9 | +use tokio::sync::{Mutex, RwLock}; |
| 10 | +use tracing::{trace, warn}; |
| 11 | + |
| 12 | +#[cfg(target_arch = "wasm32")] |
| 13 | +use lumina_node::{blockstore::IndexedDbBlockstore, store::IndexedDbStore}; |
9 | 14 | use prism_presets::{ApplyPreset, LightClientPreset, PresetError}; |
10 | 15 | use serde::{Deserialize, Serialize}; |
11 | 16 | use serde_with::{DurationSeconds, serde_as}; |
12 | | -use std::{self, sync::Arc, time::Duration}; |
13 | | -use tokio::sync::{Mutex, RwLock}; |
14 | | -use tracing::{trace, warn}; |
15 | 17 | #[cfg(not(target_arch = "wasm32"))] |
16 | 18 | use { |
17 | 19 | blockstore::EitherBlockstore, |
@@ -63,6 +65,15 @@ pub struct CelestiaLightClientDAConfig { |
63 | 65 | /// Different networks have different block times and fee structures. |
64 | 66 | pub celestia_network: CelestiaNetwork, |
65 | 67 |
|
| 68 | + /// List of bootnodes to connect to. |
| 69 | + /// |
| 70 | + /// Bootnodes are used to bootstrap the connection to the network. |
| 71 | + /// They are not required for normal operation but can help with initial |
| 72 | + /// connection in case the network is not fully connected or a custom network are used. |
| 73 | + /// |
| 74 | + /// Are the String representations of libp2p multiaddresses on the Celestia network. |
| 75 | + pub bootnodes: Vec<String>, |
| 76 | + |
66 | 77 | /// Hex-encoded namespace ID for SNARK proofs. |
67 | 78 | /// |
68 | 79 | /// Light clients will only download and verify data from this namespace, |
@@ -204,6 +215,7 @@ impl Default for CelestiaLightClientDAConfig { |
204 | 215 | Self { |
205 | 216 | celestia_network: CelestiaNetwork::Arabica, |
206 | 217 | snark_namespace_id: "00000000000000de1008".to_string(), |
| 218 | + bootnodes: Vec::new(), |
207 | 219 | pruning_window: DEFAULT_PRUNING_WINDOW, |
208 | 220 | fetch_timeout: DEFAULT_FETCH_TIMEOUT, |
209 | 221 | fetch_max_retries: DEFAULT_FETCH_MAX_RETRIES, |
@@ -342,11 +354,31 @@ impl LightClientConnection { |
342 | 354 | pub async fn new(config: &CelestiaLightClientDAConfig) -> Result<Self, DataAvailabilityError> { |
343 | 355 | let (blockstore, store) = Self::setup_stores(&config.store).await?; |
344 | 356 |
|
345 | | - let (node, event_subscriber) = NodeBuilder::new() |
| 357 | + let mut node = NodeBuilder::new() |
346 | 358 | .network(config.celestia_network.clone()) |
347 | 359 | .store(store) |
348 | 360 | .blockstore(blockstore) |
349 | | - .pruning_window(config.pruning_window) |
| 361 | + .pruning_window(config.pruning_window); |
| 362 | + |
| 363 | + if !config.bootnodes.is_empty() { |
| 364 | + let multiaddrs: Vec<Multiaddr> = config |
| 365 | + .bootnodes |
| 366 | + .clone() |
| 367 | + .into_iter() |
| 368 | + .filter_map(|addr| Multiaddr::from_str(&addr).ok()) |
| 369 | + .collect(); |
| 370 | + |
| 371 | + if multiaddrs.len() != config.bootnodes.len() { |
| 372 | + warn!( |
| 373 | + "Some bootnodes failed to parse to libp2p multiaddrs. Valid addresses contain: {:#?}", |
| 374 | + multiaddrs |
| 375 | + ); |
| 376 | + } |
| 377 | + |
| 378 | + node = node.bootnodes(multiaddrs); |
| 379 | + } |
| 380 | + |
| 381 | + let (node, event_subscriber) = node |
350 | 382 | .start_subscribed() |
351 | 383 | .await |
352 | 384 | .map_err(|e| DataAvailabilityError::InitializationError(e.to_string()))?; |
|
0 commit comments