Skip to content

Commit

Permalink
Introduce multi-hop payment test
Browse files Browse the repository at this point in the history
We establish a simple 5-node topology and try to send a payment from one
end to the other.
  • Loading branch information
tnull committed Nov 16, 2023
1 parent 878892e commit 56ae971
Showing 1 changed file with 83 additions and 17 deletions.
100 changes: 83 additions & 17 deletions src/test/functional_tests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::builder::NodeBuilder;
use crate::io::test_utils::TestSyncStore;
use crate::test::utils::*;
use crate::test::utils::{expect_event, random_config, setup_two_nodes};
use crate::test::utils::{expect_channel_pending_event, expect_event, open_channel, random_config};
use crate::{Error, Event, Node, PaymentDirection, PaymentStatus};

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

assert_eq!(node_a.list_peers().first().unwrap().node_id, node_b.node_id());
expect_event!(node_a, ChannelPending);
let funding_txo_a = expect_channel_pending_event!(node_a, node_b.node_id());
let funding_txo_b = expect_channel_pending_event!(node_b, node_a.node_id());
assert_eq!(funding_txo_a, funding_txo_b);

let funding_txo = match node_b.wait_next_event() {
ref e @ Event::ChannelPending { funding_txo, .. } => {
println!("{} got event {:?}", std::stringify!(node_b), e);
assert_eq!(node_b.next_event().as_ref(), Some(e));
node_b.event_handled();
funding_txo
}
ref e => {
panic!("{} got unexpected event!: {:?}", std::stringify!(node_b), e);
}
};

wait_for_tx(&electrsd, funding_txo.txid);
wait_for_tx(&electrsd, funding_txo_a.txid);

if !allow_0conf {
println!("\n .. generating blocks ..");
generate_blocks_and_wait(&bitcoind, &electrsd, 6);
}

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

wait_for_outpoint_spend(&electrsd, funding_txo);
wait_for_outpoint_spend(&electrsd, funding_txo_b);

generate_blocks_and_wait(&bitcoind, &electrsd, 1);
node_a.sync_wallets().unwrap();
Expand Down Expand Up @@ -341,6 +330,83 @@ fn channel_open_fails_when_funds_insufficient() {
);
}

#[test]
fn multi_hop_sending() {
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());

// Setup and fund 5 nodes
let mut nodes = Vec::new();
for _ in 0..5 {
let config = random_config();
let mut builder = NodeBuilder::from_config(config);
builder.set_esplora_server(esplora_url.clone());
let node = builder.build().unwrap();
node.start().unwrap();
nodes.push(node);
}

let addresses = nodes.iter().map(|n| n.new_onchain_address().unwrap()).collect();
let premine_amount_sat = 5_000_000;
premine_and_distribute_funds(
&bitcoind,
&electrsd,
addresses,
Amount::from_sat(premine_amount_sat),
);

for n in &nodes {
n.sync_wallets().unwrap();
assert_eq!(n.spendable_onchain_balance_sats().unwrap(), premine_amount_sat);
assert_eq!(n.next_event(), None);
}

// Setup channel topology:
// (1M:0)- N2 -(1M:0)
// / \
// N0 -(100k:0)-> N1 N4
// \ /
// (1M:0)- N3 -(1M:0)

open_channel(&nodes[0], &nodes[1], 100_000, true, &electrsd);
open_channel(&nodes[1], &nodes[2], 1_000_000, true, &electrsd);
// We need to sync wallets in-between back-to-back channel opens from the same node so BDK
// wallet picks up on the broadcast funding tx and doesn't double-spend itself.
//
// TODO: Remove once fixed in BDK.
nodes[1].sync_wallets().unwrap();
open_channel(&nodes[1], &nodes[3], 1_000_000, true, &electrsd);
open_channel(&nodes[2], &nodes[4], 1_000_000, true, &electrsd);
open_channel(&nodes[3], &nodes[4], 1_000_000, true, &electrsd);

generate_blocks_and_wait(&bitcoind, &electrsd, 6);

for n in &nodes {
n.sync_wallets().unwrap();
}

expect_event!(nodes[0], ChannelReady);
expect_event!(nodes[1], ChannelReady);
expect_event!(nodes[1], ChannelReady);
expect_event!(nodes[1], ChannelReady);
expect_event!(nodes[2], ChannelReady);
expect_event!(nodes[2], ChannelReady);
expect_event!(nodes[3], ChannelReady);
expect_event!(nodes[3], ChannelReady);
expect_event!(nodes[4], ChannelReady);
expect_event!(nodes[4], ChannelReady);

// Sleep a bit for gossip to propagate.
// FIXME: This doesn't work anyways currently and should be removed when we have a solution.
std::thread::sleep(std::time::Duration::from_secs(60));

let invoice = nodes[4].receive_payment(10000, &"asdf", 9217).unwrap();
nodes[0].send_payment(&invoice).unwrap();

expect_event!(nodes[4], PaymentReceived);
expect_event!(nodes[0], PaymentSuccessful);
}

#[test]
fn connect_to_public_testnet_esplora() {
let mut config = random_config();
Expand Down

0 comments on commit 56ae971

Please sign in to comment.