Skip to content

Commit 75c0586

Browse files
committed
Enable monitor to rebuild initial counterparty commitment tx
Upon creating a channel monitor, it is provided with the initial counterparty commitment transaction info directly before the very first time it is persisted. Because of this, the very first counterparty commitment is not seen as an update in the persistence pipeline, and so our previous changes to the monitor and updates cannot be used to reconstruct this commitment. To be able to expose the counterparty's transaction for the very first commitment, we add a thin wrapper around `provide_latest_counterparty_commitment_tx`, that stores the necessary data needed to reconstruct the initial commitment transaction in the monitor.
1 parent 966465a commit 75c0586

File tree

2 files changed

+97
-6
lines changed

2 files changed

+97
-6
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
3333
use bitcoin::secp256k1::{SecretKey, PublicKey};
3434
use bitcoin::secp256k1;
3535

36+
use crate::ln::channel::INITIAL_COMMITMENT_NUMBER;
3637
use crate::ln::{PaymentHash, PaymentPreimage};
3738
use crate::ln::msgs::DecodeError;
3839
use crate::ln::chan_utils;
@@ -888,6 +889,14 @@ pub(crate) struct ChannelMonitorImpl<Signer: WriteableEcdsaChannelSigner> {
888889

889890
/// The node_id of our counterparty
890891
counterparty_node_id: Option<PublicKey>,
892+
893+
/// Initial counterparty commmitment data needed to recreate the commitment tx
894+
/// in the persistence pipeline for third-party watchtowers. This will only be present on
895+
/// monitors created after 0.0.117.
896+
///
897+
/// Ordering of tuple data: (their_per_commitment_point, feerate_per_kw, to_broadcaster_sats,
898+
/// to_countersignatory_sats)
899+
initial_counterparty_commitment_info: Option<(PublicKey, u32, u64, u64)>,
891900
}
892901

893902
/// Transaction outputs to watch for on-chain spends.
@@ -1078,6 +1087,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signe
10781087
(11, self.confirmed_commitment_tx_counterparty_output, option),
10791088
(13, self.spendable_txids_confirmed, required_vec),
10801089
(15, self.counterparty_fulfilled_htlcs, required),
1090+
(17, self.initial_counterparty_commitment_info, option),
10811091
});
10821092

10831093
Ok(())
@@ -1228,6 +1238,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
12281238

12291239
best_block,
12301240
counterparty_node_id: Some(counterparty_node_id),
1241+
initial_counterparty_commitment_info: None,
12311242
})
12321243
}
12331244

@@ -1236,11 +1247,31 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
12361247
self.inner.lock().unwrap().provide_secret(idx, secret)
12371248
}
12381249

1250+
/// A variant of `Self::provide_latest_counterparty_commitment_tx` used to provide
1251+
/// additional information to the monitor to store in order to recreate the initial
1252+
/// counterparty commitment transaction during persistence (mainly for use in third-party
1253+
/// watchtowers).
1254+
///
1255+
/// This is used to provide the counterparty commitment information directly to the monitor
1256+
/// before the initial persistence of a new channel.
1257+
pub(crate) fn provide_initial_counterparty_commitment_tx<L: Deref>(
1258+
&self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
1259+
commitment_number: u64, their_cur_per_commitment_point: PublicKey, feerate_per_kw: u32,
1260+
to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, logger: &L,
1261+
)
1262+
where L::Target: Logger
1263+
{
1264+
self.inner.lock().unwrap().provide_initial_counterparty_commitment_tx(txid,
1265+
htlc_outputs, commitment_number, their_cur_per_commitment_point, feerate_per_kw,
1266+
to_broadcaster_value_sat, to_countersignatory_value_sat, logger);
1267+
}
1268+
12391269
/// Informs this monitor of the latest counterparty (ie non-broadcastable) commitment transaction.
12401270
/// The monitor watches for it to be broadcasted and then uses the HTLC information (and
12411271
/// possibly future revocation/preimage information) to claim outputs where possible.
12421272
/// We cache also the mapping hash:commitment number to lighten pruning of old preimages by watchtowers.
1243-
pub(crate) fn provide_latest_counterparty_commitment_tx<L: Deref>(
1273+
#[cfg(test)]
1274+
fn provide_latest_counterparty_commitment_tx<L: Deref>(
12441275
&self,
12451276
txid: Txid,
12461277
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
@@ -1376,6 +1407,22 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
13761407
ret
13771408
}
13781409

1410+
/// Gets the counterparty's initial commitment transaction. The returned commitment
1411+
/// transaction is unsigned. This is intended to be called during the initial persistence of
1412+
/// the monitor (inside an implementation of [`Persist::persist_new_channel`]), to allow for
1413+
/// watchtowers in the persistence pipeline to have enough data to form justice transactions.
1414+
///
1415+
/// This is similar to [`Self::counterparty_commitment_txs_from_update`], except
1416+
/// that for the initial commitment transaction, we don't have a corresponding update.
1417+
///
1418+
/// This will only return `Some` for channel monitors that have been created after upgrading
1419+
/// to LDK 0.0.117+.
1420+
///
1421+
/// [`Persist::persist_new_channel`]: crate::chain::chainmonitor::Persist::persist_new_channel
1422+
pub fn initial_counterparty_commitment_tx(&self) -> Option<CommitmentTransaction> {
1423+
self.inner.lock().unwrap().initial_counterparty_commitment_tx()
1424+
}
1425+
13791426
/// Gets all of the counterparty commitment transactions provided by the given update. This
13801427
/// may be empty if the update doesn't include any new counterparty commitments. Returned
13811428
/// commitment transactions are unsigned.
@@ -2255,6 +2302,25 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
22552302
Ok(())
22562303
}
22572304

