Skip to content

Commit b5147da

Browse files
committed
Lock outbound channels at 0conf if the peer indicates support for it
1 parent 7836d6b commit b5147da

File tree

4 files changed

+122
-34
lines changed

4 files changed

+122
-34
lines changed

lightning/src/ln/channel.rs

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,12 +1941,6 @@ impl<Signer: Sign> Channel<Signer> {
19411941
if msg.minimum_depth > peer_limits.max_minimum_depth {
19421942
return Err(ChannelError::Close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", peer_limits.max_minimum_depth, msg.minimum_depth)));
19431943
}
1944-
if msg.minimum_depth == 0 {
1945-
// Note that if this changes we should update the serialization minimum version to
1946-
// indicate to older clients that they don't understand some features of the current
1947-
// channel.
1948-
return Err(ChannelError::Close("Minimum confirmation depth must be at least 1".to_owned()));
1949-
}
19501944

19511945
if let Some(ty) = &msg.channel_type {
19521946
if *ty != self.channel_type {
@@ -1983,7 +1977,12 @@ impl<Signer: Sign> Channel<Signer> {
19831977
self.counterparty_selected_channel_reserve_satoshis = Some(msg.channel_reserve_satoshis);
19841978
self.counterparty_htlc_minimum_msat = msg.htlc_minimum_msat;
19851979
self.counterparty_max_accepted_htlcs = msg.max_accepted_htlcs;
1986-
self.minimum_depth = Some(msg.minimum_depth);
1980+
1981+
if peer_limits.trust_own_funding_0conf {
1982+
self.minimum_depth = Some(msg.minimum_depth);
1983+
} else {
1984+
self.minimum_depth = Some(cmp::max(1, msg.minimum_depth));
1985+
}
19871986

19881987
let counterparty_pubkeys = ChannelPublicKeys {
19891988
funding_pubkey: msg.funding_pubkey,
@@ -2123,7 +2122,7 @@ impl<Signer: Sign> Channel<Signer> {
21232122

21242123
/// Handles a funding_signed message from the remote end.
21252124
/// If this call is successful, broadcast the funding transaction (and not before!)
2126-
pub fn funding_signed<L: Deref>(&mut self, msg: &msgs::FundingSigned, best_block: BestBlock, logger: &L) -> Result<(ChannelMonitor<Signer>, Transaction), ChannelError> where L::Target: Logger {
2125+
pub fn funding_signed<L: Deref>(&mut self, msg: &msgs::FundingSigned, best_block: BestBlock, logger: &L) -> Result<(ChannelMonitor<Signer>, Transaction, Option<msgs::FundingLocked>), ChannelError> where L::Target: Logger {
21272126
if !self.is_outbound() {
21282127
return Err(ChannelError::Close("Received funding_signed for an inbound channel?".to_owned()));
21292128
}
@@ -2192,7 +2191,7 @@ impl<Signer: Sign> Channel<Signer> {
21922191

21932192
log_info!(logger, "Received funding_signed from peer for channel {}", log_bytes!(self.channel_id()));
21942193

2195-
Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap()))
2194+
Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap(), self.check_get_funding_locked(0)))
21962195
}
21972196

21982197
/// Handles a funding_locked message from our peer. If we've already sent our funding_locked
@@ -3495,12 +3494,13 @@ impl<Signer: Sign> Channel<Signer> {
34953494
/// monitor update failure must *not* have been sent to the remote end, and must instead
34963495
/// have been dropped. They will be regenerated when monitor_updating_restored is called.
34973496
pub fn monitor_update_failed(&mut self, resend_raa: bool, resend_commitment: bool,
3498-
mut pending_forwards: Vec<(PendingHTLCInfo, u64)>,
3497+
resend_funding_locked: bool, mut pending_forwards: Vec<(PendingHTLCInfo, u64)>,
34993498
mut pending_fails: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>,
35003499
mut pending_finalized_claimed_htlcs: Vec<HTLCSource>
35013500
) {
35023501
self.monitor_pending_revoke_and_ack |= resend_raa;
35033502
self.monitor_pending_commitment_signed |= resend_commitment;
3503+
self.monitor_pending_funding_locked |= resend_funding_locked;
35043504
self.monitor_pending_forwards.append(&mut pending_forwards);
35053505
self.monitor_pending_failures.append(&mut pending_fails);
35063506
self.monitor_pending_finalized_fulfills.append(&mut pending_finalized_claimed_htlcs);
@@ -3514,17 +3514,27 @@ impl<Signer: Sign> Channel<Signer> {
35143514
assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, ChannelState::MonitorUpdateFailed as u32);
35153515
self.channel_state &= !(ChannelState::MonitorUpdateFailed as u32);
35163516

3517-
let funding_broadcastable = if self.channel_state & (ChannelState::FundingSent as u32) != 0 && self.is_outbound() {
3518-
self.funding_transaction.take()
3519-
} else { None };
3517+
// If we're past (or at) the FundingSent stage on an outbound channel, try to
3518+
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
3519+
// first received the funding_signed.
3520+
let mut funding_broadcastable =
3521+
if self.is_outbound() && self.channel_state & !MULTI_STATE_FLAGS >= ChannelState::FundingSent as u32 {
3522+
self.funding_transaction.take()
3523+
} else { None };
3524+
// That said, if the funding transaction is already confirmed (ie we're active with a
3525+
// minimum_depth over 0, don't bother re-broadcasting the confirmed funding tx.
3526+
if self.channel_state & !MULTI_STATE_FLAGS >= ChannelState::ChannelFunded as u32 && self.minimum_depth != Some(0) {
3527+
funding_broadcastable = None;
3528+
}
35203529

35213530
// We will never broadcast the funding transaction when we're in MonitorUpdateFailed (and
35223531
// we assume the user never directly broadcasts the funding transaction and waits for us to
35233532
// do it). Thus, we can only ever hit monitor_pending_funding_locked when we're an inbound
35243533
// channel which failed to persist the monitor on funding_created, and we got the funding
35253534
// transaction confirmed before the monitor was persisted.
35263535
let funding_locked = if self.monitor_pending_funding_locked {
3527-
assert!(!self.is_outbound(), "Funding transaction broadcast by the local client before it should have - LDK didn't do it!");
3536+
assert!(!self.is_outbound() || self.minimum_depth == Some(0),
3537+
"Funding transaction broadcast by the local client before it should have - LDK didn't do it!");
35283538
self.monitor_pending_funding_locked = false;
35293539
let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx);
35303540
Some(msgs::FundingLocked {
@@ -4476,6 +4486,11 @@ impl<Signer: Sign> Channel<Signer> {
44764486
self.channel_state >= ChannelState::FundingSent as u32
44774487
}
44784488

4489+
/// Returns true if our funding_locked has been sent
4490+
pub fn is_our_funding_locked(&self) -> bool {
4491+
(self.channel_state & ChannelState::OurFundingLocked as u32) != 0 || self.channel_state >= ChannelState::ChannelFunded as u32
4492+
}
4493+
44794494
/// Returns true if our peer has either initiated or agreed to shut down the channel.
44804495
pub fn received_shutdown(&self) -> bool {
44814496
(self.channel_state & ChannelState::RemoteShutdownSent as u32) != 0
@@ -4506,7 +4521,7 @@ impl<Signer: Sign> Channel<Signer> {
45064521
}
45074522

45084523
fn check_get_funding_locked(&mut self, height: u32) -> Option<msgs::FundingLocked> {
4509-
if self.funding_tx_confirmation_height == 0 {
4524+
if self.funding_tx_confirmation_height == 0 && self.minimum_depth != Some(0) {
45104525
return None;
45114526
}
45124527

@@ -4682,6 +4697,10 @@ impl<Signer: Sign> Channel<Signer> {
46824697
// the funding transaction's confirmation count has dipped below minimum_depth / 2,
46834698
// close the channel and hope we can get the latest state on chain (because presumably
46844699
// the funding transaction is at least still in the mempool of most nodes).
4700+
//
4701+
// Note that ideally we wouldn't force-close if we see *any* reorg on a 1-conf or
4702+
// 0-conf funding channel, but doing not doing so may lead to the
4703+
// `ChannelManager::short_to_id` map being inconsistent, so we currently have to.
46854704
if funding_tx_confirmations < self.minimum_depth.unwrap() as i64 / 2 {
46864705
let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.",
46874706
self.minimum_depth.unwrap(), funding_tx_confirmations);
@@ -5540,7 +5559,7 @@ impl<Signer: Sign> Channel<Signer> {
55405559
}
55415560

55425561
const SERIALIZATION_VERSION: u8 = 2;
5543-
const MIN_SERIALIZATION_VERSION: u8 = 1;
5562+
const MIN_SERIALIZATION_VERSION: u8 = 2;
55445563

55455564
impl_writeable_tlv_based_enum!(InboundHTLCRemovalReason,;
55465565
(0, FailRelay),
@@ -5605,12 +5624,10 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
56055624

56065625
self.user_id.write(writer)?;
56075626

5608-
// Write out the old serialization for the config object. This is read by version-1
5609-
// deserializers, but we will read the version in the TLV at the end instead.
5610-
self.config.forwarding_fee_proportional_millionths.write(writer)?;
5611-
self.config.cltv_expiry_delta.write(writer)?;
5612-
self.config.announced_channel.write(writer)?;
5613-
self.config.commit_upfront_shutdown_pubkey.write(writer)?;
5627+
// Version 1 deserializers expected to read parts of the config object here. Version 2
5628+
// deserializers (0.0.99) now read config through TLVs, and as we now require them for
5629+
// `minimum_depth` we simply write dummy values here.
5630+
writer.write_all(&[0; 8])?;
56145631

56155632
self.channel_id.write(writer)?;
56165633
(self.channel_state | ChannelState::PeerDisconnected as u32).write(writer)?;

lightning/src/ln/channelmanager.rs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,7 @@ macro_rules! remove_channel {
15261526
}
15271527

15281528
macro_rules! handle_monitor_err {
1529-
($self: ident, $err: expr, $short_to_id: expr, $chan: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr, $chan_id: expr) => {
1529+
($self: ident, $err: expr, $short_to_id: expr, $chan: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $resend_funding_locked: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr, $chan_id: expr) => {
15301530
match $err {
15311531
ChannelMonitorUpdateErr::PermanentFailure => {
15321532
log_error!($self.logger, "Closing channel {} due to monitor update ChannelMonitorUpdateErr::PermanentFailure", log_bytes!($chan_id[..]));
@@ -1564,30 +1564,33 @@ macro_rules! handle_monitor_err {
15641564
if !$resend_raa {
15651565
debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst || !$resend_commitment);
15661566
}
1567-
$chan.monitor_update_failed($resend_raa, $resend_commitment, $failed_forwards, $failed_fails, $failed_finalized_fulfills);
1567+
$chan.monitor_update_failed($resend_raa, $resend_commitment, $resend_funding_locked, $failed_forwards, $failed_fails, $failed_finalized_fulfills);
15681568
(Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore("Failed to update ChannelMonitor".to_owned()), *$chan_id)), false)
15691569
},
15701570
}
15711571
};
1572-
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr) => { {
1573-
let (res, drop) = handle_monitor_err!($self, $err, $channel_state.short_to_id, $entry.get_mut(), $action_type, $resend_raa, $resend_commitment, $failed_forwards, $failed_fails, $failed_finalized_fulfills, $entry.key());
1572+
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $resend_funding_locked: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr) => { {
1573+
let (res, drop) = handle_monitor_err!($self, $err, $channel_state.short_to_id, $entry.get_mut(), $action_type, $resend_raa, $resend_commitment, $resend_funding_locked, $failed_forwards, $failed_fails, $failed_finalized_fulfills, $entry.key());
15741574
if drop {
15751575
$entry.remove_entry();
15761576
}
15771577
res
15781578
} };
15791579
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $chan_id: expr, COMMITMENT_UPDATE_ONLY) => { {
15801580
debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst);
1581-
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, true, Vec::new(), Vec::new(), Vec::new(), $chan_id)
1581+
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, true, false, Vec::new(), Vec::new(), Vec::new(), $chan_id)
15821582
} };
15831583
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $chan_id: expr, NO_UPDATE) => {
1584-
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, Vec::new(), Vec::new(), Vec::new(), $chan_id)
1584+
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, false, Vec::new(), Vec::new(), Vec::new(), $chan_id)
1585+
};
1586+
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_funding_locked: expr, OPTIONALLY_RESEND_FUNDING_LOCKED) => {
1587+
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, $resend_funding_locked, Vec::new(), Vec::new(), Vec::new())
15851588
};
15861589
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr) => {
1587-
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, Vec::new(), Vec::new(), Vec::new())
1590+
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, false, Vec::new(), Vec::new(), Vec::new())
15881591
};
15891592
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr) => {
1590-
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, $failed_forwards, $failed_fails, Vec::new())
1593+
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, false, $failed_forwards, $failed_fails, Vec::new())
15911594
};
15921595
}
15931596

