Skip to content

Commit e86df2c

Browse files
committed
Refactor CLN/LND tests and add Eclair test entry points
1 parent 749fa2b commit e86df2c

3 files changed

Lines changed: 407 additions & 271 deletions

File tree

tests/integration_tests_cln.rs

Lines changed: 129 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -9,119 +9,157 @@
99

1010
mod common;
1111

12-
use std::default::Default;
1312
use std::str::FromStr;
1413

15-
use clightningrpc::lightningrpc::LightningRPC;
16-
use clightningrpc::responses::NetworkAddress;
1714
use electrsd::corepc_client::client_sync::Auth;
1815
use electrsd::corepc_node::Client as BitcoindClient;
1916
use electrum_client::Client as ElectrumClient;
20-
use ldk_node::bitcoin::secp256k1::PublicKey;
21-
use ldk_node::bitcoin::Amount;
22-
use ldk_node::lightning::ln::msgs::SocketAddress;
2317
use ldk_node::{Builder, Event};
24-
use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, Description};
25-
use rand::distr::Alphanumeric;
26-
use rand::{rng, Rng};
18+
use proptest::prelude::*;
19+
use proptest::proptest;
2720

28-
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
29-
async fn test_cln() {
30-
// Setup bitcoind / electrs clients
31-
let bitcoind_client = BitcoindClient::new_with_auth(
21+
use common::cln::TestClnNode;
22+
use common::external_node::ExternalNode;
23+
use common::scenarios::*;
24+
25+
fn setup_clients() -> (BitcoindClient, ElectrumClient, TestClnNode) {
26+
let bitcoind = BitcoindClient::new_with_auth(
3227
"http://127.0.0.1:18443",
3328
Auth::UserPass("user".to_string(), "pass".to_string()),
3429
)
3530
.unwrap();
36-
let electrs_client = ElectrumClient::new("tcp://127.0.0.1:50001").unwrap();
37-
38-
// Give electrs a kick.
39-
common::generate_blocks_and_wait(&bitcoind_client, &electrs_client, 1).await;
31+
let electrs = ElectrumClient::new("tcp://127.0.0.1:50001").unwrap();
32+
let cln = TestClnNode::from_env();
33+
(bitcoind, electrs, cln)
34+
}
4035

41-
// Setup LDK Node
36+
fn setup_ldk_node() -> ldk_node::Node {
4237
let config = common::random_config(true);
4338
let mut builder = Builder::from_config(config.node_config);
4439
builder.set_chain_source_esplora("http://127.0.0.1:3002".to_string(), None);
45-
4640
let node = builder.build(config.node_entropy).unwrap();
4741
node.start().unwrap();
42+
node
43+
}
4844

49-
// Premine some funds and distribute
50-
let address = node.onchain_payment().new_address().unwrap();
51-
let premine_amount = Amount::from_sat(5_000_000);
52-
common::premine_and_distribute_funds(
53-
&bitcoind_client,
54-
&electrs_client,
55-
vec![address],
56-
premine_amount,
57-
)
58-
.await;
59-
60-
// Setup CLN
61-
let sock = "/tmp/lightning-rpc";
62-
let cln_client = LightningRPC::new(&sock);
63-
let cln_info = {
64-
loop {
65-
let info = cln_client.getinfo().unwrap();
66-
// Wait for CLN to sync block height before channel open.
67-
// Prevents crash due to unset blockheight (see LDK Node issue #527).
68-
if info.blockheight > 0 {
69-
break info;
70-
}
71-
tokio::time::sleep(std::time::Duration::from_millis(250)).await;
72-
}
73-
};
74-
let cln_node_id = PublicKey::from_str(&cln_info.id).unwrap();
75-
let cln_address: SocketAddress = match cln_info.binding.first().unwrap() {
76-
NetworkAddress::Ipv4 { address, port } => {
77-
std::net::SocketAddrV4::new(*address, *port).into()
78-
},
79-
NetworkAddress::Ipv6 { address, port } => {
80-
std::net::SocketAddrV6::new(*address, *port, 0, 0).into()
81-
},
82-
_ => {
83-
panic!()
84-
},
85-
};
86-
87-
node.sync_wallets().unwrap();
88-
89-
// Open the channel
90-
let funding_amount_sat = 1_000_000;
91-
92-
node.open_channel(cln_node_id, cln_address, funding_amount_sat, Some(500_000_000), None)
45+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
46+
async fn test_cln_basic_channel_cycle() {
47+
let (bitcoind, electrs, cln) = setup_clients();
48+
cln.wait_for_sync().await;
49+
common::generate_blocks_and_wait(&bitcoind, &electrs, 1).await;
50+
51+
let node = setup_ldk_node();
52+
setup_interop_test(&node, &cln, &bitcoind, &electrs).await;
53+
54+
let (user_channel_id, _ext_channel_id) =
55+
open_channel_to_external(&node, &cln, &bitcoind, &electrs, 1_000_000, Some(500_000_000))
56+
.await;
57+
58+
// LDK -> CLN payment
59+
let invoice = cln.create_invoice(10_000_000, "cln-test-send").await.unwrap();
60+
let parsed = lightning_invoice::Bolt11Invoice::from_str(&invoice).unwrap();
61+
node.bolt11_payment().send(&parsed, None).unwrap();
62+
common::expect_event!(node, PaymentSuccessful);
63+
64+
// CLN -> LDK payment
65+
let ldk_invoice = node
66+
.bolt11_payment()
67+
.receive(
68+
10_000_000,
69+
&lightning_invoice::Bolt11InvoiceDescription::Direct(
70+
lightning_invoice::Description::new("cln-test-recv".to_string()).unwrap(),
71+
),
72+
3600,
73+
)
9374
.unwrap();
75+
cln.pay_invoice(&ldk_invoice.to_string()).await.unwrap();
76+
common::expect_event!(node, PaymentReceived);
9477

95-
let funding_txo = common::expect_channel_pending_event!(node, cln_node_id);
96-
common::wait_for_tx(&electrs_client, funding_txo.txid).await;
97-
common::generate_blocks_and_wait(&bitcoind_client, &electrs_client, 6).await;
98-
node.sync_wallets().unwrap();
99-
let user_channel_id = common::expect_channel_ready_event!(node, cln_node_id);
78+
test_cooperative_close_by_ldk(&node, &cln, &user_channel_id).await;
79+
node.stop().unwrap();
80+
}
10081

101-
// Send a payment to CLN
102-
let mut rng = rng();
103-
let rand_label: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect();
104-
let cln_invoice =
105-
cln_client.invoice(Some(10_000_000), &rand_label, &rand_label, None, None, None).unwrap();
106-
let parsed_invoice = Bolt11Invoice::from_str(&cln_invoice.bolt11).unwrap();
82+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
83+
async fn test_cln_disconnect_reconnect() {
84+
let (bitcoind, electrs, cln) = setup_clients();
85+
cln.wait_for_sync().await;
86+
common::generate_blocks_and_wait(&bitcoind, &electrs, 1).await;
10787

108-
node.bolt11_payment().send(&parsed_invoice, None).unwrap();
109-
common::expect_event!(node, PaymentSuccessful);
110-
let cln_listed_invoices =
111-
cln_client.listinvoices(Some(&rand_label), None, None, None).unwrap().invoices;
112-
assert_eq!(cln_listed_invoices.len(), 1);
113-
assert_eq!(cln_listed_invoices.first().unwrap().status, "paid");
114-
115-
// Send a payment to LDK
116-
let rand_label: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect();
117-
let invoice_description =
118-
Bolt11InvoiceDescription::Direct(Description::new(rand_label).unwrap());
119-
let ldk_invoice =
120-
node.bolt11_payment().receive(10_000_000, &invoice_description, 3600).unwrap();
121-
cln_client.pay(&ldk_invoice.to_string(), Default::default()).unwrap();
122-
common::expect_event!(node, PaymentReceived);
88+
let node = setup_ldk_node();
89+
setup_interop_test(&node, &cln, &bitcoind, &electrs).await;
90+
let (_user_ch, _ext_ch) =
91+
open_channel_to_external(&node, &cln, &bitcoind, &electrs, 1_000_000, Some(500_000_000))
92+
.await;
12393

124-
node.close_channel(&user_channel_id, cln_node_id).unwrap();
125-
common::expect_event!(node, ChannelClosed);
94+
test_disconnect_reconnect_idle(&node, &cln, &bitcoind, &electrs, &Side::Ldk).await;
95+
test_disconnect_reconnect_idle(&node, &cln, &bitcoind, &electrs, &Side::External).await;
96+
97+
node.stop().unwrap();
98+
}
99+
100+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
101+
async fn test_cln_force_close_by_ldk() {
102+
let (bitcoind, electrs, cln) = setup_clients();
103+
cln.wait_for_sync().await;
104+
common::generate_blocks_and_wait(&bitcoind, &electrs, 1).await;
105+
106+
let node = setup_ldk_node();
107+
setup_interop_test(&node, &cln, &bitcoind, &electrs).await;
108+
let (user_ch, _ext_ch) =
109+
open_channel_to_external(&node, &cln, &bitcoind, &electrs, 1_000_000, Some(500_000_000))
110+
.await;
111+
112+
test_force_close_by_ldk(&node, &cln, &bitcoind, &electrs, &user_ch).await;
126113
node.stop().unwrap();
127114
}
115+
116+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
117+
async fn test_cln_force_close_by_external() {
118+
let (bitcoind, electrs, cln) = setup_clients();
119+
cln.wait_for_sync().await;
120+
common::generate_blocks_and_wait(&bitcoind, &electrs, 1).await;
121+
122+
let node = setup_ldk_node();
123+
setup_interop_test(&node, &cln, &bitcoind, &electrs).await;
124+
let (_user_ch, ext_ch) =
125+
open_channel_to_external(&node, &cln, &bitcoind, &electrs, 1_000_000, Some(500_000_000))
126+
.await;
127+
128+
test_force_close_by_external(&node, &cln, &bitcoind, &electrs, &ext_ch).await;
129+
node.stop().unwrap();
130+
}
131+
132+
proptest! {
133+
#![proptest_config(proptest::test_runner::Config::with_cases(8))]
134+
#[test]
135+
fn test_cln_interop_proptest(
136+
disconnect_phase in prop_oneof![
137+
Just(Phase::ChannelOpen),
138+
Just(Phase::Payment),
139+
Just(Phase::Close),
140+
Just(Phase::Idle),
141+
],
142+
disconnect_initiator in prop_oneof![Just(Side::Ldk), Just(Side::External)],
143+
close_type in prop_oneof![Just(CloseType::Cooperative), Just(CloseType::Force)],
144+
close_initiator in prop_oneof![Just(Side::Ldk), Just(Side::External)],
145+
payment_type in prop_oneof![Just(PayType::Bolt11), Just(PayType::Keysend)],
146+
) {
147+
let rt = tokio::runtime::Builder::new_multi_thread()
148+
.enable_all()
149+
.build()
150+
.unwrap();
151+
rt.block_on(async {
152+
let (bitcoind, electrs, cln) = setup_clients();
153+
cln.wait_for_sync().await;
154+
common::generate_blocks_and_wait(&bitcoind, &electrs, 1).await;
155+
156+
let node = setup_ldk_node();
157+
run_interop_property_test(
158+
&node, &cln, &bitcoind, &electrs,
159+
disconnect_phase, disconnect_initiator, close_type,
160+
close_initiator, payment_type,
161+
).await;
162+
node.stop().unwrap();
163+
});
164+
}
165+
}

0 commit comments

Comments
 (0)