Skip to content

Commit 96a70ae

Browse files
committed
Break builder pattern and expose setters via bindings
Unfortunately there is no good way of exposing the builder pattern via Uniffi bindings currenlty. We therefore resort to internal mutability and using setters on the `Builder` object.
1 parent 057fcf3 commit 96a70ae

File tree

4 files changed

+74
-48
lines changed

4 files changed

+74
-48
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ The primary abstraction of the library is the `Node`, which can be retrieved by
1111
use ldk_node::Builder;
1212
use ldk_node::lightning_invoice::Invoice;
1313
use ldk_node::bitcoin::secp256k1::PublicKey;
14+
use ldk_node::bitcoin::Network;
1415
use std::str::FromStr;
1516

1617
fn main() {
17-
let node = Builder::new()
18-
.set_network("testnet")
19-
.set_esplora_server_url("https://blockstream.info/testnet/api".to_string())
20-
.build();
18+
let mut builder = Builder::new();
19+
builder.set_network(Network::Testnet);
20+
builder.set_esplora_server_url("https://blockstream.info/testnet/api".to_string())
2121

22+
let node = builder.build();
2223
node.start().unwrap();
2324

2425
let _funding_address = node.new_funding_address();

bindings/ldk_node.udl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ interface Builder {
1313
constructor();
1414
[Name=from_config]
1515
constructor(Config config);
16+
void set_entropy_seed_path(string seed_path);
17+
void set_entropy_seed_bytes(sequence<u8> seed_bytes);
18+
void set_entropy_bip39_mnemonic(Mnemonic mnemonic, string? passphrase);
19+
void set_storage_dir_path(string storage_dir_path);
20+
void set_esplora_server_url(string esplora_server_url);
21+
void set_network(Network network);
22+
void set_listening_address(SocketAddr listening_address);
1623
Node build();
1724
};
1825

@@ -119,8 +126,8 @@ dictionary PaymentDetails {
119126
};
120127

121128
dictionary OutPoint {
122-
Txid txid;
123-
u32 vout;
129+
Txid txid;
130+
u32 vout;
124131
};
125132

126133
[Custom]
@@ -155,3 +162,6 @@ typedef string UserChannelId;
155162

156163
[Custom]
157164
typedef string Network;
165+
166+
[Custom]
167+
typedef string Mnemonic;

src/lib.rs

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@
2929
//! use ldk_node::Builder;
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();
@@ -143,6 +144,8 @@ use bitcoin::hashes::Hash;
143144
use bitcoin::secp256k1::PublicKey;
144145
use bitcoin::Network;
145146

147+
use bip39::Mnemonic;
148+
146149
use bitcoin::{Address, BlockHash, OutPoint, Txid};
147150

148151
use rand::Rng;
@@ -151,7 +154,6 @@ use std::convert::TryInto;
151154
use std::default::Default;
152155
use std::fs;
153156
use std::net::SocketAddr;
154-
use std::str::FromStr;
155157
use std::sync::atomic::{AtomicBool, Ordering};
156158
use std::sync::{Arc, Mutex, RwLock};
157159
use std::time::{Duration, Instant, SystemTime};
@@ -205,93 +207,93 @@ impl Default for Config {
205207
enum WalletEntropySource {
206208
SeedFile(String),
207209
SeedBytes([u8; WALLET_KEYS_SEED_LEN]),
208-
Bip39Mnemonic { mnemonic: bip39::Mnemonic, passphrase: Option<String> },
210+
Bip39Mnemonic { mnemonic: Mnemonic, passphrase: Option<String> },
209211
}
210212

211213
/// A builder for an [`Node`] instance, allowing to set some configuration and module choices from
212214
/// the getgo.
213-
#[derive(Debug, Clone)]
215+
#[derive(Debug)]
214216
pub struct Builder {
215-
config: Config,
216-
entropy_source: Option<WalletEntropySource>,
217+
config: Mutex<Config>,
218+
entropy_source: Mutex<Option<WalletEntropySource>>,
217219
}
218220

219221
impl Builder {
220222
/// Creates a new builder instance with the default configuration.
221223
pub fn new() -> Self {
222-
let config = Config::default();
223-
let entropy_source = None;
224+
let config = Mutex::new(Config::default());
225+
let entropy_source = Mutex::new(None);
224226
Self { config, entropy_source }
225227
}
226228

227229
/// Creates a new builder instance from an [`Config`].
228230
pub fn from_config(config: Config) -> Self {
229-
let entropy_source = None;
231+
let config = Mutex::new(config);
232+
let entropy_source = Mutex::new(None);
230233
Self { config, entropy_source }
231234
}
232235

233236
/// Configures the [`Node`] instance to source its wallet entropy from a seed file on disk.
234237
///
235238
/// If the given file does not exist a new random seed file will be generated and
236239
/// stored at the given location.
237-
pub fn set_entropy_seed_path(&mut self, seed_path: String) -> &mut Self {
238-
self.entropy_source = Some(WalletEntropySource::SeedFile(seed_path));
239-
self
240+
pub fn set_entropy_seed_path(&self, seed_path: String) {
241+
*self.entropy_source.lock().unwrap() = Some(WalletEntropySource::SeedFile(seed_path));
240242
}
241243

242-
/// Configures the [`Node`] instance to source its wallet entropy from the given seed bytes.
243-
pub fn set_entropy_seed_bytes(&mut self, seed_bytes: [u8; WALLET_KEYS_SEED_LEN]) -> &mut Self {
244-
self.entropy_source = Some(WalletEntropySource::SeedBytes(seed_bytes));
245-
self
244+
/// Configures the [`Node`] instance to source its wallet entropy from the given 64 seed bytes.
245+
///
246+
/// **Note:** Panics if the length of the given `seed_bytes` differs from 64.
247+
pub fn set_entropy_seed_bytes(&self, seed_bytes: Vec<u8>) {
248+
if seed_bytes.len() != WALLET_KEYS_SEED_LEN {
249+
panic!("Failed to set seed due to invalid length.");
250+
}
251+
let mut bytes = [0u8; WALLET_KEYS_SEED_LEN];
252+
bytes.copy_from_slice(&seed_bytes);
253+
*self.entropy_source.lock().unwrap() = Some(WalletEntropySource::SeedBytes(bytes));
246254
}
247255

248256
/// Configures the [`Node`] instance to source its wallet entropy from a [BIP 39] mnemonic.
249257
///
250258
/// [BIP 39]: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
251-
pub fn set_entropy_bip39_mnemonic(
252-
&mut self, mnemonic: bip39::Mnemonic, passphrase: Option<String>,
253-
) -> &mut Self {
254-
self.entropy_source = Some(WalletEntropySource::Bip39Mnemonic { mnemonic, passphrase });
255-
self
259+
pub fn set_entropy_bip39_mnemonic(&self, mnemonic: Mnemonic, passphrase: Option<String>) {
260+
*self.entropy_source.lock().unwrap() =
261+
Some(WalletEntropySource::Bip39Mnemonic { mnemonic, passphrase });
256262
}
257263

258264
/// Sets the used storage directory path.
259265
///
260266
/// Default: `/tmp/ldk_node/`
261-
pub fn set_storage_dir_path(&mut self, storage_dir_path: String) -> &mut Self {
262-
self.config.storage_dir_path = storage_dir_path;
263-
self
267+
pub fn set_storage_dir_path(&self, storage_dir_path: String) {
268+
let mut config = self.config.lock().unwrap();
269+
config.storage_dir_path = storage_dir_path;
264270
}
265271

266272
/// Sets the Esplora server URL.
267273
///
268274
/// Default: `https://blockstream.info/api`
269-
pub fn set_esplora_server_url(&mut self, esplora_server_url: String) -> &mut Self {
270-
self.config.esplora_server_url = esplora_server_url;
271-
self
275+
pub fn set_esplora_server_url(&self, esplora_server_url: String) {
276+
let mut config = self.config.lock().unwrap();
277+
config.esplora_server_url = esplora_server_url;
272278
}
273279

274280
/// Sets the Bitcoin network used.
275-
///
276-
/// Options: `mainnet`/`bitcoin`, `testnet`, `regtest`, `signet`
277-
///
278-
/// Default: `regtest`
279-
pub fn set_network(&mut self, network: &str) -> &mut Self {
280-
self.config.network = Network::from_str(network).unwrap_or(Network::Regtest);
281-
self
281+
pub fn set_network(&self, network: Network) {
282+
let mut config = self.config.lock().unwrap();
283+
config.network = network;
282284
}
283285

284286
/// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
285287
///
286288
/// Default: `0.0.0.0:9735`
287-
pub fn set_listening_address(&mut self, listening_address: SocketAddr) -> &mut Self {
288-
self.config.listening_address = Some(listening_address);
289-
self
289+
pub fn set_listening_address(&self, listening_address: SocketAddr) {
290+
let mut config = self.config.lock().unwrap();
291+
config.listening_address = Some(listening_address);
290292
}
291293

292294
/// Builds a [`Node`] instance according to the options previously configured.
293295
pub fn build(&self) -> Arc<Node> {
294-
let config = Arc::new(self.config.clone());
296+
let config = Arc::new(self.config.lock().unwrap().clone());
295297

296298
let ldk_data_dir = format!("{}/ldk", config.storage_dir_path);
297299
fs::create_dir_all(ldk_data_dir.clone()).expect("Failed to create LDK data directory");
@@ -304,7 +306,7 @@ impl Builder {
304306
let logger = Arc::new(FilesystemLogger::new(log_file_path));
305307

306308
// Initialize the on-chain wallet and chain access
307-
let seed_bytes = if let Some(entropy_source) = &self.entropy_source {
309+
let seed_bytes = if let Some(entropy_source) = &*self.entropy_source.lock().unwrap() {
308310
// Use the configured entropy source, if the user set one.
309311
match entropy_source {
310312
WalletEntropySource::SeedBytes(bytes) => bytes.clone(),

src/types.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ use bitcoin::hashes::Hash;
2424
use bitcoin::secp256k1::PublicKey;
2525
use bitcoin::{Address, Network, Txid};
2626

27+
use bip39::Mnemonic;
28+
2729
use std::convert::TryInto;
2830
use std::net::SocketAddr;
2931
use std::str::FromStr;
@@ -290,3 +292,14 @@ impl UniffiCustomTypeConverter for Txid {
290292
obj.to_string()
291293
}
292294
}
295+
296+
impl UniffiCustomTypeConverter for Mnemonic {
297+
type Builtin = String;
298+
fn into_custom(val: Self::Builtin) -> uniffi::Result<Self> {
299+
Ok(Mnemonic::from_str(&val).unwrap())
300+
}
301+
302+
fn from_custom(obj: Self) -> Self::Builtin {
303+
obj.to_string()
304+
}
305+
}

0 commit comments

Comments
 (0)