@@ -4495,7 +4498,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
44954498
// hasn't persisted to disk yet - we can't lose money on a transaction that we haven't
44964499
// accepted payment from yet. We do, however, need to wait to send our funding_locked
44974500
// until we have persisted our monitor.
4498-
chan.monitor_update_failed(false, false, Vec::new(), Vec::new(), Vec::new());
4501+
chan.monitor_update_failed(false, false, false, Vec::new(), Vec::new(), Vec::new());
44994502
},
45004503
}
45014504
}
@@ -4526,12 +4529,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
45264529
if chan.get().get_counterparty_node_id() != *counterparty_node_id {
45274530
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id));
45284531
}
4529-
let (monitor, funding_tx) = match chan.get_mut().funding_signed(&msg, best_block, &self.logger) {
4532+
let (monitor, funding_tx, funding_locked) = match chan.get_mut().funding_signed(&msg, best_block, &self.logger) {
45304533
Ok(update) => update,
45314534
Err(e) => try_chan_entry!(self, Err(e), channel_state, chan),
45324535
};
45334536
if let Err(e) = self.chain_monitor.watch_channel(chan.get().get_funding_txo().unwrap(), monitor) {
4534-
let mut res = handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, false, false);
4537+
let mut res = handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, funding_locked.is_some(), OPTIONALLY_RESEND_FUNDING_LOCKED);
45354538
if let Err(MsgHandleErrInternal { ref mut shutdown_finish, .. }) = res {
45364539
// We weren't able to watch the channel to begin with, so no updates should be made on
45374540
// it. Previously, full_stack_target found an (unreachable) panic when the
@@ -4542,6 +4545,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
45424545
}
45434546
return res
45444547
}
4548+
if let Some(msg) = funding_locked {
4549+
send_funding_locked!(channel_state.short_to_id, channel_state.pending_msg_events, chan.get(), msg);
4550+
}
45454551
funding_tx
45464552
},
45474553
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
@@ -4892,7 +4898,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
48924898
} else {
48934899
if let Err(e) = handle_monitor_err!(self, e, channel_state, chan,
48944900
RAACommitmentOrder::CommitmentFirst, false,
4895-
raa_updates.commitment_update.is_some(),
4901+
raa_updates.commitment_update.is_some(), false,
48964902
raa_updates.accepted_htlcs, raa_updates.failed_htlcs,
48974903
raa_updates.finalized_claimed_htlcs) {
48984904
break Err(e);
@@ -5746,6 +5752,18 @@ where
57465752
}
57475753
}
57485754
}
5755+
if channel.is_our_funding_locked() {
5756+
if let Some(real_scid) = channel.get_short_channel_id() {
5757+
// If we sent a 0conf funding_locked, and now have an SCID, we add it
5758+
// to the short_to_id map here. Note that we check whether we can relay
5759+
// using the real SCID at relay-time, and if the funding tx is ever
5760+
// un-confirmed we force-close the channel, ensuring short_to_id is
5761+
// always consistent.
5762+
let scid_insert = short_to_id.insert(real_scid, channel.channel_id());
5763+
assert!(scid_insert.is_none() || scid_insert.unwrap() == channel.channel_id(),
5764+
"SCIDs should never collide - ensure you weren't behind by a full XXX days when creating channels");
5765+
}
5766+
}
57495767
} else if let Err(reason) = res {
57505768
update_maps_on_chan_removal!(self, short_to_id, channel);
57515769
// It looks like our counterparty went on-chain or funding transaction was

lightning/src/ln/priv_short_conf_tests.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,3 +541,37 @@ fn test_scid_alias_returned() {
541541
PaymentFailedConditions::new().blamed_scid(last_hop[0].inbound_scid_alias.unwrap())
542542
.blamed_chan_closed(false).expected_htlc_error_data(0x1000|12, &err_data));
543543
}
544+
545+
#[test]
546+
fn test_simple_0_conf_channel() {
547+
// If our peer tells us they will accept our channel with 0 confs, and we funded the channel,
548+
// we should trust the funding won't be double-spent (assuming `trust_own_funding_0conf` is
549+
// set)!
550+
551+
let chanmon_cfgs = create_chanmon_cfgs(2);
552+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
553+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
554+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
555+
556+
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
557+
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
558+
559+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
560+
let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
561+
accept_channel.minimum_depth = 0;
562+
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
563+
564+
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], 100000, 42);
565+
nodes[0].node.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap();
566+
let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
567+
568+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
569+
check_added_monitors!(nodes[1], 1);
570+
let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
571+
572+
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed);
573+
check_added_monitors!(nodes[0], 1);
574+
575+
let as_funding_locked = get_event_msg!(nodes[0], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id());
576+
nodes[1].node.handle_funding_locked(&nodes[0].node.get_our_node_id(), &as_funding_locked);
577+
}

0 commit comments

Comments
 (0)