Skip to content

Commit 0b06e72

Browse files
committed
More detailed error checking for base58 addresses
1 parent 1790a8d commit 0b06e72

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

src/key_io.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
8181
std::vector<unsigned char> data;
8282
uint160 hash;
8383
error_str = "";
84-
if (DecodeBase58Check(str, data, 21)) {
84+
85+
// Note this will be false if it is a valid Bech32 address for a different network
86+
bool is_bech32 = (ToLower(str.substr(0, params.Bech32HRP().size())) == params.Bech32HRP());
87+
88+
if (!is_bech32 && DecodeBase58Check(str, data, 21)) {
8589
// base58-encoded Bitcoin addresses.
8690
// Public-key-hash-addresses have version 0 (or 111 testnet).
8791
// 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
98102
return ScriptHash(hash);
99103
}
100104

101-
// Set potential error message.
102-
// This message may be changed if the address can also be interpreted as a Bech32 address.
103-
error_str = "Invalid prefix for Base58-encoded address";
105+
if (!std::equal(script_prefix.begin(), script_prefix.end(), data.begin()) &&
106+
!std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
107+
error_str = "Invalid prefix for Base58-encoded address";
108+
} else {
109+
error_str = "Invalid length for Base58 address";
110+
}
111+
return CNoDestination();
112+
} else if (!is_bech32) {
113+
// Try Base58 decoding without the checksum, using a much larger max length
114+
if (!DecodeBase58(str, data, 100)) {
115+
error_str = "Invalid HRP or Base58 character in address";
116+
} else {
117+
error_str = "Invalid checksum or length of Base58 address";
118+
}
119+
return CNoDestination();
104120
}
121+
105122
data.clear();
106123
const auto dec = bech32::Decode(str);
107124
if ((dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) && dec.data.size() > 0) {
108125
// Bech32 decoding
109-
error_str = "";
110126
if (dec.hrp != params.Bech32HRP()) {
111127
error_str = "Invalid prefix for Bech32 address";
112128
return CNoDestination();
@@ -168,8 +184,8 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
168184
}
169185
}
170186

171-
// Set error message if address can't be interpreted as Base58 or Bech32.
172-
if (error_str.empty()) error_str = "Invalid address format";
187+
//TODO: locate Bech32 errors
188+
error_str = "Error in Bech32 encoding";
173189

174190
return CNoDestination();
175191
}

test/functional/rpc_invalid_address_message.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def test_validateaddress(self):
3939

4040
info = node.validateaddress(BECH32_INVALID_PREFIX)
4141
assert not info['isvalid']
42-
assert_equal(info['error'], 'Invalid prefix for Bech32 address')
42+
assert_equal(info['error'], 'Invalid HRP or Base58 character in address')
4343

4444
info = node.validateaddress(BECH32_INVALID_BECH32)
4545
assert not info['isvalid']
@@ -73,18 +73,18 @@ def test_validateaddress(self):
7373
# Invalid address format
7474
info = node.validateaddress(INVALID_ADDRESS)
7575
assert not info['isvalid']
76-
assert_equal(info['error'], 'Invalid address format')
76+
assert_equal(info['error'], 'Invalid HRP or Base58 character in address')
7777

7878
def test_getaddressinfo(self):
7979
node = self.nodes[0]
8080

8181
assert_raises_rpc_error(-5, "Invalid Bech32 address data size", node.getaddressinfo, BECH32_INVALID_SIZE)
8282

83-
assert_raises_rpc_error(-5, "Invalid prefix for Bech32 address", node.getaddressinfo, BECH32_INVALID_PREFIX)
83+
assert_raises_rpc_error(-5, "Invalid HRP or Base58 character in address", node.getaddressinfo, BECH32_INVALID_PREFIX)
8484

8585
assert_raises_rpc_error(-5, "Invalid prefix for Base58-encoded address", node.getaddressinfo, BASE58_INVALID_PREFIX)
8686

87-
assert_raises_rpc_error(-5, "Invalid address format", node.getaddressinfo, INVALID_ADDRESS)
87+
assert_raises_rpc_error(-5, "Invalid HRP or Base58 character in address", node.getaddressinfo, INVALID_ADDRESS)
8888

8989
def run_test(self):
9090
self.test_validateaddress()

0 commit comments

Comments
 (0)