aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Dobson <dobsonsa68@gmail.com>2021-10-01 12:14:48 +1300
committerSamuel Dobson <dobsonsa68@gmail.com>2021-10-12 12:03:14 +1300
commit0b06e720c0182dee8b560d2e8d3891b036f63ea7 (patch)
tree58a88962dec904fad592d88021808fea26ed10c7
parent1790a8ddacae0d52135f5020894ef1ceef625cf9 (diff)
downloadbitcoin-0b06e720c0182dee8b560d2e8d3891b036f63ea7.tar.xz
More detailed error checking for base58 addresses
-rw-r--r--src/key_io.cpp30
-rwxr-xr-xtest/functional/rpc_invalid_address_message.py8
2 files changed, 27 insertions, 11 deletions
diff --git a/src/key_io.cpp b/src/key_io.cpp
index 615f4c9312..9e246c0b81 100644
--- a/src/key_io.cpp
+++ b/src/key_io.cpp
@@ -81,7 +81,11 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
std::vector<unsigned char> data;
uint160 hash;
error_str = "";
- if (DecodeBase58Check(str, data, 21)) {
+
+ // Note this will be false if it is a valid Bech32 address for a different network
+ bool is_bech32 = (ToLower(str.substr(0, params.Bech32HRP().size())) == params.Bech32HRP());
+
+ if (!is_bech32 && DecodeBase58Check(str, data, 21)) {
// base58-encoded Bitcoin addresses.
// Public-key-hash-addresses have version 0 (or 111 testnet).
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
@@ -98,15 +102,27 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
return ScriptHash(hash);
}
- // Set potential error message.
- // This message may be changed if the address can also be interpreted as a Bech32 address.
- error_str = "Invalid prefix for Base58-encoded address";
+ if (!std::equal(script_prefix.begin(), script_prefix.end(), data.begin()) &&
+ !std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
+ error_str = "Invalid prefix for Base58-encoded address";
+ } else {
+ error_str = "Invalid length for Base58 address";
+ }
+ return CNoDestination();
+ } else if (!is_bech32) {
+ // Try Base58 decoding without the checksum, using a much larger max length
+ if (!DecodeBase58(str, data, 100)) {
+ error_str = "Invalid HRP or Base58 character in address";
+ } else {
+ error_str = "Invalid checksum or length of Base58 address";
+ }
+ return CNoDestination();
}
+
data.clear();
const auto dec = bech32::Decode(str);
if ((dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) && dec.data.size() > 0) {
// Bech32 decoding
- error_str = "";
if (dec.hrp != params.Bech32HRP()) {
error_str = "Invalid prefix for Bech32 address";
return CNoDestination();
@@ -168,8 +184,8 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
}
}
- // Set error message if address can't be interpreted as Base58 or Bech32.
- if (error_str.empty()) error_str = "Invalid address format";
+ //TODO: locate Bech32 errors
+ error_str = "Error in Bech32 encoding";
return CNoDestination();
}
diff --git a/test/functional/rpc_invalid_address_message.py b/test/functional/rpc_invalid_address_message.py
index 7ab5a5e90d..38008cbf42 100755
--- a/test/functional/rpc_invalid_address_message.py
+++ b/test/functional/rpc_invalid_address_message.py
@@ -39,7 +39,7 @@ class InvalidAddressErrorMessageTest(BitcoinTestFramework):
info = node.validateaddress(BECH32_INVALID_PREFIX)
assert not info['isvalid']
- assert_equal(info['error'], 'Invalid prefix for Bech32 address')
+ assert_equal(info['error'], 'Invalid HRP or Base58 character in address')
info = node.validateaddress(BECH32_INVALID_BECH32)
assert not info['isvalid']
@@ -73,18 +73,18 @@ class InvalidAddressErrorMessageTest(BitcoinTestFramework):
# Invalid address format
info = node.validateaddress(INVALID_ADDRESS)
assert not info['isvalid']
- assert_equal(info['error'], 'Invalid address format')
+ assert_equal(info['error'], 'Invalid HRP or Base58 character in address')
def test_getaddressinfo(self):
node = self.nodes[0]
assert_raises_rpc_error(-5, "Invalid Bech32 address data size", node.getaddressinfo, BECH32_INVALID_SIZE)
- assert_raises_rpc_error(-5, "Invalid prefix for Bech32 address", node.getaddressinfo, BECH32_INVALID_PREFIX)
+ assert_raises_rpc_error(-5, "Invalid HRP or Base58 character in address", node.getaddressinfo, BECH32_INVALID_PREFIX)
assert_raises_rpc_error(-5, "Invalid prefix for Base58-encoded address", node.getaddressinfo, BASE58_INVALID_PREFIX)
- assert_raises_rpc_error(-5, "Invalid address format", node.getaddressinfo, INVALID_ADDRESS)
+ assert_raises_rpc_error(-5, "Invalid HRP or Base58 character in address", node.getaddressinfo, INVALID_ADDRESS)
def run_test(self):
self.test_validateaddress()