avoid losing tx, address and txo labels when performing a full wallet refresh

This commit is contained in:
Craig Raw 2021-02-09 17:32:36 +02:00
parent 3ffb09c5e6
commit 11a0e3765b
5 changed files with 45 additions and 17 deletions

2
drongo

@ -1 +1 @@
Subproject commit 44b29b2b7b6cb849f645ce9db7af18691b438553 Subproject commit 3882a4b4bd9a738329bfffcaff72b477bb3a2d2f

View file

@ -84,6 +84,7 @@ public class CoinTreeTable extends TreeTableView<Entry> {
WalletBirthDateDialog dlg = new WalletBirthDateDialog(wallet.getBirthDate()); WalletBirthDateDialog dlg = new WalletBirthDateDialog(wallet.getBirthDate());
Optional<Date> optDate = dlg.showAndWait(); Optional<Date> optDate = dlg.showAndWait();
if(optDate.isPresent()) { if(optDate.isPresent()) {
Wallet pastWallet = wallet.copy();
wallet.setBirthDate(optDate.get()); wallet.setBirthDate(optDate.get());
Storage storage = AppServices.get().getOpenWallets().get(wallet); Storage storage = AppServices.get().getOpenWallets().get(wallet);
if(storage != null) { if(storage != null) {
@ -91,7 +92,7 @@ public class CoinTreeTable extends TreeTableView<Entry> {
EventManager.get().post(new WalletDataChangedEvent(wallet)); EventManager.get().post(new WalletDataChangedEvent(wallet));
//Trigger full wallet rescan //Trigger full wallet rescan
wallet.clearHistory(); wallet.clearHistory();
EventManager.get().post(new WalletSettingsChangedEvent(wallet, storage.getWalletFile())); EventManager.get().post(new WalletSettingsChangedEvent(wallet, pastWallet, storage.getWalletFile()));
} }
} }
}); });

View file

