improve performance on large wallets with high address reuse

This commit is contained in:
Craig Raw 2023-06-15 12:19:09 +02:00
parent 15500b6535
commit 3242f00812
2 changed files with 10 additions and 9 deletions

View file

@ -692,7 +692,9 @@ public class ElectrumServer {
//First check all provided txes that pay to this node //First check all provided txes that pay to this node
Script nodeScript = node.getOutputScript(); Script nodeScript = node.getOutputScript();
Set<BlockTransactionHash> history = nodeTransactionMap.get(node); Set<BlockTransactionHash> history = nodeTransactionMap.get(node);
Map<Sha256Hash, BlockTransactionHash> txHashHistory = new HashMap<>();
for(BlockTransactionHash reference : history) { for(BlockTransactionHash reference : history) {
txHashHistory.put(reference.getHash(), reference);
BlockTransaction blockTransaction = wallet.getTransactions().get(reference.getHash()); BlockTransaction blockTransaction = wallet.getTransactions().get(reference.getHash());
if(blockTransaction == null) { if(blockTransaction == null) {
throw new IllegalStateException("Did not retrieve transaction for hash " + reference.getHashAsString()); throw new IllegalStateException("Did not retrieve transaction for hash " + reference.getHashAsString());
@ -731,14 +733,13 @@ public class ElectrumServer {
throw new IllegalStateException("Could not retrieve transaction for hash " + reference.getHashAsString()); throw new IllegalStateException("Could not retrieve transaction for hash " + reference.getHashAsString());
} }
Optional<BlockTransactionHash> optionalTxHash = history.stream().filter(txHash -> txHash.getHash().equals(previousHash)).findFirst(); BlockTransactionHash spentTxHash = txHashHistory.get(previousHash);
if(optionalTxHash.isEmpty()) { if(spentTxHash == null) {
//No previous transaction history found, cannot check if spends from wallet //No previous transaction history found, cannot check if spends from wallet
//This is fine so long as all referenced transactions have been returned, in which case this refers to a transaction that does not affect this wallet node //This is fine so long as all referenced transactions have been returned, in which case this refers to a transaction that does not affect this wallet node
continue; continue;
} }
BlockTransactionHash spentTxHash = optionalTxHash.get();
TransactionOutput spentOutput = previousTransaction.getTransaction().getOutputs().get((int)input.getOutpoint().getIndex()); TransactionOutput spentOutput = previousTransaction.getTransaction().getOutputs().get((int)input.getOutpoint().getIndex());
if(spentOutput.getScript().equals(nodeScript)) { if(spentOutput.getScript().equals(nodeScript)) {
BlockTransactionHashIndex spendingTXI = new BlockTransactionHashIndex(reference.getHash(), reference.getHeight(), blockTransaction.getDate(), reference.getFee(), inputIndex, spentOutput.getValue()); BlockTransactionHashIndex spendingTXI = new BlockTransactionHashIndex(reference.getHash(), reference.getHeight(), blockTransaction.getDate(), reference.getFee(), inputIndex, spentOutput.getValue());

View file

@ -1,5 +1,6 @@
package com.sparrowwallet.sparrow.wallet; package com.sparrowwallet.sparrow.wallet;
import com.google.common.collect.Sets;
import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.KeyPurpose;
import com.sparrowwallet.drongo.protocol.HashIndex; import com.sparrowwallet.drongo.protocol.HashIndex;
import com.sparrowwallet.drongo.wallet.BlockTransaction; import com.sparrowwallet.drongo.wallet.BlockTransaction;
@ -72,15 +73,14 @@ public class WalletTransactionsEntry extends Entry {
.collect(Collectors.toUnmodifiableMap(entry -> new HashIndex(entry.getKey().getHash(), entry.getKey().getIndex()), Map.Entry::getKey, .collect(Collectors.toUnmodifiableMap(entry -> new HashIndex(entry.getKey().getHash(), entry.getKey().getIndex()), Map.Entry::getKey,
BinaryOperator.maxBy(BlockTransactionHashIndex::compareTo))); BinaryOperator.maxBy(BlockTransactionHashIndex::compareTo)));
List<Entry> current = getWalletTransactions(getWallet()).stream().map(WalletTransaction::getTransactionEntry).collect(Collectors.toList()); Collection<WalletTransactionsEntry.WalletTransaction> entries = getWalletTransactions(getWallet());
List<Entry> previous = new ArrayList<>(getChildren()); Set<Entry> current = entries.stream().map(WalletTransaction::getTransactionEntry).collect(Collectors.toCollection(LinkedHashSet::new));
Set<Entry> previous = new LinkedHashSet<>(getChildren());
List<Entry> entriesAdded = new ArrayList<>(current); Set<Entry> entriesAdded = Sets.difference(current, previous);
entriesAdded.removeAll(previous);
getChildren().addAll(entriesAdded); getChildren().addAll(entriesAdded);
List<Entry> entriesRemoved = new ArrayList<>(previous); Set<Entry> entriesRemoved = Sets.difference(previous, current);
entriesRemoved.removeAll(current);
getChildren().removeAll(entriesRemoved); getChildren().removeAll(entriesRemoved);
calculateBalances(true); calculateBalances(true);