Skip to content

Commit c724a89

Browse files
committed
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 f1885be commit c724a89

File tree

1 file changed

+120
-1
lines changed

1 file changed

+120
-1
lines changed

tests/integration_tests_rust.rs

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ use common::{
2323
expect_splice_pending_event, generate_blocks_and_wait, open_channel, open_channel_push_amt,
2424
premine_and_distribute_funds, premine_blocks, prepare_rbf, random_config,
2525
random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder, setup_node,
26-
setup_node_for_async_payments, setup_two_nodes, wait_for_tx, TestChainSource, TestSyncStore,
26+
setup_node_for_async_payments, setup_two_nodes, wait_for_tx, TestChainSource, TestStoreType,
27+
TestSyncStore,
2728
};
2829
use ldk_node::config::{AsyncPaymentsRole, EsploraSyncConfig};
2930
use ldk_node::liquidity::LSPS2ServiceConfig;
@@ -2317,3 +2318,121 @@ async fn lsps2_lsp_trusts_client_but_client_does_not_claim() {
23172318
Some(6)
23182319
);
23192320
}
2321+
2322+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
2323+
async fn payment_persistence_after_restart() {
2324+
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
2325+
let chain_source = TestChainSource::Esplora(&electrsd);
2326+
2327+
// Setup nodes manually so we can restart node_a with the same config
2328+
println!("== Node A ==");
2329+
let mut config_a = random_config(true);
2330+
config_a.store_type = TestStoreType::Sqlite;
2331+
2332+
let num_payments = 200;
2333+
let payment_amount_msat = 1_000_000; // 1000 sats per payment
2334+
2335+
{
2336+
let node_a = setup_node(&chain_source, config_a.clone());
2337+
2338+
println!("\n== Node B ==");
2339+
let config_b = random_config(true);
2340+
let node_b = setup_node(&chain_source, config_b);
2341+
2342+
let addr_a = node_a.onchain_payment().new_address().unwrap();
2343+
let addr_b = node_b.onchain_payment().new_address().unwrap();
2344+
2345+
// Premine sufficient funds for a large channel and many payments
2346+
let premine_amount_sat = 10_000_000;
2347+
premine_and_distribute_funds(
2348+
&bitcoind.client,
2349+
&electrsd.client,
2350+
vec![addr_a, addr_b],
2351+
Amount::from_sat(premine_amount_sat),
2352+
)
2353+
.await;
2354+
node_a.sync_wallets().unwrap();
2355+
node_b.sync_wallets().unwrap();
2356+
assert_eq!(node_a.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
2357+
assert_eq!(node_b.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
2358+
2359+
// Open a large channel from node_a to node_b
2360+
let channel_amount_sat = 5_000_000;
2361+
open_channel(&node_a, &node_b, channel_amount_sat, true, &electrsd).await;
2362+
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
2363+
node_a.sync_wallets().unwrap();
2364+
node_b.sync_wallets().unwrap();
2365+
expect_channel_ready_event!(node_a, node_b.node_id());
2366+
expect_channel_ready_event!(node_b, node_a.node_id());
2367+
2368+
// Send 200 payments from node_a to node_b
2369+
println!("\nSending {} payments from A to B...", num_payments);
2370+
let invoice_description =
2371+
Bolt11InvoiceDescription::Direct(Description::new(String::from("test")).unwrap());
2372+
2373+
for i in 0..num_payments {
2374+
let invoice = node_b
2375+
.bolt11_payment()
2376+
.receive(payment_amount_msat, &invoice_description.clone().into(), 3600)
2377+
.unwrap();
2378+
let payment_id = node_a.bolt11_payment().send(&invoice, None).unwrap();
2379+
expect_event!(node_a, PaymentSuccessful);
2380+
expect_event!(node_b, PaymentReceived);
2381+
2382+
if (i + 1) % 50 == 0 {
2383+
println!("Completed {} payments", i + 1);
2384+
}
2385+
2386+
// Verify payment succeeded
2387+
assert_eq!(node_a.payment(&payment_id).unwrap().status, PaymentStatus::Succeeded);
2388+
}
2389+
println!("All {} payments completed successfully", num_payments);
2390+
2391+
// Verify node_a has 200 outbound Bolt11 payments before shutdown
2392+
let outbound_payments_before = node_a.list_payments_with_filter(|p| {
2393+
p.direction == PaymentDirection::Outbound
2394+
&& matches!(p.kind, PaymentKind::Bolt11 { .. })
2395+
});
2396+
assert_eq!(outbound_payments_before.len(), num_payments);
2397+
2398+
// Shut down both nodes
2399+
println!("\nShutting down nodes...");
2400+
node_a.stop().unwrap();
2401+
node_b.stop().unwrap();
2402+
}
2403+
2404+
// Restart node_a with the same config
2405+
println!("\nRestarting node A...");
2406+
let restarted_node_a = setup_node(&chain_source, config_a);
2407+
2408+
// Assert all 200 payments are still in the store
2409+
let outbound_payments_after = restarted_node_a.list_payments_with_filter(|p| {
2410+
p.direction == PaymentDirection::Outbound && matches!(p.kind, PaymentKind::Bolt11 { .. })
2411+
});
2412+
assert_eq!(
2413+
outbound_payments_after.len(),
2414+
num_payments,
2415+
"Expected {} payments after restart, found {}",
2416+
num_payments,
2417+
outbound_payments_after.len()
2418+
);
2419+
2420+
// Verify all payments have the correct status
2421+
for payment in &outbound_payments_after {
2422+
assert_eq!(
2423+
payment.status,
2424+
PaymentStatus::Succeeded,
2425+
"Payment {:?} has unexpected status {:?}",
2426+
payment.id,
2427+
payment.status
2428+
);
2429+
assert_eq!(payment.amount_msat, Some(payment_amount_msat));
2430+
}
2431+
2432+
println!(
2433+
"Successfully verified {} payments persisted after restart",
2434+
outbound_payments_after.len()
2435+
);
2436+
2437+
restarted_node_a.stop().unwrap();
2438+
}

0 commit comments

Comments
 (0)