Skip to content

Commit 1b8544f

Browse files
author
Antoine Riard
committed
Implement channel closing for block_disconnected on ChainListener + test
1 parent 55f5ce0 commit 1b8544f

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

src/ln/channel.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ const BOTH_SIDES_SHUTDOWN_MASK: u32 = (ChannelState::LocalShutdownSent as u32 |
231231

232232
// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
233233
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
234-
// calling get_channel_id() before we're set up or things like get_outbound_funding_signed on an
234+
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
235235
// inbound channel.
236236
pub struct Channel {
237237
user_id: u64,

src/ln/channelmanager.rs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,13 +1085,25 @@ impl ChainListener for ChannelManager {
10851085
}
10861086
}
10871087

1088+
/// We force-close the channel without letting our counterparty participate in the shutdown
10881089
fn block_disconnected(&self, header: &BlockHeader) {
1089-
let mut channel_state = self.channel_state.lock().unwrap();
1090-
for channel in channel_state.by_id.values_mut() {
1091-
if channel.block_disconnected(header) {
1092-
//TODO Close channel here
1090+
let mut channel_lock = self.channel_state.lock().unwrap();
1091+
let channel_state = channel_lock.borrow_parts();
1092+
let short_to_id = channel_state.short_to_id;
1093+
channel_state.by_id.retain(|_, v| {
1094+
if v.block_disconnected(header) {
1095+
let tx = v.force_shutdown();
1096+
for broadcast_tx in tx {
1097+
self.tx_broadcaster.broadcast_transaction(&broadcast_tx);
1098+
}
1099+
if let Some(short_id) = v.get_short_channel_id() {
1100+
short_to_id.remove(&short_id);
1101+
}
1102+
false
1103+
} else {
1104+
true
10931105
}
1094-
}
1106+
});
10951107
}
10961108
}
10971109

@@ -1816,6 +1828,7 @@ impl ChannelMessageHandler for ChannelManager {
18161828
mod tests {
18171829
use chain::chaininterface;
18181830
use chain::transaction::OutPoint;
1831+
use chain::chaininterface::ChainListener;
18191832
use ln::channelmanager::{ChannelManager,OnionKeys};
18201833
use ln::router::{Route, RouteHop, Router};
18211834
use ln::msgs;
@@ -2919,4 +2932,30 @@ mod tests {
29192932
assert_eq!(node.chan_monitor.added_monitors.lock().unwrap().len(), 0);
29202933
}
29212934
}
2935+
2936+
#[test]
2937+
fn test_unconf_chan() {
2938+
// After creating a chan between nodes, we disconnect all blocks previously seen to force a channel close on nodes[0] side
2939+
let nodes = create_network(2);
2940+
create_announced_chan_between_nodes(&nodes, 0, 1);
2941+
2942+
let channel_state = nodes[0].node.channel_state.lock().unwrap();
2943+
assert_eq!(channel_state.by_id.len(), 1);
2944+
assert_eq!(channel_state.short_to_id.len(), 1);
2945+
mem::drop(channel_state);
2946+
2947+
let mut headers = Vec::new();
2948+
let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
2949+
headers.push(header.clone());
2950+
for _i in 2..100 {
2951+
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
2952+
headers.push(header.clone());
2953+
}
2954+
while !headers.is_empty() {
2955+
nodes[0].node.block_disconnected(&headers.pop().unwrap());
2956+
}
2957+
let channel_state = nodes[0].node.channel_state.lock().unwrap();
2958+
assert_eq!(channel_state.by_id.len(), 0);
2959+
assert_eq!(channel_state.short_to_id.len(), 0);
2960+
}
29222961
}

0 commit comments

Comments
 (0)