Skip to content

Commit bb02755

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 455e943 commit bb02755

File tree

4 files changed

+116
-62
lines changed

4 files changed

+116
-62
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
NetAddress? 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(NetAddress listening_address);
2524
LDKNode 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();
@@ -161,6 +161,13 @@ use std::time::{Duration, Instant, SystemTime};
161161

162162
uniffi::include_scaffolding!("ldk_node");
163163

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

186193
#[derive(Debug, Clone)]
187194
/// Represents the configuration of an [`Node`] instance.
195+
///
196+
/// ### Defaults
197+
///
198+
/// | Parameter | Value |
199+
/// |-----------------------------|------------------|
200+
/// | `storage_dir_path` | /tmp/ldk_node/ |
201+
/// | `network` | Network::Bitcoin |
202+
/// | `listening_address` | 0.0.0.0:9735 |
203+
/// | `default_cltv_expiry_delta` | 144 |
204+
///
188205
pub struct Config {
189206
/// The path where the underlying LDK and BDK persist their data.
190207
pub storage_dir_path: String,
191-
/// The URL of the utilized Esplora server.
192-
pub esplora_server_url: String,
193208
/// The used Bitcoin network.
194209
pub network: Network,
195210
/// The IP address and TCP port the node will listen on.
@@ -201,15 +216,19 @@ pub struct Config {
201216
impl Default for Config {
202217
fn default() -> Self {
203218
Self {
204-
storage_dir_path: "/tmp/ldk_node/".to_string(),
205-
esplora_server_url: "http://localhost:3002".to_string(),
206-
network: Network::Regtest,
207-
listening_address: Some("0.0.0.0:9735".parse().unwrap()),
208-
default_cltv_expiry_delta: 144,
219+
storage_dir_path: DEFAULT_STORAGE_DIR_PATH.to_string(),
220+
network: DEFAULT_NETWORK,
221+
listening_address: Some(DEFAULT_LISTENING_ADDR.parse().unwrap()),
222+
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
209223
}
210224
}
211225
}
212226

227+
#[derive(Debug, Clone)]
228+
enum ChainDataSourceConfig {
229+
Esplora(String),
230+
}
231+
213232
#[derive(Debug, Clone)]
214233
enum EntropySourceConfig {
215234
SeedFile(String),
@@ -225,10 +244,16 @@ enum GossipSourceConfig {
225244

226245
/// A builder for an [`Node`] instance, allowing to set some configuration and module choices from
227246
/// the getgo.
247+
///
248+
/// ### Defaults
249+
/// - Wallet entropy is sourced from a `keys_seed` file located under [`Config::storage_dir_path`]
250+
/// - Chain data is sourced from the Esplora endpoint `https://blockstream.info/api`
251+
/// - Gossip data is sourced via the peer-to-peer network
228252
#[derive(Debug)]
229253
pub struct Builder {
230254
config: RwLock<Config>,
231255
entropy_source_config: RwLock<Option<EntropySourceConfig>>,
256+
chain_data_source_config: RwLock<Option<ChainDataSourceConfig>>,
232257
gossip_source_config: RwLock<Option<GossipSourceConfig>>,
233258
}
234259

@@ -237,16 +262,18 @@ impl Builder {
237262
pub fn new() -> Self {
238263
let config = RwLock::new(Config::default());
239264
let entropy_source_config = RwLock::new(None);
265+
let chain_data_source_config = RwLock::new(None);
240266
let gossip_source_config = RwLock::new(None);
241-
Self { config, entropy_source_config, gossip_source_config }
267+
Self { config, entropy_source_config, chain_data_source_config, gossip_source_config }
242268
}
243269

244270
/// Creates a new builder instance from an [`Config`].
245271
pub fn from_config(config: Config) -> Self {
246272
let config = RwLock::new(config);
247273
let entropy_source_config = RwLock::new(None);
274+
let chain_data_source_config = RwLock::new(None);
248275
let gossip_source_config = RwLock::new(None);
249-
Self { config, entropy_source_config, gossip_source_config }
276+
Self { config, entropy_source_config, chain_data_source_config, gossip_source_config }
250277
}
251278

252279
/// Configures the [`Node`] instance to source its wallet entropy from a seed file on disk.
@@ -278,6 +305,12 @@ impl Builder {
278305
Some(EntropySourceConfig::Bip39Mnemonic { mnemonic, passphrase });
279306
}
280307

308+
/// Configures the [`Node`] instance to source its chain data from the given Esplora server.
309+
pub fn set_esplora_server(&self, esplora_server_url: String) {
310+
*self.chain_data_source_config.write().unwrap() =
311+
Some(ChainDataSourceConfig::Esplora(esplora_server_url));
312+
}
313+
281314
/// Configures the [`Node`] instance to source its gossip data from the Lightning peer-to-peer
282315
/// network.
283316
pub fn set_gossip_source_p2p(&self) {
@@ -292,30 +325,18 @@ impl Builder {
292325
}
293326

294327
/// Sets the used storage directory path.
295-
///
296-
/// Default: `/tmp/ldk_node/`
297328
pub fn set_storage_dir_path(&self, storage_dir_path: String) {
298329
let mut config = self.config.write().unwrap();
299330
config.storage_dir_path = storage_dir_path;
300331
}
301332

302-
/// Sets the Esplora server URL.
303-
///
304-
/// Default: `https://blockstream.info/api`
305-
pub fn set_esplora_server_url(&self, esplora_server_url: String) {
306-
let mut config = self.config.write().unwrap();
307-
config.esplora_server_url = esplora_server_url;
308-
}
309-
310333
/// Sets the Bitcoin network used.
311334
pub fn set_network(&self, network: Network) {
312335
let mut config = self.config.write().unwrap();
313336
config.network = network;
314337
}
315338

316339
/// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
317-
///
318-
/// Default: `0.0.0.0:9735`
319340
pub fn set_listening_address(&self, listening_address: NetAddress) {
320341
let mut config = self.config.write().unwrap();
321342
config.listening_address = Some(listening_address);
@@ -389,14 +410,30 @@ impl Builder {
389410
)
390411
.expect("Failed to set up on-chain wallet");
391412

392-
let tx_sync = Arc::new(EsploraSyncClient::new(
393-
config.esplora_server_url.clone(),
394-
Arc::clone(&logger),
395-
));
396-
397-
let blockchain =
398-
EsploraBlockchain::from_client(tx_sync.client().clone(), BDK_CLIENT_STOP_GAP)
399-
.with_concurrency(BDK_CLIENT_CONCURRENCY);
413+
let (blockchain, tx_sync) = if let Some(chain_data_source_config) =
414+
&*self.chain_data_source_config.read().unwrap()
415+
{
416+
match chain_data_source_config {
417+
ChainDataSourceConfig::Esplora(server_url) => {
418+
let tx_sync =
419+
Arc::new(EsploraSyncClient::new(server_url.clone(), Arc::clone(&logger)));
420+
let blockchain = EsploraBlockchain::from_client(
421+
tx_sync.client().clone(),
422+
BDK_CLIENT_STOP_GAP,
423+
)
424+
.with_concurrency(BDK_CLIENT_CONCURRENCY);
425+
(blockchain, tx_sync)
426+
}
427+
}
428+
} else {
429+
// Default to Esplora client with blockstream endpoint.
430+
let server_url = DEFAULT_ESPLORA_SERVER_URL.to_string();
431+
let tx_sync = Arc::new(EsploraSyncClient::new(server_url, Arc::clone(&logger)));
432+
let blockchain =
433+
EsploraBlockchain::from_client(tx_sync.client().clone(), BDK_CLIENT_STOP_GAP)
434+
.with_concurrency(BDK_CLIENT_CONCURRENCY);
435+
(blockchain, tx_sync)
436+
};
400437

401438
let runtime = Arc::new(RwLock::new(None));
402439
let wallet = Arc::new(Wallet::new(

src/test/functional_tests.rs

Lines changed: 44 additions & 26 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

@@ -221,15 +225,19 @@ fn channel_full_cycle() {
221225
fn channel_open_fails_when_funds_insufficient() {
222226
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
223227
println!("== Node A ==");
224-
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
225-
let config_a = random_config(&esplora_url);
226-
let node_a = Builder::from_config(config_a).build();
228+
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
229+
let config_a = random_config();
230+
let builder_a = Builder::from_config(config_a);
231+
builder_a.set_esplora_server(esplora_url.clone());
232+
let node_a = builder_a.build();
227233
node_a.start().unwrap();
228234
let addr_a = node_a.new_funding_address().unwrap();
229235

230236
println!("\n== Node B ==");
231-
let config_b = random_config(&esplora_url);
232-
let node_b = Builder::from_config(config_b).build();
237+
let config_b = random_config();
238+
let builder_b = Builder::from_config(config_b);
239+
builder_b.set_esplora_server(esplora_url);
240+
let node_b = builder_b.build();
233241
node_b.start().unwrap();
234242
let addr_b = node_b.new_funding_address().unwrap();
235243

@@ -261,12 +269,11 @@ fn channel_open_fails_when_funds_insufficient() {
261269

262270
#[test]
263271
fn connect_to_public_testnet_esplora() {
264-
let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd();
265-
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
266-
let mut config = random_config(&esplora_url);
267-
config.esplora_server_url = "https://blockstream.info/testnet/api".to_string();
272+
let mut config = random_config();
268273
config.network = bitcoin::Network::Testnet;
269-
let node = Builder::from_config(config).build();
274+
let builder = Builder::from_config(config);
275+
builder.set_esplora_server("https://blockstream.info/testnet/api".to_string());
276+
let node = builder.build();
270277
node.start().unwrap();
271278
node.sync_wallets().unwrap();
272279
node.stop().unwrap();
@@ -275,9 +282,11 @@ fn connect_to_public_testnet_esplora() {
275282
#[test]
276283
fn start_stop_reinit() {
277284
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
278-
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
279-
let config = random_config(&esplora_url);
280-
let node = Builder::from_config(config.clone()).build();
285+
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
286+
let config = random_config();
287+
let builder = Builder::from_config(config.clone());
288+
builder.set_esplora_server(esplora_url.clone());
289+
let node = builder.build();
281290
let expected_node_id = node.node_id();
282291

283292
let funding_address = node.new_funding_address().unwrap();
@@ -302,7 +311,9 @@ fn start_stop_reinit() {
302311
assert_eq!(node.stop(), Err(Error::NotRunning));
303312
drop(node);
304313

305-
let reinitialized_node = Builder::from_config(config).build();
314+
let new_builder = Builder::from_config(config);
315+
new_builder.set_esplora_server(esplora_url);
316+
let reinitialized_node = builder.build();
306317
assert_eq!(reinitialized_node.node_id(), expected_node_id);
307318

308319
reinitialized_node.start().unwrap();
@@ -324,15 +335,19 @@ fn start_stop_reinit() {
324335
#[test]
325336
fn onchain_spend_receive() {
326337
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
327-
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
338+
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
328339

329-
let config_a = random_config(esplora_url);
330-
let node_a = Builder::from_config(config_a).build();
340+
let config_a = random_config();
341+
let builder_a = Builder::from_config(config_a);
342+
builder_a.set_esplora_server(esplora_url.clone());
343+
let node_a = builder_a.build();
331344
node_a.start().unwrap();
332345
let addr_a = node_a.new_funding_address().unwrap();
333346

334-
let config_b = random_config(esplora_url);
335-
let node_b = Builder::from_config(config_b).build();
347+
let config_b = random_config();
348+
let builder_b = Builder::from_config(config_b);
349+
builder_b.set_esplora_server(esplora_url);
350+
let node_b = builder_b.build();
336351
node_b.start().unwrap();
337352
let addr_b = node_b.new_funding_address().unwrap();
338353

@@ -376,8 +391,11 @@ fn onchain_spend_receive() {
376391
#[test]
377392
fn sign_verify_msg() {
378393
let (_, electrsd) = setup_bitcoind_and_electrsd();
379-
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
380-
let node = Builder::from_config(random_config(esplora_url)).build();
394+
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
395+
let config = random_config();
396+
let builder = Builder::from_config(config.clone());
397+
builder.set_esplora_server(esplora_url.clone());
398+
let node = builder.build();
381399

382400
node.start().unwrap();
383401

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;
@@ -251,11 +251,11 @@ pub fn random_port() -> u16 {
251251
rng.gen_range(5000..65535)
252252
}
253253

254-
pub fn random_config(esplora_url: &str) -> Config {
254+
pub fn random_config() -> Config {
255255
let mut config = Config::default();
256256

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

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

0 commit comments

Comments
 (0)