@ -12,13 +12,19 @@ import java.io.File;
* Note that all wallet detail controllers that share a WalletForm, and that class posts WalletNodesChangedEvent once it has cleared it's entry caches. * Note that all wallet detail controllers that share a WalletForm, and that class posts WalletNodesChangedEvent once it has cleared it's entry caches.
*/ */
public class WalletSettingsChangedEvent extends WalletChangedEvent { public class WalletSettingsChangedEvent extends WalletChangedEvent {
private final Wallet pastWallet;
private final File walletFile; private final File walletFile;
public WalletSettingsChangedEvent(Wallet wallet, File walletFile) { public WalletSettingsChangedEvent(Wallet wallet, Wallet pastWallet, File walletFile) {
super(wallet); super(wallet);
this.pastWallet = pastWallet;
this.walletFile = walletFile; this.walletFile = walletFile;
} }
public Wallet getPastWallet() {
return pastWallet;
}
public File getWalletFile() { public File getWalletFile() {
return walletFile; return walletFile;
} }

View file

@ -38,6 +38,8 @@ public class SettingsWalletForm extends WalletForm {
@Override @Override
public void saveAndRefresh() throws IOException { public void saveAndRefresh() throws IOException {
Wallet pastWallet = wallet.copy();
boolean refreshAll = isRefreshNecessary(wallet, walletCopy); boolean refreshAll = isRefreshNecessary(wallet, walletCopy);
if(refreshAll) { if(refreshAll) {
walletCopy.clearNodes(); walletCopy.clearNodes();
@ -47,7 +49,7 @@ public class SettingsWalletForm extends WalletForm {
save(); save();
if(refreshAll) { if(refreshAll) {
EventManager.get().post(new WalletSettingsChangedEvent(wallet, getWalletFile())); EventManager.get().post(new WalletSettingsChangedEvent(wallet, pastWallet, getWalletFile()));
} }
} }

View file

@ -2,6 +2,8 @@ package com.sparrowwallet.sparrow.wallet;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.KeyPurpose;
import com.sparrowwallet.drongo.protocol.Sha256Hash;
import com.sparrowwallet.drongo.wallet.BlockTransaction;
import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.drongo.wallet.WalletNode; import com.sparrowwallet.drongo.wallet.WalletNode;
import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.AppServices;
@ -32,7 +34,7 @@ public class WalletForm {
public WalletForm(Storage storage, Wallet currentWallet) { public WalletForm(Storage storage, Wallet currentWallet) {
this.storage = storage; this.storage = storage;
this.wallet = currentWallet; this.wallet = currentWallet;
refreshHistory(AppServices.getCurrentBlockHeight()); refreshHistory(AppServices.getCurrentBlockHeight(), null);
} }
public Wallet getWallet() { public Wallet getWallet() {
@ -60,27 +62,28 @@ public class WalletForm {
} }
public void saveAndRefresh() throws IOException { public void saveAndRefresh() throws IOException {
Wallet pastWallet = wallet.copy();
wallet.clearHistory(); wallet.clearHistory();
save(); save();
refreshHistory(AppServices.getCurrentBlockHeight()); refreshHistory(AppServices.getCurrentBlockHeight(), pastWallet);
} }
public void saveBackup() throws IOException { public void saveBackup() throws IOException {
storage.backupWallet(); storage.backupWallet();
} }
public void refreshHistory(Integer blockHeight) { public void refreshHistory(Integer blockHeight, Wallet pastWallet) {
refreshHistory(blockHeight, null); refreshHistory(blockHeight, pastWallet, null);
} }
public void refreshHistory(Integer blockHeight, WalletNode node) { public void refreshHistory(Integer blockHeight, Wallet pastWallet, WalletNode node) {
Wallet previousWallet = wallet.copy(); Wallet previousWallet = wallet.copy();
if(wallet.isValid() && AppServices.isConnected()) { if(wallet.isValid() && AppServices.isConnected()) {
log.debug(node == null ? wallet.getName() + " refreshing full wallet history" : wallet.getName() + " requesting node wallet history for " + node.getDerivationPath()); log.debug(node == null ? wallet.getName() + " refreshing full wallet history" : wallet.getName() + " requesting node wallet history for " + node.getDerivationPath());
ElectrumServer.TransactionHistoryService historyService = new ElectrumServer.TransactionHistoryService(wallet, getWalletTransactionNodes(node)); ElectrumServer.TransactionHistoryService historyService = new ElectrumServer.TransactionHistoryService(wallet, getWalletTransactionNodes(node));
historyService.setOnSucceeded(workerStateEvent -> { historyService.setOnSucceeded(workerStateEvent -> {
EventManager.get().post(new WalletHistoryStatusEvent(wallet, false)); EventManager.get().post(new WalletHistoryStatusEvent(wallet, false));
updateWallet(previousWallet, blockHeight); updateWallet(blockHeight, pastWallet, previousWallet);
}); });
historyService.setOnFailed(workerStateEvent -> { historyService.setOnFailed(workerStateEvent -> {
log.error("Error retrieving wallet history", workerStateEvent.getSource().getException()); log.error("Error retrieving wallet history", workerStateEvent.getSource().getException());
@ -91,15 +94,31 @@ public class WalletForm {
} }
} }
private void updateWallet(Wallet previousWallet, Integer blockHeight) { private void updateWallet(Integer blockHeight, Wallet pastWallet, Wallet previousWallet) {
if(blockHeight != null) { if(blockHeight != null) {
wallet.setStoredBlockHeight(blockHeight); wallet.setStoredBlockHeight(blockHeight);
} }
notifyIfChanged(previousWallet, blockHeight); if(pastWallet != null) {
copyLabels(pastWallet);
} }
private void notifyIfChanged(Wallet previousWallet, Integer blockHeight) { notifyIfChanged(blockHeight, previousWallet);
}
private void copyLabels(Wallet pastWallet) {
wallet.getNode(KeyPurpose.RECEIVE).copyLabels(pastWallet.getNode(KeyPurpose.RECEIVE));
wallet.getNode(KeyPurpose.CHANGE).copyLabels(pastWallet.getNode(KeyPurpose.CHANGE));
for(Map.Entry<Sha256Hash, BlockTransaction> txEntry : wallet.getTransactions().entrySet()) {
BlockTransaction pastBlockTransaction = pastWallet.getTransactions().get(txEntry.getKey());
if(pastBlockTransaction != null && txEntry.getValue() != null && txEntry.getValue().getLabel() == null && pastBlockTransaction.getLabel() != null) {
txEntry.getValue().setLabel(pastBlockTransaction.getLabel());
}
}
}
private void notifyIfChanged(Integer blockHeight, Wallet previousWallet) {
List<WalletNode> historyChangedNodes = new ArrayList<>(); List<WalletNode> historyChangedNodes = new ArrayList<>();
historyChangedNodes.addAll(getHistoryChangedNodes(previousWallet.getNode(KeyPurpose.RECEIVE).getChildren(), wallet.getNode(KeyPurpose.RECEIVE).getChildren())); historyChangedNodes.addAll(getHistoryChangedNodes(previousWallet.getNode(KeyPurpose.RECEIVE).getChildren(), wallet.getNode(KeyPurpose.RECEIVE).getChildren()));
historyChangedNodes.addAll(getHistoryChangedNodes(previousWallet.getNode(KeyPurpose.CHANGE).getChildren(), wallet.getNode(KeyPurpose.CHANGE).getChildren())); historyChangedNodes.addAll(getHistoryChangedNodes(previousWallet.getNode(KeyPurpose.CHANGE).getChildren(), wallet.getNode(KeyPurpose.CHANGE).getChildren()));
@ -226,7 +245,7 @@ public class WalletForm {
walletUtxosEntry = null; walletUtxosEntry = null;
accountEntries.clear(); accountEntries.clear();
EventManager.get().post(new WalletNodesChangedEvent(wallet)); EventManager.get().post(new WalletNodesChangedEvent(wallet));
refreshHistory(AppServices.getCurrentBlockHeight()); refreshHistory(AppServices.getCurrentBlockHeight(), event.getPastWallet());
} }
} }
@ -234,13 +253,13 @@ public class WalletForm {
public void newBlock(NewBlockEvent event) { public void newBlock(NewBlockEvent event) {
//Check if wallet is valid to avoid saving wallets in initial setup //Check if wallet is valid to avoid saving wallets in initial setup
if(wallet.isValid()) { if(wallet.isValid()) {
updateWallet(wallet.copy(), event.getHeight()); updateWallet(event.getHeight(), null, wallet.copy());
} }
} }
@Subscribe @Subscribe
public void connected(ConnectionEvent event) { public void connected(ConnectionEvent event) {
refreshHistory(event.getBlockHeight()); refreshHistory(event.getBlockHeight(), null);
} }
@Subscribe @Subscribe
@ -249,7 +268,7 @@ public class WalletForm {
WalletNode walletNode = event.getWalletNode(wallet); WalletNode walletNode = event.getWalletNode(wallet);
if(walletNode != null) { if(walletNode != null) {
log.debug(wallet.getName() + " history event for node " + walletNode + " (" + event.getScriptHash() + ")"); log.debug(wallet.getName() + " history event for node " + walletNode + " (" + event.getScriptHash() + ")");
refreshHistory(AppServices.getCurrentBlockHeight(), walletNode); refreshHistory(AppServices.getCurrentBlockHeight(), null, walletNode);
} }
} }
} }