support database persistence

This commit is contained in:
Craig Raw 2021-06-10 12:07:20 +02:00
parent 42ffeb9565
commit 8e3d0d23c1
11 changed files with 77 additions and 14 deletions

View file

@ -55,7 +55,9 @@ dependencies {
} }
implementation ('ch.qos.logback:logback-classic:1.2.3') { implementation ('ch.qos.logback:logback-classic:1.2.3') {
exclude group: 'org.hamcrest', module: 'hamcrest-core' exclude group: 'org.hamcrest', module: 'hamcrest-core'
exclude group: 'org.slf4j'
} }
implementation ('org.slf4j:slf4j-api:1.7.30')
testImplementation ('junit:junit:4.12') { testImplementation ('junit:junit:4.12') {
exclude group: 'org.hamcrest', module: 'hamcrest-core' exclude group: 'org.hamcrest', module: 'hamcrest-core'
} }

View file

@ -2,13 +2,14 @@ package com.sparrowwallet.drongo.policy;
import com.sparrowwallet.drongo.protocol.ScriptType; import com.sparrowwallet.drongo.protocol.ScriptType;
import com.sparrowwallet.drongo.wallet.Keystore; import com.sparrowwallet.drongo.wallet.Keystore;
import com.sparrowwallet.drongo.wallet.Persistable;
import java.util.List; import java.util.List;
import static com.sparrowwallet.drongo.protocol.ScriptType.*; import static com.sparrowwallet.drongo.protocol.ScriptType.*;
import static com.sparrowwallet.drongo.policy.PolicyType.*; import static com.sparrowwallet.drongo.policy.PolicyType.*;
public class Policy { public class Policy extends Persistable {
private static final String DEFAULT_NAME = "Default"; private static final String DEFAULT_NAME = "Default";
private String name; private String name;
@ -23,6 +24,10 @@ public class Policy {
this.miniscript = miniscript; this.miniscript = miniscript;
} }
public String getName() {
return name;
}
public Miniscript getMiniscript() { public Miniscript getMiniscript() {
return miniscript; return miniscript;
} }
@ -57,6 +62,8 @@ public class Policy {
} }
public Policy copy() { public Policy copy() {
return new Policy(name, miniscript.copy()); Policy policy = new Policy(name, miniscript.copy());
policy.setId(getId());
return policy;
} }
} }

View file

@ -5,7 +5,7 @@ import com.sparrowwallet.drongo.protocol.Sha256Hash;
import java.util.Date; import java.util.Date;
import java.util.Objects; 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_CONFIRM = 6;
public static final int BLOCKS_TO_FULLY_CONFIRM = 100; public static final int BLOCKS_TO_FULLY_CONFIRM = 100;

View file

@ -96,6 +96,8 @@ public class BlockTransactionHashIndex extends BlockTransactionHash implements C
} }
public BlockTransactionHashIndex copy() { 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;
} }
} }

View file

@ -7,7 +7,7 @@ import com.sparrowwallet.drongo.crypto.*;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.*; 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 DEFAULT_SEED_ENTROPY_BITS = 128;
public static final int MAX_SEED_ENTROPY_BITS = 512; 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 = new DeterministicSeed(new ArrayList<>(mnemonicCode), needsPassphrase, creationTimeSeconds, type);
} }
seed.setId(getId());
seed.setPassphrase(passphrase); seed.setPassphrase(passphrase);
return seed; return seed;
} }

View file

