mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-19 13:27:35 +02:00
Merge 80e16cadd5 into merged_master (Bitcoin PR #20012)
Made some edits to rpc/client.cpp on the advice of test/functional/rpc_help.py to make the "RPC conversion tables" consistent, but I have no idea what these tables are or what they're for. I assume, given that nobody has noticed these inconsistencies ever, that they're fine.
This commit is contained in:
commit
561bf64d1b
16 changed files with 321 additions and 387 deletions
|
|
@ -21,7 +21,6 @@ test/lint/git-subtree-check.sh src/univalue
|
|||
test/lint/git-subtree-check.sh src/leveldb
|
||||
test/lint/git-subtree-check.sh src/crc32c
|
||||
test/lint/check-doc.py
|
||||
test/lint/check-rpc-mappings.py .
|
||||
test/lint/lint-all.sh
|
||||
|
||||
if [ "$CIRRUS_REPO_FULL_NAME" = "bitcoin/bitcoin" ] && [ -n "$CIRRUS_CRON" ]; then
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ static RPCHelpMan rpcNestedTest_rpc()
|
|||
}
|
||||
|
||||
static const CRPCCommand vRPCCommands[] = {
|
||||
{"test", "rpcNestedTest", &rpcNestedTest_rpc, {"arg1", "arg2", "arg3"}},
|
||||
{"test", &rpcNestedTest_rpc},
|
||||
};
|
||||
|
||||
void RPCNestedTests::rpcNestedTests()
|
||||
|
|
|
|||
|
|
@ -2746,44 +2746,44 @@ void RegisterBlockchainRPCCommands(CRPCTable &t)
|
|||
// clang-format off
|
||||
|
||||
static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) argNames
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ "blockchain", "getblockchaininfo", &getblockchaininfo, {} },
|
||||
{ "blockchain", "getchaintxstats", &getchaintxstats, {"nblocks", "blockhash"} },
|
||||
{ "blockchain", "getblockstats", &getblockstats, {"hash_or_height", "stats"} },
|
||||
{ "blockchain", "getbestblockhash", &getbestblockhash, {} },
|
||||
{ "blockchain", "getblockcount", &getblockcount, {} },
|
||||
{ "blockchain", "getblock", &getblock, {"blockhash","verbosity|verbose"} },
|
||||
{ "blockchain", "getblockhash", &getblockhash, {"height"} },
|
||||
{ "blockchain", "getblockheader", &getblockheader, {"blockhash","verbose"} },
|
||||
{ "blockchain", "getchaintips", &getchaintips, {} },
|
||||
{ "blockchain", "getdifficulty", &getdifficulty, {} },
|
||||
{ "blockchain", "getmempoolancestors", &getmempoolancestors, {"txid","verbose"} },
|
||||
{ "blockchain", "getmempooldescendants", &getmempooldescendants, {"txid","verbose"} },
|
||||
{ "blockchain", "getmempoolentry", &getmempoolentry, {"txid"} },
|
||||
{ "blockchain", "getmempoolinfo", &getmempoolinfo, {} },
|
||||
{ "blockchain", "getrawmempool", &getrawmempool, {"verbose", "mempool_sequence"} },
|
||||
{ "blockchain", "gettxout", &gettxout, {"txid","n","include_mempool"} },
|
||||
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, {"hash_type"} },
|
||||
{ "blockchain", "pruneblockchain", &pruneblockchain, {"height"} },
|
||||
{ "blockchain", "savemempool", &savemempool, {} },
|
||||
{ "blockchain", "verifychain", &verifychain, {"checklevel","nblocks"} },
|
||||
{ // category actor (function)
|
||||
// --------------------- ------------------------
|
||||
{ "blockchain", &getblockchaininfo, },
|
||||
{ "blockchain", &getchaintxstats, },
|
||||
{ "blockchain", &getblockstats, },
|
||||
{ "blockchain", &getbestblockhash, },
|
||||
{ "blockchain", &getblockcount, },
|
||||
{ "blockchain", &getblock, },
|
||||
{ "blockchain", &getblockhash, },
|
||||
{ "blockchain", &getblockheader, },
|
||||
{ "blockchain", &getchaintips, },
|
||||
{ "blockchain", &getdifficulty, },
|
||||
{ "blockchain", &getmempoolancestors, },
|
||||
{ "blockchain", &getmempooldescendants, },
|
||||
{ "blockchain", &getmempoolentry, },
|
||||
{ "blockchain", &getmempoolinfo, },
|
||||
{ "blockchain", &getrawmempool, },
|
||||
{ "blockchain", &gettxout, },
|
||||
{ "blockchain", &gettxoutsetinfo, },
|
||||
{ "blockchain", &pruneblockchain, },
|
||||
{ "blockchain", &savemempool, },
|
||||
{ "blockchain", &verifychain, },
|
||||
|
||||
{ "blockchain", "preciousblock", &preciousblock, {"blockhash"} },
|
||||
{ "blockchain", "scantxoutset", &scantxoutset, {"action", "scanobjects"} },
|
||||
{ "blockchain", "getblockfilter", &getblockfilter, {"blockhash", "filtertype"} },
|
||||
{ "blockchain", &preciousblock, },
|
||||
{ "blockchain", &scantxoutset, },
|
||||
{ "blockchain", &getblockfilter, },
|
||||
|
||||
// ELEMENTS:
|
||||
{ "blockchain", "getsidechaininfo", &getsidechaininfo, {} },
|
||||
{ "blockchain", &getsidechaininfo, },
|
||||
|
||||
/* Not shown in help */
|
||||
{ "hidden", "invalidateblock", &invalidateblock, {"blockhash"} },
|
||||
{ "hidden", "reconsiderblock", &reconsiderblock, {"blockhash"} },
|
||||
{ "hidden", "waitfornewblock", &waitfornewblock, {"timeout"} },
|
||||
{ "hidden", "waitforblock", &waitforblock, {"blockhash","timeout"} },
|
||||
{ "hidden", "waitforblockheight", &waitforblockheight, {"height","timeout"} },
|
||||
{ "hidden", "syncwithvalidationinterfacequeue", &syncwithvalidationinterfacequeue, {} },
|
||||
{ "hidden", "dumptxoutset", &dumptxoutset, {"path"} },
|
||||
{ "hidden", &invalidateblock, },
|
||||
{ "hidden", &reconsiderblock, },
|
||||
{ "hidden", &waitfornewblock, },
|
||||
{ "hidden", &waitforblock, },
|
||||
{ "hidden", &waitforblockheight, },
|
||||
{ "hidden", &syncwithvalidationinterfacequeue, },
|
||||
{ "hidden", &dumptxoutset, },
|
||||
};
|
||||
// clang-format on
|
||||
for (const auto& c : commands) {
|
||||
|
|
|
|||
|
|
@ -193,6 +193,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "stop", 0, "wait" },
|
||||
//
|
||||
// ELEMENTS:
|
||||
{ "calcfastmerkleroot", 0, "leaves" },
|
||||
{ "combineblocksigs", 1, "signatures" },
|
||||
{ "sendtomainchain", 1, "amount" },
|
||||
{ "sendtomainchain", 2, "subtractfeefromamount" },
|
||||
|
|
@ -213,12 +214,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "rawblindrawtransaction", 2, "inputamounts" },
|
||||
{ "rawblindrawtransaction", 3, "inputassets" },
|
||||
{ "rawblindrawtransaction", 4, "inputassetblinders" },
|
||||
{ "rawblindrawtransaction", 5, "totalblinder" },
|
||||
{ "rawblindrawtransaction", 6, "ignoreblindfail" },
|
||||
{ "blindrawtransaction", 1, "ignoreblindfail" },
|
||||
{ "blindrawtransaction", 2, "asset_commitments" },
|
||||
{ "blindrawtransaction", 3, "blind_issuances" },
|
||||
{ "blindrawtransaction", 4, "totalblinder" },
|
||||
{ "blindpsbt", 1, "ignoreblindfail" },
|
||||
{ "destroyamount", 1, "amount" },
|
||||
{ "destroyamount", 3, "verbose"},
|
||||
|
|
@ -227,6 +226,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "sendtoaddress", 10, "ignoreblindfail" },
|
||||
{ "createrawtransaction", 4, "output_assets" },
|
||||
{ "createpsbt", 4, "output_assets" },
|
||||
{ "walletsignpsbt", 2, "imbalance_ok" },
|
||||
|
||||
};
|
||||
// clang-format on
|
||||
|
|
@ -250,14 +250,9 @@ public:
|
|||
|
||||
CRPCConvertTable::CRPCConvertTable()
|
||||
{
|
||||
const unsigned int n_elem =
|
||||
(sizeof(vRPCConvertParams) / sizeof(vRPCConvertParams[0]));
|
||||
|
||||
for (unsigned int i = 0; i < n_elem; i++) {
|
||||
members.insert(std::make_pair(vRPCConvertParams[i].methodName,
|
||||
vRPCConvertParams[i].paramIdx));
|
||||
membersByName.insert(std::make_pair(vRPCConvertParams[i].methodName,
|
||||
vRPCConvertParams[i].paramName));
|
||||
for (const auto& cp : vRPCConvertParams) {
|
||||
members.emplace(cp.methodName, cp.paramIdx);
|
||||
membersByName.emplace(cp.methodName, cp.paramName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1737,32 +1737,31 @@ void RegisterMiningRPCCommands(CRPCTable &t)
|
|||
// clang-format off
|
||||
|
||||
static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) argNames
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ "mining", "getnetworkhashps", &getnetworkhashps, {"nblocks","height"} },
|
||||
{ "mining", "getmininginfo", &getmininginfo, {} },
|
||||
{ "mining", "prioritisetransaction", &prioritisetransaction, {"txid","dummy","fee_delta"} },
|
||||
{ "mining", "getblocktemplate", &getblocktemplate, {"template_request"} },
|
||||
{ "generating", "combineblocksigs", &combineblocksigs, {"blockhex","signatures","witnessScript"} },
|
||||
{ "mining", "submitheader", &submitheader, {"hexdata"} },
|
||||
{ "generating", "getnewblockhex", &getnewblockhex, {"min_tx_age", "proposed_parameters", "commit_data"} },
|
||||
{ "generating", "getcompactsketch", &getcompactsketch, {"block_hex"} },
|
||||
{ "generating", "consumecompactsketch", &consumecompactsketch, {"sketch"} },
|
||||
{ "generating", "consumegetblocktxn", &consumegetblocktxn, {"full_block", "block_tx_req"} },
|
||||
{ "generating", "finalizecompactblock", &finalizecompactblock, {"compact_hex","block_transactions","found_transactions"} },
|
||||
{ "mining", "testproposedblock", &testproposedblock, {"blockhex", "acceptnonstd"} },
|
||||
{ // category actor (function)
|
||||
// --------------------- ------------------------
|
||||
{ "mining", &getnetworkhashps, },
|
||||
{ "mining", &getmininginfo, },
|
||||
{ "mining", &prioritisetransaction, },
|
||||
{ "mining", &getblocktemplate, },
|
||||
{ "generating", &combineblocksigs, },
|
||||
{ "mining", &submitheader, },
|
||||
{ "generating", &getnewblockhex, },
|
||||
{ "generating", &getcompactsketch, },
|
||||
{ "generating", &consumecompactsketch, },
|
||||
{ "generating", &consumegetblocktxn, },
|
||||
{ "generating", &finalizecompactblock, },
|
||||
{ "mining", &testproposedblock, },
|
||||
|
||||
{ "mining", &submitblock, },
|
||||
|
||||
{ "mining", "submitblock", &submitblock, {"hexdata","dummy"} },
|
||||
{ "generating", &generatetoaddress, },
|
||||
{ "generating", &generatetodescriptor, },
|
||||
{ "generating", &generateblock, },
|
||||
|
||||
{ "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },
|
||||
{ "generating", "generatetodescriptor", &generatetodescriptor, {"num_blocks","descriptor","maxtries"} },
|
||||
{ "generating", "generateblock", &generateblock, {"output","transactions"} },
|
||||
{ "util", &estimatesmartfee, },
|
||||
|
||||
{ "util", "estimatesmartfee", &estimatesmartfee, {"conf_target", "estimate_mode"} },
|
||||
|
||||
{ "hidden", "estimaterawfee", &estimaterawfee, {"conf_target", "threshold"} },
|
||||
{ "hidden", "generate", &generate, {} },
|
||||
{ "hidden", &estimaterawfee, },
|
||||
{ "hidden", &generate, },
|
||||
};
|
||||
// clang-format on
|
||||
for (const auto& c : commands) {
|
||||
|
|
|
|||
|
|
@ -976,29 +976,29 @@ void RegisterMiscRPCCommands(CRPCTable &t)
|
|||
// clang-format off
|
||||
|
||||
static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) argNames
|
||||
{ // category actor (function)
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ "control", "getmemoryinfo", &getmemoryinfo, {"mode"} },
|
||||
{ "control", "logging", &logging, {"include", "exclude"}},
|
||||
{ "util", "validateaddress", &validateaddress, {"address"} },
|
||||
{ "util", "createmultisig", &createmultisig, {"nrequired","keys","address_type"} },
|
||||
{ "util", "deriveaddresses", &deriveaddresses, {"descriptor", "range"} },
|
||||
{ "util", "getdescriptorinfo", &getdescriptorinfo, {"descriptor"} },
|
||||
{ "util", "verifymessage", &verifymessage, {"address","signature","message"} },
|
||||
{ "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} },
|
||||
{ "util", "getindexinfo", &getindexinfo, {"index_name"} },
|
||||
{ "control", &getmemoryinfo, },
|
||||
{ "control", &logging, },
|
||||
{ "util", &validateaddress, },
|
||||
{ "util", &createmultisig, },
|
||||
{ "util", &deriveaddresses, },
|
||||
{ "util", &getdescriptorinfo, },
|
||||
{ "util", &verifymessage, },
|
||||
{ "util", &signmessagewithprivkey, },
|
||||
{ "util", &getindexinfo, },
|
||||
// ELEMENTS:
|
||||
{ "util", "getpakinfo", &getpakinfo, {}},
|
||||
{ "util", "tweakfedpegscript", &tweakfedpegscript, {"claim_script", "fedpegscript"} },
|
||||
{ "util", "createblindedaddress", &createblindedaddress, {"address", "blinding_key"}},
|
||||
{ "util", "dumpassetlabels", &dumpassetlabels, {}},
|
||||
{ "hidden", "calcfastmerkleroot", &calcfastmerkleroot, {"leaves"} },
|
||||
{ "util", &getpakinfo, },
|
||||
{ "util", &tweakfedpegscript, },
|
||||
{ "util", &createblindedaddress, },
|
||||
{ "util", &dumpassetlabels, },
|
||||
{ "hidden", &calcfastmerkleroot, },
|
||||
|
||||
/* Not shown in help */
|
||||
{ "hidden", "setmocktime", &setmocktime, {"timestamp"}},
|
||||
{ "hidden", "mockscheduler", &mockscheduler, {"delta_time"}},
|
||||
{ "hidden", "echo", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
|
||||
{ "hidden", "echojson", &echojson, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
|
||||
{ "hidden", &setmocktime, },
|
||||
{ "hidden", &mockscheduler, },
|
||||
{ "hidden", &echo, },
|
||||
{ "hidden", &echojson, },
|
||||
};
|
||||
// clang-format on
|
||||
for (const auto& c : commands) {
|
||||
|
|
|
|||
|
|
@ -941,24 +941,24 @@ void RegisterNetRPCCommands(CRPCTable &t)
|
|||
{
|
||||
// clang-format off
|
||||
static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) argNames
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ "network", "getconnectioncount", &getconnectioncount, {} },
|
||||
{ "network", "ping", &ping, {} },
|
||||
{ "network", "getpeerinfo", &getpeerinfo, {} },
|
||||
{ "network", "addnode", &addnode, {"node","command"} },
|
||||
{ "network", "disconnectnode", &disconnectnode, {"address", "nodeid"} },
|
||||
{ "network", "getaddednodeinfo", &getaddednodeinfo, {"node"} },
|
||||
{ "network", "getnettotals", &getnettotals, {} },
|
||||
{ "network", "getnetworkinfo", &getnetworkinfo, {} },
|
||||
{ "network", "setban", &setban, {"subnet", "command", "bantime", "absolute"} },
|
||||
{ "network", "listbanned", &listbanned, {} },
|
||||
{ "network", "clearbanned", &clearbanned, {} },
|
||||
{ "network", "setnetworkactive", &setnetworkactive, {"state"} },
|
||||
{ "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
|
||||
{ // category actor
|
||||
// --------------------- -----------------------
|
||||
{ "network", &getconnectioncount, },
|
||||
{ "network", &ping, },
|
||||
{ "network", &getpeerinfo, },
|
||||
{ "network", &addnode, },
|
||||
{ "network", &disconnectnode, },
|
||||
{ "network", &getaddednodeinfo, },
|
||||
{ "network", &getnettotals, },
|
||||
{ "network", &getnetworkinfo, },
|
||||
{ "network", &setban, },
|
||||
{ "network", &listbanned, },
|
||||
{ "network", &clearbanned, },
|
||||
{ "network", &setnetworkactive, },
|
||||
{ "network", &getnodeaddresses, },
|
||||
|
||||
{ "hidden", "addconnection", &addconnection, {"address", "connection_type"} },
|
||||
{ "hidden", "addpeeraddress", &addpeeraddress, {"address", "port"} },
|
||||
{ "hidden", &addconnection, },
|
||||
{ "hidden", &addpeeraddress, },
|
||||
};
|
||||
// clang-format on
|
||||
for (const auto& c : commands) {
|
||||
|
|
|
|||
|
|
@ -2723,31 +2723,31 @@ void RegisterRawTransactionRPCCommands(CRPCTable &t)
|
|||
{
|
||||
// clang-format off
|
||||
static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) argNames
|
||||
{ // category actor (function) argNames
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose","blockhash"} },
|
||||
{ "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime","replaceable","output_assets"} },
|
||||
{ "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring","iswitness"} },
|
||||
{ "rawtransactions", "decodescript", &decodescript, {"hexstring"} },
|
||||
{ "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","maxfeerate"} },
|
||||
{ "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} },
|
||||
{ "rawtransactions", "signrawtransactionwithkey", &signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} },
|
||||
{ "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","maxfeerate"} },
|
||||
{ "rawtransactions", "decodepsbt", &decodepsbt, {"psbt"} },
|
||||
{ "rawtransactions", "combinepsbt", &combinepsbt, {"txs"} },
|
||||
{ "rawtransactions", "blindpsbt", &blindpsbt, {"psbt","ignoreblindfail"} },
|
||||
{ "rawtransactions", "finalizepsbt", &finalizepsbt, {"psbt","extract"} },
|
||||
{ "rawtransactions", "createpsbt", &createpsbt, {"inputs","outputs","locktime","replaceable","output_assets"} },
|
||||
{ "rawtransactions", "converttopsbt", &converttopsbt, {"hexstring","permitsigdata","iswitness"} },
|
||||
{ "rawtransactions", "utxoupdatepsbt", &utxoupdatepsbt, {"psbt","descriptors"} },
|
||||
{ "rawtransactions", "joinpsbts", &joinpsbts, {"txs"} },
|
||||
{ "rawtransactions", "analyzepsbt", &analyzepsbt, {"psbt"} },
|
||||
{ "rawtransactions", &getrawtransaction, },
|
||||
{ "rawtransactions", &createrawtransaction, },
|
||||
{ "rawtransactions", &decoderawtransaction, },
|
||||
{ "rawtransactions", &decodescript, },
|
||||
{ "rawtransactions", &sendrawtransaction, },
|
||||
{ "rawtransactions", &combinerawtransaction, },
|
||||
{ "rawtransactions", &signrawtransactionwithkey, },
|
||||
{ "rawtransactions", &testmempoolaccept, },
|
||||
{ "rawtransactions", &decodepsbt, },
|
||||
{ "rawtransactions", &combinepsbt, },
|
||||
{ "rawtransactions", &blindpsbt, },
|
||||
{ "rawtransactions", &finalizepsbt, },
|
||||
{ "rawtransactions", &createpsbt, },
|
||||
{ "rawtransactions", &converttopsbt, },
|
||||
{ "rawtransactions", &utxoupdatepsbt, },
|
||||
{ "rawtransactions", &joinpsbts, },
|
||||
{ "rawtransactions", &analyzepsbt, },
|
||||
|
||||
{ "blockchain", "gettxoutproof", &gettxoutproof, {"txids","blockhash"} },
|
||||
{ "blockchain", "verifytxoutproof", &verifytxoutproof, {"proof"} },
|
||||
{ "rawtransactions", "rawissueasset", &rawissueasset, {"transaction","issuances"}},
|
||||
{ "rawtransactions", "rawreissueasset", &rawreissueasset, {"transaction","reissuances"}},
|
||||
{ "rawtransactions", "rawblindrawtransaction", &rawblindrawtransaction, {"hexstring","inputamountblinders","inputamounts","inputassets","inputassetblinders","totalblinder","ignoreblindfail"} },
|
||||
{ "blockchain", &gettxoutproof, },
|
||||
{ "blockchain", &verifytxoutproof, },
|
||||
{ "rawtransactions", &rawissueasset, },
|
||||
{ "rawtransactions", &rawreissueasset, },
|
||||
{ "rawtransactions", &rawblindrawtransaction, },
|
||||
};
|
||||
// clang-format on
|
||||
for (const auto& c : commands) {
|
||||
|
|
|
|||
|
|
@ -144,8 +144,13 @@ static RPCHelpMan help()
|
|||
[&](const RPCHelpMan& self, const JSONRPCRequest& jsonRequest) -> UniValue
|
||||
{
|
||||
std::string strCommand;
|
||||
if (jsonRequest.params.size() > 0)
|
||||
if (jsonRequest.params.size() > 0) {
|
||||
strCommand = jsonRequest.params[0].get_str();
|
||||
}
|
||||
if (strCommand == "dump_all_command_conversions") {
|
||||
// Used for testing only, undocumented
|
||||
return tableRPC.dumpArgMap();
|
||||
}
|
||||
|
||||
return tableRPC.help(strCommand, jsonRequest);
|
||||
},
|
||||
|
|
@ -244,13 +249,13 @@ static RPCHelpMan getrpcinfo()
|
|||
|
||||
// clang-format off
|
||||
static const CRPCCommand vRPCCommands[] =
|
||||
{ // category name actor (function) argNames
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ // category actor (function)
|
||||
// --------------------- -----------------------
|
||||
/* Overall control/query calls */
|
||||
{ "control", "getrpcinfo", &getrpcinfo, {} },
|
||||
{ "control", "help", &help, {"command"} },
|
||||
{ "control", "stop", &stop, {"wait"} },
|
||||
{ "control", "uptime", &uptime, {} },
|
||||
{ "control", &getrpcinfo, },
|
||||
{ "control", &help, },
|
||||
{ "control", &stop, },
|
||||
{ "control", &uptime, },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
|
@ -479,6 +484,18 @@ std::vector<std::string> CRPCTable::listCommands() const
|
|||
return commandList;
|
||||
}
|
||||
|
||||
UniValue CRPCTable::dumpArgMap() const
|
||||
{
|
||||
UniValue ret{UniValue::VARR};
|
||||
for (const auto& cmd : mapCommands) {
|
||||
for (const auto& c : cmd.second) {
|
||||
const auto help = RpcMethodFnType(c->unique_id)();
|
||||
help.AppendArgMap(ret);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
|
||||
{
|
||||
if (!timerInterface)
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ public:
|
|||
}
|
||||
|
||||
//! Simplified constructor taking plain RpcMethodFnType function pointer.
|
||||
CRPCCommand(std::string category, std::string name_in, RpcMethodFnType fn, std::vector<std::string> args_in)
|
||||
CRPCCommand(std::string category, RpcMethodFnType fn)
|
||||
: CRPCCommand(
|
||||
category,
|
||||
fn().m_name,
|
||||
|
|
@ -111,8 +111,6 @@ public:
|
|||
fn().GetArgNames(),
|
||||
intptr_t(fn))
|
||||
{
|
||||
CHECK_NONFATAL(fn().m_name == name_in);
|
||||
CHECK_NONFATAL(fn().GetArgNames() == args_in);
|
||||
}
|
||||
|
||||
std::string category;
|
||||
|
|
@ -147,6 +145,10 @@ public:
|
|||
*/
|
||||
std::vector<std::string> listCommands() const;
|
||||
|
||||
/**
|
||||
* Return all named arguments that need to be converted by the client from string to another JSON type
|
||||
*/
|
||||
UniValue dumpArgMap() const;
|
||||
|
||||
/**
|
||||
* Appends a CRPCCommand to the dispatch table.
|
||||
|
|
|
|||
|
|
@ -560,6 +560,24 @@ std::string RPCHelpMan::ToString() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
void RPCHelpMan::AppendArgMap(UniValue& arr) const
|
||||
{
|
||||
for (int i{0}; i < int(m_args.size()); ++i) {
|
||||
const auto& arg = m_args.at(i);
|
||||
std::vector<std::string> arg_names;
|
||||
boost::split(arg_names, arg.m_names, boost::is_any_of("|"));
|
||||
for (const auto& arg_name : arg_names) {
|
||||
UniValue map{UniValue::VARR};
|
||||
map.push_back(m_name);
|
||||
map.push_back(i);
|
||||
map.push_back(arg_name);
|
||||
map.push_back(arg.m_type == RPCArg::Type::STR ||
|
||||
arg.m_type == RPCArg::Type::STR_HEX);
|
||||
arr.push_back(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string RPCArg::GetFirstName() const
|
||||
{
|
||||
return m_names.substr(0, m_names.find("|"));
|
||||
|
|
|
|||
|
|
@ -341,6 +341,8 @@ public:
|
|||
RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples, RPCMethodImpl fun);
|
||||
|
||||
std::string ToString() const;
|
||||
/** Append the named args that need to be converted from string to another JSON type */
|
||||
void AppendArgMap(UniValue& arr) const;
|
||||
UniValue HandleRequest(const JSONRPCRequest& request)
|
||||
{
|
||||
Check(request);
|
||||
|
|
|
|||
|
|
@ -7028,93 +7028,93 @@ Span<const CRPCCommand> GetWalletRPCCommands()
|
|||
{
|
||||
// clang-format off
|
||||
static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) argNames
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness","solving_data"} },
|
||||
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
|
||||
{ "wallet", "abortrescan", &abortrescan, {} },
|
||||
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label","address_type"} },
|
||||
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
|
||||
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
|
||||
{ "wallet", "psbtbumpfee", &psbtbumpfee, {"txid", "options"} },
|
||||
{ "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase", "avoid_reuse", "descriptors", "load_on_startup"} },
|
||||
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
|
||||
{ "wallet", "dumpwallet", &dumpwallet, {"filename"} },
|
||||
{ "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },
|
||||
{ "wallet", "getaddressesbylabel", &getaddressesbylabel, {"label"} },
|
||||
{ "wallet", "getaddressinfo", &getaddressinfo, {"address"} },
|
||||
{ "wallet", "getbalance", &getbalance, {"dummy","minconf","include_watchonly","avoid_reuse","assetlabel"} },
|
||||
{ "wallet", "getnewaddress", &getnewaddress, {"label","address_type"} },
|
||||
{ "wallet", "getrawchangeaddress", &getrawchangeaddress, {"address_type"} },
|
||||
{ "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf","assetlabel"} },
|
||||
{ "wallet", "getreceivedbylabel", &getreceivedbylabel, {"label","minconf","assetlabel"} },
|
||||
{ "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly","verbose","assetlabel"} },
|
||||
{ "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} },
|
||||
{ "wallet", "getbalances", &getbalances, {} },
|
||||
{ "wallet", "getwalletinfo", &getwalletinfo, {} },
|
||||
{ "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} },
|
||||
{ "wallet", "importdescriptors", &importdescriptors, {"requests"} },
|
||||
{ "wallet", "importmulti", &importmulti, {"requests","options"} },
|
||||
{ "wallet", "importprivkey", &importprivkey, {"privkey","label","rescan"} },
|
||||
{ "wallet", "importprunedfunds", &importprunedfunds, {"rawtransaction","txoutproof"} },
|
||||
{ "wallet", "importpubkey", &importpubkey, {"pubkey","label","rescan"} },
|
||||
{ "wallet", "importwallet", &importwallet, {"filename"} },
|
||||
{ "wallet", "keypoolrefill", &keypoolrefill, {"newsize"} },
|
||||
{ "wallet", "listaddressgroupings", &listaddressgroupings, {} },
|
||||
{ "wallet", "listdescriptors", &listdescriptors, {} },
|
||||
{ "wallet", "listlabels", &listlabels, {"purpose"} },
|
||||
{ "wallet", "listlockunspent", &listlockunspent, {} },
|
||||
{ "wallet", "listreceivedbyaddress", &listreceivedbyaddress, {"minconf","include_empty","include_watchonly","address_filter","assetlabel"} },
|
||||
{ "wallet", "listreceivedbylabel", &listreceivedbylabel, {"minconf","include_empty","include_watchonly"} },
|
||||
{ "wallet", "listsinceblock", &listsinceblock, {"blockhash","target_confirmations","include_watchonly","include_removed"} },
|
||||
{ "wallet", "listtransactions", &listtransactions, {"label|dummy","count","skip","include_watchonly"} },
|
||||
{ "wallet", "listunspent", &listunspent, {"minconf","maxconf","addresses","include_unsafe","query_options"} },
|
||||
{ "wallet", "listwalletdir", &listwalletdir, {} },
|
||||
{ "wallet", "listwallets", &listwallets, {} },
|
||||
{ "wallet", "loadwallet", &loadwallet, {"filename", "load_on_startup"} },
|
||||
{ "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} },
|
||||
{ "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
|
||||
{ "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
|
||||
{ "wallet", "send", &send, {"outputs","conf_target","estimate_mode","fee_rate","options"} },
|
||||
{ "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode","output_assets","ignoreblindfail","fee_rate","verbose"} },
|
||||
{ "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse", "assetlabel", "ignoreblindfail", "fee_rate", "verbose"} },
|
||||
{ "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} },
|
||||
{ "wallet", "setlabel", &setlabel, {"address","label"} },
|
||||
{ "wallet", "settxfee", &settxfee, {"amount"} },
|
||||
{ "wallet", "setwalletflag", &setwalletflag, {"flag","value"} },
|
||||
{ "wallet", "signmessage", &signmessage, {"address","message"} },
|
||||
{ "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
|
||||
{ "wallet", "unloadwallet", &unloadwallet, {"wallet_name", "load_on_startup"} },
|
||||
{ "wallet", "upgradewallet", &upgradewallet, {"version"} },
|
||||
{ "wallet", "walletcreatefundedpsbt", &walletcreatefundedpsbt, {"inputs","outputs","locktime","options","bip32derivs","solving_data"} },
|
||||
{ "wallet", "walletlock", &walletlock, {} },
|
||||
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
|
||||
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
|
||||
{ "wallet", "walletprocesspsbt", &walletprocesspsbt, {"psbt","sign","sighashtype","bip32derivs"} },
|
||||
{ "wallet", "walletfillpsbtdata", &walletfillpsbtdata, {"psbt","bip32derivs"} },
|
||||
{ "wallet", "walletsignpsbt", &walletsignpsbt, {"psbt","sighashtype","imbalance_ok"} },
|
||||
{ // category actor (function) argNames
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ "rawtransactions", &fundrawtransaction, },
|
||||
{ "wallet", &abandontransaction, },
|
||||
{ "wallet", &abortrescan, },
|
||||
{ "wallet", &addmultisigaddress, },
|
||||
{ "wallet", &backupwallet, },
|
||||
{ "wallet", &bumpfee, },
|
||||
{ "wallet", &psbtbumpfee, },
|
||||
{ "wallet", &createwallet, },
|
||||
{ "wallet", &dumpprivkey, },
|
||||
{ "wallet", &dumpwallet, },
|
||||
{ "wallet", &encryptwallet, },
|
||||
{ "wallet", &getaddressesbylabel, },
|
||||
{ "wallet", &getaddressinfo, },
|
||||
{ "wallet", &getbalance, },
|
||||
{ "wallet", &getnewaddress, },
|
||||
{ "wallet", &getrawchangeaddress, },
|
||||
{ "wallet", &getreceivedbyaddress, },
|
||||
{ "wallet", &getreceivedbylabel, },
|
||||
{ "wallet", &gettransaction, },
|
||||
{ "wallet", &getunconfirmedbalance, },
|
||||
{ "wallet", &getbalances, },
|
||||
{ "wallet", &getwalletinfo, },
|
||||
{ "wallet", &importaddress, },
|
||||
{ "wallet", &importdescriptors, },
|
||||
{ "wallet", &importmulti, },
|
||||
{ "wallet", &importprivkey, },
|
||||
{ "wallet", &importprunedfunds, },
|
||||
{ "wallet", &importpubkey, },
|
||||
{ "wallet", &importwallet, },
|
||||
{ "wallet", &keypoolrefill, },
|
||||
{ "wallet", &listaddressgroupings, },
|
||||
{ "wallet", &listdescriptors, },
|
||||
{ "wallet", &listlabels, },
|
||||
{ "wallet", &listlockunspent, },
|
||||
{ "wallet", &listreceivedbyaddress, },
|
||||
{ "wallet", &listreceivedbylabel, },
|
||||
{ "wallet", &listsinceblock, },
|
||||
{ "wallet", &listtransactions, },
|
||||
{ "wallet", &listunspent, },
|
||||
{ "wallet", &listwalletdir, },
|
||||
{ "wallet", &listwallets, },
|
||||
{ "wallet", &loadwallet, },
|
||||
{ "wallet", &lockunspent, },
|
||||
{ "wallet", &removeprunedfunds, },
|
||||
{ "wallet", &rescanblockchain, },
|
||||
{ "wallet", &send, },
|
||||
{ "wallet", &sendmany, },
|
||||
{ "wallet", &sendtoaddress, },
|
||||
{ "wallet", &sethdseed, },
|
||||
{ "wallet", &setlabel, },
|
||||
{ "wallet", &settxfee, },
|
||||
{ "wallet", &setwalletflag, },
|
||||
{ "wallet", &signmessage, },
|
||||
{ "wallet", &signrawtransactionwithwallet, },
|
||||
{ "wallet", &unloadwallet, },
|
||||
{ "wallet", &upgradewallet, },
|
||||
{ "wallet", &walletcreatefundedpsbt, },
|
||||
{ "wallet", &walletlock, },
|
||||
{ "wallet", &walletpassphrase, },
|
||||
{ "wallet", &walletpassphrasechange, },
|
||||
{ "wallet", &walletprocesspsbt, },
|
||||
{ "wallet", &walletfillpsbtdata, },
|
||||
{ "wallet", &walletsignpsbt, },
|
||||
// ELEMENTS:
|
||||
{ "wallet", "getpeginaddress", &getpeginaddress, {} },
|
||||
{ "wallet", "claimpegin", &claimpegin, {"bitcoin_tx", "txoutproof", "claim_script"} },
|
||||
{ "wallet", "createrawpegin", &createrawpegin, {"bitcoin_tx", "txoutproof", "claim_script"} },
|
||||
{ "wallet", "blindrawtransaction", &blindrawtransaction, {"hexstring", "ignoreblindfail", "asset_commitments", "blind_issuances", "totalblinder"} },
|
||||
{ "wallet", "unblindrawtransaction", &unblindrawtransaction, {"hex"} },
|
||||
{ "wallet", "sendtomainchain", &sendtomainchain, {"address", "amount", "subtractfeefromamount", "verbose"} },
|
||||
{ "wallet", "initpegoutwallet", &initpegoutwallet, {"bitcoin_descriptor", "bip32_counter", "liquid_pak"} },
|
||||
{ "wallet", "getwalletpakinfo", &getwalletpakinfo, {} },
|
||||
{ "wallet", "importblindingkey", &importblindingkey, {"address", "hexkey"}},
|
||||
{ "wallet", "importmasterblindingkey", &importmasterblindingkey, {"hexkey"}},
|
||||
{ "wallet", "importissuanceblindingkey", &importissuanceblindingkey, {"txid", "vin", "blindingkey"}},
|
||||
{ "wallet", "dumpblindingkey", &dumpblindingkey, {"address"}},
|
||||
{ "wallet", "dumpmasterblindingkey", &dumpmasterblindingkey, {}},
|
||||
{ "wallet", "dumpissuanceblindingkey", &dumpissuanceblindingkey, {"txid", "vin"}},
|
||||
{ "wallet", "signblock", &signblock, {"blockhex", "witnessScript"}},
|
||||
{ "wallet", "listissuances", &listissuances, {"asset"}},
|
||||
{ "wallet", "issueasset", &issueasset, {"assetamount", "tokenamount", "blind"}},
|
||||
{ "wallet", "reissueasset", &reissueasset, {"asset", "assetamount"}},
|
||||
{ "wallet", "destroyamount", &destroyamount, {"asset", "amount", "comment", "verbose"} },
|
||||
{ "hidden", "generatepegoutproof", &generatepegoutproof, {"sumkey", "btcpubkey", "onlinepubkey"} },
|
||||
{ "hidden", "getpegoutkeys", &getpegoutkeys, {"btcprivkey", "offlinepubkey"} },
|
||||
{ "wallet", &getpeginaddress, },
|
||||
{ "wallet", &claimpegin, },
|
||||
{ "wallet", &createrawpegin, },
|
||||
{ "wallet", &blindrawtransaction, },
|
||||
{ "wallet", &unblindrawtransaction, },
|
||||
{ "wallet", &sendtomainchain, },
|
||||
{ "wallet", &initpegoutwallet, },
|
||||
{ "wallet", &getwalletpakinfo, },
|
||||
{ "wallet", &importblindingkey, },
|
||||
{ "wallet", &importmasterblindingkey, },
|
||||
{ "wallet", &importissuanceblindingkey, },
|
||||
{ "wallet", &dumpblindingkey, },
|
||||
{ "wallet", &dumpmasterblindingkey, },
|
||||
{ "wallet", &dumpissuanceblindingkey, },
|
||||
{ "wallet", &signblock, },
|
||||
{ "wallet", &listissuances, },
|
||||
{ "wallet", &issueasset, },
|
||||
{ "wallet", &reissueasset, },
|
||||
{ "wallet", &destroyamount, },
|
||||
{ "hidden", &generatepegoutproof, },
|
||||
{ "hidden", &getpegoutkeys, },
|
||||
};
|
||||
// clang-format on
|
||||
return MakeSpan(commands);
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ static RPCHelpMan getzmqnotifications()
|
|||
}
|
||||
|
||||
const CRPCCommand commands[] =
|
||||
{ // category name actor (function) argNames
|
||||
// ----------------- ------------------------ ----------------------- ----------
|
||||
{ "zmq", "getzmqnotifications", &getzmqnotifications, {} },
|
||||
{ // category actor (function)
|
||||
// ----------------- -----------------------
|
||||
{ "zmq", &getzmqnotifications, },
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
|
|
|||
|
|
@ -7,7 +7,39 @@
|
|||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_raises_rpc_error
|
||||
|
||||
from collections import defaultdict
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
def parse_string(s):
|
||||
assert s[0] == '"'
|
||||
assert s[-1] == '"'
|
||||
return s[1:-1]
|
||||
|
||||
|
||||
def process_mapping(fname):
|
||||
"""Find and parse conversion table in implementation file `fname`."""
|
||||
cmds = []
|
||||
in_rpcs = False
|
||||
with open(fname, "r", encoding="utf8") as f:
|
||||
for line in f:
|
||||
line = line.rstrip()
|
||||
if not in_rpcs:
|
||||
if line == 'static const CRPCConvertParam vRPCConvertParams[] =':
|
||||
in_rpcs = True
|
||||
else:
|
||||
if line.startswith('};'):
|
||||
in_rpcs = False
|
||||
elif '{' in line and '"' in line:
|
||||
m = re.search(r'{ *("[^"]*"), *([0-9]+) *, *("[^"]*") *},', line)
|
||||
assert m, 'No match to table expression: %s' % line
|
||||
name = parse_string(m.group(1))
|
||||
idx = int(m.group(2))
|
||||
argname = parse_string(m.group(3))
|
||||
cmds.append((name, idx, argname))
|
||||
assert not in_rpcs and cmds
|
||||
return cmds
|
||||
|
||||
|
||||
class HelpRpcTest(BitcoinTestFramework):
|
||||
|
|
@ -16,11 +48,43 @@ class HelpRpcTest(BitcoinTestFramework):
|
|||
self.supports_cli = False
|
||||
|
||||
def run_test(self):
|
||||
self.test_client_conversion_table()
|
||||
self.test_categories()
|
||||
self.dump_help()
|
||||
if self.is_wallet_compiled():
|
||||
self.wallet_help()
|
||||
|
||||
def test_client_conversion_table(self):
|
||||
file_conversion_table = os.path.join(self.config["environment"]["SRCDIR"], 'src', 'rpc', 'client.cpp')
|
||||
mapping_client = process_mapping(file_conversion_table)
|
||||
# Ignore echojson in client table
|
||||
mapping_client = [m for m in mapping_client if m[0] != 'echojson']
|
||||
|
||||
mapping_server = self.nodes[0].help("dump_all_command_conversions")
|
||||
# Filter all RPCs whether they need conversion
|
||||
mapping_server_conversion = [tuple(m[:3]) for m in mapping_server if not m[3]]
|
||||
|
||||
# Only check if all RPC methods have been compiled (i.e. wallet is enabled)
|
||||
if self.is_wallet_compiled() and sorted(mapping_client) != sorted(mapping_server_conversion):
|
||||
raise AssertionError("RPC client conversion table ({}) and RPC server named arguments mismatch!\n{}".format(
|
||||
file_conversion_table,
|
||||
set(mapping_client).symmetric_difference(mapping_server_conversion),
|
||||
))
|
||||
|
||||
# Check for conversion difference by argument name.
|
||||
# It is preferable for API consistency that arguments with the same name
|
||||
# have the same conversion, so bin by argument name.
|
||||
all_methods_by_argname = defaultdict(list)
|
||||
converts_by_argname = defaultdict(list)
|
||||
for m in mapping_server:
|
||||
all_methods_by_argname[m[2]].append(m[0])
|
||||
converts_by_argname[m[2]].append(m[3])
|
||||
|
||||
for argname, convert in converts_by_argname.items():
|
||||
if all(convert) != any(convert):
|
||||
# Only allow dummy to fail consistency check
|
||||
assert argname == 'dummy', ('WARNING: conversion mismatch for argument named %s (%s)' % (argname, list(zip(all_methods_by_argname[argname], converts_by_argname[argname]))))
|
||||
|
||||
def test_categories(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,162 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2017-2019 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Check RPC argument consistency."""
|
||||
|
||||
from collections import defaultdict
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
# Source files (relative to root) to scan for dispatch tables
|
||||
SOURCES = [
|
||||
"src/rpc/server.cpp",
|
||||
"src/rpc/blockchain.cpp",
|
||||
"src/rpc/mining.cpp",
|
||||
"src/rpc/misc.cpp",
|
||||
"src/rpc/net.cpp",
|
||||
"src/rpc/rawtransaction.cpp",
|
||||
"src/wallet/rpcwallet.cpp",
|
||||
]
|
||||
# Source file (relative to root) containing conversion mapping
|
||||
SOURCE_CLIENT = 'src/rpc/client.cpp'
|
||||
# Argument names that should be ignored in consistency checks
|
||||
IGNORE_DUMMY_ARGS = {'dummy', 'arg0', 'arg1', 'arg2', 'arg3', 'arg4', 'arg5', 'arg6', 'arg7', 'arg8', 'arg9'}
|
||||
|
||||
class RPCCommand:
|
||||
def __init__(self, name, args):
|
||||
self.name = name
|
||||
self.args = args
|
||||
|
||||
class RPCArgument:
|
||||
def __init__(self, names, idx):
|
||||
self.names = names
|
||||
self.idx = idx
|
||||
self.convert = False
|
||||
|
||||
def parse_string(s):
|
||||
assert s[0] == '"'
|
||||
assert s[-1] == '"'
|
||||
return s[1:-1]
|
||||
|
||||
def process_commands(fname):
|
||||
"""Find and parse dispatch table in implementation file `fname`."""
|
||||
cmds = []
|
||||
in_rpcs = False
|
||||
with open(fname, "r", encoding="utf8") as f:
|
||||
for line in f:
|
||||
line = line.rstrip()
|
||||
if not in_rpcs:
|
||||
if re.match(r"static const CRPCCommand .*\[\] =", line):
|
||||
in_rpcs = True
|
||||
else:
|
||||
if line.startswith('};'):
|
||||
in_rpcs = False
|
||||
elif '{' in line and '"' in line:
|
||||
m = re.search(r'{ *("[^"]*"), *("[^"]*"), *&([^,]*), *{([^}]*)} *},', line)
|
||||
assert m, 'No match to table expression: %s' % line
|
||||
name = parse_string(m.group(2))
|
||||
args_str = m.group(4).strip()
|
||||
if args_str:
|
||||
args = [RPCArgument(parse_string(x.strip()).split('|'), idx) for idx, x in enumerate(args_str.split(','))]
|
||||
else:
|
||||
args = []
|
||||
cmds.append(RPCCommand(name, args))
|
||||
assert not in_rpcs and cmds, "Something went wrong with parsing the C++ file: update the regexps"
|
||||
return cmds
|
||||
|
||||
def process_mapping(fname):
|
||||
"""Find and parse conversion table in implementation file `fname`."""
|
||||
cmds = []
|
||||
in_rpcs = False
|
||||
with open(fname, "r", encoding="utf8") as f:
|
||||
for line in f:
|
||||
line = line.rstrip()
|
||||
if not in_rpcs:
|
||||
if line == 'static const CRPCConvertParam vRPCConvertParams[] =':
|
||||
in_rpcs = True
|
||||
else:
|
||||
if line.startswith('};'):
|
||||
in_rpcs = False
|
||||
elif '{' in line and '"' in line:
|
||||
m = re.search(r'{ *("[^"]*"), *([0-9]+) *, *("[^"]*") *},', line)
|
||||
assert m, 'No match to table expression: %s' % line
|
||||
name = parse_string(m.group(1))
|
||||
idx = int(m.group(2))
|
||||
argname = parse_string(m.group(3))
|
||||
cmds.append((name, idx, argname))
|
||||
assert not in_rpcs and cmds
|
||||
return cmds
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print('Usage: {} ROOT-DIR'.format(sys.argv[0]), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
root = sys.argv[1]
|
||||
|
||||
# Get all commands from dispatch tables
|
||||
cmds = []
|
||||
for fname in SOURCES:
|
||||
cmds += process_commands(os.path.join(root, fname))
|
||||
|
||||
cmds_by_name = {}
|
||||
for cmd in cmds:
|
||||
cmds_by_name[cmd.name] = cmd
|
||||
|
||||
# Get current convert mapping for client
|
||||
client = SOURCE_CLIENT
|
||||
mapping = set(process_mapping(os.path.join(root, client)))
|
||||
|
||||
print('* Checking consistency between dispatch tables and vRPCConvertParams')
|
||||
|
||||
# Check mapping consistency
|
||||
errors = 0
|
||||
for (cmdname, argidx, argname) in mapping:
|
||||
try:
|
||||
rargnames = cmds_by_name[cmdname].args[argidx].names
|
||||
except IndexError:
|
||||
print('ERROR: %s argument %i (named %s in vRPCConvertParams) is not defined in dispatch table' % (cmdname, argidx, argname))
|
||||
errors += 1
|
||||
continue
|
||||
if argname not in rargnames:
|
||||
print('ERROR: %s argument %i is named %s in vRPCConvertParams but %s in dispatch table' % (cmdname, argidx, argname, rargnames), file=sys.stderr)
|
||||
errors += 1
|
||||
|
||||
# Check for conflicts in vRPCConvertParams conversion
|
||||
# All aliases for an argument must either be present in the
|
||||
# conversion table, or not. Anything in between means an oversight
|
||||
# and some aliases won't work.
|
||||
for cmd in cmds:
|
||||
for arg in cmd.args:
|
||||
convert = [((cmd.name, arg.idx, argname) in mapping) for argname in arg.names]
|
||||
if any(convert) != all(convert):
|
||||
print('ERROR: %s argument %s has conflicts in vRPCConvertParams conversion specifier %s' % (cmd.name, arg.names, convert))
|
||||
errors += 1
|
||||
arg.convert = all(convert)
|
||||
|
||||
# Check for conversion difference by argument name.
|
||||
# It is preferable for API consistency that arguments with the same name
|
||||
# have the same conversion, so bin by argument name.
|
||||
all_methods_by_argname = defaultdict(list)
|
||||
converts_by_argname = defaultdict(list)
|
||||
for cmd in cmds:
|
||||
for arg in cmd.args:
|
||||
for argname in arg.names:
|
||||
all_methods_by_argname[argname].append(cmd.name)
|
||||
converts_by_argname[argname].append(arg.convert)
|
||||
|
||||
for argname, convert in converts_by_argname.items():
|
||||
if all(convert) != any(convert):
|
||||
if argname in IGNORE_DUMMY_ARGS:
|
||||
# these are testing or dummy, don't warn for them
|
||||
continue
|
||||
print('WARNING: conversion mismatch for argument named %s (%s)' %
|
||||
(argname, list(zip(all_methods_by_argname[argname], converts_by_argname[argname]))))
|
||||
|
||||
sys.exit(errors > 0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue