Skip to content

Commit 4cb059e

Browse files
authored
Merge pull request #210 from TheBlueMatt/2018-10-funding-disconnected
Fix + test funding tx confirmation while peer is disconnected
2 parents 41f1e16 + 1fe616d commit 4cb059e

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

src/ln/channel.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ enum ChannelState {
269269
ShutdownComplete = 2048,
270270
}
271271
const BOTH_SIDES_SHUTDOWN_MASK: u32 = (ChannelState::LocalShutdownSent as u32 | ChannelState::RemoteShutdownSent as u32);
272+
const MULTI_STATE_FLAGS: u32 = (BOTH_SIDES_SHUTDOWN_MASK | ChannelState::PeerDisconnected as u32);
272273

273274
const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
274275

@@ -2560,7 +2561,7 @@ impl Channel {
25602561
/// apply - no calls may be made except those explicitly stated to be allowed post-shutdown.
25612562
/// Only returns an ErrorAction of DisconnectPeer, if Err.
25622563
pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<Option<msgs::FundingLocked>, HandleError> {
2563-
let non_shutdown_state = self.channel_state & (!BOTH_SIDES_SHUTDOWN_MASK);
2564+
let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
25642565
if self.funding_tx_confirmations > 0 {
25652566
if header.bitcoin_hash() != self.last_block_connected {
25662567
self.last_block_connected = header.bitcoin_hash();
@@ -2570,10 +2571,10 @@ impl Channel {
25702571
self.channel_state |= ChannelState::OurFundingLocked as u32;
25712572
true
25722573
} else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) {
2573-
self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & BOTH_SIDES_SHUTDOWN_MASK);
2574+
self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS);
25742575
self.channel_update_count += 1;
25752576
true
2576-
} else if self.channel_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) {
2577+
} else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) {
25772578
// We got a reorg but not enough to trigger a force close, just update
25782579
// funding_tx_confirmed_in and return.
25792580
false

src/ln/channelmanager.rs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2574,7 +2574,7 @@ mod tests {
25742574
(announcement, as_update, bs_update, channel_id, tx)
25752575
}
25762576

2577-
fn create_chan_between_nodes_with_value_a(node_a: &Node, node_b: &Node, channel_value: u64, push_msat: u64) -> ((msgs::FundingLocked, msgs::AnnouncementSignatures), [u8; 32], Transaction) {
2577+
fn create_chan_between_nodes_with_value_init(node_a: &Node, node_b: &Node, channel_value: u64, push_msat: u64) -> Transaction {
25782578
node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42).unwrap();
25792579

25802580
let events_1 = node_a.node.get_and_clear_pending_events();
@@ -2647,7 +2647,11 @@ mod tests {
26472647
_ => panic!("Unexpected event"),
26482648
};
26492649

2650-
confirm_transaction(&node_b.chain_monitor, &tx, chan_id);
2650+
tx
2651+
}
2652+
2653+
fn create_chan_between_nodes_with_value_confirm(node_a: &Node, node_b: &Node, tx: &Transaction) -> ((msgs::FundingLocked, msgs::AnnouncementSignatures), [u8; 32]) {
2654+
confirm_transaction(&node_b.chain_monitor, &tx, tx.version);
26512655
let events_5 = node_b.node.get_and_clear_pending_events();
26522656
assert_eq!(events_5.len(), 1);
26532657
match events_5[0] {
@@ -2661,7 +2665,7 @@ mod tests {
26612665

26622666
let channel_id;
26632667

2664-
confirm_transaction(&node_a.chain_monitor, &tx, chan_id);
2668+
confirm_transaction(&node_a.chain_monitor, &tx, tx.version);
26652669
let events_6 = node_a.node.get_and_clear_pending_events();
26662670
assert_eq!(events_6.len(), 1);
26672671
(match events_6[0] {
@@ -2671,7 +2675,13 @@ mod tests {
26712675
(msg.clone(), announcement_sigs.clone().unwrap())
26722676
},
26732677
_ => panic!("Unexpected event"),
2674-
}, channel_id, tx)
2678+
}, channel_id)
2679+
}
2680+
2681+
fn create_chan_between_nodes_with_value_a(node_a: &Node, node_b: &Node, channel_value: u64, push_msat: u64) -> ((msgs::FundingLocked, msgs::AnnouncementSignatures), [u8; 32], Transaction) {
2682+
let tx = create_chan_between_nodes_with_value_init(node_a, node_b, channel_value, push_msat);
2683+
let (msgs, chan_id) = create_chan_between_nodes_with_value_confirm(node_a, node_b, &tx);
2684+
(msgs, chan_id, tx)
26752685
}
26762686

26772687
fn create_chan_between_nodes_with_value_b(node_a: &Node, node_b: &Node, as_funding_msgs: &(msgs::FundingLocked, msgs::AnnouncementSignatures)) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate) {
@@ -5038,6 +5048,47 @@ mod tests {
50385048
do_test_drop_messages_peer_disconnect(5);
50395049
}
50405050

5051+
#[test]
5052+
fn test_funding_peer_disconnect() {
5053+
// Test that we can lock in our funding tx while disconnected
5054+
let nodes = create_network(2);
5055+
let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001);
5056+
5057+
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
5058+
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
5059+
5060+
confirm_transaction(&nodes[0].chain_monitor, &tx, tx.version);
5061+
let events_1 = nodes[0].node.get_and_clear_pending_events();
5062+
assert_eq!(events_1.len(), 1);
5063+
match events_1[0] {
5064+
Event::SendFundingLocked { ref node_id, msg: _, ref announcement_sigs } => {
5065+
assert_eq!(*node_id, nodes[1].node.get_our_node_id());
5066+
assert!(announcement_sigs.is_none());
5067+
},
5068+
_ => panic!("Unexpected event"),
5069+
}
5070+
5071+
confirm_transaction(&nodes[1].chain_monitor, &tx, tx.version);
5072+
let events_2 = nodes[1].node.get_and_clear_pending_events();
5073+
assert_eq!(events_2.len(), 1);
5074+
match events_2[0] {
5075+
Event::SendFundingLocked { ref node_id, msg: _, ref announcement_sigs } => {
5076+
assert_eq!(*node_id, nodes[0].node.get_our_node_id());
5077+
assert!(announcement_sigs.is_none());
5078+
},
5079+
_ => panic!("Unexpected event"),
5080+
}
5081+
5082+
reconnect_nodes(&nodes[0], &nodes[1], true, (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
5083+
5084+
// TODO: We shouldn't need to manually pass list_usable_chanels here once we support
5085+
// rebroadcasting announcement_signatures upon reconnect.
5086+
5087+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), Some(&nodes[0].node.list_usable_channels()), &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
5088+
let (payment_preimage, _) = send_along_route(&nodes[0], route, &[&nodes[1]], 1000000);
5089+
claim_payment(&nodes[0], &[&nodes[1]], payment_preimage);
5090+
}
5091+
50415092
#[test]
50425093
fn test_invalid_channel_announcement() {
50435094
//Test BOLT 7 channel_announcement msg requirement for final node, gather data to build customed channel_announcement msgs

0 commit comments

Comments
 (0)