Skip to content

Commit b0569b5

Browse files
committed
Introduce multi-hop payment test
We establish a simple 5-node topology and try to send a payment from one end to the other.
1 parent 18d7bde commit b0569b5

File tree

1 file changed

+83
-17
lines changed

1 file changed

+83
-17
lines changed

src/test/functional_tests.rs

+83-17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::builder::NodeBuilder;
22
use crate::io::test_utils::TestSyncStore;
33
use crate::test::utils::*;
4-
use crate::test::utils::{expect_event, random_config, setup_two_nodes};
4+
use crate::test::utils::{expect_channel_pending_event, expect_event, open_channel, random_config};
55
use crate::{Error, Event, Node, PaymentDirection, PaymentStatus};
66

77
use bitcoin::Amount;
@@ -86,24 +86,13 @@ fn do_channel_full_cycle<K: KVStore + Sync + Send>(
8686
.unwrap();
8787

8888
assert_eq!(node_a.list_peers().first().unwrap().node_id, node_b.node_id());
89-
expect_event!(node_a, ChannelPending);
89+
let funding_txo_a = expect_channel_pending_event!(node_a, node_b.node_id());
90+
let funding_txo_b = expect_channel_pending_event!(node_b, node_a.node_id());
91+
assert_eq!(funding_txo_a, funding_txo_b);
9092

91-
let funding_txo = match node_b.wait_next_event() {
92-
ref e @ Event::ChannelPending { funding_txo, .. } => {
93-
println!("{} got event {:?}", std::stringify!(node_b), e);
94-
assert_eq!(node_b.next_event().as_ref(), Some(e));
95-
node_b.event_handled();
96-
funding_txo
97-
}
98-
ref e => {
99-
panic!("{} got unexpected event!: {:?}", std::stringify!(node_b), e);
100-
}
101-
};
102-
103-
wait_for_tx(&electrsd, funding_txo.txid);
93+
wait_for_tx(&electrsd, funding_txo_a.txid);
10494

10595
if !allow_0conf {
106-
println!("\n .. generating blocks ..");
10796
generate_blocks_and_wait(&bitcoind, &electrsd, 6);
10897
}
10998

@@ -276,7 +265,7 @@ fn do_channel_full_cycle<K: KVStore + Sync + Send>(
276265
expect_event!(node_a, ChannelClosed);
277266
expect_event!(node_b, ChannelClosed);
278267

279-
wait_for_outpoint_spend(&electrsd, funding_txo);
268+
wait_for_outpoint_spend(&electrsd, funding_txo_b);
280269

281270
generate_blocks_and_wait(&bitcoind, &electrsd, 1);
282271
node_a.sync_wallets().unwrap();
@@ -341,6 +330,83 @@ fn channel_open_fails_when_funds_insufficient() {
341330
);
342331
}
343332

333+
#[test]
334+
fn multi_hop_sending() {
335+
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
336+
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
337+
338+
// Setup and fund 5 nodes
339+
let mut nodes = Vec::new();
340+
for _ in 0..5 {
341+
let config = random_config();
342+
let mut builder = NodeBuilder::from_config(config);
343+
builder.set_esplora_server(esplora_url.clone());
344+
let node = builder.build().unwrap();
345+
node.start().unwrap();
346+
nodes.push(node);
347+
}
348+
349+
let addresses = nodes.iter().map(|n| n.new_onchain_address().unwrap()).collect();
350+
let premine_amount_sat = 5_000_000;
351+
premine_and_distribute_funds(
352+
&bitcoind,
353+
&electrsd,
354+
addresses,
355+
Amount::from_sat(premine_amount_sat),
356+
);
357+
358+
for n in &nodes {
359+
n.sync_wallets().unwrap();
360+
assert_eq!(n.spendable_onchain_balance_sats().unwrap(), premine_amount_sat);
361+
assert_eq!(n.next_event(), None);
362+
}
363+
364+
// Setup channel topology:
365+
// (1M:0)- N2 -(1M:0)
366+
// / \
367+
// N0 -(100k:0)-> N1 N4
368+
// \ /
369+
// (1M:0)- N3 -(1M:0)
370+
371+
open_channel(&nodes[0], &nodes[1], 100_000, true, &electrsd);
372+
open_channel(&nodes[1], &nodes[2], 1_000_000, true, &electrsd);
373+
// We need to sync wallets in-between back-to-back channel opens from the same node so BDK
374+
// wallet picks up on the broadcast funding tx and doesn't double-spend itself.
375+
//
376+
// TODO: Remove once fixed in BDK.
377+
nodes[1].sync_wallets().unwrap();
378+
open_channel(&nodes[1], &nodes[3], 1_000_000, true, &electrsd);
379+
open_channel(&nodes[2], &nodes[4], 1_000_000, true, &electrsd);
380+
open_channel(&nodes[3], &nodes[4], 1_000_000, true, &electrsd);
381+
382+
generate_blocks_and_wait(&bitcoind, &electrsd, 6);
383+
384+
for n in &nodes {
385+
n.sync_wallets().unwrap();
386+
}
387+
388+
expect_event!(nodes[0], ChannelReady);
389+
expect_event!(nodes[1], ChannelReady);
390+
expect_event!(nodes[1], ChannelReady);
391+
expect_event!(nodes[1], ChannelReady);
392+
expect_event!(nodes[2], ChannelReady);
393+
expect_event!(nodes[2], ChannelReady);
394+
expect_event!(nodes[3], ChannelReady);
395+
expect_event!(nodes[3], ChannelReady);
396+
expect_event!(nodes[4], ChannelReady);
397+
expect_event!(nodes[4], ChannelReady);
398+
399+
// Sleep a bit for gossip to propagate.
400+
// FIXME: This doesn't work anyways currently and should be removed when we have a solution.
401+
std::thread::sleep(std::time::Duration::from_secs(60));
402+
403+
let invoice = nodes[4].receive_payment(10000, &"asdf", 9217).unwrap();
404+
nodes[0].send_payment(&invoice).unwrap();
405+
406+
expect_event!(nodes[4], PaymentReceived);
407+
expect_event!(nodes[0], PaymentSuccessful);
408+
}
409+
344410
#[test]
345411
fn connect_to_public_testnet_esplora() {
346412
let mut config = random_config();

0 commit comments

Comments
 (0)