Skip to content

Commit 3aea5ef

Browse files
committed
Minimize reads to counterparty_claimable_outpoints
Reads related to current/previous commitment_tx should be explicit and reads related to older commitment_txs should be minimized.
1 parent 1890e80 commit 3aea5ef

File tree

1 file changed

+37
-34
lines changed

1 file changed

+37
-34
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2430,8 +2430,8 @@ macro_rules! fail_unbroadcast_htlcs {
24302430
debug_assert_eq!($commitment_tx_confirmed.txid(), $commitment_txid_confirmed);
24312431

24322432
macro_rules! check_htlc_fails {
2433-
($txid: expr, $commitment_tx: expr) => {
2434-
if let Some(ref latest_outpoints) = $self.counterparty_claimable_outpoints.get($txid) {
2433+
($txid: expr, $commitment_tx: expr, $per_commitment_outpoints: expr) => {
2434+
if let Some(ref latest_outpoints) = $per_commitment_outpoints {
24352435
for &(ref htlc, ref source_option) in latest_outpoints.iter() {
24362436
if let &Some(ref source) = source_option {
24372437
// Check if the HTLC is present in the commitment transaction that was
@@ -2491,10 +2491,10 @@ macro_rules! fail_unbroadcast_htlcs {
24912491
}
24922492
}
24932493
if let Some(ref txid) = $self.current_counterparty_commitment_txid {
2494-
check_htlc_fails!(txid, "current");
2494+
check_htlc_fails!(txid, "current", $self.counterparty_claimable_outpoints.get(txid));
24952495
}
24962496
if let Some(ref txid) = $self.prev_counterparty_commitment_txid {
2497-
check_htlc_fails!(txid, "previous");
2497+
check_htlc_fails!(txid, "previous", $self.counterparty_claimable_outpoints.get(txid));
24982498
}
24992499
} }
25002500
}
@@ -2763,15 +2763,15 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
27632763
// If the channel is force closed, try to claim the output from this preimage.
27642764
// First check if a counterparty commitment transaction has been broadcasted:
27652765
macro_rules! claim_htlcs {
2766-
($commitment_number: expr, $txid: expr) => {
2767-
let (htlc_claim_reqs, _) = self.get_counterparty_output_claim_info($commitment_number, $txid, None);
2766+
($commitment_number: expr, $txid: expr, $htlcs: expr) => {
2767+
let (htlc_claim_reqs, _) = self.get_counterparty_output_claim_info($commitment_number, $txid, None, $htlcs);
27682768
self.onchain_tx_handler.update_claims_view_from_requests(htlc_claim_reqs, self.best_block.height, self.best_block.height, broadcaster, fee_estimator, logger);
27692769
}
27702770
}
27712771
if let Some(txid) = self.current_counterparty_commitment_txid {
27722772
if txid == confirmed_spend_txid {
27732773
if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) {
2774-
claim_htlcs!(*commitment_number, txid);
2774+
claim_htlcs!(*commitment_number, txid, self.counterparty_claimable_outpoints.get(&txid));
27752775
} else {
27762776
debug_assert!(false);
27772777
log_error!(logger, "Detected counterparty commitment tx on-chain without tracking commitment number");
@@ -2782,7 +2782,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
27822782
if let Some(txid) = self.prev_counterparty_commitment_txid {
27832783
if txid == confirmed_spend_txid {
27842784
if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) {
2785-
claim_htlcs!(*commitment_number, txid);
2785+
claim_htlcs!(*commitment_number, txid, self.counterparty_claimable_outpoints.get(&txid));
27862786
} else {
27872787
debug_assert!(false);
27882788
log_error!(logger, "Detected counterparty commitment tx on-chain without tracking commitment number");
@@ -3235,8 +3235,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32353235
/// Returns packages to claim the revoked output(s), as well as additional outputs to watch and
32363236
/// general information about the output that is to the counterparty in the commitment
32373237
/// transaction.
3238-
fn check_spend_counterparty_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L)
3239-
-> (Vec<PackageTemplate>, TransactionOutputs, CommitmentTxCounterpartyOutputInfo)
3238+
fn check_spend_counterparty_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, per_commitment_option: Option<&Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>, logger: &L)
3239+
-> (Vec<PackageTemplate>, TransactionOutputs, CommitmentTxCounterpartyOutputInfo)
32403240
where L::Target: Logger {
32413241
// Most secp and related errors trying to create keys means we have no hope of constructing
32423242
// a spend transaction...so we return no transactions to broadcast
@@ -3245,7 +3245,6 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32453245
let mut to_counterparty_output_info = None;
32463246

32473247
let commitment_txid = tx.txid(); //TODO: This is gonna be a performance bottleneck for watchtowers!
3248-
let per_commitment_option = self.counterparty_claimable_outpoints.get(&commitment_txid);
32493248

32503249
macro_rules! ignore_error {
32513250
( $thing : expr ) => {
@@ -3279,8 +3278,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32793278
}
32803279

32813280
// Then, try to find revoked htlc outputs
3282-
if let Some(ref per_commitment_data) = per_commitment_option {
3283-
for (_, &(ref htlc, _)) in per_commitment_data.iter().enumerate() {
3281+
if let Some(per_commitment_claimable_data) = per_commitment_option {
3282+
for (htlc, _) in per_commitment_claimable_data {
32843283
if let Some(transaction_output_index) = htlc.transaction_output_index {
32853284
if transaction_output_index as usize >= tx.output.len() ||
32863285
tx.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 {
@@ -3304,9 +3303,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
33043303
}
33053304
self.counterparty_commitment_txn_on_chain.insert(commitment_txid, commitment_number);
33063305

3307-
if let Some(per_commitment_data) = per_commitment_option {
3306+
if let Some(per_commitment_claimable_data) = per_commitment_option {
33083307
fail_unbroadcast_htlcs!(self, "revoked_counterparty", commitment_txid, tx, height,
3309-
block_hash, per_commitment_data.iter().map(|(htlc, htlc_source)|
3308+
block_hash, per_commitment_claimable_data.iter().map(|(htlc, htlc_source)|
33103309
(htlc, htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref()))
33113310
), logger);
33123311
} else {
@@ -3319,7 +3318,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
33193318
block_hash, [].iter().map(|reference| *reference), logger);
33203319
}
33213320
}
3322-
} else if let Some(per_commitment_data) = per_commitment_option {
3321+
} else if let Some(per_commitment_claimable_data) = per_commitment_option {
33233322
// While this isn't useful yet, there is a potential race where if a counterparty
33243323
// revokes a state at the same time as the commitment transaction for that state is
33253324
// confirmed, and the watchtower receives the block before the user, the user could
@@ -3334,12 +3333,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
33343333

33353334
log_info!(logger, "Got broadcast of non-revoked counterparty commitment transaction {}", commitment_txid);
33363335
fail_unbroadcast_htlcs!(self, "counterparty", commitment_txid, tx, height, block_hash,
3337-
per_commitment_data.iter().map(|(htlc, htlc_source)|
3336+
per_commitment_claimable_data.iter().map(|(htlc, htlc_source)|
33383337
(htlc, htlc_source.as_ref().map(|htlc_source| htlc_source.as_ref()))
33393338
), logger);
3340-
33413339
let (htlc_claim_reqs, counterparty_output_info) =
3342-
self.get_counterparty_output_claim_info(commitment_number, commitment_txid, Some(tx));
3340+
self.get_counterparty_output_claim_info(commitment_number, commitment_txid, Some(tx), per_commitment_option);
33433341
to_counterparty_output_info = counterparty_output_info;
33443342
for req in htlc_claim_reqs {
33453343
claimable_outpoints.push(req);
@@ -3350,12 +3348,12 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
33503348
}
33513349

33523350
/// Returns the HTLC claim package templates and the counterparty output info
3353-
fn get_counterparty_output_claim_info(&self, commitment_number: u64, commitment_txid: Txid, tx: Option<&Transaction>)
3351+
fn get_counterparty_output_claim_info(&self, commitment_number: u64, commitment_txid: Txid, tx: Option<&Transaction>, per_commitment_option: Option<&Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>)
33543352
-> (Vec<PackageTemplate>, CommitmentTxCounterpartyOutputInfo) {
33553353
let mut claimable_outpoints = Vec::new();
33563354
let mut to_counterparty_output_info: CommitmentTxCounterpartyOutputInfo = None;
33573355

3358-
let htlc_outputs = match self.counterparty_claimable_outpoints.get(&commitment_txid) {
3356+
let per_commitment_claimable_data = match per_commitment_option {
33593357
Some(outputs) => outputs,
33603358
None => return (claimable_outpoints, to_counterparty_output_info),
33613359
};
@@ -3394,7 +3392,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
33943392
}
33953393
}
33963394

3397-
for (_, &(ref htlc, _)) in htlc_outputs.iter().enumerate() {
3395+
for &(ref htlc, _) in per_commitment_claimable_data.iter() {
33983396
if let Some(transaction_output_index) = htlc.transaction_output_index {
33993397
if let Some(transaction) = tx {
34003398
if transaction_output_index as usize >= transaction.output.len() ||
@@ -3577,14 +3575,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35773575
/// Cancels any existing pending claims for a commitment that previously confirmed and has now
35783576
/// been replaced by another.
35793577
pub fn cancel_prev_commitment_claims<L: Deref>(
3580-
&mut self, logger: &L, confirmed_commitment_txid: &Txid
3578+
&mut self, logger: &L, confirmed_commitment_txid: &Txid, per_commitment_option: Option<&Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>
35813579
) where L::Target: Logger {
35823580
for (counterparty_commitment_txid, _) in &self.counterparty_commitment_txn_on_chain {
35833581
// Cancel any pending claims for counterparty commitments we've seen confirm.
35843582
if counterparty_commitment_txid == confirmed_commitment_txid {
35853583
continue;
35863584
}
3587-
for (htlc, _) in self.counterparty_claimable_outpoints.get(counterparty_commitment_txid).unwrap_or(&vec![]) {
3585+
for (htlc, _) in per_commitment_option.unwrap_or(&vec![]) {
35883586
log_trace!(logger, "Canceling claims for previously confirmed counterparty commitment {}",
35893587
counterparty_commitment_txid);
35903588
let mut outpoint = BitcoinOutPoint { txid: *counterparty_commitment_txid, vout: 0 };
@@ -3775,9 +3773,12 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
37753773
&self.channel_id(), txid);
37763774
self.funding_spend_seen = true;
37773775
let mut commitment_tx_to_counterparty_output = None;
3778-
if (tx.input[0].sequence.0 >> 8*3) as u8 == 0x80 && (tx.lock_time.to_consensus_u32() >> 8*3) as u8 == 0x20 {
3776+
let per_commitment_option = self.counterparty_claimable_outpoints.get(&tx.txid()).map(|x| x.iter()
3777+
.map(|&(ref a, ref b)| (a.clone(), b.clone())).collect::<Vec<_>>());
3778+
3779+
if (tx.input[0].sequence.0 >> 8 * 3) as u8 == 0x80 && (tx.lock_time.to_consensus_u32() >> 8 * 3) as u8 == 0x20 {
37793780
let (mut new_outpoints, new_outputs, counterparty_output_idx_sats) =
3780-
self.check_spend_counterparty_transaction(&tx, height, &block_hash, &logger);
3781+
self.check_spend_counterparty_transaction(&tx, height, &block_hash, per_commitment_option.as_ref(), &logger);
37813782
commitment_tx_to_counterparty_output = counterparty_output_idx_sats;
37823783
if !new_outputs.1.is_empty() {
37833784
watch_outputs.push(new_outputs);
@@ -3809,7 +3810,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38093810
// Now that we've detected a confirmed commitment transaction, attempt to cancel
38103811
// pending claims for any commitments that were previously confirmed such that
38113812
// we don't continue claiming inputs that no longer exist.
3812-
self.cancel_prev_commitment_claims(&logger, &txid);
3813+
self.cancel_prev_commitment_claims(&logger, &txid, per_commitment_option.as_ref());
38133814
}
38143815
}
38153816
if tx.input.len() >= 1 {
@@ -4219,9 +4220,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42194220
}
42204221

42214222
macro_rules! check_htlc_valid_counterparty {
4222-
($counterparty_txid: expr, $htlc_output: expr) => {
4223-
if let Some(txid) = $counterparty_txid {
4224-
for &(ref pending_htlc, ref pending_source) in self.counterparty_claimable_outpoints.get(&txid).unwrap() {
4223+
($htlc_output: expr, $per_commitment_data: expr) => {
4224+
for &(ref pending_htlc, ref pending_source) in $per_commitment_data {
42254225
if pending_htlc.payment_hash == $htlc_output.payment_hash && pending_htlc.amount_msat == $htlc_output.amount_msat {
42264226
if let &Some(ref source) = pending_source {
42274227
log_claim!("revoked counterparty commitment tx", false, pending_htlc, true);
@@ -4230,7 +4230,6 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42304230
}
42314231
}
42324232
}
4233-
}
42344233
}
42354234
}
42364235

@@ -4247,9 +4246,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42474246
// resolve the source HTLC with the original sender.
42484247
payment_data = Some(((*source).clone(), htlc_output.payment_hash, htlc_output.amount_msat));
42494248
} else if !$holder_tx {
4250-
check_htlc_valid_counterparty!(self.current_counterparty_commitment_txid, htlc_output);
4249+
if let Some(current_counterparty_commitment_txid) = &self.current_counterparty_commitment_txid {
4250+
check_htlc_valid_counterparty!(htlc_output, self.counterparty_claimable_outpoints.get(current_counterparty_commitment_txid).unwrap());
4251+
}
42514252
if payment_data.is_none() {
4252-
check_htlc_valid_counterparty!(self.prev_counterparty_commitment_txid, htlc_output);
4253+
if let Some(prev_counterparty_commitment_txid) = &self.prev_counterparty_commitment_txid {
4254+
check_htlc_valid_counterparty!(htlc_output, self.counterparty_claimable_outpoints.get(prev_counterparty_commitment_txid).unwrap());
4255+
}
42534256
}
42544257
}
42554258
if payment_data.is_none() {
@@ -4287,7 +4290,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42874290
}
42884291
}
42894292
if let Some(ref htlc_outputs) = self.counterparty_claimable_outpoints.get(&input.previous_output.txid) {
4290-
scan_commitment!(htlc_outputs.iter().map(|&(ref a, ref b)| (a, (b.as_ref().clone()).map(|boxed| &**boxed))),
4293+
scan_commitment!(htlc_outputs.iter().map(|&(ref a, ref b)| (a, (b.as_ref()).map(|boxed| &**boxed))),
42914294
"counterparty commitment tx", false);
42924295
}
42934296

0 commit comments

Comments
 (0)