mirror of
https://github.com/sparrowwallet/drongo.git
synced 2024-12-26 01:56:44 +00:00
support add child wallets from all wallet types, double postmix gap limit
This commit is contained in:
parent
c9e57fad01
commit
9a9a1b9254
2 changed files with 47 additions and 21 deletions
|
@ -16,9 +16,9 @@ public enum StandardAccount {
|
||||||
ACCOUNT_7("Account #7", new ChildNumber(7, true)),
|
ACCOUNT_7("Account #7", new ChildNumber(7, true)),
|
||||||
ACCOUNT_8("Account #8", new ChildNumber(8, true)),
|
ACCOUNT_8("Account #8", new ChildNumber(8, true)),
|
||||||
ACCOUNT_9("Account #9", new ChildNumber(9, true)),
|
ACCOUNT_9("Account #9", new ChildNumber(9, true)),
|
||||||
WHIRLPOOL_PREMIX("Premix", new ChildNumber(2147483645, true), ScriptType.P2WPKH),
|
WHIRLPOOL_PREMIX("Premix", new ChildNumber(2147483645, true), ScriptType.P2WPKH, null),
|
||||||
WHIRLPOOL_POSTMIX("Postmix", new ChildNumber(2147483646, true), ScriptType.P2WPKH),
|
WHIRLPOOL_POSTMIX("Postmix", new ChildNumber(2147483646, true), ScriptType.P2WPKH, Wallet.DEFAULT_LOOKAHEAD * 2),
|
||||||
WHIRLPOOL_BADBANK("Badbank", new ChildNumber(2147483644, true), ScriptType.P2WPKH);
|
WHIRLPOOL_BADBANK("Badbank", new ChildNumber(2147483644, true), ScriptType.P2WPKH, null);
|
||||||
|
|
||||||
public static final List<StandardAccount> WHIRLPOOL_ACCOUNTS = List.of(WHIRLPOOL_PREMIX, WHIRLPOOL_POSTMIX, WHIRLPOOL_BADBANK);
|
public static final List<StandardAccount> WHIRLPOOL_ACCOUNTS = List.of(WHIRLPOOL_PREMIX, WHIRLPOOL_POSTMIX, WHIRLPOOL_BADBANK);
|
||||||
public static final List<StandardAccount> WHIRLPOOL_MIX_ACCOUNTS = List.of(WHIRLPOOL_PREMIX, WHIRLPOOL_POSTMIX);
|
public static final List<StandardAccount> WHIRLPOOL_MIX_ACCOUNTS = List.of(WHIRLPOOL_PREMIX, WHIRLPOOL_POSTMIX);
|
||||||
|
@ -27,17 +27,20 @@ public enum StandardAccount {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.childNumber = childNumber;
|
this.childNumber = childNumber;
|
||||||
this.requiredScriptType = null;
|
this.requiredScriptType = null;
|
||||||
|
this.minimumGapLimit = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
StandardAccount(String name, ChildNumber childNumber, ScriptType requiredScriptType) {
|
StandardAccount(String name, ChildNumber childNumber, ScriptType requiredScriptType, Integer minimumGapLimit) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.childNumber = childNumber;
|
this.childNumber = childNumber;
|
||||||
this.requiredScriptType = requiredScriptType;
|
this.requiredScriptType = requiredScriptType;
|
||||||
|
this.minimumGapLimit = minimumGapLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final ChildNumber childNumber;
|
private final ChildNumber childNumber;
|
||||||
private final ScriptType requiredScriptType;
|
private final ScriptType requiredScriptType;
|
||||||
|
private final Integer minimumGapLimit;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -55,6 +58,10 @@ public enum StandardAccount {
|
||||||
return requiredScriptType;
|
return requiredScriptType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getMinimumGapLimit() {
|
||||||
|
return minimumGapLimit;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
|
|
|
@ -22,7 +22,7 @@ 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 extends Persistable {
|
public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||||
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";
|
||||||
|
|
||||||
|
@ -89,11 +89,7 @@ public class Wallet extends Persistable {
|
||||||
throw new IllegalStateException("Cannot add child wallet to existing child wallet");
|
throw new IllegalStateException("Cannot add child wallet to existing child wallet");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!childWallet.containsPrivateKeys()) {
|
if(childWallet.containsPrivateKeys() && childWallet.isEncrypted()) {
|
||||||
throw new IllegalStateException("Cannot derive child wallet xpub without private keys");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(childWallet.isEncrypted()) {
|
|
||||||
throw new IllegalStateException("Cannot derive child wallet xpub from encrypted wallet");
|
throw new IllegalStateException("Cannot derive child wallet xpub from encrypted wallet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +98,7 @@ public class Wallet extends Persistable {
|
||||||
childWallet.purposeNodes.clear();
|
childWallet.purposeNodes.clear();
|
||||||
childWallet.transactions.clear();
|
childWallet.transactions.clear();
|
||||||
childWallet.storedBlockHeight = null;
|
childWallet.storedBlockHeight = null;
|
||||||
childWallet.gapLimit = null;
|
childWallet.gapLimit = standardAccount.getMinimumGapLimit();
|
||||||
childWallet.birthDate = null;
|
childWallet.birthDate = null;
|
||||||
|
|
||||||
if(standardAccount.getRequiredScriptType() != null) {
|
if(standardAccount.getRequiredScriptType() != null) {
|
||||||
|
@ -111,16 +107,25 @@ public class Wallet extends Persistable {
|
||||||
|
|
||||||
for(Keystore keystore : childWallet.getKeystores()) {
|
for(Keystore keystore : childWallet.getKeystores()) {
|
||||||
List<ChildNumber> derivation = standardAccount.getRequiredScriptType() != null ? standardAccount.getRequiredScriptType().getDefaultDerivation() : keystore.getKeyDerivation().getDerivation();
|
List<ChildNumber> derivation = standardAccount.getRequiredScriptType() != null ? standardAccount.getRequiredScriptType().getDefaultDerivation() : keystore.getKeyDerivation().getDerivation();
|
||||||
List<ChildNumber> childDerivation = new ArrayList<>(derivation.subList(0, derivation.size() - 1));
|
List<ChildNumber> childDerivation;
|
||||||
childDerivation.add(standardAccount.getChildNumber());
|
if(childWallet.getScriptType().getAccount(KeyDerivation.writePath(derivation)) > -1) {
|
||||||
|
childDerivation = childWallet.getScriptType().getDefaultDerivation(standardAccount.getChildNumber().num());
|
||||||
|
} else {
|
||||||
|
childDerivation = derivation.isEmpty() ? new ArrayList<>() : new ArrayList<>(derivation.subList(0, derivation.size() - 1));
|
||||||
|
childDerivation.add(standardAccount.getChildNumber());
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
if(keystore.hasPrivateKey()) {
|
||||||
Keystore derivedKeystore = Keystore.fromSeed(keystore.getSeed(), childDerivation);
|
try {
|
||||||
keystore.setKeyDerivation(derivedKeystore.getKeyDerivation());
|
Keystore derivedKeystore = keystore.hasSeed() ? Keystore.fromSeed(keystore.getSeed(), childDerivation) : Keystore.fromMasterPrivateExtendedKey(keystore.getMasterPrivateExtendedKey(), childDerivation);
|
||||||
keystore.setExtendedPublicKey(derivedKeystore.getExtendedPublicKey());
|
keystore.setKeyDerivation(derivedKeystore.getKeyDerivation());
|
||||||
keystore.getSeed().setPassphrase(keystore.getSeed().getPassphrase());
|
keystore.setExtendedPublicKey(derivedKeystore.getExtendedPublicKey());
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
throw new IllegalStateException("Cannot derive keystore for " + standardAccount + " account", e);
|
throw new IllegalStateException("Cannot derive keystore for " + standardAccount + " account", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keystore.setKeyDerivation(new KeyDerivation(null, KeyDerivation.writePath(childDerivation)));
|
||||||
|
keystore.setExtendedPublicKey(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +159,11 @@ public class Wallet extends Persistable {
|
||||||
int keystoreAccount = getScriptType().getAccount(keystore.getKeyDerivation().getDerivationPath());
|
int keystoreAccount = getScriptType().getAccount(keystore.getKeyDerivation().getDerivationPath());
|
||||||
if(keystoreAccount != -1 && (index == -1 || keystoreAccount == index)) {
|
if(keystoreAccount != -1 && (index == -1 || keystoreAccount == index)) {
|
||||||
index = keystoreAccount;
|
index = keystoreAccount;
|
||||||
|
} else if(!keystore.getKeyDerivation().getDerivation().isEmpty()) {
|
||||||
|
keystoreAccount = keystore.getKeyDerivation().getDerivation().get(keystore.getKeyDerivation().getDerivation().size() - 1).num();
|
||||||
|
if(index == -1 || keystoreAccount == index) {
|
||||||
|
index = keystoreAccount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,7 +185,7 @@ public class Wallet extends Persistable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWhirlpoolChildWallet() {
|
public boolean isWhirlpoolChildWallet() {
|
||||||
return !isMasterWallet() && StandardAccount.WHIRLPOOL_ACCOUNTS.contains(getStandardAccountType());
|
return !isMasterWallet() && getStandardAccountType() != null && StandardAccount.WHIRLPOOL_ACCOUNTS.contains(getStandardAccountType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWhirlpoolMixWallet() {
|
public boolean isWhirlpoolMixWallet() {
|
||||||
|
@ -1458,6 +1468,15 @@ public class Wallet extends Persistable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Wallet other) {
|
||||||
|
if(getStandardAccountType() != null && other.getStandardAccountType() != null) {
|
||||||
|
return getStandardAccountType().ordinal() - other.getStandardAccountType().ordinal();
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAccountIndex() - other.getAccountIndex();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getFullName();
|
return getFullName();
|
||||||
|
|
Loading…
Reference in a new issue