Skip to content

Commit fd8e281

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

1 file changed

Lines changed: 277 additions & 0 deletions

File tree

tests/integration_tests_rust.rs

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

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

0 commit comments

Comments
 (0)