mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
support using stored mix indexes to avoid resending a utxo to the coordinator
This commit is contained in:
parent
e8af7c70bd
commit
6e6111b47c
12 changed files with 94 additions and 37 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
|||
Subproject commit b4f4cc8726de3e7b5f875816affe1e0f78f2fa25
|
||||
Subproject commit 94d22b875868760a95222e0254ec10b59c71e04f
|
|
@ -1721,7 +1721,7 @@ public class AppController implements Initializable {
|
|||
text += event.getValueAsText(event.getTotalValue());
|
||||
} else if(blockTransactions.size() > 1) {
|
||||
if(event.getTotalBlockchainValue() > 0 && event.getTotalMempoolValue() > 0) {
|
||||
text = "New transactions: " + event.getValueAsText(event.getTotalValue()) + " total (" + event.getValueAsText(event.getTotalMempoolValue()) + " in mempool)";
|
||||
text = "New transactions: " + event.getValueAsText(event.getTotalValue()) + " total";
|
||||
} else if(event.getTotalMempoolValue() > 0) {
|
||||
text = "New mempool transactions: " + event.getValueAsText(event.getTotalMempoolValue()) + " total";
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
|
||||
public class WalletMasterMixConfigChangedEvent extends WalletMixConfigChangedEvent {
|
||||
public WalletMasterMixConfigChangedEvent(Wallet wallet) {
|
||||
super(wallet.isMasterWallet() ? wallet : wallet.getMasterWallet());
|
||||
}
|
||||
}
|
|
@ -4,6 +4,6 @@ import com.sparrowwallet.drongo.wallet.Wallet;
|
|||
|
||||
public class WalletMixConfigChangedEvent extends WalletChangedEvent {
|
||||
public WalletMixConfigChangedEvent(Wallet wallet) {
|
||||
super(wallet.isMasterWallet() ? wallet : wallet.getMasterWallet());
|
||||
super(wallet);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,16 +8,16 @@ import org.jdbi.v3.sqlobject.statement.SqlQuery;
|
|||
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
|
||||
|
||||
public interface MixConfigDao {
|
||||
@SqlQuery("select id, scode, mixOnStartup, mixToWalletFile, mixToWalletName, minMixes from mixConfig where wallet = ?")
|
||||
@SqlQuery("select id, scode, mixOnStartup, mixToWalletFile, mixToWalletName, minMixes, receiveIndex, changeIndex from mixConfig where wallet = ?")
|
||||
@RegisterRowMapper(MixConfigMapper.class)
|
||||
MixConfig getForWalletId(Long id);
|
||||
|
||||
@SqlUpdate("insert into mixConfig (scode, mixOnStartup, mixToWalletFile, mixToWalletName, minMixes, wallet) values (?, ?, ?, ?, ?, ?)")
|
||||
@SqlUpdate("insert into mixConfig (scode, mixOnStartup, mixToWalletFile, mixToWalletName, minMixes, receiveIndex, changeIndex, wallet) values (?, ?, ?, ?, ?, ?, ?, ?)")
|
||||
@GetGeneratedKeys("id")
|
||||
long insertMixConfig(String scode, Boolean mixOnStartup, String mixToWalletFile, String mixToWalletName, Integer minMixes, long wallet);
|
||||
long insertMixConfig(String scode, Boolean mixOnStartup, String mixToWalletFile, String mixToWalletName, Integer minMixes, int receiveIndex, int changeIndex, long wallet);
|
||||
|
||||
@SqlUpdate("update mixConfig set scode = ?, mixOnStartup = ?, mixToWalletFile = ?, mixToWalletName = ?, minMixes = ?, wallet = ? where id = ?")
|
||||
void updateMixConfig(String scode, Boolean mixOnStartup, String mixToWalletFile, String mixToWalletName, Integer minMixes, long wallet, long id);
|
||||
@SqlUpdate("update mixConfig set scode = ?, mixOnStartup = ?, mixToWalletFile = ?, mixToWalletName = ?, minMixes = ?, receiveIndex = ?, changeIndex = ?, wallet = ? where id = ?")
|
||||
void updateMixConfig(String scode, Boolean mixOnStartup, String mixToWalletFile, String mixToWalletName, Integer minMixes, int receiveIndex, int changeIndex, long wallet, long id);
|
||||
|
||||
default void addMixConfig(Wallet wallet) {
|
||||
if(wallet.getMixConfig() != null) {
|
||||
|
@ -32,10 +32,10 @@ public interface MixConfigDao {
|
|||
}
|
||||
|
||||
if(mixConfig.getId() == null) {
|
||||
long id = insertMixConfig(mixConfig.getScode(), mixConfig.getMixOnStartup(), mixToWalletFile, mixConfig.getMixToWalletName(), mixConfig.getMinMixes(), wallet.getId());
|
||||
long id = insertMixConfig(mixConfig.getScode(), mixConfig.getMixOnStartup(), mixToWalletFile, mixConfig.getMixToWalletName(), mixConfig.getMinMixes(), mixConfig.getReceiveIndex(), mixConfig.getChangeIndex(), wallet.getId());
|
||||
mixConfig.setId(id);
|
||||
} else {
|
||||
updateMixConfig(mixConfig.getScode(), mixConfig.getMixOnStartup(), mixToWalletFile, mixConfig.getMixToWalletName(), mixConfig.getMinMixes(), wallet.getId(), mixConfig.getId());
|
||||
updateMixConfig(mixConfig.getScode(), mixConfig.getMixOnStartup(), mixToWalletFile, mixConfig.getMixToWalletName(), mixConfig.getMinMixes(), mixConfig.getReceiveIndex(), mixConfig.getChangeIndex(), wallet.getId(), mixConfig.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ public class MixConfigMapper implements RowMapper<MixConfig> {
|
|||
minMixes = null;
|
||||
}
|
||||
|
||||
MixConfig mixConfig = new MixConfig(scode, mixOnStartup, mixToWalletFile == null ? null : new File(mixToWalletFile), mixToWalletName, minMixes);
|
||||
MixConfig mixConfig = new MixConfig(scode, mixOnStartup, mixToWalletFile == null ? null : new File(mixToWalletFile), mixToWalletName, minMixes, rs.getInt("receiveIndex"), rs.getInt("changeIndex"));
|
||||
mixConfig.setId(rs.getLong("id"));
|
||||
return mixConfig;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import com.sparrowwallet.drongo.wallet.StandardAccount;
|
|||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.sparrow.AppServices;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.event.WalletMixConfigChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.WalletMasterMixConfigChangedEvent;
|
||||
import com.sparrowwallet.sparrow.whirlpool.Whirlpool;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.fxml.FXML;
|
||||
|
@ -72,14 +72,14 @@ public class MixToController implements Initializable {
|
|||
mixConfig.setMixToWalletFile(AppServices.get().getOpenWallets().get(newValue).getWalletFile());
|
||||
}
|
||||
|
||||
EventManager.get().post(new WalletMixConfigChangedEvent(wallet));
|
||||
EventManager.get().post(new WalletMasterMixConfigChangedEvent(wallet));
|
||||
});
|
||||
|
||||
int initialMinMixes = mixConfig.getMinMixes() == null ? Whirlpool.DEFAULT_MIXTO_MIN_MIXES : mixConfig.getMinMixes();
|
||||
minMixes.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 10000, initialMinMixes));
|
||||
minMixes.valueProperty().addListener((observable, oldValue, newValue) -> {
|
||||
mixConfig.setMinMixes(newValue);
|
||||
EventManager.get().post(new WalletMixConfigChangedEvent(wallet));
|
||||
EventManager.get().post(new WalletMasterMixConfigChangedEvent(wallet));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -322,7 +322,7 @@ public class UtxosController extends WalletFormController implements Initializab
|
|||
}
|
||||
|
||||
getWalletForm().getWallet().getMasterMixConfig().setMixOnStartup(Boolean.TRUE);
|
||||
EventManager.get().post(new WalletMixConfigChangedEvent(getWalletForm().getWallet()));
|
||||
EventManager.get().post(new WalletMasterMixConfigChangedEvent(getWalletForm().getWallet()));
|
||||
}
|
||||
|
||||
public void stopMixing(ActionEvent event) {
|
||||
|
@ -343,7 +343,7 @@ public class UtxosController extends WalletFormController implements Initializab
|
|||
}
|
||||
|
||||
getWalletForm().getWallet().getMasterMixConfig().setMixOnStartup(Boolean.FALSE);
|
||||
EventManager.get().post(new WalletMixConfigChangedEvent(getWalletForm().getWallet()));
|
||||
EventManager.get().post(new WalletMasterMixConfigChangedEvent(getWalletForm().getWallet()));
|
||||
}
|
||||
|
||||
public void showMixToDialog(ActionEvent event) {
|
||||
|
@ -359,7 +359,7 @@ public class UtxosController extends WalletFormController implements Initializab
|
|||
} catch(NoSuchElementException e) {
|
||||
mixConfig.setMixToWalletName(null);
|
||||
mixConfig.setMixToWalletFile(null);
|
||||
EventManager.get().post(new WalletMixConfigChangedEvent(getWalletForm().getWallet()));
|
||||
EventManager.get().post(new WalletMasterMixConfigChangedEvent(getWalletForm().getWallet()));
|
||||
whirlpool.setMixToWallet(null, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.sparrowwallet.drongo.wallet.Wallet;
|
|||
import com.sparrowwallet.sparrow.AppServices;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.control.CoinLabel;
|
||||
import com.sparrowwallet.sparrow.event.WalletMixConfigChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.WalletMasterMixConfigChangedEvent;
|
||||
import com.sparrowwallet.sparrow.io.Config;
|
||||
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||
import com.sparrowwallet.sparrow.wallet.UtxoEntry;
|
||||
|
@ -95,9 +95,13 @@ public class WhirlpoolController {
|
|||
step4.setVisible(false);
|
||||
|
||||
scode.setText(mixConfig.getScode() == null ? "" : mixConfig.getScode());
|
||||
scode.setTextFormatter(new TextFormatter<>((change) -> {
|
||||
change.setText(change.getText().toUpperCase());
|
||||
return change;
|
||||
}));
|
||||
scode.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
mixConfig.setScode(newValue);
|
||||
EventManager.get().post(new WalletMixConfigChangedEvent(wallet));
|
||||
EventManager.get().post(new WalletMasterMixConfigChangedEvent(wallet));
|
||||
});
|
||||
|
||||
if(mixConfig.getScode() != null) {
|
||||
|
@ -232,7 +236,7 @@ public class WhirlpoolController {
|
|||
private void fetchTx0Preview(Pool pool) {
|
||||
if(mixConfig.getScode() == null) {
|
||||
mixConfig.setScode("");
|
||||
EventManager.get().post(new WalletMixConfigChangedEvent(wallet));
|
||||
EventManager.get().post(new WalletMasterMixConfigChangedEvent(wallet));
|
||||
}
|
||||
|
||||
Whirlpool whirlpool = AppServices.getWhirlpoolServices().getWhirlpool(walletId);
|
||||
|
|
|
@ -1,33 +1,70 @@
|
|||
package com.sparrowwallet.sparrow.whirlpool.dataSource;
|
||||
|
||||
import com.samourai.wallet.client.indexHandler.AbstractIndexHandler;
|
||||
import com.sparrowwallet.drongo.KeyPurpose;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.event.WalletMixConfigChangedEvent;
|
||||
|
||||
public class SparrowIndexHandler extends AbstractIndexHandler {
|
||||
private final Wallet wallet;
|
||||
private final WalletNode walletNode;
|
||||
private final int defaultValue;
|
||||
|
||||
public SparrowIndexHandler(WalletNode walletNode) {
|
||||
this(walletNode, 0);
|
||||
public SparrowIndexHandler(Wallet wallet, WalletNode walletNode) {
|
||||
this(wallet, walletNode, 0);
|
||||
}
|
||||
|
||||
public SparrowIndexHandler(WalletNode walletNode, int defaultValue) {
|
||||
public SparrowIndexHandler(Wallet wallet, WalletNode walletNode, int defaultValue) {
|
||||
this.wallet = wallet;
|
||||
this.walletNode = walletNode;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int get() {
|
||||
Integer currentIndex = walletNode.getHighestUsedIndex();
|
||||
return currentIndex == null ? defaultValue : currentIndex + 1;
|
||||
return Math.max(getCurrentIndex(), getStoredIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getAndIncrement() {
|
||||
return get();
|
||||
int index = get();
|
||||
set(index + 1);
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void set(int value) {
|
||||
setStoredIndex(value);
|
||||
}
|
||||
|
||||
private int getCurrentIndex() {
|
||||
Integer currentIndex = walletNode.getHighestUsedIndex();
|
||||
return currentIndex == null ? defaultValue : currentIndex + 1;
|
||||
}
|
||||
|
||||
private int getStoredIndex() {
|
||||
if(wallet.getMixConfig() != null) {
|
||||
if(walletNode.getKeyPurpose() == KeyPurpose.RECEIVE) {
|
||||
return wallet.getMixConfig().getReceiveIndex();
|
||||
} else if(walletNode.getKeyPurpose() == KeyPurpose.CHANGE) {
|
||||
return wallet.getMixConfig().getChangeIndex();
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private void setStoredIndex(int index) {
|
||||
if(wallet.getMixConfig() != null) {
|
||||
if(walletNode.getKeyPurpose() == KeyPurpose.RECEIVE) {
|
||||
wallet.getMixConfig().setReceiveIndex(index);
|
||||
} else if(walletNode.getKeyPurpose() == KeyPurpose.CHANGE) {
|
||||
wallet.getMixConfig().setChangeIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
EventManager.get().post(new WalletMixConfigChangedEvent(wallet));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.samourai.whirlpool.client.wallet.beans.WhirlpoolAccount;
|
|||
import com.samourai.whirlpool.client.wallet.data.walletState.WalletStateSupplier;
|
||||
import com.sparrowwallet.drongo.KeyPurpose;
|
||||
import com.sparrowwallet.drongo.crypto.ChildNumber;
|
||||
import com.sparrowwallet.drongo.wallet.MixConfig;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||
import com.sparrowwallet.sparrow.whirlpool.Whirlpool;
|
||||
|
@ -32,10 +33,21 @@ public class SparrowWalletStateSupplier implements WalletStateSupplier {
|
|||
String key = mapKey(whirlpoolAccount, addressType, chain);
|
||||
IIndexHandler indexHandler = indexHandlerWallets.get(key);
|
||||
if (indexHandler == null) {
|
||||
WalletNode walletNode = findWalletNode(whirlpoolAccount, addressType, chain);
|
||||
indexHandler = new SparrowIndexHandler(walletNode, 0);
|
||||
Wallet wallet = findWallet(whirlpoolAccount);
|
||||
KeyPurpose keyPurpose = (chain == Chain.RECEIVE ? KeyPurpose.RECEIVE : KeyPurpose.CHANGE);
|
||||
WalletNode walletNode = wallet.getNode(keyPurpose);
|
||||
|
||||
//Ensure mix config is present
|
||||
MixConfig mixConfig = wallet.getMixConfig();
|
||||
if(mixConfig == null) {
|
||||
mixConfig = new MixConfig();
|
||||
wallet.setMixConfig(mixConfig);
|
||||
}
|
||||
|
||||
indexHandler = new SparrowIndexHandler(wallet, walletNode, 0);
|
||||
indexHandlerWallets.put(key, indexHandler);
|
||||
}
|
||||
|
||||
return indexHandler;
|
||||
}
|
||||
|
||||
|
@ -53,7 +65,7 @@ public class SparrowWalletStateSupplier implements WalletStateSupplier {
|
|||
|
||||
KeyPurpose keyPurpose = KeyPurpose.fromChildNumber(new ChildNumber(externalDestination.getChain()));
|
||||
WalletNode externalNode = externalWallet.getNode(keyPurpose);
|
||||
externalIndexHandler = new SparrowIndexHandler(externalNode, externalDestination.getStartIndex());
|
||||
externalIndexHandler = new SparrowIndexHandler(externalWallet, externalNode, externalDestination.getStartIndex());
|
||||
}
|
||||
|
||||
return externalIndexHandler;
|
||||
|
@ -89,18 +101,13 @@ public class SparrowWalletStateSupplier implements WalletStateSupplier {
|
|||
return whirlpoolAccount.name()+"_"+addressType.getPurpose()+"_"+chain.getIndex();
|
||||
}
|
||||
|
||||
private WalletNode findWalletNode(WhirlpoolAccount whirlpoolAccount, AddressType addressType, Chain chain) {
|
||||
private Wallet findWallet(WhirlpoolAccount whirlpoolAccount) {
|
||||
Wallet wallet = getWallet();
|
||||
if(wallet == null) {
|
||||
throw new IllegalStateException("Can't find wallet with walletId " + walletId);
|
||||
}
|
||||
|
||||
// account
|
||||
Wallet childWallet = Whirlpool.getStandardAccountWallet(whirlpoolAccount, wallet);
|
||||
|
||||
// purpose
|
||||
KeyPurpose keyPurpose = chain == Chain.RECEIVE ? KeyPurpose.RECEIVE : KeyPurpose.CHANGE;
|
||||
return childWallet.getNode(keyPurpose);
|
||||
return Whirlpool.getStandardAccountWallet(whirlpoolAccount, wallet);
|
||||
}
|
||||
|
||||
private Wallet getWallet() {
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
create table mixConfig (id identity not null, scode varchar(255), mixOnStartup boolean, mixToWalletFile varchar(1024), mixToWalletName varchar(255), minMixes integer, wallet bigint not null);
|
||||
create table mixConfig (id identity not null, scode varchar(255), mixOnStartup boolean, mixToWalletFile varchar(1024), mixToWalletName varchar(255), minMixes integer, receiveIndex integer not null, changeIndex integer not null, 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);
|
Loading…
Reference in a new issue