Skip to content

Commit cfedf38

Browse files
committed
Persist InteractiveTxSigningSession to resume signing across restarts
We fully persist `InteractiveTxSigningSession` as it provides the full context of the constructed transaction which is still needed for signing.
1 parent c0785b3 commit cfedf38

File tree

3 files changed

+84
-3
lines changed

3 files changed

+84
-3
lines changed

Diff for: lightning/src/ln/channel.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -5039,6 +5039,13 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
50395039
pub funding: FundingScope,
50405040
pending_funding: Vec<FundingScope>,
50415041
pub context: ChannelContext<SP>,
5042+
/// The signing session for the current interactive tx construction, if any.
5043+
///
5044+
/// This is populated when the interactive tx construction phase completes
5045+
/// (i.e., upon receiving a consecutive `tx_complete`) and the channel enters
5046+
/// the signing phase (`FundingNegotiated` state with the `INTERACTIVE_SIGNING` flag set).
5047+
///
5048+
/// This field is cleared once our counterparty sends a `channel_ready`.
50425049
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
50435050
holder_commitment_point: HolderCommitmentPoint,
50445051
/// Info about an in-progress, pending splice (if any), on the pre-splice channel
@@ -10949,6 +10956,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1094910956
(54, self.pending_funding, optional_vec), // Added in 0.2
1095010957
(55, removed_htlc_failure_attribution_data, optional_vec), // Added in 0.2
1095110958
(57, holding_cell_failure_attribution_data, optional_vec), // Added in 0.2
10959+
(58, self.interactive_tx_signing_session, option) // Added in 0.2
1095210960
});
1095310961

1095410962
Ok(())
@@ -11248,6 +11256,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1124811256

1124911257
let mut pending_funding = Some(Vec::new());
1125011258

11259+
let mut interactive_tx_signing_session: Option<InteractiveTxSigningSession> = None;
11260+
1125111261
read_tlv_fields!(reader, {
1125211262
(0, announcement_sigs, option),
1125311263
(1, minimum_depth, option),
@@ -11286,6 +11296,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1128611296
(54, pending_funding, optional_vec), // Added in 0.2
1128711297
(55, removed_htlc_failure_attribution_data, optional_vec),
1128811298
(57, holding_cell_failure_attribution_data, optional_vec),
11299+
(58, interactive_tx_signing_session, option), // Added in 0.2
1128911300
});
1129011301

1129111302
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -11568,7 +11579,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1156811579

1156911580
is_holder_quiescence_initiator: None,
1157011581
},
11571-
interactive_tx_signing_session: None,
11582+
interactive_tx_signing_session,
1157211583
holder_commitment_point,
1157311584
#[cfg(splicing)]
1157411585
pending_splice: None,

Diff for: lightning/src/ln/interactivetxs.rs

+51
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,18 @@ pub(crate) struct ConstructedTransaction {
189189
holder_sends_tx_signatures_first: bool,
190190
}
191191