@ -8,7 +8,7 @@ import com.sparrowwallet.drongo.crypto.*;
import java.util.List; import java.util.List;
public class Keystore { public class Keystore extends Persistable {
public static final String DEFAULT_LABEL = "Keystore 1"; public static final String DEFAULT_LABEL = "Keystore 1";
public static final int MAX_LABEL_LENGTH = 16; public static final int MAX_LABEL_LENGTH = 16;
@ -229,6 +229,7 @@ public class Keystore {
public Keystore copy() { public Keystore copy() {
Keystore copy = new Keystore(label); Keystore copy = new Keystore(label);
copy.setId(getId());
copy.setSource(source); copy.setSource(source);
copy.setWalletModel(walletModel); copy.setWalletModel(walletModel);
if(keyDerivation != null) { if(keyDerivation != null) {

View file

@ -6,7 +6,7 @@ import com.sparrowwallet.drongo.crypto.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays; import java.util.Arrays;
public class MasterPrivateExtendedKey implements EncryptableItem { public class MasterPrivateExtendedKey extends Persistable implements EncryptableItem {
private final byte[] privateKey; private final byte[] privateKey;
private final byte[] chainCode; private final byte[] chainCode;
@ -112,11 +112,15 @@ public class MasterPrivateExtendedKey implements EncryptableItem {
} }
public MasterPrivateExtendedKey copy() { public MasterPrivateExtendedKey copy() {
MasterPrivateExtendedKey copy;
if(isEncrypted()) { 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() { public void clear() {

View file

@ -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;
}
}

View file

@ -19,12 +19,13 @@ import java.util.stream.Collectors;
import static com.sparrowwallet.drongo.protocol.ScriptType.*; import static com.sparrowwallet.drongo.protocol.ScriptType.*;
import static com.sparrowwallet.drongo.protocol.Transaction.WITNESS_SCALE_FACTOR; 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 int DEFAULT_LOOKAHEAD = 20;
public static final String ALLOW_DERIVATIONS_MATCHING_OTHER_SCRIPT_TYPES_PROPERTY = "com.sparrowwallet.allowDerivationsMatchingOtherScriptTypes"; public static final String ALLOW_DERIVATIONS_MATCHING_OTHER_SCRIPT_TYPES_PROPERTY = "com.sparrowwallet.allowDerivationsMatchingOtherScriptTypes";
private String name; private String name;
private Wallet masterWallet; private Wallet masterWallet;
private List<Wallet> childWallets = new ArrayList<>();
private Network network = Network.get(); private Network network = Network.get();
private PolicyType policyType; private PolicyType policyType;
private ScriptType scriptType; private ScriptType scriptType;
@ -125,10 +126,18 @@ public class Wallet {
this.storedBlockHeight = storedBlockHeight; this.storedBlockHeight = storedBlockHeight;
} }
public Integer gapLimit() {
return gapLimit;
}
public int getGapLimit() { public int getGapLimit() {
return gapLimit == null ? DEFAULT_LOOKAHEAD : gapLimit; return gapLimit == null ? DEFAULT_LOOKAHEAD : gapLimit;
} }
public void gapLimit(Integer gapLimit) {
this.gapLimit = gapLimit;
}
public void setGapLimit(int gapLimit) { public void setGapLimit(int gapLimit) {
this.gapLimit = gapLimit; this.gapLimit = gapLimit;
} }
@ -141,6 +150,10 @@ public class Wallet {
this.birthDate = birthDate; this.birthDate = birthDate;
} }
public boolean isMasterWallet() {
return masterWallet == null;
}
public Wallet getMasterWallet() { public Wallet getMasterWallet() {
return masterWallet; return masterWallet;
} }
@ -149,6 +162,22 @@ public class Wallet {
this.masterWallet = masterWallet; this.masterWallet = masterWallet;
} }
public Wallet getChildWallet(String name) {
return childWallets.stream().filter(wallet -> wallet.getName().equals(name)).findFirst().orElse(null);
}
public List<Wallet> getChildWallets() {
return childWallets;
}
public void setChildWallets(List<Wallet> childWallets) {
this.childWallets = childWallets;
}
public TreeSet<WalletNode> getPurposeNodes() {
return purposeNodes;
}
public synchronized WalletNode getNode(KeyPurpose keyPurpose) { public synchronized WalletNode getNode(KeyPurpose keyPurpose) {
WalletNode purposeNode; WalletNode purposeNode;
Optional<WalletNode> optionalPurposeNode = purposeNodes.stream().filter(node -> node.getKeyPurpose().equals(keyPurpose)).findFirst(); Optional<WalletNode> optionalPurposeNode = purposeNodes.stream().filter(node -> node.getKeyPurpose().equals(keyPurpose)).findFirst();
@ -1108,6 +1137,9 @@ public class Wallet {
public Wallet copy() { public Wallet copy() {
Wallet copy = new Wallet(name); Wallet copy = new Wallet(name);
copy.setId(getId());
copy.setMasterWallet(masterWallet);
copy.setChildWallets(childWallets);
copy.setPolicyType(policyType); copy.setPolicyType(policyType);
copy.setScriptType(scriptType); copy.setScriptType(scriptType);
copy.setDefaultPolicy(defaultPolicy.copy()); copy.setDefaultPolicy(defaultPolicy.copy());

View file

@ -7,7 +7,7 @@ import com.sparrowwallet.drongo.crypto.ChildNumber;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class WalletNode implements Comparable<WalletNode> { public class WalletNode extends Persistable implements Comparable<WalletNode> {
private final String derivationPath; private final String derivationPath;
private String label; private String label;
private TreeSet<WalletNode> children = new TreeSet<>(); private TreeSet<WalletNode> children = new TreeSet<>();
@ -87,7 +87,7 @@ public class WalletNode implements Comparable<WalletNode> {
} }
public Set<WalletNode> getChildren() { public Set<WalletNode> getChildren() {
return children == null ? null : Collections.unmodifiableSet(children); return children;
} }
public void setChildren(TreeSet<WalletNode> children) { public void setChildren(TreeSet<WalletNode> children) {
@ -95,7 +95,7 @@ public class WalletNode implements Comparable<WalletNode> {
} }
public Set<BlockTransactionHashIndex> getTransactionOutputs() { public Set<BlockTransactionHashIndex> getTransactionOutputs() {
return transactionOutputs == null ? null : Collections.unmodifiableSet(transactionOutputs); return transactionOutputs;
} }
public void setTransactionOutputs(TreeSet<BlockTransactionHashIndex> transactionOutputs) { public void setTransactionOutputs(TreeSet<BlockTransactionHashIndex> transactionOutputs) {
@ -195,6 +195,7 @@ public class WalletNode implements Comparable<WalletNode> {
public WalletNode copy() { public WalletNode copy() {
WalletNode copy = new WalletNode(derivationPath); WalletNode copy = new WalletNode(derivationPath);
copy.setId(getId());
copy.setLabel(label); copy.setLabel(label);
for(WalletNode child : getChildren()) { for(WalletNode child : getChildren()) {

View file

@ -1,7 +1,7 @@
open module com.sparrowwallet.drongo { open module com.sparrowwallet.drongo {
requires org.bouncycastle.provider; requires org.bouncycastle.provider;
requires de.mkammerer.argon2; requires de.mkammerer.argon2;
requires slf4j.api; requires org.slf4j;
requires logback.core; requires logback.core;
requires logback.classic; requires logback.classic;
requires json.simple; requires json.simple;