From 85a26ae052c35196ed08a5bfbc93af2a6b545203 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Mon, 30 May 2022 19:31:55 +0200 Subject: [PATCH] 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). --- .../PirateChainWalletController.java | 28 +++++++++---------- .../org/qortal/crosschain/PirateChain.java | 22 +++++++++------ .../org/qortal/crosschain/PirateWallet.java | 21 ++------------ 3 files changed, 30 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/qortal/controller/PirateChainWalletController.java b/src/main/java/org/qortal/controller/PirateChainWalletController.java index 111badbb..40ea1cbb 100644 --- a/src/main/java/org/qortal/controller/PirateChainWalletController.java +++ b/src/main/java/org/qortal/controller/PirateChainWalletController.java @@ -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); if (entropyBytes == null || entropyBytes.length != 32) { @@ -107,9 +115,9 @@ public class PirateChainWalletController extends Thread { } try { - this.currentWallet = new PirateWallet(entropyBytes, false); - if (!this.currentWallet.isReady() || this.currentWallet.hasNullSeed()) { - // Don't persist wallets that aren't ready or are null seed + this.currentWallet = new PirateWallet(entropyBytes, isNullSeedWallet); + if (!this.currentWallet.isReady()) { + // Don't persist wallets that aren't ready this.currentWallet = null; } return true; @@ -120,16 +128,6 @@ public class PirateChainWalletController extends Thread { return false; } - public PirateWallet switchToNullWallet() { - try { - this.currentWallet = null; - return new PirateWallet(null, true); - - } catch (IOException e) { - return null; - } - } - private void saveCurrentWallet() { if (this.currentWallet == null) { // Nothing to do @@ -164,7 +162,7 @@ public class PirateChainWalletController extends Thread { public void ensureNotNullSeed() throws ForeignBlockchainException { // 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"); } } diff --git a/src/main/java/org/qortal/crosschain/PirateChain.java b/src/main/java/org/qortal/crosschain/PirateChain.java index 32c50cda..4a5d3b60 100644 --- a/src/main/java/org/qortal/crosschain/PirateChain.java +++ b/src/main/java/org/qortal/crosschain/PirateChain.java @@ -434,10 +434,13 @@ public class PirateChain extends Bitcoiny { public String redeemP2sh(String p2shAddress, String receivingAddress, long amount, String redeemScript58, String fundingTxid58, String secret58, String privateKey58) throws ForeignBlockchainException { - PirateWallet wallet = PirateChainWalletController.getInstance().switchToNullWallet(); - if (wallet == null) { - throw new ForeignBlockchainException("Unable to initialize null seed Pirate Chain wallet"); - } + // Use null seed wallet since we may not have the entropy bytes for a real wallet's seed + PirateChainWalletController walletController = PirateChainWalletController.getInstance(); + walletController.initNullSeedWallet(); + walletController.ensureInitialized(); + walletController.ensureSynchronized(); + + walletController.getCurrentWallet().unlock(); // Build spend JSONObject txn = new JSONObject(); @@ -483,10 +486,13 @@ public class PirateChain extends Bitcoiny { public String refundP2sh(String p2shAddress, String receivingAddress, long amount, String redeemScript58, String fundingTxid58, int lockTime, String privateKey58) throws ForeignBlockchainException { - PirateWallet wallet = PirateChainWalletController.getInstance().switchToNullWallet(); - if (wallet == null) { - throw new ForeignBlockchainException("Unable to initialize null seed Pirate Chain wallet"); - } + // Use null seed wallet since we may not have the entropy bytes for a real wallet's seed + PirateChainWalletController walletController = PirateChainWalletController.getInstance(); + walletController.initNullSeedWallet(); + walletController.ensureInitialized(); + walletController.ensureSynchronized(); + + walletController.getCurrentWallet().unlock(); // Build spend JSONObject txn = new JSONObject(); diff --git a/src/main/java/org/qortal/crosschain/PirateWallet.java b/src/main/java/org/qortal/crosschain/PirateWallet.java index 985f2f64..91fe155b 100644 --- a/src/main/java/org/qortal/crosschain/PirateWallet.java +++ b/src/main/java/org/qortal/crosschain/PirateWallet.java @@ -65,14 +65,7 @@ public class PirateWallet { LiteWalletJni.initlogging(); if (this.entropyBytes == null) { - if (this.isNullSeedWallet) { - // Use null seed - this.entropyBytes = new byte[32]; - } - else { - // Need entropy bytes for a non-null seed wallet - return false; - } + return false; } // Pirate library uses base64 encoding @@ -93,7 +86,7 @@ public class PirateWallet { int birthday = DEFAULT_BIRTHDAY; if (this.isNullSeedWallet) { 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(); } catch (ForeignBlockchainException e) { @@ -197,10 +190,6 @@ public class PirateWallet { LOGGER.info("Error: can't save wallet, because no wallet it initialized"); return false; } - if (this.isNullSeedWallet) { - LOGGER.info("Error: can't save null wallet"); - return false; - } // Encrypt first (will do nothing if already encrypted) this.encrypt(); @@ -229,10 +218,6 @@ public class PirateWallet { } public String load() throws IOException { - if (this.isNullSeedWallet) { - // Can't load null seed wallets - return null; - } Path walletPath = this.getCurrentWalletPath(); if (!Files.exists(walletPath)) { return null; @@ -321,7 +306,7 @@ public class PirateWallet { return null; } - public boolean hasNullSeed() { + public boolean isNullSeedWallet() { return this.isNullSeedWallet; }