Skip to content

Commit f76dfc4

Browse files
author
Antoine Riard
committed
Implement delay channel closing in ChannelManager until maturation
Add pruning of waiting-conf channel closing at block_disconnect Fix tests broken by introduced change
1 parent f69d9ca commit f76dfc4

File tree

2 files changed

+206
-117
lines changed

2 files changed

+206
-117
lines changed

src/ln/channelmanager.rs

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ pub struct ChannelManager {
332332
channel_state: Mutex<ChannelHolder>,
333333
our_network_key: SecretKey,
334334

335+
channel_closing_waiting_threshold_conf: Mutex<HashMap<u32, Vec<[u8; 32]>>>,
336+
335337
pending_events: Mutex<Vec<events::Event>>,
336338
/// Used when we have to take a BIG lock to make sure everything is self-consistent.
337339
/// Essentially just when we're serializing ourselves out.
@@ -556,6 +558,8 @@ impl ChannelManager {
556558
}),
557559
our_network_key: keys_manager.get_node_secret(),
558560

561+
channel_closing_waiting_threshold_conf: Mutex::new(HashMap::new()),
562+
559563
pending_events: Mutex::new(Vec::new()),
560564
total_consistency_lock: RwLock::new(()),
561565

@@ -2400,11 +2404,12 @@ impl ChainListener for ChannelManager {
24002404
let _ = self.total_consistency_lock.read().unwrap();
24012405
let mut failed_channels = Vec::new();
24022406
{
2407+
let mut channel_closing_lock = self.channel_closing_waiting_threshold_conf.lock().unwrap();
24032408
let mut channel_lock = self.channel_state.lock().unwrap();
24042409
let channel_state = channel_lock.borrow_parts();
24052410
let short_to_id = channel_state.short_to_id;
24062411
let pending_msg_events = channel_state.pending_msg_events;
2407-
channel_state.by_id.retain(|_, channel| {
2412+
channel_state.by_id.retain(|channel_id, channel| {
24082413
let chan_res = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched);
24092414
if let Ok(Some(funding_locked)) = chan_res {
24102415
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
@@ -2429,20 +2434,24 @@ impl ChainListener for ChannelManager {
24292434
for tx in txn_matched {
24302435
for inp in tx.input.iter() {
24312436
if inp.previous_output == funding_txo.into_bitcoin_outpoint() {
2432-
log_trace!(self, "Detected channel-closing tx {} spending {}:{}, closing channel {}", tx.txid(), inp.previous_output.txid, inp.previous_output.vout, log_bytes!(channel.channel_id()));
2433-
if let Some(short_id) = channel.get_short_channel_id() {
2434-
short_to_id.remove(&short_id);
2435-
}
2436-
// It looks like our counterparty went on-chain. We go ahead and
2437-
// broadcast our latest local state as well here, just in case its
2438-
// some kind of SPV attack, though we expect these to be dropped.
2439-
failed_channels.push(channel.force_shutdown());
2440-
if let Ok(update) = self.get_channel_update(&channel) {
2441-
pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
2442-
msg: update
2443-
});
2437+
log_trace!(self, "Detected channel-closing tx {} spending {}:{}, waiting until {} to close channel {}", tx.txid(), inp.previous_output.txid, inp.previous_output.vout, height + HTLC_FAIL_ANTI_REORG_DELAY - 1, log_bytes!(channel_id[..]));
2438+
match channel_closing_lock.entry(height + HTLC_FAIL_ANTI_REORG_DELAY - 1) {
2439+
hash_map::Entry::Occupied(mut entry) => {
2440+
let mut duplicate = false;
2441+
for id in entry.get().iter() {
2442+
if *id == *channel_id {
2443+
duplicate = true;
2444+
break;
2445+
}
2446+
}
2447+
if !duplicate {
2448+
entry.get_mut().push(*channel_id);
2449+
}
2450+
}
2451+
hash_map::Entry::Vacant(entry) => {
2452+
entry.insert(vec![*channel_id]);
2453+
}
24442454
}
2445-
return false;
24462455
}
24472456
}
24482457
}
@@ -2465,6 +2474,25 @@ impl ChainListener for ChannelManager {
24652474
}
24662475
true
24672476
});
2477+
if let Some(channel_closings) = channel_closing_lock.remove(&height) {
2478+
for channel_id in channel_closings {
2479+
log_trace!(self, "Enough confirmations for a broacast commitment tx, channel {} can be closed", log_bytes!(&channel_id[..]));
2480+
if let Some(mut channel) = channel_state.by_id.remove(&channel_id) {
2481+
if let Some(short_id) = channel.get_short_channel_id() {
2482+
short_to_id.remove(&short_id);
2483+
}
2484+
// It looks like our counterparty went on-chain. We go ahead and
2485+
// broadcast our latest local state as well here, just in case its
2486+
// some kind of SPV attack, though we expect these to be dropped.
2487+
failed_channels.push(channel.force_shutdown());
2488+
if let Ok(update) = self.get_channel_update(&channel) {
2489+
pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
2490+
msg: update
2491+
});
2492+
}
2493+
}
2494+
}
2495+
}
24682496
}
24692497
for failure in failed_channels.drain(..) {
24702498
self.finish_force_close_channel(failure);
@@ -2474,7 +2502,7 @@ impl ChainListener for ChannelManager {
24742502
}
24752503

24762504
/// We force-close the channel without letting our counterparty participate in the shutdown
2477-
fn block_disconnected(&self, header: &BlockHeader, _: u32) {
2505+
fn block_disconnected(&self, header: &BlockHeader, height: u32) {
24782506
let _ = self.total_consistency_lock.read().unwrap();
24792507
let mut failed_channels = Vec::new();
24802508
{
@@ -2499,6 +2527,12 @@ impl ChainListener for ChannelManager {
24992527
}
25002528
});
25012529
}
2530+
{
2531+
let mut channel_closing_lock = self.channel_closing_waiting_threshold_conf.lock().unwrap();
2532+
if let Some(_) = channel_closing_lock.remove(&(height + HTLC_FAIL_ANTI_REORG_DELAY - 1)) {
2533+
// We discard channel_closing there as brooadcast commitment tx has been disconnected, (and may be replaced by a legit closing_signed)
2534+
}
2535+
}
25022536
for failure in failed_channels.drain(..) {
25032537
self.finish_force_close_channel(failure);
25042538
}
@@ -2936,6 +2970,15 @@ impl Writeable for ChannelManager {
29362970
}
29372971
}
29382972

2973+
let channel_closing_lock = self.channel_closing_waiting_threshold_conf.lock().unwrap();
2974+
(channel_closing_lock.len() as u64).write(writer)?;
2975+
for (confirmation_height, channel_id) in channel_closing_lock.iter() {
2976+
confirmation_height.write(writer)?;
2977+
for id in channel_id {
2978+
id.write(writer)?;
2979+
}
2980+
}
2981+
29392982
Ok(())
29402983
}
29412984
}
@@ -3073,6 +3116,21 @@ impl<'a, R : ::std::io::Read> ReadableArgs<R, ChannelManagerReadArgs<'a>> for (S
30733116
claimable_htlcs.insert(payment_hash, previous_hops);
30743117
}
30753118

3119+
let channel_closing_count: u64 = Readable::read(reader)?;
3120+
let mut channel_closing: HashMap<u32, Vec<[u8; 32]>> = HashMap::with_capacity(cmp::min(channel_closing_count as usize, 32));
3121+
for _ in 0..channel_closing_count {
3122+
let confirmation_height: u32 = Readable::read(reader)?;
3123+
let channel_id: [u8; 32] = Readable::read(reader)?;
3124+
match channel_closing.entry(confirmation_height) {
3125+
hash_map::Entry::Occupied(mut entry) => {
3126+
entry.get_mut().push(channel_id);
3127+
}
3128+
hash_map::Entry::Vacant(entry) => {
3129+
entry.insert(vec![channel_id]);
3130+
}
3131+
}
3132+
}
3133+
30763134
let channel_manager = ChannelManager {
30773135
genesis_hash,
30783136
fee_estimator: args.fee_estimator,
@@ -3094,6 +3152,8 @@ impl<'a, R : ::std::io::Read> ReadableArgs<R, ChannelManagerReadArgs<'a>> for (S
30943152
}),
30953153
our_network_key: args.keys_manager.get_node_secret(),
30963154

3155+
channel_closing_waiting_threshold_conf: Mutex::new(channel_closing),
3156+
30973157
pending_events: Mutex::new(Vec::new()),
30983158
total_consistency_lock: RwLock::new(()),
30993159
keys_manager: args.keys_manager,

0 commit comments

Comments
 (0)