Skip to content

Commit a9da44a

Browse files
committed
Move esplora config to ChainDataSourceConfig
After we already have `EntropySourceConfig` and `GossipSourceConfig`, we here move the esplora server URL to a corresponding `enum ChainDataSourceConfig`, which will us to add further variants (e.g., `Electrum`) in the future without breaking the API. Additionally, we document the set defaults and switch our default config to `Network::Bitcoin` while we're here.
1 parent 46af7c5 commit a9da44a

File tree

4 files changed

+111
-60
lines changed

4 files changed

+111
-60
lines changed

bindings/ldk_node.udl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ namespace ldk_node {
33

44
dictionary Config {
55
string storage_dir_path;
6-
string esplora_server_url;
76
Network network;
87
SocketAddr? listening_address;
98
u32 default_cltv_expiry_delta;
@@ -16,10 +15,10 @@ interface Builder {
1615
void set_entropy_seed_path(string seed_path);
1716
void set_entropy_seed_bytes(sequence<u8> seed_bytes);
1817
void set_entropy_bip39_mnemonic(Mnemonic mnemonic, string? passphrase);
18+
void set_esplora_server(string esplora_server_url);
1919
void set_gossip_source_p2p();
2020
void set_gossip_source_rgs(string rgs_server_url);
2121
void set_storage_dir_path(string storage_dir_path);
22-
void set_esplora_server_url(string esplora_server_url);
2322
void set_network(Network network);
2423
void set_listening_address(SocketAddr listening_address);
2524
Node build();

src/lib.rs

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
//! fn main() {
3636
//! let mut builder = Builder::new();
3737
//! builder.set_network(Network::Testnet);
38-
//! builder.set_esplora_server_url("https://blockstream.info/testnet/api".to_string());
38+
//! builder.set_esplora_server("https://blockstream.info/testnet/api".to_string());
3939
//!
4040
//! let node = builder.build();
4141
//! node.start().unwrap();
@@ -159,6 +159,13 @@ use std::time::{Duration, Instant, SystemTime};
159159

160160
uniffi::include_scaffolding!("ldk_node");
161161

162+
// Config defaults
163+
const DEFAULT_STORAGE_DIR_PATH: &str = "/tmp/ldk_node/";
164+
const DEFAULT_NETWORK: Network = Network::Bitcoin;
165+
const DEFAULT_LISTENING_ADDR: &str = "0.0.0.0:9735";
166+
const DEFAULT_CLTV_EXPIRY_DELTA: u32 = 144;
167+
const DEFAULT_ESPLORA_SERVER_URL: &str = "https://blockstream.info/api";
168+
162169
// The 'stop gap' parameter used by BDK's wallet sync. This seems to configure the threshold
163170
// number of blocks after which BDK stops looking for scripts belonging to the wallet.
164171
const BDK_CLIENT_STOP_GAP: usize = 20;
@@ -177,11 +184,19 @@ const WALLET_KEYS_SEED_LEN: usize = 64;
177184

178185
#[derive(Debug, Clone)]
179186
/// Represents the configuration of an [`Node`] instance.
187+
///
188+
/// ### Defaults
189+
///
190+
/// | Parameter | Value |
191+
/// |-----------------------------|------------------|
192+
/// | `storage_dir_path` | /tmp/ldk_node/ |
193+
/// | `network` | Network::Bitcoin |
194+
/// | `listening_address` | 0.0.0.0:9735 |
195+
/// | `default_cltv_expiry_delta` | 144 |
196+
///
180197
pub struct Config {
181198
/// The path where the underlying LDK and BDK persist their data.
182199
pub storage_dir_path: String,
183-
/// The URL of the utilized Esplora server.
184-
pub esplora_server_url: String,
185200
/// The used Bitcoin network.
186201
pub network: Network,
187202
/// The IP address and TCP port the node will listen on.
@@ -193,15 +208,19 @@ pub struct Config {
193208
impl Default for Config {
194209
fn default() -> Self {
195210
Self {
196-
storage_dir_path: "/tmp/ldk_node/".to_string(),
197-
esplora_server_url: "http://localhost:3002".to_string(),
198-
network: Network::Regtest,
199-
listening_address: Some("0.0.0.0:9735".parse().unwrap()),
200-
default_cltv_expiry_delta: 144,
211+
storage_dir_path: DEFAULT_STORAGE_DIR_PATH.to_string(),
212+
network: DEFAULT_NETWORK,
213+
listening_address: Some(DEFAULT_LISTENING_ADDR.parse().unwrap()),
214+
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
201215
}
202216
}
203217
}
204218

219+
#[derive(Debug, Clone)]
220+
enum ChainDataSourceConfig {
221+
Esplora(String),
222+
}
223+
205224
#[derive(Debug, Clone)]
206225
enum EntropySourceConfig {
207226
SeedFile(String),
@@ -217,9 +236,15 @@ enum GossipSourceConfig {
217236

218237
/// A builder for an [`Node`] instance, allowing to set some configuration and module choices from
219238
/// the getgo.
239+
///
240+
/// ### Defaults
241+
/// - Chain data is sourced from the Esplora endpoint `https://blockstream.info/api`
242+
/// - Wallet entropy is sourced from a `keys_seed` file located under [`Config::storage_dir_path`]
243+
/// - Gossip data is sourced via the peer-to-peer network
220244
#[derive(Debug)]
221245
pub struct Builder {
222246
config: Mutex<Config>,
247+
chain_data_source_config: Mutex<Option<ChainDataSourceConfig>>,
223248
entropy_source_config: Mutex<Option<EntropySourceConfig>>,
224249
gossip_source_config: Mutex<Option<GossipSourceConfig>>,
225250
}
@@ -228,17 +253,19 @@ impl Builder {
228253
/// Creates a new builder instance with the default configuration.
229254
pub fn new() -> Self {
230255
let config = Mutex::new(Config::default());
256+
let chain_data_source_config = Mutex::new(None);
231257
let entropy_source_config = Mutex::new(None);
232258
let gossip_source_config = Mutex::new(None);
233-
Self { config, entropy_source_config, gossip_source_config }
259+
Self { config, chain_data_source_config, entropy_source_config, gossip_source_config }
234260
}
235261

236262
/// Creates a new builder instance from an [`Config`].
237263
pub fn from_config(config: Config) -> Self {
238264
let config = Mutex::new(config);
265+
let chain_data_source_config = Mutex::new(None);
239266
let entropy_source_config = Mutex::new(None);
240267
let gossip_source_config = Mutex::new(None);
241-
Self { config, entropy_source_config, gossip_source_config }
268+
Self { config, chain_data_source_config, entropy_source_config, gossip_source_config }
242269
}
243270

244271
/// Configures the [`Node`] instance to source its wallet entropy from a seed file on disk.
@@ -270,6 +297,12 @@ impl Builder {
270297
Some(EntropySourceConfig::Bip39Mnemonic { mnemonic, passphrase });
271298
}
272299

300+
/// Configures the [`Node`] instance to source its chain data from the given Esplora server.
301+
pub fn set_esplora_server(&self, esplora_server_url: String) {
302+
*self.chain_data_source_config.lock().unwrap() =
303+
Some(ChainDataSourceConfig::Esplora(esplora_server_url));
304+
}
305+
273306
/// Configures the [`Node`] instance to source its gossip data from the Lightning peer-to-peer
274307
/// network.
275308
pub fn set_gossip_source_p2p(&self) {
@@ -284,30 +317,18 @@ impl Builder {
284317
}
285318

286319
/// Sets the used storage directory path.
287-
///
288-
/// Default: `/tmp/ldk_node/`
289320
pub fn set_storage_dir_path(&self, storage_dir_path: String) {
290321
let mut config = self.config.lock().unwrap();
291322
config.storage_dir_path = storage_dir_path;
292323
}
293324

294-
/// Sets the Esplora server URL.
295-
///
296-
/// Default: `https://blockstream.info/api`
297-
pub fn set_esplora_server_url(&self, esplora_server_url: String) {
298-
let mut config = self.config.lock().unwrap();
299-
config.esplora_server_url = esplora_server_url;
300-
}
301-
302325
/// Sets the Bitcoin network used.
303326
pub fn set_network(&self, network: Network) {
304327
let mut config = self.config.lock().unwrap();
305328
config.network = network;
306329
}
307330

308331
/// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
309-
///
310-
/// Default: `0.0.0.0:9735`
311332
pub fn set_listening_address(&self, listening_address: SocketAddr) {
312333
let mut config = self.config.lock().unwrap();
313334
config.listening_address = Some(listening_address);
@@ -370,14 +391,30 @@ impl Builder {
370391
)
371392
.expect("Failed to set up on-chain wallet");
372393

373-
let tx_sync = Arc::new(EsploraSyncClient::new(
374-
config.esplora_server_url.clone(),
375-
Arc::clone(&logger),
376-
));
377-
378-
let blockchain =
379-
EsploraBlockchain::from_client(tx_sync.client().clone(), BDK_CLIENT_STOP_GAP)
380-
.with_concurrency(BDK_CLIENT_CONCURRENCY);
394+
let (blockchain, tx_sync) = if let Some(chain_data_source_config) =
395+
&*self.chain_data_source_config.lock().unwrap()
396+
{
397+
match chain_data_source_config {
398+
ChainDataSourceConfig::Esplora(server_url) => {
399+
let tx_sync =
400+
Arc::new(EsploraSyncClient::new(server_url.clone(), Arc::clone(&logger)));
401+
let blockchain = EsploraBlockchain::from_client(
402+
tx_sync.client().clone(),
403+
BDK_CLIENT_STOP_GAP,
404+
)
405+
.with_concurrency(BDK_CLIENT_CONCURRENCY);
406+
(blockchain, tx_sync)
407+
}
408+
}
409+
} else {
410+
// Default to Esplora client with blockstream endpoint.
411+
let server_url = DEFAULT_ESPLORA_SERVER_URL.to_string();
412+
let tx_sync = Arc::new(EsploraSyncClient::new(server_url, Arc::clone(&logger)));
413+
let blockchain =
414+
EsploraBlockchain::from_client(tx_sync.client().clone(), BDK_CLIENT_STOP_GAP)
415+
.with_concurrency(BDK_CLIENT_CONCURRENCY);
416+
(blockchain, tx_sync)
417+
};
381418

382419
let runtime = Arc::new(RwLock::new(None));
383420
let wallet = Arc::new(Wallet::new(

src/test/functional_tests.rs

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,19 @@ use bitcoin::Amount;
88
fn channel_full_cycle() {
99
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
1010
println!("== Node A ==");
11-
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
12-
let config_a = random_config(esplora_url);
13-
let node_a = Builder::from_config(config_a).build();
11+
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
12+
let config_a = random_config();
13+
let builder_a = Builder::from_config(config_a);
14+
builder_a.set_esplora_server(esplora_url.clone());
15+
let node_a = builder_a.build();
1416
node_a.start().unwrap();
1517
let addr_a = node_a.new_funding_address().unwrap();
1618

1719
println!("\n== Node B ==");
18-
let config_b = random_config(esplora_url);
19-
let node_b = Builder::from_config(config_b).build();
20+
let config_b = random_config();
21+
let builder_b = Builder::from_config(config_b);
22+
builder_b.set_esplora_server(esplora_url);
23+
let node_b = builder_b.build();
2024
node_b.start().unwrap();
2125
let addr_b = node_b.new_funding_address().unwrap();
2226

@@ -212,15 +216,19 @@ fn channel_full_cycle() {
212216
fn channel_open_fails_when_funds_insufficient() {
213217
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
214218
println!("== Node A ==");
215-
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
216-
let config_a = random_config(&esplora_url);
217-
let node_a = Builder::from_config(config_a).build();
219+
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
220+
let config_a = random_config();
221+
let builder_a = Builder::from_config(config_a);
222+
builder_a.set_esplora_server(esplora_url.clone());
223+
let node_a = builder_a.build();
218224
node_a.start().unwrap();
219225
let addr_a = node_a.new_funding_address().unwrap();
220226

221227
println!("\n== Node B ==");
222-
let config_b = random_config(&esplora_url);
223-
let node_b = Builder::from_config(config_b).build();
228+
let config_b = random_config();
229+
let builder_b = Builder::from_config(config_b);
230+
builder_b.set_esplora_server(esplora_url);
231+
let node_b = builder_b.build();
224232
node_b.start().unwrap();
225233
let addr_b = node_b.new_funding_address().unwrap();
226234

@@ -252,12 +260,11 @@ fn channel_open_fails_when_funds_insufficient() {
252260

253261
#[test]
254262
fn connect_to_public_testnet_esplora() {
255-
let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd();
256-
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
257-
let mut config = random_config(&esplora_url);
258-
config.esplora_server_url = "https://blockstream.info/testnet/api".to_string();
263+
let mut config = random_config();
259264
config.network = bitcoin::Network::Testnet;
260-
let node = Builder::from_config(config).build();
265+
let builder = Builder::from_config(config);
266+
builder.set_esplora_server("https://blockstream.info/testnet/api".to_string());
267+
let node = builder.build();
261268
node.start().unwrap();
262269
node.sync_wallets().unwrap();
263270
node.stop().unwrap();
@@ -266,9 +273,11 @@ fn connect_to_public_testnet_esplora() {
266273
#[test]
267274
fn start_stop_reinit() {
268275
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
269-
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
270-
let config = random_config(&esplora_url);
271-
let node = Builder::from_config(config.clone()).build();
276+
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
277+
let config = random_config();
278+
let builder = Builder::from_config(config.clone());
279+
builder.set_esplora_server(esplora_url.clone());
280+
let node = builder.build();
272281
let expected_node_id = node.node_id();
273282

274283
let funding_address = node.new_funding_address().unwrap();
@@ -293,7 +302,9 @@ fn start_stop_reinit() {
293302
assert_eq!(node.stop(), Err(Error::NotRunning));
294303
drop(node);
295304

296-
let reinitialized_node = Builder::from_config(config).build();
305+
let new_builder = Builder::from_config(config);
306+
new_builder.set_esplora_server(esplora_url);
307+
let reinitialized_node = builder.build();
297308
assert_eq!(reinitialized_node.node_id(), expected_node_id);
298309

299310
reinitialized_node.start().unwrap();
@@ -315,15 +326,19 @@ fn start_stop_reinit() {
315326
#[test]
316327
fn onchain_spend_receive() {
317328
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
318-
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
329+
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
319330

320-
let config_a = random_config(esplora_url);
321-
let node_a = Builder::from_config(config_a).build();
331+
let config_a = random_config();
332+
let builder_a = Builder::from_config(config_a);
333+
builder_a.set_esplora_server(esplora_url.clone());
334+
let node_a = builder_a.build();
322335
node_a.start().unwrap();
323336
let addr_a = node_a.new_funding_address().unwrap();
324337

325-
let config_b = random_config(esplora_url);
326-
let node_b = Builder::from_config(config_b).build();
338+
let config_b = random_config();
339+
let builder_b = Builder::from_config(config_b);
340+
builder_b.set_esplora_server(esplora_url);
341+
let node_b = builder_b.build();
327342
node_b.start().unwrap();
328343
let addr_b = node_b.new_funding_address().unwrap();
329344

src/test/utils.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use lightning::util::logger::{Level, Logger, Record};
44
use lightning::util::persist::KVStorePersister;
55
use lightning::util::ser::Writeable;
66

7-
use bitcoin::{Address, Amount, OutPoint, Txid};
7+
use bitcoin::{Address, Amount, Network, OutPoint, Txid};
88

99
use bitcoind::bitcoincore_rpc::RpcApi;
1010
use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
@@ -282,11 +282,11 @@ pub fn random_port() -> u16 {
282282
rng.gen_range(5000..65535)
283283
}
284284

285-
pub fn random_config(esplora_url: &str) -> Config {
285+
pub fn random_config() -> Config {
286286
let mut config = Config::default();
287287

288-
println!("Setting esplora server URL: {}", esplora_url);
289-
config.esplora_server_url = format!("http://{}", esplora_url);
288+
config.network = Network::Regtest;
289+
println!("Setting network: {}", config.network);
290290

291291
let rand_dir = random_storage_path();
292292
println!("Setting random LDK storage dir: {}", rand_dir);

0 commit comments

Comments
 (0)