Browse Source

add dust attack warning to utxos tab where small value txes are received on used addresses

terminal
Craig Raw 3 years ago
parent
commit
c0ca74ce6a
  1. 15
      src/main/java/com/sparrowwallet/sparrow/control/AddressCell.java
  2. 6
      src/main/java/com/sparrowwallet/sparrow/io/Config.java
  3. 18
      src/main/java/com/sparrowwallet/sparrow/wallet/UtxoEntry.java
  4. 18
      src/main/java/com/sparrowwallet/sparrow/wallet/WalletUtxosEntry.java
  5. 4
      src/main/resources/com/sparrowwallet/sparrow/wallet/wallet.css

15
src/main/java/com/sparrowwallet/sparrow/control/AddressCell.java

@ -37,11 +37,13 @@ public class AddressCell extends TreeTableCell<Entry, UtxoEntry.AddressStatus> {
setContextMenu(new EntryCell.AddressContextMenu(address, utxoEntry.getOutputDescriptor(), new NodeEntry(utxoEntry.getWallet(), utxoEntry.getNode())));
Tooltip tooltip = new Tooltip();
tooltip.setShowDelay(Duration.millis(250));
tooltip.setText(getTooltipText(utxoEntry, addressStatus.isDuplicate()));
tooltip.setText(getTooltipText(utxoEntry, addressStatus.isDuplicate(), addressStatus.isDustAttack()));
setTooltip(tooltip);
if(addressStatus.isDuplicate()) {
setGraphic(getDuplicateGlyph());
} else if(addressStatus.isDustAttack()) {
setGraphic(getDustAttackGlyph());
} else {
setGraphic(null);
}
@ -49,9 +51,9 @@ public class AddressCell extends TreeTableCell<Entry, UtxoEntry.AddressStatus> {
}
}
private String getTooltipText(UtxoEntry utxoEntry, boolean duplicate) {
private String getTooltipText(UtxoEntry utxoEntry, boolean duplicate, boolean dustAttack) {
return (utxoEntry.getNode().getWallet().isNested() ? utxoEntry.getNode().getWallet().getDisplayName() + " " : "" ) +
utxoEntry.getNode().toString() + (duplicate ? " (Duplicate address)" : "");
utxoEntry.getNode().toString() + (duplicate ? " (Duplicate address)" : (dustAttack ? " (Possible dust attack)" : ""));
}
public static Glyph getDuplicateGlyph() {
@ -60,4 +62,11 @@ public class AddressCell extends TreeTableCell<Entry, UtxoEntry.AddressStatus> {
duplicateGlyph.setFontSize(12);
return duplicateGlyph;
}
public static Glyph getDustAttackGlyph() {
Glyph dustAttackGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.EXCLAMATION_TRIANGLE);
dustAttackGlyph.getStyleClass().add("dust-attack-warning");
dustAttackGlyph.setFontSize(12);
return dustAttackGlyph;
}
}

6
src/main/java/com/sparrowwallet/sparrow/io/Config.java

@ -18,6 +18,7 @@ import java.util.stream.Collectors;
import static com.sparrowwallet.sparrow.AppServices.ENUMERATE_HW_PERIOD_SECS;
import static com.sparrowwallet.sparrow.net.PagedBatchRequestBuilder.DEFAULT_PAGE_SIZE;
import static com.sparrowwallet.sparrow.net.TcpTransport.DEFAULT_MAX_TIMEOUT;
import static com.sparrowwallet.sparrow.wallet.WalletUtxosEntry.DUST_ATTACK_THRESHOLD_SATS;
public class Config {
private static final Logger log = LoggerFactory.getLogger(Config.class);
@ -45,6 +46,7 @@ public class Config {
private boolean preventSleep = false;
private List<File> recentWalletFiles;
private Integer keyDerivationPeriod;
private long dustAttackThreshold = DUST_ATTACK_THRESHOLD_SATS;
private File hwi;
private int enumerateHwPeriod = ENUMERATE_HW_PERIOD_SECS;
private Boolean hdCapture;
@ -302,6 +304,10 @@ public class Config {
flush();
}
public long getDustAttackThreshold() {
return dustAttackThreshold;
}
public File getHwi() {
return hwi;
}

18
src/main/java/com/sparrowwallet/sparrow/wallet/UtxoEntry.java

@ -69,7 +69,13 @@ public class UtxoEntry extends HashIndexEntry {
private ObjectProperty<AddressStatus> addressStatusProperty;
public final void setDuplicateAddress(boolean value) {
addressStatusProperty().set(new AddressStatus(value));
AddressStatus addressStatus = addressStatusProperty().get();
addressStatusProperty().set(new AddressStatus(value, addressStatus.dustAttack));
}
public final void setDustAttack(boolean value) {
AddressStatus addressStatus = addressStatusProperty().get();
addressStatusProperty().set(new AddressStatus(addressStatus.duplicate, value));
}
public final boolean isDuplicateAddress() {
@ -78,7 +84,7 @@ public class UtxoEntry extends HashIndexEntry {
public final ObjectProperty<AddressStatus> addressStatusProperty() {
if(addressStatusProperty == null) {
addressStatusProperty = new SimpleObjectProperty<>(UtxoEntry.this, "addressStatus", new AddressStatus(false));
addressStatusProperty = new SimpleObjectProperty<>(UtxoEntry.this, "addressStatus", new AddressStatus(false, false));
}
return addressStatusProperty;
@ -86,9 +92,11 @@ public class UtxoEntry extends HashIndexEntry {
public class AddressStatus {
private final boolean duplicate;
private final boolean dustAttack;
public AddressStatus(boolean duplicate) {
public AddressStatus(boolean duplicate, boolean dustAttack) {
this.duplicate = duplicate;
this.dustAttack = dustAttack;
}
public UtxoEntry getUtxoEntry() {
@ -102,6 +110,10 @@ public class UtxoEntry extends HashIndexEntry {
public boolean isDuplicate() {
return duplicate;
}
public boolean isDustAttack() {
return dustAttack;
}
}
/**

18
src/main/java/com/sparrowwallet/sparrow/wallet/WalletUtxosEntry.java

@ -2,16 +2,21 @@ package com.sparrowwallet.sparrow.wallet;
import com.samourai.whirlpool.client.wallet.beans.MixProgress;
import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.drongo.wallet.WalletNode;
import com.sparrowwallet.sparrow.AppServices;
import com.sparrowwallet.sparrow.io.Config;
import com.sparrowwallet.sparrow.whirlpool.Whirlpool;
import java.util.*;
import java.util.stream.Collectors;
public class WalletUtxosEntry extends Entry {
public static final int DUST_ATTACK_THRESHOLD_SATS = 1000;
public WalletUtxosEntry(Wallet wallet) {
super(wallet, wallet.getName(), wallet.getWalletUtxos().entrySet().stream().map(entry -> new UtxoEntry(entry.getValue().getWallet(), entry.getKey(), HashIndexEntry.Type.OUTPUT, entry.getValue())).collect(Collectors.toList()));
calculateDuplicates();
calculateDust();
updateMixProgress();
}
@ -48,6 +53,18 @@ public class WalletUtxosEntry extends Entry {
}
}
protected void calculateDust() {
long dustAttackThreshold = Config.get().getDustAttackThreshold();
Set<WalletNode> duplicateNodes = getWallet().getWalletTxos().values().stream()
.collect(Collectors.groupingBy(e -> e, Collectors.counting()))
.entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toSet());
for(Entry entry : getChildren()) {
UtxoEntry utxoEntry = (UtxoEntry) entry;
utxoEntry.setDustAttack(utxoEntry.getValue() <= dustAttackThreshold && duplicateNodes.contains(utxoEntry.getNode()));
}
}
public void updateMixProgress() {
Whirlpool whirlpool = AppServices.getWhirlpoolServices().getWhirlpool(getWallet());
if(whirlpool != null) {
@ -74,6 +91,7 @@ public class WalletUtxosEntry extends Entry {
getChildren().removeAll(entriesRemoved);
calculateDuplicates();
calculateDust();
updateMixProgress();
}

4
src/main/resources/com/sparrowwallet/sparrow/wallet/wallet.css

@ -123,6 +123,10 @@
-fx-text-fill: rgb(202, 18, 67);
}
.dust-attack-warning {
-fx-text-fill: rgb(238, 210, 2);
}
.unused-check {
-fx-text-fill: #50a14f;
}

Loading…
Cancel
Save