Skip to content

Commit 6e70599

Browse files
committed
Provide built counterparty commitment transactions to ChannelMonitor
`LatestCounterpartyCommitmentTXInfo` provides `ChannelMonitor` with the data it needs to build counterparty commitment transactions. `ChannelMonitor` then rebuilds commitment transactions from these pieces of data when requested. This commit adds a new variant to `ChannelMonitorUpdateStep` called `LatestCounterpartyCommitmentTX`, which will provide fully built commitment transactions to `ChannelMonitor`. When the `ChannelMonitor` is asked for the counterparty commitment transactions, it will not rebuild them, but just clone them. As a result, this new variant eliminates any calls to the upcoming `TxBuilder` trait in `ChannelMonitor`, which gets rid of a generic parameter on `ChannelMonitor`. This commit also avoids any footguns that might come with passing around disparate pieces of data to re-build commitment transactions from scratch. We also add a `htlc_outputs` field to the variant to include the dust HTLCs, as well as all the HTLC sources. This means that this new variant will store non-dust HTLCs both in the `htlc_outputs` field, and in the `commitment_tx` field. This is ok for now as the number of HTLCs per-commitment nowadays is very low. We add code to handle this new variant, but refrain from immediately setting it. This will allow us to atomically switch from `LatestCounterpartyCommitmentTXInfo` to `LatestCounterpartyCommitmentTX` in the future while still allowing downgrades.
1 parent 4c43a5b commit 6e70599

File tree

2 files changed

+71
-39
lines changed

2 files changed

+71
-39
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,12 @@ pub(crate) enum ChannelMonitorUpdateStep {
544544
to_broadcaster_value_sat: Option<u64>,
545545
to_countersignatory_value_sat: Option<u64>,
546546
},
547+
LatestCounterpartyCommitmentTX {
548+
// The dust and non-dust htlcs for that commitment
549+
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
550+
// Contains only the non-dust htlcs
551+
commitment_tx: CommitmentTransaction,
552+
},
547553
PaymentPreimage {
548554
payment_preimage: PaymentPreimage,
549555
/// If this preimage was from an inbound payment claim, information about the claim should
@@ -571,6 +577,7 @@ impl ChannelMonitorUpdateStep {
571577
match self {
572578
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. } => "LatestHolderCommitmentTXInfo",
573579
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } => "LatestCounterpartyCommitmentTXInfo",
580+
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { .. } => "LatestCounterpartyCommitmentTX",
574581
ChannelMonitorUpdateStep::PaymentPreimage { .. } => "PaymentPreimage",
575582
ChannelMonitorUpdateStep::CommitmentSecret { .. } => "CommitmentSecret",
576583
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => "ChannelForceClosed",
@@ -609,6 +616,10 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
609616
(5, ShutdownScript) => {
610617
(0, scriptpubkey, required),
611618
},
619+
(6, LatestCounterpartyCommitmentTX) => {
620+
(0, htlc_outputs, required_vec),
621+
(2, commitment_tx, required),
622+
},
612623
);
613624

614625
/// Indicates whether the balance is derived from a cooperative close, a force-close
@@ -1019,6 +1030,11 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
10191030
/// Ordering of tuple data: (their_per_commitment_point, feerate_per_kw, to_broadcaster_sats,
10201031
/// to_countersignatory_sats)
10211032
initial_counterparty_commitment_info: Option<(PublicKey, u32, u64, u64)>,
1033+
/// Initial counterparty commitment transaction
1034+
///
1035+
/// We previously used the field above to re-build the counterparty commitment transaction,
1036+
/// we now provide the transaction outright.
1037+
initial_counterparty_commitment_tx: Option<CommitmentTransaction>,
10221038

10231039
/// The first block height at which we had no remaining claimable balances.
10241040
balances_empty_height: Option<u32>,
@@ -1242,6 +1258,7 @@ impl<Signer: EcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
12421258
(23, self.holder_pays_commitment_tx_fee, option),
12431259
(25, self.payment_preimages, required),
12441260
(27, self.first_confirmed_funding_txo, required),
1261+
(29, self.initial_counterparty_commitment_tx, option),
12451262
});
12461263

12471264
Ok(())
@@ -1454,6 +1471,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
14541471
best_block,
14551472
counterparty_node_id: counterparty_node_id,
14561473
initial_counterparty_commitment_info: None,
1474+
initial_counterparty_commitment_tx: None,
14571475
balances_empty_height: None,
14581476

