add testnet4 network support

This commit is contained in:
Craig Raw 2024-05-08 15:49:59 +02:00
parent a7dd28dde7
commit 60ac428002
5 changed files with 41 additions and 17 deletions

View file

@ -80,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 for extended key on " + Network.get().getName() + ": " + DeterministicKey.toBase58(serializedKey).substring(0, 4)); throw new IllegalArgumentException("Unknown header bytes for extended key on " + Network.getCanonical().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
@ -206,7 +206,9 @@ public class ExtendedKey {
} }
public static List<Header> getHeaders(Network network) { public static List<Header> getHeaders(Network network) {
return Arrays.stream(Header.values()).filter(header -> header.getNetwork() == network || (header.getNetwork() == Network.TESTNET && network == Network.REGTEST) || (header.getNetwork() == Network.TESTNET && network == Network.SIGNET)).collect(Collectors.toList()); return Arrays.stream(Header.values())
.filter(header -> header.getNetwork() == network || (header.getNetwork() == Network.TESTNET && network == Network.REGTEST) || (header.getNetwork() == Network.TESTNET && network == Network.SIGNET) || (header.getNetwork() == Network.TESTNET && network == Network.TESTNET4))
.collect(Collectors.toList());
} }
public static Header fromExtendedKey(String xkey) { public static Header fromExtendedKey(String xkey) {
@ -219,12 +221,12 @@ public class ExtendedKey {
for(Network network : getOtherNetworks(Network.get())) { for(Network network : getOtherNetworks(Network.get())) {
for(Header otherNetworkKeyHeader : getHeaders(network)) { for(Header otherNetworkKeyHeader : getHeaders(network)) {
if(xkey.startsWith(otherNetworkKeyHeader.name)) { 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("Provided " + otherNetworkKeyHeader.name + " extended key invalid on configured " + Network.getCanonical().getName() + " network. Use a " + network.getName() + " configuration to use this extended key.");
} }
} }
} }
throw new IllegalArgumentException("Unrecognised extended key header for " + Network.get().getName() + ": " + xkey); throw new IllegalArgumentException("Unrecognised extended key header for " + Network.getCanonical().getName() + ": " + xkey);
} }
public static Header fromScriptType(ScriptType scriptType, boolean privateKey) { public static Header fromScriptType(ScriptType scriptType, boolean privateKey) {
@ -247,7 +249,7 @@ public class ExtendedKey {
for(Network otherNetwork : getOtherNetworks(Network.get())) { for(Network otherNetwork : getOtherNetworks(Network.get())) {
for(Header otherNetworkKeyHeader : getHeaders(otherNetwork)) { for(Header otherNetworkKeyHeader : getHeaders(otherNetwork)) {
if(header == otherNetworkKeyHeader.header) { 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."); throw new IllegalArgumentException("Provided " + otherNetworkKeyHeader.name + " extended key invalid on configured " + Network.getCanonical().getName() + " network. Use a " + otherNetwork.getName() + " configuration to use this extended key.");
} }
} }
} }
@ -256,7 +258,7 @@ public class ExtendedKey {
} }
private static List<Network> getOtherNetworks(Network providedNetwork) { private static List<Network> getOtherNetworks(Network providedNetwork) {
return Arrays.stream(Network.values()).filter(network -> network != providedNetwork).collect(Collectors.toList()); return Arrays.stream(Network.canonicalValues()).filter(network -> network != providedNetwork).collect(Collectors.toList());
} }
} }
} }

View file

