Skip to content

Commit fc51b39

Browse files
committed
Make wallet entropy configurable
1 parent fdabd21 commit fc51b39

File tree

3 files changed

+50
-13
lines changed

3 files changed

+50
-13
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ lightning-background-processor = { version = "0.0.110" }
1616
lightning-rapid-gossip-sync = { version = "0.0.110" }
1717

1818
#bdk = "0.20.0"
19-
bdk = { git = "https://github.com/tnull/bdk", branch="feat/use-external-esplora-client", features = ["use-esplora-ureq", "key-value-db"]}
19+
bdk = { git = "https://github.com/tnull/bdk", branch="feat/use-external-esplora-client", features = ["use-esplora-ureq", "key-value-db", "keys-bip39"]}
2020
bitcoin = "0.28.1"
2121

2222
rand = "0.8.5"

src/io.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,17 @@ use std::io::{BufRead, BufReader, Write};
1616
use std::net::SocketAddr;
1717
use std::sync::Arc;
1818

19-
pub(crate) fn read_or_generate_seed_file(config: Arc<LdkLiteConfig>) -> Result<[u8; 32], Error> {
20-
let keys_seed_path = format!("{}/keys_seed", config.storage_dir_path);
21-
let keys_seed = if let Ok(seed) = fs::read(keys_seed_path.clone()) {
22-
assert_eq!(seed.len(), 32);
23-
let mut key = [0; 32];
19+
pub(crate) fn read_or_generate_seed_file(seed_path: String) -> Result<[u8; 64], Error> {
20+
let keys_seed = if let Ok(seed) = fs::read(seed_path.clone()) {
21+
assert_eq!(seed.len(), 64);
22+
let mut key = [0; 64];
2423
key.copy_from_slice(&seed);
2524
key
2625
} else {
27-
let mut key = [0; 32];
26+
let mut key = [0; 64];
2827
thread_rng().fill_bytes(&mut key);
2928

30-
let mut f = fs::File::create(keys_seed_path.clone()).map_err(|e| Error::StdIo(e))?;
29+
let mut f = fs::File::create(seed_path.clone()).map_err(|e| Error::StdIo(e))?;
3130
f.write_all(&key).expect("Failed to write node keys seed to disk");
3231
f.sync_all().expect("Failed to sync node keys seed to disk");
3332
key

src/lib.rs

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ use bdk::blockchain::esplora::EsploraBlockchain;
7373
use bdk::blockchain::{GetBlockHash, GetHeight};
7474
use bdk::sled;
7575
use bdk::template::Bip84;
76+
use bdk::keys::bip39;
7677

7778
use bitcoin::hashes::sha256::Hash as Sha256;
7879
use bitcoin::hashes::Hash;
@@ -114,18 +115,28 @@ pub struct LdkLiteConfig {
114115
pub default_cltv_expiry_delta: u32,
115116
}
116117

118+
#[derive(Debug, Clone)]
119+
enum LdkLiteWalletEntropy {
120+
SeedFile(String),
121+
SeedBytes([u8; 64]),
122+
Bip39Mnemonic(bip39::Mnemonic),
123+
}
124+
117125
/// A builder for an [`LdkLite`] instance, allowing to set some configuration and module choices from
118126
/// the getgo.
119127
#[derive(Debug, Clone)]
120128
pub struct LdkLiteBuilder {
121129
config: LdkLiteConfig,
130+
wallet_entropy: LdkLiteWalletEntropy,
122131
}
123132

124133
impl LdkLiteBuilder {
125134
/// Creates a new builder instance with the default configuration.
126135
pub fn new() -> Self {
127136
// Set the config defaults
128137
let storage_dir_path = "/tmp/ldk_lite/".to_string();
138+
let seed_path = format!("{}/keys_seed", storage_dir_path);
139+
let wallet_entropy = LdkLiteWalletEntropy::SeedFile(seed_path);
129140
let esplora_server_url = "https://blockstream.info/api".to_string();
130141
let network = bitcoin::Network::Testnet;
131142
let listening_port = 9735;
@@ -139,12 +150,33 @@ impl LdkLiteBuilder {
139150
default_cltv_expiry_delta,
140151
};
141152

142-
Self { config }
153+
Self { config, wallet_entropy }
143154
}
144155

145156
/// Creates a new builder instance from an [`LdkLiteConfig`].
146157
pub fn from_config(config: LdkLiteConfig) -> Self {
147-
Self { config }
158+
let seed_path = format!("{}/keys_seed", config.storage_dir_path);
159+
let wallet_entropy = LdkLiteWalletEntropy::SeedFile(seed_path);
160+
Self { config, wallet_entropy }
161+
}
162+
163+
/// Configures [`LdkLite`] to source its wallet entropy from a seed file on disk.
164+
pub fn set_entropy_seed_path(&mut self, seed_path: String) -> &mut Self {
165+
self.wallet_entropy = LdkLiteWalletEntropy::SeedFile(seed_path);
166+
self
167+
}
168+
169+
/// Configures [`LdkLite`] to source its wallet entropy from a [`Bip39`] mnemonic code.
170+
pub fn set_entropy_bip39_mnemonic(&mut self, mnemonic_str: String) -> &mut Self {
171+
let mnemonic = bip39::Mnemonic::from_str(mnemonic_str).unwrap();
172+
self.wallet_entropy = LdkLiteWalletEntropy::Bip39Mnemonic(mnemonic);
173+
self
174+
}
175+
176+
/// Configures [`LdkLite`] to source its wallet entropy from the given seed bytes.
177+
pub fn set_entropy_seed_bytes(&mut self, seed_bytes: [u8; 64]) -> &mut Self {
178+
self.wallet_entropy = LdkLiteWalletEntropy::SeedBytes(seed_bytes);
179+
self
148180
}
149181

150182
/// Sets the used storage directory path.
@@ -203,8 +235,13 @@ impl LdkLiteBuilder {
203235
let logger = Arc::new(FilesystemLogger::new(log_file_path));
204236

205237
// Step 1: Initialize the on-chain wallet and chain access
206-
let seed = io::read_or_generate_seed_file(Arc::clone(&config))?;
207-
let xprv = bitcoin::util::bip32::ExtendedPrivKey::new_master(config.network, &seed)?;
238+
let seed_bytes = match self.wallet_entropy {
239+
LdkLiteWalletEntropy::SeedBytes(bytes) => bytes,
240+
LdkLiteWalletEntropy::SeedFile(seed_path) => io::read_or_generate_seed_file(seed_path)?,
241+
LdkLiteWalletEntropy::Bip39Mnemonic(mnemonic) => mnemonic.to_seed(),
242+
};
243+
244+
let xprv = bitcoin::util::bip32::ExtendedPrivKey::new_master(config.network, &seed_bytes)?;
208245

209246
let wallet_name = bdk::wallet::wallet_name_from_descriptor(
210247
Bip84(xprv.clone(), bdk::KeychainKind::External),
@@ -244,7 +281,8 @@ impl LdkLiteBuilder {
244281

245282
// Step 5: Initialize the KeysManager
246283
let cur = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
247-
let keys_manager = Arc::new(KeysManager::new(&seed, cur.as_secs(), cur.subsec_nanos()));
284+
let ldk_seed: [u8; 32] = xprv.private_key.secret_bytes();
285+
let keys_manager = Arc::new(KeysManager::new(&ldk_seed, cur.as_secs(), cur.subsec_nanos()));
248286

249287
// Step 6: Read ChannelMonitor state from disk
250288
let mut channel_monitors = persister.read_channelmonitors(keys_manager.clone())?;

0 commit comments

Comments
 (0)