Skip to content

Add Event::DiscardFunding generation #1098

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1901,6 +1901,15 @@ impl<Signer: Sign> Channel<Signer> {
Ok(())
}

/// Returns transaction if there is pending funding transaction that is yet to broadcast
pub fn unbroadcasted_funding(&self) -> Option<Transaction> {
if self.channel_state & (ChannelState::FundingCreated as u32) != 0 {
self.funding_transaction.clone()
} else {
None
}
}

/// Returns a HTLCStats about inbound pending htlcs
fn get_inbound_pending_htlc_stats(&self) -> HTLCStats {
let mut stats = HTLCStats {
Expand Down
41 changes: 21 additions & 20 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,18 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
self.list_channels_with_filter(|&(_, ref channel)| channel.is_live())
}

/// Helper function that issues the channel close events
fn issue_channel_close_events(&self, channel: &Channel<Signer>, closure_reason: ClosureReason) {
let mut pending_events_lock = self.pending_events.lock().unwrap();
match channel.unbroadcasted_funding() {
Some(transaction) => {
pending_events_lock.push(events::Event::DiscardFunding { channel_id: channel.channel_id(), transaction })
},
None => {},
}
pending_events_lock.push(events::Event::ChannelClosed { channel_id: channel.channel_id(), reason: closure_reason });
}

fn close_channel_internal(&self, channel_id: &[u8; 32], target_feerate_sats_per_1000_weight: Option<u32>) -> Result<(), APIError> {
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);

Expand Down Expand Up @@ -1372,12 +1384,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
msg: channel_update
});
}
if let Ok(mut pending_events_lock) = self.pending_events.lock() {
pending_events_lock.push(events::Event::ChannelClosed {
channel_id: *channel_id,
reason: ClosureReason::HolderForceClosed
});
}
self.issue_channel_close_events(&channel, ClosureReason::HolderForceClosed);
}
break Ok(());
},
Expand Down Expand Up @@ -1468,13 +1475,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
if let Some(short_id) = chan.get().get_short_channel_id() {
channel_state.short_to_id.remove(&short_id);
}
let mut pending_events_lock = self.pending_events.lock().unwrap();
if peer_node_id.is_some() {
if let Some(peer_msg) = peer_msg {
pending_events_lock.push(events::Event::ChannelClosed { channel_id: *channel_id, reason: ClosureReason::CounterpartyForceClosed { peer_msg: peer_msg.to_string() } });
self.issue_channel_close_events(chan.get(),ClosureReason::CounterpartyForceClosed { peer_msg: peer_msg.to_string() });
}
} else {
pending_events_lock.push(events::Event::ChannelClosed { channel_id: *channel_id, reason: ClosureReason::HolderForceClosed });
self.issue_channel_close_events(chan.get(),ClosureReason::HolderForceClosed);
}
chan.remove_entry().1
} else {
Expand Down Expand Up @@ -3574,7 +3580,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
msg: update
});
}
self.pending_events.lock().unwrap().push(events::Event::ChannelClosed { channel_id: msg.channel_id, reason: ClosureReason::CooperativeClosure });
self.issue_channel_close_events(&chan, ClosureReason::CooperativeClosure);
}
Ok(())
}
Expand Down Expand Up @@ -3986,7 +3992,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
msg: update
});
}
self.pending_events.lock().unwrap().push(events::Event::ChannelClosed { channel_id: chan.channel_id(), reason: ClosureReason::CommitmentTxConfirmed });
self.issue_channel_close_events(&chan, ClosureReason::CommitmentTxConfirmed);
pending_msg_events.push(events::MessageSendEvent::HandleError {
node_id: chan.get_counterparty_node_id(),
action: msgs::ErrorAction::SendErrorMessage {
Expand Down Expand Up @@ -4102,12 +4108,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
});
}

if let Ok(mut pending_events_lock) = self.pending_events.lock() {
pending_events_lock.push(events::Event::ChannelClosed {
channel_id: *channel_id,
reason: ClosureReason::CooperativeClosure
});
}
self.issue_channel_close_events(chan, ClosureReason::CooperativeClosure);