192+
impl_writeable_tlv_based!(ConstructedTransaction, {
193+
(1, holder_is_initiator, required),
194+
(3, inputs, required),
195+
(5, outputs, required),
196+
(7, local_inputs_value_satoshis, required),
197+
(9, local_outputs_value_satoshis, required),
198+
(11, remote_inputs_value_satoshis, required),
199+
(13, remote_outputs_value_satoshis, required),
200+
(15, lock_time, required),
201+
(17, holder_sends_tx_signatures_first, required),
202+
});
203+
192204
impl ConstructedTransaction {
193205
fn new(context: NegotiationContext) -> Self {
194206
let local_inputs_value_satoshis = context
@@ -439,6 +451,13 @@ impl InteractiveTxSigningSession {
439451
}
440452
}
441453

454+
impl_writeable_tlv_based!(InteractiveTxSigningSession, {
455+
(1, unsigned_tx, required),
456+
(3, holder_sends_tx_signatures_first, required),
457+
(5, has_received_commitment_signed, required),
458+
(7, holder_tx_signatures, required),
459+
});
460+
442461
#[derive(Debug)]
443462
struct NegotiationContext {
444463
holder_node_id: PublicKey,
@@ -1162,6 +1181,11 @@ enum AddingRole {
11621181
Remote,
11631182
}
11641183

1184+
impl_writeable_tlv_based_enum!(AddingRole,
1185+
(1, Local) => {},
1186+
(3, Remote) => {},
1187+
);
1188+
11651189
/// Represents an input -- local or remote (both have the same fields)
11661190
#[derive(Clone, Debug, Eq, PartialEq)]
11671191
pub struct LocalOrRemoteInput {
@@ -1170,19 +1194,35 @@ pub struct LocalOrRemoteInput {
11701194
prev_output: TxOut,
11711195
}
11721196

1197+
impl_writeable_tlv_based!(LocalOrRemoteInput, {
1198+
(1, serial_id, required),
1199+
(3, input, required),
1200+
(5, prev_output, required),
1201+
});
1202+
11731203
#[derive(Clone, Debug, Eq, PartialEq)]
11741204
pub(crate) enum InteractiveTxInput {
11751205
Local(LocalOrRemoteInput),
11761206
Remote(LocalOrRemoteInput),
11771207
// TODO(splicing) SharedInput should be added
11781208
}
11791209

1210+
impl_writeable_tlv_based_enum!(InteractiveTxInput,
1211+
{1, Local} => (),
1212+
{3, Remote} => (),
1213+
);
1214+
11801215
#[derive(Clone, Debug, Eq, PartialEq)]
11811216
pub(super) struct SharedOwnedOutput {
11821217
tx_out: TxOut,
11831218
local_owned: u64,
11841219
}
11851220

1221+
impl_writeable_tlv_based!(SharedOwnedOutput, {
1222+
(1, tx_out, required),
1223+
(3, local_owned, required),
1224+
});
1225+
11861226
impl SharedOwnedOutput {
11871227
pub fn new(tx_out: TxOut, local_owned: u64) -> SharedOwnedOutput {
11881228
debug_assert!(
@@ -1210,6 +1250,11 @@ pub(super) enum OutputOwned {
12101250
Shared(SharedOwnedOutput),
12111251
}
12121252

1253+
impl_writeable_tlv_based_enum!(OutputOwned,
1254+
{1, Single} => (),
1255+
{3, Shared} => (),
1256+
);
1257+
12131258
impl OutputOwned {
12141259
pub fn tx_out(&self) -> &TxOut {
12151260
match self {
@@ -1264,6 +1309,12 @@ pub(crate) struct InteractiveTxOutput {
12641309
output: OutputOwned,
12651310
}
12661311

1312+
impl_writeable_tlv_based!(InteractiveTxOutput, {
1313+
(1, serial_id, required),
1314+
(3, added_by, required),
1315+
(5, output, required),
1316+
});
1317+
12671318
impl InteractiveTxOutput {
12681319
pub fn tx_out(&self) -> &TxOut {
12691320
self.output.tx_out()

Diff for: lightning/src/util/ser.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
1616
use crate::io::{self, BufRead, Read, Write};
1717
use crate::io_extras::{copy, sink};
18+
use crate::ln::interactivetxs::{InteractiveTxInput, InteractiveTxOutput};
1819
use crate::ln::onion_utils::{HMAC_COUNT, HMAC_LEN, HOLD_TIME_LEN, MAX_HOPS};
1920
use crate::prelude::*;
2021
use crate::sync::{Mutex, RwLock};
@@ -24,6 +25,7 @@ use core::ops::Deref;
2425

2526
use alloc::collections::BTreeMap;
2627

28+
use bitcoin::absolute::LockTime as AbsoluteLockTime;
2729
use bitcoin::amount::Amount;
2830
use bitcoin::consensus::Encodable;
2931
use bitcoin::constants::ChainHash;
@@ -39,14 +41,14 @@ use bitcoin::secp256k1::ecdsa;
3941
use bitcoin::secp256k1::schnorr;
4042
use bitcoin::secp256k1::{PublicKey, SecretKey};
4143
use bitcoin::transaction::{OutPoint, Transaction, TxOut};
42-
use bitcoin::{consensus, Witness};
44+
use bitcoin::{consensus, TxIn, Witness};
4345

4446
use dnssec_prover::rr::Name;
4547

4648
use crate::chain::ClaimId;
47-
use crate::ln::msgs::DecodeError;
4849
#[cfg(taproot)]
4950
use crate::ln::msgs::PartialSignatureWithNonce;
51+
use crate::ln::msgs::{DecodeError, SerialId};
5052
use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
5153
use core::time::Duration;
5254

@@ -1079,6 +1081,9 @@ impl_for_vec!(crate::ln::channelmanager::MonitorUpdateCompletionAction);
10791081
impl_for_vec!(crate::ln::channelmanager::PaymentClaimDetails);
10801082
impl_for_vec!(crate::ln::msgs::SocketAddress);
10811083
impl_for_vec!((A, B), A, B);
1084+
impl_for_vec!(SerialId);
1085+
impl_for_vec!(InteractiveTxInput);
1086+
impl_for_vec!(InteractiveTxOutput);
10821087
impl_writeable_for_vec!(&crate::routing::router::BlindedTail);
10831088
impl_readable_for_vec!(crate::routing::router::BlindedTail);
10841089
impl_for_vec!(crate::routing::router::TrampolineHop);
@@ -1350,6 +1355,19 @@ impl<T: LengthReadable> Readable for Option<T> {
13501355
}
13511356
}
13521357

1358+
impl Writeable for AbsoluteLockTime {
1359+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
1360+
self.to_consensus_u32().write(w)
1361+
}
1362+
}
1363+
1364+
impl Readable for AbsoluteLockTime {
1365+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
1366+
let lock_time: u32 = Readable::read(r)?;
1367+
Ok(AbsoluteLockTime::from_consensus(lock_time))
1368+
}
1369+
}
1370+
13531371
impl Writeable for Amount {
13541372
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
13551373
self.to_sat().write(w)
@@ -1451,6 +1469,7 @@ macro_rules! impl_consensus_ser {
14511469
};
14521470
}
14531471
impl_consensus_ser!(Transaction);
1472+
impl_consensus_ser!(TxIn);
14541473
impl_consensus_ser!(TxOut);
14551474
impl_consensus_ser!(Witness);
14561475

0 commit comments

Comments
 (0)