Skip to content

Commit 6cf6994

Browse files
committed
Introduce interactive signing state flags and session persistence
This intoduces the INTERACTIVE_SIGNING, THEIR_TX_SIGNATURES_SENT, and OUR_TX_SIGNATURES_SENT funded state flags. A top-level state flag for INTERACTIVE_SIGNING was avoided so that this work is compatible with splicing as well as V2 channel establishment (dual-funding).
1 parent d8306e9 commit 6cf6994

File tree

3 files changed

+185
-28
lines changed

3 files changed

+185
-28
lines changed

lightning/src/ln/channel.rs

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,12 @@ macro_rules! define_state_flags {
434434
is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent);
435435
define_state_flags!($flag_type, FundedStateFlags::LOCAL_SHUTDOWN_SENT,
436436
is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent);
437+
define_state_flags!($flag_type, FundedStateFlags::INTERACTIVE_SIGNING,
438+
is_interactive_signing, set_interactive_signing, clear_interactive_signing);
439+
define_state_flags!($flag_type, FundedStateFlags::THEIR_TX_SIGNATURES_SENT,
440+
is_their_tx_signatures_sent, set_their_tx_signatures_sent, clear_their_tx_signatures_sent);
441+
define_state_flags!($flag_type, FundedStateFlags::OUR_TX_SIGNATURES_SENT,
442+
is_our_tx_signatures_sent, set_our_tx_signatures_sent, clear_our_tx_signatures_sent);
437443

438444
impl core::ops::BitOr<FundedStateFlags> for $flag_type {
439445
type Output = Self;
@@ -479,6 +485,9 @@ mod state_flags {
479485
pub const LOCAL_STFU_SENT: u32 = 1 << 15;
480486
pub const REMOTE_STFU_SENT: u32 = 1 << 16;
481487
pub const QUIESCENT: u32 = 1 << 17;
488+
pub const INTERACTIVE_SIGNING: u32 = 1 << 18;
489+
pub const OUR_TX_SIGNATURES_SENT: u32 = 1 << 19;
490+
pub const THEIR_TX_SIGNATURES_SENT: u32 = 1 << 20;
482491
}
483492

484493
define_state_flags!(
@@ -497,7 +506,16 @@ define_state_flags!(
497506
is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent),
498507
("Indicates we sent a `shutdown` message. At this point, we may not add any new HTLCs to \
499508
the channel.", LOCAL_SHUTDOWN_SENT, state_flags::LOCAL_SHUTDOWN_SENT,
500-
is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent)
509+
is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent),
510+
("Indicates we have an active interactive signing session for an interactive transaction",
511+
INTERACTIVE_SIGNING, state_flags::INTERACTIVE_SIGNING,
512+
is_interactive_signing, set_interactive_signing, clear_interactive_singing),
513+
("Indicates they sent us a `tx_signatures` message.",
514+
THEIR_TX_SIGNATURES_SENT, state_flags::THEIR_TX_SIGNATURES_SENT,
515+
is_their_tx_signatures_sent, set_their_tx_signatures_sent, clear_their_tx_signatures_sent),
516+
("Indicates we sent them a `tx_signatures` message.",
517+
OUR_TX_SIGNATURES_SENT, state_flags::OUR_TX_SIGNATURES_SENT,
518+
is_our_tx_signatures_sent, set_our_tx_signatures_sent, clear_our_tx_signatures_sent)
501519
]
502520
);
503521

@@ -568,7 +586,8 @@ enum ChannelState {
568586
NegotiatingFunding(NegotiatingFundingFlags),
569587
/// We have sent `funding_created` and are awaiting a `funding_signed` to advance to
570588
/// `AwaitingChannelReady`. Note that this is nonsense for an inbound channel as we immediately generate
571-
/// `funding_signed` upon receipt of `funding_created`, so simply skip this state.
589+
/// `funding_signed` upon receipt of `funding_created`, so simply skip this state. For dual-funded (V2)
590+
/// channels, this state is also skipped.
572591
FundingNegotiated,
573592
/// We've received/sent `funding_created` and `funding_signed` and are thus now waiting on the
574593
/// funding transaction to confirm.
@@ -685,6 +704,9 @@ impl ChannelState {
685704
impl_state_flag!(is_monitor_update_in_progress, set_monitor_update_in_progress, clear_monitor_update_in_progress, FUNDED_STATES);
686705
impl_state_flag!(is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent, FUNDED_STATES);
687706
impl_state_flag!(is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent, FUNDED_STATES);
707+
impl_state_flag!(is_interactive_signing, set_interactive_signing, clear_interactive_signing, FUNDED_STATES);
708+
impl_state_flag!(is_our_tx_signatures_sent, set_our_tx_signatures_sent, clear_our_tx_signatures_sent, FUNDED_STATES);
709+
impl_state_flag!(is_their_tx_signatures_sent, set_their_tx_signatures_sent, clear_their_tx_signatures_sent, FUNDED_STATES);
688710
impl_state_flag!(is_our_channel_ready, set_our_channel_ready, clear_our_channel_ready, AwaitingChannelReady);
689711
impl_state_flag!(is_their_channel_ready, set_their_channel_ready, clear_their_channel_ready, AwaitingChannelReady);
690712
impl_state_flag!(is_waiting_for_batch, set_waiting_for_batch, clear_waiting_for_batch, AwaitingChannelReady);
@@ -2094,10 +2116,12 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
20942116
context.channel_id = channel_id;
20952117

20962118
assert!(!context.channel_state.is_monitor_update_in_progress()); // We have not had any monitor(s) yet to fail update!
2097-
if context.is_batch_funding() {
2098-
context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH);
2099-
} else {
2100-
context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
2119+
if !context.channel_state.is_interactive_signing() {
2120+
if context.is_batch_funding() {
2121+
context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH);
2122+
} else {
2123+
context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
2124+
}
21012125
}
21022126
if holder_commitment_point.advance(&context.holder_signer, &context.secp_ctx, logger).is_err() {
21032127
// We only fail to advance our commitment point/number if we're currently
@@ -2351,7 +2375,9 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
23512375
)));
23522376
};
23532377

2354-
self.context.channel_state = ChannelState::FundingNegotiated;
2378+
let mut channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
2379+
channel_state.set_interactive_signing();
2380+
self.context.channel_state = channel_state;
23552381

