Skip to content

Commit 7f942f4

Browse files
committed
Introduce LatestCounterpartyCommitment monitor update variant
This new variant is a backwards-incompatible successor to `LatestCounterpartyCommitmentTXInfo` that is capable of handling counterparty commitment updates while a splice is pending. Since all counterparty commitment candidates share the same set of non-dust and dust HTLCs (though each non-dust HTLC can have differing output indices), we can share the same set of HTLC source data across all candidates. Unfortunately, each `FundingScope` tracks its own set of `counterparty_claimable_outpoints`, which includes the HTLC source data (though only for the current and previous counterparty commitments), so we end up duplicating it (both in memory and on disk) temporarily.
1 parent 6b350f5 commit 7f942f4

File tree

2 files changed

+163
-75
lines changed

2 files changed

+163
-75
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 115 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,9 @@ pub(crate) enum ChannelMonitorUpdateStep {
600600
to_broadcaster_value_sat: Option<u64>,
601601
to_countersignatory_value_sat: Option<u64>,
602602
},
603-
LatestCounterpartyCommitmentTX {
604-
// The dust and non-dust htlcs for that commitment
605-
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
606-
// Contains only the non-dust htlcs
607-
commitment_tx: CommitmentTransaction,
603+
LatestCounterpartyCommitment {
604+
commitment_txs: Vec<CommitmentTransaction>,
605+
htlc_data: CommitmentHTLCData,
608606
},
609607
PaymentPreimage {
610608
payment_preimage: PaymentPreimage,
@@ -639,7 +637,7 @@ impl ChannelMonitorUpdateStep {
639637
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. } => "LatestHolderCommitmentTXInfo",
640638
ChannelMonitorUpdateStep::LatestHolderCommitment { .. } => "LatestHolderCommitment",
641639
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. } => "LatestCounterpartyCommitmentTXInfo",
642-
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { .. } => "LatestCounterpartyCommitmentTX",
640+
ChannelMonitorUpdateStep::LatestCounterpartyCommitment { .. } => "LatestCounterpartyCommitment",
643641
ChannelMonitorUpdateStep::PaymentPreimage { .. } => "PaymentPreimage",
644642
ChannelMonitorUpdateStep::CommitmentSecret { .. } => "CommitmentSecret",
645643
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => "ChannelForceClosed",
@@ -679,9 +677,10 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
679677
(5, ShutdownScript) => {
680678
(0, scriptpubkey, required),
681679
},
682-
(6, LatestCounterpartyCommitmentTX) => {
683-
(0, htlc_outputs, required_vec),
684-
(2, commitment_tx, required),
680+
(6, LatestCounterpartyCommitment) => {
681+
(1, commitment_txs, required_vec),
682+
(3, htlc_data, required),
683+
},
685684
(8, LatestHolderCommitment) => {
686685
(1, commitment_txs, required_vec),
687686
(3, htlc_data, required),
@@ -1768,40 +1767,38 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
17681767
///
17691768
/// This is used to provide the counterparty commitment transaction directly to the monitor
17701769
/// before the initial persistence of a new channel.
1771-
pub(crate) fn provide_initial_counterparty_commitment_tx<L: Deref>(
1772-
&self, commitment_tx: CommitmentTransaction, logger: &L,
1773-
) where L::Target: Logger
1774-
{
1770+
pub(crate) fn provide_initial_counterparty_commitment_tx(
1771+
&self, commitment_tx: CommitmentTransaction,
1772+
) {
17751773
let mut inner = self.inner.lock().unwrap();
1776-
let logger = WithChannelMonitor::from_impl(logger, &*inner, None);
1777-
inner.provide_initial_counterparty_commitment_tx(commitment_tx, &logger);
1774+
inner.provide_initial_counterparty_commitment_tx(commitment_tx);
17781775
}
17791776

17801777
/// Informs this monitor of the latest counterparty (ie non-broadcastable) commitment transaction.
17811778
/// The monitor watches for it to be broadcasted and then uses the HTLC information (and
17821779
/// possibly future revocation/preimage information) to claim outputs where possible.
17831780
/// We cache also the mapping hash:commitment number to lighten pruning of old preimages by watchtowers.
17841781
#[cfg(test)]
1785-
fn provide_latest_counterparty_commitment_tx<L: Deref>(
1782+
fn provide_latest_counterparty_commitment_tx(
17861783
&self,
17871784
txid: Txid,
17881785
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
17891786
commitment_number: u64,
17901787
their_per_commitment_point: PublicKey,
1791-
logger: &L,
1792-
) where L::Target: Logger {
1788+
) {
17931789
let mut inner = self.inner.lock().unwrap();
1794-
let logger = WithChannelMonitor::from_impl(logger, &*inner, None);
17951790
inner.provide_latest_counterparty_commitment_tx(
1796-
txid, htlc_outputs, commitment_number, their_per_commitment_point, &logger)
1791+
txid, htlc_outputs, commitment_number, their_per_commitment_point)
17971792
}
17981793

17991794
#[cfg(test)]
18001795
fn provide_latest_holder_commitment_tx(
18011796
&self, holder_commitment_tx: HolderCommitmentTransaction,
18021797
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
18031798
) {
1804-
self.inner.lock().unwrap().provide_latest_holder_commitment_tx(holder_commitment_tx, htlc_outputs, &Vec::new(), Vec::new())
1799+
self.inner.lock().unwrap().provide_latest_holder_commitment_tx(
1800+
holder_commitment_tx, htlc_outputs, &Vec::new(), Vec::new()
1801+
).unwrap()
18051802
}
18061803

18071804
/// This is used to provide payment preimage(s) out-of-band during startup without updating the
@@ -3144,9 +3141,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
31443141
Ok(())
31453142
}
31463143

3147-
fn provide_initial_counterparty_commitment_tx<L: Deref>(
3148-
&mut self, commitment_tx: CommitmentTransaction, logger: &WithChannelMonitor<L>,
3149-
) where L::Target: Logger {
3144+
fn provide_initial_counterparty_commitment_tx(
3145+
&mut self, commitment_tx: CommitmentTransaction,
3146+
) {
31503147
// We populate this field for downgrades
31513148
self.initial_counterparty_commitment_info = Some((commitment_tx.per_commitment_point(),
31523149
commitment_tx.feerate_per_kw(), commitment_tx.to_broadcaster_value_sat(), commitment_tx.to_countersignatory_value_sat()));
@@ -3157,16 +3154,15 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
31573154
}
31583155

31593156
self.provide_latest_counterparty_commitment_tx(commitment_tx.trust().txid(), Vec::new(), commitment_tx.commitment_number(),
3160-
commitment_tx.per_commitment_point(), logger);
3157+
commitment_tx.per_commitment_point());
31613158
// Soon, we will only populate this field
31623159
self.initial_counterparty_commitment_tx = Some(commitment_tx);
31633160
}
31643161

3165-
fn provide_latest_counterparty_commitment_tx<L: Deref>(
3166-
&mut self, txid: Txid,
3167-
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
3168-
commitment_number: u64, their_per_commitment_point: PublicKey, logger: &WithChannelMonitor<L>,
3169-
) where L::Target: Logger {
3162+
fn provide_latest_counterparty_commitment_tx(
3163+
&mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
3164+
commitment_number: u64, their_per_commitment_point: PublicKey,
3165+
) {
31703166
// TODO: Encrypt the htlc_outputs data with the single-hash of the commitment transaction
31713167
// so that a remote monitor doesn't learn anything unless there is a malicious close.
31723168
// (only maybe, sadly we cant do the same for local info, as we need to be aware of
@@ -3175,11 +3171,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
31753171
self.counterparty_hash_commitment_number.insert(htlc.payment_hash, commitment_number);
31763172
}
31773173

3178-
log_trace!(logger, "Tracking new counterparty commitment transaction with txid {} at commitment number {} with {} HTLC outputs", txid, commitment_number, htlc_outputs.len());
31793174
self.funding.prev_counterparty_commitment_txid = self.funding.current_counterparty_commitment_txid.take();
31803175
self.funding.current_counterparty_commitment_txid = Some(txid);
31813176
self.funding.counterparty_claimable_outpoints.insert(txid, htlc_outputs.clone());
31823177
self.current_counterparty_commitment_number = commitment_number;
3178+
31833179
//TODO: Merge this into the other per-counterparty-transaction output storage stuff
31843180
match self.their_cur_per_commitment_points {
31853181
Some(old_points) => {
@@ -3201,6 +3197,74 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32013197
}
32023198
}
32033199

3200+
fn update_counterparty_commitment_data(
3201+
&mut self, commitment_txs: &[CommitmentTransaction], htlc_data: &CommitmentHTLCData,
3202+
) -> Result<(), &'static str> {
3203+
if self.pending_funding.len() + 1 != commitment_txs.len() {
3204+
return Err("Commitment transaction(s) mismatch");
3205+
}
3206+
3207+
let htlcs_for_commitment = |commitment: &CommitmentTransaction| {
3208+
let mut nondust_htlcs = commitment.nondust_htlcs().clone().into_iter();
3209+
let mut sources = htlc_data.nondust_htlc_sources.clone().into_iter();
3210+
let nondust_htlcs = core::iter::from_fn(move || {
3211+
let htlc = if let Some(htlc) = nondust_htlcs.next() {
3212+
htlc
3213+
} else {
3214+
debug_assert!(sources.next().is_none());
3215+
return None;
3216+
};
3217+
3218+
let mut source = None;
3219+
if htlc.offered {
3220+
source = Some(Box::new(sources.next().expect(
3221+
"Every offered non-dust HTLC should have a corresponding source"
3222+
)));
3223+
}
3224+
3225+
Some((htlc, source))
3226+
});
3227+
3228+
let dust_htlcs = htlc_data.dust_htlcs.clone().into_iter().map(|(htlc, source)| {
3229+
(htlc, source.map(|source| Box::new(source)))
3230+
});
3231+
3232+
nondust_htlcs.chain(dust_htlcs).collect::<Vec<_>>()
3233+
};
3234+
3235+
let current_funding_commitment = commitment_txs.first().unwrap();
3236+
for (pending_funding, commitment_tx) in self.pending_funding.iter_mut().zip(commitment_txs.iter()) {
3237+
let trusted_tx = commitment_tx.trust();
3238+
if trusted_tx.commitment_number() != current_funding_commitment.commitment_number() {
3239+
return Err("Commitment number mismatch");
3240+
}
3241+
3242+
let funding_outpoint_spent =
3243+
trusted_tx.built_transaction().transaction.tx_in(0).map(|input| input.previous_output).ok();
3244+
let expected_funding_outpoint_spent =
3245+
pending_funding.channel_parameters.funding_outpoint.map(|op| op.into_bitcoin_outpoint());
3246+
if funding_outpoint_spent != expected_funding_outpoint_spent {
3247+
return Err("Funding outpoint mismatch");
3248+
}
3249+
3250+
pending_funding.prev_counterparty_commitment_txid =
3251+
pending_funding.current_counterparty_commitment_txid.take();
3252+
pending_funding.current_counterparty_commitment_txid = Some(trusted_tx.txid());
3253+
pending_funding.counterparty_claimable_outpoints.insert(
3254+
trusted_tx.txid(), htlcs_for_commitment(commitment_tx),
3255+
);
3256+
}
3257+
3258+
self.provide_latest_counterparty_commitment_tx(
3259+
current_funding_commitment.trust().txid(),
3260+
htlcs_for_commitment(current_funding_commitment),
3261+
current_funding_commitment.commitment_number(),
3262+
current_funding_commitment.per_commitment_point(),
3263+
);
3264+
3265+
Ok(())
3266+
}
3267+
32043268
/// Informs this monitor of the latest holder (ie broadcastable) commitment transaction. The
32053269
/// monitor watches for timeouts and may broadcast it if we approach such a timeout. Thus, it
32063270
/// is important that any clones of this channel monitor (including remote clones) by kept
@@ -3651,14 +3715,18 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
36513715
},
36523716
// Soon we will drop the `LatestCounterpartyCommitmentTXInfo` variant in favor of `LatestCounterpartyCommitment`.
36533717
// For now we just add the code to handle the new updates.
3654-
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant.
3718+
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitment` variant.
36553719
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid, htlc_outputs, commitment_number, their_per_commitment_point, .. } => {
36563720
log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment transaction info");
3657-
self.provide_latest_counterparty_commitment_tx(*commitment_txid, htlc_outputs.clone(), *commitment_number, *their_per_commitment_point, logger)
3721+
self.provide_latest_counterparty_commitment_tx(*commitment_txid, htlc_outputs.clone(), *commitment_number, *their_per_commitment_point)
36583722
},
3659-
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { htlc_outputs, commitment_tx } => {
3660-
log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment transaction info");
3661-
self.provide_latest_counterparty_commitment_tx(commitment_tx.trust().txid(), htlc_outputs.clone(), commitment_tx.commitment_number(), commitment_tx.per_commitment_point(), logger)
3723+
ChannelMonitorUpdateStep::LatestCounterpartyCommitment {
3724+
commitment_txs, htlc_data,
3725+
} => {
3726+
log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment");
3727+
if let Err(e) = self.update_counterparty_commitment_data(commitment_txs, htlc_data) {
3728+
log_error!(logger, "Failed updating latest counterparty commitment state: {}", e);
3729+
}
36623730
},
36633731
ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage, payment_info } => {
36643732
log_trace!(logger, "Updating ChannelMonitor with payment preimage");
@@ -3734,7 +3802,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
37343802
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. }
37353803
|ChannelMonitorUpdateStep::LatestHolderCommitment { .. }
37363804
|ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. }
3737-
|ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX { .. }
3805+
|ChannelMonitorUpdateStep::LatestCounterpartyCommitment { .. }
37383806
|ChannelMonitorUpdateStep::ShutdownScript { .. }
37393807
|ChannelMonitorUpdateStep::CommitmentSecret { .. }
37403808
|ChannelMonitorUpdateStep::RenegotiatedFunding { .. } =>
@@ -3890,7 +3958,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38903958
update.updates.iter().filter_map(|update| {
38913959
// Soon we will drop the first branch here in favor of the second.
38923960
// In preparation, we just add the second branch without deleting the first.
3893-
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitmentTX` variant.
3961+
// Next step: in channel, switch channel monitor updates to use the `LatestCounterpartyCommitment` variant.
38943962
match update {
38953963
&ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid,
38963964
ref htlc_outputs, commitment_number, their_per_commitment_point,
@@ -3908,19 +3976,17 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
39083976

39093977
debug_assert_eq!(commitment_tx.trust().txid(), commitment_txid);
39103978

3911-
Some(commitment_tx)
3979+
Some(vec![commitment_tx])
39123980
},
3913-
&ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTX {
3914-
htlc_outputs: _, ref commitment_tx,
3915-
} => {
3916-
Some(commitment_tx.clone())
3981+
&ChannelMonitorUpdateStep::LatestCounterpartyCommitment { ref commitment_txs, .. } => {
3982+
Some(commitment_txs.clone())
39173983
},
39183984
&ChannelMonitorUpdateStep::RenegotiatedFunding { ref counterparty_commitment_tx, .. } => {
3919-
Some(counterparty_commitment_tx.clone())
3985+
Some(vec![counterparty_commitment_tx.clone()])
39203986
},
39213987
_ => None,
39223988
}
3923-
}).collect()
3989+
}).flatten().collect()
39243990
}
39253991

