mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-30 07:47:36 +01:00
More detailed error checking for base58 addresses
This commit is contained in:
@@ -81,7 +81,11 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
|
|||||||
std::vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
uint160 hash;
|
uint160 hash;
|
||||||
error_str = "";
|
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.
|
// base58-encoded Bitcoin addresses.
|
||||||
// Public-key-hash-addresses have version 0 (or 111 testnet).
|
// Public-key-hash-addresses have version 0 (or 111 testnet).
|
||||||
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
|
// 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);
|
return ScriptHash(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set potential error message.
|
if (!std::equal(script_prefix.begin(), script_prefix.end(), data.begin()) &&
|
||||||
// This message may be changed if the address can also be interpreted as a Bech32 address.
|
!std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
|
||||||
error_str = "Invalid prefix for Base58-encoded address";
|
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();
|
data.clear();
|
||||||
const auto dec = bech32::Decode(str);
|
const auto dec = bech32::Decode(str);
|
||||||
if ((dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) && dec.data.size() > 0) {
|
if ((dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) && dec.data.size() > 0) {
|
||||||
// Bech32 decoding
|
// Bech32 decoding
|
||||||
error_str = "";
|
|
||||||
if (dec.hrp != params.Bech32HRP()) {
|
if (dec.hrp != params.Bech32HRP()) {
|
||||||
error_str = "Invalid prefix for Bech32 address";
|
error_str = "Invalid prefix for Bech32 address";
|
||||||
return CNoDestination();
|
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.
|
//TODO: locate Bech32 errors
|
||||||
if (error_str.empty()) error_str = "Invalid address format";
|
error_str = "Error in Bech32 encoding";
|
||||||
|
|
||||||
return CNoDestination();
|
return CNoDestination();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class InvalidAddressErrorMessageTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
info = node.validateaddress(BECH32_INVALID_PREFIX)
|
info = node.validateaddress(BECH32_INVALID_PREFIX)
|
||||||
assert not info['isvalid']
|
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)
|
info = node.validateaddress(BECH32_INVALID_BECH32)
|
||||||
assert not info['isvalid']
|
assert not info['isvalid']
|
||||||
@@ -73,18 +73,18 @@ class InvalidAddressErrorMessageTest(BitcoinTestFramework):
|
|||||||
# Invalid address format
|
# Invalid address format
|
||||||
info = node.validateaddress(INVALID_ADDRESS)
|
info = node.validateaddress(INVALID_ADDRESS)
|
||||||
assert not info['isvalid']
|
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):
|
def test_getaddressinfo(self):
|
||||||
node = self.nodes[0]
|
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 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 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):
|
def run_test(self):
|
||||||
self.test_validateaddress()
|
self.test_validateaddress()
|
||||||
|
|||||||
Reference in New Issue
Block a user