Skip to content

Commit 5ad44bd

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 bc3e0f3 commit 5ad44bd

2 files changed

Lines changed: 57 additions & 29 deletions

File tree

tests/common/mod.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -516,19 +516,7 @@ pub(crate) fn setup_node(chain_source: &TestChainSource, config: TestConfig) ->
516516
TestChainSource::Cbf(bitcoind) => {
517517
let p2p_socket = bitcoind.params.p2p_socket.expect("P2P must be enabled for CBF");
518518
let peer_addr = format!("{}", p2p_socket);
519-
let timeouts_config = SyncTimeoutsConfig {
520-
onchain_wallet_sync_timeout_secs: 3,
521-
lightning_wallet_sync_timeout_secs: 3,
522-
fee_rate_cache_update_timeout_secs: 3,
523-
tx_broadcast_timeout_secs: 3,
524-
per_request_timeout_secs: 3,
525-
};
526-
let sync_config = CbfSyncConfig {
527-
background_sync_config: None,
528-
timeouts_config,
529-
required_peers: 1,
530-
..Default::default()
531-
};
519+
let sync_config = CbfSyncConfig { background_sync_config: None, ..Default::default() };
532520
builder.set_chain_source_cbf(vec![peer_addr], Some(sync_config), None);
533521
},
534522
}
@@ -658,13 +646,27 @@ pub(crate) async fn wait_for_outpoint_spend<E: ElectrumApi>(electrs: &E, outpoin
658646
.await;
659647
}
660648

