Skip to content

Commit e39d80c

Browse files
committed
Make wallet entropy configurable
1 parent 55966e7 commit e39d80c

File tree

3 files changed

+50
-13
lines changed

3 files changed

+50
-13
lines changed

Cargo.toml

+1-1
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"]}
19+
bdk = { git = "https://github.com/tnull/bdk", branch="feat/use-external-esplora-client", features = ["use-esplora-ureq", "keys-bip39"]}
2020
bitcoin = "0.28.1"
2121

2222
rand = "0.8.5"

src/io.rs

+6-7
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

+43-5
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ use lightning_invoice::{payment, Currency, Invoice};
7171
use bdk::blockchain::esplora::EsploraBlockchain;
7272
use bdk::blockchain::{GetBlockHash, GetHeight};
7373
use bdk::database::MemoryDatabase;
74+
use bdk::keys::bip39;
7475

7576
use bitcoin::hashes::sha256::Hash as Sha256;
7677
use bitcoin::hashes::Hash;
@@ -115,18 +116,28 @@ pub struct LdkLiteConfig {
115116
pub default_cltv_expiry_delta: u32,
116117
}
117118

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

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

143-
Self { config }
154+
Self { config, wallet_entropy }
144155
}
145156

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

151183
/// Sets the used storage directory path.
@@ -204,8 +236,13 @@ impl LdkLiteBuilder {
204236
let logger = Arc::new(FilesystemLogger::new(log_file_path));
205237

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

210247
let bdk_wallet = bdk::Wallet::new(
211248
bdk::template::Bip84(xprv.clone(), bdk::KeychainKind::External),
@@ -236,7 +273,8 @@ impl LdkLiteBuilder {
236273

237274
// Step 5: Initialize the KeysManager
238275
let cur = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
239-
let keys_manager = Arc::new(KeysManager::new(&seed, cur.as_secs(), cur.subsec_nanos()));
276+
let ldk_seed: [u8; 32] = xprv.private_key.secret_bytes();
277+
let keys_manager = Arc::new(KeysManager::new(&ldk_seed, cur.as_secs(), cur.subsec_nanos()));
240278

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

0 commit comments

Comments
 (0)