Skip to content

Commit fa6b5f9

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 50f8505 commit fa6b5f9

File tree

2 files changed

+96
-6
lines changed

2 files changed

+96
-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::{self, htlc_success_tx_weight, htlc_timeout_tx_weight};
@@ -893,6 +894,14 @@ pub(crate) struct ChannelMonitorImpl<Signer: WriteableEcdsaChannelSigner> {
893894
/// the counterparty's commitment transactions for third-party watchtowers. This will only be
894895
/// present on monitors created after 0.0.117.
895896
counterparty_dust_limit_satoshis: Option<u64>,
897+
898+
/// Initial counterparty commmitment data needed to recreate the commitment tx
899+
/// in the persistence pipeline for third-party watchtowers. This will only be present on
900+
/// monitors created after 0.0.117.
901+
///
902+
/// Ordering of tuple data: (their_per_commitment_point, feerate_per_kw, to_broadcaster_sats,
903+
/// to_countersignatory_sats)
904+
initial_counterparty_commitment_info: Option<(PublicKey, u32, u64, u64)>,
896905
}
897906

898907
/// Transaction outputs to watch for on-chain spends.
@@ -1084,6 +1093,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signe
10841093
(13, self.spendable_txids_confirmed, required_vec),
10851094
(15, self.counterparty_fulfilled_htlcs, required),
10861095
(17, self.counterparty_dust_limit_satoshis, option),
1096+
(19, self.initial_counterparty_commitment_info, option),
10871097
});
10881098

10891099
Ok(())
@@ -1236,6 +1246,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
12361246
best_block,
12371247
counterparty_node_id: Some(counterparty_node_id),
12381248
counterparty_dust_limit_satoshis: Some(counterparty_dust_limit_satoshis),
1249+
initial_counterparty_commitment_info: None,
12391250
})
12401251
}
12411252

@@ -1244,11 +1255,31 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
12441255
self.inner.lock().unwrap().provide_secret(idx, secret)
12451256
}
12461257

1258+
/// A variant of `Self::provide_latest_counterparty_commitment_tx` used to provide
1259+
/// additional information to the monitor to store in order to recreate the initial
1260+
/// counterparty commitment transaction during persistence (mainly for use in third-party
1261+
/// watchtowers).
1262+
///
1263+
/// This is used to provide the counterparty commitment information directly to the monitor
1264+
/// before the initial persistence of a new channel.
1265+
pub(crate) fn provide_initial_counterparty_commitment_tx<L: Deref>(
1266+
&self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
1267+
commitment_number: u64, their_cur_per_commitment_point: PublicKey, feerate_per_kw: u32,
1268+
to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, logger: &L,
1269+
)
1270+
where L::Target: Logger
1271+
{
1272+
self.inner.lock().unwrap().provide_initial_counterparty_commitment_tx(txid,
1273+
htlc_outputs, commitment_number, their_cur_per_commitment_point, feerate_per_kw,
1274+
to_broadcaster_value_sat, to_countersignatory_value_sat, logger);
1275+
}
1276+
12471277
/// Informs this monitor of the latest counterparty (ie non-broadcastable) commitment transaction.
12481278
/// The monitor watches for it to be broadcasted and then uses the HTLC information (and
12491279
/// possibly future revocation/preimage information) to claim outputs where possible.
12501280
/// We cache also the mapping hash:commitment number to lighten pruning of old preimages by watchtowers.
1251-
pub(crate) fn provide_latest_counterparty_commitment_tx<L: Deref>(
1281+
#[cfg(test)]
1282+
fn provide_latest_counterparty_commitment_tx<L: Deref>(
12521283
&self,
12531284
txid: Txid,
12541285
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
@@ -1384,6 +1415,22 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
13841415
ret
13851416
}
13861417

1418+
/// Gets the counterparty's initial commitment transaction. The returned commitment
1419+
/// transaction is unsigned. This is intended to be called during the initial persistence of
1420+
/// the monitor (inside an implementation of [`Persist::persist_new_channel`]), to allow for
1421+
/// watchtowers in the persistence pipeline to have enough data to form justice transactions.
1422+
///
1423+
/// This is similar to [`Self::counterparty_commitment_txs_from_update`], except
1424+
/// that for the initial commitment transaction, we don't have a corresponding update.
1425+
///
1426+
/// This will only return `Some` for channel monitors that have been created after upgrading
1427+
/// to LDK 0.0.117+.
1428+
///
1429+
/// [`Persist::persist_new_channel`]: crate::chain::chainmonitor::Persist::persist_new_channel
1430+
pub fn initial_counterparty_commitment_tx(&self) -> Option<CommitmentTransaction> {
1431+
self.inner.lock().unwrap().initial_counterparty_commitment_tx()
1432+
}
1433+
13871434
/// Gets all of the counterparty commitment transactions provided by the given update. This
13881435
/// may be empty if the update doesn't include any new counterparty commitments. Returned
13891436
/// commitment transactions are unsigned.
@@ -2263,6 +2310,25 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
22632310
Ok(())
22642311
}
22652312