2305+
pub(crate) fn provide_initial_counterparty_commitment_tx<L: Deref>(
2306+
&mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
2307+
commitment_number: u64, their_per_commitment_point: PublicKey, feerate_per_kw: u32,
2308+
to_broadcaster_value: u64, to_countersignatory_value: u64, logger: &L
2309+
)
2310+
where L::Target: Logger
2311+
{
2312+
self.initial_counterparty_commitment_info = Some((their_per_commitment_point.clone(),
2313+
feerate_per_kw, to_broadcaster_value, to_countersignatory_value));
2314+
2315+
#[cfg(debug_assertions)] {
2316+
let rebuilt_commitment_tx = self.initial_counterparty_commitment_tx().unwrap();
2317+
debug_assert_eq!(rebuilt_commitment_tx.trust().txid(), txid);
2318+
}
2319+
2320+
self.provide_latest_counterparty_commitment_tx(txid, htlc_outputs, commitment_number,
2321+
their_per_commitment_point, logger);
2322+
}
2323+
22582324
pub(crate) fn provide_latest_counterparty_commitment_tx<L: Deref>(&mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>, commitment_number: u64, their_per_commitment_point: PublicKey, logger: &L) where L::Target: Logger {
22592325
// TODO: Encrypt the htlc_outputs data with the single-hash of the commitment transaction
22602326
// so that a remote monitor doesn't learn anything unless there is a malicious close.
@@ -2684,6 +2750,17 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
26842750
ret
26852751
}
26862752

2753+
pub(crate) fn initial_counterparty_commitment_tx(&mut self) -> Option<CommitmentTransaction> {
2754+
let (their_per_commitment_point, feerate_per_kw, to_broadcaster_value,
2755+
to_countersignatory_value) = self.initial_counterparty_commitment_info?;
2756+
let htlc_outputs = vec![];
2757+
2758+
let commitment_tx = self.build_counterparty_commitment_tx(INITIAL_COMMITMENT_NUMBER,
2759+
&their_per_commitment_point, to_broadcaster_value, to_countersignatory_value,
2760+
feerate_per_kw, htlc_outputs);
2761+
Some(commitment_tx)
2762+
}
2763+
26872764
fn build_counterparty_commitment_tx(
26882765
&self, commitment_number: u64, their_per_commitment_point: &PublicKey,
26892766
to_broadcaster_value: u64, to_countersignatory_value: u64, feerate_per_kw: u32,
@@ -4195,6 +4272,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
41954272
let mut confirmed_commitment_tx_counterparty_output = None;
41964273
let mut spendable_txids_confirmed = Some(Vec::new());
41974274
let mut counterparty_fulfilled_htlcs = Some(HashMap::new());
4275+
let mut initial_counterparty_commitment_info = None;
41984276
read_tlv_fields!(reader, {
41994277
(1, funding_spend_confirmed, option),
42004278
(3, htlcs_resolved_on_chain, optional_vec),
@@ -4204,6 +4282,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
42044282
(11, confirmed_commitment_tx_counterparty_output, option),
42054283
(13, spendable_txids_confirmed, optional_vec),
42064284
(15, counterparty_fulfilled_htlcs, option),
4285+
(17, initial_counterparty_commitment_info, option),
42074286
});
42084287

42094288
Ok((best_block.block_hash(), ChannelMonitor::from_impl(ChannelMonitorImpl {
@@ -4259,6 +4338,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
42594338

42604339
best_block,
42614340
counterparty_node_id,
4341+
initial_counterparty_commitment_info,
42624342
})))
42634343
}
42644344
}

