Skip to content

Commit ecabc18

Browse files
committed
test: openchannel lock release after peer goes offline
1 parent e931dba commit ecabc18

2 files changed

Lines changed: 106 additions & 0 deletions

File tree

src/test/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,6 +1892,7 @@ mod lock_unlock_changepassword;
18921892
mod multi_hop;
18931893
mod multi_open_close;
18941894
mod open_after_double_send;
1895+
mod openchannel_close_before_funding;
18951896
mod openchannel_fail;
18961897
mod openchannel_optional_addr;
18971898
mod openchannel_push_asset_amount;
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use super::*;
2+
3+
const TEST_DIR_BASE: &str = "tmp/openchannel_close_before_funding/";
4+
5+
/// Test that verifies the rgb_send_lock is released after a channel's peer goes
6+
/// offline, allowing the node to open new channels.
7+
///
8+
/// The key fixes tested here:
9+
/// - Release rgb_send_lock in FundingGenerationReady (after funding_transaction_generated)
10+
/// - Release rgb_send_lock in ChannelClosed (when channel_funding_txo is None)
11+
/// - Release rgb_send_lock in ChannelPending before broadcast (send_btc_end)
12+
///
13+
/// Without these fixes, the lock remains stuck and the node cannot open new
14+
/// channels after a peer disconnects during the channel opening process.
15+
#[serial_test::serial]
16+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
17+
#[traced_test]
18+
async fn openchannel_peer_offline_releases_lock() {
19+
initialize();
20+
21+
let test_dir_node1 = format!("{TEST_DIR_BASE}node1");
22+
let test_dir_node2 = format!("{TEST_DIR_BASE}node2");
23+
let test_dir_node3 = format!("{TEST_DIR_BASE}node3");
24+
let (node1_addr, _) = start_node(&test_dir_node1, NODE1_PEER_PORT, false).await;
25+
let (node2_addr, _) = start_node(&test_dir_node2, NODE2_PEER_PORT, false).await;
26+
27+
fund_and_create_utxos(node1_addr, Some(5)).await;
28+
29+
let node2_pubkey = node_info(node2_addr).await.pubkey;
30+
31+
// Open a vanilla (non-RGB) channel from node1 to node2
32+
let payload = OpenChannelRequest {
33+
peer_pubkey_and_opt_addr: format!("{node2_pubkey}@127.0.0.1:{NODE2_PEER_PORT}"),
34+
capacity_sat: 100_000,
35+
push_msat: 0,
36+
asset_amount: None,
37+
asset_id: None,
38+
push_asset_amount: None,
39+
public: true,
40+
with_anchors: true,
41+
fee_base_msat: None,
42+
fee_proportional_millionths: None,
43+
temporary_channel_id: None,
44+
};
45+
let res = reqwest::Client::new()
46+
.post(format!("http://{node1_addr}/openchannel"))
47+
.json(&payload)
48+
.send()
49+
.await
50+
.unwrap();
51+
assert_eq!(res.status(), reqwest::StatusCode::OK);
52+
53+
// Shut down node2; the channel will fail before confirmation
54+
shutdown(&[node2_addr]).await;
55+
56+
// Start node3 and try to open a new channel from node1
57+
let (node3_addr, _) = start_node(&test_dir_node3, NODE3_PEER_PORT, false).await;
58+
fund_and_create_utxos(node3_addr, None).await;
59+
let node3_pubkey = node_info(node3_addr).await.pubkey;
60+
61+
// Poll until the rgb_send_lock is released and we can open a new channel.
62+
// Without the fixes, this would remain stuck at 403 (OpenChannelInProgress)
63+
// because the lock was never released after the first channel's peer went
64+
// offline.
65+
let t_0 = OffsetDateTime::now_utc();
66+
loop {
67+
let payload = OpenChannelRequest {
68+
peer_pubkey_and_opt_addr: format!("{node3_pubkey}@127.0.0.1:{NODE3_PEER_PORT}"),
69+
capacity_sat: 100_000,
70+
push_msat: 0,
71+
asset_amount: None,
72+
asset_id: None,
73+
push_asset_amount: None,
74+
public: true,
75+
with_anchors: true,
76+
fee_base_msat: None,
77+
fee_proportional_millionths: None,
78+
temporary_channel_id: None,
79+
};
80+
let res = reqwest::Client::new()
81+
.post(format!("http://{node1_addr}/openchannel"))
82+
.json(&payload)
83+
.send()
84+
.await
85+
.unwrap();
86+
87+
if res.status() == reqwest::StatusCode::OK {
88+
// Lock was released and the new channel open succeeded
89+
break;
90+
}
91+
92+
assert_eq!(
93+
res.status(),
94+
reqwest::StatusCode::FORBIDDEN,
95+
"unexpected error status when opening channel to node3"
96+
);
97+
98+
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
99+
if (OffsetDateTime::now_utc() - t_0).as_seconds_f32() > 60.0 {
100+
panic!("rgb_send_lock remained stuck for 60s after peer shutdown - node cannot open new channels");
101+
}
102+
}
103+
104+
shutdown(&[node1_addr, node3_addr]).await;
105+
}

0 commit comments

Comments
 (0)