Skip to content

Commit 29a8b9f

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 `ChannelMonitor` is asked for 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 avoids adding a generic parameter on `ChannelMonitor`. This commit also stomps any bugs that might come from 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 29a8b9f

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)