log_info!(self.logger, "Broadcasting {}", log_tx!(tx));
self.tx_broadcaster.broadcast_transaction(&tx);
Expand Down Expand Up @@ -4529,7 +4530,7 @@ where
msg: update
});
}
self.pending_events.lock().unwrap().push(events::Event::ChannelClosed { channel_id: channel.channel_id(), reason: ClosureReason::CommitmentTxConfirmed });
self.issue_channel_close_events(channel, ClosureReason::CommitmentTxConfirmed);
pending_msg_events.push(events::MessageSendEvent::HandleError {
node_id: channel.get_counterparty_node_id(),
action: msgs::ErrorAction::SendErrorMessage { msg: e },
Expand Down Expand Up @@ -4720,7 +4721,7 @@ impl<Signer: Sign, M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >
msg: update
});
}
self.pending_events.lock().unwrap().push(events::Event::ChannelClosed { channel_id: chan.channel_id(), reason: ClosureReason::DisconnectedPeer });
self.issue_channel_close_events(chan, ClosureReason::DisconnectedPeer);
false
} else {
true
Expand All @@ -4735,7 +4736,7 @@ impl<Signer: Sign, M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >
if let Some(short_id) = chan.get_short_channel_id() {
short_to_id.remove(&short_id);
}
self.pending_events.lock().unwrap().push(events::Event::ChannelClosed { channel_id: chan.channel_id(), reason: ClosureReason::DisconnectedPeer });
self.issue_channel_close_events(chan, ClosureReason::DisconnectedPeer);
return false;
} else {
no_channels_remain = false;
Expand Down
12 changes: 10 additions & 2 deletions lightning/src/ln/functional_test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -763,21 +763,29 @@ macro_rules! check_closed_broadcast {
}}
}

/// Check that a channel's closing channel event has been issued
/// Check that a channel's closing channel events has been issued
#[macro_export]
macro_rules! check_closed_event {
($node: expr, $events: expr, $reason: expr) => {{
($node: expr, $events: expr, $reason: expr) => {
check_closed_event!($node, $events, $reason, false);
};
($node: expr, $events: expr, $reason: expr, $is_check_discard_funding: expr) => {{
let events = $node.node.get_and_clear_pending_events();
assert_eq!(events.len(), $events);
let expected_reason = $reason;
let mut issues_discard_funding = false;
for event in events {
match event {
Event::ChannelClosed { ref reason, .. } => {
assert_eq!(*reason, expected_reason);
},
Event::DiscardFunding { .. } => {
issues_discard_funding = true;
}
_ => panic!("Unexpected event"),
}
}
assert_eq!($is_check_discard_funding, issues_discard_funding);
}}
}

Expand Down
2 changes: 1 addition & 1 deletion lightning/src/ln/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8632,7 +8632,7 @@ fn test_pre_lockin_no_chan_closed_update() {
let channel_id = ::chain::transaction::OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }.to_channel_id();
nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { channel_id, data: "Hi".to_owned() });
assert!(nodes[0].chain_monitor.added_monitors.lock().unwrap().is_empty());
check_closed_event!(nodes[0], 1, ClosureReason::CounterpartyForceClosed { peer_msg: "Hi".to_string() });
check_closed_event!(nodes[0], 2, ClosureReason::CounterpartyForceClosed { peer_msg: "Hi".to_string() }, true);
}

#[test]
Expand Down
25 changes: 25 additions & 0 deletions lightning/src/util/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use io;
use prelude::*;
use core::time::Duration;
use core::ops::Deref;
use bitcoin::Transaction;

/// Some information provided on receipt of payment depends on whether the payment received is a
/// spontaneous payment or a "conventional" lightning payment that's paying an invoice.
Expand Down Expand Up @@ -254,6 +255,14 @@ pub enum Event {
channel_id: [u8; 32],
/// The reason the channel was closed.
reason: ClosureReason
},
/// Used to indicate to the user that they can abandon the funding transaction and recycle the
/// inputs for another purpose.
DiscardFunding {
/// The channel_id of the channel which has been closed.
channel_id: [u8; 32],
/// The full transaction received from the user
transaction: Transaction
}
}

Expand Down Expand Up @@ -340,6 +349,13 @@ impl Writeable for Event {
(2, reason, required)
});
},
&Event::DiscardFunding { ref channel_id, ref transaction } => {
11u8.write(writer)?;
write_tlv_fields!(writer, {
(0, channel_id, required),
(2, transaction, required)
})
},
// Note that, going forward, all new events must only write data inside of
// `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
// data via `write_tlv_fields`.
Expand Down Expand Up @@ -471,6 +487,15 @@ impl MaybeReadable for Event {
if reason.is_none() { return Ok(None); }
Ok(Some(Event::ChannelClosed { channel_id, reason: reason.unwrap() }))
},
11u8 => {
let mut channel_id = [0; 32];
let mut transaction = Transaction{ version: 2, lock_time: 0, input: Vec::new(), output: Vec::new() };
read_tlv_fields!(reader, {
(0, channel_id, required),
(2, transaction, required),
});
Ok(Some(Event::DiscardFunding { channel_id, transaction } ))
},
// Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
// Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
// reads.
Expand Down