Skip to content

Commit 70a8a62

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 b4448ef commit 70a8a62

File tree

3 files changed

+143
-4
lines changed

3 files changed

+143
-4
lines changed

lightning/src/ln/channel.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -10640,6 +10640,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1064010640
(49, self.context.local_initiated_shutdown, option), // Added in 0.0.122
1064110641
(51, is_manual_broadcast, option), // Added in 0.0.124
1064210642
(53, funding_tx_broadcast_safe_event_emitted, option), // Added in 0.0.124
10643+
(54, self.interactive_tx_signing_session, option) // Added in 0.2, even as we don't want downgrades during a signing session
1064310644
});
1064410645

1064510646
Ok(())
@@ -10931,6 +10932,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1093110932
let mut next_holder_commitment_point_opt: Option<PublicKey> = None;
1093210933
let mut is_manual_broadcast = None;
1093310934

10935+
let mut interactive_tx_signing_session: Option<InteractiveTxSigningSession> = None;
10936+
1093410937
read_tlv_fields!(reader, {
1093510938
(0, announcement_sigs, option),
1093610939
(1, minimum_depth, option),
@@ -10966,6 +10969,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1096610969
(49, local_initiated_shutdown, option),
1096710970
(51, is_manual_broadcast, option),
1096810971
(53, funding_tx_broadcast_safe_event_emitted, option),
10972+
(54, interactive_tx_signing_session, option),
1096910973
});
1097010974

1097110975
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -11220,7 +11224,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1122011224

1122111225
is_holder_quiescence_initiator: None,
1122211226
},
11223-
interactive_tx_signing_session: None,
11227+
interactive_tx_signing_session,
1122411228
is_v2_established,
1122511229
holder_commitment_point,
1122611230
#[cfg(splicing)]

lightning/src/ln/interactivetxs.rs

+133-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@
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;
1515
use bitcoin::consensus::Encodable;
1616
use bitcoin::constants::WITNESS_SCALE_FACTOR;
17+
use bitcoin::hashes::Hash;
1718
use bitcoin::policy::MAX_STANDARD_TX_WEIGHT;
1819
use bitcoin::secp256k1::PublicKey;
1920
use bitcoin::transaction::Version;
@@ -26,11 +27,13 @@ use crate::ln::msgs;
2627
use crate::ln::msgs::{MessageSendEvent, SerialId, TxSignatures};
2728
use crate::ln::types::ChannelId;
2829
use crate::sign::{EntropySource, P2TR_KEY_PATH_WITNESS_WEIGHT, P2WPKH_WITNESS_WEIGHT};
29-
use crate::util::ser::TransactionU16LenLimited;
30+
use crate::util::ser::{Readable, TransactionU16LenLimited, Writeable, Writer};
3031

3132
use core::fmt::Display;
3233
use core::ops::Deref;
3334

35+
use super::msgs::DecodeError;
36+
3437
/// The number of received `tx_add_input` messages during a negotiation at which point the
3538
/// negotiation MUST be failed.
3639
const MAX_RECEIVED_TX_ADD_INPUT_COUNT: u16 = 4096;
@@ -168,6 +171,61 @@ pub(crate) struct ConstructedTransaction {
168171
holder_sends_tx_signatures_first: bool,
169172
}
170173

