mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 05:06:45 +00:00
fixes for encrypted whirlpool wallets and other issues
This commit is contained in:
parent
f30c00ba8f
commit
aa10bcfe1a
17 changed files with 142 additions and 69 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
||||||
Subproject commit 7ac4bce14f04163c57b94e34945b5e4a1bf79eb6
|
Subproject commit 71b5778226ef22881240143425325525c1a98d06
|
|
@ -1229,6 +1229,8 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EventManager.get().post(new WalletOpenedEvent(storage, wallet));
|
||||||
}
|
}
|
||||||
|
|
||||||
public WalletForm addWalletSubTab(TabPane subTabs, Storage storage, Wallet wallet, Wallet backupWallet) {
|
public WalletForm addWalletSubTab(TabPane subTabs, Storage storage, Wallet wallet, Wallet backupWallet) {
|
||||||
|
|
|
@ -968,7 +968,10 @@ public class AppServices {
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void walletOpening(WalletOpeningEvent event) {
|
public void walletOpening(WalletOpeningEvent event) {
|
||||||
restartBwt(event.getWallet());
|
restartBwt(event.getWallet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void walletOpened(WalletOpenedEvent event) {
|
||||||
String walletId = event.getStorage().getWalletId(event.getWallet());
|
String walletId = event.getStorage().getWalletId(event.getWallet());
|
||||||
Whirlpool whirlpool = whirlpoolMap.get(walletId);
|
Whirlpool whirlpool = whirlpoolMap.get(walletId);
|
||||||
if(whirlpool != null && !whirlpool.isStarted() && isConnected()) {
|
if(whirlpool != null && !whirlpool.isStarted() && isConnected()) {
|
||||||
|
|
|
@ -42,7 +42,13 @@ public class MainApp extends Application {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() throws Exception {
|
public void init() throws Exception {
|
||||||
Thread.setDefaultUncaughtExceptionHandler((t, e) -> LoggerFactory.getLogger(MainApp.class).error("Exception in thread \"" + t.getName() + "\"", e));
|
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
|
||||||
|
if(e instanceof IndexOutOfBoundsException && Arrays.stream(e.getStackTrace()).anyMatch(element -> element.getClassName().equals("javafx.scene.chart.BarChart"))) {
|
||||||
|
LoggerFactory.getLogger(MainApp.class).debug("Exception in thread \"" + t.getName() + "\"", e);;
|
||||||
|
} else {
|
||||||
|
LoggerFactory.getLogger(MainApp.class).error("Exception in thread \"" + t.getName() + "\"", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
super.init();
|
super.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,10 @@ public class HelpLabel extends Label {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Glyph getHelpGlyph() {
|
private static Glyph getHelpGlyph() {
|
||||||
Glyph lockGlyph = new Glyph("Font Awesome 5 Free Solid", FontAwesome5.Glyph.QUESTION_CIRCLE);
|
Glyph glyph = new Glyph("Font Awesome 5 Free Solid", FontAwesome5.Glyph.QUESTION_CIRCLE);
|
||||||
lockGlyph.getStyleClass().add("help-icon");
|
glyph.getStyleClass().add("help-icon");
|
||||||
lockGlyph.setFontSize(12);
|
glyph.setFontSize(11);
|
||||||
return lockGlyph;
|
return glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final StringProperty helpTextProperty() {
|
public final StringProperty helpTextProperty() {
|
||||||
|
|
|
@ -101,7 +101,9 @@ public class UtxosTreeTable extends CoinTreeTable {
|
||||||
|
|
||||||
public void updateHistory(List<WalletNode> updatedNodes) {
|
public void updateHistory(List<WalletNode> updatedNodes) {
|
||||||
//Utxo entries should have already been updated, so only a resort required
|
//Utxo entries should have already been updated, so only a resort required
|
||||||
sort();
|
if(!getRoot().getChildren().isEmpty()) {
|
||||||
|
sort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLabel(Entry entry) {
|
public void updateLabel(Entry entry) {
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.sparrow.io.Storage;
|
||||||
|
|
||||||
|
public class WalletOpenedEvent {
|
||||||
|
private final Storage storage;
|
||||||
|
private final Wallet wallet;
|
||||||
|
|
||||||
|
public WalletOpenedEvent(Storage storage, Wallet wallet) {
|
||||||
|
this.storage = storage;
|
||||||
|
this.wallet = wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Storage getStorage() {
|
||||||
|
return storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Wallet getWallet() {
|
||||||
|
return wallet;
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,7 @@ public class FontAwesome5 extends GlyphFont {
|
||||||
HAND_HOLDING_MEDICAL('\ue05c'),
|
HAND_HOLDING_MEDICAL('\ue05c'),
|
||||||
HAND_HOLDING_WATER('\uf4c1'),
|
HAND_HOLDING_WATER('\uf4c1'),
|
||||||
HISTORY('\uf1da'),
|
HISTORY('\uf1da'),
|
||||||
|
INFO_CIRCLE('\uf05a'),
|
||||||
KEY('\uf084'),
|
KEY('\uf084'),
|
||||||
LAPTOP('\uf109'),
|
LAPTOP('\uf109'),
|
||||||
LOCK('\uf023'),
|
LOCK('\uf023'),
|
||||||
|
|
|
@ -128,7 +128,10 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
private ToggleButton privacyToggle;
|
private ToggleButton privacyToggle;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private HelpLabel privacyAnalysis;
|
private HelpLabel optimizationHelp;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label privacyAnalysis;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Button clearButton;
|
private Button clearButton;
|
||||||
|
@ -417,6 +420,9 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
});
|
});
|
||||||
setPreferredOptimizationStrategy();
|
setPreferredOptimizationStrategy();
|
||||||
updatePrivacyAnalysis(null);
|
updatePrivacyAnalysis(null);
|
||||||
|
optimizationHelp.managedProperty().bind(optimizationHelp.visibleProperty());
|
||||||
|
privacyAnalysis.managedProperty().bind(privacyAnalysis.visibleProperty());
|
||||||
|
optimizationHelp.visibleProperty().bind(privacyAnalysis.visibleProperty().not());
|
||||||
|
|
||||||
createButton.managedProperty().bind(createButton.visibleProperty());
|
createButton.managedProperty().bind(createButton.visibleProperty());
|
||||||
premixButton.managedProperty().bind(premixButton.visibleProperty());
|
premixButton.managedProperty().bind(premixButton.visibleProperty());
|
||||||
|
@ -971,11 +977,15 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
|
|
||||||
private void updatePrivacyAnalysis(WalletTransaction walletTransaction) {
|
private void updatePrivacyAnalysis(WalletTransaction walletTransaction) {
|
||||||
if(walletTransaction == null) {
|
if(walletTransaction == null) {
|
||||||
privacyAnalysis.setHelpText("Determines whether to optimize the transaction for low fees or greater privacy");
|
privacyAnalysis.setVisible(false);
|
||||||
privacyAnalysis.setHelpGraphic(null);
|
privacyAnalysis.setTooltip(null);
|
||||||
} else {
|
} else {
|
||||||
privacyAnalysis.setHelpText("");
|
privacyAnalysis.setVisible(true);
|
||||||
privacyAnalysis.setHelpGraphic(new PrivacyAnalysisTooltip(walletTransaction));
|
Tooltip tooltip = new Tooltip();
|
||||||
|
tooltip.setShowDelay(new Duration(50));
|
||||||
|
tooltip.setShowDuration(Duration.INDEFINITE);
|
||||||
|
tooltip.setGraphic(new PrivacyAnalysisTooltip(walletTransaction));
|
||||||
|
privacyAnalysis.setTooltip(tooltip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1012,6 +1022,9 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
validationSupport.setErrorDecorationEnabled(false);
|
validationSupport.setErrorDecorationEnabled(false);
|
||||||
|
|
||||||
setInputFieldsDisabled(false);
|
setInputFieldsDisabled(false);
|
||||||
|
|
||||||
|
premixButton.setVisible(false);
|
||||||
|
createButton.setDefaultButton(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UtxoSelector getUtxoSelector() {
|
public UtxoSelector getUtxoSelector() {
|
||||||
|
@ -1108,35 +1121,8 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Wallet copy = getWalletForm().getWallet().copy();
|
//The WhirlpoolWallet has already been configured for the tx0 preview
|
||||||
String walletId = walletForm.getWalletId();
|
|
||||||
|
|
||||||
if(copy.isEncrypted()) {
|
|
||||||
WalletPasswordDialog dlg = new WalletPasswordDialog(copy.getMasterName(), WalletPasswordDialog.PasswordRequirement.LOAD);
|
|
||||||
Optional<SecureString> password = dlg.showAndWait();
|
|
||||||
if(password.isPresent()) {
|
|
||||||
Storage.DecryptWalletService decryptWalletService = new Storage.DecryptWalletService(copy, password.get());
|
|
||||||
decryptWalletService.setOnSucceeded(workerStateEvent -> {
|
|
||||||
EventManager.get().post(new StorageEvent(walletId, TimedEvent.Action.END, "Done"));
|
|
||||||
Wallet decryptedWallet = decryptWalletService.getValue();
|
|
||||||
broadcastPremixUnencrypted(decryptedWallet);
|
|
||||||
});
|
|
||||||
decryptWalletService.setOnFailed(workerStateEvent -> {
|
|
||||||
EventManager.get().post(new StorageEvent(walletId, TimedEvent.Action.END, "Failed"));
|
|
||||||
AppServices.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage());
|
|
||||||
});
|
|
||||||
EventManager.get().post(new StorageEvent(walletId, TimedEvent.Action.START, "Decrypting wallet..."));
|
|
||||||
decryptWalletService.start();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
broadcastPremixUnencrypted(copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void broadcastPremixUnencrypted(Wallet decryptedWallet) {
|
|
||||||
Whirlpool whirlpool = AppServices.get().getWhirlpool(getWalletForm().getWalletId());
|
Whirlpool whirlpool = AppServices.get().getWhirlpool(getWalletForm().getWalletId());
|
||||||
whirlpool.setScode(Config.get().getScode());
|
|
||||||
whirlpool.setHDWallet(getWalletForm().getWalletId(), decryptedWallet);
|
|
||||||
Map<BlockTransactionHashIndex, WalletNode> utxos = walletTransactionProperty.get().getSelectedUtxos();
|
Map<BlockTransactionHashIndex, WalletNode> utxos = walletTransactionProperty.get().getSelectedUtxos();
|
||||||
Whirlpool.Tx0BroadcastService tx0BroadcastService = new Whirlpool.Tx0BroadcastService(whirlpool, whirlpoolProperty.get(), utxos.keySet());
|
Whirlpool.Tx0BroadcastService tx0BroadcastService = new Whirlpool.Tx0BroadcastService(whirlpool, whirlpoolProperty.get(), utxos.keySet());
|
||||||
tx0BroadcastService.setOnRunning(workerStateEvent -> {
|
tx0BroadcastService.setOnRunning(workerStateEvent -> {
|
||||||
|
@ -1146,12 +1132,10 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
tx0BroadcastService.setOnSucceeded(workerStateEvent -> {
|
tx0BroadcastService.setOnSucceeded(workerStateEvent -> {
|
||||||
premixButton.setDisable(false);
|
premixButton.setDisable(false);
|
||||||
Sha256Hash txid = tx0BroadcastService.getValue();
|
Sha256Hash txid = tx0BroadcastService.getValue();
|
||||||
decryptedWallet.clearPrivate();
|
|
||||||
clear(null);
|
clear(null);
|
||||||
});
|
});
|
||||||
tx0BroadcastService.setOnFailed(workerStateEvent -> {
|
tx0BroadcastService.setOnFailed(workerStateEvent -> {
|
||||||
premixButton.setDisable(false);
|
premixButton.setDisable(false);
|
||||||
decryptedWallet.clearPrivate();
|
|
||||||
Throwable exception = workerStateEvent.getSource().getException();
|
Throwable exception = workerStateEvent.getSource().getException();
|
||||||
while(exception.getCause() != null) {
|
while(exception.getCause() != null) {
|
||||||
exception = exception.getCause();
|
exception = exception.getCause();
|
||||||
|
|
|
@ -6,8 +6,10 @@ import com.samourai.whirlpool.client.tx0.Tx0Preview;
|
||||||
import com.sparrowwallet.drongo.BitcoinUnit;
|
import com.sparrowwallet.drongo.BitcoinUnit;
|
||||||
import com.sparrowwallet.drongo.KeyPurpose;
|
import com.sparrowwallet.drongo.KeyPurpose;
|
||||||
import com.sparrowwallet.drongo.Network;
|
import com.sparrowwallet.drongo.Network;
|
||||||
|
import com.sparrowwallet.drongo.SecureString;
|
||||||
import com.sparrowwallet.drongo.address.Address;
|
import com.sparrowwallet.drongo.address.Address;
|
||||||
import com.sparrowwallet.drongo.address.InvalidAddressException;
|
import com.sparrowwallet.drongo.address.InvalidAddressException;
|
||||||
|
import com.sparrowwallet.drongo.crypto.*;
|
||||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||||
import com.sparrowwallet.drongo.wallet.*;
|
import com.sparrowwallet.drongo.wallet.*;
|
||||||
import com.sparrowwallet.sparrow.AppServices;
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
|
@ -15,6 +17,7 @@ import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.control.*;
|
import com.sparrowwallet.sparrow.control.*;
|
||||||
import com.sparrowwallet.sparrow.event.*;
|
import com.sparrowwallet.sparrow.event.*;
|
||||||
import com.sparrowwallet.sparrow.io.Config;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
|
import com.sparrowwallet.sparrow.io.Storage;
|
||||||
import com.sparrowwallet.sparrow.whirlpool.Whirlpool;
|
import com.sparrowwallet.sparrow.whirlpool.Whirlpool;
|
||||||
import com.sparrowwallet.sparrow.whirlpool.WhirlpoolDialog;
|
import com.sparrowwallet.sparrow.whirlpool.WhirlpoolDialog;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
@ -160,17 +163,70 @@ public class UtxosController extends WalletFormController implements Initializab
|
||||||
List<UtxoEntry> selectedEntries = getSelectedUtxos();
|
List<UtxoEntry> selectedEntries = getSelectedUtxos();
|
||||||
WhirlpoolDialog whirlpoolDialog = new WhirlpoolDialog(getWalletForm().getWalletId(), getWalletForm().getWallet(), selectedEntries);
|
WhirlpoolDialog whirlpoolDialog = new WhirlpoolDialog(getWalletForm().getWalletId(), getWalletForm().getWallet(), selectedEntries);
|
||||||
Optional<Tx0Preview> optTx0Preview = whirlpoolDialog.showAndWait();
|
Optional<Tx0Preview> optTx0Preview = whirlpoolDialog.showAndWait();
|
||||||
optTx0Preview.ifPresent(tx0Preview -> previewPremixTransaction(getWalletForm().getWallet(), tx0Preview, selectedEntries));
|
optTx0Preview.ifPresent(tx0Preview -> previewPremix(tx0Preview, selectedEntries));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void previewPremixTransaction(Wallet wallet, Tx0Preview tx0Preview, List<UtxoEntry> utxoEntries) {
|
public void previewPremix(Tx0Preview tx0Preview, List<UtxoEntry> utxoEntries) {
|
||||||
|
Wallet wallet = getWalletForm().getWallet();
|
||||||
|
String walletId = walletForm.getWalletId();
|
||||||
|
|
||||||
|
if(!wallet.isWhirlpoolMasterWallet() && wallet.isEncrypted()) {
|
||||||
|
WalletPasswordDialog dlg = new WalletPasswordDialog(wallet.getMasterName(), WalletPasswordDialog.PasswordRequirement.LOAD);
|
||||||
|
Optional<SecureString> password = dlg.showAndWait();
|
||||||
|
if(password.isPresent()) {
|
||||||
|
Storage.KeyDerivationService keyDerivationService = new Storage.KeyDerivationService(walletForm.getStorage(), password.get());
|
||||||
|
keyDerivationService.setOnSucceeded(workerStateEvent -> {
|
||||||
|
EventManager.get().post(new StorageEvent(walletId, TimedEvent.Action.END, "Done"));
|
||||||
|
ECKey encryptionFullKey = keyDerivationService.getValue();
|
||||||
|
Key key = new Key(encryptionFullKey.getPrivKeyBytes(), walletForm.getStorage().getKeyDeriver().getSalt(), EncryptionType.Deriver.ARGON2);
|
||||||
|
wallet.decrypt(key);
|
||||||
|
|
||||||
|
try {
|
||||||
|
prepareWhirlpoolWallet(wallet);
|
||||||
|
} finally {
|
||||||
|
wallet.encrypt(key);
|
||||||
|
for(Wallet childWallet : wallet.getChildWallets()) {
|
||||||
|
if(!childWallet.isEncrypted()) {
|
||||||
|
childWallet.encrypt(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
key.clear();
|
||||||
|
encryptionFullKey.clear();
|
||||||
|
password.get().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
previewPremix(wallet, tx0Preview, utxoEntries);
|
||||||
|
});
|
||||||
|
keyDerivationService.setOnFailed(workerStateEvent -> {
|
||||||
|
EventManager.get().post(new StorageEvent(walletId, TimedEvent.Action.END, "Failed"));
|
||||||
|
AppServices.showErrorDialog("Incorrect Password", keyDerivationService.getException().getMessage());
|
||||||
|
});
|
||||||
|
EventManager.get().post(new StorageEvent(walletId, TimedEvent.Action.START, "Decrypting wallet..."));
|
||||||
|
keyDerivationService.start();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(!wallet.isWhirlpoolMasterWallet()) {
|
||||||
|
prepareWhirlpoolWallet(wallet);
|
||||||
|
}
|
||||||
|
|
||||||
|
previewPremix(wallet, tx0Preview, utxoEntries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareWhirlpoolWallet(Wallet decryptedWallet) {
|
||||||
|
Whirlpool whirlpool = AppServices.get().getWhirlpool(getWalletForm().getWalletId());
|
||||||
|
whirlpool.setScode(Config.get().getScode());
|
||||||
|
whirlpool.setHDWallet(getWalletForm().getWalletId(), decryptedWallet);
|
||||||
|
|
||||||
for(StandardAccount whirlpoolAccount : StandardAccount.WHIRLPOOL_ACCOUNTS) {
|
for(StandardAccount whirlpoolAccount : StandardAccount.WHIRLPOOL_ACCOUNTS) {
|
||||||
if(wallet.getChildWallet(whirlpoolAccount) == null) {
|
if(decryptedWallet.getChildWallet(whirlpoolAccount) == null) {
|
||||||
Wallet childWallet = wallet.addChildWallet(whirlpoolAccount);
|
Wallet childWallet = decryptedWallet.addChildWallet(whirlpoolAccount);
|
||||||
EventManager.get().post(new ChildWalletAddedEvent(getWalletForm().getStorage(), wallet, childWallet));
|
EventManager.get().post(new ChildWalletAddedEvent(getWalletForm().getStorage(), decryptedWallet, childWallet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void previewPremix(Wallet wallet, Tx0Preview tx0Preview, List<UtxoEntry> utxoEntries) {
|
||||||
Wallet premixWallet = wallet.getChildWallet(StandardAccount.WHIRLPOOL_PREMIX);
|
Wallet premixWallet = wallet.getChildWallet(StandardAccount.WHIRLPOOL_PREMIX);
|
||||||
Wallet badbankWallet = wallet.getChildWallet(StandardAccount.WHIRLPOOL_BADBANK);
|
Wallet badbankWallet = wallet.getChildWallet(StandardAccount.WHIRLPOOL_BADBANK);
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ public class Whirlpool {
|
||||||
private HD_Wallet hdWallet;
|
private HD_Wallet hdWallet;
|
||||||
private String walletId;
|
private String walletId;
|
||||||
|
|
||||||
private BooleanProperty mixingProperty = new SimpleBooleanProperty(false);
|
private final BooleanProperty mixingProperty = new SimpleBooleanProperty(false);
|
||||||
|
|
||||||
public Whirlpool(Network network, HostAndPort torProxy, String sCode) {
|
public Whirlpool(Network network, HostAndPort torProxy, String sCode) {
|
||||||
this.torProxy = torProxy;
|
this.torProxy = torProxy;
|
||||||
|
@ -134,14 +134,8 @@ public class Whirlpool {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tx0ParamService getTx0ParamService() {
|
private Tx0ParamService getTx0ParamService() {
|
||||||
try {
|
SparrowMinerFeeSupplier minerFeeSupplier = SparrowMinerFeeSupplier.getInstance();
|
||||||
SparrowMinerFeeSupplier minerFeeSupplier = SparrowMinerFeeSupplier.getInstance();
|
return new Tx0ParamService(minerFeeSupplier, config);
|
||||||
return new Tx0ParamService(minerFeeSupplier, config);
|
|
||||||
} catch(Exception e) {
|
|
||||||
log.error("Error fetching miner fees", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHDWallet(String walletId, Wallet wallet) {
|
public void setHDWallet(String walletId, Wallet wallet) {
|
||||||
|
|
|
@ -9,8 +9,8 @@ import com.samourai.whirlpool.client.wallet.data.walletState.WalletStateSupplier
|
||||||
import com.sparrowwallet.sparrow.whirlpool.dataSource.SparrowWalletStateSupplier;
|
import com.sparrowwallet.sparrow.whirlpool.dataSource.SparrowWalletStateSupplier;
|
||||||
|
|
||||||
public class SparrowDataPersister implements DataPersister {
|
public class SparrowDataPersister implements DataPersister {
|
||||||
private WalletStateSupplier walletStateSupplier;
|
private final WalletStateSupplier walletStateSupplier;
|
||||||
private UtxoConfigSupplier utxoConfigSupplier;
|
private final UtxoConfigSupplier utxoConfigSupplier;
|
||||||
|
|
||||||
public SparrowDataPersister(WhirlpoolWallet whirlpoolWallet) throws Exception {
|
public SparrowDataPersister(WhirlpoolWallet whirlpoolWallet) throws Exception {
|
||||||
WhirlpoolWalletConfig config = whirlpoolWallet.getConfig();
|
WhirlpoolWalletConfig config = whirlpoolWallet.getConfig();
|
||||||
|
|
|
@ -4,8 +4,8 @@ import com.samourai.wallet.client.indexHandler.AbstractIndexHandler;
|
||||||
import com.sparrowwallet.drongo.wallet.WalletNode;
|
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||||
|
|
||||||
public class SparrowIndexHandler extends AbstractIndexHandler {
|
public class SparrowIndexHandler extends AbstractIndexHandler {
|
||||||
private WalletNode walletNode;
|
private final WalletNode walletNode;
|
||||||
private int defaultValue;
|
private final int defaultValue;
|
||||||
|
|
||||||
public SparrowIndexHandler(WalletNode walletNode) {
|
public SparrowIndexHandler(WalletNode walletNode) {
|
||||||
this(walletNode, 0);
|
this(walletNode, 0);
|
||||||
|
@ -19,8 +19,7 @@ public class SparrowIndexHandler extends AbstractIndexHandler {
|
||||||
@Override
|
@Override
|
||||||
public synchronized int get() {
|
public synchronized int get() {
|
||||||
Integer currentIndex = walletNode.getHighestUsedIndex();
|
Integer currentIndex = walletNode.getHighestUsedIndex();
|
||||||
int nextIndex = currentIndex == null ? defaultValue : currentIndex + 1;
|
return currentIndex == null ? defaultValue : currentIndex + 1;
|
||||||
return nextIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,13 +15,13 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SparrowWalletStateSupplier implements WalletStateSupplier {
|
public class SparrowWalletStateSupplier implements WalletStateSupplier {
|
||||||
private String walletId;
|
private final String walletId;
|
||||||
private Map<String, IIndexHandler> indexHandlerWallets;
|
private final Map<String, IIndexHandler> indexHandlerWallets;
|
||||||
// private int externalIndexDefault;
|
// private int externalIndexDefault;
|
||||||
|
|
||||||
public SparrowWalletStateSupplier(String walletId, ExternalDestination externalDestination) throws Exception {
|
public SparrowWalletStateSupplier(String walletId, ExternalDestination externalDestination) throws Exception {
|
||||||
this.walletId = walletId;
|
this.walletId = walletId;
|
||||||
this.indexHandlerWallets = new LinkedHashMap();
|
this.indexHandlerWallets = new LinkedHashMap<>();
|
||||||
// this.externalIndexDefault = externalDestination != null ? externalDestination.getStartIndex() : 0;
|
// this.externalIndexDefault = externalDestination != null ? externalDestination.getStartIndex() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
drop table if exists utxoMixData;
|
|
||||||
create table utxoMixData (id identity not null, hash binary(32) not null, mixesDone integer not null default 0, expired bigint, wallet bigint not null);
|
create table utxoMixData (id identity not null, hash binary(32) not null, mixesDone integer not null default 0, expired bigint, wallet bigint not null);
|
|
@ -176,7 +176,12 @@
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
</buttons>
|
</buttons>
|
||||||
</SegmentedButton>
|
</SegmentedButton>
|
||||||
<HelpLabel fx:id="privacyAnalysis" />
|
<HelpLabel fx:id="optimizationHelp" helpText="Determines whether to optimize the transaction for low fees or greater privacy" />
|
||||||
|
<Label fx:id="privacyAnalysis" graphicTextGap="5" text="Analysis..." styleClass="help-label">
|
||||||
|
<graphic>
|
||||||
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="11" icon="INFO_CIRCLE" />
|
||||||
|
</graphic>
|
||||||
|
</Label>
|
||||||
</HBox>
|
</HBox>
|
||||||
<HBox AnchorPane.rightAnchor="10">
|
<HBox AnchorPane.rightAnchor="10">
|
||||||
<Button fx:id="clearButton" text="Clear" cancelButton="true" onAction="#clear" />
|
<Button fx:id="clearButton" text="Clear" cancelButton="true" onAction="#clear" />
|
||||||
|
|
|
@ -100,7 +100,7 @@
|
||||||
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="RANDOM" styleClass="title-icon" />
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="RANDOM" styleClass="title-icon" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</Label>
|
</Label>
|
||||||
<Label text="Choose which pool to use below. You will then be able to preview your premix transaction." wrapText="true" styleClass="content-text" />
|
<Label text="Choose which pool to use below. You will then be able to preview your premix transaction. Your wallet password may be required to add the premix wallet." wrapText="true" styleClass="content-text" />
|
||||||
<HBox spacing="20" alignment="CENTER_LEFT">
|
<HBox spacing="20" alignment="CENTER_LEFT">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets top="20" bottom="5" />
|
<Insets top="20" bottom="5" />
|
||||||
|
|
Loading…
Reference in a new issue