Skip to content

Commit 817e764

Browse files
committed
test(cbf): strengthen wait_for_cbf_sync with state verification
The old wait_for_cbf_sync only checked that the onchain sync timestamp advanced, which could false-pass when the timestamp updated but wallet state was still stale. The new version verifies both onchain and lightning wallet syncs completed, and accepts a check closure so callers can assert concrete wallet state (e.g. balance, payment existence). Also simplifies CbfSyncConfig in test setup to use Default (which already sets required_peers: 1 and reasonable timeouts).
1 parent 17378e3 commit 817e764

File tree

2 files changed

+57
-30
lines changed

2 files changed

+57
-30
lines changed

tests/common/mod.rs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ use electrsd::{corepc_node, ElectrsD};
3131
use electrum_client::ElectrumApi;
3232
use ldk_node::config::{
3333
AsyncPaymentsRole, CbfSyncConfig, Config, ElectrumSyncConfig, EsploraSyncConfig,
34-
SyncTimeoutsConfig,
3534
};
3635
use ldk_node::entropy::{generate_entropy_mnemonic, NodeEntropy};
3736
use ldk_node::io::sqlite_store::SqliteStore;
@@ -499,19 +498,7 @@ pub(crate) fn setup_node(chain_source: &TestChainSource, config: TestConfig) ->
499498
TestChainSource::Cbf(bitcoind) => {
500499
let p2p_socket = bitcoind.params.p2p_socket.expect("P2P must be enabled for CBF");
501500
let peer_addr = format!("{}", p2p_socket);
502-
let timeouts_config = SyncTimeoutsConfig {
503-
onchain_wallet_sync_timeout_secs: 3,
504-
lightning_wallet_sync_timeout_secs: 3,
505-
fee_rate_cache_update_timeout_secs: 3,
506-
tx_broadcast_timeout_secs: 3,
507-
per_request_timeout_secs: 3,
508-
};
509-
let sync_config = CbfSyncConfig {
510-
background_sync_config: None,
511-
timeouts_config,
512-
required_peers: 1,
513-
..Default::default()
514-
};
501+
let sync_config = CbfSyncConfig { background_sync_config: None, ..Default::default() };
515502
builder.set_chain_source_cbf(vec![peer_addr], Some(sync_config), None);
516503
},
517504
}
@@ -641,13 +628,27 @@ pub(crate) async fn wait_for_outpoint_spend<E: ElectrumApi>(electrs: &E, outpoin
641628
.await;
642629
}
643630

