X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Frpcwallet.cpp;h=f6a03830827f6782f60e16337305b9bbecc9f1f7;hb=24c6c44c55e61e2abf79928d3387a98509165414;hp=ed024a562c75112874a27562e97fb970ba8a6196;hpb=9167b228998e353585d2d5e45826d57dfddf534e;p=novacoin.git diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index ed024a5..f6a0383 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -12,7 +12,7 @@ using namespace json_spirit; using namespace std; -int64 nWalletUnlockTime; +int64_t nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry); @@ -20,7 +20,7 @@ extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spiri std::string HelpRequiringPassphrase() { return pwalletMain->IsCrypted() - ? "\nrequires wallet passphrase to be set with walletpassphrase first" + ? "\n\nRequires wallet passphrase to be set with walletpassphrase first" : ""; } @@ -259,40 +259,39 @@ Value mergecoins(const Array& params, bool fHelp) { if (fHelp || params.size() != 3) throw runtime_error( - "mergecoins \n" + "mergecoins \n" " is resulting inputs sum\n" + " is minimum value of inputs which are used in join process\n" " is resulting value of inputs which will be created\n" - " is maximum value of inputs which are used in join process\n" - "All values are real and and rounded to the nearest " + FormatMoney(MIN_TXOUT_AMOUNT) + "All values are real and and rounded to the nearest " + FormatMoney(nMinimumInputValue) + HelpRequiringPassphrase()); if (pwalletMain->IsLocked()) throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); - // Amount - int64 nAmount = AmountFromValue(params[0]); + // Total amount + int64_t nAmount = AmountFromValue(params[0]); - // Amount - int64 nOutputValue = AmountFromValue(params[1]); + // Min input amount + int64_t nMinValue = AmountFromValue(params[1]); - // Amount - int64 nMaxValue = AmountFromValue(params[2]); + // Output amount + int64_t nOutputValue = AmountFromValue(params[2]); - if (nAmount < MIN_TXOUT_AMOUNT) + if (nAmount < nMinimumInputValue) throw JSONRPCError(-101, "Send amount too small"); - if (nOutputValue < MIN_TXOUT_AMOUNT) - throw JSONRPCError(-101, "Output value too small"); - - if (nMaxValue < MIN_TXOUT_AMOUNT) + if (nMinValue < nMinimumInputValue) throw JSONRPCError(-101, "Max value too small"); - if (nOutputValue < nMaxValue) - throw JSONRPCError(-101, "Output value is lower than max value"); + if (nOutputValue < nMinimumInputValue) + throw JSONRPCError(-101, "Output value too small"); + if (nOutputValue < nMinValue) + throw JSONRPCError(-101, "Output value is lower than min value"); list listMerged; - if (!pwalletMain->MergeCoins(nAmount, nMaxValue, nOutputValue, listMerged)) + if (!pwalletMain->MergeCoins(nAmount, nMinValue, nOutputValue, listMerged)) return Value::null; Array mergedHashes; @@ -307,7 +306,7 @@ Value sendtoaddress(const Array& params, bool fHelp) if (fHelp || params.size() < 2 || params.size() > 4) throw runtime_error( "sendtoaddress [comment] [comment-to]\n" - " is a real and is rounded to the nearest " + FormatMoney(MIN_TXOUT_AMOUNT) + " is a real and is rounded to the nearest " + FormatMoney(nMinimumInputValue) + HelpRequiringPassphrase()); CBitcoinAddress address(params[0].get_str()); @@ -315,9 +314,9 @@ Value sendtoaddress(const Array& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address"); // Amount - int64 nAmount = AmountFromValue(params[1]); + int64_t nAmount = AmountFromValue(params[1]); - if (nAmount < MIN_TXOUT_AMOUNT) + if (nAmount < nMinimumInputValue) throw JSONRPCError(-101, "Send amount too small"); // Wallet comments @@ -347,7 +346,7 @@ Value listaddressgroupings(const Array& params, bool fHelp) "in past transactions"); Array jsonGroupings; - map balances = pwalletMain->GetAddressBalances(); + map balances = pwalletMain->GetAddressBalances(); BOOST_FOREACH(set grouping, pwalletMain->GetAddressGroupings()) { Array jsonGrouping; @@ -462,7 +461,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) nMinDepth = params[1].get_int(); // Tally - int64 nAmount = 0; + int64_t nAmount = 0; for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; @@ -508,7 +507,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) GetAccountAddresses(strAccount, setAddress); // Tally - int64 nAmount = 0; + int64_t nAmount = 0; for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; @@ -528,9 +527,9 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) } -int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter) +int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter) { - int64 nBalance = 0; + int64_t nBalance = 0; // Tally wallet transactions for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) @@ -539,7 +538,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD if (!wtx.IsFinal()) continue; - int64 nGenerated, nReceived, nSent, nFee; + int64_t nGenerated, nReceived, nSent, nFee; wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee, filter); if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) @@ -553,7 +552,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD return nBalance; } -int64 GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter) +int64_t GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter) { CWalletDB walletdb(pwalletMain->strWalletFile); return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); @@ -584,26 +583,26 @@ Value getbalance(const Array& params, bool fHelp) // Calculate total balance a different way from GetBalance() // (GetBalance() sums up all unspent TxOuts) // getbalance and getbalance '*' 0 should return the same number. - int64 nBalance = 0; + int64_t nBalance = 0; for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; if (!wtx.IsTrusted()) continue; - int64 allGeneratedImmature, allGeneratedMature, allFee; + int64_t allGeneratedImmature, allGeneratedMature, allFee; allGeneratedImmature = allGeneratedMature = allFee = 0; string strSentAccount; - list > listReceived; - list > listSent; + list > listReceived; + list > listSent; wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount, filter); if (wtx.GetDepthInMainChain() >= nMinDepth) { - BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& r, listReceived) + BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived) nBalance += r.second; } - BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& r, listSent) + BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listSent) nBalance -= r.second; nBalance -= allFee; nBalance += allGeneratedMature; @@ -613,7 +612,7 @@ Value getbalance(const Array& params, bool fHelp) string strAccount = AccountFromValue(params[0]); - int64 nBalance = GetAccountBalance(strAccount, nMinDepth, filter); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, filter); return ValueFromAmount(nBalance); } @@ -628,9 +627,9 @@ Value movecmd(const Array& params, bool fHelp) string strFrom = AccountFromValue(params[0]); string strTo = AccountFromValue(params[1]); - int64 nAmount = AmountFromValue(params[2]); + int64_t nAmount = AmountFromValue(params[2]); - if (nAmount < MIN_TXOUT_AMOUNT) + if (nAmount < nMinimumInputValue) throw JSONRPCError(-101, "Send amount too small"); if (params.size() > 3) @@ -644,7 +643,7 @@ Value movecmd(const Array& params, bool fHelp) if (!walletdb.TxnBegin()) throw JSONRPCError(RPC_DATABASE_ERROR, "database error"); - int64 nNow = GetAdjustedTime(); + int64_t nNow = GetAdjustedTime(); // Debit CAccountingEntry debit; @@ -678,16 +677,16 @@ Value sendfrom(const Array& params, bool fHelp) if (fHelp || params.size() < 3 || params.size() > 6) throw runtime_error( "sendfrom [minconf=1] [comment] [comment-to]\n" - " is a real and is rounded to the nearest " + FormatMoney(MIN_TXOUT_AMOUNT) + " is a real and is rounded to the nearest " + FormatMoney(nMinimumInputValue) + HelpRequiringPassphrase()); string strAccount = AccountFromValue(params[0]); CBitcoinAddress address(params[1].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address"); - int64 nAmount = AmountFromValue(params[2]); + int64_t nAmount = AmountFromValue(params[2]); - if (nAmount < MIN_TXOUT_AMOUNT) + if (nAmount < nMinimumInputValue) throw JSONRPCError(-101, "Send amount too small"); int nMinDepth = 1; @@ -704,7 +703,7 @@ Value sendfrom(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64 nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -737,9 +736,9 @@ Value sendmany(const Array& params, bool fHelp) wtx.mapValue["comment"] = params[3].get_str(); set setAddress; - vector > vecSend; + vector > vecSend; - int64 totalAmount = 0; + int64_t totalAmount = 0; BOOST_FOREACH(const Pair& s, sendTo) { CBitcoinAddress address(s.name_); @@ -752,9 +751,9 @@ Value sendmany(const Array& params, bool fHelp) CScript scriptPubKey; scriptPubKey.SetDestination(address.Get()); - int64 nAmount = AmountFromValue(s.value_); + int64_t nAmount = AmountFromValue(s.value_); - if (nAmount < MIN_TXOUT_AMOUNT) + if (nAmount < nMinimumInputValue) throw JSONRPCError(-101, "Send amount too small"); totalAmount += nAmount; @@ -765,17 +764,17 @@ Value sendmany(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64 nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); if (totalAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); // Send CReserveKey keyChange(pwalletMain); - int64 nFeeRequired = 0; + int64_t nFeeRequired = 0; bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired); if (!fCreated) { - int64 nTotal = pwalletMain->GetBalance(), nWatchOnly = pwalletMain->GetWatchOnlyBalance(); + int64_t nTotal = pwalletMain->GetBalance(), nWatchOnly = pwalletMain->GetWatchOnlyBalance(); if (totalAmount + nFeeRequired > nTotal - nWatchOnly) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds"); throw JSONRPCError(RPC_WALLET_ERROR, "Transaction creation failed"); @@ -809,7 +808,9 @@ Value addmultisigaddress(const Array& params, bool fHelp) if ((int)keys.size() < nRequired) throw runtime_error( strprintf("not enough keys supplied " - "(got %"PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired)); + "(got %" PRIszu " keys, but need at least %d to redeem)", keys.size(), nRequired)); + if (keys.size() > 16) + throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number"); std::vector pubkeys; pubkeys.resize(keys.size()); for (unsigned int i = 0; i < keys.size(); i++) @@ -848,6 +849,11 @@ Value addmultisigaddress(const Array& params, bool fHelp) // Construct using pay-to-script-hash: CScript inner; inner.SetMultisig(nRequired, pubkeys); + + if (inner.size() > MAX_SCRIPT_ELEMENT_SIZE) + throw runtime_error( + strprintf("redeemScript exceeds size limit: %" PRIszu " > %d", inner.size(), MAX_SCRIPT_ELEMENT_SIZE)); + CScriptID innerID = inner.GetID(); pwalletMain->AddCScript(inner); @@ -881,7 +887,7 @@ Value addredeemscript(const Array& params, bool fHelp) struct tallyitem { - int64 nAmount; + int64_t nAmount; int nConf; tallyitem() { @@ -938,7 +944,7 @@ Value ListReceived(const Array& params, bool fByAccounts) if (it == mapTally.end() && !fIncludeEmpty) continue; - int64 nAmount = 0; + int64_t nAmount = 0; int nConf = std::numeric_limits::max(); if (it != mapTally.end()) { @@ -967,7 +973,7 @@ Value ListReceived(const Array& params, bool fByAccounts) { for (map::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it) { - int64 nAmount = (*it).second.nAmount; + int64_t nAmount = (*it).second.nAmount; int nConf = (*it).second.nConf; Object obj; obj.push_back(Pair("account", (*it).first)); @@ -1020,10 +1026,10 @@ static void MaybePushAddress(Object & entry, const CTxDestination &dest) void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter) { - int64 nGeneratedImmature, nGeneratedMature, nFee; + int64_t nGeneratedImmature, nGeneratedMature, nFee; string strSentAccount; - list > listReceived; - list > listSent; + list > listReceived; + list > listSent; wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount, filter); @@ -1053,7 +1059,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe // Sent if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount)) { - BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64)& s, listSent) + BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) { Object entry; entry.push_back(Pair("account", strSentAccount)); @@ -1078,7 +1084,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe // Received if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) { - BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64)& r, listReceived) + BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& r, listReceived) { string account; if (pwalletMain->mapAddressBook.count(r.first)) @@ -1207,7 +1213,7 @@ Value listaccounts(const Array& params, bool fHelp) includeWatchonly = includeWatchonly | MINE_WATCH_ONLY; - map mapAccountBalances; + map mapAccountBalances; BOOST_FOREACH(const PAIRTYPE(CTxDestination, string)& entry, pwalletMain->mapAddressBook) { if (IsMine(*pwalletMain, entry.first)) // This address belongs to me mapAccountBalances[entry.second] = 0; @@ -1216,18 +1222,18 @@ Value listaccounts(const Array& params, bool fHelp) for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - int64 nGeneratedImmature, nGeneratedMature, nFee; + int64_t nGeneratedImmature, nGeneratedMature, nFee; string strSentAccount; - list > listReceived; - list > listSent; + list > listReceived; + list > listSent; wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount, includeWatchonly); mapAccountBalances[strSentAccount] -= nFee; - BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64)& s, listSent) + BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) mapAccountBalances[strSentAccount] -= s.second; if (wtx.GetDepthInMainChain() >= nMinDepth) { mapAccountBalances[""] += nGeneratedMature; - BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64)& r, listReceived) + BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& r, listReceived) if (pwalletMain->mapAddressBook.count(r.first)) mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second; else @@ -1241,7 +1247,7 @@ Value listaccounts(const Array& params, bool fHelp) mapAccountBalances[entry.strAccount] += entry.nCreditDebit; Object ret; - BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) { + BOOST_FOREACH(const PAIRTYPE(string, int64_t)& accountBalance, mapAccountBalances) { ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second))); } return ret; @@ -1338,10 +1344,10 @@ Value gettransaction(const Array& params, bool fHelp) TxToJSON(wtx, 0, entry); - int64 nCredit = wtx.GetCredit(filter); - int64 nDebit = wtx.GetDebit(filter); - int64 nNet = nCredit - nDebit; - int64 nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0); + int64_t nCredit = wtx.GetCredit(filter); + int64_t nDebit = wtx.GetDebit(filter); + int64_t nNet = nCredit - nDebit; + int64_t nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0); entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); if (wtx.IsFromMe(filter)) @@ -1404,10 +1410,12 @@ Value keypoolrefill(const Array& params, bool fHelp) if (fHelp || params.size() > 1) throw runtime_error( "keypoolrefill [new-size]\n" - "Fills the keypool." + "Fills the keypool.\n" + "IMPORTANT: Any previous backups you have made of your wallet file " + "should be replaced with the newly generated one." + HelpRequiringPassphrase()); - unsigned int nSize = max(GetArg("-keypool", 100), 0LL); + unsigned int nSize = max(GetArg("-keypool", 100), 0); if (params.size() > 0) { if (params[0].get_int() < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size"); @@ -1424,6 +1432,33 @@ Value keypoolrefill(const Array& params, bool fHelp) return Value::null; } +Value keypoolreset(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "keypoolreset [new-size]\n" + "Resets the keypool.\n" + "IMPORTANT: Any previous backups you have made of your wallet file " + "should be replaced with the newly generated one." + + HelpRequiringPassphrase()); + + unsigned int nSize = max(GetArg("-keypool", 100), 0); + if (params.size() > 0) { + if (params[0].get_int() < 0) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size"); + nSize = (unsigned int) params[0].get_int(); + } + + EnsureWalletIsUnlocked(); + + pwalletMain->NewKeyPool(nSize); + + if (pwalletMain->GetKeyPoolSize() < nSize) + throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool."); + + return Value::null; +} + void ThreadTopUpKeyPool(void* parg) { @@ -1438,7 +1473,7 @@ void ThreadCleanWalletPassphrase(void* parg) // Make this thread recognisable as the wallet relocking thread RenameThread("novacoin-lock-wa"); - int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000; + int64_t nMyWakeTime = GetTimeMillis() + *((int64_t*)parg) * 1000; ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime); @@ -1450,7 +1485,7 @@ void ThreadCleanWalletPassphrase(void* parg) { if (nWalletUnlockTime==0) break; - int64 nToSleep = nWalletUnlockTime - GetTimeMillis(); + int64_t nToSleep = nWalletUnlockTime - GetTimeMillis(); if (nToSleep <= 0) break; @@ -1474,7 +1509,7 @@ void ThreadCleanWalletPassphrase(void* parg) LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime); - delete (int64*)parg; + delete (int64_t*)parg; } Value walletpassphrase(const Array& params, bool fHelp) @@ -1509,7 +1544,7 @@ Value walletpassphrase(const Array& params, bool fHelp) "Stores the wallet decryption key in memory for seconds."); NewThread(ThreadTopUpKeyPool, NULL); - int64* pnSleepTime = new int64(params[1].get_int64()); + int64_t* pnSleepTime = new int64_t(params[1].get_int64()); NewThread(ThreadCleanWalletPassphrase, pnSleepTime); // ppcoin: if user OS account compromised prevent trivial sendmoney commands @@ -1702,7 +1737,7 @@ Value reservebalance(const Array& params, bool fHelp) { if (params.size() == 1) throw runtime_error("must provide amount to reserve balance.\n"); - int64 nAmount = AmountFromValue(params[1]); + int64_t nAmount = AmountFromValue(params[1]); nAmount = (nAmount / CENT) * CENT; // round to cent if (nAmount < 0) throw runtime_error("amount cannot be negative.\n"); @@ -1717,7 +1752,7 @@ Value reservebalance(const Array& params, bool fHelp) } Object result; - int64 nReserveBalance = 0; + int64_t nReserveBalance = 0; if (mapArgs.count("-reservebalance") && !ParseMoney(mapArgs["-reservebalance"], nReserveBalance)) throw runtime_error("invalid reserve balance amount\n"); result.push_back(Pair("reserve", (nReserveBalance > 0))); @@ -1735,7 +1770,7 @@ Value checkwallet(const Array& params, bool fHelp) "Check wallet for integrity.\n"); int nMismatchSpent; - int64 nBalanceInQuestion; + int64_t nBalanceInQuestion; pwalletMain->FixSpentCoins(nMismatchSpent, nBalanceInQuestion, true); Object result; if (nMismatchSpent == 0) @@ -1758,7 +1793,7 @@ Value repairwallet(const Array& params, bool fHelp) "Repair wallet if checkwallet reports any problem.\n"); int nMismatchSpent; - int64 nBalanceInQuestion; + int64_t nBalanceInQuestion; pwalletMain->FixSpentCoins(nMismatchSpent, nBalanceInQuestion); Object result; if (nMismatchSpent == 0)