Skip to content

Commit 5f1a872

Browse files
committed
Prefactor: Move ChainSource creation before Wallet creation
In the following commits we will use the chain source to poll a best tip before intializing the listener objects. As a prefactor, we here move the creation of our onchain wallet after creation of the chain source, which in turn means we'll need to use the same pattern as for the other listeners, i.e., not giving the wallet reference to `ChainSource` on creation but rather handing it in when it's being used at runtime.
1 parent 90e9736 commit 5f1a872

File tree

6 files changed

+150
-141
lines changed

6 files changed

+150
-141
lines changed

src/builder.rs

Lines changed: 57 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,54 +1178,6 @@ fn build_with_store_internal(
11781178
}
11791179
},
11801180
};
1181-
1182-
// Initialize the on-chain wallet and chain access
1183-
let xprv = bitcoin::bip32::Xpriv::new_master(config.network, &seed_bytes).map_err(|e| {
1184-
log_error!(logger, "Failed to derive master secret: {}", e);
1185-
BuildError::InvalidSeedBytes
1186-
})?;
1187-
1188-
let descriptor = Bip84(xprv, KeychainKind::External);
1189-
let change_descriptor = Bip84(xprv, KeychainKind::Internal);
1190-
let mut wallet_persister =
1191-
KVStoreWalletPersister::new(Arc::clone(&kv_store), Arc::clone(&logger));
1192-
let wallet_opt = BdkWallet::load()
1193-
.descriptor(KeychainKind::External, Some(descriptor.clone()))
1194-
.descriptor(KeychainKind::Internal, Some(change_descriptor.clone()))
1195-
.extract_keys()
1196-
.check_network(config.network)
1197-
.load_wallet(&mut wallet_persister)
1198-
.map_err(|e| match e {
1199-
bdk_wallet::LoadWithPersistError::InvalidChangeSet(
1200-
bdk_wallet::LoadError::Mismatch(bdk_wallet::LoadMismatch::Network {
1201-
loaded,
1202-
expected,
1203-
}),
1204-
) => {
1205-
log_error!(
1206-
logger,
1207-
"Failed to setup wallet: Networks do not match. Expected {} but got {}",
1208-
expected,
1209-
loaded
1210-
);
1211-
BuildError::NetworkMismatch
1212-
},
1213-
_ => {
1214-
log_error!(logger, "Failed to set up wallet: {}", e);
1215-
BuildError::WalletSetupFailed
1216-
},
1217-
})?;
1218-
let bdk_wallet = match wallet_opt {
1219-
Some(wallet) => wallet,
1220-
None => BdkWallet::create(descriptor, change_descriptor)
1221-
.network(config.network)
1222-
.create_wallet(&mut wallet_persister)
1223-
.map_err(|e| {
1224-
log_error!(logger, "Failed to set up wallet: {}", e);
1225-
BuildError::WalletSetupFailed
1226-
})?,
1227-
};
1228-
12291181
let tx_broadcaster = Arc::new(TransactionBroadcaster::new(Arc::clone(&logger)));
12301182
let fee_estimator = Arc::new(OnchainFeeEstimator::new());
12311183

@@ -1243,24 +1195,13 @@ fn build_with_store_internal(
12431195
},
12441196
};
12451197