644-
pub(crate) async fn wait_for_cbf_sync(node: &TestNode) {
645-
let before = node.status().latest_onchain_wallet_sync_timestamp;
631+
/// Wait for a CBF sync cycle to complete successfully.
632+
///
633+
/// Unlike the old version which only checked that the onchain sync timestamp
634+
/// advanced, this also verifies that both the onchain *and* lightning wallet
635+
/// syncs completed, and calls a user-supplied `check` closure after each
636+
/// successful sync so the caller can verify concrete wallet state (e.g.
637+
/// balance). This prevents false passes where the timestamp advances but
638+
/// the wallet state is still stale.
639+
pub(crate) async fn wait_for_cbf_sync<F>(node: &TestNode, check: F)
640+
where
641+
F: Fn() -> bool,
642+
{
643+
let before_onchain = node.status().latest_onchain_wallet_sync_timestamp;
644+
let before_lightning = node.status().latest_lightning_wallet_sync_timestamp;
646645
let mut delay = Duration::from_millis(200);
647646
for _ in 0..30 {
648647
if node.sync_wallets().is_ok() {
649-
let after = node.status().latest_onchain_wallet_sync_timestamp;
650-
if after > before {
648+
let status = node.status();
649+
let onchain_synced = status.latest_onchain_wallet_sync_timestamp > before_onchain;
650+
let lightning_synced = status.latest_lightning_wallet_sync_timestamp > before_lightning;
651+
if onchain_synced && lightning_synced && check() {
651652
return;
652653
}
653654
}

tests/integration_tests_rust.rs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use common::{
2424
generate_listening_addresses, open_channel, open_channel_push_amt, open_channel_with_all,
2525
premine_and_distribute_funds, premine_blocks, prepare_rbf, random_chain_source, random_config,
2626
random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder, setup_node,
27-
setup_two_nodes, splice_in_with_all, skip_if_cbf, wait_for_cbf_sync, wait_for_tx,
27+
setup_two_nodes, skip_if_cbf, splice_in_with_all, wait_for_cbf_sync, wait_for_tx,
2828
TestChainSource, TestStoreType, TestSyncStore,
2929
};
3030
use electrsd::corepc_node::Node as BitcoinD;
@@ -2911,7 +2911,8 @@ async fn fee_rate_estimation_after_manual_sync_cbf() {
29112911
)
29122912
.await;
29132913

2914-
wait_for_cbf_sync(&node).await;
2914+
wait_for_cbf_sync(&node, || node.status().latest_fee_rate_cache_update_timestamp.is_some())
2915+
.await;
29152916
let first_fee_update = node.status().latest_fee_rate_cache_update_timestamp;
29162917
assert!(first_fee_update.is_some());
29172918

@@ -2941,7 +2942,10 @@ async fn repeated_manual_sync_cbf() {
29412942
)
29422943
.await;
29432944

2944-
wait_for_cbf_sync(&node).await;
2945+
wait_for_cbf_sync(&node, || {
2946+
node.list_balances().spendable_onchain_balance_sats == premine_amount_sat
2947+
})
2948+
.await;
29452949
assert_eq!(node.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
29462950

29472951
// Regression: the second manual sync must not block forever.
@@ -2986,7 +2990,10 @@ async fn start_stop_reinit_cbf() {
29862990
)
29872991
.await;
29882992

2989-
wait_for_cbf_sync(&node).await;
2993+
wait_for_cbf_sync(&node, || {
2994+
node.list_balances().spendable_onchain_balance_sats == expected_amount.to_sat()
2995+
})
2996+
.await;
29902997
assert_eq!(node.list_balances().spendable_onchain_balance_sats, expected_amount.to_sat());
29912998

29922999
node.stop().unwrap();
@@ -3014,7 +3021,11 @@ async fn start_stop_reinit_cbf() {
30143021
expected_amount.to_sat()
30153022
);
30163023

3017-
wait_for_cbf_sync(&reinitialized_node).await;
3024+
wait_for_cbf_sync(&reinitialized_node, || {
3025+
reinitialized_node.list_balances().spendable_onchain_balance_sats
3026+
== expected_amount.to_sat()
3027+
})
3028+
.await;
30183029
assert_eq!(
30193030
reinitialized_node.list_balances().spendable_onchain_balance_sats,
30203031
expected_amount.to_sat()
@@ -3044,7 +3055,10 @@ async fn onchain_wallet_recovery_cbf() {
30443055
)
30453056
.await;
30463057

3047-
wait_for_cbf_sync(&original_node).await;
3058+
wait_for_cbf_sync(&original_node, || {
3059+
original_node.list_balances().spendable_onchain_balance_sats == premine_amount_sat
3060+
})
3061+
.await;
30483062
assert_eq!(original_node.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
30493063

30503064
let addr_2 = original_node.onchain_payment().new_address().unwrap();
@@ -3060,7 +3074,10 @@ async fn onchain_wallet_recovery_cbf() {
30603074

30613075
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 1).await;
30623076

3063-
wait_for_cbf_sync(&original_node).await;
3077+
wait_for_cbf_sync(&original_node, || {
3078+
original_node.list_balances().spendable_onchain_balance_sats == premine_amount_sat * 2
3079+
})
3080+
.await;
30643081
assert_eq!(
30653082
original_node.list_balances().spendable_onchain_balance_sats,
30663083
premine_amount_sat * 2
@@ -3075,7 +3092,10 @@ async fn onchain_wallet_recovery_cbf() {
30753092
recovered_config.recovery_mode = true;
30763093
let recovered_node = setup_node(&chain_source, recovered_config);
30773094

3078-
wait_for_cbf_sync(&recovered_node).await;
3095+
wait_for_cbf_sync(&recovered_node, || {
3096+
recovered_node.list_balances().spendable_onchain_balance_sats == premine_amount_sat * 2
3097+
})
3098+
.await;
30793099
assert_eq!(
30803100
recovered_node.list_balances().spendable_onchain_balance_sats,
30813101
premine_amount_sat * 2
@@ -3098,7 +3118,10 @@ async fn onchain_wallet_recovery_cbf() {
30983118

30993119
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 1).await;
31003120

3101-
wait_for_cbf_sync(&recovered_node).await;
3121+
wait_for_cbf_sync(&recovered_node, || {
3122+
recovered_node.list_balances().spendable_onchain_balance_sats == premine_amount_sat * 3
3123+
})
3124+
.await;
31023125
assert_eq!(
31033126
recovered_node.list_balances().spendable_onchain_balance_sats,
31043127
premine_amount_sat * 3
@@ -3125,7 +3148,10 @@ async fn onchain_send_receive_cbf() {
31253148
)
31263149
.await;
31273150

3128-
wait_for_cbf_sync(&node_a).await;
3151+
wait_for_cbf_sync(&node_a, || {
3152+
node_a.list_balances().spendable_onchain_balance_sats == premine_amount_sat
3153+
})
3154+
.await;
31293155
node_b.sync_wallets().unwrap();
31303156
assert_eq!(node_a.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
31313157
assert_eq!(node_b.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
@@ -3156,7 +3182,7 @@ async fn onchain_send_receive_cbf() {
31563182

31573183
// Mine the transaction so CBF can see it.
31583184
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
3159-
wait_for_cbf_sync(&node_a).await;
3185+
wait_for_cbf_sync(&node_a, || node_a.payment(&PaymentId(txid.to_byte_array())).is_some()).await;
31603186
node_b.sync_wallets().unwrap();
31613187

31623188
let payment_id = PaymentId(txid.to_byte_array());
@@ -3201,7 +3227,7 @@ async fn onchain_send_receive_cbf() {
32013227
wait_for_tx(&electrsd.client, txid).await;
32023228

32033229
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
3204-
wait_for_cbf_sync(&node_a).await;
3230+
wait_for_cbf_sync(&node_a, || node_a.list_balances().spendable_onchain_balance_sats == 0).await;
32053231
node_b.sync_wallets().unwrap();
32063232

32073233
assert_eq!(node_a.list_balances().spendable_onchain_balance_sats, 0);

0 commit comments

Comments
 (0)