Skip to content

Commit

Permalink
RPC/misc: Attempt to autodetect address type for error checking
Browse files Browse the repository at this point in the history
  • Loading branch information
luke-jr committed Nov 13, 2019
1 parent 2f8e687 commit 65b45fa
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 6 deletions.
10 changes: 9 additions & 1 deletion src/key_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,16 @@ bool IsValidDestinationString(const std::string& str)
return IsValidDestinationString(str, Params());
}

std::pair<int, std::string> LocateErrorInDestinationString(const std::string& str, const std::string& address_type)
std::pair<int, std::string> LocateErrorInDestinationString(const std::string& str, std::string& address_type)
{
if (address_type.empty()) {
size_t hrp_end_pos = str.rfind('1');
if (hrp_end_pos != str.npos && ToLower(str.substr(0, hrp_end_pos)) == Params().Bech32HRP()) {
address_type = "bech32";
} else {
address_type = "legacy";
}
}
std::vector<unsigned char> data;
if (address_type == "legacy" || address_type == "p2sh-segwit") {
uint160 hash;
Expand Down
2 changes: 1 addition & 1 deletion src/key_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ CTxDestination DecodeDestination(const std::string& str);
bool IsValidDestinationString(const std::string& str);
bool IsValidDestinationString(const std::string& str, const CChainParams& params);

std::pair<int, std::string> LocateErrorInDestinationString(const std::string& str, const std::string& address_type);
std::pair<int, std::string> LocateErrorInDestinationString(const std::string& str, std::string& address_type);

#endif // BITCOIN_KEY_IO_H
5 changes: 3 additions & 2 deletions src/rpc/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ static UniValue validateaddress(const JSONRPCRequest& request)

UniValue detail = DescribeAddress(dest);
ret.pushKVs(detail);
} else if (!request.params[1].isNull()) {
std::string address_type = request.params[1].get_str();
} else {
std::string address_type;
if (!request.params[1].isNull()) address_type = request.params[1].get_str();
std::string error;
auto res = LocateErrorInDestinationString(address, address_type);
ret.pushKV("error", res.second);
Expand Down
17 changes: 15 additions & 2 deletions test/functional/rpc_validateaddress.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ def set_test_params(self):
self.num_nodes = 1

def run_test(self):

# Valid address
address = "bcrt1q049ldschfnwystcqnsvyfpj23mpsg3jcedq9xv"
res = self.nodes[0].validateaddress(address, "bech32")
Expand All @@ -30,7 +29,7 @@ def run_test(self):
address = "bcrtq049ldschfnwystcqnsvyfpj23mpsg3jcedq9xv"
res = self.nodes[0].validateaddress(address)
assert_equal(res['isvalid'], False)
assert 'error' not in res
assert_equal(res['error'], "Invalid Base58 character in address")
assert 'error_index' not in res

# Address with no '1' separator
Expand Down Expand Up @@ -61,6 +60,13 @@ def run_test(self):
assert_equal(res['error_index'], 9)
assert_equal(res['error'], "Invalid")

# Address with one error, without type specified
address = "bcrt1q049edschfnwystcqnsvyfpj23mpsg3jcedq9xv"
res = self.nodes[0].validateaddress(address)
assert_equal(res['isvalid'], False)
assert_equal(res['error_index'], 9)
assert_equal(res['error'], "Invalid")

# Capitalised address with one error
address = "BCRT1QPLMTZKC2XHARPPZDLNPAQL78RSHJ68U32RAH7R"
res = self.nodes[0].validateaddress(address, "bech32")
Expand Down Expand Up @@ -106,6 +112,13 @@ def run_test(self):
assert_equal(res['error'], "Invalid checksum for Base58 address")
assert 'error_index' not in res

# Legacy address with one error, without type specified
address = "muehQnn2P5NhiRCGg9HewAWrXLRy2d7TZE"
res = self.nodes[0].validateaddress(address)
assert_equal(res['isvalid'], False)
assert_equal(res['error'], "Invalid checksum for Base58 address")
assert 'error_index' not in res

# Legacy address with a non-Base58 character
address = "muehQnn2P5NiiRCGO9HewAWrXLRy2d7TZE"
res = self.nodes[0].validateaddress(address, "legacy")
Expand Down

0 comments on commit 65b45fa

Please sign in to comment.