Skip to content

Commit ce7b0b4

Browse files
authored
Merge pull request #1401 from TheBlueMatt/2022-02-0conf-round-two
Zero Conf Channels
2 parents 1fd6c6f + ffaf9bc commit ce7b0b4

11 files changed

+590
-68
lines changed

fuzz/src/router.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
222222
channel_type: None,
223223
short_channel_id: Some(scid),
224224
inbound_scid_alias: None,
225+
outbound_scid_alias: None,
225226
channel_value_satoshis: capacity,
226227
user_channel_id: 0, inbound_capacity_msat: 0,
227228
unspendable_punishment_reserve: None,

lightning/src/ln/channel.rs

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,11 @@ pub(super) struct Channel<Signer: Sign> {
710710
// Our counterparty can offer us SCID aliases which they will map to this channel when routing
711711
// outbound payments. These can be used in invoice route hints to avoid explicitly revealing
712712
// the channel's funding UTXO.
713+
//
714+
// We also use this when sending our peer a channel_update that isn't to be broadcasted
715+
// publicly - allowing them to re-use their map of SCID -> channel for channel_update ->
716+
// associated channel mapping.
717+
//
713718
// We only bother storing the most recent SCID alias at any time, though our counterparty has
714719
// to store all of them.
715720
latest_inbound_scid_alias: Option<u64>,
@@ -1307,7 +1312,7 @@ impl<Signer: Sign> Channel<Signer> {
13071312
counterparty_htlc_minimum_msat: msg.htlc_minimum_msat,
13081313
holder_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat },
13091314
counterparty_max_accepted_htlcs: msg.max_accepted_htlcs,
1310-
minimum_depth: Some(config.own_channel_config.minimum_depth),
1315+
minimum_depth: Some(cmp::max(config.own_channel_config.minimum_depth, 1)),
13111316

13121317
counterparty_forwarding_info: None,
13131318

@@ -1987,12 +1992,6 @@ impl<Signer: Sign> Channel<Signer> {
19871992
if msg.minimum_depth > peer_limits.max_minimum_depth {
19881993
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)));
19891994
}
1990-
if msg.minimum_depth == 0 {
1991-
// Note that if this changes we should update the serialization minimum version to
1992-
// indicate to older clients that they don't understand some features of the current
1993-
// channel.
1994-
return Err(ChannelError::Close("Minimum confirmation depth must be at least 1".to_owned()));
1995-
}
19961995

19971996
if let Some(ty) = &msg.channel_type {
19981997
if *ty != self.channel_type {
@@ -2029,7 +2028,12 @@ impl<Signer: Sign> Channel<Signer> {
20292028
self.counterparty_selected_channel_reserve_satoshis = Some(msg.channel_reserve_satoshis);
20302029
self.counterparty_htlc_minimum_msat = msg.htlc_minimum_msat;
20312030
self.counterparty_max_accepted_htlcs = msg.max_accepted_htlcs;
2032-
self.minimum_depth = Some(msg.minimum_depth);
2031+
2032+
if peer_limits.trust_own_funding_0conf {
2033+
self.minimum_depth = Some(msg.minimum_depth);
2034+
} else {
2035+
self.minimum_depth = Some(cmp::max(1, msg.minimum_depth));
2036+
}
20332037

20342038
let counterparty_pubkeys = ChannelPublicKeys {
20352039
funding_pubkey: msg.funding_pubkey,
@@ -2089,7 +2093,7 @@ impl<Signer: Sign> Channel<Signer> {
20892093
&self.get_counterparty_pubkeys().funding_pubkey
20902094
}
20912095

2092-
pub fn funding_created<L: Deref>(&mut self, msg: &msgs::FundingCreated, best_block: BestBlock, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor<Signer>), ChannelError> where L::Target: Logger {
2096+
pub fn funding_created<L: Deref>(&mut self, msg: &msgs::FundingCreated, best_block: BestBlock, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor<Signer>, Option<msgs::FundingLocked>), ChannelError> where L::Target: Logger {
20932097
if self.is_outbound() {
20942098
return Err(ChannelError::Close("Received funding_created for an outbound channel?".to_owned()));
20952099
}
@@ -2164,12 +2168,12 @@ impl<Signer: Sign> Channel<Signer> {
21642168
Ok((msgs::FundingSigned {
21652169
channel_id: self.channel_id,
21662170
signature
2167-
}, channel_monitor))
2171+
}, channel_monitor, self.check_get_funding_locked(0)))
21682172
}
21692173

21702174
/// Handles a funding_signed message from the remote end.
21712175
/// If this call is successful, broadcast the funding transaction (and not before!)
2172-
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 {
2176+
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 {
21732177
if !self.is_outbound() {
21742178
return Err(ChannelError::Close("Received funding_signed for an inbound channel?".to_owned()));
21752179
}
@@ -2238,7 +2242,7 @@ impl<Signer: Sign> Channel<Signer> {
22382242

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

2241-
Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap()))
2245+
Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap(), self.check_get_funding_locked(0)))
22422246
}
22432247

22442248
/// Handles a funding_locked message from our peer. If we've already sent our funding_locked
@@ -3540,12 +3544,13 @@ impl<Signer: Sign> Channel<Signer> {
35403544
/// monitor update failure must *not* have been sent to the remote end, and must instead
35413545
/// have been dropped. They will be regenerated when monitor_updating_restored is called.
35423546
pub fn monitor_update_failed(&mut self, resend_raa: bool, resend_commitment: bool,
3543-
mut pending_forwards: Vec<(PendingHTLCInfo, u64)>,
3547+
resend_funding_locked: bool, mut pending_forwards: Vec<(PendingHTLCInfo, u64)>,
35443548
mut pending_fails: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>,
35453549
mut pending_finalized_claimed_htlcs: Vec<HTLCSource>
35463550
) {
35473551
self.monitor_pending_revoke_and_ack |= resend_raa;
35483552
self.monitor_pending_commitment_signed |= resend_commitment;
3553+
self.monitor_pending_funding_locked |= resend_funding_locked;
35493554
self.monitor_pending_forwards.append(&mut pending_forwards);
35503555
self.monitor_pending_failures.append(&mut pending_fails);
35513556
self.monitor_pending_finalized_fulfills.append(&mut pending_finalized_claimed_htlcs);
@@ -3559,17 +3564,28 @@ impl<Signer: Sign> Channel<Signer> {
35593564
assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, ChannelState::MonitorUpdateFailed as u32);
35603565
self.channel_state &= !(ChannelState::MonitorUpdateFailed as u32);
35613566

3562-
let funding_broadcastable = if self.channel_state & (ChannelState::FundingSent as u32) != 0 && self.is_outbound() {
3563-
self.funding_transaction.take()
3564-
} else { None };
3567+
// If we're past (or at) the FundingSent stage on an outbound channel, try to
3568+
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
3569+
// first received the funding_signed.
3570+
let mut funding_broadcastable =
3571+
if self.is_outbound() && self.channel_state & !MULTI_STATE_FLAGS >= ChannelState::FundingSent as u32 {
3572+
self.funding_transaction.take()
3573+
} else { None };
3574+
// That said, if the funding transaction is already confirmed (ie we're active with a
3575+
// minimum_depth over 0) don't bother re-broadcasting the confirmed funding tx.
3576+
if self.channel_state & !MULTI_STATE_FLAGS >= ChannelState::ChannelFunded as u32 && self.minimum_depth != Some(0) {
3577+
funding_broadcastable = None;
3578+
}
35653579

35663580
// We will never broadcast the funding transaction when we're in MonitorUpdateFailed (and
35673581
// we assume the user never directly broadcasts the funding transaction and waits for us to
3568-
// do it). Thus, we can only ever hit monitor_pending_funding_locked when we're an inbound
3569-
// channel which failed to persist the monitor on funding_created, and we got the funding
3570-
// transaction confirmed before the monitor was persisted.
3582+
// do it). Thus, we can only ever hit monitor_pending_funding_locked when we're
3583+
// * an inbound channel that failed to persist the monitor on funding_created and we got
3584+
// the funding transaction confirmed before the monitor was persisted, or
3585+
// * a 0-conf channel and intended to send the funding_locked before any broadcast at all.
35713586
let funding_locked = if self.monitor_pending_funding_locked {
3572-
assert!(!self.is_outbound(), "Funding transaction broadcast by the local client before it should have - LDK didn't do it!");
3587+
assert!(!self.is_outbound() || self.minimum_depth == Some(0),
3588+
"Funding transaction broadcast by the local client before it should have - LDK didn't do it!");
35733589
self.monitor_pending_funding_locked = false;
35743590
let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx);
35753591
Some(msgs::FundingLocked {
@@ -4551,6 +4567,11 @@ impl<Signer: Sign> Channel<Signer> {
45514567
self.channel_state >= ChannelState::FundingSent as u32
45524568
}
45534569

4570+
/// Returns true if our funding_locked has been sent
4571+
pub fn is_our_funding_locked(&self) -> bool {
4572+
(self.channel_state & ChannelState::OurFundingLocked as u32) != 0 || self.channel_state >= ChannelState::ChannelFunded as u32
4573+
}
4574+
45544575
/// Returns true if our peer has either initiated or agreed to shut down the channel.
45554576
pub fn received_shutdown(&self) -> bool {
45564577
(self.channel_state & ChannelState::RemoteShutdownSent as u32) != 0
@@ -4581,7 +4602,7 @@ impl<Signer: Sign> Channel<Signer> {
45814602
}
45824603

45834604
fn check_get_funding_locked(&mut self, height: u32) -> Option<msgs::FundingLocked> {
4584-
if self.funding_tx_confirmation_height == 0 {
4605+
if self.funding_tx_confirmation_height == 0 && self.minimum_depth != Some(0) {
45854606
return None;
45864607
}
45874608

@@ -4636,12 +4657,11 @@ impl<Signer: Sign> Channel<Signer> {
46364657
pub fn transactions_confirmed<L: Deref>(&mut self, block_hash: &BlockHash, height: u32,
46374658
txdata: &TransactionData, genesis_block_hash: BlockHash, node_pk: PublicKey, logger: &L)
46384659
-> Result<(Option<msgs::FundingLocked>, Option<msgs::AnnouncementSignatures>), ClosureReason> where L::Target: Logger {
4639-
let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
46404660
if let Some(funding_txo) = self.get_funding_txo() {
46414661
for &(index_in_block, tx) in txdata.iter() {
4642-
// If we haven't yet sent a funding_locked, but are in FundingSent (ignoring
4643-
// whether they've sent a funding_locked or not), check if we should send one.
4644-
if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 {
4662+
// Check if the transaction is the expected funding transaction, and if it is,
4663+
// check that it pays the right amount to the right script.
4664+
if self.funding_tx_confirmation_height == 0 {
46454665
if tx.txid() == funding_txo.txid {
46464666
let txo_idx = funding_txo.index as usize;
46474667
if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.get_funding_redeemscript().to_v0_p2wsh() ||
@@ -4758,9 +4778,9 @@ impl<Signer: Sign> Channel<Signer> {
47584778
// close the channel and hope we can get the latest state on chain (because presumably
47594779
// the funding transaction is at least still in the mempool of most nodes).
47604780
//
4761-
// Note that ideally we wouldn't force-close if we see *any* reorg on a 1-conf channel,
4762-
// but not doing so may lead to the `ChannelManager::short_to_id` map being
4763-
// inconsistent, so we currently have to.
4781+
// Note that ideally we wouldn't force-close if we see *any* reorg on a 1-conf or
4782+
// 0-conf channel, but not doing so may lead to the `ChannelManager::short_to_id` map
4783+
// being inconsistent, so we currently have to.
47644784
if funding_tx_confirmations == 0 && self.funding_tx_confirmed_in.is_some() {
47654785
let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.",
47664786
self.minimum_depth.unwrap(), funding_tx_confirmations);
@@ -4857,6 +4877,12 @@ impl<Signer: Sign> Channel<Signer> {
48574877
self.inbound_awaiting_accept
48584878
}
48594879

4880+
/// Sets this channel to accepting 0conf, must be done before `get_accept_channel`
4881+
pub fn set_0conf(&mut self) {
4882+
assert!(self.inbound_awaiting_accept);
4883+
self.minimum_depth = Some(0);
4884+
}
4885+
48604886
/// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannel`] message which
48614887
/// should be sent back to the counterparty node.
48624888
///
@@ -5619,7 +5645,7 @@ impl<Signer: Sign> Channel<Signer> {
56195645
}
56205646

56215647
const SERIALIZATION_VERSION: u8 = 2;
5622-
const MIN_SERIALIZATION_VERSION: u8 = 1;
5648+
const MIN_SERIALIZATION_VERSION: u8 = 2;
56235649

56245650
impl_writeable_tlv_based_enum!(InboundHTLCRemovalReason,;
56255651
(0, FailRelay),
@@ -5684,12 +5710,10 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
56845710

56855711
self.user_id.write(writer)?;
56865712

5687-
// Write out the old serialization for the config object. This is read by version-1
5688-
// deserializers, but we will read the version in the TLV at the end instead.
5689-
self.config.forwarding_fee_proportional_millionths.write(writer)?;
5690-
self.config.cltv_expiry_delta.write(writer)?;
5691-
self.config.announced_channel.write(writer)?;
5692-
self.config.commit_upfront_shutdown_pubkey.write(writer)?;
5713+
// Version 1 deserializers expected to read parts of the config object here. Version 2
5714+
// deserializers (0.0.99) now read config through TLVs, and as we now require them for
5715+
// `minimum_depth` we simply write dummy values here.
5716+
writer.write_all(&[0; 8])?;
56935717

56945718
self.channel_id.write(writer)?;
56955719
(self.channel_state | ChannelState::PeerDisconnected as u32).write(writer)?;
@@ -6667,7 +6691,7 @@ mod tests {
66676691
}]};
66686692
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
66696693
let funding_created_msg = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).unwrap();
6670-
let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&logger).unwrap();
6694+
let (funding_signed_msg, _, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&logger).unwrap();
66716695

66726696
// Node B --> Node A: funding signed
66736697
let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&logger);

0 commit comments

Comments
 (0)