14591477
failed_back_htlc_ids: new_hash_set(),
@@ -1493,17 +1511,12 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
14931511
/// This is used to provide the counterparty commitment information directly to the monitor
14941512
/// before the initial persistence of a new channel.
14951513
pub(crate) fn provide_initial_counterparty_commitment_tx<L: Deref>(
1496-
&self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
1497-
commitment_number: u64, their_cur_per_commitment_point: PublicKey, feerate_per_kw: u32,
1498-
to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, logger: &L,
1499-
)
1500-
where L::Target: Logger
1514+
&self, commitment_tx: CommitmentTransaction, logger: &L,
1515+
) where L::Target: Logger
15011516
{
15021517
let mut inner = self.inner.lock().unwrap();
15031518
let logger = WithChannelMonitor::from_impl(logger, &*inner, None);
1504-
inner.provide_initial_counterparty_commitment_tx(txid,
1505-
htlc_outputs, commitment_number, their_cur_per_commitment_point, feerate_per_kw,
1506-
to_broadcaster_value_sat, to_countersignatory_value_sat, &logger);
1519+
inner.provide_initial_counterparty_commitment_tx(commitment_tx, &logger);
15071520
}
15081521

15091522
/// Informs this monitor of the latest counterparty (ie non-broadcastable) commitment transaction.
@@ -2872,20 +2885,21 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
28722885
}
28732886

28742887
fn provide_initial_counterparty_commitment_tx<L: Deref>(
2875-
&mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
2876-
commitment_number: u64, their_per_commitment_point: PublicKey, feerate_per_kw: u32,
2877-
to_broadcaster_value: u64, to_countersignatory_value: u64, logger: &WithChannelMonitor<L>,
2888+
&mut self, commitment_tx: CommitmentTransaction, logger: &WithChannelMonitor<L>,
28782889
) where L::Target: Logger {
2879-
self.initial_counterparty_commitment_info = Some((their_per_commitment_point.clone(),
2880-
feerate_per_kw, to_broadcaster_value, to_countersignatory_value));
2890+
// We populate this field for downgrades
2891+
self.initial_counterparty_commitment_info = Some((commitment_tx.per_commitment_point(),
2892+
commitment_tx.feerate_per_kw(), commitment_tx.to_broadcaster_value_sat(), commitment_tx.to_countersignatory_value_sat()));
28812893

28822894
#[cfg(debug_assertions)] {
28832895
let rebuilt_commitment_tx = self.initial_counterparty_commitment_tx().unwrap();
2884-
debug_assert_eq!(rebuilt_commitment_tx.trust().txid(), txid);
2896+
debug_assert_eq!(rebuilt_commitment_tx.trust().txid(), commitment_tx.trust().txid());
28852897
}
28862898

2887-
self.provide_latest_counterparty_commitment_tx(txid, htlc_outputs, commitment_number,
2888-
their_per_commitment_point, logger);
2899+
self.provide_latest_counterparty_commitment_tx(commitment_tx.trust().txid(), Vec::new(), commitment_tx.commitment_number(),
2900+
commitment_tx.per_commitment_point(), logger);
2901+
// Soon, we will only populate this field
2902+
self.initial_counterparty_commitment_tx = Some(commitment_tx);
28892903
}
28902904

28912905
fn provide_latest_counterparty_commitment_tx<L: Deref>(
@@ -3223,10 +3237,17 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32233237
if self.lockdown_from_offchain { panic!(); }
32243238
self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone(), &claimed_htlcs, nondust_htlc_sources.clone());
32253239
}
3240+
// Soon we will drop the `LatestCounterpartyCommitmentTXInfo` variant in favor of `LatestCounterpartyCommitmentTX`.
3241+
// For now we just add the code to handle the new updates.
3242+
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant.
32263243
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid, htlc_outputs, commitment_number, their_per_commitment_point, .. } => {
32273244
log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment transaction info");
32283245
self.provide_latest_counterparty_commitment_tx(*commitment_txid, htlc_outputs.clone(), *commitment_number, *their_per_commitment_point, logger)
32293246
},
3247+
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { htlc_outputs, commitment_tx } => {
3248+
log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment transaction info");
3249+
self.provide_latest_counterparty_commitment_tx(commitment_tx.trust().txid(), htlc_outputs.clone(), commitment_tx.commitment_number(), commitment_tx.per_commitment_point(), logger)
3250+
},
32303251
ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage, payment_info } => {
32313252
log_trace!(logger, "Updating ChannelMonitor with payment preimage");
32323253
self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()), &payment_preimage, payment_info, broadcaster, &bounded_fee_estimator, logger)
@@ -3289,6 +3310,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32893310
match update {
32903311
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. }
32913312
|ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. }
3313+
|ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { .. }
32923314
|ChannelMonitorUpdateStep::ShutdownScript { .. }
32933315
|ChannelMonitorUpdateStep::CommitmentSecret { .. } =>
32943316
is_pre_close_update = true,
@@ -3419,14 +3441,21 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34193441
}
34203442

