Skip to content

Commit 5d0876f

Browse files
committed
wip interactivesigning channelstate
1 parent 2079148 commit 5d0876f

File tree

3 files changed

+153
-14
lines changed

3 files changed

+153
-14
lines changed

lightning/src/ln/channel.rs

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,12 @@ macro_rules! define_state_flags {
432432
is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent);
433433
define_state_flags!($flag_type, FundedStateFlags::LOCAL_SHUTDOWN_SENT,
434434
is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent);
435+
define_state_flags!($flag_type, FundedStateFlags::INTERACTIVE_SIGNING,
436+
is_interactive_signing, set_interactive_signing, clear_interactive_signing);
437+
define_state_flags!($flag_type, FundedStateFlags::THEIR_TX_SIGNATURES_SENT,
438+
is_their_tx_signatures, set_their_tx_signatures, clear_their_tx_signatures);
439+
define_state_flags!($flag_type, FundedStateFlags::OUR_TX_SIGNATURES_SENT,
440+
is_our_tx_signatures, set_our_tx_signatures, clear_our_tx_signatures);
435441

436442
impl core::ops::BitOr<FundedStateFlags> for $flag_type {
437443
type Output = Self;
@@ -477,6 +483,9 @@ mod state_flags {
477483
pub const LOCAL_STFU_SENT: u32 = 1 << 15;
478484
pub const REMOTE_STFU_SENT: u32 = 1 << 16;
479485
pub const QUIESCENT: u32 = 1 << 17;
486+
pub const INTERACTIVE_SIGNING: u32 = 1 << 18;
487+
pub const OUR_TX_SIGNATURES_SENT: u32 = 1 << 19;
488+
pub const THEIR_TX_SIGNATURES_SENT: u32 = 1 << 20;
480489
}
481490

482491
define_state_flags!(
@@ -495,7 +504,16 @@ define_state_flags!(
495504
is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent),
496505
("Indicates we sent a `shutdown` message. At this point, we may not add any new HTLCs to \
497506
the channel.", LOCAL_SHUTDOWN_SENT, state_flags::LOCAL_SHUTDOWN_SENT,
498-
is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent)
507+
is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent),
508+
("Indicates we have an active interactive signing session for an interactive transaction",
509+
INTERACTIVE_SIGNING, state_flags::INTERACTIVE_SIGNING,
510+
is_interactive_signing, set_interactive_signing, clear_interactive_singing),
511+
("Indicates they sent us a `tx_signatures` message.",
512+
THEIR_TX_SIGNATURES_SENT, state_flags::THEIR_TX_SIGNATURES_SENT,
513+
is_their_tx_signatures, set_their_tx_signatures, clear_their_tx_signatures),
514+
("Indicates we sent them a `tx_signatures` message.",
515+
OUR_TX_SIGNATURES_SENT, state_flags::OUR_TX_SIGNATURES_SENT,
516+
is_our_tx_signatures, set_our_tx_signatures, clear_our_tx_signatures)
499517
]
500518
);
501519

