mirror of
https://github.com/sparrowwallet/drongo.git
synced 2024-12-27 02:26:44 +00:00
add support for alternative (non-mainnet) networks
This commit is contained in:
parent
e8d8fa6126
commit
747bfa915f
10 changed files with 252 additions and 37 deletions
|
@ -6,6 +6,7 @@ import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class ExtendedKey {
|
public class ExtendedKey {
|
||||||
private final byte[] parentFingerprint;
|
private final byte[] parentFingerprint;
|
||||||
|
@ -53,7 +54,7 @@ public class ExtendedKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getExtendedKeyBytes() {
|
public byte[] getExtendedKeyBytes() {
|
||||||
return getExtendedKeyBytes(key.isPubKeyOnly() ? Header.xpub : Header.xprv);
|
return getExtendedKeyBytes(key.isPubKeyOnly() ? Network.get().getXpubHeader() : Network.get().getXprvHeader());
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getExtendedKeyBytes(Header extendedKeyHeader) {
|
public byte[] getExtendedKeyBytes(Header extendedKeyHeader) {
|
||||||
|
@ -79,7 +80,7 @@ public class ExtendedKey {
|
||||||
int headerInt = buffer.getInt();
|
int headerInt = buffer.getInt();
|
||||||
Header header = Header.getHeader(headerInt);
|
Header header = Header.getHeader(headerInt);
|
||||||
if(header == null) {
|
if(header == null) {
|
||||||
throw new IllegalArgumentException("Unknown header bytes: " + DeterministicKey.toBase58(serializedKey).substring(0, 4));
|
throw new IllegalArgumentException("Unknown header bytes for extended key on " + Network.get().getName() + ": " + DeterministicKey.toBase58(serializedKey).substring(0, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
int depth = buffer.get() & 0xFF; // convert signed byte to positive int since depth cannot be negative
|
int depth = buffer.get() & 0xFF; // convert signed byte to positive int since depth cannot be negative
|
||||||
|
@ -196,38 +197,62 @@ public class ExtendedKey {
|
||||||
return privateKey;
|
return privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMainnet() {
|
public Network getNetwork() {
|
||||||
return mainnet;
|
return mainnet ? Network.MAINNET : Network.TESTNET;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Header> getHeaders(Network network) {
|
||||||
|
return Arrays.stream(Header.values()).filter(header -> header.getNetwork() == network || (header.getNetwork() == Network.TESTNET && network == Network.REGTEST)).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Header fromExtendedKey(String xkey) {
|
public static Header fromExtendedKey(String xkey) {
|
||||||
for(Header extendedKeyHeader : Header.values()) {
|
for(Header extendedKeyHeader : getHeaders(Network.get())) {
|
||||||
if(xkey.startsWith(extendedKeyHeader.name)) {
|
if(xkey.startsWith(extendedKeyHeader.name)) {
|
||||||
return extendedKeyHeader;
|
return extendedKeyHeader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException("Unrecognised extended key header for extended key: " + xkey);
|
for(Network network : getOtherNetworks(Network.get())) {
|
||||||
|
for(Header otherNetworkKeyHeader : getHeaders(network)) {
|
||||||
|
if(xkey.startsWith(otherNetworkKeyHeader.name)) {
|
||||||
|
throw new IllegalArgumentException("Provided " + otherNetworkKeyHeader.name + " extended key invalid on configured " + Network.get().getName() + " network. Use a " + network.getName() + " configuration to use this extended key.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("Unrecognised extended key header for " + Network.get().getName() + ": " + xkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Header fromScriptType(ScriptType scriptType, boolean privateKey) {
|
public static Header fromScriptType(ScriptType scriptType, boolean privateKey) {
|
||||||
for(Header header : Header.values()) {
|
for(Header header : getHeaders(Network.get())) {
|
||||||
if(header.defaultScriptType != null && header.defaultScriptType.equals(scriptType) && header.isPrivateKey() == privateKey) {
|
if(header.defaultScriptType != null && header.defaultScriptType.equals(scriptType) && header.isPrivateKey() == privateKey) {
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Header.xpub;
|
return Network.get().getXpubHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Header getHeader(int header) {
|
private static Header getHeader(int header) {
|
||||||
for(Header extendedKeyHeader : Header.values()) {
|
for(Header extendedKeyHeader : getHeaders(Network.get())) {
|
||||||
if(header == extendedKeyHeader.header) {
|
if(header == extendedKeyHeader.header) {
|
||||||
return extendedKeyHeader;
|
return extendedKeyHeader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(Network otherNetwork : getOtherNetworks(Network.get())) {
|
||||||
|
for(Header otherNetworkKeyHeader : getHeaders(otherNetwork)) {
|
||||||
|
if(header == otherNetworkKeyHeader.header) {
|
||||||
|
throw new IllegalArgumentException("Provided " + otherNetworkKeyHeader.name + " extended key invalid on configured " + Network.get().getName() + " network. Use a " + otherNetwork.getName() + " configuration to use this extended key.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<Network> getOtherNetworks(Network providedNetwork) {
|
||||||
|
return Arrays.stream(Network.values()).filter(network -> network != providedNetwork).collect(Collectors.toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
87
src/main/java/com/sparrowwallet/drongo/Network.java
Normal file
87
src/main/java/com/sparrowwallet/drongo/Network.java
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
package com.sparrowwallet.drongo;
|
||||||
|
|
||||||
|
public enum Network {
|
||||||
|
MAINNET("mainnet", 0, "1", 5, "3", "bc", ExtendedKey.Header.xprv, ExtendedKey.Header.xpub),
|
||||||
|
TESTNET("testnet", 111, "mn", 196, "2", "tb", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub),
|
||||||
|
REGTEST("regtest", 111, "mn", 196, "2", "bcrt", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub);
|
||||||
|
|
||||||
|
Network(String name, int p2pkhAddressHeader, String p2pkhAddressPrefix, int p2shAddressHeader, String p2shAddressPrefix, String bech32AddressHrp, ExtendedKey.Header xprvHeader, ExtendedKey.Header xpubHeader) {
|
||||||
|
this.name = name;
|
||||||
|
this.p2pkhAddressHeader = p2pkhAddressHeader;
|
||||||
|
this.p2pkhAddressPrefix = p2pkhAddressPrefix;
|
||||||
|
this.p2shAddressHeader = p2shAddressHeader;
|
||||||
|
this.p2shAddressPrefix = p2shAddressPrefix;
|
||||||
|
this.bech32AddressHrp = bech32AddressHrp;
|
||||||
|
this.xprvHeader = xprvHeader;
|
||||||
|
this.xpubHeader = xpubHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final int p2pkhAddressHeader;
|
||||||
|
private final String p2pkhAddressPrefix;
|
||||||
|
private final int p2shAddressHeader;
|
||||||
|
private final String p2shAddressPrefix;
|
||||||
|
private final String bech32AddressHrp;
|
||||||
|
private final ExtendedKey.Header xprvHeader;
|
||||||
|
private final ExtendedKey.Header xpubHeader;
|
||||||
|
|
||||||
|
private static Network currentNetwork;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getP2PKHAddressHeader() {
|
||||||
|
return p2pkhAddressHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getP2SHAddressHeader() {
|
||||||
|
return p2shAddressHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBech32AddressHRP() {
|
||||||
|
return bech32AddressHrp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedKey.Header getXprvHeader() {
|
||||||
|
return xprvHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedKey.Header getXpubHeader() {
|
||||||
|
return xpubHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasP2PKHAddressPrefix(String address) {
|
||||||
|
for(String prefix : p2pkhAddressPrefix.split("")) {
|
||||||
|
if(address.startsWith(prefix)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasP2SHAddressPrefix(String address) {
|
||||||
|
return address.startsWith(p2shAddressPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Network get() {
|
||||||
|
if(currentNetwork == null) {
|
||||||
|
currentNetwork = MAINNET;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void set(Network network) {
|
||||||
|
if(currentNetwork != null && network != currentNetwork && !isTest()) {
|
||||||
|
throw new IllegalStateException("Network already set to " + currentNetwork.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
currentNetwork = network;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isTest() {
|
||||||
|
return System.getProperty("org.gradle.test.worker") != null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.sparrowwallet.drongo.address;
|
package com.sparrowwallet.drongo.address;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.Network;
|
||||||
import com.sparrowwallet.drongo.protocol.Base58;
|
import com.sparrowwallet.drongo.protocol.Base58;
|
||||||
import com.sparrowwallet.drongo.protocol.Bech32;
|
import com.sparrowwallet.drongo.protocol.Bech32;
|
||||||
import com.sparrowwallet.drongo.protocol.Script;
|
import com.sparrowwallet.drongo.protocol.Script;
|
||||||
|
@ -7,8 +8,6 @@ import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static com.sparrowwallet.drongo.address.P2WPKHAddress.HRP;
|
|
||||||
|
|
||||||
public abstract class Address {
|
public abstract class Address {
|
||||||
protected final byte[] hash;
|
protected final byte[] hash;
|
||||||
|
|
||||||
|
@ -21,14 +20,26 @@ public abstract class Address {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAddress() {
|
public String getAddress() {
|
||||||
return Base58.encodeChecked(getVersion(), hash);
|
return getAddress(Network.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddress(Network network) {
|
||||||
|
return Base58.encodeChecked(getVersion(network), hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getAddress();
|
return getAddress(Network.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract int getVersion();
|
public String toString(Network network) {
|
||||||
|
return getAddress(network);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return getVersion(Network.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract int getVersion(Network network);
|
||||||
|
|
||||||
public abstract ScriptType getScriptType();
|
public abstract ScriptType getScriptType();
|
||||||
|
|
||||||
|
@ -52,18 +63,37 @@ public abstract class Address {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Address fromString(String address) throws InvalidAddressException {
|
public static Address fromString(String address) throws InvalidAddressException {
|
||||||
|
try {
|
||||||
|
return fromString(Network.get(), address);
|
||||||
|
} catch(InvalidAddressException e) {
|
||||||
|
for(Network network : Network.values()) {
|
||||||
|
try {
|
||||||
|
fromString(network, address);
|
||||||
|
if(network != Network.get()) {
|
||||||
|
throw new InvalidAddressException("Provided " + network.getName() + " address invalid on configured " + Network.get().getName() + " network: " + address + ". Use a " + network.getName() + " configuration to use this address.");
|
||||||
|
}
|
||||||
|
} catch(InvalidAddressException i) {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Address fromString(Network network, String address) throws InvalidAddressException {
|
||||||
Exception nested = null;
|
Exception nested = null;
|
||||||
|
|
||||||
if(address != null && (address.startsWith("1") || address.startsWith("3"))) {
|
if(address != null && (network.hasP2PKHAddressPrefix(address) || network.hasP2SHAddressPrefix(address))) {
|
||||||
try {
|
try {
|
||||||
byte[] decodedBytes = Base58.decodeChecked(address);
|
byte[] decodedBytes = Base58.decodeChecked(address);
|
||||||
if(decodedBytes.length == 21) {
|
if(decodedBytes.length == 21) {
|
||||||
int version = decodedBytes[0];
|
int version = Byte.toUnsignedInt(decodedBytes[0]);
|
||||||
byte[] hash = Arrays.copyOfRange(decodedBytes, 1, 21);
|
byte[] hash = Arrays.copyOfRange(decodedBytes, 1, 21);
|
||||||
if(version == 0) {
|
if(version == network.getP2PKHAddressHeader()) {
|
||||||
return new P2PKHAddress(hash);
|
return new P2PKHAddress(hash);
|
||||||
}
|
}
|
||||||
if(version == 5) {
|
if(version == network.getP2SHAddressHeader()) {
|
||||||
return new P2SHAddress(hash);
|
return new P2SHAddress(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,10 +102,10 @@ public abstract class Address {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(address != null && address.startsWith(HRP)) {
|
if(address != null && address.startsWith(network.getBech32AddressHRP())) {
|
||||||
try {
|
try {
|
||||||
Bech32.Bech32Data data = Bech32.decode(address);
|
Bech32.Bech32Data data = Bech32.decode(address);
|
||||||
if (data.hrp.equals(HRP)) {
|
if(data.hrp.equals(network.getBech32AddressHRP())) {
|
||||||
int witnessVersion = data.data[0];
|
int witnessVersion = data.data[0];
|
||||||
if (witnessVersion == 0) {
|
if (witnessVersion == 0) {
|
||||||
byte[] convertedProgram = Arrays.copyOfRange(data.data, 1, data.data.length);
|
byte[] convertedProgram = Arrays.copyOfRange(data.data, 1, data.data.length);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.sparrowwallet.drongo.address;
|
package com.sparrowwallet.drongo.address;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.Network;
|
||||||
import com.sparrowwallet.drongo.Utils;
|
import com.sparrowwallet.drongo.Utils;
|
||||||
import com.sparrowwallet.drongo.protocol.Script;
|
import com.sparrowwallet.drongo.protocol.Script;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
@ -12,8 +13,9 @@ public class P2PKAddress extends Address {
|
||||||
this.pubKey = pubKey;
|
this.pubKey = pubKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVersion() {
|
@Override
|
||||||
return 0;
|
public int getVersion(Network network) {
|
||||||
|
return network.getP2PKHAddressHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptType getScriptType() {
|
public ScriptType getScriptType() {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.sparrowwallet.drongo.address;
|
package com.sparrowwallet.drongo.address;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.Network;
|
||||||
import com.sparrowwallet.drongo.protocol.Script;
|
import com.sparrowwallet.drongo.protocol.Script;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
|
||||||
|
@ -8,14 +9,17 @@ public class P2PKHAddress extends Address {
|
||||||
super(pubKeyHash);
|
super(pubKeyHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVersion() {
|
@Override
|
||||||
return 0;
|
public int getVersion(Network network) {
|
||||||
|
return network.getP2PKHAddressHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ScriptType getScriptType() {
|
public ScriptType getScriptType() {
|
||||||
return ScriptType.P2PKH;
|
return ScriptType.P2PKH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Script getOutputScript() {
|
public Script getOutputScript() {
|
||||||
return getScriptType().getOutputScript(hash);
|
return getScriptType().getOutputScript(hash);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.sparrowwallet.drongo.address;
|
package com.sparrowwallet.drongo.address;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.Network;
|
||||||
import com.sparrowwallet.drongo.Utils;
|
import com.sparrowwallet.drongo.Utils;
|
||||||
import com.sparrowwallet.drongo.protocol.Script;
|
import com.sparrowwallet.drongo.protocol.Script;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
@ -9,8 +10,9 @@ public class P2SHAddress extends Address {
|
||||||
super(scriptHash);
|
super(scriptHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVersion() {
|
@Override
|
||||||
return 5;
|
public int getVersion(Network network) {
|
||||||
|
return network.getP2SHAddressHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,24 +1,26 @@
|
||||||
package com.sparrowwallet.drongo.address;
|
package com.sparrowwallet.drongo.address;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.Network;
|
||||||
import com.sparrowwallet.drongo.protocol.Bech32;
|
import com.sparrowwallet.drongo.protocol.Bech32;
|
||||||
import com.sparrowwallet.drongo.protocol.Script;
|
import com.sparrowwallet.drongo.protocol.Script;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
|
||||||
public class P2WPKHAddress extends Address {
|
public class P2WPKHAddress extends Address {
|
||||||
public static final String HRP = "bc";
|
|
||||||
|
|
||||||
public P2WPKHAddress(byte[] pubKeyHash) {
|
public P2WPKHAddress(byte[] pubKeyHash) {
|
||||||
super(pubKeyHash);
|
super(pubKeyHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVersion() {
|
@Override
|
||||||
|
public int getVersion(Network network) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAddress() {
|
@Override
|
||||||
return Bech32.encode(HRP, getVersion(), hash);
|
public String getAddress(Network network) {
|
||||||
|
return Bech32.encode(network.getBech32AddressHRP(), getVersion(), hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ScriptType getScriptType() {
|
public ScriptType getScriptType() {
|
||||||
return ScriptType.P2WPKH;
|
return ScriptType.P2WPKH;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
package com.sparrowwallet.drongo.address;
|
package com.sparrowwallet.drongo.address;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.Network;
|
||||||
import com.sparrowwallet.drongo.protocol.*;
|
import com.sparrowwallet.drongo.protocol.*;
|
||||||
|
|
||||||
import static com.sparrowwallet.drongo.address.P2WPKHAddress.HRP;
|
|
||||||
|
|
||||||
public class P2WSHAddress extends Address {
|
public class P2WSHAddress extends Address {
|
||||||
public P2WSHAddress(byte[] scriptHash) {
|
public P2WSHAddress(byte[] scriptHash) {
|
||||||
super(scriptHash);
|
super(scriptHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVersion() {
|
@Override
|
||||||
|
public int getVersion(Network network) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAddress() {
|
@Override
|
||||||
return Bech32.encode(HRP, getVersion(), hash);
|
public String getAddress(Network network) {
|
||||||
|
return Bech32.encode(network.getBech32AddressHRP(), getVersion(), hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ScriptType getScriptType() {
|
public ScriptType getScriptType() {
|
||||||
return ScriptType.P2WSH;
|
return ScriptType.P2WSH;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.sparrowwallet.drongo.address;
|
package com.sparrowwallet.drongo.address;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.Network;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -23,6 +25,51 @@ public class AddressTest {
|
||||||
Address address4 = Address.fromString("34jnjFM4SbaB7Q8aMtNDG849RQ1gUYgpgo");
|
Address address4 = Address.fromString("34jnjFM4SbaB7Q8aMtNDG849RQ1gUYgpgo");
|
||||||
Assert.assertTrue(address4 instanceof P2SHAddress);
|
Assert.assertTrue(address4 instanceof P2SHAddress);
|
||||||
Assert.assertEquals("34jnjFM4SbaB7Q8aMtNDG849RQ1gUYgpgo", address4.toString());
|
Assert.assertEquals("34jnjFM4SbaB7Q8aMtNDG849RQ1gUYgpgo", address4.toString());
|
||||||
|
|
||||||
|
Address address5 = Address.fromString(Network.TESTNET, "tb1qawkzyj2l5yck5jq4wyhkc4837x088580y9uyk8");
|
||||||
|
Assert.assertTrue(address5 instanceof P2WPKHAddress);
|
||||||
|
Assert.assertEquals("tb1qawkzyj2l5yck5jq4wyhkc4837x088580y9uyk8", address5.toString(Network.TESTNET));
|
||||||
|
|
||||||
|
Address address6 = Address.fromString(Network.TESTNET, "tb1q8kdkthp5a6vfrdas84efkpv25ul3s9wpzc755cra8av48xq4a7wsjcsdma");
|
||||||
|
Assert.assertTrue(address6 instanceof P2WSHAddress);
|
||||||
|
Assert.assertEquals("tb1q8kdkthp5a6vfrdas84efkpv25ul3s9wpzc755cra8av48xq4a7wsjcsdma", address6.toString(Network.TESTNET));
|
||||||
|
|
||||||
|
Address address7 = Address.fromString(Network.TESTNET, "mng6R5oLWBBo8iFWU9Mx4zFy5pWhrWMeW2");
|
||||||
|
Assert.assertTrue(address7 instanceof P2PKHAddress);
|
||||||
|
Assert.assertEquals("mng6R5oLWBBo8iFWU9Mx4zFy5pWhrWMeW2", address7.toString(Network.TESTNET));
|
||||||
|
|
||||||
|
Address address8 = Address.fromString(Network.TESTNET, "n1S1rnnZm3RdW9iuAF6Hjk3gLZWGc59zDi");
|
||||||
|
Assert.assertTrue(address8 instanceof P2PKHAddress);
|
||||||
|
Assert.assertEquals("n1S1rnnZm3RdW9iuAF6Hjk3gLZWGc59zDi", address8.toString(Network.TESTNET));
|
||||||
|
|
||||||
|
Address address9 = Address.fromString(Network.TESTNET, "2NCZUtUt6gzXyBiPEQi5yQyrgR6f6F6Ki6A");
|
||||||
|
Assert.assertTrue(address9 instanceof P2SHAddress);
|
||||||
|
Assert.assertEquals("2NCZUtUt6gzXyBiPEQi5yQyrgR6f6F6Ki6A", address9.toString(Network.TESTNET));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testnetValidAddressTest() throws InvalidAddressException {
|
||||||
|
Network.set(Network.TESTNET);
|
||||||
|
|
||||||
|
Address address5 = Address.fromString("tb1qawkzyj2l5yck5jq4wyhkc4837x088580y9uyk8");
|
||||||
|
Assert.assertTrue(address5 instanceof P2WPKHAddress);
|
||||||
|
Assert.assertEquals("tb1qawkzyj2l5yck5jq4wyhkc4837x088580y9uyk8", address5.toString());
|
||||||
|
|
||||||
|
Address address6 = Address.fromString("tb1q8kdkthp5a6vfrdas84efkpv25ul3s9wpzc755cra8av48xq4a7wsjcsdma");
|
||||||
|
Assert.assertTrue(address6 instanceof P2WSHAddress);
|
||||||
|
Assert.assertEquals("tb1q8kdkthp5a6vfrdas84efkpv25ul3s9wpzc755cra8av48xq4a7wsjcsdma", address6.toString());
|
||||||
|
|
||||||
|
Address address7 = Address.fromString("mng6R5oLWBBo8iFWU9Mx4zFy5pWhrWMeW2");
|
||||||
|
Assert.assertTrue(address7 instanceof P2PKHAddress);
|
||||||
|
Assert.assertEquals("mng6R5oLWBBo8iFWU9Mx4zFy5pWhrWMeW2", address7.toString());
|
||||||
|
|
||||||
|
Address address8 = Address.fromString("n1S1rnnZm3RdW9iuAF6Hjk3gLZWGc59zDi");
|
||||||
|
Assert.assertTrue(address8 instanceof P2PKHAddress);
|
||||||
|
Assert.assertEquals("n1S1rnnZm3RdW9iuAF6Hjk3gLZWGc59zDi", address8.toString());
|
||||||
|
|
||||||
|
Address address9 = Address.fromString("2NCZUtUt6gzXyBiPEQi5yQyrgR6f6F6Ki6A");
|
||||||
|
Assert.assertTrue(address9 instanceof P2SHAddress);
|
||||||
|
Assert.assertEquals("2NCZUtUt6gzXyBiPEQi5yQyrgR6f6F6Ki6A", address9.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -67,4 +114,9 @@ public class AddressTest {
|
||||||
public void invalidChecksumAddressTest2() throws InvalidAddressException {
|
public void invalidChecksumAddressTest2() throws InvalidAddressException {
|
||||||
Address address1 = Address.fromString("bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmb3");
|
Address address1 = Address.fromString("bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmb3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
Network.set(null);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -2,10 +2,12 @@ package com.sparrowwallet.drongo.psbt;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.ExtendedKey;
|
import com.sparrowwallet.drongo.ExtendedKey;
|
||||||
import com.sparrowwallet.drongo.KeyDerivation;
|
import com.sparrowwallet.drongo.KeyDerivation;
|
||||||
|
import com.sparrowwallet.drongo.Network;
|
||||||
import com.sparrowwallet.drongo.Utils;
|
import com.sparrowwallet.drongo.Utils;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
import com.sparrowwallet.drongo.protocol.*;
|
import com.sparrowwallet.drongo.protocol.*;
|
||||||
import org.bouncycastle.util.encoders.Hex;
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -197,6 +199,8 @@ public class PSBTTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validP2wshMultisigWithXpubs() throws PSBTParseException {
|
public void validP2wshMultisigWithXpubs() throws PSBTParseException {
|
||||||
|
Network.set(Network.TESTNET);
|
||||||
|
|
||||||
String psbt = "cHNidP8BAFICAAAAAZ38ZijCbFiZ/hvT3DOGZb/VXXraEPYiCXPfLTht7BJ2AQAAAAD/////AfA9zR0AAAAAFgAUezoAv9wU0neVwrdJAdCdpu8TNXkAAAAATwEENYfPAto/0AiAAAAAlwSLGtBEWx7IJ1UXcnyHtOTrwYogP/oPlMAVZr046QADUbdDiH7h1A3DKmBDck8tZFmztaTXPa7I+64EcvO8Q+IM2QxqT64AAIAAAACATwEENYfPAto/0AiAAAABuQRSQnE5zXjCz/JES+NTzVhgXj5RMoXlKLQH+uP2FzUD0wpel8itvFV9rCrZp+OcFyLrrGnmaLbyZnzB1nHIPKsM2QxqT64AAIABAACAAAEBKwBlzR0AAAAAIgAgLFSGEmxJeAeagU4TcV1l82RZ5NbMre0mbQUIZFuvpjIBBUdSIQKdoSzbWyNWkrkVNq/v5ckcOrlHPY5DtTODarRWKZyIcSEDNys0I07Xz5wf6l0F1EFVeSe+lUKxYusC4ass6AIkwAtSriIGAp2hLNtbI1aSuRU2r+/lyRw6uUc9jkO1M4NqtFYpnIhxENkMak+uAACAAAAAgAAAAAAiBgM3KzQjTtfPnB/qXQXUQVV5J76VQrFi6wLhqyzoAiTACxDZDGpPrgAAgAEAAIAAAAAAACICA57/H1R6HV+S36K6evaslxpL0DukpzSwMVaiVritOh75EO3kXMUAAACAAAAAgAEAAIAA";
|
String psbt = "cHNidP8BAFICAAAAAZ38ZijCbFiZ/hvT3DOGZb/VXXraEPYiCXPfLTht7BJ2AQAAAAD/////AfA9zR0AAAAAFgAUezoAv9wU0neVwrdJAdCdpu8TNXkAAAAATwEENYfPAto/0AiAAAAAlwSLGtBEWx7IJ1UXcnyHtOTrwYogP/oPlMAVZr046QADUbdDiH7h1A3DKmBDck8tZFmztaTXPa7I+64EcvO8Q+IM2QxqT64AAIAAAACATwEENYfPAto/0AiAAAABuQRSQnE5zXjCz/JES+NTzVhgXj5RMoXlKLQH+uP2FzUD0wpel8itvFV9rCrZp+OcFyLrrGnmaLbyZnzB1nHIPKsM2QxqT64AAIABAACAAAEBKwBlzR0AAAAAIgAgLFSGEmxJeAeagU4TcV1l82RZ5NbMre0mbQUIZFuvpjIBBUdSIQKdoSzbWyNWkrkVNq/v5ckcOrlHPY5DtTODarRWKZyIcSEDNys0I07Xz5wf6l0F1EFVeSe+lUKxYusC4ass6AIkwAtSriIGAp2hLNtbI1aSuRU2r+/lyRw6uUc9jkO1M4NqtFYpnIhxENkMak+uAACAAAAAgAAAAAAiBgM3KzQjTtfPnB/qXQXUQVV5J76VQrFi6wLhqyzoAiTACxDZDGpPrgAAgAEAAIAAAAAAACICA57/H1R6HV+S36K6evaslxpL0DukpzSwMVaiVritOh75EO3kXMUAAACAAAAAgAEAAIAA";
|
||||||
PSBT psbt1 = PSBT.fromString(psbt);
|
PSBT psbt1 = PSBT.fromString(psbt);
|
||||||
|
|
||||||
|
@ -371,4 +375,9 @@ public class PSBTTest {
|
||||||
|
|
||||||
Assert.assertEquals("0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000", Utils.bytesToHex(transaction.bitcoinSerialize()));
|
Assert.assertEquals("0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000", Utils.bytesToHex(transaction.bitcoinSerialize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
Network.set(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue