Skip to content

Commit 85eac68

Browse files
committed
DRY the comparison blocks in update_claims_view_from_matched_txn
In `update_claims_view_from_matched_txn` we have two different tx-equivalence checks which do the same thing - both check that the tx which appeared on chain spent all of the outpoints which we intended to spend in a given package. While one is more effecient than the other (but only usable in a subset of cases), the difference between O(N) and O(N^2) when N is 1-5 is trivial. Still, it is possible we hit this code with just shy of 900 HTLC outputs in a channel, and a transaction with a ton of inputs. While having to spin through a few million entries if our counterparty wastes a full block isn't really a big deal, we go ahead and use a sorted vec and binary searches because its trivial.
1 parent de44894 commit 85eac68

File tree

1 file changed

+6
-23
lines changed

1 file changed

+6
-23
lines changed

lightning/src/chain/onchaintx.rs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -733,31 +733,14 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
733733
// outpoints to know if transaction is the original claim or a bumped one issued
734734
// by us.
735735
let mut are_sets_equal = true;
736-
if !request.requires_external_funding() || !request.is_malleable() {
737-
// If the claim does not require external funds to be allocated through
738-
// additional inputs we can simply check the inputs in order as they
739-
// cannot change under us.
740-
if request.outpoints().len() != tx.input.len() {
736+
// Do a linear search for each input (we don't expect large input sets to
737+
// exist) to ensure the request's input set is fully spent to be resilient
738+
// against the external claim reordering inputs.
739+
for request_input in request.outpoints() {
740+
if tx.input.iter().find(|input| input.previous_output == *request_input).is_none() {
741741
are_sets_equal = false;
742-
} else {
743-
for (claim_inp, tx_inp) in request.outpoints().iter().zip(tx.input.iter()) {
744-
if **claim_inp != tx_inp.previous_output {
745-
are_sets_equal = false;
746-
}
747-
}
748-
}
749-
} else {
750-
// Otherwise, we'll do a linear search for each input (we don't expect
751-
// large input sets to exist) to ensure the request's input set is fully
752-
// spent to be resilient against the external claim reordering inputs.
753-
let mut spends_all_inputs = true;
754-
for request_input in request.outpoints() {
755-
if tx.input.iter().find(|input| input.previous_output == *request_input).is_none() {
756-
spends_all_inputs = false;
757-
break;
758-
}
742+
break;
759743
}
760-
are_sets_equal = spends_all_inputs;
761744
}
762745

763746
macro_rules! clean_claim_request_after_safety_delay {

0 commit comments

Comments
 (0)