Skip to content

Commit 9739331

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 8467702 commit 9739331

File tree

3 files changed

+111
-17
lines changed

3 files changed

+111
-17
lines changed

lightning/src/ln/channel.rs

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,8 @@ pub(super) struct ReestablishResponses {
930930
pub order: RAACommitmentOrder,
931931
pub announcement_sigs: Option<msgs::AnnouncementSignatures>,
932932
pub shutdown_msg: Option<msgs::Shutdown>,
933+
pub tx_signatures: Option<msgs::TxSignatures>,
934+
pub tx_abort: Option<msgs::TxAbort>,
933935
}
934936

935937
/// The first message we send to our peer after connection
@@ -2117,7 +2119,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21172119

21182120
let mut output_index = None;
21192121
let expected_spk = self.context.get_funding_redeemscript().to_p2wsh();
2120-
for (idx, outp) in signing_session.unsigned_tx.outputs().enumerate() {
2122+
for (idx, outp) in signing_session.unsigned_tx().outputs().enumerate() {
21212123
if outp.script_pubkey() == &expected_spk && outp.value() == self.context.get_value_satoshis() {
21222124
if output_index.is_some() {
21232125
return Err(ChannelError::Close(
@@ -2130,7 +2132,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21302132
}
21312133
}
21322134
let outpoint = if let Some(output_index) = output_index {
2133-
OutPoint { txid: signing_session.unsigned_tx.compute_txid(), index: output_index }
2135+
OutPoint { txid: signing_session.unsigned_tx().compute_txid(), index: output_index }
21342136
} else {
21352137
return Err(ChannelError::Close(
21362138
(
@@ -2145,7 +2147,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21452147
let commitment_signed = self.context.get_initial_commitment_signed(logger);
21462148
let commitment_signed = match commitment_signed {
21472149
Ok(commitment_signed) => {
2148-
self.context.funding_transaction = Some(signing_session.unsigned_tx.build_unsigned_tx());
2150+
self.context.funding_transaction = Some(signing_session.unsigned_tx().build_unsigned_tx());
21492151
commitment_signed
21502152
},
21512153
Err(err) => {
@@ -6003,7 +6005,7 @@ impl<SP: Deref> FundedChannel<SP> where
60036005
}
60046006

60056007
if let Some(ref mut signing_session) = self.interactive_tx_signing_session {
6006-
if msg.tx_hash != signing_session.unsigned_tx.compute_txid() {
6008+
if msg.tx_hash != signing_session.unsigned_tx().compute_txid() {
60076009
return Err(ChannelError::Close(
60086010
(
60096011
"The txid for the transaction does not match".to_string(),
@@ -6633,7 +6635,7 @@ impl<SP: Deref> FundedChannel<SP> where
66336635
}
66346636

66356637
if msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER ||
6636-
msg.next_local_commitment_number == 0 {
6638+
msg.next_local_commitment_number == 0 && msg.next_funding_txid.is_none() {
66376639
return Err(ChannelError::close("Peer sent an invalid channel_reestablish to force close in a non-standard way".to_owned()));
66386640
}
66396641

@@ -6697,6 +6699,8 @@ impl<SP: Deref> FundedChannel<SP> where
66976699
raa: None, commitment_update: None,
66986700
order: RAACommitmentOrder::CommitmentFirst,
66996701
shutdown_msg, announcement_sigs,
6702+
tx_signatures: None,
6703+
tx_abort: None,
67006704
});
67016705
}
67026706

@@ -6706,6 +6710,8 @@ impl<SP: Deref> FundedChannel<SP> where
67066710
raa: None, commitment_update: None,
67076711
order: RAACommitmentOrder::CommitmentFirst,
67086712
shutdown_msg, announcement_sigs,
6713+
tx_signatures: None,
6714+
tx_abort: None,
67096715
});
67106716
}
67116717

@@ -6751,11 +6757,67 @@ impl<SP: Deref> FundedChannel<SP> where
67516757
log_debug!(logger, "Reconnected channel {} with no loss", &self.context.channel_id());
67526758
}
67536759

6760+
// if next_funding_txid is set:
6761+
let (commitment_update, tx_signatures, tx_abort) = if let Some(next_funding_txid) = msg.next_funding_txid {
6762+
if let Some(session) = &self.interactive_tx_signing_session {
6763+
// if next_funding_txid matches the latest interactive funding transaction:
6764+
if session.unsigned_tx().compute_txid() == next_funding_txid {
6765+
// if it has not received tx_signatures for that funding transaction:
6766+
if !session.counterparty_sent_tx_signatures() {
6767+
// if next_commitment_number is zero:
6768+
let commitment_update = if msg.next_local_commitment_number == 0 {
6769+
// MUST retransmit its commitment_signed for that funding transaction.
6770+
let commitment_signed = self.context.get_initial_commitment_signed(logger)?;
6771+
Some(msgs::CommitmentUpdate {
6772+
commitment_signed,
6773+
update_add_htlcs: vec![],
6774+
update_fulfill_htlcs: vec![],
6775+
update_fail_htlcs: vec![],
6776+
update_fail_malformed_htlcs: vec![],
6777+
update_fee: None,
6778+
})
6779+
} else { None };
6780+
// if it has already received commitment_signed and it should sign first, as specified in the tx_signatures requirements:
6781+
if session.has_received_commitment_signed() && session.holder_sends_tx_signatures_first() {
6782+
// MUST send its tx_signatures for that funding transaction.
6783+
(commitment_update, session.holder_tx_signatures().clone(), None)
6784+
} else {
6785+
(commitment_update, None, None)
6786+
}
6787+
} else {
6788+
// if it has already received tx_signatures for that funding transaction:
6789+
// MUST send its tx_signatures for that funding transaction.
6790+
(None, session.holder_tx_signatures().clone(), None)
6791+
}
6792+
} else {
6793+
// MUST send tx_abort to let the sending node know that they can forget this funding transaction.
6794+
(None, None, Some(msgs::TxAbort { channel_id: self.context.channel_id(), data: vec![] }))
6795+
}
6796+
} else {
6797+
// Counterparty set `next_funding_txid` at incorrect state.
6798+
// TODO(dual_funding): Should probably error here (or send tx_abort) but not in spec.
6799+
(None, None, None)
6800+
}
6801+
} else {
6802+
// if `next_funding_txid` is not set, and `next_commitment_number` is zero:
6803+
if msg.next_local_commitment_number == 0 {
6804+
// MUST immediately fail the channel and broadcast any relevant latest commitment transaction.
6805+
return Err(ChannelError::close(format!(
6806+
"Peer attempted to reestablish channel expecting a future local commitment transaction: {} (received) vs {} (expected)",
6807+
msg.next_remote_commitment_number,
6808+
our_commitment_transaction
6809+
)));
6810+
}
6811+
(None, None, None)
6812+
};
6813+
67546814
Ok(ReestablishResponses {
67556815
channel_ready, shutdown_msg, announcement_sigs,
67566816
raa: required_revoke,
6757-
commitment_update: None,
6817+
commitment_update,
67586818
order: self.context.resend_order.clone(),
6819+
tx_signatures,
6820+
tx_abort,
67596821
})
67606822
} else if msg.next_local_commitment_number == next_counterparty_commitment_number - 1 {
67616823
if required_revoke.is_some() || self.context.signer_pending_revoke_and_ack {
@@ -6770,6 +6832,8 @@ impl<SP: Deref> FundedChannel<SP> where
67706832
channel_ready, shutdown_msg, announcement_sigs,
67716833
commitment_update: None, raa: None,
67726834
order: self.context.resend_order.clone(),
6835+
tx_signatures: None,
6836+
tx_abort: None,
67736837
})
67746838
} else {
67756839
let commitment_update = if self.context.resend_order == RAACommitmentOrder::RevokeAndACKFirst
@@ -6792,6 +6856,8 @@ impl<SP: Deref> FundedChannel<SP> where
67926856
channel_ready, shutdown_msg, announcement_sigs,
67936857
raa, commitment_update,
67946858
order: self.context.resend_order.clone(),
6859+
tx_signatures: None,
6860+
tx_abort: None,
67956861
})
67966862
}
67976863
} else if msg.next_local_commitment_number < next_counterparty_commitment_number {
@@ -8069,7 +8135,7 @@ impl<SP: Deref> FundedChannel<SP> where
80698135
// to the txid of that interactive transaction, else we MUST NOT set it.
80708136
if let Some(signing_session) = &self.interactive_tx_signing_session {
80718137
// Since we have a signing_session, this implies we've sent an initial `commitment_signed`...
8072-
if !signing_session.counterparty_sent_tx_signatures {
8138+
if !signing_session.counterparty_sent_tx_signatures() {
80738139
// ...but we didn't receive a `tx_signatures` from the counterparty yet.
80748140
Some(self.funding_outpoint().txid)
80758141
} else {

lightning/src/ln/channelmanager.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,7 +3208,7 @@ macro_rules! handle_monitor_update_completion {
32083208
&mut $peer_state.pending_msg_events, $chan, updates.raa,
32093209
updates.commitment_update, updates.order, updates.accepted_htlcs, updates.pending_update_adds,
32103210
updates.funding_broadcastable, updates.channel_ready,
3211-
updates.announcement_sigs, updates.tx_signatures);
3211+
updates.announcement_sigs, updates.tx_signatures, None);
32123212
if let Some(upd) = channel_update {
32133213
$peer_state.pending_msg_events.push(upd);
32143214
}
@@ -7522,10 +7522,10 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
75227522
pending_forwards: Vec<(PendingHTLCInfo, u64)>, pending_update_adds: Vec<msgs::UpdateAddHTLC>,
75237523
funding_broadcastable: Option<Transaction>,
75247524
channel_ready: Option<msgs::ChannelReady>, announcement_sigs: Option<msgs::AnnouncementSignatures>,
7525-
tx_signatures: Option<msgs::TxSignatures>
7525+
tx_signatures: Option<msgs::TxSignatures>, tx_abort: Option<msgs::TxAbort>,
75267526
) -> (Option<(u64, Option<PublicKey>, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)>, Option<(u64, Vec<msgs::UpdateAddHTLC>)>) {
75277527
let logger = WithChannelContext::from(&self.logger, &channel.context, None);
7528-
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",
7528+
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",
75297529
&channel.context.channel_id(),
75307530
if raa.is_some() { "an" } else { "no" },
75317531
if commitment_update.is_some() { "a" } else { "no" },
@@ -7534,6 +7534,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
75347534
if channel_ready.is_some() { "sending" } else { "without" },
75357535
if announcement_sigs.is_some() { "sending" } else { "without" },
75367536
if tx_signatures.is_some() { "sending" } else { "without" },
7537+
if tx_abort.is_some() { "sending" } else { "without" },
75377538
);
75387539

75397540
let counterparty_node_id = channel.context.get_counterparty_node_id();
@@ -7567,6 +7568,12 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
75677568
msg,
75687569
});
75697570
}
7571+
if let Some(msg) = tx_abort {
7572+
pending_msg_events.push(events::MessageSendEvent::SendTxAbort {
7573+
node_id: counterparty_node_id,
7574+
msg,
7575+
});
7576+
}
75707577

75717578
macro_rules! handle_cs { () => {
75727579
if let Some(update) = commitment_update {
@@ -9238,7 +9245,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
92389245
let need_lnd_workaround = chan.context.workaround_lnd_bug_4006.take();
92399246
let (htlc_forwards, decode_update_add_htlcs) = self.handle_channel_resumption(
92409247
&mut peer_state.pending_msg_events, chan, responses.raa, responses.commitment_update, responses.order,
9241-
Vec::new(), Vec::new(), None, responses.channel_ready, responses.announcement_sigs, None);
9248+
Vec::new(), Vec::new(), None, responses.channel_ready, responses.announcement_sigs,
9249+
responses.tx_signatures, responses.tx_abort);
92429250
debug_assert!(htlc_forwards.is_none());
92439251
debug_assert!(decode_update_add_htlcs.is_none());
92449252
if let Some(upd) = channel_update {

lightning/src/ln/interactivetxs.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,16 +289,36 @@ impl ConstructedTransaction {
289289
/// https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#sharing-funding-signatures-tx_signatures
290290
#[derive(Debug, Clone, PartialEq)]
291291
pub(crate) struct InteractiveTxSigningSession {
292-
pub unsigned_tx: ConstructedTransaction,
293-
pub counterparty_sent_tx_signatures: bool,
292+
unsigned_tx: ConstructedTransaction,
293+
counterparty_sent_tx_signatures: bool,
294294
holder_sends_tx_signatures_first: bool,
295-
received_commitment_signed: bool,
295+
has_received_commitment_signed: bool,
296296
holder_tx_signatures: Option<TxSignatures>,
297297
}
298298

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

309329
pub fn get_tx_signatures(&self) -> Option<TxSignatures> {
310-
if self.received_commitment_signed {
330+
if self.has_received_commitment_signed {
311331
self.holder_tx_signatures.clone()
312332
} else {
313333
None
@@ -988,7 +1008,7 @@ macro_rules! define_state_transitions {
9881008
let signing_session = InteractiveTxSigningSession {
9891009
holder_sends_tx_signatures_first: tx.holder_sends_tx_signatures_first,
9901010
unsigned_tx: tx,
991-
received_commitment_signed: false,
1011+
has_received_commitment_signed: false,
9921012
holder_tx_signatures: None,
9931013
counterparty_sent_tx_signatures: false,
9941014
};

0 commit comments

Comments
 (0)