2313+
pub(crate) fn provide_initial_counterparty_commitment_tx<L: Deref>(
2314+
&mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
2315+
commitment_number: u64, their_per_commitment_point: PublicKey, feerate_per_kw: u32,
2316+
to_broadcaster_value: u64, to_countersignatory_value: u64, logger: &L
2317+
)
2318+
where L::Target: Logger
2319+
{
2320+
self.initial_counterparty_commitment_info = Some((their_per_commitment_point.clone(),
2321+
feerate_per_kw, to_broadcaster_value, to_countersignatory_value));
2322+
2323+
#[cfg(debug_assertions)] {
2324+
let rebuilt_commitment_tx = self.initial_counterparty_commitment_tx().unwrap();
2325+
debug_assert_eq!(rebuilt_commitment_tx.trust().txid(), txid);
2326+
}
2327+
2328+
self.provide_latest_counterparty_commitment_tx(txid, htlc_outputs, commitment_number,
2329+
their_per_commitment_point, logger);
2330+
}
2331+
22662332
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 {
22672333
// TODO: Encrypt the htlc_outputs data with the single-hash of the commitment transaction
22682334
// so that a remote monitor doesn't learn anything unless there is a malicious close.
@@ -2692,6 +2758,17 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
26922758
ret
26932759
}
26942760

2761+
pub(crate) fn initial_counterparty_commitment_tx(&mut self) -> Option<CommitmentTransaction> {
2762+
let (their_per_commitment_point, feerate_per_kw, to_broadcaster_value,
2763+
to_countersignatory_value) = self.initial_counterparty_commitment_info?;
2764+
let htlc_outputs = vec![];
2765+
2766+
let commitment_tx = self.build_counterparty_commitment_tx(INITIAL_COMMITMENT_NUMBER,
2767+
&their_per_commitment_point, to_broadcaster_value, to_countersignatory_value,
2768+
feerate_per_kw, htlc_outputs);
2769+
Some(commitment_tx)
2770+
}
2771+
26952772
fn build_counterparty_commitment_tx(
26962773
&self, commitment_number: u64, their_per_commitment_point: &PublicKey,
26972774
to_broadcaster_value: u64, to_countersignatory_value: u64, feerate_per_kw: u32,
@@ -4219,6 +4296,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
42194296
let mut spendable_txids_confirmed = Some(Vec::new());
42204297
let mut counterparty_fulfilled_htlcs = Some(HashMap::new());
42214298
let mut counterparty_dust_limit_satoshis = None;
4299+
let mut initial_counterparty_commitment_info = None;
42224300
read_tlv_fields!(reader, {
42234301
(1, funding_spend_confirmed, option),
42244302
(3, htlcs_resolved_on_chain, optional_vec),
@@ -4229,6 +4307,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
42294307
(13, spendable_txids_confirmed, optional_vec),
42304308
(15, counterparty_fulfilled_htlcs, option),
42314309
(17, counterparty_dust_limit_satoshis, option),
4310+
(19, initial_counterparty_commitment_info, option),
42324311
});
42334312

42344313
Ok((best_block.block_hash(), ChannelMonitor::from_impl(ChannelMonitorImpl {
@@ -4285,6 +4364,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
42854364
best_block,
42864365
counterparty_node_id,
42874366
counterparty_dust_limit_satoshis,
4367+
initial_counterparty_commitment_info,
42884368
})))
42894369
}
42904370
}

lightning/src/ln/channel.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2544,7 +2544,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
25442544
holder_commitment_tx, best_block, self.context.counterparty_node_id,
25452545
self.context.counterparty_dust_limit_satoshis);
25462546

2547-
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);
2547+
channel_monitor.provide_initial_counterparty_commitment_tx(
2548+
counterparty_initial_bitcoin_tx.txid, Vec::new(),
2549+
self.context.cur_counterparty_commitment_transaction_number,
2550+
self.context.counterparty_cur_commitment_point.unwrap(), self.context.feerate_per_kw,
2551+
counterparty_initial_commitment_tx.to_broadcaster_value_sat(),
2552+
counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger);
25482553

25492554
assert_eq!(self.context.channel_state & (ChannelState::MonitorUpdateInProgress as u32), 0); // We have no had any monitor(s) yet to fail update!
25502555
self.context.channel_state = ChannelState::FundingSent as u32;
@@ -6432,7 +6437,7 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
64326437
self.generate_accept_channel_message()
64336438
}
64346439

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

64386443
let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
@@ -6461,7 +6466,7 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
64616466
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0;
64626467

64636468
// We sign "counterparty" commitment transaction, allowing them to broadcast the tx if they wish.
6464-
Ok((counterparty_initial_bitcoin_tx.txid, initial_commitment_tx, counterparty_signature))
6469+
Ok((counterparty_initial_commitment_tx, initial_commitment_tx, counterparty_signature))
64656470
}
64666471

64676472
pub fn funding_created<SP: Deref, L: Deref>(
@@ -6495,7 +6500,7 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
64956500
// funding_created_signature may fail.
64966501
self.context.holder_signer.provide_channel_parameters(&self.context.channel_transaction_parameters);
64976502

6498-
let (counterparty_initial_commitment_txid, initial_commitment_tx, signature) = match self.funding_created_signature(&msg.signature, logger) {
6503+
let (counterparty_initial_commitment_tx, initial_commitment_tx, signature) = match self.funding_created_signature(&msg.signature, logger) {
64996504
Ok(res) => res,
65006505
Err(ChannelError::Close(e)) => {
65016506
self.context.channel_transaction_parameters.funding_outpoint = None;
@@ -6537,7 +6542,12 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
65376542
holder_commitment_tx, best_block, self.context.counterparty_node_id,
65386543
self.context.counterparty_dust_limit_satoshis);
65396544

6540-
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);
6545+
channel_monitor.provide_initial_counterparty_commitment_tx(
6546+
counterparty_initial_commitment_tx.trust().txid(), Vec::new(),
6547+
self.context.cur_counterparty_commitment_transaction_number,
6548+
self.context.counterparty_cur_commitment_point.unwrap(), self.context.feerate_per_kw,
6549+
counterparty_initial_commitment_tx.to_broadcaster_value_sat(),
6550+
counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger);
65416551

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

0 commit comments

Comments
 (0)