From 3242f00812f08a72733f0a76aaaf5bd0cca68c12 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Thu, 15 Jun 2023 12:19:09 +0200 Subject: [PATCH] improve performance on large wallets with high address reuse --- .../sparrowwallet/sparrow/net/ElectrumServer.java | 7 ++++--- .../sparrow/wallet/WalletTransactionsEntry.java | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java b/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java index 20b05df7..055025b0 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java @@ -692,7 +692,9 @@ public class ElectrumServer { //First check all provided txes that pay to this node Script nodeScript = node.getOutputScript(); Set history = nodeTransactionMap.get(node); + Map txHashHistory = new HashMap<>(); for(BlockTransactionHash reference : history) { + txHashHistory.put(reference.getHash(), reference); BlockTransaction blockTransaction = wallet.getTransactions().get(reference.getHash()); if(blockTransaction == null) { 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()); } - Optional optionalTxHash = history.stream().filter(txHash -> txHash.getHash().equals(previousHash)).findFirst(); - if(optionalTxHash.isEmpty()) { + BlockTransactionHash spentTxHash = txHashHistory.get(previousHash); + if(spentTxHash == null) { //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 continue; } - BlockTransactionHash spentTxHash = optionalTxHash.get(); TransactionOutput spentOutput = previousTransaction.getTransaction().getOutputs().get((int)input.getOutpoint().getIndex()); if(spentOutput.getScript().equals(nodeScript)) { BlockTransactionHashIndex spendingTXI = new BlockTransactionHashIndex(reference.getHash(), reference.getHeight(), blockTransaction.getDate(), reference.getFee(), inputIndex, spentOutput.getValue()); diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletTransactionsEntry.java b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletTransactionsEntry.java index 2d3e0fbb..ad06421f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletTransactionsEntry.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletTransactionsEntry.java @@ -1,5 +1,6 @@ package com.sparrowwallet.sparrow.wallet; +import com.google.common.collect.Sets; import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.protocol.HashIndex; 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, BinaryOperator.maxBy(BlockTransactionHashIndex::compareTo))); - List current = getWalletTransactions(getWallet()).stream().map(WalletTransaction::getTransactionEntry).collect(Collectors.toList()); - List previous = new ArrayList<>(getChildren()); + Collection entries = getWalletTransactions(getWallet()); + Set current = entries.stream().map(WalletTransaction::getTransactionEntry).collect(Collectors.toCollection(LinkedHashSet::new)); + Set previous = new LinkedHashSet<>(getChildren()); - List entriesAdded = new ArrayList<>(current); - entriesAdded.removeAll(previous); + Set entriesAdded = Sets.difference(current, previous); getChildren().addAll(entriesAdded); - List entriesRemoved = new ArrayList<>(previous); - entriesRemoved.removeAll(current); + Set entriesRemoved = Sets.difference(previous, current); getChildren().removeAll(entriesRemoved); calculateBalances(true);