# UNDF: UNDF-2026-000000932 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/UtxoEntry.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/UtxoEntry.java @@ -149,16 +149,23 @@ public class UtxoEntry extends HashIndexEntry { public int recountMixesDone(Wallet postmixWallet, BlockTransactionHashIndex postmixUtxo) { int mixesDone = 0; - Set walletTxos = postmixWallet.getWalletTxos().entrySet().stream() - .filter(entry -> entry.getValue().getKeyPurpose() == KeyPurpose.RECEIVE).map(Map.Entry::getKey).collect(Collectors.toSet()); + // Build a lookup index: txHash -> set of output indices for O(1) membership test + // instead of streaming the entire walletTxos set per input per mix iteration + Map> txoIndex = new HashMap<>(); + for(Map.Entry entry : postmixWallet.getWalletTxos().entrySet()) { + if(entry.getValue().getKeyPurpose() == KeyPurpose.RECEIVE) { + BlockTransactionHashIndex txo = entry.getKey(); + txoIndex.computeIfAbsent(txo.getHash(), k -> new HashSet<>()).add(txo.getIndex()); + } + } BlockTransaction blkTx = postmixWallet.getTransactions().get(postmixUtxo.getHash()); while(blkTx != null) { mixesDone++; List inputs = blkTx.getTransaction().getInputs(); blkTx = null; for(TransactionInput txInput : inputs) { BlockTransaction inputTx = postmixWallet.getTransactions().get(txInput.getOutpoint().getHash()); - if(inputTx != null && walletTxos.stream().anyMatch(txo -> txo.getHash().equals(inputTx.getHash()) && txo.getIndex() == txInput.getOutpoint().getIndex()) && inputTx.getTransaction() != null) { + Set indices = inputTx == null ? null : txoIndex.get(inputTx.getHash()); + if(inputTx != null && indices != null && indices.contains(txInput.getOutpoint().getIndex()) && inputTx.getTransaction() != null) { blkTx = inputTx; } }