temporarily disconnect from whirlpool if gap limit is increasing rapidly

This commit is contained in:
Craig Raw 2023-11-08 11:59:19 +02:00
parent 0d7ae74f0f
commit 995d2c5e4e
5 changed files with 64 additions and 1 deletions

View file

@ -999,7 +999,7 @@ public class TransactionDiagram extends GridPane {
}
private boolean isDuplicateAddress(Payment payment) {
return walletTx.getPayments().stream().filter(p -> payment != p).anyMatch(p -> payment.getAddress().equals(p.getAddress()));
return walletTx.getPayments().stream().filter(p -> payment != p).anyMatch(p -> payment.getAddress() != null && payment.getAddress().equals(p.getAddress()));
}
public static Glyph getExcludeGlyph() {

View file

@ -0,0 +1,15 @@
package com.sparrowwallet.sparrow.event;
import com.sparrowwallet.drongo.wallet.Wallet;
public class WhirlpoolIndexHighFrequencyEvent {
private final Wallet wallet;
public WhirlpoolIndexHighFrequencyEvent(Wallet wallet) {
this.wallet = wallet;
}
public Wallet getWallet() {
return wallet;
}
}

View file

@ -45,6 +45,7 @@ import javafx.beans.property.SimpleBooleanProperty;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.util.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -75,6 +76,7 @@ public class Whirlpool {
private boolean resyncMixesDone;
private StartupService startupService;
private Duration startupServiceDelay;
private final BooleanProperty startingProperty = new SimpleBooleanProperty(false);
private final BooleanProperty stoppingProperty = new SimpleBooleanProperty(false);
@ -563,6 +565,14 @@ public class Whirlpool {
return stoppingProperty;
}
public Duration getStartupServiceDelay() {
return startupServiceDelay;
}
public void setStartupServiceDelay(Duration startupServiceDelay) {
this.startupServiceDelay = startupServiceDelay;
}
@Subscribe
public void onMixSuccess(MixSuccessEvent e) {
WalletUtxo walletUtxo = getUtxo(e.getWhirlpoolUtxo());

View file

@ -15,6 +15,7 @@ import com.sparrowwallet.sparrow.WalletTabData;
import com.sparrowwallet.sparrow.event.*;
import com.sparrowwallet.sparrow.io.Storage;
import com.sparrowwallet.sparrow.soroban.Soroban;
import javafx.application.Platform;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
@ -105,6 +106,11 @@ public class WhirlpoolServices {
}
Whirlpool.StartupService startupService = whirlpool.createStartupService();
if(whirlpool.getStartupServiceDelay() != null) {
startupService.setDelay(whirlpool.getStartupServiceDelay());
whirlpool.setStartupServiceDelay(null);
}
startupService.setPeriod(Duration.minutes(2));
startupService.setOnSucceeded(workerStateEvent -> {
startupService.cancel();
@ -281,4 +287,17 @@ public class WhirlpoolServices {
whirlpool.refreshUtxos();
}
}
@Subscribe
public void whirlpoolIndexHighFrequency(WhirlpoolIndexHighFrequencyEvent event) {
Whirlpool whirlpool = getWhirlpool(event.getWallet());
if(whirlpool != null && whirlpool.isStarted() && !whirlpool.isStopping()) {
log.warn("Rapidly increasing address index detected, temporarily disconnecting " + event.getWallet().getMasterName() + " from Whirlpool");
Platform.runLater(() -> {
EventManager.get().post(new StatusEvent("Error communicating with Whirlpool, will retry soon..."));
whirlpool.setStartupServiceDelay(Duration.minutes(5));
stopWhirlpool(whirlpool, false);
});
}
}
}

View file

@ -8,12 +8,17 @@ import com.sparrowwallet.sparrow.AppServices;
import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.event.WalletGapLimitChangedEvent;
import com.sparrowwallet.sparrow.event.WalletMixConfigChangedEvent;
import com.sparrowwallet.sparrow.event.WhirlpoolIndexHighFrequencyEvent;
public class SparrowIndexHandler extends AbstractIndexHandler {
private final Wallet wallet;
private final WalletNode walletNode;
private final int defaultValue;
private static final long PERIOD = 1000 * 60 * 10L; //Period of 10 minutes
private long periodStart;
private int periodCount;
public SparrowIndexHandler(Wallet wallet, WalletNode walletNode) {
this(wallet, walletNode, 0);
}
@ -77,6 +82,20 @@ public class SparrowIndexHandler extends AbstractIndexHandler {
if(index > highestUsedIndex + existingGapLimit) {
wallet.setGapLimit(Math.max(wallet.getGapLimit(), index - highestUsedIndex));
EventManager.get().post(new WalletGapLimitChangedEvent(getWalletId(), wallet, existingGapLimit));
checkFrequency();
}
}
private void checkFrequency() {
if(periodStart > 0 && System.currentTimeMillis() - periodStart < PERIOD) {
periodCount++;
} else {
periodStart = System.currentTimeMillis();
periodCount = 0;
}
if(periodCount >= Wallet.DEFAULT_LOOKAHEAD) {
EventManager.get().post(new WhirlpoolIndexHighFrequencyEvent(wallet));
}
}