Skip to content

Commit bd4646e

Browse files
committed
Handle receiving channel_reestablish with next_funding_txid
This follows the the specification closely in branching without being too verbose, so that it should be easy to follow the logic. See: https://github.com/lightning/bolts/blob/aa5207a/02-peer-protocol.md?plain=1#L2520-L2531
1 parent 828932f commit bd4646e

File tree

3 files changed

+119
-17
lines changed

3 files changed

+119
-17
lines changed

lightning/src/ln/channel.rs

+81-7
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,8 @@ pub(super) struct ReestablishResponses {
968968
pub order: RAACommitmentOrder,
969969
pub announcement_sigs: Option<msgs::AnnouncementSignatures>,
970970
pub shutdown_msg: Option<msgs::Shutdown>,
971+
pub tx_signatures: Option<msgs::TxSignatures>,
972+
pub tx_abort: Option<msgs::TxAbort>,
971973
}
972974

973975
/// The first message we send to our peer after connection
@@ -2273,7 +2275,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22732275

22742276
let mut output_index = None;
22752277
let expected_spk = self.funding.get_funding_redeemscript().to_p2wsh();
2276-
for (idx, outp) in signing_session.unsigned_tx.outputs().enumerate() {
2278+
for (idx, outp) in signing_session.unsigned_tx().outputs().enumerate() {
22772279
if outp.script_pubkey() == &expected_spk && outp.value() == self.funding.get_value_satoshis() {
22782280
if output_index.is_some() {
22792281
return Err(ChannelError::Close(
@@ -2286,7 +2288,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22862288
}
22872289
}
22882290
let outpoint = if let Some(output_index) = output_index {
2289-
OutPoint { txid: signing_session.unsigned_tx.compute_txid(), index: output_index }
2291+
OutPoint { txid: signing_session.unsigned_tx().compute_txid(), index: output_index }
22902292
} else {
22912293
return Err(ChannelError::Close(
22922294
(
@@ -2300,7 +2302,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
23002302
let commitment_signed = self.context.get_initial_commitment_signed(&self.funding, logger);
23012303
let commitment_signed = match commitment_signed {
23022304
Ok(commitment_signed) => {
2303-
self.funding.funding_transaction = Some(signing_session.unsigned_tx.build_unsigned_tx());
2305+
self.funding.funding_transaction = Some(signing_session.unsigned_tx().build_unsigned_tx());
23042306
commitment_signed
23052307
},
23062308
Err(err) => {
@@ -6164,7 +6166,7 @@ impl<SP: Deref> FundedChannel<SP> where
61646166
}
61656167

61666168
if let Some(ref mut signing_session) = self.interactive_tx_signing_session {
6167-
if msg.tx_hash != signing_session.unsigned_tx.compute_txid() {
6169+
if msg.tx_hash != signing_session.unsigned_tx().compute_txid() {
61686170
return Err(ChannelError::Close(
61696171
(
61706172
"The txid for the transaction does not match".to_string(),
@@ -6809,7 +6811,10 @@ impl<SP: Deref> FundedChannel<SP> where
68096811
}
68106812

68116813
if msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER ||
6812-
msg.next_local_commitment_number == 0 {
6814+
msg.next_local_commitment_number == 0 && msg.next_funding_txid.is_none() {
6815+
// Note: This also covers the following case in the V2 channel establishment specification:
6816+
// if `next_funding_txid` is not set, and `next_commitment_number` is zero:
6817+
// MUST immediately fail the channel and broadcast any relevant latest commitment transaction.
68136818
return Err(ChannelError::close("Peer sent an invalid channel_reestablish to force close in a non-standard way".to_owned()));
68146819
}
68156820

@@ -6873,6 +6878,8 @@ impl<SP: Deref> FundedChannel<SP> where
68736878
raa: None, commitment_update: None,
68746879
order: RAACommitmentOrder::CommitmentFirst,
68756880
shutdown_msg, announcement_sigs,
6881+
tx_signatures: None,
6882+
tx_abort: None,
68766883
});
68776884
}
68786885

@@ -6882,6 +6889,8 @@ impl<SP: Deref> FundedChannel<SP> where
68826889
raa: None, commitment_update: None,
68836890
order: RAACommitmentOrder::CommitmentFirst,
68846891
shutdown_msg, announcement_sigs,
6892+
tx_signatures: None,
6893+
tx_abort: None,
68856894
});
68866895
}
68876896

@@ -6924,11 +6933,72 @@ impl<SP: Deref> FundedChannel<SP> where
69246933
log_debug!(logger, "Reconnected channel {} with no loss", &self.context.channel_id());
69256934
}
69266935

6936+
// if next_funding_txid is set:
6937+
let (commitment_update, tx_signatures, tx_abort) = if let Some(next_funding_txid) = msg.next_funding_txid {
6938+
if let Some(session) = &self.interactive_tx_signing_session {
6939+
// if next_funding_txid matches the latest interactive funding transaction:
6940+
if session.unsigned_tx().compute_txid() == next_funding_txid {
6941+
// if it has not received tx_signatures for that funding transaction:
6942+
if !session.counterparty_sent_tx_signatures() {
6943+
// if next_commitment_number is zero:
6944+
let commitment_update = if msg.next_local_commitment_number == 0 {
6945+
// MUST retransmit its commitment_signed for that funding transaction.
6946+
let commitment_signed = self.context.get_initial_commitment_signed(&self.funding, logger)?;
6947+
Some(msgs::CommitmentUpdate {
6948+
commitment_signed,
6949+
update_add_htlcs: vec![],
6950+
update_fulfill_htlcs: vec![],
6951+
update_fail_htlcs: vec![],
6952+
update_fail_malformed_htlcs: vec![],
6953+
update_fee: None,
6954+
})
6955+
} else { None };
6956+
// if it has already received commitment_signed and it should sign first, as specified in the tx_signatures requirements:
6957+
if session.has_received_commitment_signed() && session.holder_sends_tx_signatures_first() {
6958+
// MUST send its tx_signatures for that funding transaction.
6959+
if self.context.channel_state.is_monitor_update_in_progress() {
6960+
log_debug!(logger, "Not sending tx_signatures: a monitor update is in progress. Setting monitor_pending_tx_signatures.");
6961+
self.context.monitor_pending_tx_signatures = session.holder_tx_signatures().clone();
6962+
// We can still send the initial commitment transaction if a monitor update is pending.
6963+
(commitment_update, None, None)
6964+
} else {
6965+
(commitment_update, session.holder_tx_signatures().clone(), None)
6966+
}
6967+
} else {
6968+
(commitment_update, None, None)
6969+
}
6970+
} else {
6971+
// if it has already received tx_signatures for that funding transaction:
6972+
// MUST send its tx_signatures for that funding transaction.
6973+
if self.context.channel_state.is_monitor_update_in_progress() {
6974+
log_debug!(logger, "Not sending tx_signatures: a monitor update is in progress. Setting monitor_pending_tx_signatures.");
6975+
self.context.monitor_pending_tx_signatures = session.holder_tx_signatures().clone();
6976+
(None, None, None)
6977+
} else {
6978+
// If `holder_tx_signatures` is `None` here, the `tx_signatures` message will be sent
6979+
// when the holder provides their witnesses as this will queue a `tx_signatures` if the
6980+
// holder must send one.
6981+
(None, session.holder_tx_signatures().clone(), None)
6982+
}
6983+
}
6984+
} else {
6985+
// MUST send tx_abort to let the sending node know that they can forget this funding transaction.
6986+
(None, None, Some(msgs::TxAbort { channel_id: self.context.channel_id(), data: vec![] }))
6987+
}
6988+
} else {
6989+
return Err(ChannelError::close("Counterparty set `next_funding_txid` at incorrect state".into()));
6990+
}
6991+
} else {
6992+
(None, None, None)
6993+
};
6994+
69276995
Ok(ReestablishResponses {
69286996
channel_ready, shutdown_msg, announcement_sigs,
69296997
raa: required_revoke,
6930-
commitment_update: None,
6998+
commitment_update,
69316999
order: self.context.resend_order.clone(),
7000+
tx_signatures,
7001+
tx_abort,
69327002
})
69337003
} else if msg.next_local_commitment_number == next_counterparty_commitment_number - 1 {
69347004
if required_revoke.is_some() || self.context.signer_pending_revoke_and_ack {
@@ -6943,6 +7013,8 @@ impl<SP: Deref> FundedChannel<SP> where
69437013
channel_ready, shutdown_msg, announcement_sigs,
69447014
commitment_update: None, raa: None,
69457015
order: self.context.resend_order.clone(),
7016+
tx_signatures: None,
7017+
tx_abort: None,
69467018
})
69477019
} else {
69487020
let commitment_update = if self.context.resend_order == RAACommitmentOrder::RevokeAndACKFirst
@@ -6965,6 +7037,8 @@ impl<SP: Deref> FundedChannel<SP> where
69657037
channel_ready, shutdown_msg, announcement_sigs,
69667038
raa, commitment_update,
69677039
order: self.context.resend_order.clone(),
7040+
tx_signatures: None,
7041+
tx_abort: None,
69687042
})
69697043
}
69707044
} else if msg.next_local_commitment_number < next_counterparty_commitment_number {
@@ -8259,7 +8333,7 @@ impl<SP: Deref> FundedChannel<SP> where
82598333
// to the txid of that interactive transaction, else we MUST NOT set it.
82608334
if let Some(signing_session) = &self.interactive_tx_signing_session {
82618335
// Since we have a signing_session, this implies we've sent an initial `commitment_signed`...
8262-
if !signing_session.counterparty_sent_tx_signatures {
8336+
if !signing_session.counterparty_sent_tx_signatures() {
82638337
// ...but we didn't receive a `tx_signatures` from the counterparty yet.
82648338
Some(self.funding_outpoint().txid)
82658339
} else {

lightning/src/ln/channelmanager.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -3269,7 +3269,7 @@ macro_rules! handle_monitor_update_completion {
32693269
&mut $peer_state.pending_msg_events, $chan, updates.raa,
32703270
updates.commitment_update, updates.order, updates.accepted_htlcs, updates.pending_update_adds,
32713271
updates.funding_broadcastable, updates.channel_ready,
3272-
updates.announcement_sigs, updates.tx_signatures);
3272+
updates.announcement_sigs, updates.tx_signatures, None);
32733273
if let Some(upd) = channel_update {
32743274
$peer_state.pending_msg_events.push(upd);
32753275
}
@@ -7601,10 +7601,10 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
76017601
pending_forwards: Vec<(PendingHTLCInfo, u64)>, pending_update_adds: Vec<msgs::UpdateAddHTLC>,
76027602
funding_broadcastable: Option<Transaction>,
76037603
channel_ready: Option<msgs::ChannelReady>, announcement_sigs: Option<msgs::AnnouncementSignatures>,
7604-
tx_signatures: Option<msgs::TxSignatures>
7604+
tx_signatures: Option<msgs::TxSignatures>, tx_abort: Option<msgs::TxAbort>,
76057605
) -> (Option<(u64, Option<PublicKey>, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)>, Option<(u64, Vec<msgs::UpdateAddHTLC>)>) {
76067606
let logger = WithChannelContext::from(&self.logger, &channel.context, None);
7607-
log_trace!(logger, "Handling channel resumption for channel {} with {} RAA, {} commitment update, {} pending forwards, {} pending update_add_htlcs, {}broadcasting funding, {} channel ready, {} announcement, {} tx_signatures",
7607+
log_trace!(logger, "Handling channel resumption for channel {} with {} RAA, {} commitment update, {} pending forwards, {} pending update_add_htlcs, {}broadcasting funding, {} channel ready, {} announcement, {} tx_signatures, {} tx_abort",
76087608
&channel.context.channel_id(),
76097609
if raa.is_some() { "an" } else { "no" },
76107610
if commitment_update.is_some() { "a" } else { "no" },
@@ -7613,6 +7613,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
76137613
if channel_ready.is_some() { "sending" } else { "without" },
76147614
if announcement_sigs.is_some() { "sending" } else { "without" },
76157615
if tx_signatures.is_some() { "sending" } else { "without" },
7616+
if tx_abort.is_some() { "sending" } else { "without" },
76167617
);
76177618

76187619
let counterparty_node_id = channel.context.get_counterparty_node_id();
@@ -7646,6 +7647,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
76467647
msg,
76477648
});
76487649
}
7650+
if let Some(msg) = tx_abort {
7651+
pending_msg_events.push(MessageSendEvent::SendTxAbort {
7652+
node_id: counterparty_node_id,
7653+
msg,
7654+
});
7655+
}
76497656

76507657
macro_rules! handle_cs { () => {
76517658
if let Some(update) = commitment_update {
@@ -9417,7 +9424,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
94179424
let need_lnd_workaround = chan.context.workaround_lnd_bug_4006.take();
94189425
let (htlc_forwards, decode_update_add_htlcs) = self.handle_channel_resumption(
94199426
&mut peer_state.pending_msg_events, chan, responses.raa, responses.commitment_update, responses.order,
9420-
Vec::new(), Vec::new(), None, responses.channel_ready, responses.announcement_sigs, None);
9427+
Vec::new(), Vec::new(), None, responses.channel_ready, responses.announcement_sigs,
9428+
responses.tx_signatures, responses.tx_abort);
94219429
debug_assert!(htlc_forwards.is_none());
94229430
debug_assert!(decode_update_add_htlcs.is_none());
94239431
if let Some(upd) = channel_update {

lightning/src/ln/interactivetxs.rs

+26-6
Original file line numberDiff line numberDiff line change
@@ -288,16 +288,36 @@ impl ConstructedTransaction {
288288
/// https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#sharing-funding-signatures-tx_signatures
289289
#[derive(Debug, Clone, PartialEq)]
290290
pub(crate) struct InteractiveTxSigningSession {
291-
pub unsigned_tx: ConstructedTransaction,
292-
pub counterparty_sent_tx_signatures: bool,
291+
unsigned_tx: ConstructedTransaction,
292+
counterparty_sent_tx_signatures: bool,
293293
holder_sends_tx_signatures_first: bool,
294-
received_commitment_signed: bool,
294+
has_received_commitment_signed: bool,
295295
holder_tx_signatures: Option<TxSignatures>,
296296
}
297297

298298
impl InteractiveTxSigningSession {
299+
pub fn unsigned_tx(&self) -> &ConstructedTransaction {
300+
&self.unsigned_tx
301+
}
302+
303+
pub fn counterparty_sent_tx_signatures(&self) -> bool {
304+
self.counterparty_sent_tx_signatures
305+
}
306+
307+
pub fn holder_sends_tx_signatures_first(&self) -> bool {
308+
self.holder_sends_tx_signatures_first
309+
}
310+
311+
pub fn has_received_commitment_signed(&self) -> bool {
312+
self.has_received_commitment_signed
313+
}
314+
315+
pub fn holder_tx_signatures(&self) -> &Option<TxSignatures> {
316+
&self.holder_tx_signatures
317+
}
318+
299319
pub fn received_commitment_signed(&mut self) -> Option<TxSignatures> {
300-
self.received_commitment_signed = true;
320+
self.has_received_commitment_signed = true;
301321
if self.holder_sends_tx_signatures_first {
302322
self.holder_tx_signatures.clone()
303323
} else {
@@ -306,7 +326,7 @@ impl InteractiveTxSigningSession {
306326
}
307327

308328
pub fn get_tx_signatures(&self) -> Option<TxSignatures> {
309-
if self.received_commitment_signed {
329+
if self.has_received_commitment_signed {
310330
self.holder_tx_signatures.clone()
311331
} else {
312332
None
@@ -987,7 +1007,7 @@ macro_rules! define_state_transitions {
9871007
let signing_session = InteractiveTxSigningSession {
9881008
holder_sends_tx_signatures_first: tx.holder_sends_tx_signatures_first,
9891009
unsigned_tx: tx,
990-
received_commitment_signed: false,
1010+
has_received_commitment_signed: false,
9911011
holder_tx_signatures: None,
9921012
counterparty_sent_tx_signatures: false,
9931013
};

0 commit comments

Comments
 (0)