[wallet] Add include_unsafe argument to listunspent RPC

This commit is contained in:
Russell Yanofsky 2017-01-17 10:40:41 -05:00 committed by Alexander Block
parent e1e03f42c4
commit 55ef4d0a9b
3 changed files with 36 additions and 14 deletions

View File

@ -78,16 +78,20 @@ void RPCTypeCheck(const UniValue& params,
break; break;
const UniValue& v = params[i]; const UniValue& v = params[i];
if (!((v.type() == t) || (fAllowNull && (v.isNull())))) if (!(fAllowNull && v.isNull())) {
{ RPCTypeCheckArgument(v, t);
string err = strprintf("Expected type %s, got %s",
uvTypeName(t), uvTypeName(v.type()));
throw JSONRPCError(RPC_TYPE_ERROR, err);
} }
i++; i++;
} }
} }
void RPCTypeCheckArgument(const UniValue& value, UniValue::VType typeExpected)
{
if (value.type() != typeExpected) {
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected type %s, got %s", uvTypeName(typeExpected), uvTypeName(value.type())));
}
}
void RPCTypeCheckObj(const UniValue& o, void RPCTypeCheckObj(const UniValue& o,
const map<string, UniValueType>& typesExpected, const map<string, UniValueType>& typesExpected,
bool fAllowNull, bool fAllowNull,

View File

@ -76,6 +76,11 @@ bool RPCIsInWarmup(std::string *statusOut);
void RPCTypeCheck(const UniValue& params, void RPCTypeCheck(const UniValue& params,
const std::list<UniValue::VType>& typesExpected, bool fAllowNull=false); const std::list<UniValue::VType>& typesExpected, bool fAllowNull=false);
/**
* Type-check one argument; throws JSONRPCError if wrong type given.
*/
void RPCTypeCheckArgument(const UniValue& value, UniValue::VType typeExpected);
/* /*
Check for expected keys/value types in an Object. Check for expected keys/value types in an Object.
*/ */

View File

@ -2487,9 +2487,9 @@ UniValue listunspent(const JSONRPCRequest& request)
if (!EnsureWalletIsAvailable(request.fHelp)) if (!EnsureWalletIsAvailable(request.fHelp))
return NullUniValue; return NullUniValue;
if (request.fHelp || request.params.size() > 3) if (request.fHelp || request.params.size() > 4)
throw runtime_error( throw runtime_error(
"listunspent ( minconf maxconf [\"addresses\",...] )\n" "listunspent ( minconf maxconf [\"addresses\",...] [include_unsafe] )\n"
"\nReturns array of unspent transaction outputs\n" "\nReturns array of unspent transaction outputs\n"
"with between minconf and maxconf (inclusive) confirmations.\n" "with between minconf and maxconf (inclusive) confirmations.\n"
"Optionally filter to only include txouts paid to specified addresses.\n" "Optionally filter to only include txouts paid to specified addresses.\n"
@ -2501,6 +2501,10 @@ UniValue listunspent(const JSONRPCRequest& request)
" \"address\" (string) dash address\n" " \"address\" (string) dash address\n"
" ,...\n" " ,...\n"
" ]\n" " ]\n"
"4. include_unsafe (bool, optional, default=true) Include outputs that are not safe to spend\n"
" because they come from unconfirmed untrusted transactions or unconfirmed\n"
" replacement transactions (cases where we are less sure that a conflicting\n"
" transaction won't be mined).\n"
"\nResult:\n" "\nResult:\n"
"[ (array of json object)\n" "[ (array of json object)\n"
" {\n" " {\n"
@ -2525,18 +2529,21 @@ UniValue listunspent(const JSONRPCRequest& request)
+ HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\\\",\\\"XuQQkwA4FYkq2XERzMY2CiAZhJTEDAbtcg\\\"]\"") + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\\\",\\\"XuQQkwA4FYkq2XERzMY2CiAZhJTEDAbtcg\\\"]\"")
); );
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR));
int nMinDepth = 1; int nMinDepth = 1;
if (request.params.size() > 0) if (request.params.size() > 0 && !request.params[0].isNull()) {
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
nMinDepth = request.params[0].get_int(); nMinDepth = request.params[0].get_int();
}
int nMaxDepth = 9999999; int nMaxDepth = 9999999;
if (request.params.size() > 1) if (request.params.size() > 1 && !request.params[1].isNull()) {
RPCTypeCheckArgument(request.params[1], UniValue::VNUM);
nMaxDepth = request.params[1].get_int(); nMaxDepth = request.params[1].get_int();
}
set<CBitcoinAddress> setAddress; set<CBitcoinAddress> setAddress;
if (request.params.size() > 2) { if (request.params.size() > 2 && !request.params[2].isNull()) {
RPCTypeCheckArgument(request.params[2], UniValue::VARR);
UniValue inputs = request.params[2].get_array(); UniValue inputs = request.params[2].get_array();
for (unsigned int idx = 0; idx < inputs.size(); idx++) { for (unsigned int idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx]; const UniValue& input = inputs[idx];
@ -2549,11 +2556,17 @@ UniValue listunspent(const JSONRPCRequest& request)
} }
} }
bool include_unsafe = true;
if (request.params.size() > 3 && !request.params[3].isNull()) {
RPCTypeCheckArgument(request.params[3], UniValue::VBOOL);
include_unsafe = request.params[3].get_bool();
}
UniValue results(UniValue::VARR); UniValue results(UniValue::VARR);
vector<COutput> vecOutputs; vector<COutput> vecOutputs;
assert(pwalletMain != NULL); assert(pwalletMain != NULL);
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); pwalletMain->AvailableCoins(vecOutputs, !include_unsafe, NULL, true);
BOOST_FOREACH(const COutput& out, vecOutputs) { BOOST_FOREACH(const COutput& out, vecOutputs) {
if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
continue; continue;
@ -2816,7 +2829,7 @@ static const CRPCCommand commands[] =
{ "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","addlockconf","include_empty","include_watchonly"} }, { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","addlockconf","include_empty","include_watchonly"} },
{ "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} }, { "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} },
{ "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} }, { "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} },
{ "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses"} }, { "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe"} },
{ "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} }, { "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} },
{ "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} }, { "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} },
{ "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","addlockconf","comment","comment_to"} }, { "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","addlockconf","comment","comment_to"} },