661-
pub(crate) async fn wait_for_cbf_sync(node: &TestNode) {
662-
let before = node.status().latest_onchain_wallet_sync_timestamp;
649+
/// Wait for a CBF sync cycle to complete successfully.
650+
///
651+
/// Unlike the old version which only checked that the onchain sync timestamp
652+
/// advanced, this also verifies that both the onchain *and* lightning wallet
653+
/// syncs completed, and calls a user-supplied `check` closure after each
654+
/// successful sync so the caller can verify concrete wallet state (e.g.
655+
/// balance). This prevents false passes where the timestamp advances but
656+
/// the wallet state is still stale.
657+
pub(crate) async fn wait_for_cbf_sync<F>(node: &TestNode, check: F)
658+
where
659+
F: Fn() -> bool,
660+
{
661+
let before_onchain = node.status().latest_onchain_wallet_sync_timestamp;
662+
let before_lightning = node.status().latest_lightning_wallet_sync_timestamp;
663663
let mut delay = Duration::from_millis(200);
664664
for _ in 0..30 {
665665
if node.sync_wallets().is_ok() {
666-
let after = node.status().latest_onchain_wallet_sync_timestamp;
667-
if after > before {
666+
let status = node.status();
667+
let onchain_synced = status.latest_onchain_wallet_sync_timestamp > before_onchain;
668+
let lightning_synced = status.latest_lightning_wallet_sync_timestamp > before_lightning;
669+
if onchain_synced && lightning_synced && check() {
668670
return;
669671
}
670672
}

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;
@@ -2995,7 +2995,8 @@ async fn fee_rate_estimation_after_manual_sync_cbf() {
29952995
)
29962996
.await;
29972997

2998-
wait_for_cbf_sync(&node).await;
2998+
wait_for_cbf_sync(&node, || node.status().latest_fee_rate_cache_update_timestamp.is_some())
2999+
.await;
29993000
let first_fee_update = node.status().latest_fee_rate_cache_update_timestamp;
30003001
assert!(first_fee_update.is_some());
30013002

@@ -3025,7 +3026,10 @@ async fn repeated_manual_sync_cbf() {
30253026
)
30263027
.await;
30273028

3028-
wait_for_cbf_sync(&node).await;
3029+
wait_for_cbf_sync(&node, || {
3030+
node.list_balances().spendable_onchain_balance_sats == premine_amount_sat
3031+
})
3032+
.await;
30293033
assert_eq!(node.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
30303034

30313035
// Regression: the second manual sync must not block forever.
@@ -3070,7 +3074,10 @@ async fn start_stop_reinit_cbf() {
30703074
)
30713075
.await;
30723076

3073-
wait_for_cbf_sync(&node).await;
3077+
wait_for_cbf_sync(&node, || {
3078+
node.list_balances().spendable_onchain_balance_sats == expected_amount.to_sat()
3079+
})
3080+
.await;
30743081
assert_eq!(node.list_balances().spendable_onchain_balance_sats, expected_amount.to_sat());
30753082

30763083
node.stop().unwrap();
@@ -3098,7 +3105,11 @@ async fn start_stop_reinit_cbf() {
30983105
expected_amount.to_sat()
30993106
);
31003107

3101-
wait_for_cbf_sync(&reinitialized_node).await;
3108+
wait_for_cbf_sync(&reinitialized_node, || {
3109+
reinitialized_node.list_balances().spendable_onchain_balance_sats
3110+
== expected_amount.to_sat()
3111+
})
3112+
.await;
31023113
assert_eq!(
31033114
reinitialized_node.list_balances().spendable_onchain_balance_sats,
31043115
expected_amount.to_sat()
@@ -3128,7 +3139,10 @@ async fn onchain_wallet_recovery_cbf() {
31283139
)
31293140
.await;
31303141

3131-
wait_for_cbf_sync(&original_node).await;
3142+
wait_for_cbf_sync(&original_node, || {
3143+
original_node.list_balances().spendable_onchain_balance_sats == premine_amount_sat
3144+
})
3145+
.await;
31323146
assert_eq!(original_node.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
31333147

31343148
let addr_2 = original_node.onchain_payment().new_address().unwrap();
@@ -3144,7 +3158,10 @@ async fn onchain_wallet_recovery_cbf() {
31443158

31453159
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 1).await;
31463160

3147-
wait_for_cbf_sync(&original_node).await;
3161+
wait_for_cbf_sync(&original_node, || {
3162+
original_node.list_balances().spendable_onchain_balance_sats == premine_amount_sat * 2
3163+
})
3164+
.await;
31483165
assert_eq!(
31493166
original_node.list_balances().spendable_onchain_balance_sats,
31503167
premine_amount_sat * 2
@@ -3159,7 +3176,10 @@ async fn onchain_wallet_recovery_cbf() {
31593176
recovered_config.recovery_mode = true;
31603177
let recovered_node = setup_node(&chain_source, recovered_config);
31613178

3162-
wait_for_cbf_sync(&recovered_node).await;
3179+
wait_for_cbf_sync(&recovered_node, || {
3180+
recovered_node.list_balances().spendable_onchain_balance_sats == premine_amount_sat * 2
3181+
})
3182+
.await;
31633183
assert_eq!(
31643184
recovered_node.list_balances().spendable_onchain_balance_sats,
31653185
premine_amount_sat * 2
@@ -3182,7 +3202,10 @@ async fn onchain_wallet_recovery_cbf() {
31823202

31833203
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 1).await;
31843204

3185-
wait_for_cbf_sync(&recovered_node).await;
3205+
wait_for_cbf_sync(&recovered_node, || {
3206+
recovered_node.list_balances().spendable_onchain_balance_sats == premine_amount_sat * 3
3207+
})
3208+
.await;
31863209
assert_eq!(
31873210
recovered_node.list_balances().spendable_onchain_balance_sats,
31883211
premine_amount_sat * 3
@@ -3209,7 +3232,10 @@ async fn onchain_send_receive_cbf() {
32093232
)
32103233
.await;
32113234

3212-
wait_for_cbf_sync(&node_a).await;
3235+
wait_for_cbf_sync(&node_a, || {
3236+
node_a.list_balances().spendable_onchain_balance_sats == premine_amount_sat
3237+
})
3238+
.await;
32133239
node_b.sync_wallets().unwrap();
32143240
assert_eq!(node_a.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
32153241
assert_eq!(node_b.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
@@ -3240,7 +3266,7 @@ async fn onchain_send_receive_cbf() {
32403266

32413267
// Mine the transaction so CBF can see it.
32423268
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
3243-
wait_for_cbf_sync(&node_a).await;
3269+
wait_for_cbf_sync(&node_a, || node_a.payment(&PaymentId(txid.to_byte_array())).is_some()).await;
32443270
node_b.sync_wallets().unwrap();
32453271

32463272
let payment_id = PaymentId(txid.to_byte_array());
@@ -3285,7 +3311,7 @@ async fn onchain_send_receive_cbf() {
32853311
wait_for_tx(&electrsd.client, txid).await;
32863312

32873313
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
3288-
wait_for_cbf_sync(&node_a).await;
3314+
wait_for_cbf_sync(&node_a, || node_a.list_balances().spendable_onchain_balance_sats == 0).await;
32893315
node_b.sync_wallets().unwrap();
32903316

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

0 commit comments

Comments
 (0)