174+
impl Writeable for ConstructedTransaction {
175+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
176+
let lock_time = self.lock_time.to_consensus_u32();
177+
write_tlv_fields!(writer, {
178+
(1, self.holder_is_initiator, required),
179+
(3, self.inputs, required),
180+
(5, self.outputs, required),
181+
(7, self.local_inputs_value_satoshis, required),
182+
(9, self.local_outputs_value_satoshis, required),
183+
(11, self.remote_inputs_value_satoshis, required),
184+
(13, self.remote_outputs_value_satoshis, required),
185+
(15, lock_time, required),
186+
(17, self.holder_sends_tx_signatures_first, required),
187+
});
188+
Ok(())
189+
}
190+
}
191+
192+
impl Readable for ConstructedTransaction {
193+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
194+
let mut holder_is_initiator = false;
195+
let mut inputs: Vec<InteractiveTxInput> = vec![];
196+
let mut outputs: Vec<InteractiveTxOutput> = vec![];
197+
let mut local_inputs_value_satoshis: u64 = 0;
198+
let mut local_outputs_value_satoshis: u64 = 0;
199+
let mut remote_inputs_value_satoshis: u64 = 0;
200+
let mut remote_outputs_value_satoshis: u64 = 0;
201+
let mut lock_time: u32 = 0;
202+
let mut holder_sends_tx_signatures_first = false;
203+
read_tlv_fields!(reader, {
204+
(1, holder_is_initiator, required),
205+
(3, inputs, required),
206+
(5, outputs, required),
207+
(7, local_inputs_value_satoshis, required),
208+
(9, local_outputs_value_satoshis, required),
209+
(11, remote_inputs_value_satoshis, required),
210+
(13, remote_outputs_value_satoshis, required),
211+
(15, lock_time, required),
212+
(17, holder_sends_tx_signatures_first, required),
213+
});
214+
let lock_time = AbsoluteLockTime::from_consensus(lock_time);
215+
Ok(ConstructedTransaction {
216+
holder_is_initiator,
217+
inputs,
218+
outputs,
219+
local_inputs_value_satoshis,
220+
local_outputs_value_satoshis,
221+
remote_inputs_value_satoshis,
222+
remote_outputs_value_satoshis,
223+
lock_time,
224+
holder_sends_tx_signatures_first,
225+
})
226+
}
227+
}
228+
171229
impl ConstructedTransaction {
172230
fn new(context: NegotiationContext) -> Self {
173231
let local_inputs_value_satoshis = context
@@ -418,6 +476,13 @@ impl InteractiveTxSigningSession {
418476
}
419477
}
420478

479+
impl_writeable_tlv_based!(InteractiveTxSigningSession, {
480+
(1, unsigned_tx, required),
481+
(3, holder_sends_tx_signatures_first, required),
482+
(5, has_received_commitment_signed, required),
483+
(7, holder_tx_signatures, required),
484+
});
485+
421486
#[derive(Debug)]
422487
struct NegotiationContext {
423488
holder_node_id: PublicKey,
@@ -1141,6 +1206,11 @@ enum AddingRole {
11411206
Remote,
11421207
}
11431208

1209+
impl_writeable_tlv_based_enum!(AddingRole,
1210+
(1, Local) => {},
1211+
(3, Remote) => {},
1212+
);
1213+
11441214
/// Represents an input -- local or remote (both have the same fields)
11451215
#[derive(Clone, Debug, Eq, PartialEq)]
11461216
pub struct LocalOrRemoteInput {
@@ -1149,19 +1219,68 @@ pub struct LocalOrRemoteInput {
11491219
prev_output: TxOut,
11501220
}
11511221

1222+
impl Writeable for LocalOrRemoteInput {
1223+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
1224+
write_tlv_fields!(writer, {
1225+
(1, self.serial_id, required),
1226+
(3, self.input.sequence.0, required),
1227+
(5, self.input.previous_output, required),
1228+
(7, self.input.script_sig, required),
1229+
(9, self.input.witness, required),
1230+
(11, self.prev_output, required),
1231+
});
1232+
Ok(())
1233+
}
1234+
}
1235+
1236+
impl Readable for LocalOrRemoteInput {
1237+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
1238+
let mut serial_id: u64 = 0;
1239+
let mut sequence: u32 = 0;
1240+
let mut previous_output = OutPoint::new(Txid::from_byte_array([0; 32]), 0);
1241+
let mut script_sig = ScriptBuf::default();
1242+
let mut witness = Witness::new();
1243+
let mut prev_output =
1244+
TxOut { value: Amount::default(), script_pubkey: ScriptBuf::default() };
1245+
read_tlv_fields!(reader, {
1246+
(1, serial_id, required),
1247+
(3, sequence, required),
1248+
(5, previous_output, required),
1249+
(7, script_sig, required),
1250+
(9, witness, required),
1251+
(11, prev_output, required),
1252+
});
1253+
Ok(LocalOrRemoteInput {
1254+
serial_id,
1255+
input: TxIn { previous_output, script_sig, sequence: Sequence(sequence), witness },
1256+
prev_output,
1257+
})
1258+
}
1259+
}
1260+
11521261
#[derive(Clone, Debug, Eq, PartialEq)]
11531262
pub(crate) enum InteractiveTxInput {
11541263
Local(LocalOrRemoteInput),
11551264
Remote(LocalOrRemoteInput),
11561265
// TODO(splicing) SharedInput should be added
11571266
}
11581267

1268+
impl_writeable_tlv_based_enum!(InteractiveTxInput,
1269+
{1, Local} => (),
1270+
{3, Remote} => (),
1271+
);
1272+
11591273
#[derive(Clone, Debug, Eq, PartialEq)]
11601274
pub struct SharedOwnedOutput {
11611275
tx_out: TxOut,
11621276
local_owned: u64,
11631277
}
11641278

1279+
impl_writeable_tlv_based!(SharedOwnedOutput, {
1280+
(1, tx_out, required),
1281+
(3, local_owned, required),
1282+
});
1283+
11651284
impl SharedOwnedOutput {
11661285
fn new(tx_out: TxOut, local_owned: u64) -> SharedOwnedOutput {
11671286
debug_assert!(
@@ -1191,6 +1310,12 @@ pub enum OutputOwned {
11911310
Shared(SharedOwnedOutput),
11921311
}
11931312

1313+
impl_writeable_tlv_based_enum!(OutputOwned,
1314+
{1, Single} => (),
1315+
{3, SharedControlFullyOwned} => (),
1316+
{5, Shared} => (),
1317+
);
1318+
11941319
impl OutputOwned {
11951320
fn tx_out(&self) -> &TxOut {
11961321
match self {
@@ -1250,6 +1375,12 @@ pub(crate) struct InteractiveTxOutput {
12501375
output: OutputOwned,
12511376
}
12521377

1378+
impl_writeable_tlv_based!(InteractiveTxOutput, {
1379+
(1, serial_id, required),
1380+
(3, added_by, required),
1381+
(5, output, required),
1382+
});
1383+
12531384
impl InteractiveTxOutput {
12541385
pub fn tx_out(&self) -> &TxOut {
12551386
self.output.tx_out()

lightning/src/util/ser.rs

+5-1
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::prelude::*;
1920
use crate::sync::{Mutex, RwLock};
2021
use core::cmp;
@@ -43,9 +44,9 @@ use bitcoin::{consensus, Witness};
4344
use dnssec_prover::rr::Name;
4445

4546
use crate::chain::ClaimId;
46-
use crate::ln::msgs::DecodeError;
4747
#[cfg(taproot)]
4848
use crate::ln::msgs::PartialSignatureWithNonce;
49+
use crate::ln::msgs::{DecodeError, SerialId};
4950
use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
5051
use core::time::Duration;
5152

@@ -1074,6 +1075,9 @@ impl_for_vec!(crate::ln::channelmanager::MonitorUpdateCompletionAction);
10741075
impl_for_vec!(crate::ln::channelmanager::PaymentClaimDetails);
10751076
impl_for_vec!(crate::ln::msgs::SocketAddress);
10761077
impl_for_vec!((A, B), A, B);
1078+
impl_for_vec!(SerialId);
1079+
impl_for_vec!(InteractiveTxInput);
1080+
impl_for_vec!(InteractiveTxOutput);
10771081
impl_writeable_for_vec!(&crate::routing::router::BlindedTail);
10781082
impl_readable_for_vec!(crate::routing::router::BlindedTail);
10791083
impl_for_vec!(crate::routing::router::TrampolineHop);

0 commit comments

Comments
 (0)