add initial support for silent payments wallets
This commit is contained in:
parent
3a1712bdbf
commit
3b8677e59b
@ -110,6 +110,20 @@ public class KeyDerivation {
|
||||
return List.of(new ChildNumber(352, true), new ChildNumber(Network.get() == Network.MAINNET ? 0 : 1, true), new ChildNumber(Math.max(0, account), true));
|
||||
}
|
||||
|
||||
public static List<ChildNumber> getBip352ScanDerivation(List<ChildNumber> derivation) {
|
||||
List<ChildNumber> scanDerivation = new ArrayList<>(derivation);
|
||||
scanDerivation.add(new ChildNumber(1, true));
|
||||
scanDerivation.add(new ChildNumber(0, false));
|
||||
return Collections.unmodifiableList(scanDerivation);
|
||||
}
|
||||
|
||||
public static List<ChildNumber> getBip352SpendDerivation(List<ChildNumber> derivation) {
|
||||
List<ChildNumber> spendDerivation = new ArrayList<>(derivation);
|
||||
spendDerivation.add(new ChildNumber(0, true));
|
||||
spendDerivation.add(new ChildNumber(0, false));
|
||||
return Collections.unmodifiableList(spendDerivation);
|
||||
}
|
||||
|
||||
public KeyDerivation copy() {
|
||||
return new KeyDerivation(masterFingerprint, derivationPath);
|
||||
}
|
||||
|
||||
@ -3,16 +3,16 @@ package com.sparrowwallet.drongo;
|
||||
import java.util.Locale;
|
||||
|
||||
public enum Network {
|
||||
MAINNET("mainnet", "Mainnet", "mainnet", 0, "1", 5, "3", "bc", "sp", ExtendedKey.Header.xprv, ExtendedKey.Header.xpub, 128, 8332),
|
||||
TESTNET("testnet", "Testnet3", "testnet3", 111, "mn", 196, "2", "tb", "tsp", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 18332),
|
||||
REGTEST("regtest", "Regtest", "regtest", 111, "mn", 196, "2", "bcrt", "sprt", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 18443),
|
||||
SIGNET("signet", "Signet", "signet", 111, "mn", 196, "2", "tb", "tsp", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 38332),
|
||||
TESTNET4("testnet4", "Testnet4", "testnet4", 111, "mn", 196, "2", "tb", "tsp", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 48332);
|
||||
MAINNET("mainnet", "Mainnet", "mainnet", 0, "1", 5, "3", "bc", "sp", "spscan", "spspend", ExtendedKey.Header.xprv, ExtendedKey.Header.xpub, 128, 8332),
|
||||
TESTNET("testnet", "Testnet3", "testnet3", 111, "mn", 196, "2", "tb", "tsp", "tspscan", "tspspend", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 18332),
|
||||
REGTEST("regtest", "Regtest", "regtest", 111, "mn", 196, "2", "bcrt", "sprt", "tspscan", "tspspend", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 18443),
|
||||
SIGNET("signet", "Signet", "signet", 111, "mn", 196, "2", "tb", "tsp", "tspscan", "tspspend", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 38332),
|
||||
TESTNET4("testnet4", "Testnet4", "testnet4", 111, "mn", 196, "2", "tb", "tsp", "tspscan", "tspspend", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 48332);
|
||||
|
||||
public static final String BLOCK_HEIGHT_PROPERTY = "com.sparrowwallet.blockHeight";
|
||||
private static final Network[] CANONICAL_VALUES = new Network[]{MAINNET, TESTNET, REGTEST, SIGNET};
|
||||
|
||||
Network(String name, String displayName, String home, int p2pkhAddressHeader, String p2pkhAddressPrefix, int p2shAddressHeader, String p2shAddressPrefix, String bech32AddressHrp, String spAddressHrp, ExtendedKey.Header xprvHeader, ExtendedKey.Header xpubHeader, int dumpedPrivateKeyHeader, int defaultPort) {
|
||||
Network(String name, String displayName, String home, int p2pkhAddressHeader, String p2pkhAddressPrefix, int p2shAddressHeader, String p2shAddressPrefix, String bech32AddressHrp, String spAddressHrp, String spScanKeyHrp, String spSpendKeyHrp, ExtendedKey.Header xprvHeader, ExtendedKey.Header xpubHeader, int dumpedPrivateKeyHeader, int defaultPort) {
|
||||
this.name = name;
|
||||
this.displayName = displayName;
|
||||
this.home = home;
|
||||
@ -22,6 +22,8 @@ public enum Network {
|
||||
this.p2shAddressPrefix = p2shAddressPrefix;
|
||||
this.bech32AddressHrp = bech32AddressHrp;
|
||||
this.spAddressHrp = spAddressHrp;
|
||||
this.spScanKeyHrp = spScanKeyHrp;
|
||||
this.spSpendKeyHrp = spSpendKeyHrp;
|
||||
this.xprvHeader = xprvHeader;
|
||||
this.xpubHeader = xpubHeader;
|
||||
this.dumpedPrivateKeyHeader = dumpedPrivateKeyHeader;
|
||||
@ -37,6 +39,8 @@ public enum Network {
|
||||
private final String p2shAddressPrefix;
|
||||
private final String bech32AddressHrp;
|
||||
private final String spAddressHrp;
|
||||
private final String spScanKeyHrp;
|
||||
private final String spSpendKeyHrp;
|
||||
private final ExtendedKey.Header xprvHeader;
|
||||
private final ExtendedKey.Header xpubHeader;
|
||||
private final int dumpedPrivateKeyHeader;
|
||||
@ -76,6 +80,14 @@ public enum Network {
|
||||
return spAddressHrp;
|
||||
}
|
||||
|
||||
public String getSilentPaymentsKeyHrp() {
|
||||
return spScanKeyHrp;
|
||||
}
|
||||
|
||||
public String getSilentPaymentsSpendKeyHrp() {
|
||||
return spSpendKeyHrp;
|
||||
}
|
||||
|
||||
public ExtendedKey.Header getXprvHeader() {
|
||||
return xprvHeader;
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ public class OutputDescriptor {
|
||||
}
|
||||
|
||||
public boolean isCosigner() {
|
||||
return !isMultisig() && scriptType.isAllowed(PolicyType.MULTI);
|
||||
return !isMultisig() && scriptType.isAllowed(PolicyType.MULTI_HD);
|
||||
}
|
||||
|
||||
public ExtendedKey getSingletonExtendedPublicKey() {
|
||||
@ -266,7 +266,7 @@ public class OutputDescriptor {
|
||||
|
||||
public Wallet toWallet() {
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(isMultisig() || isCosigner() ? PolicyType.MULTI : PolicyType.SINGLE);
|
||||
wallet.setPolicyType(isMultisig() || isCosigner() ? PolicyType.MULTI_HD : PolicyType.SINGLE_HD);
|
||||
wallet.setScriptType(scriptType);
|
||||
|
||||
for(Map.Entry<ExtendedKey,KeyDerivation> extKeyEntry : extendedPublicKeys.entrySet()) {
|
||||
@ -318,7 +318,7 @@ public class OutputDescriptor {
|
||||
keystore.setExtendedPublicKey(extendedKey);
|
||||
setKeystoreLabel(keystore);
|
||||
wallet.getKeystores().add(keystore);
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(isCosigner() ? PolicyType.MULTI : PolicyType.SINGLE, wallet.getScriptType(), wallet.getKeystores(), 1));
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(isCosigner() ? PolicyType.MULTI_HD : PolicyType.SINGLE_HD, wallet.getScriptType(), wallet.getKeystores(), 1));
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ public class Bip322 {
|
||||
}
|
||||
|
||||
private static void checkScriptType(ScriptType scriptType) {
|
||||
if(!scriptType.isAllowed(PolicyType.SINGLE)) {
|
||||
if(!scriptType.isAllowed(PolicyType.SINGLE_HD)) {
|
||||
throw new UnsupportedOperationException("Only singlesig addresses are currently supported");
|
||||
}
|
||||
|
||||
|
||||
@ -4,8 +4,9 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Miniscript {
|
||||
private static final Pattern SINGLE_PATTERN = Pattern.compile("pkh?\\(");
|
||||
private static final Pattern KEYHASH_PATTERN = Pattern.compile("pkh?\\(");
|
||||
private static final Pattern TAPROOT_PATTERN = Pattern.compile("tr\\(");
|
||||
private static final Pattern SILENT_PAYMENTS_PATTERN = Pattern.compile("sp\\(");
|
||||
private static final Pattern MULTI_PATTERN = Pattern.compile("multi\\((\\d+)");
|
||||
|
||||
private String script;
|
||||
@ -23,7 +24,7 @@ public class Miniscript {
|
||||
}
|
||||
|
||||
public int getNumSignaturesRequired() {
|
||||
Matcher singleMatcher = SINGLE_PATTERN.matcher(script);
|
||||
Matcher singleMatcher = KEYHASH_PATTERN.matcher(script);
|
||||
if(singleMatcher.find()) {
|
||||
return 1;
|
||||
}
|
||||
@ -33,6 +34,11 @@ public class Miniscript {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Matcher silentPaymentsMatcher = SILENT_PAYMENTS_PATTERN.matcher(script);
|
||||
if(silentPaymentsMatcher.find()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Matcher multiMatcher = MULTI_PATTERN.matcher(script);
|
||||
if(multiMatcher.find()) {
|
||||
String threshold = multiMatcher.group(1);
|
||||
|
||||
@ -41,11 +41,11 @@ public class Policy extends Persistable {
|
||||
}
|
||||
|
||||
public static Policy getPolicy(PolicyType policyType, ScriptType scriptType, List<Keystore> keystores, Integer threshold) {
|
||||
if(SINGLE.equals(policyType)) {
|
||||
if(SINGLE_HD.equals(policyType)) {
|
||||
return new Policy(new Miniscript(scriptType.getDescriptor() + keystores.get(0).getScriptName() + scriptType.getCloseDescriptor()));
|
||||
}
|
||||
|
||||
if(MULTI.equals(policyType)) {
|
||||
if(MULTI_HD.equals(policyType)) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(scriptType.getDescriptor());
|
||||
builder.append(MULTISIG.getDescriptor());
|
||||
@ -58,6 +58,10 @@ public class Policy extends Persistable {
|
||||
return new Policy(new Miniscript(builder.toString()));
|
||||
}
|
||||
|
||||
if(SINGLE_SP.equals(policyType)) {
|
||||
return new Policy(new Miniscript("sp(" + keystores.get(0).getScriptName() + ")"));
|
||||
}
|
||||
|
||||
throw new PolicyException("No standard policy for " + policyType + " policy with script type " + scriptType);
|
||||
}
|
||||
|
||||
|
||||
@ -5,13 +5,15 @@ import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||
import static com.sparrowwallet.drongo.protocol.ScriptType.*;
|
||||
|
||||
public enum PolicyType {
|
||||
SINGLE("Single Signature", P2WPKH), MULTI("Multi Signature", P2WSH), CUSTOM("Custom", P2WSH);
|
||||
SINGLE_HD("Single Signature HD", "Single Signature HD", P2WPKH), MULTI_HD("Multi Signature HD", "Multi Signature HD", P2WSH), SINGLE_SP("Single Signature SP", "Single Signature SP (Silent Payments)", P2TR);
|
||||
|
||||
private String name;
|
||||
private ScriptType defaultScriptType;
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final ScriptType defaultScriptType;
|
||||
|
||||
PolicyType(String name, ScriptType defaultScriptType) {
|
||||
PolicyType(String name, String description, ScriptType defaultScriptType) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.defaultScriptType = defaultScriptType;
|
||||
}
|
||||
|
||||
@ -19,6 +21,10 @@ public enum PolicyType {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public ScriptType getDefaultScriptType() {
|
||||
return defaultScriptType;
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ public enum ScriptType {
|
||||
|
||||
@Override
|
||||
public List<PolicyType> getAllowedPolicyTypes() {
|
||||
return List.of(SINGLE);
|
||||
return List.of(SINGLE_HD);
|
||||
}
|
||||
},
|
||||
P2PKH("P2PKH", "Legacy (P2PKH)", "m/44'/0'/0'") {
|
||||
@ -251,7 +251,7 @@ public enum ScriptType {
|
||||
|
||||
@Override
|
||||
public List<PolicyType> getAllowedPolicyTypes() {
|
||||
return List.of(SINGLE);
|
||||
return List.of(SINGLE_HD);
|
||||
}
|
||||
},
|
||||
MULTISIG("Bare Multisig", "Bare Multisig", "m/44'/0'/0'") {
|
||||
@ -442,7 +442,7 @@ public enum ScriptType {
|
||||
|
||||
@Override
|
||||
public List<PolicyType> getAllowedPolicyTypes() {
|
||||
return List.of(MULTI);
|
||||
return List.of(MULTI_HD);
|
||||
}
|
||||
},
|
||||
P2SH("P2SH", "Legacy (P2SH)", "m/45'") {
|
||||
@ -572,7 +572,7 @@ public enum ScriptType {
|
||||
|
||||
@Override
|
||||
public List<PolicyType> getAllowedPolicyTypes() {
|
||||
return List.of(MULTI);
|
||||
return List.of(MULTI_HD);
|
||||
}
|
||||
},
|
||||
P2SH_P2WPKH("P2SH-P2WPKH", "Nested Segwit (P2SH-P2WPKH)", "m/49'/0'/0'") {
|
||||
@ -680,7 +680,7 @@ public enum ScriptType {
|
||||
|
||||
@Override
|
||||
public List<PolicyType> getAllowedPolicyTypes() {
|
||||
return List.of(SINGLE);
|
||||
return List.of(SINGLE_HD);
|
||||
}
|
||||
},
|
||||
P2SH_P2WSH("P2SH-P2WSH", "Nested Segwit (P2SH-P2WSH)", "m/48'/0'/0'/1'") {
|
||||
@ -786,7 +786,7 @@ public enum ScriptType {
|
||||
|
||||
@Override
|
||||
public List<PolicyType> getAllowedPolicyTypes() {
|
||||
return List.of(MULTI, CUSTOM);
|
||||
return List.of(MULTI_HD);
|
||||
}
|
||||
},
|
||||
P2WPKH("P2WPKH", "Native Segwit (P2WPKH)", "m/84'/0'/0'") {
|
||||
@ -896,7 +896,7 @@ public enum ScriptType {
|
||||
|
||||
@Override
|
||||
public List<PolicyType> getAllowedPolicyTypes() {
|
||||
return List.of(SINGLE);
|
||||
return List.of(SINGLE_HD);
|
||||
}
|
||||
},
|
||||
P2WSH("P2WSH", "Native Segwit (P2WSH)", "m/48'/0'/0'/2'") {
|
||||
@ -1012,7 +1012,7 @@ public enum ScriptType {
|
||||
|
||||
@Override
|
||||
public List<PolicyType> getAllowedPolicyTypes() {
|
||||
return List.of(MULTI, CUSTOM);
|
||||
return List.of(MULTI_HD);
|
||||
}
|
||||
},
|
||||
P2TR("P2TR", "Taproot (P2TR)", "m/86'/0'/0'") {
|
||||
@ -1132,7 +1132,7 @@ public enum ScriptType {
|
||||
|
||||
@Override
|
||||
public List<PolicyType> getAllowedPolicyTypes() {
|
||||
return List.of(SINGLE);
|
||||
return List.of(SINGLE_HD, SINGLE_SP);
|
||||
}
|
||||
},
|
||||
P2A("P2A", "Anchor (P2A)", "m/86'/0'/0'") {
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
package com.sparrowwallet.drongo.silentpayments;
|
||||
|
||||
import com.sparrowwallet.drongo.KeyDerivation;
|
||||
import com.sparrowwallet.drongo.Network;
|
||||
import com.sparrowwallet.drongo.Utils;
|
||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||
import com.sparrowwallet.drongo.policy.Policy;
|
||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||
import com.sparrowwallet.drongo.protocol.Bech32;
|
||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||
import com.sparrowwallet.drongo.wallet.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class SilentPaymentScanAddress extends SilentPaymentAddress {
|
||||
public SilentPaymentScanAddress(ECKey scanPrivateKey, ECKey spendPublicKey) {
|
||||
super(scanPrivateKey, spendPublicKey);
|
||||
@ -35,11 +40,11 @@ public class SilentPaymentScanAddress extends SilentPaymentAddress {
|
||||
|
||||
public static SilentPaymentScanAddress from(DeterministicSeed deterministicSeed, int account) throws MnemonicException {
|
||||
Wallet spWallet = new Wallet();
|
||||
spWallet.setPolicyType(PolicyType.SINGLE);
|
||||
spWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
spWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Keystore spKeystore = Keystore.fromSeed(deterministicSeed, KeyDerivation.getBip352Derivation(account));
|
||||
spWallet.getKeystores().add(spKeystore);
|
||||
spWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, spWallet.getKeystores(), 1));
|
||||
spWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, spWallet.getKeystores(), 1));
|
||||
|
||||
WalletNode spendNode = new WalletNode(spWallet, "m/0'/0");
|
||||
WalletNode scanNode = new WalletNode(spWallet, "m/1'/0");
|
||||
@ -50,4 +55,27 @@ public class SilentPaymentScanAddress extends SilentPaymentAddress {
|
||||
public static SilentPaymentScanAddress from(ECKey scanPrivateKey, ECKey spendPublicKey) {
|
||||
return new SilentPaymentScanAddress(scanPrivateKey, spendPublicKey);
|
||||
}
|
||||
|
||||
public SilentPaymentScanAddress copy() {
|
||||
return new SilentPaymentScanAddress(getScanKey(), getSpendKey());
|
||||
}
|
||||
|
||||
public String toKeyString() {
|
||||
return Bech32.encode(Network.get().getSilentPaymentsKeyHrp(), 0, Bech32.Encoding.BECH32M, toBytes());
|
||||
}
|
||||
|
||||
public byte[] toBytes() {
|
||||
return Utils.concat(getScanKey().getPrivKeyBytes(), getSpendKey().getPubKey(true));
|
||||
}
|
||||
|
||||
public static SilentPaymentScanAddress fromBytes(byte[] bytes) {
|
||||
if(bytes == null || bytes.length != 65) {
|
||||
throw new IllegalArgumentException("Invalid silent payments scan address serialization, must be 65 bytes long");
|
||||
}
|
||||
|
||||
ECKey scanKey = ECKey.fromPrivate(Arrays.copyOfRange(bytes, 0, 32));
|
||||
ECKey spendKey = ECKey.fromPublicOnly(Arrays.copyOfRange(bytes, 32, 65));
|
||||
|
||||
return new SilentPaymentScanAddress(scanKey, spendKey);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,8 +10,6 @@ import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTInput;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* This is a special wallet that is used solely to finalize a fully signed PSBT by reading from the partial signatures and UTXO scriptPubKey
|
||||
@ -67,7 +65,7 @@ public class FinalizingPSBTWallet extends Wallet {
|
||||
setGapLimit(0);
|
||||
purposeNode.setChildren(new TreeSet<>());
|
||||
|
||||
setPolicyType(numSignatures == 1 ? PolicyType.SINGLE : PolicyType.MULTI);
|
||||
setPolicyType(numSignatures == 1 ? PolicyType.SINGLE_HD : PolicyType.MULTI_HD);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -9,11 +9,11 @@ import com.sparrowwallet.drongo.bip47.PaymentCode;
|
||||
import com.sparrowwallet.drongo.crypto.*;
|
||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||
import com.sparrowwallet.drongo.silentpayments.SilentPaymentScanAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Keystore extends Persistable {
|
||||
@ -28,6 +28,7 @@ public class Keystore extends Persistable {
|
||||
private KeyDerivation keyDerivation;
|
||||
private ExtendedKey extendedPublicKey;
|
||||
private PaymentCode externalPaymentCode;
|
||||
private SilentPaymentScanAddress silentPaymentScanAddress;
|
||||
private byte[] deviceRegistration;
|
||||
private MasterPrivateExtendedKey masterPrivateExtendedKey;
|
||||
private DeterministicSeed seed;
|
||||
@ -106,6 +107,14 @@ public class Keystore extends Persistable {
|
||||
this.externalPaymentCode = paymentCode;
|
||||
}
|
||||
|
||||
public SilentPaymentScanAddress getSilentPaymentScanAddress() {
|
||||
return silentPaymentScanAddress;
|
||||
}
|
||||
|
||||
public void setSilentPaymentScanAddress(SilentPaymentScanAddress silentPaymentScanAddress) {
|
||||
this.silentPaymentScanAddress = silentPaymentScanAddress;
|
||||
}
|
||||
|
||||
public byte[] getDeviceRegistration() {
|
||||
return deviceRegistration;
|
||||
}
|
||||
@ -310,8 +319,8 @@ public class Keystore extends Persistable {
|
||||
throw new InvalidKeystoreException("No key derivation specified");
|
||||
}
|
||||
|
||||
if(extendedPublicKey == null) {
|
||||
throw new InvalidKeystoreException("No extended public key specified");
|
||||
if(extendedPublicKey == null && silentPaymentScanAddress == null) {
|
||||
throw new InvalidKeystoreException("No extended public key or silent payment scan address specified");
|
||||
}
|
||||
|
||||
if(label.isEmpty()) {
|
||||
@ -385,6 +394,9 @@ public class Keystore extends Persistable {
|
||||
if(bip47ExtendedPrivateKey != null) {
|
||||
copy.setBip47ExtendedPrivateKey(bip47ExtendedPrivateKey.copy());
|
||||
}
|
||||
if(silentPaymentScanAddress != null) {
|
||||
copy.setSilentPaymentScanAddress(silentPaymentScanAddress.copy());
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@ -416,12 +428,17 @@ public class Keystore extends Persistable {
|
||||
keystore.setKeyDerivation(new KeyDerivation(masterFingerprint, KeyDerivation.writePath(derivation)));
|
||||
keystore.setExtendedPublicKey(ExtendedKey.fromDescriptor(xpub.toString()));
|
||||
|
||||
int account = ScriptType.getScriptTypesForPolicyType(PolicyType.SINGLE).stream()
|
||||
int account = ScriptType.getScriptTypesForPolicyType(PolicyType.SINGLE_HD).stream()
|
||||
.mapToInt(scriptType -> scriptType.getAccount(keystore.getKeyDerivation().getDerivationPath())).filter(idx -> idx > -1).findFirst().orElse(0);
|
||||
List<ChildNumber> bip47Derivation = KeyDerivation.getBip47Derivation(account);
|
||||
DeterministicKey bip47Key = xprv.getKey(bip47Derivation);
|
||||
ExtendedKey bip47ExtendedPrivateKey = new ExtendedKey(bip47Key, bip47Key.getParentFingerprint(), bip47Derivation.get(bip47Derivation.size() - 1));
|
||||
keystore.setBip47ExtendedPrivateKey(ExtendedKey.fromDescriptor(bip47ExtendedPrivateKey.toString()));
|
||||
|
||||
DeterministicKey scanKey = xprv.getKey(KeyDerivation.getBip352ScanDerivation(derivation));
|
||||
DeterministicKey spendKey = xprv.getKey(KeyDerivation.getBip352SpendDerivation(derivation));
|
||||
SilentPaymentScanAddress spScanAddress = new SilentPaymentScanAddress(ECKey.fromPrivate(scanKey.getPrivKey()), ECKey.fromPublicOnly(spendKey));
|
||||
keystore.setSilentPaymentScanAddress(spScanAddress);
|
||||
}
|
||||
|
||||
public boolean isEncrypted() {
|
||||
|
||||
@ -187,7 +187,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
}
|
||||
|
||||
public Wallet addChildWallet(PaymentCode externalPaymentCode, ScriptType childScriptType, String label) {
|
||||
if(policyType != PolicyType.SINGLE) {
|
||||
if(policyType != PolicyType.SINGLE_HD) {
|
||||
throw new IllegalStateException("Cannot add payment code wallet to " + policyType.getName() + " wallet");
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
|
||||
Wallet childWallet = new Wallet(childScriptType + "-" + externalPaymentCode.toString());
|
||||
childWallet.setLabel(label);
|
||||
childWallet.setPolicyType(PolicyType.SINGLE);
|
||||
childWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
childWallet.setScriptType(childScriptType);
|
||||
childWallet.setGapLimit(5);
|
||||
|
||||
@ -217,7 +217,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
keystore.setExtendedPublicKey(new ExtendedKey(pubKey, keystore.getBip47ExtendedPrivateKey().getParentFingerprint(), derivation.get(derivation.size() - 1)));
|
||||
|
||||
childWallet.getKeystores().add(keystore);
|
||||
childWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, scriptType, childWallet.getKeystores(), 1));
|
||||
childWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, scriptType, childWallet.getKeystores(), 1));
|
||||
|
||||
childWallet.setMasterWallet(this);
|
||||
getChildWallets().add(childWallet);
|
||||
@ -251,7 +251,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
}
|
||||
|
||||
public boolean hasPaymentCode() {
|
||||
return getKeystores().size() == 1 && getKeystores().get(0).getBip47ExtendedPrivateKey() != null && policyType == PolicyType.SINGLE
|
||||
return getKeystores().size() == 1 && getKeystores().get(0).getBip47ExtendedPrivateKey() != null && policyType == PolicyType.SINGLE_HD
|
||||
&& PaymentCode.SEGWIT_SCRIPT_TYPES.contains(scriptType);
|
||||
}
|
||||
|
||||
@ -266,7 +266,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
public Wallet getNotificationWallet() {
|
||||
if(isMasterWallet() && hasPaymentCode()) {
|
||||
Wallet notificationWallet = new Wallet();
|
||||
notificationWallet.setPolicyType(PolicyType.SINGLE);
|
||||
notificationWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
notificationWallet.setScriptType(ScriptType.P2PKH);
|
||||
notificationWallet.setGapLimit(0);
|
||||
|
||||
@ -280,7 +280,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
keystore.setBip47ExtendedPrivateKey(masterKeystore.getBip47ExtendedPrivateKey());
|
||||
|
||||
notificationWallet.getKeystores().add(keystore);
|
||||
notificationWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2PKH, notificationWallet.getKeystores(), 1));
|
||||
notificationWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2PKH, notificationWallet.getKeystores(), 1));
|
||||
|
||||
return notificationWallet;
|
||||
}
|
||||
@ -322,7 +322,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
}
|
||||
|
||||
public boolean canSendSilentPayments() {
|
||||
return getKeystores().size() == 1 && policyType == PolicyType.SINGLE && SilentPayment.VALID_INPUT_SCRIPT_TYPES.contains(scriptType);
|
||||
return getKeystores().size() == 1 && (policyType == PolicyType.SINGLE_HD || policyType == PolicyType.SINGLE_SP) && SilentPayment.VALID_INPUT_SCRIPT_TYPES.contains(scriptType);
|
||||
}
|
||||
|
||||
public StandardAccount getStandardAccountType() {
|
||||
@ -661,10 +661,8 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
}
|
||||
|
||||
public ECKey getPubKey(WalletNode node) {
|
||||
if(policyType == PolicyType.MULTI) {
|
||||
if(policyType == PolicyType.MULTI_HD) {
|
||||
throw new IllegalStateException("Attempting to retrieve a single key for a multisig policy wallet");
|
||||
} else if(policyType == PolicyType.CUSTOM) {
|
||||
throw new UnsupportedOperationException("Cannot determine a public key for a custom policy");
|
||||
}
|
||||
|
||||
Keystore keystore = getKeystores().get(0);
|
||||
@ -672,20 +670,18 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
}
|
||||
|
||||
public List<ECKey> getPubKeys(WalletNode node) {
|
||||
if(policyType == PolicyType.SINGLE) {
|
||||
if(policyType == PolicyType.SINGLE_HD || policyType == PolicyType.SINGLE_SP) {
|
||||
throw new IllegalStateException("Attempting to retrieve multiple keys for a singlesig policy wallet");
|
||||
} else if(policyType == PolicyType.CUSTOM) {
|
||||
throw new UnsupportedOperationException("Cannot determine public keys for a custom policy");
|
||||
}
|
||||
|
||||
return getKeystores().stream().map(keystore -> keystore.getPubKey(node)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Address getAddress(WalletNode node) {
|
||||
if(policyType == PolicyType.SINGLE) {
|
||||
if(policyType == PolicyType.SINGLE_HD || policyType == PolicyType.SINGLE_SP) {
|
||||
ECKey pubKey = node.getPubKey();
|
||||
return scriptType.getAddress(pubKey);
|
||||
} else if(policyType == PolicyType.MULTI) {
|
||||
} else if(policyType == PolicyType.MULTI_HD) {
|
||||
List<ECKey> pubKeys = node.getPubKeys();
|
||||
Script script = ScriptType.MULTISIG.getOutputScript(defaultPolicy.getNumSignaturesRequired(), pubKeys);
|
||||
return scriptType.getAddress(script);
|
||||
@ -695,10 +691,10 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
}
|
||||
|
||||
public Script getOutputScript(WalletNode node) {
|
||||
if(policyType == PolicyType.SINGLE) {
|
||||
if(policyType == PolicyType.SINGLE_HD || policyType == PolicyType.SINGLE_SP) {
|
||||
ECKey pubKey = node.getPubKey();
|
||||
return scriptType.getOutputScript(pubKey);
|
||||
} else if(policyType == PolicyType.MULTI) {
|
||||
} else if(policyType == PolicyType.MULTI_HD) {
|
||||
List<ECKey> pubKeys = node.getPubKeys();
|
||||
Script script = ScriptType.MULTISIG.getOutputScript(defaultPolicy.getNumSignaturesRequired(), pubKeys);
|
||||
return scriptType.getOutputScript(script);
|
||||
@ -708,10 +704,10 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
}
|
||||
|
||||
public String getOutputDescriptor(WalletNode node) {
|
||||
if(policyType == PolicyType.SINGLE) {
|
||||
if(policyType == PolicyType.SINGLE_HD || policyType == PolicyType.SINGLE_SP) {
|
||||
ECKey pubKey = node.getPubKey();
|
||||
return scriptType.getOutputDescriptor(pubKey);
|
||||
} else if(policyType == PolicyType.MULTI) {
|
||||
} else if(policyType == PolicyType.MULTI_HD) {
|
||||
List<ECKey> pubKeys = node.getPubKeys();
|
||||
Script script = ScriptType.MULTISIG.getOutputScript(defaultPolicy.getNumSignaturesRequired(), pubKeys);
|
||||
return scriptType.getOutputDescriptor(script);
|
||||
@ -1004,11 +1000,11 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
TransactionOutput prevTxOut = transaction.addOutput(1L, receiveNode.getAddress());
|
||||
|
||||
TransactionInput txInput = null;
|
||||
if(getPolicyType().equals(PolicyType.SINGLE)) {
|
||||
if(getPolicyType().equals(PolicyType.SINGLE_HD) || getPolicyType().equals(PolicyType.SINGLE_SP)) {
|
||||
ECKey pubKey = receiveNode.getPubKey();
|
||||
TransactionSignature signature = TransactionSignature.dummy(getScriptType().getSignatureType());
|
||||
txInput = getScriptType().addSpendingInput(transaction, prevTxOut, pubKey, signature);
|
||||
} else if(getPolicyType().equals(PolicyType.MULTI)) {
|
||||
} else if(getPolicyType().equals(PolicyType.MULTI_HD)) {
|
||||
List<ECKey> pubKeys = receiveNode.getPubKeys();
|
||||
int threshold = getDefaultPolicy().getNumSignaturesRequired();
|
||||
Map<ECKey, TransactionSignature> pubKeySignatures = new TreeMap<>(new ECKey.LexicographicECKeyComparator());
|
||||
@ -1231,10 +1227,10 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
|
||||
public static TransactionInput addDummySpendingInput(Transaction transaction, WalletNode walletNode, TransactionOutput prevTxOut) {
|
||||
Wallet signingWallet = walletNode.getWallet();
|
||||
if(signingWallet.getPolicyType().equals(PolicyType.SINGLE)) {
|
||||
if(signingWallet.getPolicyType().equals(PolicyType.SINGLE_HD) || signingWallet.getPolicyType().equals(PolicyType.SINGLE_SP)) {
|
||||
ECKey pubKey = walletNode.getPubKey();
|
||||
return signingWallet.getScriptType().addSpendingInput(transaction, prevTxOut, pubKey, TransactionSignature.dummy(signingWallet.getScriptType().getSignatureType()));
|
||||
} else if(signingWallet.getPolicyType().equals(PolicyType.MULTI)) {
|
||||
} else if(signingWallet.getPolicyType().equals(PolicyType.MULTI_HD)) {
|
||||
List<ECKey> pubKeys = walletNode.getPubKeys();
|
||||
int threshold = signingWallet.getDefaultPolicy().getNumSignaturesRequired();
|
||||
Map<ECKey, TransactionSignature> pubKeySignatures = new TreeMap<>(new ECKey.LexicographicECKeyComparator());
|
||||
@ -1585,10 +1581,6 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
}
|
||||
|
||||
private WalletNode matchDerivation(KeyDerivation keyDerivation, Script scriptPubKey) {
|
||||
if(policyType == PolicyType.CUSTOM) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for(Keystore keystore : getKeystores()) {
|
||||
ECKey derivedKey = keystore.getPubKeyForDerivation(keyDerivation);
|
||||
if(derivedKey == null) {
|
||||
@ -1807,7 +1799,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
Transaction transaction = new Transaction();
|
||||
|
||||
TransactionInput finalizedTxInput;
|
||||
if(getPolicyType().equals(PolicyType.SINGLE)) {
|
||||
if(getPolicyType().equals(PolicyType.SINGLE_HD) || getPolicyType().equals(PolicyType.SINGLE_SP)) {
|
||||
ECKey pubKey = signingNode.getPubKey();
|
||||
TransactionSignature transactionSignature = psbtInput.isTaproot() ? psbtInput.getTapKeyPathSignature() : psbtInput.getPartialSignature(pubKey);
|
||||
if(transactionSignature == null) {
|
||||
@ -1815,7 +1807,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
}
|
||||
|
||||
finalizedTxInput = signingNode.getWallet().getScriptType().addSpendingInput(transaction, utxo, pubKey, transactionSignature);
|
||||
} else if(getPolicyType().equals(PolicyType.MULTI)) {
|
||||
} else if(getPolicyType().equals(PolicyType.MULTI_HD)) {
|
||||
List<ECKey> pubKeys = signingNode.getPubKeys();
|
||||
|
||||
Map<ECKey, TransactionSignature> pubKeySignatures = new TreeMap<>(new ECKey.LexicographicECKeyComparator());
|
||||
@ -1950,14 +1942,22 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
||||
throw new InvalidWalletException("Cannot determine number of required signatures to sign a transaction");
|
||||
}
|
||||
|
||||
if(policyType.equals(PolicyType.SINGLE) && (numSigs != 1 || keystores.size() != 1)) {
|
||||
if((policyType.equals(PolicyType.SINGLE_HD) || policyType.equals(PolicyType.SINGLE_SP)) && (numSigs != 1 || keystores.size() != 1)) {
|
||||
throw new InvalidWalletException(policyType + " wallet needs " + numSigs + " and has " + keystores.size() + " keystores");
|
||||
}
|
||||
|
||||
if(policyType.equals(PolicyType.MULTI) && (numSigs < 1 || numSigs > keystores.size())) {
|
||||
if(policyType.equals(PolicyType.MULTI_HD) && (numSigs < 1 || numSigs > keystores.size())) {
|
||||
throw new InvalidWalletException(policyType + " wallet needs " + numSigs + " and has " + keystores.size() + " keystores");
|
||||
}
|
||||
|
||||
if(policyType.equals(PolicyType.SINGLE_HD) && keystores.getFirst().getExtendedPublicKey() == null) {
|
||||
throw new InvalidWalletException(policyType + " wallet needs an extended public key");
|
||||
}
|
||||
|
||||
if(policyType.equals(PolicyType.SINGLE_SP) && keystores.getFirst().getSilentPaymentScanAddress() == null) {
|
||||
throw new InvalidWalletException(policyType + " wallet needs a silent payment scan address");
|
||||
}
|
||||
|
||||
if(containsDuplicateKeystoreLabels()) {
|
||||
throw new InvalidWalletException("Wallet keystores have duplicate labels");
|
||||
}
|
||||
|
||||
@ -92,22 +92,22 @@ public class PaymentCodeTest {
|
||||
List<String> receiveWords = bip39MnemonicCode.toMnemonic(receiveEntropy);
|
||||
DeterministicSeed receiveSeed = new DeterministicSeed(receiveWords, "", 0, DeterministicSeed.Type.BIP39);
|
||||
Wallet receiveWallet = new Wallet();
|
||||
receiveWallet.setPolicyType(PolicyType.SINGLE);
|
||||
receiveWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
receiveWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Keystore receiveKeystore = Keystore.fromSeed(receiveSeed, receiveWallet.getScriptType().getDefaultDerivation());
|
||||
receiveWallet.getKeystores().add(receiveKeystore);
|
||||
receiveWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, receiveWallet.getKeystores(), 1));
|
||||
receiveWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, receiveWallet.getKeystores(), 1));
|
||||
|
||||
byte[] sendEntropy = new byte[128];
|
||||
secureRandom.nextBytes(sendEntropy);
|
||||
List<String> sendWords = bip39MnemonicCode.toMnemonic(sendEntropy);
|
||||
DeterministicSeed sendSeed = new DeterministicSeed(sendWords, "pp", 0, DeterministicSeed.Type.BIP39);
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Keystore sendKeystore = Keystore.fromSeed(sendSeed, sendWallet.getScriptType().getDefaultDerivation());
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
PaymentCode paymentCode = sendWallet.getPaymentCode();
|
||||
PaymentCode externalPaymentCode = receiveWallet.getPaymentCode();
|
||||
@ -165,10 +165,10 @@ public class PaymentCodeTest {
|
||||
public void testChildWallet() throws MnemonicException, InvalidPaymentCodeException {
|
||||
DeterministicSeed aliceSeed = new DeterministicSeed("response seminar brave tip suit recall often sound stick owner lottery motion", "", 0, DeterministicSeed.Type.BIP39);
|
||||
Wallet aliceWallet = new Wallet();
|
||||
aliceWallet.setPolicyType(PolicyType.SINGLE);
|
||||
aliceWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
aliceWallet.setScriptType(ScriptType.P2PKH);
|
||||
aliceWallet.getKeystores().add(Keystore.fromSeed(aliceSeed, aliceWallet.getScriptType().getDefaultDerivation()));
|
||||
aliceWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2PKH, aliceWallet.getKeystores(), 1));
|
||||
aliceWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2PKH, aliceWallet.getKeystores(), 1));
|
||||
|
||||
PaymentCode paymentCodeBob = new PaymentCode("PM8TJS2JxQ5ztXUpBBRnpTbcUXbUHy2T1abfrb3KkAAtMEGNbey4oumH7Hc578WgQJhPjBxteQ5GHHToTYHE3A1w6p7tU6KSoFmWBVbFGjKPisZDbP97");
|
||||
|
||||
@ -193,10 +193,10 @@ public class PaymentCodeTest {
|
||||
|
||||
DeterministicSeed bobSeed = new DeterministicSeed("reward upper indicate eight swift arch injury crystal super wrestle already dentist", "", 0, DeterministicSeed.Type.BIP39);
|
||||
Wallet bobWallet = new Wallet();
|
||||
bobWallet.setPolicyType(PolicyType.SINGLE);
|
||||
bobWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
bobWallet.setScriptType(ScriptType.P2PKH);
|
||||
bobWallet.getKeystores().add(Keystore.fromSeed(bobSeed, bobWallet.getScriptType().getDefaultDerivation()));
|
||||
bobWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2PKH, bobWallet.getKeystores(), 1));
|
||||
bobWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2PKH, bobWallet.getKeystores(), 1));
|
||||
|
||||
Wallet bobBip47Wallet = bobWallet.addChildWallet(paymentCodeAlice, ScriptType.P2PKH, "Bob");
|
||||
Assertions.assertEquals(paymentCodeBob.toString(), bobBip47Wallet.getKeystores().get(0).getPaymentCode().toString());
|
||||
|
||||
@ -18,11 +18,11 @@ public class ECKeyTest {
|
||||
String words = "absent essay fox snake vast pumpkin height crouch silent bulb excuse razor";
|
||||
DeterministicSeed seed = new DeterministicSeed(words, "", 0, DeterministicSeed.Type.BIP39);
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(PolicyType.SINGLE);
|
||||
wallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
wallet.setScriptType(ScriptType.P2PKH);
|
||||
Keystore keystore = Keystore.fromSeed(seed, wallet.getScriptType().getDefaultDerivation());
|
||||
wallet.getKeystores().add(keystore);
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2PKH, wallet.getKeystores(), 1));
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2PKH, wallet.getKeystores(), 1));
|
||||
|
||||
WalletNode firstReceive = wallet.getNode(KeyPurpose.RECEIVE).getChildren().iterator().next();
|
||||
Address address = firstReceive.getAddress();
|
||||
|
||||
@ -167,7 +167,7 @@ public class SilentPaymentUtilsTest {
|
||||
Assertions.assertEquals("3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1", Utils.bytesToHex(address.getData()));
|
||||
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -186,7 +186,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
List<SilentPayment> silentPayments = List.of(new SilentPayment(silentPaymentAddress, "", 0, false));
|
||||
@ -200,7 +200,7 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testSimpleSendTwoInputsReversed() throws InvalidSilentPaymentException {
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -219,7 +219,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
List<SilentPayment> silentPayments = List.of(new SilentPayment(silentPaymentAddress, "", 0, false));
|
||||
@ -232,7 +232,7 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testSimpleSendTwoInputsSameTransaction() throws InvalidSilentPaymentException {
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -251,7 +251,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
List<SilentPayment> silentPayments = List.of(new SilentPayment(silentPaymentAddress, "", 0, false));
|
||||
@ -264,7 +264,7 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testSimpleSendTwoInputsSameTransactionReversed() throws InvalidSilentPaymentException {
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -283,7 +283,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
List<SilentPayment> silentPayments = List.of(new SilentPayment(silentPaymentAddress, "", 0, false));
|
||||
@ -296,7 +296,7 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testOutpointOrderingIndex() throws InvalidSilentPaymentException {
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -315,7 +315,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
List<SilentPayment> silentPayments = List.of(new SilentPayment(silentPaymentAddress, "", 0, false));
|
||||
@ -328,7 +328,7 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testSingleRecipientSamePubKey() throws InvalidSilentPaymentException {
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -347,7 +347,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
List<SilentPayment> silentPayments = List.of(new SilentPayment(silentPaymentAddress, "", 0, false));
|
||||
@ -360,7 +360,7 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testSingleRecipientTaprootOnlyEvenY() throws InvalidSilentPaymentException {
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2TR);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -389,7 +389,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
List<SilentPayment> silentPayments = List.of(new SilentPayment(silentPaymentAddress, "", 0, false));
|
||||
@ -402,7 +402,7 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testSingleRecipientTaprootOnlyMixedY() throws InvalidSilentPaymentException {
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2TR);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -431,7 +431,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
List<SilentPayment> silentPayments = List.of(new SilentPayment(silentPaymentAddress, "", 0, false));
|
||||
@ -444,12 +444,12 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testSingleRecipientTaprootEvenYAndNonTaproot() throws InvalidSilentPaymentException {
|
||||
Wallet taprootWallet = new Wallet();
|
||||
taprootWallet.setPolicyType(PolicyType.SINGLE);
|
||||
taprootWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
taprootWallet.setScriptType(ScriptType.P2TR);
|
||||
Map<WalletNode, ECKey> taprootPrivateKeys = new LinkedHashMap<>();
|
||||
|
||||
Wallet segwitWallet = new Wallet();
|
||||
segwitWallet.setPolicyType(PolicyType.SINGLE);
|
||||
segwitWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
segwitWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<WalletNode, ECKey> segwitPrivateKeys = new LinkedHashMap<>();
|
||||
|
||||
@ -474,11 +474,11 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore taprootKeystore = new TestKeystore(taprootPrivateKeys);
|
||||
taprootWallet.getKeystores().add(taprootKeystore);
|
||||
taprootWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, taprootWallet.getKeystores(), 1));
|
||||
taprootWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, taprootWallet.getKeystores(), 1));
|
||||
|
||||
TestKeystore segwitKeystore = new TestKeystore(segwitPrivateKeys);
|
||||
segwitWallet.getKeystores().add(segwitKeystore);
|
||||
segwitWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, segwitWallet.getKeystores(), 1));
|
||||
segwitWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, segwitWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
List<SilentPayment> silentPayments = List.of(new SilentPayment(silentPaymentAddress, "", 0, false));
|
||||
@ -491,12 +491,12 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testSingleRecipientTaprootOddYAndNonTaproot() throws InvalidSilentPaymentException {
|
||||
Wallet taprootWallet = new Wallet();
|
||||
taprootWallet.setPolicyType(PolicyType.SINGLE);
|
||||
taprootWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
taprootWallet.setScriptType(ScriptType.P2TR);
|
||||
Map<WalletNode, ECKey> taprootPrivateKeys = new LinkedHashMap<>();
|
||||
|
||||
Wallet segwitWallet = new Wallet();
|
||||
segwitWallet.setPolicyType(PolicyType.SINGLE);
|
||||
segwitWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
segwitWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<WalletNode, ECKey> segwitPrivateKeys = new LinkedHashMap<>();
|
||||
|
||||
@ -521,11 +521,11 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore taprootKeystore = new TestKeystore(taprootPrivateKeys);
|
||||
taprootWallet.getKeystores().add(taprootKeystore);
|
||||
taprootWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, taprootWallet.getKeystores(), 1));
|
||||
taprootWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, taprootWallet.getKeystores(), 1));
|
||||
|
||||
TestKeystore segwitKeystore = new TestKeystore(segwitPrivateKeys);
|
||||
segwitWallet.getKeystores().add(segwitKeystore);
|
||||
segwitWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, segwitWallet.getKeystores(), 1));
|
||||
segwitWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, segwitWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
List<SilentPayment> silentPayments = List.of(new SilentPayment(silentPaymentAddress, "", 0, false));
|
||||
@ -538,7 +538,7 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testMultipleOutputsSameRecipient() throws InvalidSilentPaymentException {
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -557,7 +557,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress0 = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
SilentPaymentAddress silentPaymentAddress1 = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
@ -574,7 +574,7 @@ public class SilentPaymentUtilsTest {
|
||||
@Test
|
||||
public void testMultipleOutputsMultipleRecipients() throws InvalidSilentPaymentException {
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -593,7 +593,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
SilentPaymentAddress silentPaymentAddress0 = SilentPaymentAddress.from("sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv");
|
||||
SilentPaymentAddress silentPaymentAddress1 = SilentPaymentAddress.from("sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn");
|
||||
@ -619,7 +619,7 @@ public class SilentPaymentUtilsTest {
|
||||
// Expected sum = A (non-zero)
|
||||
|
||||
Wallet sendWallet = new Wallet();
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE);
|
||||
sendWallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
sendWallet.setScriptType(ScriptType.P2WPKH);
|
||||
Map<HashIndex, WalletNode> utxos = new LinkedHashMap<>();
|
||||
Map<WalletNode, ECKey> privateKeys = new LinkedHashMap<>();
|
||||
@ -647,7 +647,7 @@ public class SilentPaymentUtilsTest {
|
||||
|
||||
TestKeystore sendKeystore = new TestKeystore(privateKeys);
|
||||
sendWallet.getKeystores().add(sendKeystore);
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
sendWallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, sendWallet.getKeystores(), 1));
|
||||
|
||||
ECKey summedKey = SilentPaymentUtils.getSummedPrivateKey(utxos.values());
|
||||
Assertions.assertEquals("a6df6a0bb448992a301df4258e06a89fe7cf7146f59ac3bd5ff26083acb22ceb", Utils.bytesToHex(summedKey.getPrivKeyBytes()));
|
||||
|
||||
@ -16,27 +16,27 @@ public class PolicyTest {
|
||||
Keystore keystore2 = new Keystore("Keystore 2");
|
||||
Keystore keystore3 = new Keystore("Keystore 3");
|
||||
|
||||
Policy policy = Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2PKH, List.of(keystore1), 1);
|
||||
Policy policy = Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2PKH, List.of(keystore1), 1);
|
||||
Assertions.assertEquals("pkh(keystore1)", policy.getMiniscript().toString().toLowerCase(Locale.ROOT));
|
||||
Assertions.assertEquals(1, policy.getNumSignaturesRequired());
|
||||
|
||||
Policy policy2 = Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2SH_P2WPKH, List.of(keystore1), 1);
|
||||
Policy policy2 = Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2SH_P2WPKH, List.of(keystore1), 1);
|
||||
Assertions.assertEquals("sh(wpkh(keystore1))", policy2.getMiniscript().toString().toLowerCase(Locale.ROOT));
|
||||
Assertions.assertEquals(1, policy2.getNumSignaturesRequired());
|
||||
|
||||
Policy policy3 = Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, List.of(keystore1), 1);
|
||||
Policy policy3 = Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, List.of(keystore1), 1);
|
||||
Assertions.assertEquals("wpkh(keystore1)", policy3.getMiniscript().toString().toLowerCase(Locale.ROOT));
|
||||
Assertions.assertEquals(1, policy3.getNumSignaturesRequired());
|
||||
|
||||
Policy policy4 = Policy.getPolicy(PolicyType.MULTI, ScriptType.P2SH, List.of(keystore1, keystore2, keystore3), 2);
|
||||
Policy policy4 = Policy.getPolicy(PolicyType.MULTI_HD, ScriptType.P2SH, List.of(keystore1, keystore2, keystore3), 2);
|
||||
Assertions.assertEquals("sh(sortedmulti(2,keystore1,keystore2,keystore3))", policy4.getMiniscript().toString().toLowerCase(Locale.ROOT));
|
||||
Assertions.assertEquals(2, policy4.getNumSignaturesRequired());
|
||||
|
||||
Policy policy5 = Policy.getPolicy(PolicyType.MULTI, ScriptType.P2SH_P2WSH, List.of(keystore1, keystore2, keystore3), 2);
|
||||
Policy policy5 = Policy.getPolicy(PolicyType.MULTI_HD, ScriptType.P2SH_P2WSH, List.of(keystore1, keystore2, keystore3), 2);
|
||||
Assertions.assertEquals("sh(wsh(sortedmulti(2,keystore1,keystore2,keystore3)))", policy5.getMiniscript().toString().toLowerCase(Locale.ROOT));
|
||||
Assertions.assertEquals(2, policy5.getNumSignaturesRequired());
|
||||
|
||||
Policy policy6 = Policy.getPolicy(PolicyType.MULTI, ScriptType.P2WSH, List.of(keystore1, keystore2, keystore3), 2);
|
||||
Policy policy6 = Policy.getPolicy(PolicyType.MULTI_HD, ScriptType.P2WSH, List.of(keystore1, keystore2, keystore3), 2);
|
||||
Assertions.assertEquals("wsh(sortedmulti(2,keystore1,keystore2,keystore3))", policy6.getMiniscript().toString().toLowerCase(Locale.ROOT));
|
||||
Assertions.assertEquals(2, policy6.getNumSignaturesRequired());
|
||||
}
|
||||
|
||||
@ -22,11 +22,11 @@ public class WalletTest {
|
||||
String words = "absent essay fox snake vast pumpkin height crouch silent bulb excuse razor";
|
||||
DeterministicSeed seed = new DeterministicSeed(words, "pp", 0, DeterministicSeed.Type.BIP39);
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(PolicyType.SINGLE);
|
||||
wallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
wallet.setScriptType(ScriptType.P2PKH);
|
||||
Keystore keystore = Keystore.fromSeed(seed, wallet.getScriptType().getDefaultDerivation());
|
||||
wallet.getKeystores().add(keystore);
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2PKH, wallet.getKeystores(), 1));
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2PKH, wallet.getKeystores(), 1));
|
||||
|
||||
KeyDeriver keyDeriver = new Argon2KeyDeriver();
|
||||
Key key = keyDeriver.deriveKey("pass");
|
||||
@ -110,11 +110,11 @@ public class WalletTest {
|
||||
String words = "absent essay fox snake vast pumpkin height crouch silent bulb excuse razor";
|
||||
DeterministicSeed seed = new DeterministicSeed(words, "pp", 0, DeterministicSeed.Type.BIP39);
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(PolicyType.SINGLE);
|
||||
wallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
wallet.setScriptType(ScriptType.P2PKH);
|
||||
Keystore keystore = Keystore.fromSeed(seed, wallet.getScriptType().getDefaultDerivation());
|
||||
wallet.getKeystores().add(keystore);
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2PKH, wallet.getKeystores(), 1));
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2PKH, wallet.getKeystores(), 1));
|
||||
|
||||
WalletNode receive0 = new WalletNode(wallet, KeyPurpose.RECEIVE, 0);
|
||||
Assertions.assertEquals("12kTQjuWDp7Uu6PwY6CsS1KLTt3d1DBHZa", receive0.getAddress().toString());
|
||||
@ -127,11 +127,11 @@ public class WalletTest {
|
||||
String words = "absent essay fox snake vast pumpkin height crouch silent bulb excuse razor";
|
||||
DeterministicSeed seed = new DeterministicSeed(words, "pp", 0, DeterministicSeed.Type.BIP39);
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(PolicyType.SINGLE);
|
||||
wallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
wallet.setScriptType(ScriptType.P2SH_P2WPKH);
|
||||
Keystore keystore = Keystore.fromSeed(seed, wallet.getScriptType().getDefaultDerivation());
|
||||
wallet.getKeystores().add(keystore);
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2SH_P2WPKH, wallet.getKeystores(), 1));
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2SH_P2WPKH, wallet.getKeystores(), 1));
|
||||
|
||||
WalletNode receive0 = new WalletNode(wallet, KeyPurpose.RECEIVE, 0);
|
||||
Assertions.assertEquals("3NZLE4TntsjtcZ5MbrfxwtYo9meBVybVQj", receive0.getAddress().toString());
|
||||
@ -144,11 +144,11 @@ public class WalletTest {
|
||||
String words = "absent essay fox snake vast pumpkin height crouch silent bulb excuse razor";
|
||||
DeterministicSeed seed = new DeterministicSeed(words, "pp", 0, DeterministicSeed.Type.BIP39);
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(PolicyType.SINGLE);
|
||||
wallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
wallet.setScriptType(ScriptType.P2WPKH);
|
||||
Keystore keystore = Keystore.fromSeed(seed, wallet.getScriptType().getDefaultDerivation());
|
||||
wallet.getKeystores().add(keystore);
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, wallet.getKeystores(), 1));
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE_HD, ScriptType.P2WPKH, wallet.getKeystores(), 1));
|
||||
|
||||
WalletNode receive0 = new WalletNode(wallet, KeyPurpose.RECEIVE, 0);
|
||||
Assertions.assertEquals("bc1quvxdut936uswuxwxrk6nvjmgwxh463r0fjwn55", receive0.getAddress().toString());
|
||||
@ -165,7 +165,7 @@ public class WalletTest {
|
||||
DeterministicSeed seed2 = new DeterministicSeed(words2, "", 0, DeterministicSeed.Type.BIP39);
|
||||
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(PolicyType.MULTI);
|
||||
wallet.setPolicyType(PolicyType.MULTI_HD);
|
||||
wallet.setScriptType(ScriptType.P2SH);
|
||||
Keystore keystore = Keystore.fromSeed(seed, ScriptType.P2PKH.getDefaultDerivation());
|
||||
Assertions.assertEquals("xprv9s21ZrQH143K4G3jeUxf7h93qLeinXNULjjaef1yZFXpoc5D16iHEFkgJ7ThkWzAEBwNNwyJFtrVhJVJRjCc9ew76JrgsVoXT4VYHJBbbSV", keystore.getExtendedMasterPrivateKey().toString());
|
||||
@ -175,7 +175,7 @@ public class WalletTest {
|
||||
Assertions.assertEquals("xprv9s21ZrQH143K4FNcBwXNXfzVNskpoRS7cf4jQTLrhbPkhhXp8hz4QRXT62HziiHziM3Pxyd2Qx3UQkoRpcDu2BauuJJRdyrduXBJGgjAgFx", keystore2.getExtendedMasterPrivateKey().toString());
|
||||
Assertions.assertEquals("xpub6ChqMsFBYpJiJYzcJgEvddHtbZr1mTaE1o4RbhFRBAYVxN8SScGb9kjwkXtM33JKejR16gBZhNbkV14AccetR5u2McnCgTCpDBfa8hee9v8", keystore2.getExtendedPublicKey().toString());
|
||||
wallet.getKeystores().add(keystore2);
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI, ScriptType.P2SH, wallet.getKeystores(), 2));
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI_HD, ScriptType.P2SH, wallet.getKeystores(), 2));
|
||||
|
||||
WalletNode receive0 = new WalletNode(wallet, KeyPurpose.RECEIVE, 0);
|
||||
Assertions.assertEquals("38kq6yz4VcYymTExQPY3gppbz38mtPLveK", receive0.getAddress().toString());
|
||||
@ -192,7 +192,7 @@ public class WalletTest {
|
||||
DeterministicSeed seed2 = new DeterministicSeed(words2, "", 0, DeterministicSeed.Type.BIP39);
|
||||
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(PolicyType.MULTI);
|
||||
wallet.setPolicyType(PolicyType.MULTI_HD);
|
||||
wallet.setScriptType(ScriptType.P2SH_P2WSH);
|
||||
Keystore keystore = Keystore.fromSeed(seed, ScriptType.P2PKH.getDefaultDerivation());
|
||||
Assertions.assertEquals("xprv9s21ZrQH143K4G3jeUxf7h93qLeinXNULjjaef1yZFXpoc5D16iHEFkgJ7ThkWzAEBwNNwyJFtrVhJVJRjCc9ew76JrgsVoXT4VYHJBbbSV", keystore.getExtendedMasterPrivateKey().toString());
|
||||
@ -202,7 +202,7 @@ public class WalletTest {
|
||||
Assertions.assertEquals("xprv9s21ZrQH143K4FNcBwXNXfzVNskpoRS7cf4jQTLrhbPkhhXp8hz4QRXT62HziiHziM3Pxyd2Qx3UQkoRpcDu2BauuJJRdyrduXBJGgjAgFx", keystore2.getExtendedMasterPrivateKey().toString());
|
||||
Assertions.assertEquals("xpub6ChqMsFBYpJiJYzcJgEvddHtbZr1mTaE1o4RbhFRBAYVxN8SScGb9kjwkXtM33JKejR16gBZhNbkV14AccetR5u2McnCgTCpDBfa8hee9v8", keystore2.getExtendedPublicKey().toString());
|
||||
wallet.getKeystores().add(keystore2);
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI, ScriptType.P2SH_P2WSH, wallet.getKeystores(), 2));
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI_HD, ScriptType.P2SH_P2WSH, wallet.getKeystores(), 2));
|
||||
|
||||
WalletNode receive0 = new WalletNode(wallet, KeyPurpose.RECEIVE, 0);
|
||||
Assertions.assertEquals("3Mw8xqAHh8g3eBvh7q1UEUmoexqdXDK9Tf", receive0.getAddress().toString());
|
||||
@ -219,7 +219,7 @@ public class WalletTest {
|
||||
DeterministicSeed seed2 = new DeterministicSeed(words2, "", 0, DeterministicSeed.Type.BIP39);
|
||||
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(PolicyType.MULTI);
|
||||
wallet.setPolicyType(PolicyType.MULTI_HD);
|
||||
wallet.setScriptType(ScriptType.P2WSH);
|
||||
Keystore keystore = Keystore.fromSeed(seed, ScriptType.P2PKH.getDefaultDerivation());
|
||||
Assertions.assertEquals("xprv9s21ZrQH143K4G3jeUxf7h93qLeinXNULjjaef1yZFXpoc5D16iHEFkgJ7ThkWzAEBwNNwyJFtrVhJVJRjCc9ew76JrgsVoXT4VYHJBbbSV", keystore.getExtendedMasterPrivateKey().toString());
|
||||
@ -229,7 +229,7 @@ public class WalletTest {
|
||||
Assertions.assertEquals("xprv9s21ZrQH143K4FNcBwXNXfzVNskpoRS7cf4jQTLrhbPkhhXp8hz4QRXT62HziiHziM3Pxyd2Qx3UQkoRpcDu2BauuJJRdyrduXBJGgjAgFx", keystore2.getExtendedMasterPrivateKey().toString());
|
||||
Assertions.assertEquals("xpub6ChqMsFBYpJiJYzcJgEvddHtbZr1mTaE1o4RbhFRBAYVxN8SScGb9kjwkXtM33JKejR16gBZhNbkV14AccetR5u2McnCgTCpDBfa8hee9v8", keystore2.getExtendedPublicKey().toString());
|
||||
wallet.getKeystores().add(keystore2);
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI, ScriptType.P2WSH, wallet.getKeystores(), 2));
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI_HD, ScriptType.P2WSH, wallet.getKeystores(), 2));
|
||||
|
||||
WalletNode receive0 = new WalletNode(wallet, KeyPurpose.RECEIVE, 0);
|
||||
Assertions.assertEquals("bc1q20e4vm656h5lvmngz9ztz6hjzftvh39yzngqhuqzk8qzj7tqnzaqgclrwc", receive0.getAddress().toString());
|
||||
@ -240,7 +240,7 @@ public class WalletTest {
|
||||
@Test
|
||||
public void testHighDerivationPath() {
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(PolicyType.SINGLE);
|
||||
wallet.setPolicyType(PolicyType.SINGLE_HD);
|
||||
wallet.setScriptType(ScriptType.P2WPKH);
|
||||
Keystore keystore = new Keystore();
|
||||
keystore.setKeyDerivation(new KeyDerivation("ffffffff", "m/84'/0'/2147483646'"));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user