Skip to content

Commit b8a03cd

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 b8a03cd

File tree

2 files changed

+86
-43
lines changed

2 files changed

+86
-43
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 79 additions & 28 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(),
@@ -1486,24 +1504,19 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
14861504
}
14871505

14881506
/// A variant of `Self::provide_latest_counterparty_commitment_tx` used to provide
1489-
/// additional information to the monitor to store in order to recreate the initial
1490-
/// counterparty commitment transaction during persistence (mainly for use in third-party
1491-
/// watchtowers).
1507+
/// the counterparty commitment transaction to the monitor so that the transaction
1508+
/// can be retrieved during the initial persistence of the monitor (mainly for use in
1509+
/// third-party watchtowers).
14921510
///
1493-
/// This is used to provide the counterparty commitment information directly to the monitor
1511+
/// This is used to provide the counterparty commitment transaction 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,32 @@ 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.map(
3448+
|(
3449+
their_per_commitment_point,
3450+
feerate_per_kw,
3451+
to_broadcaster_value,
3452+
to_countersignatory_value,
3453+
)| {
3454+
let htlc_outputs = vec![];
3455+
3456+
let commitment_tx = self.build_counterparty_commitment_tx(
3457+
INITIAL_COMMITMENT_NUMBER,
3458+
&their_per_commitment_point,
3459+
to_broadcaster_value,
3460+
to_countersignatory_value,
3461+
feerate_per_kw,
3462+
htlc_outputs,
3463+
);
3464+
// Take the opportunity to populate this recently introduced field
3465+
self.initial_counterparty_commitment_tx = Some(commitment_tx.clone());
3466+
commitment_tx
3467+
},
3468+
)
3469+
})
34303470
}
34313471

34323472
fn build_counterparty_commitment_tx(
@@ -3454,6 +3494,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34543494

34553495
fn counterparty_commitment_txs_from_update(&self, update: &ChannelMonitorUpdate) -> Vec<CommitmentTransaction> {
34563496
update.updates.iter().filter_map(|update| {
3497+
// Soon we will drop the first branch here in favor of the second.
3498+
// In preparation, we just add the second branch without deleting the first.
3499+
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant.
34573500
match update {
34583501
&ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid,
34593502
ref htlc_outputs, commitment_number, their_per_commitment_point,
@@ -3473,6 +3516,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34733516

34743517
Some(commitment_tx)
34753518
},
3519+
&ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX {
3520+
htlc_outputs: _, ref commitment_tx,
3521+
} => {
3522+
Some(commitment_tx.clone())
3523+
},
34763524
_ => None,
34773525
}
34783526
}).collect()
@@ -5043,6 +5091,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
50435091
let mut spendable_txids_confirmed = Some(Vec::new());
50445092
let mut counterparty_fulfilled_htlcs = Some(new_hash_map());
50455093
let mut initial_counterparty_commitment_info = None;
5094+
let mut initial_counterparty_commitment_tx = None;
50465095
let mut balances_empty_height = None;
50475096
let mut channel_id = None;
50485097
let mut holder_pays_commitment_tx_fee = None;
@@ -5063,6 +5112,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
50635112
(23, holder_pays_commitment_tx_fee, option),
50645113
(25, payment_preimages_with_info, option),
50655114
(27, first_confirmed_funding_txo, (default_value, funding_info.0)),
5115+
(29, initial_counterparty_commitment_tx, option),
50665116
});
50675117
if let Some(payment_preimages_with_info) = payment_preimages_with_info {
50685118
if payment_preimages_with_info.len() != payment_preimages.len() {
@@ -5166,6 +5216,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
51665216
best_block,
51675217
counterparty_node_id: counterparty_node_id.unwrap(),
51685218
initial_counterparty_commitment_info,
5219+
initial_counterparty_commitment_tx,
51695220
balances_empty_height,
51705221
failed_back_htlc_ids: new_hash_set(),
51715222
})))

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)