mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-03-10 00:09:31 +01:00
BitcoinNetwork: add address validation methods
There are use cases where an already parsed address needs to be validated for a specific network. In one use case the address came from an external source and needs validation with an error message displayed: that's what `isValidAddress(Address)` is for. In the other case we can treat the invalid address as a fatal error. That's `checkAddress(Address)`.
This commit is contained in:
parent
f1a5ebe71e
commit
53a6b3e150
2 changed files with 103 additions and 0 deletions
|
@ -182,6 +182,57 @@ public enum BitcoinNetwork implements Network {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an address is valid on this network.
|
||||||
|
* This is meant to be used as a precondition for a method or function that expects a valid address. If
|
||||||
|
* you are validating addresses provided externally, you probably want to use
|
||||||
|
* {@link #isValidAddress(Address)} to handle errors more gracefully. This method uses {@link #isValidAddress(Address)}
|
||||||
|
* internally which properly accounts for address normalization.
|
||||||
|
* @param address Address to validate
|
||||||
|
* @return The unmodified address if valid on this network
|
||||||
|
* @throws IllegalArgumentException if address not valid on this network
|
||||||
|
*/
|
||||||
|
public Address checkAddress(Address address) throws IllegalArgumentException {
|
||||||
|
if (!isValidAddress(address)) {
|
||||||
|
throw new IllegalArgumentException(String.format("Address %s not valid on network %s", address, this));
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is address valid for this network. Because we normalize the {@code network()} value in the {@link Address}
|
||||||
|
* type (see the JavaDoc for {@link Address#network()}) this method should be used in preference to simply
|
||||||
|
* verifying that {@code address.network()} returns the desired network type.
|
||||||
|
* @param address Address to validate
|
||||||
|
* @return {@code true} if valid on this network, {@code false} otherwise
|
||||||
|
*/
|
||||||
|
public boolean isValidAddress(Address address) {
|
||||||
|
boolean valid;
|
||||||
|
switch (this) {
|
||||||
|
case MAINNET:
|
||||||
|
valid = address.network() == MAINNET;
|
||||||
|
break;
|
||||||
|
case TESTNET:
|
||||||
|
case SIGNET:
|
||||||
|
// SIGNET uses the same addresses as TESTNET
|
||||||
|
valid = address.network() == TESTNET;
|
||||||
|
break;
|
||||||
|
case REGTEST:
|
||||||
|
if (address instanceof LegacyAddress) {
|
||||||
|
// For Legacy addresses, REGTEST uses TESTNET addresses
|
||||||
|
valid = ((LegacyAddress) address).network == TESTNET;
|
||||||
|
} else {
|
||||||
|
// On segwit, REGTEST has its own address type
|
||||||
|
valid = address.network() == REGTEST;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the {@code BitcoinNetwork} from a name string, e.g. "mainnet", "testnet" or "signet".
|
* Find the {@code BitcoinNetwork} from a name string, e.g. "mainnet", "testnet" or "signet".
|
||||||
* A number of common alternate names are allowed too, e.g. "main" or "prod".
|
* A number of common alternate names are allowed too, e.g. "main" or "prod".
|
||||||
|
|
|
@ -18,8 +18,13 @@ package org.bitcoinj.base;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.bitcoinj.base.BitcoinNetwork.MAINNET;
|
||||||
|
import static org.bitcoinj.base.BitcoinNetwork.REGTEST;
|
||||||
|
import static org.bitcoinj.base.BitcoinNetwork.SIGNET;
|
||||||
|
import static org.bitcoinj.base.BitcoinNetwork.TESTNET;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class BitcoinNetworkTest {
|
public class BitcoinNetworkTest {
|
||||||
@Test
|
@Test
|
||||||
|
@ -79,4 +84,51 @@ public class BitcoinNetworkTest {
|
||||||
public void fromIdString_notExisting() {
|
public void fromIdString_notExisting() {
|
||||||
assertFalse(BitcoinNetwork.fromIdString("a.b.c").isPresent());
|
assertFalse(BitcoinNetwork.fromIdString("a.b.c").isPresent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLegacyAddressValidity() {
|
||||||
|
LegacyAddress m = LegacyAddress.fromBase58("17kzeh4N8g49GFvdDzSf8PjaPfyoD1MndL", MAINNET);
|
||||||
|
LegacyAddress t = LegacyAddress.fromBase58("n4eA2nbYqErp7H6jebchxAN59DmNpksexv", TESTNET);
|
||||||
|
|
||||||
|
assertTrue(MAINNET.isValidAddress(m));
|
||||||
|
assertTrue(TESTNET.isValidAddress(t));
|
||||||
|
assertTrue(SIGNET.isValidAddress(t));
|
||||||
|
assertTrue(REGTEST.isValidAddress(t));
|
||||||
|
|
||||||
|
assertFalse(MAINNET.isValidAddress(t));
|
||||||
|
assertFalse(TESTNET.isValidAddress(m));
|
||||||
|
assertFalse(SIGNET.isValidAddress(m));
|
||||||
|
assertFalse(REGTEST.isValidAddress(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSegwitAddressValidity() {
|
||||||
|
SegwitAddress m = SegwitAddress.fromBech32("bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs", MAINNET);
|
||||||
|
SegwitAddress t = SegwitAddress.fromBech32("tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c", TESTNET);
|
||||||
|
SegwitAddress rt = SegwitAddress.fromBech32("bcrt1qspfueag7fvty7m8htuzare3xs898zvh30fttu2", REGTEST);
|
||||||
|
|
||||||
|
assertTrue(MAINNET.isValidAddress(m));
|
||||||
|
assertTrue(TESTNET.isValidAddress(t));
|
||||||
|
assertTrue(SIGNET.isValidAddress(t));
|
||||||
|
assertTrue(REGTEST.isValidAddress(rt));
|
||||||
|
|
||||||
|
assertFalse(MAINNET.isValidAddress(t));
|
||||||
|
assertFalse(MAINNET.isValidAddress(rt));
|
||||||
|
assertFalse(TESTNET.isValidAddress(m));
|
||||||
|
assertFalse(TESTNET.isValidAddress(rt));
|
||||||
|
assertFalse(SIGNET.isValidAddress(m));
|
||||||
|
assertFalse(SIGNET.isValidAddress(rt));
|
||||||
|
assertFalse(REGTEST.isValidAddress(m));
|
||||||
|
assertFalse(REGTEST.isValidAddress(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testLegacyAddressCheckThrow() {
|
||||||
|
MAINNET.checkAddress(LegacyAddress.fromBase58("n4eA2nbYqErp7H6jebchxAN59DmNpksexv", TESTNET));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testSegwitAddressCheckThrow() {
|
||||||
|
MAINNET.checkAddress(SegwitAddress.fromBech32("tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c", TESTNET));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue