Skip to content

Commit 8dc83a9

Browse files
tnullamackillop
authored andcommitted
Add test for payment persistence after node restart
Add integration test that verifies 200 payments are correctly persisted and retrievable via `list_payments` after restarting a node. Co-Authored-By: Claude AI
1 parent 0e31d35 commit 8dc83a9

1 file changed

Lines changed: 120 additions & 1 deletion

File tree

tests/integration_tests_rust.rs

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ use common::{
5151
expect_splice_pending_event, generate_blocks_and_wait, open_channel, open_channel_push_amt,
5252
premine_and_distribute_funds, premine_blocks, prepare_rbf, random_config,
5353
random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder, setup_node,
54-
setup_node_for_async_payments, setup_two_nodes, wait_for_tx, TestChainSource, TestSyncStore,
54+
setup_node_for_async_payments, setup_two_nodes, wait_for_tx, TestChainSource, TestStoreType,
55+
TestSyncStore,
5556
};
5657
use ldk_node::config::{AsyncPaymentsRole, EsploraSyncConfig};
5758
use ldk_node::liquidity::LSPS2ServiceConfig;
@@ -2617,3 +2618,121 @@ async fn lsps2_lsp_trusts_client_but_client_does_not_claim() {
26172618
Some(6)
26182619
);
26192620
}
2621+
2622+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
2623+
async fn payment_persistence_after_restart() {
2624+
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
2625+
let chain_source = TestChainSource::Esplora(&electrsd);
2626+
2627+
// Setup nodes manually so we can restart node_a with the same config
2628+
println!("== Node A ==");
2629+
let mut config_a = random_config(true);
2630+
config_a.store_type = TestStoreType::Sqlite;
2631+
2632+
let num_payments = 200;
2633+
let payment_amount_msat = 1_000_000; // 1000 sats per payment
2634+
2635+
{
2636+
let node_a = setup_node(&chain_source, config_a.clone());
2637+
2638+
println!("\n== Node B ==");
2639+
let config_b = random_config(true);
2640+
let node_b = setup_node(&chain_source, config_b);
2641+
2642+
let addr_a = node_a.onchain_payment().new_address().unwrap();
2643+
let addr_b = node_b.onchain_payment().new_address().unwrap();
2644+
2645+
// Premine sufficient funds for a large channel and many payments
2646+
let premine_amount_sat = 10_000_000;
2647+
premine_and_distribute_funds(
2648+
&bitcoind.client,
2649+
&electrsd.client,
2650+
vec![addr_a, addr_b],
2651+
Amount::from_sat(premine_amount_sat),
2652+
)
2653+
.await;
2654+
node_a.sync_wallets().unwrap();
2655+
node_b.sync_wallets().unwrap();
2656+
assert_eq!(node_a.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
2657+
assert_eq!(node_b.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
2658+
2659+
// Open a large channel from node_a to node_b
2660+
let channel_amount_sat = 5_000_000;
2661+
open_channel(&node_a, &node_b, channel_amount_sat, true, &electrsd).await;
2662+
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
2663+
node_a.sync_wallets().unwrap();
2664+
node_b.sync_wallets().unwrap();
2665+
expect_channel_ready_event!(node_a, node_b.node_id());
2666+
expect_channel_ready_event!(node_b, node_a.node_id());
2667+
2668+
// Send 200 payments from node_a to node_b
2669+
println!("\nSending {} payments from A to B...", num_payments);
2670+
let invoice_description =
2671+
Bolt11InvoiceDescription::Direct(Description::new(String::from("test")).unwrap());
2672+
2673+
for i in 0..num_payments {
2674+
let invoice = node_b
2675+
.bolt11_payment()
2676+
.receive(payment_amount_msat, &invoice_description.clone().into(), 3600)
2677+
.unwrap();
2678+
let payment_id = node_a.bolt11_payment().send(&invoice, None).unwrap();
2679+
expect_event!(node_a, PaymentSuccessful);
2680+
expect_event!(node_b, PaymentReceived);
2681+
2682+
if (i + 1) % 50 == 0 {
2683+
println!("Completed {} payments", i + 1);
2684+
}
2685+
2686+
// Verify payment succeeded
2687+
assert_eq!(node_a.payment(&payment_id).unwrap().status, PaymentStatus::Succeeded);
2688+
}
2689+
println!("All {} payments completed successfully", num_payments);
2690+
2691+
// Verify node_a has 200 outbound Bolt11 payments before shutdown
2692+
let outbound_payments_before = node_a.list_payments_with_filter(|p| {
2693+
p.direction == PaymentDirection::Outbound
2694+
&& matches!(p.kind, PaymentKind::Bolt11 { .. })
2695+
});
2696+
assert_eq!(outbound_payments_before.len(), num_payments);
2697+
2698+
// Shut down both nodes
2699+
println!("\nShutting down nodes...");
2700+
node_a.stop().unwrap();
2701+
node_b.stop().unwrap();
2702+
}
2703+
2704+
// Restart node_a with the same config
2705+
println!("\nRestarting node A...");
2706+
let restarted_node_a = setup_node(&chain_source, config_a);
2707+
2708+
// Assert all 200 payments are still in the store
2709+
let outbound_payments_after = restarted_node_a.list_payments_with_filter(|p| {
2710+
p.direction == PaymentDirection::Outbound && matches!(p.kind, PaymentKind::Bolt11 { .. })
2711+
});
2712+
assert_eq!(
2713+
outbound_payments_after.len(),
2714+
num_payments,
2715+
"Expected {} payments after restart, found {}",
2716+
num_payments,
2717+
outbound_payments_after.len()
2718+
);
2719+
2720+
// Verify all payments have the correct status
2721+
for payment in &outbound_payments_after {
2722+
assert_eq!(
2723+
payment.status,
2724+
PaymentStatus::Succeeded,
2725+
"Payment {:?} has unexpected status {:?}",
2726+
payment.id,
2727+
payment.status
2728+
);
2729+
assert_eq!(payment.amount_msat, Some(payment_amount_msat));
2730+
}
2731+
2732+
println!(
2733+
"Successfully verified {} payments persisted after restart",
2734+
outbound_payments_after.len()
2735+
);
2736+
2737+
restarted_node_a.stop().unwrap();
2738+
}

0 commit comments

Comments
 (0)