39263992
fn sign_to_local_justice_tx(
@@ -5988,9 +6054,9 @@ mod tests {
59886054
monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(),
59896055
nondust_htlcs.into_iter().map(|htlc| (htlc.clone(), Some(dummy_sig), Some(dummy_source.clone()))).collect());
59906056
monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"1").to_byte_array()),
5991-
preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key, &logger);
6057+
preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key);
59926058
monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"2").to_byte_array()),
5993-
preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key, &logger);
6059+
preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key);
59946060
for &(ref preimage, ref hash) in preimages.iter() {
59956061
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator);
59966062
monitor.provide_payment_preimage_unsafe_legacy(
@@ -6007,7 +6073,7 @@ mod tests {
60076073
test_preimages_exist!(&preimages[15..20], monitor);
60086074

60096075
monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"3").to_byte_array()),
6010-
preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key, &logger);
6076+
preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key);
60116077

60126078
// Now provide a further secret, pruning preimages 15-17
60136079
secret[0..32].clone_from_slice(&<Vec<u8>>::from_hex("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap());
@@ -6017,7 +6083,7 @@ mod tests {
60176083
test_preimages_exist!(&preimages[17..20], monitor);
60186084

60196085
monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"4").to_byte_array()),
6020-
preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key, &logger);
6086+
preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key);
60216087

60226088
// Now update holder commitment tx info, pruning only element 18 as we still care about the
60236089
// previous commitment tx's preimages too

0 commit comments

Comments
 (0)