Skip to content

Commit 90147d6

Browse files
committed
Provide built commitment transactions to ChannelMonitor
Prior to this commit, `LatestCounterpartyCommitmentTXInfo` provided `ChannelMonitor` with the data it needed to build counterparty commitment transactions, instead of the fully built transaction. This was an unnecessary optimization, as the data still included all the htlcs. This meant that the size of `LatestCounterpartyCommitmentTXInfo` scaled with the number of htlcs, just like a fully built transaction. This commit adds a new variant to `ChannelMonitorUpdateStep` called `LatestCounterpartyCommitmentTX`, which will provide the commitment transaction, together with the dust and non-dust htlcs for that commitment. We add code to handle this new variant, but refrain from immediately setting it, as this would otherwise double the size of our updates.
1 parent c4d0560 commit 90147d6

File tree

2 files changed

+70
-34
lines changed

2 files changed

+70
-34
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,12 @@ pub(crate) enum ChannelMonitorUpdateStep {
554554
to_broadcaster_value_sat: Option<u64>,
555555
to_countersignatory_value_sat: Option<u64>,
556556
},
557+
LatestCounterpartyCommitmentTX {
558+
// The dust and non-dust htlcs for that commitment
559+
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
560+
// Contains only the non-dust htlcs
561+
commitment_tx: CommitmentTransaction,
562+
},
557563
PaymentPreimage {
558564
payment_preimage: PaymentPreimage,
559565
/// If this preimage was from an inbound payment claim, information about the claim should
@@ -581,6 +587,7 @@ impl ChannelMonitorUpdateStep {
581587
match self {
582588
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. } => "LatestHolderCommitmentTXInfo",
583589
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } => "LatestCounterpartyCommitmentTXInfo",
590+
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { .. } => "LatestCounterpartyCommitmentTX",
584591
ChannelMonitorUpdateStep::PaymentPreimage { .. } => "PaymentPreimage",
585592
ChannelMonitorUpdateStep::CommitmentSecret { .. } => "CommitmentSecret",
586593
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => "ChannelForceClosed",
@@ -619,6 +626,10 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
619626
(5, ShutdownScript) => {
620627
(0, scriptpubkey, required),
621628
},
629+
(6, LatestCounterpartyCommitmentTX) => {
630+
(0, htlc_outputs, required_vec),
631+
(2, commitment_tx, required),
632+
},
622633
);
623634

624635
/// Indicates whether the balance is derived from a cooperative close, a force-close
@@ -1029,6 +1040,11 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
10291040
/// Ordering of tuple data: (their_per_commitment_point, feerate_per_kw, to_broadcaster_sats,
10301041
/// to_countersignatory_sats)
10311042
initial_counterparty_commitment_info: Option<(PublicKey, u32, u64, u64)>,
1043+
/// Initial counterparty commitment transaction
1044+
///
1045+
/// We previously used the field above to re-build the counterparty commitment transaction,
1046+
/// we now provide the transaction outright.
1047+
initial_counterparty_commitment_tx: Option<CommitmentTransaction>,
10321048

10331049
/// The first block height at which we had no remaining claimable balances.
10341050
balances_empty_height: Option<u32>,
@@ -1252,6 +1268,7 @@ impl<Signer: EcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
12521268
(23, self.holder_pays_commitment_tx_fee, option),
12531269
(25, self.payment_preimages, required),
12541270
(27, self.first_confirmed_funding_txo, required),
1271+
(29, self.initial_counterparty_commitment_tx, option),
12551272
});
12561273

12571274
Ok(())
@@ -1464,6 +1481,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
14641481
best_block,
14651482
counterparty_node_id: Some(counterparty_node_id),
14661483
initial_counterparty_commitment_info: None,
1484+
initial_counterparty_commitment_tx: None,
14671485
balances_empty_height: None,
14681486

14691487
failed_back_htlc_ids: new_hash_set(),
@@ -1503,17 +1521,12 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
15031521
/// This is used to provide the counterparty commitment information directly to the monitor
15041522
/// before the initial persistence of a new channel.
15051523
pub(crate) fn provide_initial_counterparty_commitment_tx<L: Deref>(
1506-
&self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
1507-
commitment_number: u64, their_cur_per_commitment_point: PublicKey, feerate_per_kw: u32,
1508-
to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, logger: &L,
1509-
)
1510-
where L::Target: Logger
1524+
&self, commitment_tx: CommitmentTransaction, logger: &L,
1525+
) where L::Target: Logger
15111526
{
15121527
let mut inner = self.inner.lock().unwrap();
15131528
let logger = WithChannelMonitor::from_impl(logger, &*inner, None);
1514-
inner.provide_initial_counterparty_commitment_tx(txid,
1515-
htlc_outputs, commitment_number, their_cur_per_commitment_point, feerate_per_kw,
1516-
to_broadcaster_value_sat, to_countersignatory_value_sat, &logger);
1529+
inner.provide_initial_counterparty_commitment_tx(commitment_tx, &logger);
15171530
}
15181531

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