34213443
fn initial_counterparty_commitment_tx(&mut self) -> Option<CommitmentTransaction> {
3422-
let (their_per_commitment_point, feerate_per_kw, to_broadcaster_value,
3423-
to_countersignatory_value) = self.initial_counterparty_commitment_info?;
3424-
let htlc_outputs = vec![];
3425-
3426-
let commitment_tx = self.build_counterparty_commitment_tx(INITIAL_COMMITMENT_NUMBER,
3427-
&their_per_commitment_point, to_broadcaster_value, to_countersignatory_value,
3428-
feerate_per_kw, htlc_outputs);
3429-
Some(commitment_tx)
3444+
self.initial_counterparty_commitment_tx.clone().or_else(|| {
3445+
// This provides forward compatibility; an old monitor will not contain the full
3446+
// transaction; only enough information to rebuild it
3447+
self.initial_counterparty_commitment_info
3448+
.map(|(their_per_commitment_point, feerate_per_kw, to_broadcaster_value, to_countersignatory_value)| {
3449+
let htlc_outputs = vec![];
3450+
3451+
let commitment_tx = self.build_counterparty_commitment_tx(INITIAL_COMMITMENT_NUMBER,
3452+
&their_per_commitment_point, to_broadcaster_value, to_countersignatory_value,
3453+
feerate_per_kw, htlc_outputs);
3454+
// Take the opportunity to populate this recently introduced field
3455+
self.initial_counterparty_commitment_tx = Some(commitment_tx.clone());
3456+
commitment_tx
3457+
})
3458+
})
34303459
}
34313460

34323461
fn build_counterparty_commitment_tx(
@@ -3454,6 +3483,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34543483

34553484
fn counterparty_commitment_txs_from_update(&self, update: &ChannelMonitorUpdate) -> Vec<CommitmentTransaction> {
34563485
update.updates.iter().filter_map(|update| {
3486+
// Soon we will drop the first branch here in favor of the second.
3487+
// In preparation, we just add the second branch without deleting the first.
3488+
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant.
34573489
match update {
34583490
&ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid,
34593491
ref htlc_outputs, commitment_number, their_per_commitment_point,
@@ -3473,6 +3505,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34733505

34743506
Some(commitment_tx)
34753507
},
3508+
&ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { htlc_outputs: _,
3509+
ref commitment_tx,
3510+
} => {
3511+
Some(commitment_tx.clone())
3512+
},
34763513
_ => None,
34773514
}
34783515
}).collect()
@@ -5043,6 +5080,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
50435080
let mut spendable_txids_confirmed = Some(Vec::new());
50445081
let mut counterparty_fulfilled_htlcs = Some(new_hash_map());
50455082
let mut initial_counterparty_commitment_info = None;
5083+
let mut initial_counterparty_commitment_tx = None;
50465084
let mut balances_empty_height = None;
50475085
let mut channel_id = None;
50485086
let mut holder_pays_commitment_tx_fee = None;
@@ -5063,6 +5101,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
50635101
(23, holder_pays_commitment_tx_fee, option),
50645102
(25, payment_preimages_with_info, option),
50655103
(27, first_confirmed_funding_txo, (default_value, funding_info.0)),
5104+
(29, initial_counterparty_commitment_tx, option),
50665105
});
50675106
if let Some(payment_preimages_with_info) = payment_preimages_with_info {
50685107
if payment_preimages_with_info.len() != payment_preimages.len() {
@@ -5166,6 +5205,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
51665205
best_block,
51675206
counterparty_node_id: counterparty_node_id.unwrap(),
51685207
initial_counterparty_commitment_info,
5208+
initial_counterparty_commitment_tx,
51695209
balances_empty_height,
51705210
failed_back_htlc_ids: new_hash_set(),
51715211
})))

