Skip to content

Commit a703e18

Browse files
committed
Refactor CLN/LND tests and add Eclair test entry points
1 parent 3a101b7 commit a703e18

3 files changed

Lines changed: 411 additions & 269 deletions

File tree

tests/integration_tests_cln.rs

Lines changed: 129 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -9,119 +9,158 @@
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;
2117
use ldk_node::bitcoin::Amount;
22-
use ldk_node::lightning::ln::msgs::SocketAddress;
2318
use ldk_node::{Builder, Event};
24-
use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, Description};
25-
use rand::distr::Alphanumeric;
26-
use rand::{rng, Rng};
19+
use proptest::prelude::*;
20+
use proptest::proptest;
2721

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(
22+
use common::cln::TestClnNode;
23+
use common::external_node::ExternalNode;
24+
use common::scenarios::*;
25+
26+
fn setup_clients() -> (BitcoindClient, ElectrumClient, TestClnNode) {
27+
let bitcoind = BitcoindClient::new_with_auth(
3228
"http://127.0.0.1:18443",
3329
Auth::UserPass("user".to_string(), "pass".to_string()),
3430
)
3531
.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;
32+
let electrs = ElectrumClient::new("tcp://127.0.0.1:50001").unwrap();
33+
let cln = TestClnNode::from_env();
34+
(bitcoind, electrs, cln)
35+
}
4036

41-
// Setup LDK Node
37+
fn setup_ldk_node() -> ldk_node::Node {
4238
let config = common::random_config(true);
4339
let mut builder = Builder::from_config(config.node_config);
4440
builder.set_chain_source_esplora("http://127.0.0.1:3002".to_string(), None);
45-
4641
let node = builder.build(config.node_entropy).unwrap();
4742
node.start().unwrap();
43+
node
44+
}
4845

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)
46+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
47+
async fn test_cln_basic_channel_cycle() {
48+
let (bitcoind, electrs, cln) = setup_clients();
49+
cln.wait_for_sync().await;
50+
common::generate_blocks_and_wait(&bitcoind, &electrs, 1).await;
51+
52+
let node = setup_ldk_node();
53+
setup_interop_test(&node, &cln, &bitcoind, &electrs).await;
54+
55+
let (user_channel_id, _ext_channel_id) =
56+
open_channel_to_external(&node, &cln, &bitcoind, &electrs, 1_000_000, Some(500_000_000))
57+
.await;
58+
59+
// LDK -> CLN payment
60+
let invoice = cln.create_invoice(10_000_000, "cln-test-send").await.unwrap();
61+
let parsed = lightning_invoice::Bolt11Invoice::from_str(&invoice).unwrap();
62+
node.bolt11_payment().send(&parsed, None).unwrap();
63+
common::expect_event!(node, PaymentSuccessful);
64+
65+
// CLN -> LDK payment
66+
let ldk_invoice = node
67+
.bolt11_payment()
68+
.receive(
69+
10_000_000,
70+
&lightning_invoice::Bolt11InvoiceDescription::Direct(
71+
lightning_invoice::Description::new("cln-test-recv".to_string()).unwrap(),
72+
),
73+
3600,
74+
)
9375
.unwrap();
76+
cln.pay_invoice(&ldk_invoice.to_string()).await.unwrap();
77+
common::expect_event!(node, PaymentReceived);
9478

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);
79+
test_cooperative_close_by_ldk(&node, &cln, &user_channel_id).await;
80+
node.stop().unwrap();
81+
}
10082

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();
83+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
84+
async fn test_cln_disconnect_reconnect() {
85+
let (bitcoind, electrs, cln) = setup_clients();
86+
cln.wait_for_sync().await;
87+
common::generate_blocks_and_wait(&bitcoind, &electrs, 1).await;
10788

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);
89+
let node = setup_ldk_node();
90+
setup_interop_test(&node, &cln, &bitcoind, &electrs).await;
91+
let (_user_ch, _ext_ch) =
92+
open_channel_to_external(&node, &cln, &bitcoind, &electrs, 1_000_000, Some(500_000_000))
93+
.await;
12394

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

0 commit comments

Comments
 (0)