diff --git a/src/main/java/com/sparrowwallet/drongo/address/Address.java b/src/main/java/com/sparrowwallet/drongo/address/Address.java index f13663c..af55c62 100644 --- a/src/main/java/com/sparrowwallet/drongo/address/Address.java +++ b/src/main/java/com/sparrowwallet/drongo/address/Address.java @@ -43,9 +43,13 @@ public abstract class Address { public abstract ScriptType getScriptType(); - public abstract Script getOutputScript(); + public Script getOutputScript() { + return getScriptType().getOutputScript(data); + } - public abstract byte[] getOutputScriptData(); + public byte[] getOutputScriptData() { + return data; + } public abstract String getOutputScriptDataType(); diff --git a/src/main/java/com/sparrowwallet/drongo/address/P2PKAddress.java b/src/main/java/com/sparrowwallet/drongo/address/P2PKAddress.java index 0680b75..dd2e1da 100644 --- a/src/main/java/com/sparrowwallet/drongo/address/P2PKAddress.java +++ b/src/main/java/com/sparrowwallet/drongo/address/P2PKAddress.java @@ -24,15 +24,6 @@ public class P2PKAddress extends Address { return ScriptType.P2PK; } - public Script getOutputScript() { - return getScriptType().getOutputScript(data); - } - - @Override - public byte[] getOutputScriptData() { - return data; - } - @Override public String getOutputScriptDataType() { return "Public Key"; diff --git a/src/main/java/com/sparrowwallet/drongo/address/P2PKHAddress.java b/src/main/java/com/sparrowwallet/drongo/address/P2PKHAddress.java index e1d6792..6de9b9a 100644 --- a/src/main/java/com/sparrowwallet/drongo/address/P2PKHAddress.java +++ b/src/main/java/com/sparrowwallet/drongo/address/P2PKHAddress.java @@ -19,16 +19,6 @@ public class P2PKHAddress extends Address { return ScriptType.P2PKH; } - @Override - public Script getOutputScript() { - return getScriptType().getOutputScript(data); - } - - @Override - public byte[] getOutputScriptData() { - return data; - } - @Override public String getOutputScriptDataType() { return "Public Key Hash"; diff --git a/src/main/java/com/sparrowwallet/drongo/address/P2SHAddress.java b/src/main/java/com/sparrowwallet/drongo/address/P2SHAddress.java index 99687d5..de02e8f 100644 --- a/src/main/java/com/sparrowwallet/drongo/address/P2SHAddress.java +++ b/src/main/java/com/sparrowwallet/drongo/address/P2SHAddress.java @@ -20,16 +20,6 @@ public class P2SHAddress extends Address { return ScriptType.P2SH; } - @Override - public Script getOutputScript() { - return getScriptType().getOutputScript(data); - } - - @Override - public byte[] getOutputScriptData() { - return data; - } - @Override public String getOutputScriptDataType() { return "Script Hash"; diff --git a/src/main/java/com/sparrowwallet/drongo/address/P2TRAddress.java b/src/main/java/com/sparrowwallet/drongo/address/P2TRAddress.java index eb668a9..255982a 100644 --- a/src/main/java/com/sparrowwallet/drongo/address/P2TRAddress.java +++ b/src/main/java/com/sparrowwallet/drongo/address/P2TRAddress.java @@ -25,16 +25,6 @@ public class P2TRAddress extends Address { return ScriptType.P2TR; } - @Override - public Script getOutputScript() { - return getScriptType().getOutputScript(data); - } - - @Override - public byte[] getOutputScriptData() { - return data; - } - @Override public String getOutputScriptDataType() { return "Taproot"; diff --git a/src/main/java/com/sparrowwallet/drongo/address/P2WPKHAddress.java b/src/main/java/com/sparrowwallet/drongo/address/P2WPKHAddress.java index 3db918a..f6358bb 100644 --- a/src/main/java/com/sparrowwallet/drongo/address/P2WPKHAddress.java +++ b/src/main/java/com/sparrowwallet/drongo/address/P2WPKHAddress.java @@ -25,16 +25,6 @@ public class P2WPKHAddress extends Address { return ScriptType.P2WPKH; } - @Override - public Script getOutputScript() { - return getScriptType().getOutputScript(data); - } - - @Override - public byte[] getOutputScriptData() { - return data; - } - @Override public String getOutputScriptDataType() { return "Witness Public Key Hash"; diff --git a/src/main/java/com/sparrowwallet/drongo/address/P2WSHAddress.java b/src/main/java/com/sparrowwallet/drongo/address/P2WSHAddress.java index 6ebd886..3b70585 100644 --- a/src/main/java/com/sparrowwallet/drongo/address/P2WSHAddress.java +++ b/src/main/java/com/sparrowwallet/drongo/address/P2WSHAddress.java @@ -23,16 +23,6 @@ public class P2WSHAddress extends Address { return ScriptType.P2WSH; } - @Override - public Script getOutputScript() { - return getScriptType().getOutputScript(data); - } - - @Override - public byte[] getOutputScriptData() { - return data; - } - @Override public String getOutputScriptDataType() { return "Witness Script Hash"; diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java b/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java index b4079e5..6045866 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java @@ -31,7 +31,10 @@ public class Keystore extends Persistable { private DeterministicSeed seed; //For BIP47 keystores - not persisted but must be unencrypted to generate keys - private ExtendedKey bip47ExtendedPrivateKey; + private transient ExtendedKey bip47ExtendedPrivateKey; + + //Avoid performing repeated expensive seed derivation checks + private transient boolean extendedPublicKeyChecked; public Keystore() { this(DEFAULT_LABEL); @@ -83,6 +86,7 @@ public class Keystore extends Persistable { public void setExtendedPublicKey(ExtendedKey extendedPublicKey) { this.extendedPublicKey = extendedPublicKey; + this.extendedPublicKeyChecked = false; } public PaymentCode getExternalPaymentCode() { @@ -125,6 +129,14 @@ public class Keystore extends Persistable { return hasMasterPrivateKey() || (source == KeystoreSource.SW_PAYMENT_CODE && bip47ExtendedPrivateKey != null); } + public boolean needsPassphrase() { + if(seed != null) { + return seed.needsPassphrase(); + } + + return false; + } + public PaymentCode getPaymentCode() { DeterministicKey bip47Key = bip47ExtendedPrivateKey.getKey(); return new PaymentCode(bip47Key.getPubKey(), bip47Key.getChainCode()); @@ -278,7 +290,7 @@ public class Keystore extends Persistable { throw new InvalidKeystoreException("Source of " + source + " but no seed or master private key is present"); } - if((seed != null && !seed.isEncrypted()) || (masterPrivateExtendedKey != null && !masterPrivateExtendedKey.isEncrypted())) { + if(!extendedPublicKeyChecked && ((seed != null && !seed.isEncrypted()) || (masterPrivateExtendedKey != null && !masterPrivateExtendedKey.isEncrypted()))) { try { List derivation = getKeyDerivation().getDerivation(); DeterministicKey derivedKey = getExtendedMasterPrivateKey().getKey(derivation); @@ -287,6 +299,7 @@ public class Keystore extends Persistable { if(!xpub.equals(getExtendedPublicKey())) { throw new InvalidKeystoreException("Specified extended public key does not match public key derived from seed"); } + extendedPublicKeyChecked = true; } catch(MnemonicException e) { throw new InvalidKeystoreException("Invalid mnemonic specified for seed", e); } diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/WalletNode.java b/src/main/java/com/sparrowwallet/drongo/wallet/WalletNode.java index 269e99e..d4267c2 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/WalletNode.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/WalletNode.java @@ -13,6 +13,7 @@ import java.util.stream.Collectors; public class WalletNode extends Persistable implements Comparable { private final String derivationPath; private String label; + private Address address; private TreeSet children = new TreeSet<>(); private TreeSet transactionOutputs = new TreeSet<>(); @@ -267,11 +268,28 @@ public class WalletNode extends Persistable implements Comparable { } public Address getAddress() { + if(address != null) { + return address; + } + + if(wallet.getKeystores().stream().noneMatch(Keystore::needsPassphrase)) { + address = wallet.getAddress(this); + return address; + } + return wallet.getAddress(this); } + public byte[] getAddressData() { + return address == null ? null : address.getData(); + } + + public void setAddress(Address address) { + this.address = address; + } + public Script getOutputScript() { - return wallet.getOutputScript(this); + return getAddress().getOutputScript(); } public String getOutputDescriptor() { @@ -324,6 +342,7 @@ public class WalletNode extends Persistable implements Comparable { WalletNode copy = new WalletNode(walletCopy, derivationPath); copy.setId(getId()); copy.setLabel(label); + copy.setAddress(address); for(WalletNode child : getChildren()) { copy.children.add(child.copy(walletCopy));