@ -3,15 +3,19 @@ package com.sparrowwallet.drongo;
import java.util.Locale; import java.util.Locale;
public enum Network { public enum Network {
MAINNET("mainnet", 0, "1", 5, "3", "bc", ExtendedKey.Header.xprv, ExtendedKey.Header.xpub, 128, 8332), MAINNET("mainnet", "Mainnet", "mainnet", 0, "1", 5, "3", "bc", ExtendedKey.Header.xprv, ExtendedKey.Header.xpub, 128, 8332),
TESTNET("testnet", 111, "mn", 196, "2", "tb", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 18332), TESTNET("testnet", "Testnet3", "testnet3", 111, "mn", 196, "2", "tb", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 18332),
REGTEST("regtest", 111, "mn", 196, "2", "bcrt", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 18443), REGTEST("regtest", "Regtest", "regtest", 111, "mn", 196, "2", "bcrt", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 18443),
SIGNET("signet", 111, "mn", 196, "2", "tb", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 38332); SIGNET("signet", "Signet", "signet", 111, "mn", 196, "2", "tb", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 38332),
TESTNET4("testnet4", "Testnet4", "testnet4", 111, "mn", 196, "2", "tb", ExtendedKey.Header.tprv, ExtendedKey.Header.tpub, 239, 48332);
public static final String BLOCK_HEIGHT_PROPERTY = "com.sparrowwallet.blockHeight"; 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, int p2pkhAddressHeader, String p2pkhAddressPrefix, int p2shAddressHeader, String p2shAddressPrefix, String bech32AddressHrp, 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, ExtendedKey.Header xprvHeader, ExtendedKey.Header xpubHeader, int dumpedPrivateKeyHeader, int defaultPort) {
this.name = name; this.name = name;
this.displayName = displayName;
this.home = home;
this.p2pkhAddressHeader = p2pkhAddressHeader; this.p2pkhAddressHeader = p2pkhAddressHeader;
this.p2pkhAddressPrefix = p2pkhAddressPrefix; this.p2pkhAddressPrefix = p2pkhAddressPrefix;
this.p2shAddressHeader = p2shAddressHeader; this.p2shAddressHeader = p2shAddressHeader;
@ -24,6 +28,8 @@ public enum Network {
} }
private final String name; private final String name;
private final String displayName;
private final String home;
private final int p2pkhAddressHeader; private final int p2pkhAddressHeader;
private final String p2pkhAddressPrefix; private final String p2pkhAddressPrefix;
private final int p2shAddressHeader; private final int p2shAddressHeader;
@ -40,10 +46,18 @@ public enum Network {
return name; return name;
} }
public String toDisplayString() { public String getCapitalizedName() {
return name.substring(0, 1).toUpperCase(Locale.ROOT) + name.substring(1); return name.substring(0, 1).toUpperCase(Locale.ROOT) + name.substring(1);
} }
public String toDisplayString() {
return displayName;
}
public String getHome() {
return home;
}
public int getP2PKHAddressHeader() { public int getP2PKHAddressHeader() {
return p2pkhAddressHeader; return p2pkhAddressHeader;
} }
@ -94,6 +108,14 @@ public enum Network {
return currentNetwork; return currentNetwork;
} }
public static Network getCanonical() {
return get() == TESTNET4 ? TESTNET : get();
}
public static Network[] canonicalValues() {
return CANONICAL_VALUES;
}
public static void set(Network network) { public static void set(Network network) {
if(currentNetwork != null && network != currentNetwork && !isTest()) { if(currentNetwork != null && network != currentNetwork && !isTest()) {
throw new IllegalStateException("Network already set to " + currentNetwork.getName()); throw new IllegalStateException("Network already set to " + currentNetwork.getName());

View file

@ -70,11 +70,11 @@ public abstract class Address {
try { try {
return fromString(Network.get(), address); return fromString(Network.get(), address);
} catch(InvalidAddressException e) { } catch(InvalidAddressException e) {
for(Network network : Network.values()) { for(Network network : Network.canonicalValues()) {
try { try {
fromString(network, address); fromString(network, address);
if(network != Network.get()) { if(network != Network.getCanonical()) {
throw new InvalidAddressException("Provided " + network.getName() + " address invalid on configured " + Network.get().getName() + " network: " + address + ". Use a " + network.getName() + " configuration to use this address."); throw new InvalidAddressException("Provided " + network.getName() + " address invalid on configured " + Network.getCanonical().getName() + " network: " + address + ". Use a " + network.getName() + " configuration to use this address.");
} }
} catch(InvalidAddressException i) { } catch(InvalidAddressException i) {
//ignore //ignore

View file

@ -48,7 +48,7 @@ public class DumpedPrivateKey extends VersionedChecksummedBytes {
private DumpedPrivateKey(String encoded) { private DumpedPrivateKey(String encoded) {
super(encoded); super(encoded);
if(version != Network.get().getDumpedPrivateKeyHeader()) if(version != Network.get().getDumpedPrivateKeyHeader())
throw new IllegalArgumentException("Invalid version " + version + " for network " + Network.get()); throw new IllegalArgumentException("Invalid version " + version + " for network " + Network.getCanonical());
if(bytes.length == 33 && bytes[32] == 1) { if(bytes.length == 33 && bytes[32] == 1) {
compressed = true; compressed = true;
bytes = Arrays.copyOf(bytes, 32); // Chop off the additional marker byte. bytes = Arrays.copyOf(bytes, 32); // Chop off the additional marker byte.

View file

@ -32,7 +32,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
private String label; private String label;
private Wallet masterWallet; private Wallet masterWallet;
private List<Wallet> childWallets = new ArrayList<>(); private List<Wallet> childWallets = new ArrayList<>();
private Network network = Network.get(); private Network network = Network.getCanonical();
private PolicyType policyType; private PolicyType policyType;
private ScriptType scriptType; private ScriptType scriptType;
private Policy defaultPolicy; private Policy defaultPolicy;