@@ -566,7 +584,8 @@ enum ChannelState {
566584
NegotiatingFunding(NegotiatingFundingFlags),
567585
/// We have sent `funding_created` and are awaiting a `funding_signed` to advance to
568586
/// `AwaitingChannelReady`. Note that this is nonsense for an inbound channel as we immediately generate
569-
/// `funding_signed` upon receipt of `funding_created`, so simply skip this state.
587+
/// `funding_signed` upon receipt of `funding_created`, so simply skip this state. For dual-funded (V2)
588+
/// channels, this state is also skipped.
570589
FundingNegotiated,
571590
/// We've received/sent `funding_created` and `funding_signed` and are thus now waiting on the
572591
/// funding transaction to confirm.
@@ -683,6 +702,9 @@ impl ChannelState {
683702
impl_state_flag!(is_monitor_update_in_progress, set_monitor_update_in_progress, clear_monitor_update_in_progress, FUNDED_STATES);
684703
impl_state_flag!(is_local_shutdown_sent, set_local_shutdown_sent, clear_local_shutdown_sent, FUNDED_STATES);
685704
impl_state_flag!(is_remote_shutdown_sent, set_remote_shutdown_sent, clear_remote_shutdown_sent, FUNDED_STATES);
705+
impl_state_flag!(is_interactive_signing, set_interactive_signing, clear_interactive_signing, FUNDED_STATES);
706+
impl_state_flag!(is_our_tx_signatures, set_our_tx_signatures, clear_our_tx_signatures, FUNDED_STATES);
707+
impl_state_flag!(is_their_tx_signatures, set_their_tx_signatures, clear_their_tx_signatures, FUNDED_STATES);
686708
impl_state_flag!(is_our_channel_ready, set_our_channel_ready, clear_our_channel_ready, AwaitingChannelReady);
687709
impl_state_flag!(is_their_channel_ready, set_their_channel_ready, clear_their_channel_ready, AwaitingChannelReady);
688710
impl_state_flag!(is_waiting_for_batch, set_waiting_for_batch, clear_waiting_for_batch, AwaitingChannelReady);
@@ -2084,10 +2106,15 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
20842106
context.channel_id = channel_id;
20852107

20862108
assert!(!context.channel_state.is_monitor_update_in_progress()); // We have not had any monitor(s) yet to fail update!
2087-
if context.is_batch_funding() {
2088-
context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH);
2089-
} else {
2090-
context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
2109+
if !matches!(
2110+
context.channel_state,
2111+
ChannelState::AwaitingChannelReady(flags) if flags.is_set(FundedStateFlags::INTERACTIVE_SIGNING.into())
2112+
) {
2113+
if context.is_batch_funding() {
2114+
context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH);
2115+
} else {
2116+
context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
2117+
}
20912118
}
20922119
if holder_commitment_point.advance(&context.holder_signer, &context.secp_ctx, logger).is_err() {
20932120
// We only fail to advance our commitment point/number if we're currently
@@ -2348,7 +2375,9 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
23482375
)));
23492376
};
23502377

2351-
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;
23522381

23532382
// Clear the interactive transaction constructor
23542383
self.interactive_tx_constructor.take();
@@ -4289,7 +4318,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
42894318
ChannelState::FundingNegotiated => f(),
42904319
ChannelState::AwaitingChannelReady(flags) =>
42914320
if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) ||
4292-
flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into())
4321+
flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into()) ||
4322+
(flags.is_set(FundedStateFlags::THEIR_TX_SIGNATURES_SENT.into()) && flags.is_set(FundedStateFlags::OUR_TX_SIGNATURES_SENT.into()))
42934323
{
42944324
f()
42954325
} else {
@@ -5440,7 +5470,7 @@ impl<SP: Deref> FundedChannel<SP> where
54405470
) -> Result<ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>, ChannelError>
54415471
where L::Target: Logger
54425472
{
5443-
if !matches!(self.context.channel_state, ChannelState::FundingNegotiated) {
5473+
if !matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(_)) {
54445474
return Err(ChannelError::Close(
54455475
(
54465476
"Received initial commitment_signed before funding transaction constructed!".to_owned(),
@@ -5458,7 +5488,6 @@ impl<SP: Deref> FundedChannel<SP> where
54585488
log_info!(logger, "Received initial commitment_signed from peer for channel {}", &self.context.channel_id());
54595489

54605490
let need_channel_ready = self.check_get_channel_ready(0, logger).is_some();
5461-
self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
54625491
self.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
54635492

54645493
if let Some(tx_signatures) = self.interactive_tx_signing_session.as_mut().and_then(
@@ -10348,6 +10377,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1034810377
(49, self.context.local_initiated_shutdown, option), // Added in 0.0.122
1034910378
(51, is_manual_broadcast, option), // Added in 0.0.124
1035010379
(53, funding_tx_broadcast_safe_event_emitted, option), // Added in 0.0.124
10380+
(55, self.interactive_tx_signing_session, option) // Added in 0.2
1035110381
});
1035210382

1035310383
Ok(())
@@ -10636,6 +10666,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1063610666
let mut next_holder_commitment_point_opt: Option<PublicKey> = None;
1063710667
let mut is_manual_broadcast = None;
1063810668

10669+
let mut interactive_tx_signing_session: Option<InteractiveTxSigningSession> = None;
10670+
1063910671
read_tlv_fields!(reader, {
1064010672
(0, announcement_sigs, option),
1064110673
(1, minimum_depth, option),
@@ -10671,6 +10703,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1067110703
(49, local_initiated_shutdown, option),
1067210704
(51, is_manual_broadcast, option),
1067310705
(53, funding_tx_broadcast_safe_event_emitted, option),
10706+
(55, interactive_tx_signing_session, option),
1067410707
});
1067510708

1067610709
let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
@@ -10800,6 +10833,24 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1080010833
&channel_parameters.counterparty_parameters.as_ref()
1080110834
.expect("Persisted channel must have counterparty parameters").pubkeys.revocation_basepoint);
1080210835

10836+
let interactive_tx_signing_session = if matches!(
10837+
channel_state,
10838+
ChannelState::AwaitingChannelReady(flags) if flags.is_set(FundedStateFlags::INTERACTIVE_SIGNING.into())
10839+
) {
10840+
if let Some(mut signing_session) = interactive_tx_signing_session {
10841+
if let Some(ref funding_tx) = funding_transaction {
10842+
signing_session.update_from_funding_tx_after_read(funding_tx);
10843+
Some(signing_session)
10844+
} else {
10845+
None
10846+
}
10847+
} else {
10848+
None
10849+
}
10850+
} else {
10851+
None
10852+
};
10853+
1080310854
Ok(FundedChannel {
1080410855
funding: FundingScope {
1080510856
value_to_self_msat,
@@ -10932,7 +10983,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1093210983

1093310984
is_holder_quiescence_initiator: None,
1093410985
},
10935-
interactive_tx_signing_session: None,
10986+
interactive_tx_signing_session,
1093610987
is_v2_established,
1093710988
holder_commitment_point,
1093810989
})

lightning/src/ln/interactivetxs.rs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// licenses.
99

1010
use crate::io_extras::sink;
11-
use crate::prelude::*;
11+
use crate::{io, prelude::*};
1212

1313
use bitcoin::absolute::LockTime as AbsoluteLockTime;
1414
use bitcoin::amount::Amount;
@@ -27,11 +27,13 @@ use crate::ln::msgs;
2727
use crate::ln::msgs::{SerialId, TxSignatures};
2828
use crate::ln::types::ChannelId;
2929
use crate::sign::{EntropySource, P2TR_KEY_PATH_WITNESS_WEIGHT, P2WPKH_WITNESS_WEIGHT};
30-
use crate::util::ser::TransactionU16LenLimited;
30+
use crate::util::ser::{Readable, TransactionU16LenLimited, Writeable, Writer};
3131

3232
use core::fmt::Display;
3333
use core::ops::Deref;
3434

35+
use super::msgs::DecodeError;
36+
3537
/// The number of received `tx_add_input` messages during a negotiation at which point the
3638
/// negotiation MUST be failed.
3739
const MAX_RECEIVED_TX_ADD_INPUT_COUNT: u16 = 4096;
@@ -431,6 +433,91 @@ impl InteractiveTxSigningSession {
431433
output: outputs.iter().cloned().map(|output| output.into_tx_out()).collect(),
432434
}
433435
}
436+
437+
pub fn update_from_funding_tx_after_read(&mut self, funding_tx: &Transaction) {
438+
self.unsigned_tx.inputs.iter_mut().zip(funding_tx.input.iter().cloned()).for_each(|(placeholder, real)| {
439+
*placeholder.txin_mut() = real;
440+
});
441+
self.unsigned_tx.outputs.iter_mut().zip(funding_tx.output.iter().cloned()).for_each(|(placeholder, real)| {
442+
(*placeholder).output = OutputOwned::Single(real);
443+
});
444+
}
445+
}
446+
447+
impl Writeable for InteractiveTxSigningSession {
448+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
449+
self.unsigned_tx.holder_is_initiator.write(writer)?;
450+
self.unsigned_tx.holder_sends_tx_signatures_first.write(writer)?;
451+
self.unsigned_tx.inputs.iter().map(|input| {
452+
input.serial_id()
453+
}).collect::<Vec<_>>().write(writer)?;
454+
self.unsigned_tx.outputs.iter().map(|output| {
455+
output.serial_id
456+
}).collect::<Vec<_>>().write(writer)?;
457+
self.holder_tx_signatures.write(writer)?;
458+
self.counterparty_sent_tx_signatures.write(writer)?;
459+
self.has_received_commitment_signed.write(writer)?;
460+
Ok(())
461+
}
462+
}
463+
464+
impl Readable for InteractiveTxSigningSession {
465+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
466+
let holder_is_initiator: bool = Readable::read(reader)?;
467+
let holder_sends_tx_signatures_first: bool = Readable::read(reader)?;
468+
let inputs: Vec<SerialId> = Readable::read(reader)?;
469+
let outputs: Vec<SerialId> = Readable::read(reader)?;
470+
let holder_tx_signatures: Option<TxSignatures> = Readable::read(reader)?;
471+
let counterparty_sent_tx_signatures: bool = Readable::read(reader)?;
472+
let has_received_commitment_signed: bool = Readable::read(reader)?;
473+
474+
// We use an empty dummy `TxOut` for all `TxOut`s as they will be populated with their real
475+
// values from `funding_transaction` after reading.
476+
let dummy_txout = TxOut { value: Amount::default(), script_pubkey: ScriptBuf::new() };
477+
478+
Ok(
479+
InteractiveTxSigningSession {
480+
counterparty_sent_tx_signatures,
481+
holder_sends_tx_signatures_first,
482+
has_received_commitment_signed,
483+
holder_tx_signatures,
484+
unsigned_tx: ConstructedTransaction {
485+
holder_is_initiator,
486+
holder_sends_tx_signatures_first,
487+
inputs: inputs.into_iter().map(|serial_id| {
488+
if is_serial_id_valid_for_counterparty(holder_is_initiator, serial_id) {
489+
InteractiveTxInput::Remote(
490+
LocalOrRemoteInput { serial_id, input: TxIn::default(), prev_output: dummy_txout.clone() }
491+
)
492+
} else {
493+
InteractiveTxInput::Local(
494+
// We use a dummy TxOut that will be populated from the funding_transaction after read.
495+
LocalOrRemoteInput { serial_id, input: TxIn::default(), prev_output: dummy_txout.clone() }
496+
)
497+
}
498+
}).collect(),
499+
outputs: outputs.into_iter().map(|serial_id| {
500+
let added_by = if is_serial_id_valid_for_counterparty(holder_is_initiator, serial_id) {
501+
AddingRole::Remote
502+
} else { AddingRole::Local };
503+
InteractiveTxOutput {
504+
serial_id,
505+
added_by,
506+
// The ownership of the output is irrelevant at this point as the read would only happen
507+
// at `ChannelState::InteractiveSigning`, so we just use `Single` here.
508+
output: OutputOwned::Single(dummy_txout.clone()),
509+
510+
}
511+
}).collect(),
512+
local_inputs_value_satoshis: 0,
513+
local_outputs_value_satoshis: 0,
514+
remote_inputs_value_satoshis: 0,
515+
remote_outputs_value_satoshis: 0,
516+
lock_time: AbsoluteLockTime::from_height(0).expect("0 is a valid absolute locktime"),
517+
},
518+
}
519+
)
520+
}
434521
}
435522

436523
#[derive(Debug)]

lightning/src/util/ser.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use bitcoin::{consensus, Witness};
4343
use dnssec_prover::rr::Name;
4444

4545
use crate::chain::ClaimId;
46-
use crate::ln::msgs::DecodeError;
46+
use crate::ln::msgs::{DecodeError, SerialId};
4747
#[cfg(taproot)]
4848
use crate::ln::msgs::PartialSignatureWithNonce;
4949
use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
@@ -1058,6 +1058,7 @@ impl_for_vec!(crate::ln::channelmanager::MonitorUpdateCompletionAction);
10581058
impl_for_vec!(crate::ln::channelmanager::PaymentClaimDetails);
10591059
impl_for_vec!(crate::ln::msgs::SocketAddress);
10601060
impl_for_vec!((A, B), A, B);
1061+
impl_for_vec!(SerialId);
10611062
impl_writeable_for_vec!(&crate::routing::router::BlindedTail);
10621063
impl_readable_for_vec!(crate::routing::router::BlindedTail);
10631064
impl_for_vec!(crate::routing::router::TrampolineHop);

0 commit comments

Comments
 (0)