Another rework of null seed wallets, to allow them to be saved and loaded.

A full sync is unavoidable for P2SH redeem/refund, so we need to be able to save our progress. Creating a new null seed wallet each time isn't an option because it relies on having a recent checkpoint to avoid having to sync large amounts of blocks every time (sync is per wallet, not per node).
This commit is contained in:
CalDescent 2022-05-30 19:31:55 +02:00
parent c30b1145a1
commit 85a26ae052
3 changed files with 30 additions and 41 deletions

View File

@ -87,7 +87,15 @@ public class PirateChainWalletController extends Thread {
} }
public boolean initWithEntropy58(String entropy58) throws ForeignBlockchainException { public boolean initWithEntropy58(String entropy58) {
return this.initWithEntropy58(entropy58, false);
}
public boolean initNullSeedWallet() {
return this.initWithEntropy58(Base58.encode(new byte[32]), true);
}
private boolean initWithEntropy58(String entropy58, boolean isNullSeedWallet) {
byte[] entropyBytes = Base58.decode(entropy58); byte[] entropyBytes = Base58.decode(entropy58);
if (entropyBytes == null || entropyBytes.length != 32) { if (entropyBytes == null || entropyBytes.length != 32) {
@ -107,9 +115,9 @@ public class PirateChainWalletController extends Thread {
} }
try { try {
this.currentWallet = new PirateWallet(entropyBytes, false); this.currentWallet = new PirateWallet(entropyBytes, isNullSeedWallet);
if (!this.currentWallet.isReady() || this.currentWallet.hasNullSeed()) { if (!this.currentWallet.isReady()) {
// Don't persist wallets that aren't ready or are null seed // Don't persist wallets that aren't ready
this.currentWallet = null; this.currentWallet = null;
} }
return true; return true;
@ -120,16 +128,6 @@ public class PirateChainWalletController extends Thread {
return false; return false;
} }
public PirateWallet switchToNullWallet() {
try {
this.currentWallet = null;
return new PirateWallet(null, true);
} catch (IOException e) {
return null;
}
}
private void saveCurrentWallet() { private void saveCurrentWallet() {
if (this.currentWallet == null) { if (this.currentWallet == null) {
// Nothing to do // Nothing to do
@ -164,7 +162,7 @@ public class PirateChainWalletController extends Thread {
public void ensureNotNullSeed() throws ForeignBlockchainException { public void ensureNotNullSeed() throws ForeignBlockchainException {
// Safety check to make sure funds aren't sent to a null seed wallet // Safety check to make sure funds aren't sent to a null seed wallet
if (this.currentWallet == null || this.currentWallet.hasNullSeed()) { if (this.currentWallet == null || this.currentWallet.isNullSeedWallet()) {
throw new ForeignBlockchainException("Invalid wallet"); throw new ForeignBlockchainException("Invalid wallet");
} }
} }

View File

@ -434,10 +434,13 @@ public class PirateChain extends Bitcoiny {
public String redeemP2sh(String p2shAddress, String receivingAddress, long amount, String redeemScript58, public String redeemP2sh(String p2shAddress, String receivingAddress, long amount, String redeemScript58,
String fundingTxid58, String secret58, String privateKey58) throws ForeignBlockchainException { String fundingTxid58, String secret58, String privateKey58) throws ForeignBlockchainException {
PirateWallet wallet = PirateChainWalletController.getInstance().switchToNullWallet(); // Use null seed wallet since we may not have the entropy bytes for a real wallet's seed
if (wallet == null) { PirateChainWalletController walletController = PirateChainWalletController.getInstance();
throw new ForeignBlockchainException("Unable to initialize null seed Pirate Chain wallet"); walletController.initNullSeedWallet();
} walletController.ensureInitialized();
walletController.ensureSynchronized();
walletController.getCurrentWallet().unlock();
// Build spend // Build spend
JSONObject txn = new JSONObject(); JSONObject txn = new JSONObject();
@ -483,10 +486,13 @@ public class PirateChain extends Bitcoiny {
public String refundP2sh(String p2shAddress, String receivingAddress, long amount, String redeemScript58, public String refundP2sh(String p2shAddress, String receivingAddress, long amount, String redeemScript58,
String fundingTxid58, int lockTime, String privateKey58) throws ForeignBlockchainException { String fundingTxid58, int lockTime, String privateKey58) throws ForeignBlockchainException {
PirateWallet wallet = PirateChainWalletController.getInstance().switchToNullWallet(); // Use null seed wallet since we may not have the entropy bytes for a real wallet's seed
if (wallet == null) { PirateChainWalletController walletController = PirateChainWalletController.getInstance();
throw new ForeignBlockchainException("Unable to initialize null seed Pirate Chain wallet"); walletController.initNullSeedWallet();
} walletController.ensureInitialized();
walletController.ensureSynchronized();
walletController.getCurrentWallet().unlock();
// Build spend // Build spend
JSONObject txn = new JSONObject(); JSONObject txn = new JSONObject();

View File

@ -65,14 +65,7 @@ public class PirateWallet {
LiteWalletJni.initlogging(); LiteWalletJni.initlogging();
if (this.entropyBytes == null) { if (this.entropyBytes == null) {
if (this.isNullSeedWallet) { return false;
// Use null seed
this.entropyBytes = new byte[32];
}
else {
// Need entropy bytes for a non-null seed wallet
return false;
}
} }
// Pirate library uses base64 encoding // Pirate library uses base64 encoding
@ -93,7 +86,7 @@ public class PirateWallet {
int birthday = DEFAULT_BIRTHDAY; int birthday = DEFAULT_BIRTHDAY;
if (this.isNullSeedWallet) { if (this.isNullSeedWallet) {
try { try {
// Attempt to set birthday to the current block for null wallets // Attempt to set birthday to the current block for null seed wallets
birthday = PirateChain.getInstance().blockchainProvider.getCurrentHeight(); birthday = PirateChain.getInstance().blockchainProvider.getCurrentHeight();
} }
catch (ForeignBlockchainException e) { catch (ForeignBlockchainException e) {
@ -197,10 +190,6 @@ public class PirateWallet {
LOGGER.info("Error: can't save wallet, because no wallet it initialized"); LOGGER.info("Error: can't save wallet, because no wallet it initialized");
return false; return false;
} }
if (this.isNullSeedWallet) {
LOGGER.info("Error: can't save null wallet");
return false;
}
// Encrypt first (will do nothing if already encrypted) // Encrypt first (will do nothing if already encrypted)
this.encrypt(); this.encrypt();
@ -229,10 +218,6 @@ public class PirateWallet {
} }
public String load() throws IOException { public String load() throws IOException {
if (this.isNullSeedWallet) {
// Can't load null seed wallets
return null;
}
Path walletPath = this.getCurrentWalletPath(); Path walletPath = this.getCurrentWalletPath();
if (!Files.exists(walletPath)) { if (!Files.exists(walletPath)) {
return null; return null;
@ -321,7 +306,7 @@ public class PirateWallet {
return null; return null;
} }
public boolean hasNullSeed() { public boolean isNullSeedWallet() {
return this.isNullSeedWallet; return this.isNullSeedWallet;
} }