mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
calculate and cache script hashes statuses on wallet load to avoid unnecessary initial history fetching
This commit is contained in:
parent
1677c47500
commit
42bfe572ef
2 changed files with 49 additions and 4 deletions
|
@ -17,8 +17,6 @@ import com.sparrowwallet.sparrow.wallet.SendController;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.IntegerProperty;
|
import javafx.beans.property.IntegerProperty;
|
||||||
import javafx.beans.property.SimpleIntegerProperty;
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
|
||||||
import javafx.beans.property.StringProperty;
|
|
||||||
import javafx.concurrent.ScheduledService;
|
import javafx.concurrent.ScheduledService;
|
||||||
import javafx.concurrent.Service;
|
import javafx.concurrent.Service;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
|
@ -26,6 +24,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.locks.Condition;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
@ -89,7 +88,7 @@ public class ElectrumServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
//If changing server, don't rely on previous transaction history
|
//If changing server, don't rely on previous transaction history
|
||||||
if(!electrumServer.equals(previousServerAddress)) {
|
if(previousServerAddress != null && !electrumServer.equals(previousServerAddress)) {
|
||||||
retrievedScriptHashes.clear();
|
retrievedScriptHashes.clear();
|
||||||
}
|
}
|
||||||
previousServerAddress = electrumServer;
|
previousServerAddress = electrumServer;
|
||||||
|
@ -160,6 +159,51 @@ public class ElectrumServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void addCalculatedScriptHashes(Wallet wallet) {
|
||||||
|
calculateScriptHashes(wallet, KeyPurpose.RECEIVE).forEach(retrievedScriptHashes::putIfAbsent);
|
||||||
|
calculateScriptHashes(wallet, KeyPurpose.CHANGE).forEach(retrievedScriptHashes::putIfAbsent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> calculateScriptHashes(Wallet wallet, KeyPurpose keyPurpose) {
|
||||||
|
Map<String, String> calculatedScriptHashes = new LinkedHashMap<>();
|
||||||
|
for(WalletNode walletNode : wallet.getNode(keyPurpose).getChildren()) {
|
||||||
|
String scriptHash = getScriptHash(wallet, walletNode);
|
||||||
|
|
||||||
|
List<BlockTransactionHashIndex> txos = new ArrayList<>(walletNode.getTransactionOutputs());
|
||||||
|
txos.addAll(walletNode.getTransactionOutputs().stream().filter(BlockTransactionHashIndex::isSpent).map(BlockTransactionHashIndex::getSpentBy).collect(Collectors.toList()));
|
||||||
|
Set<Sha256Hash> unique = new HashSet<>(txos.size());
|
||||||
|
txos.removeIf(ref -> !unique.add(ref.getHash()));
|
||||||
|
txos.sort((txo1, txo2) -> {
|
||||||
|
if(txo1.getHeight() != txo2.getHeight()) {
|
||||||
|
return txo1.getComparisonHeight() - txo2.getComparisonHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(txo1.isSpent() && txo1.getSpentBy().equals(txo2)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(txo2.isSpent() && txo2.getSpentBy().equals(txo1)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//We cannot further sort by order within a block, so sometimes multiple txos to an address will mean an incorrect status
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
if(!txos.isEmpty()) {
|
||||||
|
StringBuilder scriptHashStatus = new StringBuilder();
|
||||||
|
for(BlockTransactionHashIndex txo : txos) {
|
||||||
|
scriptHashStatus.append(txo.getHash().toString()).append(":").append(txo.getHeight()).append(":");
|
||||||
|
}
|
||||||
|
|
||||||
|
calculatedScriptHashes.put(scriptHash, Utils.bytesToHex(Sha256Hash.hash(scriptHashStatus.toString().getBytes(StandardCharsets.UTF_8))));
|
||||||
|
} else {
|
||||||
|
calculatedScriptHashes.put(scriptHash, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return calculatedScriptHashes;
|
||||||
|
}
|
||||||
|
|
||||||
public static void clearRetrievedScriptHashes(Wallet wallet) {
|
public static void clearRetrievedScriptHashes(Wallet wallet) {
|
||||||
wallet.getNode(KeyPurpose.RECEIVE).getChildren().stream().map(node -> getScriptHash(wallet, node)).forEach(scriptHash -> retrievedScriptHashes.remove(scriptHash));
|
wallet.getNode(KeyPurpose.RECEIVE).getChildren().stream().map(node -> getScriptHash(wallet, node)).forEach(scriptHash -> retrievedScriptHashes.remove(scriptHash));
|
||||||
wallet.getNode(KeyPurpose.CHANGE).getChildren().stream().map(node -> getScriptHash(wallet, node)).forEach(scriptHash -> retrievedScriptHashes.remove(scriptHash));
|
wallet.getNode(KeyPurpose.CHANGE).getChildren().stream().map(node -> getScriptHash(wallet, node)).forEach(scriptHash -> retrievedScriptHashes.remove(scriptHash));
|
||||||
|
|
|
@ -46,7 +46,8 @@ public class WalletForm {
|
||||||
//Unencrypted wallets load before isConnected is true, waiting for the ConnectionEvent to refresh history - save the backup for this event
|
//Unencrypted wallets load before isConnected is true, waiting for the ConnectionEvent to refresh history - save the backup for this event
|
||||||
savedPastWallet = backupWallet;
|
savedPastWallet = backupWallet;
|
||||||
|
|
||||||
if(refreshHistory) {
|
if(refreshHistory && wallet.isValid()) {
|
||||||
|
ElectrumServer.addCalculatedScriptHashes(wallet);
|
||||||
refreshHistory(AppServices.getCurrentBlockHeight(), backupWallet);
|
refreshHistory(AppServices.getCurrentBlockHeight(), backupWallet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue