Skip to content

Commit 49baa90

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 0335866 commit 49baa90

File tree

4 files changed

+111
-61
lines changed

4 files changed

+111
-61
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
Node build();

src/lib.rs

Lines changed: 67 additions & 31 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();
@@ -155,13 +155,19 @@ use std::convert::TryInto;
155155
use std::default::Default;
156156
use std::fs;
157157
use std::net::ToSocketAddrs;
158-
use std::str::FromStr;
159158
use std::sync::atomic::{AtomicBool, Ordering};
160159
use std::sync::{Arc, Mutex, RwLock};
161160
use std::time::{Duration, Instant, SystemTime};
162161

163162
uniffi::include_scaffolding!("ldk_node");
164163

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+
165171
// The 'stop gap' parameter used by BDK's wallet sync. This seems to configure the threshold
166172
// number of blocks after which BDK stops looking for scripts belonging to the wallet.
167173
const BDK_CLIENT_STOP_GAP: usize = 20;
@@ -183,11 +189,19 @@ const WALLET_KEYS_SEED_LEN: usize = 64;
183189

184190
#[derive(Debug, Clone)]
185191
/// Represents the configuration of an [`Node`] instance.
192+
///
193+
/// ### Defaults
194+
///
195+
/// | Parameter | Value |
196+
/// |-----------------------------|------------------|
197+
/// | `storage_dir_path` | /tmp/ldk_node/ |
198+
/// | `network` | Network::Bitcoin |
199+
/// | `listening_address` | 0.0.0.0:9735 |
200+
/// | `default_cltv_expiry_delta` | 144 |
201+
///
186202
pub struct Config {
187203
/// The path where the underlying LDK and BDK persist their data.
188204
pub storage_dir_path: String,
189-
/// The URL of the utilized Esplora server.
190-
pub esplora_server_url: String,
191205
/// The used Bitcoin network.
192206
pub network: Network,
193207
/// The IP address and TCP port the node will listen on.
@@ -199,15 +213,19 @@ pub struct Config {
199213
impl Default for Config {
200214
fn default() -> Self {
201215
Self {
202-
storage_dir_path: "/tmp/ldk_node/".to_string(),
203-
esplora_server_url: "http://localhost:3002".to_string(),
204-
network: Network::Regtest,
205-
listening_address: Some(NetAddress::from_str("0.0.0.0:9735").unwrap()),
206-
default_cltv_expiry_delta: 144,
216+
storage_dir_path: DEFAULT_STORAGE_DIR_PATH.to_string(),
217+
network: DEFAULT_NETWORK,
218+
listening_address: Some(DEFAULT_LISTENING_ADDR.parse().unwrap()),
219+
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
207220
}
208221
}
209222
}
210223

224+
#[derive(Debug, Clone)]
225+
enum ChainDataSourceConfig {
226+
Esplora(String),
227+
}
228+
211229
#[derive(Debug, Clone)]
212230
enum EntropySourceConfig {
213231
SeedFile(String),
@@ -223,9 +241,15 @@ enum GossipSourceConfig {
223241

224242
/// A builder for an [`Node`] instance, allowing to set some configuration and module choices from
225243
/// the getgo.
244+
///
245+
/// ### Defaults
246+
/// - Chain data is sourced from the Esplora endpoint `https://blockstream.info/api`
247+
/// - Wallet entropy is sourced from a `keys_seed` file located under [`Config::storage_dir_path`]
248+
/// - Gossip data is sourced via the peer-to-peer network
226249
#[derive(Debug)]
227250
pub struct Builder {
228251
config: Mutex<Config>,
252+
chain_data_source_config: Mutex<Option<ChainDataSourceConfig>>,
229253
entropy_source_config: Mutex<Option<EntropySourceConfig>>,
230254
gossip_source_config: Mutex<Option<GossipSourceConfig>>,
231255
}
@@ -234,17 +258,19 @@ impl Builder {
234258
/// Creates a new builder instance with the default configuration.
235259
pub fn new() -> Self {
236260
let config = Mutex::new(Config::default());
261+
let chain_data_source_config = Mutex::new(None);
237262
let entropy_source_config = Mutex::new(None);
238263
let gossip_source_config = Mutex::new(None);
239-
Self { config, entropy_source_config, gossip_source_config }
264+
Self { config, chain_data_source_config, entropy_source_config, gossip_source_config }
240265
}
241266

242267
/// Creates a new builder instance from an [`Config`].
243268
pub fn from_config(config: Config) -> Self {
244269
let config = Mutex::new(config);
270+
let chain_data_source_config = Mutex::new(None);
245271
let entropy_source_config = Mutex::new(None);
246272
let gossip_source_config = Mutex::new(None);
247-
Self { config, entropy_source_config, gossip_source_config }
273+
Self { config, chain_data_source_config, entropy_source_config, gossip_source_config }
248274
}
249275

250276
/// Configures the [`Node`] instance to source its wallet entropy from a seed file on disk.
@@ -276,6 +302,12 @@ impl Builder {
276302
Some(EntropySourceConfig::Bip39Mnemonic { mnemonic, passphrase });
277303
}
278304

305+
/// Configures the [`Node`] instance to source its chain data from the given Esplora server.
306+
pub fn set_esplora_server(&self, esplora_server_url: String) {
307+
*self.chain_data_source_config.lock().unwrap() =
308+
Some(ChainDataSourceConfig::Esplora(esplora_server_url));
309+
}
310+
279311
/// Configures the [`Node`] instance to source its gossip data from the Lightning peer-to-peer
280312
/// network.
281313
pub fn set_gossip_source_p2p(&self) {
@@ -290,30 +322,18 @@ impl Builder {
290322
}
291323

292324
/// Sets the used storage directory path.
293-
///
294-
/// Default: `/tmp/ldk_node/`
295325
pub fn set_storage_dir_path(&self, storage_dir_path: String) {
296326
let mut config = self.config.lock().unwrap();
297327
config.storage_dir_path = storage_dir_path;
298328
}
299329

300-
/// Sets the Esplora server URL.
301-
///
302-
/// Default: `https://blockstream.info/api`
303-
pub fn set_esplora_server_url(&self, esplora_server_url: String) {
304-
let mut config = self.config.lock().unwrap();
305-
config.esplora_server_url = esplora_server_url;
306-
}
307-
308330
/// Sets the Bitcoin network used.
309331
pub fn set_network(&self, network: Network) {
310332
let mut config = self.config.lock().unwrap();
311333
config.network = network;
312334
}
313335

314336
/// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
315-
///
316-
/// Default: `0.0.0.0:9735`
317337
pub fn set_listening_address(&self, listening_address: NetAddress) {
318338
let mut config = self.config.lock().unwrap();
319339
config.listening_address = Some(listening_address);
@@ -376,14 +396,30 @@ impl Builder {
376396
)
377397
.expect("Failed to set up on-chain wallet");
378398

379-
let tx_sync = Arc::new(EsploraSyncClient::new(
380-
config.esplora_server_url.clone(),
381-
Arc::clone(&logger),
382-
));
383-
384-
let blockchain =
385-
EsploraBlockchain::from_client(tx_sync.client().clone(), BDK_CLIENT_STOP_GAP)
386-
.with_concurrency(BDK_CLIENT_CONCURRENCY);
399+
let (blockchain, tx_sync) = if let Some(chain_data_source_config) =
400+
&*self.chain_data_source_config.lock().unwrap()
401+
{
402+
match chain_data_source_config {
403+
ChainDataSourceConfig::Esplora(server_url) => {
404+
let tx_sync =
405+
Arc::new(EsploraSyncClient::new(server_url.clone(), Arc::clone(&logger)));
406+
let blockchain = EsploraBlockchain::from_client(
407+
tx_sync.client().clone(),
408+
BDK_CLIENT_STOP_GAP,
409+
)
410+
.with_concurrency(BDK_CLIENT_CONCURRENCY);
411+
(blockchain, tx_sync)
412+
}
413+
}
414+
} else {
415+
// Default to Esplora client with blockstream endpoint.
416+
let server_url = DEFAULT_ESPLORA_SERVER_URL.to_string();
417+
let tx_sync = Arc::new(EsploraSyncClient::new(server_url, Arc::clone(&logger)));
418+
let blockchain =
419+
EsploraBlockchain::from_client(tx_sync.client().clone(), BDK_CLIENT_STOP_GAP)
420+
.with_concurrency(BDK_CLIENT_CONCURRENCY);
421+
(blockchain, tx_sync)
422+
};
387423

388424
let runtime = Arc::new(RwLock::new(None));
389425
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

@@ -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

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)