diff --git a/core/src/main/java/org/bitcoinj/core/AddressFormatException.java b/core/src/main/java/org/bitcoinj/core/AddressFormatException.java index c7846026..e3b23e74 100644 --- a/core/src/main/java/org/bitcoinj/core/AddressFormatException.java +++ b/core/src/main/java/org/bitcoinj/core/AddressFormatException.java @@ -75,11 +75,26 @@ public class AddressFormatException extends IllegalArgumentException { /** * This exception is thrown by the {@link PrefixedChecksummedBytes} hierarchy of classes when you try and decode an - * address with a version header that isn't used by that network. You shouldn't allow the user to proceed in this - * case as they are trying to send money across different chains, an operation that is guaranteed to destroy the - * money. + * address or private key with an invalid prefix (version header or human-readable part). You shouldn't allow the + * user to proceed in this case. */ - public static class WrongNetwork extends AddressFormatException { + public static class InvalidPrefix extends AddressFormatException { + public InvalidPrefix() { + super(); + } + + public InvalidPrefix(String message) { + super(message); + } + } + + /** + * This exception is thrown by the {@link PrefixedChecksummedBytes} hierarchy of classes when you try and decode an + * address with a prefix (version header or human-readable part) that used by another network (usually: mainnet vs + * testnet). You shouldn't allow the user to proceed in this case as they are trying to send money across different + * chains, an operation that is guaranteed to destroy the money. + */ + public static class WrongNetwork extends InvalidPrefix { public WrongNetwork(int versionHeader) { super("Version code of address did not match acceptable versions for network: " + versionHeader); } diff --git a/core/src/main/java/org/bitcoinj/core/Bech32.java b/core/src/main/java/org/bitcoinj/core/Bech32.java index c6cf72e7..ad0c940a 100644 --- a/core/src/main/java/org/bitcoinj/core/Bech32.java +++ b/core/src/main/java/org/bitcoinj/core/Bech32.java @@ -143,7 +143,7 @@ public class Bech32 { } } final int pos = str.lastIndexOf('1'); - if (pos < 1) throw new AddressFormatException("Missing human-readable part"); + if (pos < 1) throw new AddressFormatException.InvalidPrefix("Missing human-readable part"); final int dataPartLength = str.length() - 1 - pos; if (dataPartLength < 6) throw new AddressFormatException.InvalidDataLength("Data part too short: " + dataPartLength); byte[] values = new byte[dataPartLength]; diff --git a/core/src/main/java/org/bitcoinj/core/DumpedPrivateKey.java b/core/src/main/java/org/bitcoinj/core/DumpedPrivateKey.java index 2268eb4a..3594daaa 100644 --- a/core/src/main/java/org/bitcoinj/core/DumpedPrivateKey.java +++ b/core/src/main/java/org/bitcoinj/core/DumpedPrivateKey.java @@ -52,7 +52,7 @@ public class DumpedPrivateKey extends PrefixedChecksummedBytes { for (NetworkParameters p : Networks.get()) if (version == p.getDumpedPrivateKeyHeader()) return new DumpedPrivateKey(p, bytes); - throw new AddressFormatException("No network found for version " + version); + throw new AddressFormatException.InvalidPrefix("No network found for version " + version); } else { if (version == params.getDumpedPrivateKeyHeader()) return new DumpedPrivateKey(params, bytes); diff --git a/core/src/main/java/org/bitcoinj/core/LegacyAddress.java b/core/src/main/java/org/bitcoinj/core/LegacyAddress.java index a62578ca..066bcf9b 100644 --- a/core/src/main/java/org/bitcoinj/core/LegacyAddress.java +++ b/core/src/main/java/org/bitcoinj/core/LegacyAddress.java @@ -151,7 +151,7 @@ public class LegacyAddress extends Address { else if (version == p.getP2SHHeader()) return new LegacyAddress(p, true, bytes); } - throw new AddressFormatException("No network found for " + base58); + throw new AddressFormatException.InvalidPrefix("No network found for " + base58); } else { if (version == params.getAddressHeader()) return new LegacyAddress(params, false, bytes); diff --git a/core/src/main/java/org/bitcoinj/core/SegwitAddress.java b/core/src/main/java/org/bitcoinj/core/SegwitAddress.java index f0efe25a..28257b8b 100644 --- a/core/src/main/java/org/bitcoinj/core/SegwitAddress.java +++ b/core/src/main/java/org/bitcoinj/core/SegwitAddress.java @@ -177,7 +177,7 @@ public class SegwitAddress extends Address { if (bechData.hrp.equals(p.getSegwitAddressHrp())) return new SegwitAddress(p, bechData.data); } - throw new AddressFormatException("No network found for " + bech32); + throw new AddressFormatException.InvalidPrefix("No network found for " + bech32); } else { if (bechData.hrp.equals(params.getSegwitAddressHrp())) return new SegwitAddress(params, bechData.data); diff --git a/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java b/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java index 904ed197..f4c2268a 100644 --- a/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java +++ b/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java @@ -60,7 +60,7 @@ public class BIP38PrivateKey extends PrefixedChecksummedBytes { byte[] bytes = Arrays.copyOfRange(versionAndDataBytes, 1, versionAndDataBytes.length); if (version != 0x01) - throw new AddressFormatException("Mismatched version number: " + version); + throw new AddressFormatException.InvalidPrefix("Mismatched version number: " + version); if (bytes.length != 38) throw new AddressFormatException.InvalidDataLength("Wrong number of bytes: " + bytes.length); boolean hasLotAndSequence = (bytes[1] & 0x04) != 0; // bit 2 diff --git a/core/src/test/java/org/bitcoinj/core/Bech32Test.java b/core/src/test/java/org/bitcoinj/core/Bech32Test.java index 5848bd58..a8ec6a9c 100644 --- a/core/src/test/java/org/bitcoinj/core/Bech32Test.java +++ b/core/src/test/java/org/bitcoinj/core/Bech32Test.java @@ -89,4 +89,9 @@ public class Bech32Test { public void decode_invalidNetwork() { Bech32.decode("A12UEL5X"); } + + @Test(expected = AddressFormatException.InvalidPrefix.class) + public void decode_invalidHrp() { + Bech32.decode("1pzry9x0s0muk"); + } } diff --git a/core/src/test/java/org/bitcoinj/core/SegwitAddressTest.java b/core/src/test/java/org/bitcoinj/core/SegwitAddressTest.java index e999c2e5..fbcd1234 100644 --- a/core/src/test/java/org/bitcoinj/core/SegwitAddressTest.java +++ b/core/src/test/java/org/bitcoinj/core/SegwitAddressTest.java @@ -180,6 +180,16 @@ public class SegwitAddressTest { SegwitAddress.fromBech32(null, "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90"); } + @Test(expected = AddressFormatException.InvalidPrefix.class) + public void fromBech32_invalidHrp() { + SegwitAddress.fromBech32(null, "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty"); + } + + @Test(expected = AddressFormatException.WrongNetwork.class) + public void fromBech32_wrongNetwork() { + SegwitAddress.fromBech32(TESTNET, "bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj"); + } + @Test public void testJavaSerialization() throws Exception { SegwitAddress address = SegwitAddress.fromBech32(null, "BC1SW50QA3JX3S");