23562382
// Clear the interactive transaction constructor
23572383
self.interactive_tx_constructor.take();
@@ -4437,7 +4463,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
44374463
ChannelState::FundingNegotiated => f(),
44384464
ChannelState::AwaitingChannelReady(flags) =>
44394465
if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) ||
4440-
flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into())
4466+
flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into()) ||
4467+
(flags.is_set(FundedStateFlags::THEIR_TX_SIGNATURES_SENT.into()) && flags.is_set(FundedStateFlags::OUR_TX_SIGNATURES_SENT.into()))
44414468
{
44424469
f()
44434470
} else {
@@ -5644,7 +5671,7 @@ impl<SP: Deref> FundedChannel<SP> where
56445671
) -> Result<ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>, ChannelError>
56455672
where L::Target: Logger
56465673
{
5647-
if !matches!(self.context.channel_state, ChannelState::FundingNegotiated) {
5674+
if !matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(_)) {
56485675
return Err(ChannelError::Close(
56495676
(
56505677
"Received initial commitment_signed before funding transaction constructed!".to_owned(),
@@ -5661,7 +5688,6 @@ impl<SP: Deref> FundedChannel<SP> where
56615688
log_info!(logger, "Received initial commitment_signed from peer for channel {}", &self.context.channel_id());
56625689

56635690
let need_channel_ready = self.check_get_channel_ready(0, logger).is_some();
5664-
self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
56655691
self.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
56665692

56675693
if let Some(tx_signatures) = self.interactive_tx_signing_session.as_mut().and_then(
@@ -6251,7 +6277,7 @@ impl<SP: Deref> FundedChannel<SP> where
62516277
pub fn tx_signatures<L: Deref>(&mut self, msg: &msgs::TxSignatures, logger: &L) -> Result<Option<msgs::TxSignatures>, ChannelError>
62526278
where L::Target: Logger
62536279
{
6254-
if !matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(_)) {
6280+
if !matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.is_interactive_signing()) {
62556281
return Err(ChannelError::close("Received tx_signatures in strange state!".to_owned()));
62566282
}
62576283

@@ -6288,6 +6314,8 @@ impl<SP: Deref> FundedChannel<SP> where
62886314
let (holder_tx_signatures_opt, funding_tx_opt) = signing_session.received_tx_signatures(msg.clone())
62896315
.map_err(|_| ChannelError::Warn("Witness count did not match contributed input count".to_string()))?;
62906316

6317+
// Set `THEIR_TX_SIGNATURES_SENT` flag after all potential errors.
6318+
self.context.channel_state.set_their_tx_signatures_sent();
62916319

62926320
if funding_tx_opt.is_some() {
62936321
// We have a finalized funding transaction, so we can set the funding transaction and reset the
@@ -6302,6 +6330,10 @@ impl<SP: Deref> FundedChannel<SP> where
63026330
return Ok(None);
63036331
}
63046332

6333+
if holder_tx_signatures_opt.is_some() {
6334+
self.context.channel_state.set_our_tx_signatures_sent();
6335+
}
6336+
63056337
Ok(holder_tx_signatures_opt)
63066338
} else {
63076339
Err(ChannelError::Close((
@@ -6524,7 +6556,7 @@ impl<SP: Deref> FundedChannel<SP> where
65246556
// first received the funding_signed.
65256557
let mut funding_broadcastable = None;
65266558
if let Some(funding_transaction) = &self.funding.funding_transaction {
6527-
if (self.funding.is_outbound() || self.is_v2_established()) &&
6559+
if (self.funding.is_outbound() || (self.is_v2_established() && self.context.channel_state.is_their_tx_signatures_sent())) &&
65286560
(matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) ||
65296561
matches!(self.context.channel_state, ChannelState::ChannelReady(_)))
65306562
{
@@ -6562,6 +6594,9 @@ impl<SP: Deref> FundedChannel<SP> where
65626594
// MonitorUpdateInProgress (and we assume the user will never directly broadcast the funding
65636595
// transaction and waits for us to do it).
65646596
let tx_signatures = self.context.monitor_pending_tx_signatures.take();
6597+
if tx_signatures.is_some() {
6598+
self.context.channel_state.set_our_tx_signatures_sent();
6599+
}
65656600

65666601
if self.context.channel_state.is_peer_disconnected() {
65676602
self.context.monitor_pending_revoke_and_ack = false;
@@ -7030,7 +7065,7 @@ impl<SP: Deref> FundedChannel<SP> where
70307065
if session.unsigned_tx().compute_txid() == next_funding_txid {
70317066
debug_assert_eq!(session.unsigned_tx().compute_txid(), self.maybe_get_next_funding_txid().unwrap());
70327067

7033-
let commitment_update = if !session.counterparty_sent_tx_signatures() && msg.next_local_commitment_number == 0 {
7068+
let commitment_update = if !self.context.channel_state.is_their_tx_signatures_sent() && msg.next_local_commitment_number == 0 {
70347069
// if it has not received tx_signatures for that funding transaction AND
70357070
// if next_commitment_number is zero:
70367071
// MUST retransmit its commitment_signed for that funding transaction.
@@ -7050,9 +7085,9 @@ impl<SP: Deref> FundedChannel<SP> where
70507085
// else if it HAS received commitment_signed AND has received tx_signatures for that funding transaction:
70517086
// MUST send its tx_signatures for that funding transaction.
70527087
let tx_signatures = if session.has_received_commitment_signed() && ((
7053-
!session.counterparty_sent_tx_signatures() &&
7088+
!self.context.channel_state.is_their_tx_signatures_sent() &&
70547089
session.holder_sends_tx_signatures_first()
7055-
) || session.counterparty_sent_tx_signatures()) {
7090+
) || self.context.channel_state.is_their_tx_signatures_sent()) {
70567091
// This should have already been set in `commitment_signed_initial_v2`, but check again
70577092
// just in case.
70587093
if self.context.channel_state.is_monitor_update_in_progress() {
@@ -8424,9 +8459,9 @@ impl<SP: Deref> FundedChannel<SP> where
84248459
// If we've sent `commtiment_signed` for an interactively constructed transaction
84258460
// during a signing session, but have not received `tx_signatures` we MUST set `next_funding_txid`
84268461
// to the txid of that interactive transaction, else we MUST NOT set it.
8427-
if let Some(signing_session) = &self.interactive_tx_signing_session {
8462+
if self.context.channel_state.is_interactive_signing() {
84288463
// Since we have a signing_session, this implies we've sent an initial `commitment_signed`...
8429-
if !signing_session.counterparty_sent_tx_signatures() {
8464+
if !self.context.channel_state.is_their_tx_signatures_sent() {
84308465
// ...but we didn't receive a `tx_signatures` from the counterparty yet.
84318466
Some(self.funding_outpoint().txid)
84328467
} else {
@@ -10614,6 +10649,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1061410649
(49, self.context.local_initiated_shutdown, option), // Added in 0.0.122
1061510650
(51, is_manual_broadcast, option), // Added in 0.0.124
1061610651
(53, funding_tx_broadcast_safe_event_emitted, option), // Added in 0.0.124
10652+
(55, self.interactive_tx_signing_session, option) // Added in 0.2
1061710653
});
1061810654

1061910655
Ok(())
@@ -10905,6 +10941,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1090510941
let mut next_holder_commitment_point_opt: Option<PublicKey> = None;
1090610942
let mut is_manual_broadcast = None;
1090710943

10944+
let mut interactive_tx_signing_session: Option<InteractiveTxSigningSession> = None;
10945+
1090810946
read_tlv_fields!(reader, {
1090910947
(0, announcement_sigs, option),
1091010948
(1, minimum_depth, option),
@@ -10940,6 +10978,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1094010978
(49, local_initiated_shutdown, option),
1094110979
(51, is_manual_broadcast, option),
1094210980
(53, funding_tx_broadcast_safe_event_emitted, option),
10981+
(55, interactive_tx_signing_session, option),
1094310982
});
1094410983

1094510984
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -11062,6 +11101,15 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1106211101
&channel_parameters.counterparty_parameters.as_ref()
1106311102
.expect("Persisted channel must have counterparty parameters").pubkeys.revocation_basepoint);
1106411103

11104+
let interactive_tx_signing_session = if channel_state.is_interactive_signing() {
11105+
interactive_tx_signing_session.zip(funding_transaction.as_ref()).map(|(mut session, funding_tx)| {
11106+
session.update_from_funding_tx_after_read(funding_tx);
11107+
session
11108+
})
11109+
} else {
11110+
None
11111+
};
11112+
1106511113
Ok(FundedChannel {
1106611114
funding: FundingScope {
1106711115
value_to_self_msat,
@@ -11194,7 +11242,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1119411242

1119511243
is_holder_quiescence_initiator: None,
1119611244
},
11197-
interactive_tx_signing_session: None,
11245+
interactive_tx_signing_session,
1119811246
is_v2_established,
1119911247
holder_commitment_point,
1120011248
#[cfg(splicing)]

0 commit comments

Comments
 (0)