28872900
fn provide_initial_counterparty_commitment_tx<L: Deref>(
2888-
&mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
2889-
commitment_number: u64, their_per_commitment_point: PublicKey, feerate_per_kw: u32,
2890-
to_broadcaster_value: u64, to_countersignatory_value: u64, logger: &WithChannelMonitor<L>,
2901+
&mut self, commitment_tx: CommitmentTransaction, logger: &WithChannelMonitor<L>,
28912902
) where L::Target: Logger {
2892-
self.initial_counterparty_commitment_info = Some((their_per_commitment_point.clone(),
2893-
feerate_per_kw, to_broadcaster_value, to_countersignatory_value));
2903+
// We populate this field for downgrades
2904+
self.initial_counterparty_commitment_info = Some((commitment_tx.per_commitment_point(),
2905+
commitment_tx.feerate_per_kw(), commitment_tx.to_broadcaster_value_sat(), commitment_tx.to_countersignatory_value_sat()));
28942906

28952907
#[cfg(debug_assertions)] {
28962908
let rebuilt_commitment_tx = self.initial_counterparty_commitment_tx().unwrap();
2897-
debug_assert_eq!(rebuilt_commitment_tx.trust().txid(), txid);
2909+
debug_assert_eq!(rebuilt_commitment_tx.trust().txid(), commitment_tx.trust().txid());
28982910
}
28992911

2900-
self.provide_latest_counterparty_commitment_tx(txid, htlc_outputs, commitment_number,
2901-
their_per_commitment_point, logger);
2912+
self.provide_latest_counterparty_commitment_tx(commitment_tx.trust().txid(), Vec::new(), commitment_tx.commitment_number(),
2913+
commitment_tx.per_commitment_point(), logger);
2914+
// Soon, we will only populate this field
2915+
self.initial_counterparty_commitment_tx = Some(commitment_tx);
29022916
}
29032917

29042918
fn provide_latest_counterparty_commitment_tx<L: Deref>(
@@ -3244,10 +3258,17 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32443258
if self.lockdown_from_offchain { panic!(); }
32453259
self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone(), &claimed_htlcs, nondust_htlc_sources.clone());
32463260
}
3261+
// Soon we will drop the `LatestCounterpartyCommitmentTXInfo` variant in favor of `LatestCounterpartyCommitmentTX`.
3262+
// For now we just add the code to handle the new updates.
3263+
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant.
32473264
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid, htlc_outputs, commitment_number, their_per_commitment_point, .. } => {
32483265
log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment transaction info");
32493266
self.provide_latest_counterparty_commitment_tx(*commitment_txid, htlc_outputs.clone(), *commitment_number, *their_per_commitment_point, logger)
32503267
},
3268+
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { htlc_outputs, commitment_tx } => {
3269+
log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment transaction info");
3270+
self.provide_latest_counterparty_commitment_tx(commitment_tx.trust().txid(), htlc_outputs.clone(), commitment_tx.commitment_number(), commitment_tx.per_commitment_point(), logger)
3271+
},
32513272
ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage, payment_info } => {
32523273
log_trace!(logger, "Updating ChannelMonitor with payment preimage");
32533274
self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()), &payment_preimage, payment_info, broadcaster, &bounded_fee_estimator, logger)
@@ -3310,6 +3331,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
33103331
match update {
33113332
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. }
33123333
|ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. }
3334+
|ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { .. }
33133335
|ChannelMonitorUpdateStep::ShutdownScript { .. }
33143336
|ChannelMonitorUpdateStep::CommitmentSecret { .. } =>
33153337
is_pre_close_update = true,
@@ -3446,14 +3468,21 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34463468
}
34473469

34483470
fn initial_counterparty_commitment_tx(&mut self) -> Option<CommitmentTransaction> {
3449-
let (their_per_commitment_point, feerate_per_kw, to_broadcaster_value,
3450-
to_countersignatory_value) = self.initial_counterparty_commitment_info?;
3451-
let htlc_outputs = vec![];
3452-
3453-
let commitment_tx = self.build_counterparty_commitment_tx(INITIAL_COMMITMENT_NUMBER,
3454-
&their_per_commitment_point, to_broadcaster_value, to_countersignatory_value,
3455-
feerate_per_kw, htlc_outputs);
3456-
Some(commitment_tx)
3471+
self.initial_counterparty_commitment_tx.clone().or_else(|| {
3472+
// This provides forward compatibility; an old monitor will not contain the full
3473+
// transaction; only enough information to rebuild it
3474+
self.initial_counterparty_commitment_info
3475+
.map(|(their_per_commitment_point, feerate_per_kw, to_broadcaster_value, to_countersignatory_value)| {
3476+
let htlc_outputs = vec![];
3477+
3478+
let commitment_tx = self.build_counterparty_commitment_tx(INITIAL_COMMITMENT_NUMBER,
3479+
&their_per_commitment_point, to_broadcaster_value, to_countersignatory_value,
3480+
feerate_per_kw, htlc_outputs);
3481+
// Take the opportunity to populate this recently introduced field
3482+
self.initial_counterparty_commitment_tx = Some(commitment_tx.clone());
3483+
commitment_tx
3484+
})
3485+
})
34573486
}
34583487

