add detached labels map to store labels during a wallet refresh

This commit is contained in:
Craig Raw 2022-02-09 11:38:23 +02:00
parent ee732fb223
commit de87ab1102
2 changed files with 87 additions and 8 deletions

View file

@ -37,6 +37,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
private List<Keystore> keystores = new ArrayList<>(); private List<Keystore> keystores = new ArrayList<>();
private final TreeSet<WalletNode> purposeNodes = new TreeSet<>(); private final TreeSet<WalletNode> purposeNodes = new TreeSet<>();
private final Map<Sha256Hash, BlockTransaction> transactions = new HashMap<>(); private final Map<Sha256Hash, BlockTransaction> transactions = new HashMap<>();
private final Map<String, String> detachedLabels = new HashMap<>();
private MixConfig mixConfig; private MixConfig mixConfig;
private final Map<Sha256Hash, UtxoMixData> utxoMixes = new HashMap<>(); private final Map<Sha256Hash, UtxoMixData> utxoMixes = new HashMap<>();
private Integer storedBlockHeight; private Integer storedBlockHeight;
@ -116,6 +117,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
childWallet.setName(standardAccount.getName()); childWallet.setName(standardAccount.getName());
childWallet.purposeNodes.clear(); childWallet.purposeNodes.clear();
childWallet.transactions.clear(); childWallet.transactions.clear();
childWallet.detachedLabels.clear();
childWallet.storedBlockHeight = null; childWallet.storedBlockHeight = null;
childWallet.gapLimit = standardAccount.getMinimumGapLimit(); childWallet.gapLimit = standardAccount.getMinimumGapLimit();
childWallet.birthDate = null; childWallet.birthDate = null;
@ -273,10 +275,19 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
public synchronized void updateTransactions(Map<Sha256Hash, BlockTransaction> updatedTransactions) { public synchronized void updateTransactions(Map<Sha256Hash, BlockTransaction> updatedTransactions) {
for(BlockTransaction blockTx : updatedTransactions.values()) { for(BlockTransaction blockTx : updatedTransactions.values()) {
if(!transactions.isEmpty()) {
Optional<String> optionalLabel = transactions.values().stream().filter(oldBlTx -> oldBlTx.getHash().equals(blockTx.getHash())).map(BlockTransaction::getLabel).filter(Objects::nonNull).findFirst(); Optional<String> optionalLabel = transactions.values().stream().filter(oldBlTx -> oldBlTx.getHash().equals(blockTx.getHash())).map(BlockTransaction::getLabel).filter(Objects::nonNull).findFirst();
optionalLabel.ifPresent(blockTx::setLabel); optionalLabel.ifPresent(blockTx::setLabel);
} }
if(!detachedLabels.isEmpty()) {
String label = detachedLabels.remove(blockTx.getHashAsString());
if(label != null && (blockTx.getLabel() == null || blockTx.getLabel().isEmpty())) {
blockTx.setLabel(label);
}
}
}
transactions.putAll(updatedTransactions); transactions.putAll(updatedTransactions);
if(!transactions.isEmpty()) { if(!transactions.isEmpty()) {
@ -284,6 +295,10 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
} }
} }
public Map<String, String> getDetachedLabels() {
return detachedLabels;
}
public MixConfig getMixConfig() { public MixConfig getMixConfig() {
return mixConfig; return mixConfig;
} }
@ -394,7 +409,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
purposeNode = optionalPurposeNode.get(); purposeNode = optionalPurposeNode.get();
} }
purposeNode.fillToIndex(getLookAheadIndex(purposeNode)); purposeNode.fillToIndex(this, getLookAheadIndex(purposeNode));
return purposeNode; return purposeNode;
} }
@ -426,7 +441,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
} }
if(index >= node.getChildren().size()) { if(index >= node.getChildren().size()) {
node.fillToIndex(index); node.fillToIndex(this, index);
} }
for(WalletNode childNode : node.getChildren()) { for(WalletNode childNode : node.getChildren()) {
@ -1311,13 +1326,15 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
return BitcoinUnit.SATOSHIS; return BitcoinUnit.SATOSHIS;
} }
public void clearNodes() { public void clearNodes(Wallet previousWallet) {
detachedLabels.putAll(previousWallet.getDetachedLabels(true));
purposeNodes.clear(); purposeNodes.clear();
transactions.clear(); transactions.clear();
storedBlockHeight = 0; storedBlockHeight = 0;
} }
public void clearHistory() { public void clearHistory() {
detachedLabels.putAll(getDetachedLabels(false));
for(WalletNode purposeNode : purposeNodes) { for(WalletNode purposeNode : purposeNodes) {
purposeNode.clearHistory(); purposeNode.clearHistory();
} }
@ -1326,6 +1343,35 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
storedBlockHeight = 0; storedBlockHeight = 0;
} }
private Map<String, String> getDetachedLabels(boolean includeAddresses) {
Map<String, String> labels = new HashMap<>();
for(BlockTransaction blockTransaction : transactions.values()) {
if(blockTransaction.getLabel() != null && !blockTransaction.getLabel().isEmpty()) {
labels.put(blockTransaction.getHashAsString(), blockTransaction.getLabel());
}
}
for(WalletNode purposeNode : purposeNodes) {
for(WalletNode addressNode : purposeNode.getChildren()) {
if(includeAddresses && addressNode.getLabel() != null && !addressNode.getLabel().isEmpty()) {
labels.put(getAddress(addressNode).toString(), addressNode.getLabel());
}
for(BlockTransactionHashIndex output : addressNode.getTransactionOutputs()) {
if(output.getLabel() != null && !output.getLabel().isEmpty()) {
labels.put(output.getHash().toString() + "<" + output.getIndex(), output.getLabel());
}
if(output.isSpent() && output.getSpentBy().getLabel() != null && !output.getSpentBy().getLabel().isEmpty()) {
labels.put(output.getSpentBy().getHash() + ">" + output.getSpentBy().getIndex(), output.getSpentBy().getLabel());
}
}
}
}
return labels;
}
public boolean isValid() { public boolean isValid() {
try { try {
checkWallet(); checkWallet();
@ -1466,6 +1512,9 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
for(Sha256Hash hash : transactions.keySet()) { for(Sha256Hash hash : transactions.keySet()) {
copy.transactions.put(hash, transactions.get(hash)); copy.transactions.put(hash, transactions.get(hash));
} }
for(String entry : detachedLabels.keySet()) {
copy.detachedLabels.put(entry, detachedLabels.get(entry));
}
copy.setMixConfig(mixConfig == null ? null : mixConfig.copy()); copy.setMixConfig(mixConfig == null ? null : mixConfig.copy());
for(Sha256Hash hash : utxoMixes.keySet()) { for(Sha256Hash hash : utxoMixes.keySet()) {
copy.utxoMixes.put(hash, utxoMixes.get(hash)); copy.utxoMixes.put(hash, utxoMixes.get(hash));

View file

@ -106,12 +106,28 @@ public class WalletNode extends Persistable implements Comparable<WalletNode> {
this.transactionOutputs = transactionOutputs; this.transactionOutputs = transactionOutputs;
} }
public synchronized void updateTransactionOutputs(Set<BlockTransactionHashIndex> updatedOutputs) { public synchronized void updateTransactionOutputs(Wallet wallet, Set<BlockTransactionHashIndex> updatedOutputs) {
for(BlockTransactionHashIndex txo : updatedOutputs) { for(BlockTransactionHashIndex txo : updatedOutputs) {
if(!transactionOutputs.isEmpty()) {
Optional<String> optionalLabel = transactionOutputs.stream().filter(oldTxo -> oldTxo.getHash().equals(txo.getHash()) && oldTxo.getIndex() == txo.getIndex()).map(BlockTransactionHash::getLabel).filter(Objects::nonNull).findFirst(); Optional<String> optionalLabel = transactionOutputs.stream().filter(oldTxo -> oldTxo.getHash().equals(txo.getHash()) && oldTxo.getIndex() == txo.getIndex()).map(BlockTransactionHash::getLabel).filter(Objects::nonNull).findFirst();
optionalLabel.ifPresent(txo::setLabel); optionalLabel.ifPresent(txo::setLabel);
} }
if(!wallet.getDetachedLabels().isEmpty()) {
String label = wallet.getDetachedLabels().remove(txo.getHash().toString() + "<" + txo.getIndex());
if(label != null && (txo.getLabel() == null || txo.getLabel().isEmpty())) {
txo.setLabel(label);
}
if(txo.isSpent()) {
String spentByLabel = wallet.getDetachedLabels().remove(txo.getSpentBy().getHash() + ">" + txo.getSpentBy().getIndex());
if(spentByLabel != null && (txo.getSpentBy().getLabel() == null || txo.getSpentBy().getLabel().isEmpty())) {
txo.getSpentBy().setLabel(spentByLabel);
}
}
}
}
transactionOutputs.clear(); transactionOutputs.clear();
transactionOutputs.addAll(updatedOutputs); transactionOutputs.addAll(updatedOutputs);
} }
@ -134,6 +150,20 @@ public class WalletNode extends Persistable implements Comparable<WalletNode> {
return value; return value;
} }
public Set<WalletNode> fillToIndex(Wallet wallet, int index) {
Set<WalletNode> newNodes = fillToIndex(index);
if(!wallet.getDetachedLabels().isEmpty()) {
for(WalletNode newNode : newNodes) {
String label = wallet.getDetachedLabels().remove(wallet.getAddress(newNode).toString());
if(label != null && (newNode.getLabel() == null || newNode.getLabel().isEmpty())) {
newNode.setLabel(label);
}
}
}
return newNodes;
}
public synchronized Set<WalletNode> fillToIndex(int index) { public synchronized Set<WalletNode> fillToIndex(int index) {
Set<WalletNode> newNodes = new TreeSet<>(); Set<WalletNode> newNodes = new TreeSet<>();
for(int i = 0; i <= index; i++) { for(int i = 0; i <= index; i++) {