java-topology/defects/sparrow-0001/patch/sparrow-0001.patch
russell@unturf.com 830b54936d sparrow-0001/sparrow-0002: Sparrow Wallet CWE-407 scan, 2 defects
sparrow-0001: WalletUtxosEntry.updateUtxos() ArrayList.removeAll O(N^2)
  UTXO diff uses List.removeAll which is O(current * previous).
  Fix: Set-based diff via Sets.difference (same pattern already used
  in WalletTransactionsEntry). MEDIUM, 250x at N=1000 UTXOs.

sparrow-0002: UtxoEntry.recountMixesDone stream().anyMatch O(M*I*T)
  Whirlpool mix chain walk streams all wallet TXOs per input per mix.
  Fix: HashMap<Sha256Hash, Set<Long>> index for O(1) lookup.
  MEDIUM-HIGH, 50x at M=200 mixes, T=1000 TXOs.

MOAD-0002 (Intertangle): EventManager is a thin Guava EventBus singleton,
  not a god object. Wallet/network/UI coupling is event-driven, acceptable.
MOAD-0003 (Leaked Context): CLEAN, no ThreadLocal usage found.
MOAD-0004 (Logged Secret): CLEAN, no private keys/mnemonics/passphrases
  logged. SecureChannelSession has commented-out secret logging.
MOAD-0005 (Thundering Herd): CLEAN, no unsynchronized cache patterns.

4/4 unit tests PASS. UNDF-2026-000000931 through UNDF-2026-000000932.
2026-03-31 09:41:11 -04:00

30 lines
1.4 KiB
Diff

# UNDF: UNDF-2026-000000931
--- a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletUtxosEntry.java
+++ b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletUtxosEntry.java
@@ -1,6 +1,7 @@
package com.sparrowwallet.sparrow.wallet;
import com.sparrowwallet.drongo.wallet.Wallet;
+import com.google.common.collect.Sets;
import com.sparrowwallet.drongo.wallet.WalletNode;
import com.sparrowwallet.sparrow.io.Config;
@@ -63,14 +64,14 @@ public class WalletUtxosEntry extends Entry {
public void updateUtxos() {
List<Entry> current = getWallet().getWalletUtxos().entrySet().stream().map(entry -> new UtxoEntry(entry.getValue().getWallet(), entry.getKey(), HashIndexEntry.Type.OUTPUT, entry.getValue())).collect(Collectors.toList());
- List<Entry> previous = new ArrayList<>(getChildren());
+ Set<Entry> currentSet = new LinkedHashSet<>(current);
+ Set<Entry> previousSet = new LinkedHashSet<>(getChildren());
- List<Entry> entriesAdded = new ArrayList<>(current);
- entriesAdded.removeAll(previous);
+ Set<Entry> entriesAdded = Sets.difference(currentSet, previousSet);
getChildren().addAll(entriesAdded);
- List<Entry> entriesRemoved = new ArrayList<>(previous);
- entriesRemoved.removeAll(current);
+ Set<Entry> entriesRemoved = Sets.difference(previousSet, currentSet);
getChildren().removeAll(entriesRemoved);
calculateDuplicates();