lightning/src/ln/channel.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2534,7 +2534,13 @@ impl<SP: Deref> Channel<SP> where
25342534
obscure_factor,
25352535
holder_commitment_tx, best_block, self.context.counterparty_node_id);
25362536

2537-
channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_bitcoin_tx.txid, Vec::new(), self.context.cur_counterparty_commitment_transaction_number, self.context.counterparty_cur_commitment_point.unwrap(), logger);
2537+
channel_monitor.provide_initial_counterparty_commitment_tx(
2538+
counterparty_initial_bitcoin_tx.txid, Vec::new(),
2539+
self.context.cur_counterparty_commitment_transaction_number,
2540+
self.context.counterparty_cur_commitment_point.unwrap(),
2541+
counterparty_initial_commitment_tx.feerate_per_kw(),
2542+
counterparty_initial_commitment_tx.to_broadcaster_value_sat(),
2543+
counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger);
25382544

25392545
assert_eq!(self.context.channel_state & (ChannelState::MonitorUpdateInProgress as u32), 0); // We have no had any monitor(s) yet to fail update!
25402546
self.context.channel_state = ChannelState::FundingSent as u32;
@@ -6464,7 +6470,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
64646470
self.generate_accept_channel_message()
64656471
}
64666472

6467-
fn funding_created_signature<L: Deref>(&mut self, sig: &Signature, logger: &L) -> Result<(Txid, CommitmentTransaction, Signature), ChannelError> where L::Target: Logger {
6473+
fn funding_created_signature<L: Deref>(&mut self, sig: &Signature, logger: &L) -> Result<(CommitmentTransaction, CommitmentTransaction, Signature), ChannelError> where L::Target: Logger {
64686474
let funding_script = self.context.get_funding_redeemscript();
64696475

64706476
let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
@@ -6496,7 +6502,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
64966502
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0;
64976503

64986504
// We sign "counterparty" commitment transaction, allowing them to broadcast the tx if they wish.
6499-
Ok((counterparty_initial_bitcoin_tx.txid, initial_commitment_tx, counterparty_signature))
6505+
Ok((counterparty_initial_commitment_tx, initial_commitment_tx, counterparty_signature))
65006506
}
65016507
}
65026508
}
@@ -6528,7 +6534,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
65286534
// funding_created_signature may fail.
65296535
self.context.holder_signer.as_mut().provide_channel_parameters(&self.context.channel_transaction_parameters);
65306536

6531-
let (counterparty_initial_commitment_txid, initial_commitment_tx, signature) = match self.funding_created_signature(&msg.signature, logger) {
6537+
let (counterparty_initial_commitment_tx, initial_commitment_tx, signature) = match self.funding_created_signature(&msg.signature, logger) {
65326538
Ok(res) => res,
65336539
Err(ChannelError::Close(e)) => {
65346540
self.context.channel_transaction_parameters.funding_outpoint = None;
@@ -6569,7 +6575,12 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
65696575
obscure_factor,
65706576
holder_commitment_tx, best_block, self.context.counterparty_node_id);
65716577

6572-
channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_commitment_txid, Vec::new(), self.context.cur_counterparty_commitment_transaction_number, self.context.counterparty_cur_commitment_point.unwrap(), logger);
6578+
channel_monitor.provide_initial_counterparty_commitment_tx(
6579+
counterparty_initial_commitment_tx.trust().txid(), Vec::new(),
6580+
self.context.cur_counterparty_commitment_transaction_number,
6581+
self.context.counterparty_cur_commitment_point.unwrap(), self.context.feerate_per_kw,
6582+
counterparty_initial_commitment_tx.to_broadcaster_value_sat(),
6583+
counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger);
65736584

65746585
self.context.channel_state = ChannelState::FundingSent as u32;
65756586
self.context.channel_id = funding_txo.to_channel_id();

0 commit comments

Comments
 (0)