Skip to content

Commit f641845

Browse files
authored
Merge pull request #706 from tnull/2025-11-poll-tip-on-init
`bitcoind` chain source: Poll tip before intialization
2 parents 90e9736 + c0880d9 commit f641845

File tree

6 files changed

+254
-205
lines changed

6 files changed

+254
-205
lines changed

src/builder.rs

Lines changed: 117 additions & 101 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,45 +1195,33 @@ 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-
1256-
let chain_source = match chain_data_source_config {
1198+
let (chain_source, chain_tip_opt) = match chain_data_source_config {
12571199
Some(ChainDataSourceConfig::Esplora { server_url, headers, sync_config }) => {
12581200
let sync_config = sync_config.unwrap_or(EsploraSyncConfig::default());
1259-
Arc::new(ChainSource::new_esplora(
1201+
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),
12671208
Arc::clone(&config),
12681209
Arc::clone(&logger),
12691210
Arc::clone(&node_metrics),
1270-
))
1211+
)
12711212
},
12721213
Some(ChainDataSourceConfig::Electrum { server_url, sync_config }) => {
12731214
let sync_config = sync_config.unwrap_or(ElectrumSyncConfig::default());
1274-
Arc::new(ChainSource::new_electrum(
1215+
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),
12811221
Arc::clone(&config),
12821222
Arc::clone(&logger),
12831223
Arc::clone(&node_metrics),
1284-
))
1224+
)
12851225
},
12861226
Some(ChainDataSourceConfig::Bitcoind {
12871227
rpc_host,
@@ -1290,53 +1230,132 @@ fn build_with_store_internal(
12901230
rpc_password,
12911231
rest_client_config,
12921232
}) => match rest_client_config {
1293-
Some(rest_client_config) => Arc::new(ChainSource::new_bitcoind_rest(
1294-
rpc_host.clone(),
1295-
*rpc_port,
1296-
rpc_user.clone(),
1297-
rpc_password.clone(),
1298-
Arc::clone(&wallet),
1299-
Arc::clone(&fee_estimator),
1300-
Arc::clone(&tx_broadcaster),
1301-
Arc::clone(&kv_store),
1302-
Arc::clone(&config),
1303-
rest_client_config.clone(),
1304-
Arc::clone(&logger),
1305-
Arc::clone(&node_metrics),
1306-
)),
1307-
None => Arc::new(ChainSource::new_bitcoind_rpc(
1308-
rpc_host.clone(),
1309-
*rpc_port,
1310-
rpc_user.clone(),
1311-
rpc_password.clone(),
1312-
Arc::clone(&wallet),
1313-
Arc::clone(&fee_estimator),
1314-
Arc::clone(&tx_broadcaster),
1315-
Arc::clone(&kv_store),
1316-
Arc::clone(&config),
1317-
Arc::clone(&logger),
1318-
Arc::clone(&node_metrics),
1319-
)),
1233+
Some(rest_client_config) => runtime.block_on(async {
1234+
ChainSource::new_bitcoind_rest(
1235+
rpc_host.clone(),
1236+
*rpc_port,
1237+
rpc_user.clone(),
1238+
rpc_password.clone(),
1239+
Arc::clone(&fee_estimator),
1240+
Arc::clone(&tx_broadcaster),
1241+
Arc::clone(&kv_store),
1242+
Arc::clone(&config),
1243+
rest_client_config.clone(),
1244+
Arc::clone(&logger),
1245+
Arc::clone(&node_metrics),
1246+
)
1247+
.await
1248+
}),
1249+
None => runtime.block_on(async {
1250+
ChainSource::new_bitcoind_rpc(
1251+
rpc_host.clone(),
1252+
*rpc_port,
1253+
rpc_user.clone(),
1254+
rpc_password.clone(),
1255+
Arc::clone(&fee_estimator),
1256+
Arc::clone(&tx_broadcaster),
1257+
Arc::clone(&kv_store),
1258+
Arc::clone(&config),
1259+
Arc::clone(&logger),
1260+
Arc::clone(&node_metrics),
1261+
)
1262+
.await
1263+
}),
13201264
},
13211265

13221266
None => {
13231267
// Default to Esplora client.
13241268
let server_url = DEFAULT_ESPLORA_SERVER_URL.to_string();
13251269
let sync_config = EsploraSyncConfig::default();
1326-
Arc::new(ChainSource::new_esplora(
1270+
ChainSource::new_esplora(
13271271
server_url.clone(),
13281272
HashMap::new(),
13291273
sync_config,
1330-
Arc::clone(&wallet),
13311274
Arc::clone(&fee_estimator),
13321275
Arc::clone(&tx_broadcaster),
13331276
Arc::clone(&kv_store),
13341277
Arc::clone(&config),
13351278
Arc::clone(&logger),
13361279
Arc::clone(&node_metrics),
1337-
))
1280+
)
13381281
},
13391282
};
1283+
let chain_source = Arc::new(chain_source);
1284+
1285+
// Initialize the on-chain wallet and chain access
1286+
let xprv = bitcoin::bip32::Xpriv::new_master(config.network, &seed_bytes).map_err(|e| {
1287+
log_error!(logger, "Failed to derive master secret: {}", e);
1288+
BuildError::InvalidSeedBytes
1289+
})?;
1290+
1291+
let descriptor = Bip84(xprv, KeychainKind::External);
1292+
let change_descriptor = Bip84(xprv, KeychainKind::Internal);
1293+
let mut wallet_persister =
1294+
KVStoreWalletPersister::new(Arc::clone(&kv_store), Arc::clone(&logger));
1295+
let wallet_opt = BdkWallet::load()
1296+
.descriptor(KeychainKind::External, Some(descriptor.clone()))
1297+
.descriptor(KeychainKind::Internal, Some(change_descriptor.clone()))
1298+
.extract_keys()
1299+
.check_network(config.network)
1300+
.load_wallet(&mut wallet_persister)
1301+
.map_err(|e| match e {
1302+
bdk_wallet::LoadWithPersistError::InvalidChangeSet(
1303+
bdk_wallet::LoadError::Mismatch(bdk_wallet::LoadMismatch::Network {
1304+
loaded,
1305+
expected,
1306+
}),
1307+
) => {
1308+
log_error!(
1309+
logger,
1310+
"Failed to setup wallet: Networks do not match. Expected {} but got {}",
1311+
expected,
1312+
loaded
1313+
);
1314+
BuildError::NetworkMismatch
1315+
},
1316+
_ => {
1317+
log_error!(logger, "Failed to set up wallet: {}", e);
1318+
BuildError::WalletSetupFailed
1319+
},
1320+
})?;
1321+
let bdk_wallet = match wallet_opt {
1322+
Some(wallet) => wallet,
1323+
None => {
1324+
let mut wallet = BdkWallet::create(descriptor, change_descriptor)
1325+
.network(config.network)
1326+
.create_wallet(&mut wallet_persister)
1327+
.map_err(|e| {
1328+
log_error!(logger, "Failed to set up wallet: {}", e);
1329+
BuildError::WalletSetupFailed
1330+
})?;
1331+
1332+
if let Some(best_block) = chain_tip_opt {
1333+
// Insert the first checkpoint if we have it, to avoid resyncing from genesis.
1334+
// TODO: Use a proper wallet birthday once BDK supports it.
1335+
let mut latest_checkpoint = wallet.latest_checkpoint();
1336+
let block_id =
1337+
bdk_chain::BlockId { height: best_block.height, hash: best_block.block_hash };
1338+
latest_checkpoint = latest_checkpoint.insert(block_id);
1339+
let update =
1340+
bdk_wallet::Update { chain: Some(latest_checkpoint), ..Default::default() };
1341+
wallet.apply_update(update).map_err(|e| {
1342+
log_error!(logger, "Failed to apply checkpoint during wallet setup: {}", e);
1343+
BuildError::WalletSetupFailed
1344+
})?;
1345+
}
1346+
wallet
1347+
},
1348+
};
1349+
1350+
let wallet = Arc::new(Wallet::new(
1351+
bdk_wallet,
1352+
wallet_persister,
1353+
Arc::clone(&tx_broadcaster),
1354+
Arc::clone(&fee_estimator),
1355+
Arc::clone(&payment_store),
1356+
Arc::clone(&config),
1357+
Arc::clone(&logger),
1358+
));
13401359

13411360
// Initialize the KeysManager
13421361
let cur_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).map_err(|e| {
@@ -1505,13 +1524,10 @@ fn build_with_store_internal(
15051524
channel_manager
15061525
} else {
15071526
// We're starting a fresh node.
1508-
let genesis_block_hash =
1509-
bitcoin::blockdata::constants::genesis_block(config.network).block_hash();
1527+
let best_block =
1528+
chain_tip_opt.unwrap_or_else(|| BestBlock::from_network(config.network));
15101529

1511-
let chain_params = ChainParameters {
1512-
network: config.network.into(),
1513-
best_block: BestBlock::new(genesis_block_hash, 0),
1514-
};
1530+
let chain_params = ChainParameters { network: config.network.into(), best_block };
15151531
channelmanager::ChannelManager::new(
15161532
Arc::clone(&fee_estimator),
15171533
Arc::clone(&chain_monitor),

0 commit comments

Comments
 (0)