mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 15:10:44 +01:00
Use cache for WalletService.getNumTxOutputsForAddress
Use a guava Multiset to cache the total number of tx outputs (out of the live txs in the user's wallet) with a given address. Since this requires a scan of the entire tx set, compute all the counts in one go and store in an ImmutableMultiset<Address>. Invalidate the entire cache any time a tx set change occurs, by attaching a WalletChangeEventListener to the wallet (using a direct executor for immediate effect). This is to fix a quadratic time bug in DepositView, which uses the count to determine if a given address in the BTC wallet is used/unused.
This commit is contained in:
parent
70a13b8783
commit
217aaf826d
1 changed files with 23 additions and 10 deletions
|
@ -72,6 +72,8 @@ import org.bitcoinj.wallet.listeners.WalletReorganizeEventListener;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
|
@ -83,8 +85,10 @@ import org.bouncycastle.crypto.params.KeyParameter;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.Getter;
|
||||
|
@ -110,6 +114,8 @@ public abstract class WalletService {
|
|||
private final CopyOnWriteArraySet<AddressConfidenceListener> addressConfidenceListeners = new CopyOnWriteArraySet<>();
|
||||
private final CopyOnWriteArraySet<TxConfidenceListener> txConfidenceListeners = new CopyOnWriteArraySet<>();
|
||||
private final CopyOnWriteArraySet<BalanceListener> balanceListeners = new CopyOnWriteArraySet<>();
|
||||
private final WalletChangeEventListener cacheInvalidationListener;
|
||||
private final AtomicReference<Multiset<Address>> txOutputAddressCache = new AtomicReference<>();
|
||||
@Getter
|
||||
protected Wallet wallet;
|
||||
@Getter
|
||||
|
@ -131,6 +137,8 @@ public abstract class WalletService {
|
|||
this.feeService = feeService;
|
||||
|
||||
params = walletsSetup.getParams();
|
||||
|
||||
cacheInvalidationListener = wallet -> txOutputAddressCache.set(null);
|
||||
}
|
||||
|
||||
|
||||
|
@ -143,6 +151,7 @@ public abstract class WalletService {
|
|||
wallet.addCoinsSentEventListener(walletEventListener);
|
||||
wallet.addReorganizeEventListener(walletEventListener);
|
||||
wallet.addTransactionConfidenceEventListener(walletEventListener);
|
||||
wallet.addChangeEventListener(Threading.SAME_THREAD, cacheInvalidationListener);
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
|
@ -151,6 +160,7 @@ public abstract class WalletService {
|
|||
wallet.removeCoinsSentEventListener(walletEventListener);
|
||||
wallet.removeReorganizeEventListener(walletEventListener);
|
||||
wallet.removeTransactionConfidenceEventListener(walletEventListener);
|
||||
wallet.removeChangeEventListener(cacheInvalidationListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,16 +506,19 @@ public abstract class WalletService {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public int getNumTxOutputsForAddress(Address address) {
|
||||
List<TransactionOutput> transactionOutputs = new ArrayList<>();
|
||||
wallet.getTransactions(false).forEach(t -> transactionOutputs.addAll(t.getOutputs()));
|
||||
int outputs = 0;
|
||||
for (TransactionOutput output : transactionOutputs) {
|
||||
if (isOutputScriptConvertibleToAddress(output) &&
|
||||
address != null &&
|
||||
address.equals(getAddressFromOutput(output)))
|
||||
outputs++;
|
||||
}
|
||||
return outputs;
|
||||
return getTxOutputAddressMultiset().count(address);
|
||||
}
|
||||
|
||||
private Multiset<Address> getTxOutputAddressMultiset() {
|
||||
return txOutputAddressCache.updateAndGet(set -> set != null ? set : computeTxOutputAddressMultiset());
|
||||
}
|
||||
|
||||
private Multiset<Address> computeTxOutputAddressMultiset() {
|
||||
return wallet.getTransactions(false).stream()
|
||||
.flatMap(t -> t.getOutputs().stream())
|
||||
.map(WalletService::getAddressFromOutput)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(ImmutableMultiset.toImmutableMultiset());
|
||||
}
|
||||
|
||||
public boolean isAddressUnused(Address address) {
|
||||
|
|
Loading…
Add table
Reference in a new issue