Skip to content
Open
25 changes: 21 additions & 4 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ use crate::types::{
GossipSync, Graph, HRNResolver, KeysManager, MessageRouter, OnionMessenger, PaymentStore,
PeerManager, PendingPaymentStore,
};
use crate::wallet::persist::KVStoreWalletPersister;
use crate::wallet::persist::{read_address_pool, KVStoreWalletPersister};
use crate::wallet::Wallet;
use crate::{Node, NodeMetrics, PersistedNodeMetrics};

Expand Down Expand Up @@ -1439,8 +1439,8 @@ fn build_with_store_internal(

let kv_store_ref = Arc::clone(&kv_store);
let logger_ref = Arc::clone(&logger);
let (payment_store_res, node_metris_res, pending_payment_store_res) =
runtime.block_on(async move {
let (payment_store_res, node_metris_res, pending_payment_store_res, address_pool_res) = runtime
.block_on(async move {
tokio::join!(
read_all_objects(
&*kv_store_ref,
Expand All @@ -1454,7 +1454,8 @@ fn build_with_store_internal(
PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
Arc::clone(&logger_ref),
)
),
read_address_pool(&*kv_store_ref, &*logger_ref)
)
});

Expand Down Expand Up @@ -1741,9 +1742,18 @@ fn build_with_store_internal(
},
};

let persisted_pool_indices = match address_pool_res {
Ok(indices) => indices,
Err(e) => {
log_error!(logger, "Failed to read address pool data from store: {}", e);
return Err(BuildError::ReadFailed);
},
};

let wallet = Arc::new(Wallet::new(
bdk_wallet,
wallet_persister,
persisted_pool_indices,
Arc::clone(&tx_broadcaster),
Arc::clone(&fee_estimator),
Arc::clone(&chain_source),
Expand All @@ -1754,6 +1764,13 @@ fn build_with_store_internal(
Arc::clone(&pending_payment_store),
));

// Fill the address pool up front so LDK's sync `SignerProvider` callbacks can hand out
// pre-persisted addresses without waiting on wallet persistence.
runtime.block_on(wallet.refill_address_pool()).map_err(|e| {
log_error!(logger, "Failed to fill the wallet's address pool: {}", e);
BuildError::WalletSetupFailed
})?;

tx_broadcaster.set_wallet(Arc::downgrade(&wallet));

// Initialize the KeysManager
Expand Down
16 changes: 16 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,22 @@ pub const MIN_FULL_SCAN_STOP_GAP: u32 = 1;
/// Values above 1000 are clamped to 1000 when a full scan runs.
pub const MAX_FULL_SCAN_STOP_GAP: u32 = 1000;

/// The number of addresses the node keeps revealed and persisted ahead of use, from which it
/// serves fresh-address requests and channel destination and shutdown scripts.
///
/// Pooled addresses are revealed-but-unused wallet scripts. Addresses are handed out oldest
/// first, which keeps the pool beyond the handed-out addresses, where it cannot hide funds
/// from a full scan's stop gap (e.g. [`EsploraSyncConfig::full_scan_stop_gap`]). A handout
/// that fails while a concurrent one proceeds can briefly leave a pooled address below a
/// handed-out one; such inversions are bounded by the pool size and consumed by the next
/// handouts.
///
/// After a restore from seed, the pool refills from the keychain's first indices before the
/// initial full scan runs, so it can serve addresses a previous installation of the wallet
/// already handed out — possibly even used ones. The cost is address reuse, not fund
/// visibility: the reveals keep the scripts watched and the scan discovers any prior use.
pub const ADDRESS_POOL_SIZE: u32 = 16;

// The number of concurrent requests made against the API provider.
pub(crate) const BDK_CLIENT_CONCURRENCY: usize = 4;

Expand Down
5 changes: 5 additions & 0 deletions src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ pub(crate) const BDK_WALLET_INDEXER_PRIMARY_NAMESPACE: &str = "bdk_wallet";
pub(crate) const BDK_WALLET_INDEXER_SECONDARY_NAMESPACE: &str = "";
pub(crate) const BDK_WALLET_INDEXER_KEY: &str = "indexer";

/// The derivation indices of the wallet's address pool will be persisted under this key.
pub(crate) const BDK_WALLET_ADDRESS_POOL_PRIMARY_NAMESPACE: &str = "bdk_wallet";
pub(crate) const BDK_WALLET_ADDRESS_POOL_SECONDARY_NAMESPACE: &str = "";
pub(crate) const BDK_WALLET_ADDRESS_POOL_KEY: &str = "address_pool";

/// [`StaticInvoice`]s will be persisted under this key.
///
/// [`StaticInvoice`]: lightning::offers::static_invoice::StaticInvoice
Expand Down
Loading
Loading