lightning/src/ln/channel.rs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,7 +2062,7 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
20622062

20632063
fn initial_commitment_signed<L: Deref>(
20642064
&mut self, channel_id: ChannelId, counterparty_signature: Signature, holder_commitment_point: &mut HolderCommitmentPoint,
2065-
counterparty_commitment_number: u64, best_block: BestBlock, signer_provider: &SP, logger: &L,
2065+
best_block: BestBlock, signer_provider: &SP, logger: &L,
20662066
) -> Result<(ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>, CommitmentTransaction), ChannelError>
20672067
where
20682068
L::Target: Logger
@@ -2140,14 +2140,7 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
21402140
funding_redeemscript.clone(), funding.get_value_satoshis(),
21412141
obscure_factor,
21422142
holder_commitment_tx, best_block, context.counterparty_node_id, context.channel_id());
2143-
channel_monitor.provide_initial_counterparty_commitment_tx(
2144-
counterparty_initial_bitcoin_tx.txid, Vec::new(),
2145-
counterparty_commitment_number,
2146-
context.counterparty_cur_commitment_point.unwrap(),
2147-
counterparty_initial_commitment_tx.feerate_per_kw(),
2148-
counterparty_initial_commitment_tx.to_broadcaster_value_sat(),
2149-
counterparty_initial_commitment_tx.to_countersignatory_value_sat(),
2150-
logger);
2143+
channel_monitor.provide_initial_counterparty_commitment_tx(counterparty_initial_commitment_tx.clone(), logger);
21512144

21522145
self.context_mut().cur_counterparty_commitment_transaction_number -= 1;
21532146

@@ -5681,8 +5674,7 @@ impl<SP: Deref> FundedChannel<SP> where
56815674
self.context.assert_no_commitment_advancement(holder_commitment_point.transaction_number(), "initial commitment_signed");
56825675

56835676
let (channel_monitor, _) = self.initial_commitment_signed(
5684-
self.context.channel_id(), msg.signature, holder_commitment_point,
5685-
self.context.cur_counterparty_commitment_transaction_number, best_block, signer_provider, logger)?;
5677+
self.context.channel_id(), msg.signature, holder_commitment_point, best_block, signer_provider, logger)?;
56865678
self.holder_commitment_point = *holder_commitment_point;
56875679

56885680
log_info!(logger, "Received initial commitment_signed from peer for channel {}", &self.context.channel_id());
@@ -8743,6 +8735,8 @@ impl<SP: Deref> FundedChannel<SP> where
87438735
self.context.latest_monitor_update_id += 1;
87448736
let monitor_update = ChannelMonitorUpdate {
87458737
update_id: self.context.latest_monitor_update_id,
8738+
// Soon, we will switch this to `LatestCounterpartyCommitmentTX`,
8739+
// and provide the full commit tx instead of the information needed to rebuild it.
87468740
updates: vec![ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo {
87478741
commitment_txid: counterparty_commitment_txid,
87488742
htlc_outputs: htlcs.clone(),
@@ -9465,8 +9459,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
94659459

94669460
let (channel_monitor, _) = match self.initial_commitment_signed(
94679461
self.context.channel_id(), msg.signature,
9468-
&mut holder_commitment_point, self.context.cur_counterparty_commitment_transaction_number,
9469-
best_block, signer_provider, logger
9462+
&mut holder_commitment_point, best_block, signer_provider, logger
94709463
) {
94719464
Ok(channel_monitor) => channel_monitor,
94729465
Err(err) => return Err((self, err)),
@@ -9735,8 +9728,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
97359728

97369729
let (channel_monitor, counterparty_initial_commitment_tx) = match self.initial_commitment_signed(
97379730
ChannelId::v1_from_funding_outpoint(funding_txo), msg.signature,
9738-
&mut holder_commitment_point, self.context.cur_counterparty_commitment_transaction_number,
9739-
best_block, signer_provider, logger
9731+
&mut holder_commitment_point, best_block, signer_provider, logger
97409732
) {
97419733
Ok(channel_monitor) => channel_monitor,
97429734
Err(err) => return Err((self, err)),

0 commit comments

Comments
 (0)