rpc/wallet: Add coinType to queryOptions of listunspent (#3483)

* wallet: Add MAX_COIN_TYPE to CoinTypes to allow dynamic range checks

* rpc: Add coinType to the queryOptions object of listunspent rpc command

This allows to filter the output by CoinType:

0 -> ALL_COINS 
1 -> ONLY_FULLY_MIXED
2 -> ONLY_READY_TO_MIX
3 -> ONLY_NONDENOMINATED
4 -> ONLY_1000
5 -> ONLY_PRIVATESEND_COLLATERAL

* wallet/rpc: Rename CoinType ONLY_1000 to ONLY_MASTERNODE_COLLATERAL

Make it more obvious what ONLY_1000 is in the description of the 
listunspent command.

* wallet/rpc: Formatting only

Co-Authored-By: UdjinM6 <UdjinM6@users.noreply.github.com>

* wallet: Add MIN_COIN_TYPE to CoinTypes

Co-Authored-By: UdjinM6 <UdjinM6@users.noreply.github.com>

* rpc: Check the lower boundary of CoinType in listunspent's queryOptions

Co-Authored-By: UdjinM6 <UdjinM6@users.noreply.github.com>

Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
This commit is contained in:
dustinface 2020-05-18 14:26:18 +02:00 committed by GitHub
parent 3a56ed9ca6
commit 0c5c99243a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 6 deletions

View File

@ -228,7 +228,7 @@ UniValue masternode_outputs(const JSONRPCRequest& request)
// Find possible candidates
std::vector<COutput> vPossibleCoins;
CCoinControl coin_control;
coin_control.nCoinType = CoinType::ONLY_1000;
coin_control.nCoinType = CoinType::ONLY_MASTERNODE_COLLATERAL;
pwallet->AvailableCoins(vPossibleCoins, true, &coin_control);
UniValue obj(UniValue::VOBJ);

View File

@ -17,8 +17,11 @@ enum class CoinType
ONLY_FULLY_MIXED,
ONLY_READY_TO_MIX,
ONLY_NONDENOMINATED,
ONLY_1000, // find masternode outputs including locked ones (use with caution)
ONLY_MASTERNODE_COLLATERAL, // find masternode outputs including locked ones (use with caution)
ONLY_PRIVATESEND_COLLATERAL,
// Attributes
MIN_COIN_TYPE = ALL_COINS,
MAX_COIN_TYPE = ONLY_PRIVATESEND_COLLATERAL,
};
/** Coin Control Features. */

View File

@ -3022,6 +3022,9 @@ UniValue listunspent(const JSONRPCRequest& request)
" \"maximumAmount\" (numeric or string, default=unlimited) Maximum value of each UTXO in " + CURRENCY_UNIT + "\n"
" \"maximumCount\" (numeric or string, default=unlimited) Maximum number of UTXOs\n"
" \"minimumSumAmount\" (numeric or string, default=unlimited) Minimum sum value of all UTXOs in " + CURRENCY_UNIT + "\n"
" \"coinType\" (numeric, default=0) Filter coinTypes as follows:\n"
" 0=ALL_COINS, 1=ONLY_FULLY_MIXED, 2=ONLY_READY_TO_MIX, 3=ONLY_NONDENOMINATED,\n"
" 4=ONLY_MASTERNODE_COLLATERAL, 5=ONLY_PRIVATESEND_COLLATERAL\n"
" }\n"
"\nResult\n"
"[ (array of json object)\n"
@ -3092,6 +3095,8 @@ UniValue listunspent(const JSONRPCRequest& request)
CAmount nMaximumAmount = MAX_MONEY;
CAmount nMinimumSumAmount = MAX_MONEY;
uint64_t nMaximumCount = 0;
CCoinControl coinControl;
coinControl.nCoinType = CoinType::ALL_COINS;
if (!request.params[4].isNull()) {
const UniValue& options = request.params[4].get_obj();
@ -3107,6 +3112,16 @@ UniValue listunspent(const JSONRPCRequest& request)
if (options.exists("maximumCount"))
nMaximumCount = options["maximumCount"].get_int64();
if (options.exists("coinType")) {
int64_t nCoinType = options["coinType"].get_int64();
if (nCoinType < static_cast<int64_t>(CoinType::MIN_COIN_TYPE) || nCoinType > static_cast<int64_t>(CoinType::MAX_COIN_TYPE)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid coinType selected. Available range: %d - %d", static_cast<int64_t>(CoinType::MIN_COIN_TYPE), static_cast<int64_t>(CoinType::MAX_COIN_TYPE)));
}
coinControl.nCoinType = static_cast<CoinType>(nCoinType);
}
}
// Make sure the results are valid at least up to the most recent block
@ -3117,7 +3132,7 @@ UniValue listunspent(const JSONRPCRequest& request)
std::vector<COutput> vecOutputs;
LOCK2(cs_main, pwallet->cs_wallet);
pwallet->AvailableCoins(vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
pwallet->AvailableCoins(vecOutputs, !include_unsafe, &coinControl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
for (const COutput& out : vecOutputs) {
CTxDestination address;
const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;

View File

@ -2829,7 +2829,7 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
} else if(nCoinType == CoinType::ONLY_NONDENOMINATED) {
if (CPrivateSend::IsCollateralAmount(pcoin->tx->vout[i].nValue)) continue; // do not use collateral amounts
found = !CPrivateSend::IsDenominatedAmount(pcoin->tx->vout[i].nValue);
} else if(nCoinType == CoinType::ONLY_1000) {
} else if(nCoinType == CoinType::ONLY_MASTERNODE_COLLATERAL) {
found = pcoin->tx->vout[i].nValue == 1000*COIN;
} else if(nCoinType == CoinType::ONLY_PRIVATESEND_COLLATERAL) {
found = CPrivateSend::IsCollateralAmount(pcoin->tx->vout[i].nValue);
@ -2844,7 +2844,7 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(wtxid, i)))
continue;
if (IsLockedCoin(wtxid, i) && nCoinType != CoinType::ONLY_1000)
if (IsLockedCoin(wtxid, i) && nCoinType != CoinType::ONLY_MASTERNODE_COLLATERAL)
continue;
if (IsSpent(wtxid, i))
@ -3503,7 +3503,7 @@ bool CWallet::GetMasternodeOutpointAndKeys(COutPoint& outpointRet, CPubKey& pubK
// Find possible candidates
std::vector<COutput> vPossibleCoins;
CCoinControl coin_control;
coin_control.nCoinType = CoinType::ONLY_1000;
coin_control.nCoinType = CoinType::ONLY_MASTERNODE_COLLATERAL;
AvailableCoins(vPossibleCoins, true, &coin_control);
if(vPossibleCoins.empty()) {
LogPrintf("CWallet::GetMasternodeOutpointAndKeys -- Could not locate any valid masternode vin\n");