fix/tests: fix inconsistencies in getaddressinfo, add tests (#5196)

## Issue being fixed or feature implemented
fixes an issue mentioned
[here](https://github.com/dashpay/dash/pull/5177#pullrequestreview-1293957617)

## What was done?
added missing implementation for `pubkeys`, added help text for
`addresses`, implemented some tests

## How Has This Been Tested?
`./src/test/test_dash -t wallet_tests/rpc_getaddressinfo`

## Breaking Changes
n/a


## Checklist:
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have added or updated relevant unit/integration/functional/e2e
tests
- [ ] I have made corresponding changes to the documentation

**For repository code-owners and collaborators only**
- [x] I have assigned this pull request to a milestone
This commit is contained in:
UdjinM6 2023-02-16 21:39:23 +03:00 committed by GitHub
parent 2083380bc3
commit 33703a5f2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 101 additions and 12 deletions

View File

@ -238,7 +238,7 @@ UniValue getnewaddress(const JSONRPCRequest& request)
return EncodeDestination(dest);
}
static UniValue getrawchangeaddress(const JSONRPCRequest& request)
UniValue getrawchangeaddress(const JSONRPCRequest& request)
{
RPCHelpMan{"getrawchangeaddress",
"\nReturns a new Dash address, for receiving change.\n"
@ -972,7 +972,7 @@ static UniValue sendmany(const JSONRPCRequest& request)
return tx->GetHash().GetHex();
}
static UniValue addmultisigaddress(const JSONRPCRequest& request)
UniValue addmultisigaddress(const JSONRPCRequest& request)
{
RPCHelpMan{"addmultisigaddress",
"\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
@ -3589,19 +3589,24 @@ public:
UniValue obj(UniValue::VOBJ);
CScript subscript;
if (provider && provider->GetCScript(scriptID, subscript)) {
std::vector<CTxDestination> addresses;
TxoutType whichType;
int nRequired;
ExtractDestinations(subscript, whichType, addresses, nRequired);
// Always present: script type and redeemscript
std::vector<std::vector<unsigned char>> solutions_data;
TxoutType whichType = Solver(subscript, solutions_data);
obj.pushKV("script", GetTxnOutputType(whichType));
obj.pushKV("hex", HexStr(subscript));
UniValue a(UniValue::VARR);
for (const CTxDestination& addr : addresses) {
a.push_back(EncodeDestination(addr));
if (whichType == TxoutType::MULTISIG) {
// Also report some information on multisig scripts (which do not have a corresponding address).
UniValue pubkeys(UniValue::VARR);
UniValue addresses(UniValue::VARR);
for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
CPubKey pubkey(solutions_data[i]);
pubkeys.push_back(HexStr(pubkey));
addresses.push_back(EncodeDestination(PKHash(pubkey)));
}
obj.pushKV("pubkeys", std::move(pubkeys));
obj.pushKV("addresses", std::move(addresses));
obj.pushKV("sigsrequired", solutions_data[0][0]);
}
obj.pushKV("addresses", a);
if (whichType == TxoutType::MULTISIG)
obj.pushKV("sigsrequired", nRequired);
}
return obj;
}
@ -3657,6 +3662,10 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
{
{RPCResult::Type::STR, "pubkey", ""},
}},
{RPCResult::Type::ARR, "addresses", /* optional */ true, "Array of addresses associated with the known redeemscript (only if \"script\" is \"multisig\").",
{
{RPCResult::Type::STR, "address", ""},
}},
{RPCResult::Type::NUM, "sigsrequired", /* optional */ true, "The number of signatures required to spend multisig output (only if \"script\" is \"multisig\")."},
{RPCResult::Type::STR_HEX, "pubkey", /* optional */ true, "The hex value of the raw public key, for single-key addresses."},
{RPCResult::Type::BOOL, "iscompressed", /* optional */ true, "If the pubkey is compressed."},

View File

@ -38,5 +38,7 @@ WalletContext& EnsureWalletContext(const CoreContext& context);
LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet);
UniValue getaddressinfo(const JSONRPCRequest& request);
UniValue getrawchangeaddress(const JSONRPCRequest& request);
UniValue addmultisigaddress(const JSONRPCRequest& request);
UniValue signrawtransactionwithwallet(const JSONRPCRequest& request);
#endif //BITCOIN_WALLET_RPCWALLET_H

View File

@ -30,6 +30,9 @@ extern UniValue importmulti(const JSONRPCRequest& request);
extern UniValue dumpwallet(const JSONRPCRequest& request);
extern UniValue importwallet(const JSONRPCRequest& request);
extern UniValue getnewaddress(const JSONRPCRequest& request);
extern UniValue getrawchangeaddress(const JSONRPCRequest& request);
extern UniValue getaddressinfo(const JSONRPCRequest& request);
extern UniValue addmultisigaddress(const JSONRPCRequest& request);
BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
@ -306,6 +309,81 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
SetMockTime(0);
}
// Verify getaddressinfo RPC produces more or less expected results
BOOST_FIXTURE_TEST_CASE(rpc_getaddressinfo, TestChain100Setup)
{
NodeContext node;
auto chain = interfaces::MakeChain(node);
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateMockWalletDatabase());
AddWallet(wallet);
CoreContext context{m_node};
JSONRPCRequest request(context);
UniValue response;
// test p2pkh
std::string addr;
BOOST_CHECK_NO_THROW(addr = ::getrawchangeaddress(request).get_str());
request.params.clear();
request.params.setArray();
request.params.push_back(addr);
BOOST_CHECK_NO_THROW(response = ::getaddressinfo(request).get_obj());
BOOST_CHECK_EQUAL(find_value(response, "ismine").get_bool(), true);
BOOST_CHECK_EQUAL(find_value(response, "solvable").get_bool(), true);
BOOST_CHECK_EQUAL(find_value(response, "iswatchonly").get_bool(), false);
BOOST_CHECK_EQUAL(find_value(response, "isscript").get_bool(), false);
BOOST_CHECK_EQUAL(find_value(response, "ischange").get_bool(), true);
BOOST_CHECK(find_value(response, "pubkeys").isNull());
BOOST_CHECK(find_value(response, "addresses").isNull());
BOOST_CHECK(find_value(response, "sigsrequired").isNull());
BOOST_CHECK(find_value(response, "label").isNull());
// test p2sh/multisig
std::string addr1;
std::string addr2;
BOOST_CHECK_NO_THROW(addr1 = ::getnewaddress(request).get_str());
BOOST_CHECK_NO_THROW(addr2 = ::getnewaddress(request).get_str());
UniValue keys;
keys.setArray();
keys.push_back(addr1);
keys.push_back(addr2);
request.params.clear();
request.params.setArray();
request.params.push_back(2);
request.params.push_back(keys);
BOOST_CHECK_NO_THROW(response = ::addmultisigaddress(request));
std::string multisig = find_value(response.get_obj(), "address").get_str();
request.params.clear();
request.params.setArray();
request.params.push_back(multisig);
BOOST_CHECK_NO_THROW(response = ::getaddressinfo(request).get_obj());
BOOST_CHECK_EQUAL(find_value(response, "ismine").get_bool(), true);
BOOST_CHECK_EQUAL(find_value(response, "solvable").get_bool(), true);
BOOST_CHECK_EQUAL(find_value(response, "iswatchonly").get_bool(), false);
BOOST_CHECK_EQUAL(find_value(response, "isscript").get_bool(), true);
BOOST_CHECK_EQUAL(find_value(response, "ischange").get_bool(), false);
BOOST_CHECK_EQUAL(find_value(response, "label").get_str(), "");
BOOST_CHECK_EQUAL(find_value(response, "sigsrequired").get_int(), 2);
UniValue pubkeys = find_value(response, "pubkeys").get_array();
UniValue addresses = find_value(response, "addresses").get_array();
BOOST_CHECK_EQUAL(addresses.size(), 2);
BOOST_CHECK_EQUAL(addresses[0].get_str(), addr1);
BOOST_CHECK_EQUAL(addresses[1].get_str(), addr2);
BOOST_CHECK_EQUAL(pubkeys.size(), 2);
RemoveWallet(wallet, std::nullopt);
}
// Check that GetImmatureCredit() returns a newly calculated value instead of
// the cached value after a MarkDirty() call.
//