34593488
fn build_counterparty_commitment_tx(
@@ -3481,12 +3510,16 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34813510

34823511
fn counterparty_commitment_txs_from_update(&self, update: &ChannelMonitorUpdate) -> Vec<CommitmentTransaction> {
34833512
update.updates.iter().filter_map(|update| {
3513+
// Soon we will drop the first branch here in favor of the second.
3514+
// In preparation, we just add the second branch without deleting the first.
3515+
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant.
34843516
match update {
34853517
&ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid,
34863518
ref htlc_outputs, commitment_number, their_per_commitment_point,
34873519
feerate_per_kw: Some(feerate_per_kw),
34883520
to_broadcaster_value_sat: Some(to_broadcaster_value),
3489-
to_countersignatory_value_sat: Some(to_countersignatory_value) } => {
3521+
to_countersignatory_value_sat: Some(to_countersignatory_value)
3522+
} => {
34903523

34913524
let nondust_htlcs = htlc_outputs.iter().filter_map(|(htlc, _)| {
34923525
htlc.transaction_output_index.map(|_| (htlc.clone(), None))
@@ -3500,6 +3533,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35003533

35013534
Some(commitment_tx)
35023535
},
3536+
&ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { htlc_outputs: _,
3537+
ref commitment_tx,
3538+
} => {
3539+
Some(commitment_tx.clone())
3540+
},
35033541
_ => None,
35043542
}
35053543
}).collect()
@@ -5070,6 +5108,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
50705108
let mut spendable_txids_confirmed = Some(Vec::new());
50715109
let mut counterparty_fulfilled_htlcs = Some(new_hash_map());
50725110
let mut initial_counterparty_commitment_info = None;
5111+
let mut initial_counterparty_commitment_tx = None;
50735112
let mut balances_empty_height = None;
50745113
let mut channel_id = None;
50755114
let mut holder_pays_commitment_tx_fee = None;
@@ -5090,6 +5129,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
50905129
(23, holder_pays_commitment_tx_fee, option),
50915130
(25, payment_preimages_with_info, option),
50925131
(27, first_confirmed_funding_txo, (default_value, funding_info.0)),
5132+
(29, initial_counterparty_commitment_tx, option),
50935133
});
50945134
if let Some(payment_preimages_with_info) = payment_preimages_with_info {
50955135
if payment_preimages_with_info.len() != payment_preimages.len() {
@@ -5186,6 +5226,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
51865226
best_block,
51875227
counterparty_node_id,
51885228
initial_counterparty_commitment_info,
5229+
initial_counterparty_commitment_tx,
51895230
balances_empty_height,
51905231
failed_back_htlc_ids: new_hash_set(),
51915232
})))

lightning/src/ln/channel.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,7 +2053,7 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
20532053

20542054
fn initial_commitment_signed<L: Deref>(
20552055
&mut self, channel_id: ChannelId, counterparty_signature: Signature, holder_commitment_point: &mut HolderCommitmentPoint,
2056-
counterparty_commitment_number: u64, best_block: BestBlock, signer_provider: &SP, logger: &L,
2056+
_counterparty_commitment_number: u64, best_block: BestBlock, signer_provider: &SP, logger: &L,
20572057
) -> Result<(ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>, CommitmentTransaction), ChannelError>
20582058
where
20592059
L::Target: Logger
@@ -2131,14 +2131,7 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
21312131
funding_redeemscript.clone(), funding.get_value_satoshis(),
21322132
obscure_factor,
21332133
holder_commitment_tx, best_block, context.counterparty_node_id, context.channel_id());
2134-
channel_monitor.provide_initial_counterparty_commitment_tx(
2135-
counterparty_initial_bitcoin_tx.txid, Vec::new(),
2136-
counterparty_commitment_number,
2137-
context.counterparty_cur_commitment_point.unwrap(),
2138-
counterparty_initial_commitment_tx.feerate_per_kw(),
2139-
counterparty_initial_commitment_tx.to_broadcaster_value_sat(),
2140-
counterparty_initial_commitment_tx.to_countersignatory_value_sat(),
2141-
logger);
2134+
channel_monitor.provide_initial_counterparty_commitment_tx(counterparty_initial_commitment_tx.clone(), logger);
21422135

21432136
self.context_mut().cur_counterparty_commitment_transaction_number -= 1;
21442137

@@ -8544,6 +8537,8 @@ impl<SP: Deref> FundedChannel<SP> where
85448537
let monitor_update = ChannelMonitorUpdate {
85458538
update_id: self.context.latest_monitor_update_id,
85468539
counterparty_node_id: Some(self.context.counterparty_node_id),
8540+
// Soon, we will switch this to `LatestCounterpartyCommitmentTX`,
8541+
// and provide the full commit tx instead of the information needed to rebuild it.
85478542
updates: vec![ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo {
85488543
commitment_txid: counterparty_commitment_txid,
85498544
htlc_outputs: htlcs.clone(),

0 commit comments

Comments
 (0)