1246-
let wallet = Arc::new(Wallet::new(
1247-
bdk_wallet,
1248-
wallet_persister,
1249-
Arc::clone(&tx_broadcaster),
1250-
Arc::clone(&fee_estimator),
1251-
Arc::clone(&payment_store),
1252-
Arc::clone(&config),
1253-
Arc::clone(&logger),
1254-
));
1255-
12561198
let chain_source = match chain_data_source_config {
12571199
Some(ChainDataSourceConfig::Esplora { server_url, headers, sync_config }) => {
12581200
let sync_config = sync_config.unwrap_or(EsploraSyncConfig::default());
12591201
Arc::new(ChainSource::new_esplora(
12601202
server_url.clone(),
12611203
headers.clone(),
12621204
sync_config,
1263-
Arc::clone(&wallet),
12641205
Arc::clone(&fee_estimator),
12651206
Arc::clone(&tx_broadcaster),
12661207
Arc::clone(&kv_store),
@@ -1274,7 +1215,6 @@ fn build_with_store_internal(
12741215
Arc::new(ChainSource::new_electrum(
12751216
server_url.clone(),
12761217
sync_config,
1277-
Arc::clone(&wallet),
12781218
Arc::clone(&fee_estimator),
12791219
Arc::clone(&tx_broadcaster),
12801220
Arc::clone(&kv_store),
@@ -1295,7 +1235,6 @@ fn build_with_store_internal(
12951235
*rpc_port,
12961236
rpc_user.clone(),
12971237
rpc_password.clone(),
1298-
Arc::clone(&wallet),
12991238
Arc::clone(&fee_estimator),
13001239
Arc::clone(&tx_broadcaster),
13011240
Arc::clone(&kv_store),
@@ -1309,7 +1248,6 @@ fn build_with_store_internal(
13091248
*rpc_port,
13101249
rpc_user.clone(),
13111250
rpc_password.clone(),
1312-
Arc::clone(&wallet),
13131251
Arc::clone(&fee_estimator),
13141252
Arc::clone(&tx_broadcaster),
13151253
Arc::clone(&kv_store),
@@ -1327,7 +1265,6 @@ fn build_with_store_internal(
13271265
server_url.clone(),
13281266
HashMap::new(),
13291267
sync_config,
1330-
Arc::clone(&wallet),
13311268
Arc::clone(&fee_estimator),
13321269
Arc::clone(&tx_broadcaster),
13331270
Arc::clone(&kv_store),
@@ -1338,6 +1275,63 @@ fn build_with_store_internal(
13381275
},
13391276
};
13401277

1278+
// Initialize the on-chain wallet and chain access
1279+
let xprv = bitcoin::bip32::Xpriv::new_master(config.network, &seed_bytes).map_err(|e| {
1280+
log_error!(logger, "Failed to derive master secret: {}", e);
1281+
BuildError::InvalidSeedBytes
1282+
})?;
1283+
1284+
let descriptor = Bip84(xprv, KeychainKind::External);
1285+
let change_descriptor = Bip84(xprv, KeychainKind::Internal);
1286+
let mut wallet_persister =
1287+
KVStoreWalletPersister::new(Arc::clone(&kv_store), Arc::clone(&logger));
1288+
let wallet_opt = BdkWallet::load()
1289+
.descriptor(KeychainKind::External, Some(descriptor.clone()))
1290+
.descriptor(KeychainKind::Internal, Some(change_descriptor.clone()))
1291+
.extract_keys()
1292+
.check_network(config.network)
1293+
.load_wallet(&mut wallet_persister)
1294+
.map_err(|e| match e {
1295+
bdk_wallet::LoadWithPersistError::InvalidChangeSet(
1296+
bdk_wallet::LoadError::Mismatch(bdk_wallet::LoadMismatch::Network {
1297+
loaded,
1298+
expected,
1299+
}),
1300+
) => {
1301+
log_error!(
1302+
logger,
1303+
"Failed to setup wallet: Networks do not match. Expected {} but got {}",
1304+
expected,
1305+
loaded
1306+
);
1307+
BuildError::NetworkMismatch
1308+
},
1309+
_ => {
1310+
log_error!(logger, "Failed to set up wallet: {}", e);
1311+
BuildError::WalletSetupFailed
1312+
},
1313+
})?;
1314+
let bdk_wallet = match wallet_opt {
1315+
Some(wallet) => wallet,
1316+
None => BdkWallet::create(descriptor, change_descriptor)
1317+
.network(config.network)
1318+
.create_wallet(&mut wallet_persister)
1319+
.map_err(|e| {
1320+
log_error!(logger, "Failed to set up wallet: {}", e);
1321+
BuildError::WalletSetupFailed
1322+
})?,
1323+
};
1324+
1325+
let wallet = Arc::new(Wallet::new(
1326+
bdk_wallet,
1327+
wallet_persister,
1328+
Arc::clone(&tx_broadcaster),
1329+
Arc::clone(&fee_estimator),
1330+
Arc::clone(&payment_store),
1331+
Arc::clone(&config),
1332+
Arc::clone(&logger),
1333+
));
1334+
13411335
// Initialize the KeysManager
13421336
let cur_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).map_err(|e| {
13431337
log_error!(logger, "Failed to get current time: {}", e);

src/chain/bitcoind.rs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ pub(super) struct BitcoindChainSource {
4747
api_client: Arc<BitcoindClient>,
4848
header_cache: tokio::sync::Mutex<BoundedHeaderCache>,
4949
latest_chain_tip: RwLock<Option<ValidatedBlockHeader>>,
50-
onchain_wallet: Arc<Wallet>,
5150
wallet_polling_status: Mutex<WalletSyncStatus>,
5251
fee_estimator: Arc<OnchainFeeEstimator>,
5352
kv_store: Arc<DynStore>,
@@ -59,9 +58,8 @@ pub(super) struct BitcoindChainSource {
5958
impl BitcoindChainSource {
6059
pub(crate) fn new_rpc(
6160
rpc_host: String, rpc_port: u16, rpc_user: String, rpc_password: String,
62-
onchain_wallet: Arc<Wallet>, fee_estimator: Arc<OnchainFeeEstimator>,
63-
kv_store: Arc<DynStore>, config: Arc<Config>, logger: Arc<Logger>,
64-
node_metrics: Arc<RwLock<NodeMetrics>>,
61+
fee_estimator: Arc<OnchainFeeEstimator>, kv_store: Arc<DynStore>, config: Arc<Config>,
62+
logger: Arc<Logger>, node_metrics: Arc<RwLock<NodeMetrics>>,
6563
) -> Self {
6664
let api_client = Arc::new(BitcoindClient::new_rpc(
6765
rpc_host.clone(),
@@ -77,7 +75,6 @@ impl BitcoindChainSource {
7775
api_client,
7876
header_cache,
7977
latest_chain_tip,
80-
onchain_wallet,
8178
wallet_polling_status,
8279
fee_estimator,
8380
kv_store,
@@ -89,9 +86,9 @@ impl BitcoindChainSource {
8986

9087
pub(crate) fn new_rest(
9188
rpc_host: String, rpc_port: u16, rpc_user: String, rpc_password: String,
92-
onchain_wallet: Arc<Wallet>, fee_estimator: Arc<OnchainFeeEstimator>,
93-
kv_store: Arc<DynStore>, config: Arc<Config>, rest_client_config: BitcoindRestClientConfig,
94-
logger: Arc<Logger>, node_metrics: Arc<RwLock<NodeMetrics>>,
89+
fee_estimator: Arc<OnchainFeeEstimator>, kv_store: Arc<DynStore>, config: Arc<Config>,
90+
rest_client_config: BitcoindRestClientConfig, logger: Arc<Logger>,
91+
node_metrics: Arc<RwLock<NodeMetrics>>,
9592
) -> Self {
9693
let api_client = Arc::new(BitcoindClient::new_rest(
9794
rest_client_config.rest_host,
@@ -111,7 +108,6 @@ impl BitcoindChainSource {
111108
header_cache,
112109
latest_chain_tip,
113110
wallet_polling_status,
114-
onchain_wallet,
115111
fee_estimator,
116112
kv_store,
117113
config,
@@ -126,8 +122,8 @@ impl BitcoindChainSource {
126122

127123
pub(super) async fn continuously_sync_wallets(
128124
&self, mut stop_sync_receiver: tokio::sync::watch::Receiver<()>,
129-
channel_manager: Arc<ChannelManager>, chain_monitor: Arc<ChainMonitor>,
130-
output_sweeper: Arc<Sweeper>,
125+
onchain_wallet: Arc<Wallet>, channel_manager: Arc<ChannelManager>,
126+
chain_monitor: Arc<ChainMonitor>, output_sweeper: Arc<Sweeper>,
131127
) {
132128
// First register for the wallet polling status to make sure `Node::sync_wallets` calls
133129
// wait on the result before proceeding.
@@ -155,14 +151,10 @@ impl BitcoindChainSource {
155151

156152
let channel_manager_best_block_hash = channel_manager.current_best_block().block_hash;
157153
let sweeper_best_block_hash = output_sweeper.current_best_block().block_hash;
158-
let onchain_wallet_best_block_hash =
159-
self.onchain_wallet.current_best_block().block_hash;
154+
let onchain_wallet_best_block_hash = onchain_wallet.current_best_block().block_hash;
160155

161156
let mut chain_listeners = vec![
162-
(
163-
onchain_wallet_best_block_hash,
164-
&*self.onchain_wallet as &(dyn Listen + Send + Sync),
165-
),
157+
(onchain_wallet_best_block_hash, &*onchain_wallet as &(dyn Listen + Send + Sync)),
166158
(channel_manager_best_block_hash, &*channel_manager as &(dyn Listen + Send + Sync)),
167159
(sweeper_best_block_hash, &*output_sweeper as &(dyn Listen + Send + Sync)),
168160
];
@@ -307,6 +299,7 @@ impl BitcoindChainSource {
307299
return;
308300
}
309301
_ = self.poll_and_update_listeners(
302+
Arc::clone(&onchain_wallet),
310303
Arc::clone(&channel_manager),
311304
Arc::clone(&chain_monitor),
312305
Arc::clone(&output_sweeper)
@@ -337,8 +330,8 @@ impl BitcoindChainSource {
337330
}
338331

339332
pub(super) async fn poll_and_update_listeners(
340-
&self, channel_manager: Arc<ChannelManager>, chain_monitor: Arc<ChainMonitor>,
341-
output_sweeper: Arc<Sweeper>,
333+
&self, onchain_wallet: Arc<Wallet>, channel_manager: Arc<ChannelManager>,
334+
chain_monitor: Arc<ChainMonitor>, output_sweeper: Arc<Sweeper>,
342335
) -> Result<(), Error> {
343336
let receiver_res = {
344337
let mut status_lock = self.wallet_polling_status.lock().unwrap();
@@ -355,7 +348,12 @@ impl BitcoindChainSource {
355348
}
356349

357350
let res = self
358-
.poll_and_update_listeners_inner(channel_manager, chain_monitor, output_sweeper)
351+
.poll_and_update_listeners_inner(
352+
onchain_wallet,
353+
channel_manager,
354+
chain_monitor,
355+
output_sweeper,
356+
)
359357
.await;
360358

361359
self.wallet_polling_status.lock().unwrap().propagate_result_to_subscribers(res);
@@ -364,8 +362,8 @@ impl BitcoindChainSource {
364362
}
365363

366364
async fn poll_and_update_listeners_inner(
367-
&self, channel_manager: Arc<ChannelManager>, chain_monitor: Arc<ChainMonitor>,
368-
output_sweeper: Arc<Sweeper>,
365+
&self, onchain_wallet: Arc<Wallet>, channel_manager: Arc<ChannelManager>,
366+
chain_monitor: Arc<ChainMonitor>, output_sweeper: Arc<Sweeper>,
369367
) -> Result<(), Error> {
370368
let latest_chain_tip_opt = self.latest_chain_tip.read().unwrap().clone();
371369
let chain_tip = if let Some(tip) = latest_chain_tip_opt {
@@ -386,7 +384,7 @@ impl BitcoindChainSource {
386384
let mut locked_header_cache = self.header_cache.lock().await;
387385
let chain_poller = ChainPoller::new(Arc::clone(&self.api_client), self.config.network);
388386
let chain_listener = ChainListener {
389-
onchain_wallet: Arc::clone(&self.onchain_wallet),
387+
onchain_wallet: Arc::clone(&onchain_wallet),
390388
channel_manager: Arc::clone(&channel_manager),
391389
chain_monitor: Arc::clone(&chain_monitor),
392390
output_sweeper,
@@ -422,7 +420,7 @@ impl BitcoindChainSource {
422420
let cur_height = channel_manager.current_best_block().height;
423421

424422
let now = SystemTime::now();
425-
let bdk_unconfirmed_txids = self.onchain_wallet.get_unconfirmed_txids();
423+
let bdk_unconfirmed_txids = onchain_wallet.get_unconfirmed_txids();
426424
match self
427425
.api_client
428426
.get_updated_mempool_transactions(cur_height, bdk_unconfirmed_txids)
@@ -436,11 +434,11 @@ impl BitcoindChainSource {
436434
evicted_txids.len(),
437435
now.elapsed().unwrap().as_millis()
438436
);
439-
self.onchain_wallet
440-
.apply_mempool_txs(unconfirmed_txs, evicted_txids)
441-
.unwrap_or_else(|e| {
437+
onchain_wallet.apply_mempool_txs(unconfirmed_txs, evicted_txids).unwrap_or_else(
438+
|e| {
442439
log_error!(self.logger, "Failed to apply mempool transactions: {:?}", e);
443-
});
440+
},
441+
);
444442
},
445443
Err(e) => {
446444
log_error!(self.logger, "Failed to poll for mempool transactions: {:?}", e);

0 commit comments

Comments
 (0)