diff --git a/core/src/main/java/com/google/bitcoin/core/Address.java b/core/src/main/java/com/google/bitcoin/core/Address.java index 234aad34c..649a7f2ad 100644 --- a/core/src/main/java/com/google/bitcoin/core/Address.java +++ b/core/src/main/java/com/google/bitcoin/core/Address.java @@ -21,6 +21,8 @@ import com.google.bitcoin.params.TestNet3Params; import javax.annotation.Nullable; +import static com.google.common.base.Preconditions.checkArgument; + /** *
A Bitcoin address looks like 1MsScoe2fTJoq4ZPdQgqyhgWeoNamYPevy and is derived from an elliptic curve public key * plus a set of network parameters. Not to be confused with a {@link PeerAddress} or {@link AddressMessage} @@ -43,12 +45,11 @@ public class Address extends VersionedChecksummedBytes { * *
new Address(NetworkParameters.prodNet(), NetworkParameters.getAddressHeader(), Hex.decode("4a22c3c4cbb31e4d03b15550636762bda0baf85a"));*/ - public Address(NetworkParameters params, int version, byte[] hash160) { + public Address(NetworkParameters params, int version, byte[] hash160) throws WrongNetworkException { super(version, hash160); + checkArgument(hash160.length == 20, "Addresses are 160-bit hashes, so you must provide 20 bytes"); if (!isAcceptableVersion(params, version)) - throw new RuntimeException("Unrecognized Address version"); - if (hash160.length != 20) // 160 = 8 * 20 - throw new RuntimeException("Addresses are 160-bit hashes, so you must provide 20 bytes"); + throw new WrongNetworkException(version, params.getAcceptableAddressCodes()); } /** @@ -57,7 +58,8 @@ public class Address extends VersionedChecksummedBytes { *
new Address(NetworkParameters.prodNet(), Hex.decode("4a22c3c4cbb31e4d03b15550636762bda0baf85a"));*/ public Address(NetworkParameters params, byte[] hash160) { - this(params, params.getAddressHeader(), hash160); + super(params.getAddressHeader(), hash160); + checkArgument(hash160.length == 20, "Addresses are 160-bit hashes, so you must provide 20 bytes"); } /** @@ -70,7 +72,7 @@ public class Address extends VersionedChecksummedBytes { * @throws AddressFormatException if the given address doesn't parse or the checksum is invalid * @throws WrongNetworkException if the given address is valid but for a different chain (eg testnet vs prodnet) */ - public Address(@Nullable NetworkParameters params, String address) throws AddressFormatException, WrongNetworkException { + public Address(@Nullable NetworkParameters params, String address) throws AddressFormatException { super(address); if (params != null) { if (!isAcceptableVersion(params, version)) { @@ -89,7 +91,8 @@ public class Address extends VersionedChecksummedBytes { * See also https://en.bitcoin.it/wiki/BIP_0013: Address Format for pay-to-script-hash */ public boolean isP2SHAddress() { - return this.version == getParameters().p2shHeader; + final NetworkParameters parameters = getParameters(); + return parameters != null && this.version == parameters.p2shHeader; } /** @@ -100,6 +103,7 @@ public class Address extends VersionedChecksummedBytes { * * @return a NetworkParameters representing the network the address is intended for, or null if unknown. */ + @Nullable public NetworkParameters getParameters() { // TODO: There should be a more generic way to get all supported networks. NetworkParameters[] networks = { TestNet3Params.get(), MainNetParams.get() }; @@ -114,21 +118,22 @@ public class Address extends VersionedChecksummedBytes { /** * Given an address, examines the version byte and attempts to find a matching NetworkParameters. If you aren't sure * which network the address is intended for (eg, it was provided by a user), you can use this to decide if it is - * compatible with the current wallet. You should be able to handle a null response from this method. + * compatible with the current wallet. + * @return a NetworkParameters or null if the string wasn't of a known version. */ + @Nullable public static NetworkParameters getParametersFromAddress(String address) throws AddressFormatException { try { return new Address(null, address).getParameters(); } catch (WrongNetworkException e) { - // Cannot happen. - throw new RuntimeException(e); + throw new RuntimeException(e); // Cannot happen. } } /** * Check if a given address version is valid given the NetworkParameters. */ - private boolean isAcceptableVersion(NetworkParameters params, int version) { + private static boolean isAcceptableVersion(NetworkParameters params, int version) { for (int v : params.getAcceptableAddressCodes()) { if (version == v) { return true;