Skip to content

Commit d6ef174

Browse files
committed
Add CBF integration tests for restart, recovery, and on-chain send/receive
1 parent 7909339 commit d6ef174

1 file changed

Lines changed: 274 additions & 0 deletions

File tree

tests/integration_tests_rust.rs

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,3 +3041,277 @@ async fn onchain_wallet_sync_cbf_reorgs_out_confirmed_receive() {
30413041

30423042
node.stop().unwrap();
30433043
}
3044+
3045+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
3046+
async fn start_stop_reinit_cbf() {
3047+
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
3048+
let config = random_config(true);
3049+
3050+
let p2p_socket = bitcoind.params.p2p_socket.expect("P2P must be enabled for CBF");
3051+
let peer_addr = format!("{}", p2p_socket);
3052+
let sync_config = ldk_node::config::CbfSyncConfig {
3053+
background_sync_config: None,
3054+
timeouts_config: Default::default(),
3055+
};
3056+
3057+
let test_sync_store = TestSyncStore::new(config.node_config.storage_dir_path.clone().into());
3058+
3059+
setup_builder!(builder, config.node_config);
3060+
builder.set_chain_source_cbf(vec![peer_addr.clone()], Some(sync_config.clone()));
3061+
3062+
let node = builder
3063+
.build_with_store(config.node_entropy.clone().into(), test_sync_store.clone())
3064+
.unwrap();
3065+
node.start().unwrap();
3066+
3067+
let expected_node_id = node.node_id();
3068+
assert_eq!(node.start(), Err(NodeError::AlreadyRunning));
3069+
3070+
let funding_address = node.onchain_payment().new_address().unwrap();
3071+
assert_eq!(node.list_balances().total_onchain_balance_sats, 0);
3072+
3073+
let expected_amount = Amount::from_sat(100_000);
3074+
premine_and_distribute_funds(
3075+
&bitcoind.client,
3076+
&electrsd.client,
3077+
vec![funding_address],
3078+
expected_amount,
3079+
)
3080+
.await;
3081+
3082+
wait_for_cbf_filters().await;
3083+
node.sync_wallets().unwrap();
3084+
assert_eq!(node.list_balances().spendable_onchain_balance_sats, expected_amount.to_sat());
3085+
3086+
node.stop().unwrap();
3087+
assert_eq!(node.stop(), Err(NodeError::NotRunning));
3088+
3089+
node.start().unwrap();
3090+
assert_eq!(node.start(), Err(NodeError::AlreadyRunning));
3091+
3092+
node.stop().unwrap();
3093+
assert_eq!(node.stop(), Err(NodeError::NotRunning));
3094+
drop(node);
3095+
3096+
// Reinitialize from the same config and store.
3097+
setup_builder!(builder, config.node_config);
3098+
builder.set_chain_source_cbf(vec![peer_addr], Some(sync_config));
3099+
3100+
let reinitialized_node =
3101+
builder.build_with_store(config.node_entropy.into(), test_sync_store).unwrap();
3102+
reinitialized_node.start().unwrap();
3103+
assert_eq!(reinitialized_node.node_id(), expected_node_id);
3104+
3105+
// Balance should be persisted from the previous run.
3106+
assert_eq!(
3107+
reinitialized_node.list_balances().spendable_onchain_balance_sats,
3108+
expected_amount.to_sat()
3109+
);
3110+
3111+
wait_for_cbf_filters().await;
3112+
reinitialized_node.sync_wallets().unwrap();
3113+
assert_eq!(
3114+
reinitialized_node.list_balances().spendable_onchain_balance_sats,
3115+
expected_amount.to_sat()
3116+
);
3117+
3118+
reinitialized_node.stop().unwrap();
3119+
}
3120+
3121+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
3122+
async fn onchain_wallet_recovery_cbf() {
3123+
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
3124+
let chain_source = TestChainSource::Cbf(&bitcoind);
3125+
3126+
let original_config = random_config(true);
3127+
let original_node_entropy = original_config.node_entropy.clone();
3128+
let original_node = setup_node(&chain_source, original_config);
3129+
3130+
let premine_amount_sat = 100_000;
3131+
3132+
let addr_1 = original_node.onchain_payment().new_address().unwrap();
3133+
3134+
premine_and_distribute_funds(
3135+
&bitcoind.client,
3136+
&electrsd.client,
3137+
vec![addr_1],
3138+
Amount::from_sat(premine_amount_sat),
3139+
)
3140+
.await;
3141+
3142+
wait_for_cbf_filters().await;
3143+
original_node.sync_wallets().unwrap();
3144+
assert_eq!(original_node.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
3145+
3146+
let addr_2 = original_node.onchain_payment().new_address().unwrap();
3147+
3148+
let txid = bitcoind
3149+
.client
3150+
.send_to_address(&addr_2, Amount::from_sat(premine_amount_sat))
3151+
.unwrap()
3152+
.0
3153+
.parse()
3154+
.unwrap();
3155+
wait_for_tx(&electrsd.client, txid).await;
3156+
3157+
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 1).await;
3158+
3159+
wait_for_cbf_filters().await;
3160+
original_node.sync_wallets().unwrap();
3161+
assert_eq!(
3162+
original_node.list_balances().spendable_onchain_balance_sats,
3163+
premine_amount_sat * 2
3164+
);
3165+
3166+
original_node.stop().unwrap();
3167+
drop(original_node);
3168+
3169+
// Now we start from scratch, only the seed remains the same.
3170+
let mut recovered_config = random_config(true);
3171+
recovered_config.node_entropy = original_node_entropy;
3172+
recovered_config.recovery_mode = true;
3173+
let recovered_node = setup_node(&chain_source, recovered_config);
3174+
3175+
wait_for_cbf_filters().await;
3176+
recovered_node.sync_wallets().unwrap();
3177+
assert_eq!(
3178+
recovered_node.list_balances().spendable_onchain_balance_sats,
3179+
premine_amount_sat * 2
3180+
);
3181+
3182+
// Check we sync even when skipping some addresses.
3183+
let _addr_3 = recovered_node.onchain_payment().new_address().unwrap();
3184+
let _addr_4 = recovered_node.onchain_payment().new_address().unwrap();
3185+
let _addr_5 = recovered_node.onchain_payment().new_address().unwrap();
3186+
let addr_6 = recovered_node.onchain_payment().new_address().unwrap();
3187+
3188+
let txid = bitcoind
3189+
.client
3190+
.send_to_address(&addr_6, Amount::from_sat(premine_amount_sat))
3191+
.unwrap()
3192+
.0
3193+
.parse()
3194+
.unwrap();
3195+
wait_for_tx(&electrsd.client, txid).await;
3196+
3197+
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 1).await;
3198+
3199+
wait_for_cbf_filters().await;
3200+
recovered_node.sync_wallets().unwrap();
3201+
assert_eq!(
3202+
recovered_node.list_balances().spendable_onchain_balance_sats,
3203+
premine_amount_sat * 3
3204+
);
3205+
3206+
recovered_node.stop().unwrap();
3207+
}
3208+
3209+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
3210+
async fn onchain_send_receive_cbf() {
3211+
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
3212+
let chain_source = TestChainSource::Cbf(&bitcoind);
3213+
let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false);
3214+
3215+
let addr_a = node_a.onchain_payment().new_address().unwrap();
3216+
let addr_b = node_b.onchain_payment().new_address().unwrap();
3217+
3218+
let premine_amount_sat = 1_100_000;
3219+
premine_and_distribute_funds(
3220+
&bitcoind.client,
3221+
&electrsd.client,
3222+
vec![addr_a.clone(), addr_b.clone()],
3223+
Amount::from_sat(premine_amount_sat),
3224+
)
3225+
.await;
3226+
3227+
wait_for_cbf_filters().await;
3228+
node_a.sync_wallets().unwrap();
3229+
node_b.sync_wallets().unwrap();
3230+
assert_eq!(node_a.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
3231+
assert_eq!(node_b.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
3232+
3233+
// Check on-chain payment tracking after premine.
3234+
let node_a_payments = node_a.list_payments();
3235+
let node_b_payments = node_b.list_payments();
3236+
for payments in [&node_a_payments, &node_b_payments] {
3237+
assert_eq!(payments.len(), 1);
3238+
}
3239+
for p in [node_a_payments.first().unwrap(), node_b_payments.first().unwrap()] {
3240+
assert_eq!(p.amount_msat, Some(premine_amount_sat * 1000));
3241+
assert_eq!(p.direction, PaymentDirection::Inbound);
3242+
assert_eq!(p.status, PaymentStatus::Pending);
3243+
match p.kind {
3244+
PaymentKind::Onchain { status, .. } => {
3245+
assert!(matches!(status, ConfirmationStatus::Confirmed { .. }));
3246+
},
3247+
_ => panic!("Unexpected payment kind"),
3248+
}
3249+
}
3250+
3251+
// Send from B to A.
3252+
let amount_to_send_sats = 54_321;
3253+
let txid =
3254+
node_b.onchain_payment().send_to_address(&addr_a, amount_to_send_sats, None).unwrap();
3255+
wait_for_tx(&electrsd.client, txid).await;
3256+
3257+
// Mine the transaction so CBF can see it.
3258+
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
3259+
wait_for_cbf_filters().await;
3260+
3261+
node_a.sync_wallets().unwrap();
3262+
node_b.sync_wallets().unwrap();
3263+
3264+
let payment_id = PaymentId(txid.to_byte_array());
3265+
let payment_a = node_a.payment(&payment_id).unwrap();
3266+
match payment_a.kind {
3267+
PaymentKind::Onchain { txid: tx, status } => {
3268+
assert_eq!(tx, txid);
3269+
assert!(matches!(status, ConfirmationStatus::Confirmed { .. }));
3270+
},
3271+
_ => panic!("Unexpected payment kind"),
3272+
}
3273+
assert!(payment_a.fee_paid_msat > Some(0));
3274+
assert_eq!(payment_a.amount_msat, Some(amount_to_send_sats * 1000));
3275+
3276+
let payment_b = node_b.payment(&payment_id).unwrap();
3277+
match payment_b.kind {
3278+
PaymentKind::Onchain { txid: tx, status } => {
3279+
assert_eq!(tx, txid);
3280+
assert!(matches!(status, ConfirmationStatus::Confirmed { .. }));
3281+
},
3282+
_ => panic!("Unexpected payment kind"),
3283+
}
3284+
assert!(payment_b.fee_paid_msat > Some(0));
3285+
assert_eq!(payment_b.amount_msat, Some(amount_to_send_sats * 1000));
3286+
assert_eq!(payment_a.fee_paid_msat, payment_b.fee_paid_msat);
3287+
3288+
let onchain_fee_buffer_sat = 1000;
3289+
let expected_node_a_balance = premine_amount_sat + amount_to_send_sats;
3290+
assert_eq!(node_a.list_balances().spendable_onchain_balance_sats, expected_node_a_balance);
3291+
assert!(
3292+
node_b.list_balances().spendable_onchain_balance_sats
3293+
> premine_amount_sat - amount_to_send_sats - onchain_fee_buffer_sat
3294+
);
3295+
assert!(
3296+
node_b.list_balances().spendable_onchain_balance_sats
3297+
< premine_amount_sat - amount_to_send_sats
3298+
);
3299+
3300+
// Test send_all_to_address.
3301+
let addr_b2 = node_b.onchain_payment().new_address().unwrap();
3302+
let txid = node_a.onchain_payment().send_all_to_address(&addr_b2, false, None).unwrap();
3303+
wait_for_tx(&electrsd.client, txid).await;
3304+
3305+
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
3306+
wait_for_cbf_filters().await;
3307+
3308+
node_a.sync_wallets().unwrap();
3309+
node_b.sync_wallets().unwrap();
3310+
3311+
assert_eq!(node_a.list_balances().spendable_onchain_balance_sats, 0);
3312+
assert_eq!(node_a.list_balances().total_onchain_balance_sats, 0);
3313+
assert!(node_b.list_balances().spendable_onchain_balance_sats > premine_amount_sat);
3314+
3315+
node_a.stop().unwrap();
3316+
node_b.stop().unwrap();
3317+
}

0 commit comments

Comments
 (0)