From 34f0001ccce45d8676c57c11f72bec31ced51aad Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 22 Aug 2016 09:18:44 -0700 Subject: [PATCH] Implement RPC call z_listoperationids and update z_getoperationstatus to take a list parameter. --- src/rpcclient.cpp | 1 + src/rpcserver.cpp | 1 + src/rpcserver.h | 1 + src/wallet/rpcwallet.cpp | 102 ++++++++++++++++++++++++++++++++------- 4 files changed, 87 insertions(+), 18 deletions(-) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index f3d1a5454..3e007ca58 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -100,6 +100,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getblocksubsidy", 0}, { "z_sendmany", 1}, { "z_sendmany", 2}, + { "z_getoperationstatus", 0}, { "z_importkey", 1 } }; diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 819ff4b23..906ecee9f 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -388,6 +388,7 @@ static const CRPCCommand vRPCCommands[] = { "wallet", "zcsamplejoinsplit", &zc_sample_joinsplit, true }, { "wallet", "z_sendmany", &z_sendmany, true }, { "wallet", "z_getoperationstatus", &z_getoperationstatus, true }, + { "wallet", "z_listoperationids", &z_listoperationids, true }, { "wallet", "z_getnewaddress", &z_getnewaddress, true }, { "wallet", "z_listaddresses", &z_listaddresses, true }, { "wallet", "z_exportkey", &z_exportkey, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 1d9712711..986d12731 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -258,6 +258,7 @@ extern json_spirit::Value z_exportwallet(const json_spirit::Array& params, bool extern json_spirit::Value z_importwallet(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp extern json_spirit::Value z_sendmany(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp extern json_spirit::Value z_getoperationstatus(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp +extern json_spirit::Value z_listoperationids(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp // in rest.cpp diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a2e2e9d11..f1ee45dd1 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2838,36 +2838,53 @@ Value z_getoperationstatus(const Array& params, bool fHelp) if (!EnsureWalletIsAvailable(fHelp)) return Value::null; - if (fHelp || params.size() != 1) + if (fHelp || params.size() > 1) throw runtime_error( - "z_getoperationstatus \"operationid\"\n" + "z_getoperationstatus ([\"operationid\", ... ]) \n" "\nGet operation status and any associated result or error data." + HelpRequiringPassphrase() + "\n" "\nArguments:\n" - "1. \"operationid\" (string, required) The operation id returned by an async operation call.\n" + "1. \"operationid\" (array, optional) A list of operation ids we are interested in.\n" "\nResult:\n" - "\" object\" (string) FIXME: ASYNC operation object \n" - " with some key value pairs.\n" + "\" [object, ...]\" (array) A list of JSON objects\n" ); LOCK2(cs_main, pwalletMain->cs_wallet); - AsyncRPCOperationId id = params[0].get_str(); - + std::set filter; + if (params.size()==1) { + Array ids = params[0].get_array(); + for (Value & v : ids) { + filter.insert(v.get_str()); + } + } + bool useFilter = (filter.size()>0); + + Array ret; std::shared_ptr q = getAsyncRPCQueue(); - std::shared_ptr operation = q->getOperationForId(id); - if (!operation) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "No operation exists for that id."); + std::vector ids = q->getAllOperationIds(); + + for (auto id : ids) { + if (useFilter && !filter.count(id)) + continue; + + std::shared_ptr operation = q->getOperationForId(id); + if (!operation) { + continue; + // It's possible that the operation was removed from the internal queue and map during this loop + // throw JSONRPCError(RPC_INVALID_PARAMETER, "No operation exists for that id."); + } + + Value status = operation->getStatus(); + ret.push_back(status); + + // Remove operation from memory when it has finished and the caller has retrieved the result and reason for finishing. + if (operation->isSuccess() || operation->isFailed() || operation->isCancelled()) { + q->popOperationForId(id); + } } - Value status = operation->getStatus(); - - // Remove operation from memory when it has finished and the caller has retrieved the result and reason for finishing. - if (operation->isSuccess() || operation->isFailed() || operation->isCancelled()) { - q->popOperationForId(id); - } - - return status; + return ret; } Value z_sendmany(const Array& params, bool fHelp) @@ -3007,3 +3024,52 @@ Value z_sendmany(const Array& params, bool fHelp) AsyncRPCOperationId operationId = operation->getId(); return operationId; } + + +Value z_listoperationids(const Array& params, bool fHelp) +{ + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + + if (fHelp || params.size() > 1) + throw runtime_error( + "z_listoperationids\n" + "\nReturns the list of operation ids currently known to the wallet.\n" + "\nArguments:\n" + "1. \"status\" (string, optional) Filter result by the operation's state state e.g. \"success\".\n" + "\nResult:\n" + "[ (json array of string)\n" + " \"operationid\" (string) an operation id belonging to the wallet\n" + " ,...\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("z_listoperationids", "") + + HelpExampleRpc("z_listoperationids", "") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + std::string filter; + bool useFilter = false; + if (params.size()==1) { + filter = params[0].get_str(); + useFilter = true; + } + + Array ret; + std::shared_ptr q = getAsyncRPCQueue(); + std::vector ids = q->getAllOperationIds(); + for (auto id : ids) { + std::shared_ptr operation = q->getOperationForId(id); + if (!operation) { + continue; + } + std::string state = operation->getStateAsString(); + if (useFilter && filter.compare(state)!=0) + continue; + ret.push_back(id); + } + + return ret; +} +