|
| 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