2929//! use ldk_node::{Builder, NetAddress};
3030//! use ldk_node::lightning_invoice::Invoice;
3131//! use ldk_node::bitcoin::secp256k1::PublicKey;
32+ //! use ldk_node::bitcoin::Network;
3233//! use std::str::FromStr;
3334//!
3435//! fn main() {
35- //! let node = Builder::new()
36- //! .set_network("testnet")
37- //! .set_esplora_server_url("https://blockstream.info/testnet/api".to_string())
38- //! .build();
36+ //! let mut builder = Builder::new();
37+ //! builder.set_network(Network::Testnet);
38+ //! builder.set_esplora_server_url("https://blockstream.info/testnet/api".to_string());
3939//!
40+ //! let node = builder.build();
4041//! node.start().unwrap();
4142//!
4243//! let _funding_address = node.new_funding_address();
@@ -144,6 +145,8 @@ use bitcoin::hashes::Hash;
144145use bitcoin:: secp256k1:: PublicKey ;
145146use bitcoin:: Network ;
146147
148+ use bip39:: Mnemonic ;
149+
147150use bitcoin:: { Address , BlockHash , OutPoint , Txid } ;
148151
149152use rand:: Rng ;
@@ -152,7 +155,6 @@ use std::convert::TryInto;
152155use std:: default:: Default ;
153156use std:: fs;
154157use std:: net:: ToSocketAddrs ;
155- use std:: str:: FromStr ;
156158use std:: sync:: atomic:: { AtomicBool , Ordering } ;
157159use std:: sync:: { Arc , Mutex , RwLock } ;
158160use std:: time:: { Duration , Instant , SystemTime } ;
@@ -212,7 +214,7 @@ impl Default for Config {
212214enum EntropySourceConfig {
213215 SeedFile ( String ) ,
214216 SeedBytes ( [ u8 ; WALLET_KEYS_SEED_LEN ] ) ,
215- Bip39Mnemonic { mnemonic : bip39 :: Mnemonic , passphrase : Option < String > } ,
217+ Bip39Mnemonic { mnemonic : Mnemonic , passphrase : Option < String > } ,
216218}
217219
218220#[ derive( Debug , Clone ) ]
@@ -223,107 +225,107 @@ enum GossipSourceConfig {
223225
224226/// A builder for an [`Node`] instance, allowing to set some configuration and module choices from
225227/// the getgo.
226- #[ derive( Debug , Clone ) ]
228+ #[ derive( Debug ) ]
227229pub struct Builder {
228- config : Config ,
229- entropy_source_config : Option < EntropySourceConfig > ,
230- gossip_source_config : Option < GossipSourceConfig > ,
230+ config : RwLock < Config > ,
231+ entropy_source_config : RwLock < Option < EntropySourceConfig > > ,
232+ gossip_source_config : RwLock < Option < GossipSourceConfig > > ,
231233}
232234
233235impl Builder {
234236 /// Creates a new builder instance with the default configuration.
235237 pub fn new ( ) -> Self {
236- let config = Config :: default ( ) ;
237- let entropy_source_config = None ;
238- let gossip_source_config = None ;
238+ let config = RwLock :: new ( Config :: default ( ) ) ;
239+ let entropy_source_config = RwLock :: new ( None ) ;
240+ let gossip_source_config = RwLock :: new ( None ) ;
239241 Self { config, entropy_source_config, gossip_source_config }
240242 }
241243
242244 /// Creates a new builder instance from an [`Config`].
243245 pub fn from_config ( config : Config ) -> Self {
244- let entropy_source_config = None ;
245- let gossip_source_config = None ;
246+ let config = RwLock :: new ( config) ;
247+ let entropy_source_config = RwLock :: new ( None ) ;
248+ let gossip_source_config = RwLock :: new ( None ) ;
246249 Self { config, entropy_source_config, gossip_source_config }
247250 }
248251
249252 /// Configures the [`Node`] instance to source its wallet entropy from a seed file on disk.
250253 ///
251254 /// If the given file does not exist a new random seed file will be generated and
252255 /// stored at the given location.
253- pub fn set_entropy_seed_path ( & mut self , seed_path : String ) -> & mut Self {
254- self . entropy_source_config = Some ( EntropySourceConfig :: SeedFile ( seed_path) ) ;
255- self
256+ pub fn set_entropy_seed_path ( & self , seed_path : String ) {
257+ * self . entropy_source_config . write ( ) . unwrap ( ) =
258+ Some ( EntropySourceConfig :: SeedFile ( seed_path) ) ;
259+ }
260+
261+ /// Configures the [`Node`] instance to source its wallet entropy from the given 64 seed bytes.
262+ ///
263+ /// **Note:** Panics if the length of the given `seed_bytes` differs from 64.
264+ pub fn set_entropy_seed_bytes ( & self , seed_bytes : Vec < u8 > ) {
265+ if seed_bytes. len ( ) != WALLET_KEYS_SEED_LEN {
266+ panic ! ( "Failed to set seed due to invalid length." ) ;
267+ }
268+ let mut bytes = [ 0u8 ; WALLET_KEYS_SEED_LEN ] ;
269+ bytes. copy_from_slice ( & seed_bytes) ;
270+ * self . entropy_source_config . write ( ) . unwrap ( ) = Some ( EntropySourceConfig :: SeedBytes ( bytes) ) ;
256271 }
257272
258- /// Configures the [`Node`] instance to source its wallet entropy from the given seed bytes.
259- pub fn set_entropy_seed_bytes ( & mut self , seed_bytes : [ u8 ; WALLET_KEYS_SEED_LEN ] ) -> & mut Self {
260- self . entropy_source_config = Some ( EntropySourceConfig :: SeedBytes ( seed_bytes) ) ;
261- self
273+ /// Configures the [`Node`] instance to source its wallet entropy from a [BIP 39] mnemonic.
274+ ///
275+ /// [BIP 39]: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
276+ pub fn set_entropy_bip39_mnemonic ( & self , mnemonic : Mnemonic , passphrase : Option < String > ) {
277+ * self . entropy_source_config . write ( ) . unwrap ( ) =
278+ Some ( EntropySourceConfig :: Bip39Mnemonic { mnemonic, passphrase } ) ;
262279 }
263280
264281 /// Configures the [`Node`] instance to source its gossip data from the Lightning peer-to-peer
265282 /// network.
266- pub fn set_gossip_source_p2p ( & mut self ) -> & mut Self {
267- self . gossip_source_config = Some ( GossipSourceConfig :: P2PNetwork ) ;
268- self
283+ pub fn set_gossip_source_p2p ( & self ) {
284+ * self . gossip_source_config . write ( ) . unwrap ( ) = Some ( GossipSourceConfig :: P2PNetwork ) ;
269285 }
270286
271287 /// Configures the [`Node`] instance to source its gossip data from the given RapidGossipSync
272288 /// server.
273- pub fn set_gossip_source_rgs ( & mut self , rgs_server_url : String ) -> & mut Self {
274- self . gossip_source_config = Some ( GossipSourceConfig :: RapidGossipSync ( rgs_server_url) ) ;
275- self
276- }
277-
278- /// Configures the [`Node`] instance to source its wallet entropy from a [BIP 39] mnemonic.
279- ///
280- /// [BIP 39]: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
281- pub fn set_entropy_bip39_mnemonic (
282- & mut self , mnemonic : bip39:: Mnemonic , passphrase : Option < String > ,
283- ) -> & mut Self {
284- self . entropy_source_config =
285- Some ( EntropySourceConfig :: Bip39Mnemonic { mnemonic, passphrase } ) ;
286- self
289+ pub fn set_gossip_source_rgs ( & self , rgs_server_url : String ) {
290+ * self . gossip_source_config . write ( ) . unwrap ( ) =
291+ Some ( GossipSourceConfig :: RapidGossipSync ( rgs_server_url) ) ;
287292 }
288293
289294 /// Sets the used storage directory path.
290295 ///
291296 /// Default: `/tmp/ldk_node/`
292- pub fn set_storage_dir_path ( & mut self , storage_dir_path : String ) -> & mut Self {
293- self . config . storage_dir_path = storage_dir_path ;
294- self
297+ pub fn set_storage_dir_path ( & self , storage_dir_path : String ) {
298+ let mut config = self . config . write ( ) . unwrap ( ) ;
299+ config . storage_dir_path = storage_dir_path ;
295300 }
296301
297302 /// Sets the Esplora server URL.
298303 ///
299304 /// Default: `https://blockstream.info/api`
300- pub fn set_esplora_server_url ( & mut self , esplora_server_url : String ) -> & mut Self {
301- self . config . esplora_server_url = esplora_server_url ;
302- self
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 ;
303308 }
304309
305310 /// Sets the Bitcoin network used.
306- ///
307- /// Options: `mainnet`/`bitcoin`, `testnet`, `regtest`, `signet`
308- ///
309- /// Default: `regtest`
310- pub fn set_network ( & mut self , network : & str ) -> & mut Self {
311- self . config . network = Network :: from_str ( network) . unwrap_or ( Network :: Regtest ) ;
312- self
311+ pub fn set_network ( & self , network : Network ) {
312+ let mut config = self . config . write ( ) . unwrap ( ) ;
313+ config. network = network;
313314 }
314315
315316 /// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
316317 ///
317318 /// Default: `0.0.0.0:9735`
318- pub fn set_listening_address ( & mut self , listening_address : NetAddress ) -> & mut Self {
319- self . config . listening_address = Some ( listening_address ) ;
320- self
319+ pub fn set_listening_address ( & self , listening_address : NetAddress ) {
320+ let mut config = self . config . write ( ) . unwrap ( ) ;
321+ config . listening_address = Some ( listening_address ) ;
321322 }
322323
323324 /// Builds a [`Node`] instance with a [`FilesystemStore`] backend and according to the options
324325 /// previously configured.
325326 pub fn build ( & self ) -> Arc < Node < FilesystemStore > > {
326- let ldk_data_dir = format ! ( "{}/ldk" , self . config. storage_dir_path) ;
327+ let config = self . config . read ( ) . unwrap ( ) ;
328+ let ldk_data_dir = format ! ( "{}/ldk" , config. storage_dir_path) ;
327329 let kv_store = Arc :: new ( FilesystemStore :: new ( ldk_data_dir. clone ( ) . into ( ) ) ) ;
328330 self . build_with_store ( kv_store)
329331 }
@@ -332,7 +334,7 @@ impl Builder {
332334 pub fn build_with_store < K : KVStore + Sync + Send + ' static > (
333335 & self , kv_store : Arc < K > ,
334336 ) -> Arc < Node < K > > {
335- let config = Arc :: new ( self . config . clone ( ) ) ;
337+ let config = Arc :: new ( self . config . read ( ) . unwrap ( ) . clone ( ) ) ;
336338
337339 let ldk_data_dir = format ! ( "{}/ldk" , config. storage_dir_path) ;
338340 fs:: create_dir_all ( ldk_data_dir. clone ( ) ) . expect ( "Failed to create LDK data directory" ) ;
@@ -345,7 +347,9 @@ impl Builder {
345347 let logger = Arc :: new ( FilesystemLogger :: new ( log_file_path) ) ;
346348
347349 // Initialize the on-chain wallet and chain access
348- let seed_bytes = if let Some ( entropy_source_config) = & self . entropy_source_config {
350+ let seed_bytes = if let Some ( entropy_source_config) =
351+ & * self . entropy_source_config . read ( ) . unwrap ( )
352+ {
349353 // Use the configured entropy source, if the user set one.
350354 match entropy_source_config {
351355 EntropySourceConfig :: SeedBytes ( bytes) => bytes. clone ( ) ,
@@ -550,8 +554,9 @@ impl Builder {
550554
551555 // Initialize the GossipSource
552556 // Use the configured gossip source, if the user set one, otherwise default to P2PNetwork.
557+ let gossip_source_config_lock = self . gossip_source_config . read ( ) . unwrap ( ) ;
553558 let gossip_source_config =
554- self . gossip_source_config . as_ref ( ) . unwrap_or ( & GossipSourceConfig :: P2PNetwork ) ;
559+ gossip_source_config_lock . as_ref ( ) . unwrap_or ( & GossipSourceConfig :: P2PNetwork ) ;
555560
556561 let gossip_source = match gossip_source_config {
557562 GossipSourceConfig :: P2PNetwork => {
0 commit comments