From 8e3d0d23c129b7fe9eedb16769827155f53c84d5 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Thu, 10 Jun 2021 12:07:20 +0200 Subject: [PATCH] support database persistence --- build.gradle | 2 ++ .../sparrowwallet/drongo/policy/Policy.java | 11 ++++-- .../drongo/wallet/BlockTransactionHash.java | 2 +- .../wallet/BlockTransactionHashIndex.java | 4 ++- .../drongo/wallet/DeterministicSeed.java | 3 +- .../sparrowwallet/drongo/wallet/Keystore.java | 3 +- .../wallet/MasterPrivateExtendedKey.java | 10 ++++-- .../drongo/wallet/Persistable.java | 13 +++++++ .../sparrowwallet/drongo/wallet/Wallet.java | 34 ++++++++++++++++++- .../drongo/wallet/WalletNode.java | 7 ++-- src/main/java/module-info.java | 2 +- 11 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/sparrowwallet/drongo/wallet/Persistable.java diff --git a/build.gradle b/build.gradle index ae5cca6..d6be80e 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,9 @@ dependencies { } implementation ('ch.qos.logback:logback-classic:1.2.3') { exclude group: 'org.hamcrest', module: 'hamcrest-core' + exclude group: 'org.slf4j' } + implementation ('org.slf4j:slf4j-api:1.7.30') testImplementation ('junit:junit:4.12') { exclude group: 'org.hamcrest', module: 'hamcrest-core' } diff --git a/src/main/java/com/sparrowwallet/drongo/policy/Policy.java b/src/main/java/com/sparrowwallet/drongo/policy/Policy.java index b6991a2..370a111 100644 --- a/src/main/java/com/sparrowwallet/drongo/policy/Policy.java +++ b/src/main/java/com/sparrowwallet/drongo/policy/Policy.java @@ -2,13 +2,14 @@ package com.sparrowwallet.drongo.policy; import com.sparrowwallet.drongo.protocol.ScriptType; import com.sparrowwallet.drongo.wallet.Keystore; +import com.sparrowwallet.drongo.wallet.Persistable; import java.util.List; import static com.sparrowwallet.drongo.protocol.ScriptType.*; import static com.sparrowwallet.drongo.policy.PolicyType.*; -public class Policy { +public class Policy extends Persistable { private static final String DEFAULT_NAME = "Default"; private String name; @@ -23,6 +24,10 @@ public class Policy { this.miniscript = miniscript; } + public String getName() { + return name; + } + public Miniscript getMiniscript() { return miniscript; } @@ -57,6 +62,8 @@ public class Policy { } public Policy copy() { - return new Policy(name, miniscript.copy()); + Policy policy = new Policy(name, miniscript.copy()); + policy.setId(getId()); + return policy; } } diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/BlockTransactionHash.java b/src/main/java/com/sparrowwallet/drongo/wallet/BlockTransactionHash.java index 09af7c2..daa2231 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/BlockTransactionHash.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/BlockTransactionHash.java @@ -5,7 +5,7 @@ import com.sparrowwallet.drongo.protocol.Sha256Hash; import java.util.Date; import java.util.Objects; -public abstract class BlockTransactionHash { +public abstract class BlockTransactionHash extends Persistable { public static final int BLOCKS_TO_CONFIRM = 6; public static final int BLOCKS_TO_FULLY_CONFIRM = 100; diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/BlockTransactionHashIndex.java b/src/main/java/com/sparrowwallet/drongo/wallet/BlockTransactionHashIndex.java index 2046c38..30010a6 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/BlockTransactionHashIndex.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/BlockTransactionHashIndex.java @@ -96,6 +96,8 @@ public class BlockTransactionHashIndex extends BlockTransactionHash implements C } public BlockTransactionHashIndex copy() { - return new BlockTransactionHashIndex(super.getHash(), super.getHeight(), super.getDate(), super.getFee(), index, value, spentBy == null ? null : spentBy.copy(), super.getLabel()); + BlockTransactionHashIndex copy = new BlockTransactionHashIndex(super.getHash(), super.getHeight(), super.getDate(), super.getFee(), index, value, spentBy == null ? null : spentBy.copy(), super.getLabel()); + copy.setId(getId()); + return copy; } } diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/DeterministicSeed.java b/src/main/java/com/sparrowwallet/drongo/wallet/DeterministicSeed.java index 3dbb34a..6005f95 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/DeterministicSeed.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/DeterministicSeed.java @@ -7,7 +7,7 @@ import com.sparrowwallet.drongo.crypto.*; import java.security.SecureRandom; import java.util.*; -public class DeterministicSeed implements EncryptableItem { +public class DeterministicSeed extends Persistable implements EncryptableItem { public static final int DEFAULT_SEED_ENTROPY_BITS = 128; public static final int MAX_SEED_ENTROPY_BITS = 512; @@ -341,6 +341,7 @@ public class DeterministicSeed implements EncryptableItem { seed = new DeterministicSeed(new ArrayList<>(mnemonicCode), needsPassphrase, creationTimeSeconds, type); } + seed.setId(getId()); seed.setPassphrase(passphrase); return seed; } diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java b/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java index e8d2614..db40a68 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java @@ -8,7 +8,7 @@ import com.sparrowwallet.drongo.crypto.*; import java.util.List; -public class Keystore { +public class Keystore extends Persistable { public static final String DEFAULT_LABEL = "Keystore 1"; public static final int MAX_LABEL_LENGTH = 16; @@ -229,6 +229,7 @@ public class Keystore { public Keystore copy() { Keystore copy = new Keystore(label); + copy.setId(getId()); copy.setSource(source); copy.setWalletModel(walletModel); if(keyDerivation != null) { diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/MasterPrivateExtendedKey.java b/src/main/java/com/sparrowwallet/drongo/wallet/MasterPrivateExtendedKey.java index efd99b4..e36d08c 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/MasterPrivateExtendedKey.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/MasterPrivateExtendedKey.java @@ -6,7 +6,7 @@ import com.sparrowwallet.drongo.crypto.*; import java.nio.ByteBuffer; import java.util.Arrays; -public class MasterPrivateExtendedKey implements EncryptableItem { +public class MasterPrivateExtendedKey extends Persistable implements EncryptableItem { private final byte[] privateKey; private final byte[] chainCode; @@ -112,11 +112,15 @@ public class MasterPrivateExtendedKey implements EncryptableItem { } public MasterPrivateExtendedKey copy() { + MasterPrivateExtendedKey copy; if(isEncrypted()) { - return new MasterPrivateExtendedKey(encryptedKey.copy()); + copy = new MasterPrivateExtendedKey(encryptedKey.copy()); + } else { + copy = new MasterPrivateExtendedKey(Arrays.copyOf(privateKey, 32), Arrays.copyOf(chainCode, 32)); } - return new MasterPrivateExtendedKey(Arrays.copyOf(privateKey, 32), Arrays.copyOf(chainCode, 32)); + copy.setId(getId()); + return copy; } public void clear() { diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/Persistable.java b/src/main/java/com/sparrowwallet/drongo/wallet/Persistable.java new file mode 100644 index 0000000..9d6712f --- /dev/null +++ b/src/main/java/com/sparrowwallet/drongo/wallet/Persistable.java @@ -0,0 +1,13 @@ +package com.sparrowwallet.drongo.wallet; + +public class Persistable { + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java b/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java index 89114f0..1254bbe 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java @@ -19,12 +19,13 @@ import java.util.stream.Collectors; import static com.sparrowwallet.drongo.protocol.ScriptType.*; import static com.sparrowwallet.drongo.protocol.Transaction.WITNESS_SCALE_FACTOR; -public class Wallet { +public class Wallet extends Persistable { public static final int DEFAULT_LOOKAHEAD = 20; public static final String ALLOW_DERIVATIONS_MATCHING_OTHER_SCRIPT_TYPES_PROPERTY = "com.sparrowwallet.allowDerivationsMatchingOtherScriptTypes"; private String name; private Wallet masterWallet; + private List childWallets = new ArrayList<>(); private Network network = Network.get(); private PolicyType policyType; private ScriptType scriptType; @@ -125,10 +126,18 @@ public class Wallet { this.storedBlockHeight = storedBlockHeight; } + public Integer gapLimit() { + return gapLimit; + } + public int getGapLimit() { return gapLimit == null ? DEFAULT_LOOKAHEAD : gapLimit; } + public void gapLimit(Integer gapLimit) { + this.gapLimit = gapLimit; + } + public void setGapLimit(int gapLimit) { this.gapLimit = gapLimit; } @@ -141,6 +150,10 @@ public class Wallet { this.birthDate = birthDate; } + public boolean isMasterWallet() { + return masterWallet == null; + } + public Wallet getMasterWallet() { return masterWallet; } @@ -149,6 +162,22 @@ public class Wallet { this.masterWallet = masterWallet; } + public Wallet getChildWallet(String name) { + return childWallets.stream().filter(wallet -> wallet.getName().equals(name)).findFirst().orElse(null); + } + + public List getChildWallets() { + return childWallets; + } + + public void setChildWallets(List childWallets) { + this.childWallets = childWallets; + } + + public TreeSet getPurposeNodes() { + return purposeNodes; + } + public synchronized WalletNode getNode(KeyPurpose keyPurpose) { WalletNode purposeNode; Optional optionalPurposeNode = purposeNodes.stream().filter(node -> node.getKeyPurpose().equals(keyPurpose)).findFirst(); @@ -1108,6 +1137,9 @@ public class Wallet { public Wallet copy() { Wallet copy = new Wallet(name); + copy.setId(getId()); + copy.setMasterWallet(masterWallet); + copy.setChildWallets(childWallets); copy.setPolicyType(policyType); copy.setScriptType(scriptType); copy.setDefaultPolicy(defaultPolicy.copy()); diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/WalletNode.java b/src/main/java/com/sparrowwallet/drongo/wallet/WalletNode.java index 835e040..d97cc17 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/WalletNode.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/WalletNode.java @@ -7,7 +7,7 @@ import com.sparrowwallet.drongo.crypto.ChildNumber; import java.util.*; import java.util.stream.Collectors; -public class WalletNode implements Comparable { +public class WalletNode extends Persistable implements Comparable { private final String derivationPath; private String label; private TreeSet children = new TreeSet<>(); @@ -87,7 +87,7 @@ public class WalletNode implements Comparable { } public Set getChildren() { - return children == null ? null : Collections.unmodifiableSet(children); + return children; } public void setChildren(TreeSet children) { @@ -95,7 +95,7 @@ public class WalletNode implements Comparable { } public Set getTransactionOutputs() { - return transactionOutputs == null ? null : Collections.unmodifiableSet(transactionOutputs); + return transactionOutputs; } public void setTransactionOutputs(TreeSet transactionOutputs) { @@ -195,6 +195,7 @@ public class WalletNode implements Comparable { public WalletNode copy() { WalletNode copy = new WalletNode(derivationPath); + copy.setId(getId()); copy.setLabel(label); for(WalletNode child : getChildren()) { diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index af29d6a..d287fa9 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,7 +1,7 @@ open module com.sparrowwallet.drongo { requires org.bouncycastle.provider; requires de.mkammerer.argon2; - requires slf4j.api; + requires org.slf4j; requires logback.core; requires logback.classic; requires json.simple;