Skip to content

Commit b05d04f

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 bd7d098 commit b05d04f

File tree

4 files changed

+72
-46
lines changed

4 files changed

+72
-46
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: 10 additions & 0 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

@@ -182,3 +189,6 @@ typedef string UserChannelId;
182189

183190
[Custom]
184191
typedef string Network;
192+
193+
[Custom]
194+
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();
@@ -142,6 +143,8 @@ use bitcoin::hashes::Hash;
142143
use bitcoin::secp256k1::PublicKey;
143144
use bitcoin::Network;
144145

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

147150
use rand::Rng;
@@ -150,7 +153,6 @@ use std::convert::TryInto;
150153
use std::default::Default;
151154
use std::fs;
152155
use std::net::SocketAddr;
153-
use std::str::FromStr;
154156
use std::sync::atomic::{AtomicBool, Ordering};
155157
use std::sync::{Arc, Mutex, RwLock};
156158
use std::time::{Duration, Instant, SystemTime};
@@ -204,93 +206,93 @@ impl Default for Config {
204206
enum WalletEntropySource {
205207
SeedFile(String),
206208
SeedBytes([u8; WALLET_KEYS_SEED_LEN]),
207-
Bip39Mnemonic { mnemonic: bip39::Mnemonic, passphrase: Option<String> },
209+
Bip39Mnemonic { mnemonic: Mnemonic, passphrase: Option<String> },
208210
}
209211

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

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

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

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

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

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

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

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

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

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

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

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

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

src/types.rs

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

28+
use bip39::Mnemonic;
29+
2830
use std::convert::TryInto;
2931
use std::net::SocketAddr;
3032
use std::str::FromStr;
@@ -401,3 +403,14 @@ pub struct PeerDetails {
401403
/// Indicates whether or not the user is currently has an active connection with the peer.
402404
pub is_connected: bool,
403405
}
406+
407+
impl UniffiCustomTypeConverter for Mnemonic {
408+
type Builtin = String;
409+
fn into_custom(val: Self::Builtin) -> uniffi::Result<Self> {
410+
Ok(Mnemonic::from_str(&val).unwrap())
411+
}
412+
413+
fn from_custom(obj: Self) -> Self::Builtin {
414+
obj.to_string()
415+
}
416+
}

0 commit comments

Comments
 (0)