Better error handling in Address.

This commit is contained in:
Mike Hearn 2013-11-30 15:33:24 +01:00
parent ff54085129
commit 2271e7198e

View file

@ -21,6 +21,8 @@ import com.google.bitcoin.params.TestNet3Params;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
/**
* <p>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 {
*
* <pre>new Address(NetworkParameters.prodNet(), NetworkParameters.getAddressHeader(), Hex.decode("4a22c3c4cbb31e4d03b15550636762bda0baf85a"));</pre>
*/
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 {
* <pre>new Address(NetworkParameters.prodNet(), Hex.decode("4a22c3c4cbb31e4d03b15550636762bda0baf85a"));</pre>
*/
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;