1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "amount.h"
7 #include "base58.h"
8 #include "chain.h"
9 #include "core_io.h"
10 #include "init.h"
11 #include "main.h"
12 #include "net.h"
13 #include "netbase.h"
14 #include "policy/rbf.h"
15 #include "rpc/server.h"
16 #include "timedata.h"
17 #include "util.h"
18 #include "utilmoneystr.h"
19 #include "wallet.h"
20 #include "walletdb.h"
21 
22 #include <stdint.h>
23 
24 #include <boost/assign/list_of.hpp>
25 
26 #include <univalue.h>
27 
28 using namespace std;
29 
30 int64_t nWalletUnlockTime;
31 static CCriticalSection cs_nWalletUnlockTime;
32 
HelpRequiringPassphrase()33 std::string HelpRequiringPassphrase()
34 {
35     return pwalletMain && pwalletMain->IsCrypted()
36         ? "\nRequires wallet passphrase to be set with walletpassphrase call."
37         : "";
38 }
39 
EnsureWalletIsAvailable(bool avoidException)40 bool EnsureWalletIsAvailable(bool avoidException)
41 {
42     if (!pwalletMain)
43     {
44         if (!avoidException)
45             throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
46         else
47             return false;
48     }
49     return true;
50 }
51 
EnsureWalletIsUnlocked()52 void EnsureWalletIsUnlocked()
53 {
54     if (pwalletMain->IsLocked())
55         throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
56 }
57 
WalletTxToJSON(const CWalletTx & wtx,UniValue & entry)58 void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
59 {
60     int confirms = wtx.GetDepthInMainChain();
61     entry.push_back(Pair("confirmations", confirms));
62     if (wtx.IsCoinBase())
63         entry.push_back(Pair("generated", true));
64     if (confirms > 0)
65     {
66         entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
67         entry.push_back(Pair("blockindex", wtx.nIndex));
68         entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
69     } else {
70         entry.push_back(Pair("trusted", wtx.IsTrusted()));
71     }
72     uint256 hash = wtx.GetHash();
73     entry.push_back(Pair("txid", hash.GetHex()));
74     UniValue conflicts(UniValue::VARR);
75     BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
76         conflicts.push_back(conflict.GetHex());
77     entry.push_back(Pair("walletconflicts", conflicts));
78     entry.push_back(Pair("time", wtx.GetTxTime()));
79     entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
80 
81     // Add opt-in RBF status
82     std::string rbfStatus = "no";
83     if (confirms <= 0) {
84         LOCK(mempool.cs);
85         RBFTransactionState rbfState = IsRBFOptIn(wtx, mempool);
86         if (rbfState == RBF_TRANSACTIONSTATE_UNKNOWN)
87             rbfStatus = "unknown";
88         else if (rbfState == RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125)
89             rbfStatus = "yes";
90     }
91     entry.push_back(Pair("bip125-replaceable", rbfStatus));
92 
93     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
94         entry.push_back(Pair(item.first, item.second));
95 }
96 
AccountFromValue(const UniValue & value)97 string AccountFromValue(const UniValue& value)
98 {
99     string strAccount = value.get_str();
100     if (strAccount == "*")
101         throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
102     return strAccount;
103 }
104 
getnewaddress(const UniValue & params,bool fHelp)105 UniValue getnewaddress(const UniValue& params, bool fHelp)
106 {
107     if (!EnsureWalletIsAvailable(fHelp))
108         return NullUniValue;
109 
110     if (fHelp || params.size() > 1)
111         throw runtime_error(
112             "getnewaddress ( \"account\" )\n"
113             "\nReturns a new Zetacoin address for receiving payments.\n"
114             "If 'account' is specified (DEPRECATED), it is added to the address book \n"
115             "so payments received with the address will be credited to 'account'.\n"
116             "\nArguments:\n"
117             "1. \"account\"        (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n"
118             "\nResult:\n"
119             "\"zetacoinaddress\"    (string) The new zetacoin address\n"
120             "\nExamples:\n"
121             + HelpExampleCli("getnewaddress", "")
122             + HelpExampleRpc("getnewaddress", "")
123         );
124 
125     LOCK2(cs_main, pwalletMain->cs_wallet);
126 
127     // Parse the account first so we don't generate a key if there's an error
128     string strAccount;
129     if (params.size() > 0)
130         strAccount = AccountFromValue(params[0]);
131 
132     if (!pwalletMain->IsLocked())
133         pwalletMain->TopUpKeyPool();
134 
135     // Generate a new key that is added to wallet
136     CPubKey newKey;
137     if (!pwalletMain->GetKeyFromPool(newKey))
138         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
139     CKeyID keyID = newKey.GetID();
140 
141     pwalletMain->SetAddressBook(keyID, strAccount, "receive");
142 
143     return CBitcoinAddress(keyID).ToString();
144 }
145 
146 
GetAccountAddress(string strAccount,bool bForceNew=false)147 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
148 {
149     CPubKey pubKey;
150     if (!pwalletMain->GetAccountPubkey(pubKey, strAccount, bForceNew)) {
151         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
152     }
153 
154     return CBitcoinAddress(pubKey.GetID());
155 }
156 
getaccountaddress(const UniValue & params,bool fHelp)157 UniValue getaccountaddress(const UniValue& params, bool fHelp)
158 {
159     if (!EnsureWalletIsAvailable(fHelp))
160         return NullUniValue;
161 
162     if (fHelp || params.size() != 1)
163         throw runtime_error(
164             "getaccountaddress \"account\"\n"
165             "\nDEPRECATED. Returns the current Zetacoin address for receiving payments to this account.\n"
166             "\nArguments:\n"
167             "1. \"account\"       (string, required) The account name for the address. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created and a new address created  if there is no account by the given name.\n"
168             "\nResult:\n"
169             "\"zetacoinaddress\"   (string) The account zetacoin address\n"
170             "\nExamples:\n"
171             + HelpExampleCli("getaccountaddress", "")
172             + HelpExampleCli("getaccountaddress", "\"\"")
173             + HelpExampleCli("getaccountaddress", "\"myaccount\"")
174             + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
175         );
176 
177     LOCK2(cs_main, pwalletMain->cs_wallet);
178 
179     // Parse the account first so we don't generate a key if there's an error
180     string strAccount = AccountFromValue(params[0]);
181 
182     UniValue ret(UniValue::VSTR);
183 
184     ret = GetAccountAddress(strAccount).ToString();
185     return ret;
186 }
187 
188 
getrawchangeaddress(const UniValue & params,bool fHelp)189 UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
190 {
191     if (!EnsureWalletIsAvailable(fHelp))
192         return NullUniValue;
193 
194     if (fHelp || params.size() > 1)
195         throw runtime_error(
196             "getrawchangeaddress\n"
197             "\nReturns a new Zetacoin address, for receiving change.\n"
198             "This is for use with raw transactions, NOT normal use.\n"
199             "\nResult:\n"
200             "\"address\"    (string) The address\n"
201             "\nExamples:\n"
202             + HelpExampleCli("getrawchangeaddress", "")
203             + HelpExampleRpc("getrawchangeaddress", "")
204        );
205 
206     LOCK2(cs_main, pwalletMain->cs_wallet);
207 
208     if (!pwalletMain->IsLocked())
209         pwalletMain->TopUpKeyPool();
210 
211     CReserveKey reservekey(pwalletMain);
212     CPubKey vchPubKey;
213     if (!reservekey.GetReservedKey(vchPubKey))
214         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
215 
216     reservekey.KeepKey();
217 
218     CKeyID keyID = vchPubKey.GetID();
219 
220     return CBitcoinAddress(keyID).ToString();
221 }
222 
223 
setaccount(const UniValue & params,bool fHelp)224 UniValue setaccount(const UniValue& params, bool fHelp)
225 {
226     if (!EnsureWalletIsAvailable(fHelp))
227         return NullUniValue;
228 
229     if (fHelp || params.size() < 1 || params.size() > 2)
230         throw runtime_error(
231             "setaccount \"zetacoinaddress\" \"account\"\n"
232             "\nDEPRECATED. Sets the account associated with the given address.\n"
233             "\nArguments:\n"
234             "1. \"zetacoinaddress\"  (string, required) The zetacoin address to be associated with an account.\n"
235             "2. \"account\"         (string, required) The account to assign the address to.\n"
236             "\nExamples:\n"
237             + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
238             + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
239         );
240 
241     LOCK2(cs_main, pwalletMain->cs_wallet);
242 
243     CBitcoinAddress address(params[0].get_str());
244     if (!address.IsValid())
245         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zetacoin address");
246 
247     string strAccount;
248     if (params.size() > 1)
249         strAccount = AccountFromValue(params[1]);
250 
251     // Only add the account if the address is yours.
252     if (IsMine(*pwalletMain, address.Get()))
253     {
254         // Detect when changing the account of an address that is the 'unused current key' of another account:
255         if (pwalletMain->mapAddressBook.count(address.Get()))
256         {
257             string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
258             if (address == GetAccountAddress(strOldAccount))
259                 GetAccountAddress(strOldAccount, true);
260         }
261         pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
262     }
263     else
264         throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
265 
266     return NullUniValue;
267 }
268 
269 
getaccount(const UniValue & params,bool fHelp)270 UniValue getaccount(const UniValue& params, bool fHelp)
271 {
272     if (!EnsureWalletIsAvailable(fHelp))
273         return NullUniValue;
274 
275     if (fHelp || params.size() != 1)
276         throw runtime_error(
277             "getaccount \"zetacoinaddress\"\n"
278             "\nDEPRECATED. Returns the account associated with the given address.\n"
279             "\nArguments:\n"
280             "1. \"zetacoinaddress\"  (string, required) The zetacoin address for account lookup.\n"
281             "\nResult:\n"
282             "\"accountname\"        (string) the account address\n"
283             "\nExamples:\n"
284             + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
285             + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
286         );
287 
288     LOCK2(cs_main, pwalletMain->cs_wallet);
289 
290     CBitcoinAddress address(params[0].get_str());
291     if (!address.IsValid())
292         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zetacoin address");
293 
294     string strAccount;
295     map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
296     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
297         strAccount = (*mi).second.name;
298     return strAccount;
299 }
300 
301 
getaddressesbyaccount(const UniValue & params,bool fHelp)302 UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
303 {
304     if (!EnsureWalletIsAvailable(fHelp))
305         return NullUniValue;
306 
307     if (fHelp || params.size() != 1)
308         throw runtime_error(
309             "getaddressesbyaccount \"account\"\n"
310             "\nDEPRECATED. Returns the list of addresses for the given account.\n"
311             "\nArguments:\n"
312             "1. \"account\"  (string, required) The account name.\n"
313             "\nResult:\n"
314             "[                     (json array of string)\n"
315             "  \"zetacoinaddress\"  (string) a zetacoin address associated with the given account\n"
316             "  ,...\n"
317             "]\n"
318             "\nExamples:\n"
319             + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
320             + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
321         );
322 
323     LOCK2(cs_main, pwalletMain->cs_wallet);
324 
325     string strAccount = AccountFromValue(params[0]);
326 
327     // Find all addresses that have the given account
328     UniValue ret(UniValue::VARR);
329     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
330     {
331         const CBitcoinAddress& address = item.first;
332         const string& strName = item.second.name;
333         if (strName == strAccount)
334             ret.push_back(address.ToString());
335     }
336     return ret;
337 }
338 
SendMoney(const CTxDestination & address,CAmount nValue,bool fSubtractFeeFromAmount,CWalletTx & wtxNew)339 static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
340 {
341     CAmount curBalance = pwalletMain->GetBalance();
342 
343     // Check amount
344     if (nValue <= 0)
345         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
346 
347     if (nValue > curBalance)
348         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
349 
350     // Parse Bitcoin address
351     CScript scriptPubKey = GetScriptForDestination(address);
352 
353     // Create and send the transaction
354     CReserveKey reservekey(pwalletMain);
355     CAmount nFeeRequired;
356     std::string strError;
357     vector<CRecipient> vecSend;
358     int nChangePosRet = -1;
359     CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
360     vecSend.push_back(recipient);
361     if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
362         if (!fSubtractFeeFromAmount && nValue + nFeeRequired > pwalletMain->GetBalance())
363             strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired));
364         throw JSONRPCError(RPC_WALLET_ERROR, strError);
365     }
366     if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
367         throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of the wallet and coins were spent in the copy but not marked as spent here.");
368 }
369 
sendtoaddress(const UniValue & params,bool fHelp)370 UniValue sendtoaddress(const UniValue& params, bool fHelp)
371 {
372     if (!EnsureWalletIsAvailable(fHelp))
373         return NullUniValue;
374 
375     if (fHelp || params.size() < 2 || params.size() > 5)
376         throw runtime_error(
377             "sendtoaddress \"zetacoinaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
378             "\nSend an amount to a given address.\n"
379             + HelpRequiringPassphrase() +
380             "\nArguments:\n"
381             "1. \"zetacoinaddress\"  (string, required) The zetacoin address to send to.\n"
382             "2. \"amount\"      (numeric or string, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
383             "3. \"comment\"     (string, optional) A comment used to store what the transaction is for. \n"
384             "                             This is not part of the transaction, just kept in your wallet.\n"
385             "4. \"comment-to\"  (string, optional) A comment to store the name of the person or organization \n"
386             "                             to which you're sending the transaction. This is not part of the \n"
387             "                             transaction, just kept in your wallet.\n"
388             "5. subtractfeefromamount  (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
389             "                             The recipient will receive less Zetacoins than you enter in the amount field.\n"
390             "\nResult:\n"
391             "\"transactionid\"  (string) The transaction id.\n"
392             "\nExamples:\n"
393             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
394             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
395             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
396             + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
397         );
398 
399     LOCK2(cs_main, pwalletMain->cs_wallet);
400 
401     CBitcoinAddress address(params[0].get_str());
402     if (!address.IsValid())
403         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zetacoin address");
404 
405     // Amount
406     CAmount nAmount = AmountFromValue(params[1]);
407     if (nAmount <= 0)
408         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
409 
410     // Wallet comments
411     CWalletTx wtx;
412     if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty())
413         wtx.mapValue["comment"] = params[2].get_str();
414     if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
415         wtx.mapValue["to"]      = params[3].get_str();
416 
417     bool fSubtractFeeFromAmount = false;
418     if (params.size() > 4)
419         fSubtractFeeFromAmount = params[4].get_bool();
420 
421     EnsureWalletIsUnlocked();
422 
423     SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
424 
425     return wtx.GetHash().GetHex();
426 }
427 
listaddressgroupings(const UniValue & params,bool fHelp)428 UniValue listaddressgroupings(const UniValue& params, bool fHelp)
429 {
430     if (!EnsureWalletIsAvailable(fHelp))
431         return NullUniValue;
432 
433     if (fHelp)
434         throw runtime_error(
435             "listaddressgroupings\n"
436             "\nLists groups of addresses which have had their common ownership\n"
437             "made public by common use as inputs or as the resulting change\n"
438             "in past transactions\n"
439             "\nResult:\n"
440             "[\n"
441             "  [\n"
442             "    [\n"
443             "      \"zetacoinaddress\",     (string) The zetacoin address\n"
444             "      amount,                 (numeric) The amount in " + CURRENCY_UNIT + "\n"
445             "      \"account\"             (string, optional) The account (DEPRECATED)\n"
446             "    ]\n"
447             "    ,...\n"
448             "  ]\n"
449             "  ,...\n"
450             "]\n"
451             "\nExamples:\n"
452             + HelpExampleCli("listaddressgroupings", "")
453             + HelpExampleRpc("listaddressgroupings", "")
454         );
455 
456     LOCK2(cs_main, pwalletMain->cs_wallet);
457 
458     UniValue jsonGroupings(UniValue::VARR);
459     map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
460     BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
461     {
462         UniValue jsonGrouping(UniValue::VARR);
463         BOOST_FOREACH(CTxDestination address, grouping)
464         {
465             UniValue addressInfo(UniValue::VARR);
466             addressInfo.push_back(CBitcoinAddress(address).ToString());
467             addressInfo.push_back(ValueFromAmount(balances[address]));
468             {
469                 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
470                     addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
471             }
472             jsonGrouping.push_back(addressInfo);
473         }
474         jsonGroupings.push_back(jsonGrouping);
475     }
476     return jsonGroupings;
477 }
478 
signmessage(const UniValue & params,bool fHelp)479 UniValue signmessage(const UniValue& params, bool fHelp)
480 {
481     if (!EnsureWalletIsAvailable(fHelp))
482         return NullUniValue;
483 
484     if (fHelp || params.size() != 2)
485         throw runtime_error(
486             "signmessage \"zetacoinaddress\" \"message\"\n"
487             "\nSign a message with the private key of an address"
488             + HelpRequiringPassphrase() + "\n"
489             "\nArguments:\n"
490             "1. \"zetacoinaddress\"  (string, required) The zetacoin address to use for the private key.\n"
491             "2. \"message\"         (string, required) The message to create a signature of.\n"
492             "\nResult:\n"
493             "\"signature\"          (string) The signature of the message encoded in base 64\n"
494             "\nExamples:\n"
495             "\nUnlock the wallet for 30 seconds\n"
496             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
497             "\nCreate the signature\n"
498             + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
499             "\nVerify the signature\n"
500             + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
501             "\nAs json rpc\n"
502             + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
503         );
504 
505     LOCK2(cs_main, pwalletMain->cs_wallet);
506 
507     EnsureWalletIsUnlocked();
508 
509     string strAddress = params[0].get_str();
510     string strMessage = params[1].get_str();
511 
512     CBitcoinAddress addr(strAddress);
513     if (!addr.IsValid())
514         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
515 
516     CKeyID keyID;
517     if (!addr.GetKeyID(keyID))
518         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
519 
520     CKey key;
521     if (!pwalletMain->GetKey(keyID, key))
522         throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
523 
524     CHashWriter ss(SER_GETHASH, 0);
525     ss << strMessageMagic;
526     ss << strMessage;
527 
528     vector<unsigned char> vchSig;
529     if (!key.SignCompact(ss.GetHash(), vchSig))
530         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
531 
532     return EncodeBase64(&vchSig[0], vchSig.size());
533 }
534 
getreceivedbyaddress(const UniValue & params,bool fHelp)535 UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
536 {
537     if (!EnsureWalletIsAvailable(fHelp))
538         return NullUniValue;
539 
540     if (fHelp || params.size() < 1 || params.size() > 2)
541         throw runtime_error(
542             "getreceivedbyaddress \"zetacoinaddress\" ( minconf )\n"
543             "\nReturns the total amount received by the given zetacoinaddress in transactions with at least minconf confirmations.\n"
544             "\nArguments:\n"
545             "1. \"zetacoinaddress\"  (string, required) The zetacoin address for transactions.\n"
546             "2. minconf             (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
547             "\nResult:\n"
548             "amount   (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
549             "\nExamples:\n"
550             "\nThe amount from transactions with at least 1 confirmation\n"
551             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") +
552             "\nThe amount including unconfirmed transactions, zero confirmations\n"
553             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 0") +
554             "\nThe amount with at least 6 confirmation, very safe\n"
555             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 6") +
556             "\nAs a json rpc call\n"
557             + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
558        );
559 
560     LOCK2(cs_main, pwalletMain->cs_wallet);
561 
562     // Bitcoin address
563     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
564     if (!address.IsValid())
565         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zetacoin address");
566     CScript scriptPubKey = GetScriptForDestination(address.Get());
567     if (!IsMine(*pwalletMain, scriptPubKey))
568         return ValueFromAmount(0);
569 
570     // Minimum confirmations
571     int nMinDepth = 1;
572     if (params.size() > 1)
573         nMinDepth = params[1].get_int();
574 
575     // Tally
576     CAmount nAmount = 0;
577     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
578     {
579         const CWalletTx& wtx = (*it).second;
580         if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
581             continue;
582 
583         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
584             if (txout.scriptPubKey == scriptPubKey)
585                 if (wtx.GetDepthInMainChain() >= nMinDepth)
586                     nAmount += txout.nValue;
587     }
588 
589     return  ValueFromAmount(nAmount);
590 }
591 
592 
getreceivedbyaccount(const UniValue & params,bool fHelp)593 UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
594 {
595     if (!EnsureWalletIsAvailable(fHelp))
596         return NullUniValue;
597 
598     if (fHelp || params.size() < 1 || params.size() > 2)
599         throw runtime_error(
600             "getreceivedbyaccount \"account\" ( minconf )\n"
601             "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
602             "\nArguments:\n"
603             "1. \"account\"      (string, required) The selected account, may be the default account using \"\".\n"
604             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
605             "\nResult:\n"
606             "amount              (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
607             "\nExamples:\n"
608             "\nAmount received by the default account with at least 1 confirmation\n"
609             + HelpExampleCli("getreceivedbyaccount", "\"\"") +
610             "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
611             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
612             "\nThe amount with at least 6 confirmation, very safe\n"
613             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
614             "\nAs a json rpc call\n"
615             + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
616         );
617 
618     LOCK2(cs_main, pwalletMain->cs_wallet);
619 
620     // Minimum confirmations
621     int nMinDepth = 1;
622     if (params.size() > 1)
623         nMinDepth = params[1].get_int();
624 
625     // Get the set of pub keys assigned to account
626     string strAccount = AccountFromValue(params[0]);
627     set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
628 
629     // Tally
630     CAmount nAmount = 0;
631     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
632     {
633         const CWalletTx& wtx = (*it).second;
634         if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
635             continue;
636 
637         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
638         {
639             CTxDestination address;
640             if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
641                 if (wtx.GetDepthInMainChain() >= nMinDepth)
642                     nAmount += txout.nValue;
643         }
644     }
645 
646     return ValueFromAmount(nAmount);
647 }
648 
649 
getbalance(const UniValue & params,bool fHelp)650 UniValue getbalance(const UniValue& params, bool fHelp)
651 {
652     if (!EnsureWalletIsAvailable(fHelp))
653         return NullUniValue;
654 
655     if (fHelp || params.size() > 3)
656         throw runtime_error(
657             "getbalance ( \"account\" minconf includeWatchonly )\n"
658             "\nIf account is not specified, returns the server's total available balance.\n"
659             "If account is specified (DEPRECATED), returns the balance in the account.\n"
660             "Note that the account \"\" is not the same as leaving the parameter out.\n"
661             "The server total may be different to the balance in the default \"\" account.\n"
662             "\nArguments:\n"
663             "1. \"account\"      (string, optional) DEPRECATED. The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
664             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
665             "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
666             "\nResult:\n"
667             "amount              (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
668             "\nExamples:\n"
669             "\nThe total amount in the wallet\n"
670             + HelpExampleCli("getbalance", "") +
671             "\nThe total amount in the wallet at least 5 blocks confirmed\n"
672             + HelpExampleCli("getbalance", "\"*\" 6") +
673             "\nAs a json rpc call\n"
674             + HelpExampleRpc("getbalance", "\"*\", 6")
675         );
676 
677     LOCK2(cs_main, pwalletMain->cs_wallet);
678 
679     if (params.size() == 0)
680         return  ValueFromAmount(pwalletMain->GetBalance());
681 
682     int nMinDepth = 1;
683     if (params.size() > 1)
684         nMinDepth = params[1].get_int();
685     isminefilter filter = ISMINE_SPENDABLE;
686     if(params.size() > 2)
687         if(params[2].get_bool())
688             filter = filter | ISMINE_WATCH_ONLY;
689 
690     if (params[0].get_str() == "*") {
691         // Calculate total balance a different way from GetBalance()
692         // (GetBalance() sums up all unspent TxOuts)
693         // getbalance and "getbalance * 1 true" should return the same number
694         CAmount nBalance = 0;
695         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
696         {
697             const CWalletTx& wtx = (*it).second;
698             if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
699                 continue;
700 
701             CAmount allFee;
702             string strSentAccount;
703             list<COutputEntry> listReceived;
704             list<COutputEntry> listSent;
705             wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
706             if (wtx.GetDepthInMainChain() >= nMinDepth)
707             {
708                 BOOST_FOREACH(const COutputEntry& r, listReceived)
709                     nBalance += r.amount;
710             }
711             BOOST_FOREACH(const COutputEntry& s, listSent)
712                 nBalance -= s.amount;
713             nBalance -= allFee;
714         }
715         return  ValueFromAmount(nBalance);
716     }
717 
718     string strAccount = AccountFromValue(params[0]);
719 
720     CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, filter);
721 
722     return ValueFromAmount(nBalance);
723 }
724 
getunconfirmedbalance(const UniValue & params,bool fHelp)725 UniValue getunconfirmedbalance(const UniValue &params, bool fHelp)
726 {
727     if (!EnsureWalletIsAvailable(fHelp))
728         return NullUniValue;
729 
730     if (fHelp || params.size() > 0)
731         throw runtime_error(
732                 "getunconfirmedbalance\n"
733                 "Returns the server's total unconfirmed balance\n");
734 
735     LOCK2(cs_main, pwalletMain->cs_wallet);
736 
737     return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
738 }
739 
740 
movecmd(const UniValue & params,bool fHelp)741 UniValue movecmd(const UniValue& params, bool fHelp)
742 {
743     if (!EnsureWalletIsAvailable(fHelp))
744         return NullUniValue;
745 
746     if (fHelp || params.size() < 3 || params.size() > 5)
747         throw runtime_error(
748             "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
749             "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
750             "\nArguments:\n"
751             "1. \"fromaccount\"   (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
752             "2. \"toaccount\"     (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
753             "3. amount            (numeric) Quantity of " + CURRENCY_UNIT + " to move between accounts.\n"
754             "4. minconf           (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
755             "5. \"comment\"       (string, optional) An optional comment, stored in the wallet only.\n"
756             "\nResult:\n"
757             "true|false           (boolean) true if successful.\n"
758             "\nExamples:\n"
759             "\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n"
760             + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
761             "\nMove 0.01 " + CURRENCY_UNIT + " timotei to akiko with a comment and funds have 6 confirmations\n"
762             + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
763             "\nAs a json rpc call\n"
764             + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
765         );
766 
767     LOCK2(cs_main, pwalletMain->cs_wallet);
768 
769     string strFrom = AccountFromValue(params[0]);
770     string strTo = AccountFromValue(params[1]);
771     CAmount nAmount = AmountFromValue(params[2]);
772     if (nAmount <= 0)
773         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
774     if (params.size() > 3)
775         // unused parameter, used to be nMinDepth, keep type-checking it though
776         (void)params[3].get_int();
777     string strComment;
778     if (params.size() > 4)
779         strComment = params[4].get_str();
780 
781     if (!pwalletMain->AccountMove(strFrom, strTo, nAmount, strComment))
782         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
783 
784     return true;
785 }
786 
787 
sendfrom(const UniValue & params,bool fHelp)788 UniValue sendfrom(const UniValue& params, bool fHelp)
789 {
790     if (!EnsureWalletIsAvailable(fHelp))
791         return NullUniValue;
792 
793     if (fHelp || params.size() < 3 || params.size() > 6)
794         throw runtime_error(
795             "sendfrom \"fromaccount\" \"tozetacoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
796             "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a zetacoin address."
797             + HelpRequiringPassphrase() + "\n"
798             "\nArguments:\n"
799             "1. \"fromaccount\"       (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
800             "2. \"tozetacoinaddress\"  (string, required) The zetacoin address to send funds to.\n"
801             "3. amount                (numeric or string, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n"
802             "4. minconf               (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
803             "5. \"comment\"           (string, optional) A comment used to store what the transaction is for. \n"
804             "                                     This is not part of the transaction, just kept in your wallet.\n"
805             "6. \"comment-to\"        (string, optional) An optional comment to store the name of the person or organization \n"
806             "                                     to which you're sending the transaction. This is not part of the transaction, \n"
807             "                                     it is just kept in your wallet.\n"
808             "\nResult:\n"
809             "\"transactionid\"        (string) The transaction id.\n"
810             "\nExamples:\n"
811             "\nSend 0.01 " + CURRENCY_UNIT + " from the default account to the address, must have at least 1 confirmation\n"
812             + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
813             "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
814             + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
815             "\nAs a json rpc call\n"
816             + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
817         );
818 
819     LOCK2(cs_main, pwalletMain->cs_wallet);
820 
821     string strAccount = AccountFromValue(params[0]);
822     CBitcoinAddress address(params[1].get_str());
823     if (!address.IsValid())
824         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zetacoin address");
825     CAmount nAmount = AmountFromValue(params[2]);
826     if (nAmount <= 0)
827         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
828     int nMinDepth = 1;
829     if (params.size() > 3)
830         nMinDepth = params[3].get_int();
831 
832     CWalletTx wtx;
833     wtx.strFromAccount = strAccount;
834     if (params.size() > 4 && !params[4].isNull() && !params[4].get_str().empty())
835         wtx.mapValue["comment"] = params[4].get_str();
836     if (params.size() > 5 && !params[5].isNull() && !params[5].get_str().empty())
837         wtx.mapValue["to"]      = params[5].get_str();
838 
839     EnsureWalletIsUnlocked();
840 
841     // Check funds
842     CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
843     if (nAmount > nBalance)
844         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
845 
846     SendMoney(address.Get(), nAmount, false, wtx);
847 
848     return wtx.GetHash().GetHex();
849 }
850 
851 
sendmany(const UniValue & params,bool fHelp)852 UniValue sendmany(const UniValue& params, bool fHelp)
853 {
854     if (!EnsureWalletIsAvailable(fHelp))
855         return NullUniValue;
856 
857     if (fHelp || params.size() < 2 || params.size() > 5)
858         throw runtime_error(
859             "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
860             "\nSend multiple times. Amounts are double-precision floating point numbers."
861             + HelpRequiringPassphrase() + "\n"
862             "\nArguments:\n"
863             "1. \"fromaccount\"         (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
864             "2. \"amounts\"             (string, required) A json object with addresses and amounts\n"
865             "    {\n"
866             "      \"address\":amount   (numeric or string) The zetacoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value\n"
867             "      ,...\n"
868             "    }\n"
869             "3. minconf                 (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
870             "4. \"comment\"             (string, optional) A comment\n"
871             "5. subtractfeefromamount   (string, optional) A json array with addresses.\n"
872             "                           The fee will be equally deducted from the amount of each selected address.\n"
873             "                           Those recipients will receive less Zetacoins than you enter in their corresponding amount field.\n"
874             "                           If no addresses are specified here, the sender pays the fee.\n"
875             "    [\n"
876             "      \"address\"            (string) Subtract fee from this address\n"
877             "      ,...\n"
878             "    ]\n"
879             "\nResult:\n"
880             "\"transactionid\"          (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
881             "                                    the number of addresses.\n"
882             "\nExamples:\n"
883             "\nSend two amounts to two different addresses:\n"
884             + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
885             "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
886             + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
887             "\nSend two amounts to two different addresses, subtract fee from amount:\n"
888             + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
889             "\nAs a json rpc call\n"
890             + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
891         );
892 
893     LOCK2(cs_main, pwalletMain->cs_wallet);
894 
895     string strAccount = AccountFromValue(params[0]);
896     UniValue sendTo = params[1].get_obj();
897     int nMinDepth = 1;
898     if (params.size() > 2)
899         nMinDepth = params[2].get_int();
900 
901     CWalletTx wtx;
902     wtx.strFromAccount = strAccount;
903     if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
904         wtx.mapValue["comment"] = params[3].get_str();
905 
906     UniValue subtractFeeFromAmount(UniValue::VARR);
907     if (params.size() > 4)
908         subtractFeeFromAmount = params[4].get_array();
909 
910     set<CBitcoinAddress> setAddress;
911     vector<CRecipient> vecSend;
912 
913     CAmount totalAmount = 0;
914     vector<string> keys = sendTo.getKeys();
915     BOOST_FOREACH(const string& name_, keys)
916     {
917         CBitcoinAddress address(name_);
918         if (!address.IsValid())
919             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zetacoin address: ")+name_);
920 
921         if (setAddress.count(address))
922             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
923         setAddress.insert(address);
924 
925         CScript scriptPubKey = GetScriptForDestination(address.Get());
926         CAmount nAmount = AmountFromValue(sendTo[name_]);
927         if (nAmount <= 0)
928             throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
929         totalAmount += nAmount;
930 
931         bool fSubtractFeeFromAmount = false;
932         for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
933             const UniValue& addr = subtractFeeFromAmount[idx];
934             if (addr.get_str() == name_)
935                 fSubtractFeeFromAmount = true;
936         }
937 
938         CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
939         vecSend.push_back(recipient);
940     }
941 
942     EnsureWalletIsUnlocked();
943 
944     // Check funds
945     CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
946     if (totalAmount > nBalance)
947         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
948 
949     // Send
950     CReserveKey keyChange(pwalletMain);
951     CAmount nFeeRequired = 0;
952     int nChangePosRet = -1;
953     string strFailReason;
954     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
955     if (!fCreated)
956         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
957     if (!pwalletMain->CommitTransaction(wtx, keyChange))
958         throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
959 
960     return wtx.GetHash().GetHex();
961 }
962 
963 // Defined in rpc/misc.cpp
964 extern CScript _createmultisig_redeemScript(const UniValue& params);
965 
addmultisigaddress(const UniValue & params,bool fHelp)966 UniValue addmultisigaddress(const UniValue& params, bool fHelp)
967 {
968     if (!EnsureWalletIsAvailable(fHelp))
969         return NullUniValue;
970 
971     if (fHelp || params.size() < 2 || params.size() > 3)
972     {
973         string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
974             "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
975             "Each key is a Zetacoin address or hex-encoded public key.\n"
976             "If 'account' is specified (DEPRECATED), assign address to that account.\n"
977 
978             "\nArguments:\n"
979             "1. nrequired        (numeric, required) The number of required signatures out of the n keys or addresses.\n"
980             "2. \"keysobject\"   (string, required) A json array of zetacoin addresses or hex-encoded public keys\n"
981             "     [\n"
982             "       \"address\"  (string) zetacoin address or hex-encoded public key\n"
983             "       ...,\n"
984             "     ]\n"
985             "3. \"account\"      (string, optional) DEPRECATED. An account to assign the addresses to.\n"
986 
987             "\nResult:\n"
988             "\"zetacoinaddress\"  (string) A zetacoin address associated with the keys.\n"
989 
990             "\nExamples:\n"
991             "\nAdd a multisig address from 2 addresses\n"
992             + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
993             "\nAs json rpc call\n"
994             + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
995         ;
996         throw runtime_error(msg);
997     }
998 
999     LOCK2(cs_main, pwalletMain->cs_wallet);
1000 
1001     string strAccount;
1002     if (params.size() > 2)
1003         strAccount = AccountFromValue(params[2]);
1004 
1005     // Construct using pay-to-script-hash:
1006     CScript inner = _createmultisig_redeemScript(params);
1007     CScriptID innerID(inner);
1008     pwalletMain->AddCScript(inner);
1009 
1010     pwalletMain->SetAddressBook(innerID, strAccount, "send");
1011     return CBitcoinAddress(innerID).ToString();
1012 }
1013 
1014 class Witnessifier : public boost::static_visitor<bool>
1015 {
1016 public:
1017     CScriptID result;
1018 
operator ()(const CNoDestination & dest) const1019     bool operator()(const CNoDestination &dest) const { return false; }
1020 
operator ()(const CKeyID & keyID)1021     bool operator()(const CKeyID &keyID) {
1022         CPubKey pubkey;
1023         if (pwalletMain) {
1024             CScript basescript = GetScriptForDestination(keyID);
1025             isminetype typ;
1026             typ = IsMine(*pwalletMain, basescript, SIGVERSION_WITNESS_V0);
1027             if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
1028                 return false;
1029             CScript witscript = GetScriptForWitness(basescript);
1030             pwalletMain->AddCScript(witscript);
1031             result = CScriptID(witscript);
1032             return true;
1033         }
1034         return false;
1035     }
1036 
operator ()(const CScriptID & scriptID)1037     bool operator()(const CScriptID &scriptID) {
1038         CScript subscript;
1039         if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
1040             int witnessversion;
1041             std::vector<unsigned char> witprog;
1042             if (subscript.IsWitnessProgram(witnessversion, witprog)) {
1043                 result = scriptID;
1044                 return true;
1045             }
1046             isminetype typ;
1047             typ = IsMine(*pwalletMain, subscript, SIGVERSION_WITNESS_V0);
1048             if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
1049                 return false;
1050             CScript witscript = GetScriptForWitness(subscript);
1051             pwalletMain->AddCScript(witscript);
1052             result = CScriptID(witscript);
1053             return true;
1054         }
1055         return false;
1056     }
1057 };
1058 
addwitnessaddress(const UniValue & params,bool fHelp)1059 UniValue addwitnessaddress(const UniValue& params, bool fHelp)
1060 {
1061     if (!EnsureWalletIsAvailable(fHelp))
1062         return NullUniValue;
1063 
1064     if (fHelp || params.size() < 1 || params.size() > 1)
1065     {
1066         string msg = "addwitnessaddress \"address\"\n"
1067             "\nAdd a witness address for a script (with pubkey or redeemscript known).\n"
1068             "It returns the witness script.\n"
1069 
1070             "\nArguments:\n"
1071             "1. \"address\"       (string, required) An address known to the wallet\n"
1072 
1073             "\nResult:\n"
1074             "\"witnessaddress\",  (string) The value of the new address (P2SH of witness script).\n"
1075             "}\n"
1076         ;
1077         throw runtime_error(msg);
1078     }
1079 
1080     {
1081         LOCK(cs_main);
1082         if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus()) && !GetBoolArg("-walletprematurewitness", false)) {
1083             throw JSONRPCError(RPC_WALLET_ERROR, "Segregated witness not enabled on network");
1084         }
1085     }
1086 
1087     CBitcoinAddress address(params[0].get_str());
1088     if (!address.IsValid())
1089         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zetacoin address");
1090 
1091     Witnessifier w;
1092     CTxDestination dest = address.Get();
1093     bool ret = boost::apply_visitor(w, dest);
1094     if (!ret) {
1095         throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed");
1096     }
1097 
1098     pwalletMain->SetAddressBook(w.result, "", "receive");
1099 
1100     return CBitcoinAddress(w.result).ToString();
1101 }
1102 
1103 struct tallyitem
1104 {
1105     CAmount nAmount;
1106     int nConf;
1107     vector<uint256> txids;
1108     bool fIsWatchonly;
tallyitemtallyitem1109     tallyitem()
1110     {
1111         nAmount = 0;
1112         nConf = std::numeric_limits<int>::max();
1113         fIsWatchonly = false;
1114     }
1115 };
1116 
ListReceived(const UniValue & params,bool fByAccounts)1117 UniValue ListReceived(const UniValue& params, bool fByAccounts)
1118 {
1119     // Minimum confirmations
1120     int nMinDepth = 1;
1121     if (params.size() > 0)
1122         nMinDepth = params[0].get_int();
1123 
1124     // Whether to include empty accounts
1125     bool fIncludeEmpty = false;
1126     if (params.size() > 1)
1127         fIncludeEmpty = params[1].get_bool();
1128 
1129     isminefilter filter = ISMINE_SPENDABLE;
1130     if(params.size() > 2)
1131         if(params[2].get_bool())
1132             filter = filter | ISMINE_WATCH_ONLY;
1133 
1134     // Tally
1135     map<CBitcoinAddress, tallyitem> mapTally;
1136     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1137     {
1138         const CWalletTx& wtx = (*it).second;
1139 
1140         if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
1141             continue;
1142 
1143         int nDepth = wtx.GetDepthInMainChain();
1144         if (nDepth < nMinDepth)
1145             continue;
1146 
1147         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1148         {
1149             CTxDestination address;
1150             if (!ExtractDestination(txout.scriptPubKey, address))
1151                 continue;
1152 
1153             isminefilter mine = IsMine(*pwalletMain, address);
1154             if(!(mine & filter))
1155                 continue;
1156 
1157             tallyitem& item = mapTally[address];
1158             item.nAmount += txout.nValue;
1159             item.nConf = min(item.nConf, nDepth);
1160             item.txids.push_back(wtx.GetHash());
1161             if (mine & ISMINE_WATCH_ONLY)
1162                 item.fIsWatchonly = true;
1163         }
1164     }
1165 
1166     // Reply
1167     UniValue ret(UniValue::VARR);
1168     map<string, tallyitem> mapAccountTally;
1169     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
1170     {
1171         const CBitcoinAddress& address = item.first;
1172         const string& strAccount = item.second.name;
1173         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1174         if (it == mapTally.end() && !fIncludeEmpty)
1175             continue;
1176 
1177         CAmount nAmount = 0;
1178         int nConf = std::numeric_limits<int>::max();
1179         bool fIsWatchonly = false;
1180         if (it != mapTally.end())
1181         {
1182             nAmount = (*it).second.nAmount;
1183             nConf = (*it).second.nConf;
1184             fIsWatchonly = (*it).second.fIsWatchonly;
1185         }
1186 
1187         if (fByAccounts)
1188         {
1189             tallyitem& item = mapAccountTally[strAccount];
1190             item.nAmount += nAmount;
1191             item.nConf = min(item.nConf, nConf);
1192             item.fIsWatchonly = fIsWatchonly;
1193         }
1194         else
1195         {
1196             UniValue obj(UniValue::VOBJ);
1197             if(fIsWatchonly)
1198                 obj.push_back(Pair("involvesWatchonly", true));
1199             obj.push_back(Pair("address",       address.ToString()));
1200             obj.push_back(Pair("account",       strAccount));
1201             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1202             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1203             if (!fByAccounts)
1204                 obj.push_back(Pair("label", strAccount));
1205             UniValue transactions(UniValue::VARR);
1206             if (it != mapTally.end())
1207             {
1208                 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1209                 {
1210                     transactions.push_back(item.GetHex());
1211                 }
1212             }
1213             obj.push_back(Pair("txids", transactions));
1214             ret.push_back(obj);
1215         }
1216     }
1217 
1218     if (fByAccounts)
1219     {
1220         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1221         {
1222             CAmount nAmount = (*it).second.nAmount;
1223             int nConf = (*it).second.nConf;
1224             UniValue obj(UniValue::VOBJ);
1225             if((*it).second.fIsWatchonly)
1226                 obj.push_back(Pair("involvesWatchonly", true));
1227             obj.push_back(Pair("account",       (*it).first));
1228             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1229             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1230             ret.push_back(obj);
1231         }
1232     }
1233 
1234     return ret;
1235 }
1236 
listreceivedbyaddress(const UniValue & params,bool fHelp)1237 UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
1238 {
1239     if (!EnsureWalletIsAvailable(fHelp))
1240         return NullUniValue;
1241 
1242     if (fHelp || params.size() > 3)
1243         throw runtime_error(
1244             "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
1245             "\nList balances by receiving address.\n"
1246             "\nArguments:\n"
1247             "1. minconf       (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1248             "2. includeempty  (bool, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1249             "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1250 
1251             "\nResult:\n"
1252             "[\n"
1253             "  {\n"
1254             "    \"involvesWatchonly\" : true,        (bool) Only returned if imported addresses were involved in transaction\n"
1255             "    \"address\" : \"receivingaddress\",  (string) The receiving address\n"
1256             "    \"account\" : \"accountname\",       (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
1257             "    \"amount\" : x.xxx,                  (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
1258             "    \"confirmations\" : n,               (numeric) The number of confirmations of the most recent transaction included\n"
1259             "    \"label\" : \"label\"                (string) A comment for the address/transaction, if any\n"
1260             "  }\n"
1261             "  ,...\n"
1262             "]\n"
1263 
1264             "\nExamples:\n"
1265             + HelpExampleCli("listreceivedbyaddress", "")
1266             + HelpExampleCli("listreceivedbyaddress", "6 true")
1267             + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1268         );
1269 
1270     LOCK2(cs_main, pwalletMain->cs_wallet);
1271 
1272     return ListReceived(params, false);
1273 }
1274 
listreceivedbyaccount(const UniValue & params,bool fHelp)1275 UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
1276 {
1277     if (!EnsureWalletIsAvailable(fHelp))
1278         return NullUniValue;
1279 
1280     if (fHelp || params.size() > 3)
1281         throw runtime_error(
1282             "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
1283             "\nDEPRECATED. List balances by account.\n"
1284             "\nArguments:\n"
1285             "1. minconf      (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1286             "2. includeempty (bool, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1287             "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1288 
1289             "\nResult:\n"
1290             "[\n"
1291             "  {\n"
1292             "    \"involvesWatchonly\" : true,   (bool) Only returned if imported addresses were involved in transaction\n"
1293             "    \"account\" : \"accountname\",  (string) The account name of the receiving account\n"
1294             "    \"amount\" : x.xxx,             (numeric) The total amount received by addresses with this account\n"
1295             "    \"confirmations\" : n,          (numeric) The number of confirmations of the most recent transaction included\n"
1296             "    \"label\" : \"label\"           (string) A comment for the address/transaction, if any\n"
1297             "  }\n"
1298             "  ,...\n"
1299             "]\n"
1300 
1301             "\nExamples:\n"
1302             + HelpExampleCli("listreceivedbyaccount", "")
1303             + HelpExampleCli("listreceivedbyaccount", "6 true")
1304             + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1305         );
1306 
1307     LOCK2(cs_main, pwalletMain->cs_wallet);
1308 
1309     return ListReceived(params, true);
1310 }
1311 
MaybePushAddress(UniValue & entry,const CTxDestination & dest)1312 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
1313 {
1314     CBitcoinAddress addr;
1315     if (addr.Set(dest))
1316         entry.push_back(Pair("address", addr.ToString()));
1317 }
1318 
ListTransactions(const CWalletTx & wtx,const string & strAccount,int nMinDepth,bool fLong,UniValue & ret,const isminefilter & filter)1319 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
1320 {
1321     CAmount nFee;
1322     string strSentAccount;
1323     list<COutputEntry> listReceived;
1324     list<COutputEntry> listSent;
1325 
1326     wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1327 
1328     bool fAllAccounts = (strAccount == string("*"));
1329     bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1330 
1331     // Sent
1332     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1333     {
1334         BOOST_FOREACH(const COutputEntry& s, listSent)
1335         {
1336             UniValue entry(UniValue::VOBJ);
1337             if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
1338                 entry.push_back(Pair("involvesWatchonly", true));
1339             entry.push_back(Pair("account", strSentAccount));
1340             MaybePushAddress(entry, s.destination);
1341             entry.push_back(Pair("category", "send"));
1342             entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1343             if (pwalletMain->mapAddressBook.count(s.destination))
1344                 entry.push_back(Pair("label", pwalletMain->mapAddressBook[s.destination].name));
1345             entry.push_back(Pair("vout", s.vout));
1346             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1347             if (fLong)
1348                 WalletTxToJSON(wtx, entry);
1349             entry.push_back(Pair("abandoned", wtx.isAbandoned()));
1350             ret.push_back(entry);
1351         }
1352     }
1353 
1354     // Received
1355     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1356     {
1357         BOOST_FOREACH(const COutputEntry& r, listReceived)
1358         {
1359             string account;
1360             if (pwalletMain->mapAddressBook.count(r.destination))
1361                 account = pwalletMain->mapAddressBook[r.destination].name;
1362             if (fAllAccounts || (account == strAccount))
1363             {
1364                 UniValue entry(UniValue::VOBJ);
1365                 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
1366                     entry.push_back(Pair("involvesWatchonly", true));
1367                 entry.push_back(Pair("account", account));
1368                 MaybePushAddress(entry, r.destination);
1369                 if (wtx.IsCoinBase())
1370                 {
1371                     if (wtx.GetDepthInMainChain() < 1)
1372                         entry.push_back(Pair("category", "orphan"));
1373                     else if (wtx.GetBlocksToMaturity() > 0)
1374                         entry.push_back(Pair("category", "immature"));
1375                     else
1376                         entry.push_back(Pair("category", "generate"));
1377                 }
1378                 else
1379                 {
1380                     entry.push_back(Pair("category", "receive"));
1381                 }
1382                 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1383                 if (pwalletMain->mapAddressBook.count(r.destination))
1384                     entry.push_back(Pair("label", account));
1385                 entry.push_back(Pair("vout", r.vout));
1386                 if (fLong)
1387                     WalletTxToJSON(wtx, entry);
1388                 ret.push_back(entry);
1389             }
1390         }
1391     }
1392 }
1393 
AcentryToJSON(const CAccountingEntry & acentry,const string & strAccount,UniValue & ret)1394 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, UniValue& ret)
1395 {
1396     bool fAllAccounts = (strAccount == string("*"));
1397 
1398     if (fAllAccounts || acentry.strAccount == strAccount)
1399     {
1400         UniValue entry(UniValue::VOBJ);
1401         entry.push_back(Pair("account", acentry.strAccount));
1402         entry.push_back(Pair("category", "move"));
1403         entry.push_back(Pair("time", acentry.nTime));
1404         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1405         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1406         entry.push_back(Pair("comment", acentry.strComment));
1407         ret.push_back(entry);
1408     }
1409 }
1410 
listtransactions(const UniValue & params,bool fHelp)1411 UniValue listtransactions(const UniValue& params, bool fHelp)
1412 {
1413     if (!EnsureWalletIsAvailable(fHelp))
1414         return NullUniValue;
1415 
1416     if (fHelp || params.size() > 4)
1417         throw runtime_error(
1418             "listtransactions ( \"account\" count from includeWatchonly)\n"
1419             "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1420             "\nArguments:\n"
1421             "1. \"account\"    (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
1422             "2. count          (numeric, optional, default=10) The number of transactions to return\n"
1423             "3. from           (numeric, optional, default=0) The number of transactions to skip\n"
1424             "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
1425             "\nResult:\n"
1426             "[\n"
1427             "  {\n"
1428             "    \"account\":\"accountname\",       (string) DEPRECATED. The account name associated with the transaction. \n"
1429             "                                                It will be \"\" for the default account.\n"
1430             "    \"address\":\"zetacoinaddress\",    (string) The zetacoin address of the transaction. Not present for \n"
1431             "                                                move transactions (category = move).\n"
1432             "    \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1433             "                                                transaction between accounts, and not associated with an address,\n"
1434             "                                                transaction id or block. 'send' and 'receive' transactions are \n"
1435             "                                                associated with an address, transaction id and block details\n"
1436             "    \"amount\": x.xxx,          (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n"
1437             "                                         'move' category for moves outbound. It is positive for the 'receive' category,\n"
1438             "                                         and for the 'move' category for inbound funds.\n"
1439             "    \"vout\": n,                (numeric) the vout value\n"
1440             "    \"fee\": x.xxx,             (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1441             "                                         'send' category of transactions.\n"
1442             "    \"abandoned\": xxx          (bool) 'true' if the transaction has been abandoned (inputs are respendable).\n"
1443             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1444             "                                         'receive' category of transactions. Negative confirmations indicate the\n"
1445             "                                         transaction conflicts with the block chain\n"
1446             "    \"trusted\": xxx            (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n"
1447             "    \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1448             "                                          category of transactions.\n"
1449             "    \"blockindex\": n,          (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive'\n"
1450             "                                          category of transactions.\n"
1451             "    \"blocktime\": xxx,         (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1452             "    \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1453             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1454             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1455             "                                          for 'send' and 'receive' category of transactions.\n"
1456             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
1457             "    \"label\": \"label\"        (string) A comment for the address/transaction, if any\n"
1458             "    \"otheraccount\": \"accountname\",  (string) For the 'move' category of transactions, the account the funds came \n"
1459             "                                          from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1460             "                                          negative amounts).\n"
1461             "    \"bip125-replaceable\": \"yes|no|unknown\"  (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1462             "                                                     may be unknown for unconfirmed transactions not in the mempool\n"
1463             "  }\n"
1464             "]\n"
1465 
1466             "\nExamples:\n"
1467             "\nList the most recent 10 transactions in the systems\n"
1468             + HelpExampleCli("listtransactions", "") +
1469             "\nList transactions 100 to 120\n"
1470             + HelpExampleCli("listtransactions", "\"*\" 20 100") +
1471             "\nAs a json rpc call\n"
1472             + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
1473         );
1474 
1475     LOCK2(cs_main, pwalletMain->cs_wallet);
1476 
1477     string strAccount = "*";
1478     if (params.size() > 0)
1479         strAccount = params[0].get_str();
1480     int nCount = 10;
1481     if (params.size() > 1)
1482         nCount = params[1].get_int();
1483     int nFrom = 0;
1484     if (params.size() > 2)
1485         nFrom = params[2].get_int();
1486     isminefilter filter = ISMINE_SPENDABLE;
1487     if(params.size() > 3)
1488         if(params[3].get_bool())
1489             filter = filter | ISMINE_WATCH_ONLY;
1490 
1491     if (nCount < 0)
1492         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1493     if (nFrom < 0)
1494         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1495 
1496     UniValue ret(UniValue::VARR);
1497 
1498     const CWallet::TxItems & txOrdered = pwalletMain->wtxOrdered;
1499 
1500     // iterate backwards until we have nCount items to return:
1501     for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1502     {
1503         CWalletTx *const pwtx = (*it).second.first;
1504         if (pwtx != 0)
1505             ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
1506         CAccountingEntry *const pacentry = (*it).second.second;
1507         if (pacentry != 0)
1508             AcentryToJSON(*pacentry, strAccount, ret);
1509 
1510         if ((int)ret.size() >= (nCount+nFrom)) break;
1511     }
1512     // ret is newest to oldest
1513 
1514     if (nFrom > (int)ret.size())
1515         nFrom = ret.size();
1516     if ((nFrom + nCount) > (int)ret.size())
1517         nCount = ret.size() - nFrom;
1518 
1519     vector<UniValue> arrTmp = ret.getValues();
1520 
1521     vector<UniValue>::iterator first = arrTmp.begin();
1522     std::advance(first, nFrom);
1523     vector<UniValue>::iterator last = arrTmp.begin();
1524     std::advance(last, nFrom+nCount);
1525 
1526     if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
1527     if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
1528 
1529     std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
1530 
1531     ret.clear();
1532     ret.setArray();
1533     ret.push_backV(arrTmp);
1534 
1535     return ret;
1536 }
1537 
listaccounts(const UniValue & params,bool fHelp)1538 UniValue listaccounts(const UniValue& params, bool fHelp)
1539 {
1540     if (!EnsureWalletIsAvailable(fHelp))
1541         return NullUniValue;
1542 
1543     if (fHelp || params.size() > 2)
1544         throw runtime_error(
1545             "listaccounts ( minconf includeWatchonly)\n"
1546             "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
1547             "\nArguments:\n"
1548             "1. minconf          (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
1549             "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
1550             "\nResult:\n"
1551             "{                      (json object where keys are account names, and values are numeric balances\n"
1552             "  \"account\": x.xxx,  (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1553             "  ...\n"
1554             "}\n"
1555             "\nExamples:\n"
1556             "\nList account balances where there at least 1 confirmation\n"
1557             + HelpExampleCli("listaccounts", "") +
1558             "\nList account balances including zero confirmation transactions\n"
1559             + HelpExampleCli("listaccounts", "0") +
1560             "\nList account balances for 6 or more confirmations\n"
1561             + HelpExampleCli("listaccounts", "6") +
1562             "\nAs json rpc call\n"
1563             + HelpExampleRpc("listaccounts", "6")
1564         );
1565 
1566     LOCK2(cs_main, pwalletMain->cs_wallet);
1567 
1568     int nMinDepth = 1;
1569     if (params.size() > 0)
1570         nMinDepth = params[0].get_int();
1571     isminefilter includeWatchonly = ISMINE_SPENDABLE;
1572     if(params.size() > 1)
1573         if(params[1].get_bool())
1574             includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1575 
1576     map<string, CAmount> mapAccountBalances;
1577     BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1578         if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
1579             mapAccountBalances[entry.second.name] = 0;
1580     }
1581 
1582     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1583     {
1584         const CWalletTx& wtx = (*it).second;
1585         CAmount nFee;
1586         string strSentAccount;
1587         list<COutputEntry> listReceived;
1588         list<COutputEntry> listSent;
1589         int nDepth = wtx.GetDepthInMainChain();
1590         if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1591             continue;
1592         wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1593         mapAccountBalances[strSentAccount] -= nFee;
1594         BOOST_FOREACH(const COutputEntry& s, listSent)
1595             mapAccountBalances[strSentAccount] -= s.amount;
1596         if (nDepth >= nMinDepth)
1597         {
1598             BOOST_FOREACH(const COutputEntry& r, listReceived)
1599                 if (pwalletMain->mapAddressBook.count(r.destination))
1600                     mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
1601                 else
1602                     mapAccountBalances[""] += r.amount;
1603         }
1604     }
1605 
1606     const list<CAccountingEntry> & acentries = pwalletMain->laccentries;
1607     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1608         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1609 
1610     UniValue ret(UniValue::VOBJ);
1611     BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
1612         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1613     }
1614     return ret;
1615 }
1616 
listsinceblock(const UniValue & params,bool fHelp)1617 UniValue listsinceblock(const UniValue& params, bool fHelp)
1618 {
1619     if (!EnsureWalletIsAvailable(fHelp))
1620         return NullUniValue;
1621 
1622     if (fHelp)
1623         throw runtime_error(
1624             "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
1625             "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1626             "\nArguments:\n"
1627             "1. \"blockhash\"   (string, optional) The block hash to list transactions since\n"
1628             "2. target-confirmations:    (numeric, optional) The confirmations required, must be 1 or more\n"
1629             "3. includeWatchonly:        (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
1630             "\nResult:\n"
1631             "{\n"
1632             "  \"transactions\": [\n"
1633             "    \"account\":\"accountname\",       (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
1634             "    \"address\":\"zetacoinaddress\",    (string) The zetacoin address of the transaction. Not present for move transactions (category = move).\n"
1635             "    \"category\":\"send|receive\",     (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1636             "    \"amount\": x.xxx,          (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n"
1637             "                                          outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1638             "    \"vout\" : n,               (numeric) the vout value\n"
1639             "    \"fee\": x.xxx,             (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the 'send' category of transactions.\n"
1640             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1641             "    \"blockhash\": \"hashvalue\",     (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1642             "    \"blockindex\": n,          (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive' category of transactions.\n"
1643             "    \"blocktime\": xxx,         (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1644             "    \"txid\": \"transactionid\",  (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1645             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1646             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1647             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
1648             "    \"label\" : \"label\"       (string) A comment for the address/transaction, if any\n"
1649             "    \"to\": \"...\",            (string) If a comment to is associated with the transaction.\n"
1650              "  ],\n"
1651             "  \"lastblock\": \"lastblockhash\"     (string) The hash of the last block\n"
1652             "}\n"
1653             "\nExamples:\n"
1654             + HelpExampleCli("listsinceblock", "")
1655             + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1656             + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1657         );
1658 
1659     LOCK2(cs_main, pwalletMain->cs_wallet);
1660 
1661     CBlockIndex *pindex = NULL;
1662     int target_confirms = 1;
1663     isminefilter filter = ISMINE_SPENDABLE;
1664 
1665     if (params.size() > 0)
1666     {
1667         uint256 blockId;
1668 
1669         blockId.SetHex(params[0].get_str());
1670         BlockMap::iterator it = mapBlockIndex.find(blockId);
1671         if (it != mapBlockIndex.end())
1672             pindex = it->second;
1673     }
1674 
1675     if (params.size() > 1)
1676     {
1677         target_confirms = params[1].get_int();
1678 
1679         if (target_confirms < 1)
1680             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1681     }
1682 
1683     if(params.size() > 2)
1684         if(params[2].get_bool())
1685             filter = filter | ISMINE_WATCH_ONLY;
1686 
1687     int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1688 
1689     UniValue transactions(UniValue::VARR);
1690 
1691     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1692     {
1693         CWalletTx tx = (*it).second;
1694 
1695         if (depth == -1 || tx.GetDepthInMainChain() < depth)
1696             ListTransactions(tx, "*", 0, true, transactions, filter);
1697     }
1698 
1699     CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1700     uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
1701 
1702     UniValue ret(UniValue::VOBJ);
1703     ret.push_back(Pair("transactions", transactions));
1704     ret.push_back(Pair("lastblock", lastblock.GetHex()));
1705 
1706     return ret;
1707 }
1708 
gettransaction(const UniValue & params,bool fHelp)1709 UniValue gettransaction(const UniValue& params, bool fHelp)
1710 {
1711     if (!EnsureWalletIsAvailable(fHelp))
1712         return NullUniValue;
1713 
1714     if (fHelp || params.size() < 1 || params.size() > 2)
1715         throw runtime_error(
1716             "gettransaction \"txid\" ( includeWatchonly )\n"
1717             "\nGet detailed information about in-wallet transaction <txid>\n"
1718             "\nArguments:\n"
1719             "1. \"txid\"    (string, required) The transaction id\n"
1720             "2. \"includeWatchonly\"    (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
1721             "\nResult:\n"
1722             "{\n"
1723             "  \"amount\" : x.xxx,        (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
1724             "  \"confirmations\" : n,     (numeric) The number of confirmations\n"
1725             "  \"blockhash\" : \"hash\",  (string) The block hash\n"
1726             "  \"blockindex\" : xx,       (numeric) The index of the transaction in the block that includes it\n"
1727             "  \"blocktime\" : ttt,       (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1728             "  \"txid\" : \"transactionid\",   (string) The transaction id.\n"
1729             "  \"time\" : ttt,            (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1730             "  \"timereceived\" : ttt,    (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1731             "  \"bip125-replaceable\": \"yes|no|unknown\"  (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1732             "                                                   may be unknown for unconfirmed transactions not in the mempool\n"
1733             "  \"details\" : [\n"
1734             "    {\n"
1735             "      \"account\" : \"accountname\",  (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
1736             "      \"address\" : \"zetacoinaddress\",   (string) The zetacoin address involved in the transaction\n"
1737             "      \"category\" : \"send|receive\",    (string) The category, either 'send' or 'receive'\n"
1738             "      \"amount\" : x.xxx,                 (numeric) The amount in " + CURRENCY_UNIT + "\n"
1739             "      \"label\" : \"label\",              (string) A comment for the address/transaction, if any\n"
1740             "      \"vout\" : n,                       (numeric) the vout value\n"
1741             "    }\n"
1742             "    ,...\n"
1743             "  ],\n"
1744             "  \"hex\" : \"data\"         (string) Raw data for transaction\n"
1745             "}\n"
1746 
1747             "\nExamples:\n"
1748             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1749             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
1750             + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1751         );
1752 
1753     LOCK2(cs_main, pwalletMain->cs_wallet);
1754 
1755     uint256 hash;
1756     hash.SetHex(params[0].get_str());
1757 
1758     isminefilter filter = ISMINE_SPENDABLE;
1759     if(params.size() > 1)
1760         if(params[1].get_bool())
1761             filter = filter | ISMINE_WATCH_ONLY;
1762 
1763     UniValue entry(UniValue::VOBJ);
1764     if (!pwalletMain->mapWallet.count(hash))
1765         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1766     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1767 
1768     CAmount nCredit = wtx.GetCredit(filter);
1769     CAmount nDebit = wtx.GetDebit(filter);
1770     CAmount nNet = nCredit - nDebit;
1771     CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
1772 
1773     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1774     if (wtx.IsFromMe(filter))
1775         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1776 
1777     WalletTxToJSON(wtx, entry);
1778 
1779     UniValue details(UniValue::VARR);
1780     ListTransactions(wtx, "*", 0, false, details, filter);
1781     entry.push_back(Pair("details", details));
1782 
1783     string strHex = EncodeHexTx(static_cast<CTransaction>(wtx), RPCSerializationFlags());
1784     entry.push_back(Pair("hex", strHex));
1785 
1786     return entry;
1787 }
1788 
abandontransaction(const UniValue & params,bool fHelp)1789 UniValue abandontransaction(const UniValue& params, bool fHelp)
1790 {
1791     if (!EnsureWalletIsAvailable(fHelp))
1792         return NullUniValue;
1793 
1794     if (fHelp || params.size() != 1)
1795         throw runtime_error(
1796             "abandontransaction \"txid\"\n"
1797             "\nMark in-wallet transaction <txid> as abandoned\n"
1798             "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
1799             "for their inputs to be respent.  It can be used to replace \"stuck\" or evicted transactions.\n"
1800             "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
1801             "It has no effect on transactions which are already conflicted or abandoned.\n"
1802             "\nArguments:\n"
1803             "1. \"txid\"    (string, required) The transaction id\n"
1804             "\nResult:\n"
1805             "\nExamples:\n"
1806             + HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1807             + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1808         );
1809 
1810     LOCK2(cs_main, pwalletMain->cs_wallet);
1811 
1812     uint256 hash;
1813     hash.SetHex(params[0].get_str());
1814 
1815     if (!pwalletMain->mapWallet.count(hash))
1816         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1817     if (!pwalletMain->AbandonTransaction(hash))
1818         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
1819 
1820     return NullUniValue;
1821 }
1822 
1823 
backupwallet(const UniValue & params,bool fHelp)1824 UniValue backupwallet(const UniValue& params, bool fHelp)
1825 {
1826     if (!EnsureWalletIsAvailable(fHelp))
1827         return NullUniValue;
1828 
1829     if (fHelp || params.size() != 1)
1830         throw runtime_error(
1831             "backupwallet \"destination\"\n"
1832             "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n"
1833             "\nArguments:\n"
1834             "1. \"destination\"   (string) The destination directory or file\n"
1835             "\nExamples:\n"
1836             + HelpExampleCli("backupwallet", "\"backup.dat\"")
1837             + HelpExampleRpc("backupwallet", "\"backup.dat\"")
1838         );
1839 
1840     LOCK2(cs_main, pwalletMain->cs_wallet);
1841 
1842     string strDest = params[0].get_str();
1843     if (!pwalletMain->BackupWallet(strDest))
1844         throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1845 
1846     return NullUniValue;
1847 }
1848 
1849 
keypoolrefill(const UniValue & params,bool fHelp)1850 UniValue keypoolrefill(const UniValue& params, bool fHelp)
1851 {
1852     if (!EnsureWalletIsAvailable(fHelp))
1853         return NullUniValue;
1854 
1855     if (fHelp || params.size() > 1)
1856         throw runtime_error(
1857             "keypoolrefill ( newsize )\n"
1858             "\nFills the keypool."
1859             + HelpRequiringPassphrase() + "\n"
1860             "\nArguments\n"
1861             "1. newsize     (numeric, optional, default=100) The new keypool size\n"
1862             "\nExamples:\n"
1863             + HelpExampleCli("keypoolrefill", "")
1864             + HelpExampleRpc("keypoolrefill", "")
1865         );
1866 
1867     LOCK2(cs_main, pwalletMain->cs_wallet);
1868 
1869     // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1870     unsigned int kpSize = 0;
1871     if (params.size() > 0) {
1872         if (params[0].get_int() < 0)
1873             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1874         kpSize = (unsigned int)params[0].get_int();
1875     }
1876 
1877     EnsureWalletIsUnlocked();
1878     pwalletMain->TopUpKeyPool(kpSize);
1879 
1880     if (pwalletMain->GetKeyPoolSize() < kpSize)
1881         throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1882 
1883     return NullUniValue;
1884 }
1885 
1886 
LockWallet(CWallet * pWallet)1887 static void LockWallet(CWallet* pWallet)
1888 {
1889     LOCK(cs_nWalletUnlockTime);
1890     nWalletUnlockTime = 0;
1891     pWallet->Lock();
1892 }
1893 
walletpassphrase(const UniValue & params,bool fHelp)1894 UniValue walletpassphrase(const UniValue& params, bool fHelp)
1895 {
1896     if (!EnsureWalletIsAvailable(fHelp))
1897         return NullUniValue;
1898 
1899     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1900         throw runtime_error(
1901             "walletpassphrase \"passphrase\" timeout\n"
1902             "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1903             "This is needed prior to performing transactions related to private keys such as sending Zetacoins\n"
1904             "\nArguments:\n"
1905             "1. \"passphrase\"     (string, required) The wallet passphrase\n"
1906             "2. timeout            (numeric, required) The time to keep the decryption key in seconds.\n"
1907             "\nNote:\n"
1908             "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1909             "time that overrides the old one.\n"
1910             "\nExamples:\n"
1911             "\nunlock the wallet for 60 seconds\n"
1912             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1913             "\nLock the wallet again (before 60 seconds)\n"
1914             + HelpExampleCli("walletlock", "") +
1915             "\nAs json rpc call\n"
1916             + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1917         );
1918 
1919     LOCK2(cs_main, pwalletMain->cs_wallet);
1920 
1921     if (fHelp)
1922         return true;
1923     if (!pwalletMain->IsCrypted())
1924         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1925 
1926     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1927     SecureString strWalletPass;
1928     strWalletPass.reserve(100);
1929     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1930     // Alternately, find a way to make params[0] mlock()'d to begin with.
1931     strWalletPass = params[0].get_str().c_str();
1932 
1933     if (strWalletPass.length() > 0)
1934     {
1935         if (!pwalletMain->Unlock(strWalletPass))
1936             throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1937     }
1938     else
1939         throw runtime_error(
1940             "walletpassphrase <passphrase> <timeout>\n"
1941             "Stores the wallet decryption key in memory for <timeout> seconds.");
1942 
1943     pwalletMain->TopUpKeyPool();
1944 
1945     int64_t nSleepTime = params[1].get_int64();
1946     LOCK(cs_nWalletUnlockTime);
1947     nWalletUnlockTime = GetTime() + nSleepTime;
1948     RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
1949 
1950     return NullUniValue;
1951 }
1952 
1953 
walletpassphrasechange(const UniValue & params,bool fHelp)1954 UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
1955 {
1956     if (!EnsureWalletIsAvailable(fHelp))
1957         return NullUniValue;
1958 
1959     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1960         throw runtime_error(
1961             "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
1962             "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
1963             "\nArguments:\n"
1964             "1. \"oldpassphrase\"      (string) The current passphrase\n"
1965             "2. \"newpassphrase\"      (string) The new passphrase\n"
1966             "\nExamples:\n"
1967             + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1968             + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1969         );
1970 
1971     LOCK2(cs_main, pwalletMain->cs_wallet);
1972 
1973     if (fHelp)
1974         return true;
1975     if (!pwalletMain->IsCrypted())
1976         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1977 
1978     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1979     // Alternately, find a way to make params[0] mlock()'d to begin with.
1980     SecureString strOldWalletPass;
1981     strOldWalletPass.reserve(100);
1982     strOldWalletPass = params[0].get_str().c_str();
1983 
1984     SecureString strNewWalletPass;
1985     strNewWalletPass.reserve(100);
1986     strNewWalletPass = params[1].get_str().c_str();
1987 
1988     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1989         throw runtime_error(
1990             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1991             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1992 
1993     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1994         throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1995 
1996     return NullUniValue;
1997 }
1998 
1999 
walletlock(const UniValue & params,bool fHelp)2000 UniValue walletlock(const UniValue& params, bool fHelp)
2001 {
2002     if (!EnsureWalletIsAvailable(fHelp))
2003         return NullUniValue;
2004 
2005     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
2006         throw runtime_error(
2007             "walletlock\n"
2008             "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
2009             "After calling this method, you will need to call walletpassphrase again\n"
2010             "before being able to call any methods which require the wallet to be unlocked.\n"
2011             "\nExamples:\n"
2012             "\nSet the passphrase for 2 minutes to perform a transaction\n"
2013             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
2014             "\nPerform a send (requires passphrase set)\n"
2015             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
2016             "\nClear the passphrase since we are done before 2 minutes is up\n"
2017             + HelpExampleCli("walletlock", "") +
2018             "\nAs json rpc call\n"
2019             + HelpExampleRpc("walletlock", "")
2020         );
2021 
2022     LOCK2(cs_main, pwalletMain->cs_wallet);
2023 
2024     if (fHelp)
2025         return true;
2026     if (!pwalletMain->IsCrypted())
2027         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
2028 
2029     {
2030         LOCK(cs_nWalletUnlockTime);
2031         pwalletMain->Lock();
2032         nWalletUnlockTime = 0;
2033     }
2034 
2035     return NullUniValue;
2036 }
2037 
2038 
encryptwallet(const UniValue & params,bool fHelp)2039 UniValue encryptwallet(const UniValue& params, bool fHelp)
2040 {
2041     if (!EnsureWalletIsAvailable(fHelp))
2042         return NullUniValue;
2043 
2044     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
2045         throw runtime_error(
2046             "encryptwallet \"passphrase\"\n"
2047             "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
2048             "After this, any calls that interact with private keys such as sending or signing \n"
2049             "will require the passphrase to be set prior the making these calls.\n"
2050             "Use the walletpassphrase call for this, and then walletlock call.\n"
2051             "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
2052             "Note that this will shutdown the server.\n"
2053             "\nArguments:\n"
2054             "1. \"passphrase\"    (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
2055             "\nExamples:\n"
2056             "\nEncrypt you wallet\n"
2057             + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
2058             "\nNow set the passphrase to use the wallet, such as for signing or sending Zetacoin\n"
2059             + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
2060             "\nNow we can so something like sign\n"
2061             + HelpExampleCli("signmessage", "\"zetacoinaddress\" \"test message\"") +
2062             "\nNow lock the wallet again by removing the passphrase\n"
2063             + HelpExampleCli("walletlock", "") +
2064             "\nAs a json rpc call\n"
2065             + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
2066         );
2067 
2068     LOCK2(cs_main, pwalletMain->cs_wallet);
2069 
2070     if (fHelp)
2071         return true;
2072     if (pwalletMain->IsCrypted())
2073         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
2074 
2075     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2076     // Alternately, find a way to make params[0] mlock()'d to begin with.
2077     SecureString strWalletPass;
2078     strWalletPass.reserve(100);
2079     strWalletPass = params[0].get_str().c_str();
2080 
2081     if (strWalletPass.length() < 1)
2082         throw runtime_error(
2083             "encryptwallet <passphrase>\n"
2084             "Encrypts the wallet with <passphrase>.");
2085 
2086     if (!pwalletMain->EncryptWallet(strWalletPass))
2087         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
2088 
2089     // BDB seems to have a bad habit of writing old data into
2090     // slack space in .dat files; that is bad if the old data is
2091     // unencrypted private keys. So:
2092     StartShutdown();
2093     return "wallet encrypted; Zetacoin server stopping, restart to run with encrypted wallet. The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup.";
2094 }
2095 
lockunspent(const UniValue & params,bool fHelp)2096 UniValue lockunspent(const UniValue& params, bool fHelp)
2097 {
2098     if (!EnsureWalletIsAvailable(fHelp))
2099         return NullUniValue;
2100 
2101     if (fHelp || params.size() < 1 || params.size() > 2)
2102         throw runtime_error(
2103             "lockunspent unlock ([{\"txid\":\"txid\",\"vout\":n},...])\n"
2104             "\nUpdates list of temporarily unspendable outputs.\n"
2105             "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
2106             "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
2107             "A locked transaction output will not be chosen by automatic coin selection, when spending Zetacoins.\n"
2108             "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2109             "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2110             "Also see the listunspent call\n"
2111             "\nArguments:\n"
2112             "1. unlock            (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
2113             "2. \"transactions\"  (string, optional) A json array of objects. Each object the txid (string) vout (numeric)\n"
2114             "     [           (json array of json objects)\n"
2115             "       {\n"
2116             "         \"txid\":\"id\",    (string) The transaction id\n"
2117             "         \"vout\": n         (numeric) The output number\n"
2118             "       }\n"
2119             "       ,...\n"
2120             "     ]\n"
2121 
2122             "\nResult:\n"
2123             "true|false    (boolean) Whether the command was successful or not\n"
2124 
2125             "\nExamples:\n"
2126             "\nList the unspent transactions\n"
2127             + HelpExampleCli("listunspent", "") +
2128             "\nLock an unspent transaction\n"
2129             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2130             "\nList the locked transactions\n"
2131             + HelpExampleCli("listlockunspent", "") +
2132             "\nUnlock the transaction again\n"
2133             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2134             "\nAs a json rpc call\n"
2135             + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2136         );
2137 
2138     LOCK2(cs_main, pwalletMain->cs_wallet);
2139 
2140     if (params.size() == 1)
2141         RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL));
2142     else
2143         RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
2144 
2145     bool fUnlock = params[0].get_bool();
2146 
2147     if (params.size() == 1) {
2148         if (fUnlock)
2149             pwalletMain->UnlockAllCoins();
2150         return true;
2151     }
2152 
2153     UniValue outputs = params[1].get_array();
2154     for (unsigned int idx = 0; idx < outputs.size(); idx++) {
2155         const UniValue& output = outputs[idx];
2156         if (!output.isObject())
2157             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
2158         const UniValue& o = output.get_obj();
2159 
2160         RPCTypeCheckObj(o,
2161             {
2162                 {"txid", UniValueType(UniValue::VSTR)},
2163                 {"vout", UniValueType(UniValue::VNUM)},
2164             });
2165 
2166         string txid = find_value(o, "txid").get_str();
2167         if (!IsHex(txid))
2168             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
2169 
2170         int nOutput = find_value(o, "vout").get_int();
2171         if (nOutput < 0)
2172             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
2173 
2174         COutPoint outpt(uint256S(txid), nOutput);
2175 
2176         if (fUnlock)
2177             pwalletMain->UnlockCoin(outpt);
2178         else
2179             pwalletMain->LockCoin(outpt);
2180     }
2181 
2182     return true;
2183 }
2184 
listlockunspent(const UniValue & params,bool fHelp)2185 UniValue listlockunspent(const UniValue& params, bool fHelp)
2186 {
2187     if (!EnsureWalletIsAvailable(fHelp))
2188         return NullUniValue;
2189 
2190     if (fHelp || params.size() > 0)
2191         throw runtime_error(
2192             "listlockunspent\n"
2193             "\nReturns list of temporarily unspendable outputs.\n"
2194             "See the lockunspent call to lock and unlock transactions for spending.\n"
2195             "\nResult:\n"
2196             "[\n"
2197             "  {\n"
2198             "    \"txid\" : \"transactionid\",     (string) The transaction id locked\n"
2199             "    \"vout\" : n                      (numeric) The vout value\n"
2200             "  }\n"
2201             "  ,...\n"
2202             "]\n"
2203             "\nExamples:\n"
2204             "\nList the unspent transactions\n"
2205             + HelpExampleCli("listunspent", "") +
2206             "\nLock an unspent transaction\n"
2207             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2208             "\nList the locked transactions\n"
2209             + HelpExampleCli("listlockunspent", "") +
2210             "\nUnlock the transaction again\n"
2211             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2212             "\nAs a json rpc call\n"
2213             + HelpExampleRpc("listlockunspent", "")
2214         );
2215 
2216     LOCK2(cs_main, pwalletMain->cs_wallet);
2217 
2218     vector<COutPoint> vOutpts;
2219     pwalletMain->ListLockedCoins(vOutpts);
2220 
2221     UniValue ret(UniValue::VARR);
2222 
2223     BOOST_FOREACH(COutPoint &outpt, vOutpts) {
2224         UniValue o(UniValue::VOBJ);
2225 
2226         o.push_back(Pair("txid", outpt.hash.GetHex()));
2227         o.push_back(Pair("vout", (int)outpt.n));
2228         ret.push_back(o);
2229     }
2230 
2231     return ret;
2232 }
2233 
settxfee(const UniValue & params,bool fHelp)2234 UniValue settxfee(const UniValue& params, bool fHelp)
2235 {
2236     if (!EnsureWalletIsAvailable(fHelp))
2237         return NullUniValue;
2238 
2239     if (fHelp || params.size() < 1 || params.size() > 1)
2240         throw runtime_error(
2241             "settxfee amount\n"
2242             "\nSet the transaction fee per kB. Overwrites the paytxfee parameter.\n"
2243             "\nArguments:\n"
2244             "1. amount         (numeric or string, required) The transaction fee in " + CURRENCY_UNIT + "/kB\n"
2245             "\nResult\n"
2246             "true|false        (boolean) Returns true if successful\n"
2247             "\nExamples:\n"
2248             + HelpExampleCli("settxfee", "0.00001")
2249             + HelpExampleRpc("settxfee", "0.00001")
2250         );
2251 
2252     LOCK2(cs_main, pwalletMain->cs_wallet);
2253 
2254     // Amount
2255     CAmount nAmount = AmountFromValue(params[0]);
2256 
2257     payTxFee = CFeeRate(nAmount, 1000);
2258     return true;
2259 }
2260 
getwalletinfo(const UniValue & params,bool fHelp)2261 UniValue getwalletinfo(const UniValue& params, bool fHelp)
2262 {
2263     if (!EnsureWalletIsAvailable(fHelp))
2264         return NullUniValue;
2265 
2266     if (fHelp || params.size() != 0)
2267         throw runtime_error(
2268             "getwalletinfo\n"
2269             "Returns an object containing various wallet state info.\n"
2270             "\nResult:\n"
2271             "{\n"
2272             "  \"walletversion\": xxxxx,       (numeric) the wallet version\n"
2273             "  \"balance\": xxxxxxx,           (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2274             "  \"unconfirmed_balance\": xxx,   (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2275             "  \"immature_balance\": xxxxxx,   (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
2276             "  \"txcount\": xxxxxxx,           (numeric) the total number of transactions in the wallet\n"
2277             "  \"keypoololdest\": xxxxxx,      (numeric) the timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool\n"
2278             "  \"keypoolsize\": xxxx,          (numeric) how many new keys are pre-generated\n"
2279             "  \"unlocked_until\": ttt,        (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
2280             "  \"paytxfee\": x.xxxx,           (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
2281             "  \"hdmasterkeyid\": \"<hash160>\", (string) the Hash160 of the HD master pubkey\n"
2282             "}\n"
2283             "\nExamples:\n"
2284             + HelpExampleCli("getwalletinfo", "")
2285             + HelpExampleRpc("getwalletinfo", "")
2286         );
2287 
2288     LOCK2(cs_main, pwalletMain->cs_wallet);
2289 
2290     UniValue obj(UniValue::VOBJ);
2291     obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
2292     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
2293     obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
2294     obj.push_back(Pair("immature_balance",    ValueFromAmount(pwalletMain->GetImmatureBalance())));
2295     obj.push_back(Pair("txcount",       (int)pwalletMain->mapWallet.size()));
2296     obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
2297     obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
2298     if (pwalletMain->IsCrypted())
2299         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
2300     obj.push_back(Pair("paytxfee",      ValueFromAmount(payTxFee.GetFeePerK())));
2301     CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID;
2302     if (!masterKeyID.IsNull())
2303          obj.push_back(Pair("hdmasterkeyid", masterKeyID.GetHex()));
2304     return obj;
2305 }
2306 
resendwallettransactions(const UniValue & params,bool fHelp)2307 UniValue resendwallettransactions(const UniValue& params, bool fHelp)
2308 {
2309     if (!EnsureWalletIsAvailable(fHelp))
2310         return NullUniValue;
2311 
2312     if (fHelp || params.size() != 0)
2313         throw runtime_error(
2314             "resendwallettransactions\n"
2315             "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
2316             "Intended only for testing; the wallet code periodically re-broadcasts\n"
2317             "automatically.\n"
2318             "Returns array of transaction ids that were re-broadcast.\n"
2319             );
2320 
2321     LOCK2(cs_main, pwalletMain->cs_wallet);
2322 
2323     std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
2324     UniValue result(UniValue::VARR);
2325     BOOST_FOREACH(const uint256& txid, txids)
2326     {
2327         result.push_back(txid.ToString());
2328     }
2329     return result;
2330 }
2331 
listunspent(const UniValue & params,bool fHelp)2332 UniValue listunspent(const UniValue& params, bool fHelp)
2333 {
2334     if (!EnsureWalletIsAvailable(fHelp))
2335         return NullUniValue;
2336 
2337     if (fHelp || params.size() > 3)
2338         throw runtime_error(
2339             "listunspent ( minconf maxconf  [\"address\",...] )\n"
2340             "\nReturns array of unspent transaction outputs\n"
2341             "with between minconf and maxconf (inclusive) confirmations.\n"
2342             "Optionally filter to only include txouts paid to specified addresses.\n"
2343             "\nArguments:\n"
2344             "1. minconf          (numeric, optional, default=1) The minimum confirmations to filter\n"
2345             "2. maxconf          (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2346             "3. \"addresses\"    (string) A json array of zetacoin addresses to filter\n"
2347             "    [\n"
2348             "      \"address\"   (string) zetacoin address\n"
2349             "      ,...\n"
2350             "    ]\n"
2351             "\nResult\n"
2352             "[                   (array of json object)\n"
2353             "  {\n"
2354             "    \"txid\" : \"txid\",          (string) the transaction id \n"
2355             "    \"vout\" : n,               (numeric) the vout value\n"
2356             "    \"address\" : \"address\",    (string) the zetacoin address\n"
2357             "    \"account\" : \"account\",    (string) DEPRECATED. The associated account, or \"\" for the default account\n"
2358             "    \"scriptPubKey\" : \"key\",   (string) the script key\n"
2359             "    \"amount\" : x.xxx,         (numeric) the transaction amount in " + CURRENCY_UNIT + "\n"
2360             "    \"confirmations\" : n,      (numeric) The number of confirmations\n"
2361             "    \"redeemScript\" : n        (string) The redeemScript if scriptPubKey is P2SH\n"
2362             "    \"spendable\" : xxx,        (bool) Whether we have the private keys to spend this output\n"
2363             "    \"solvable\" : xxx          (bool) Whether we know how to spend this output, ignoring the lack of keys\n"
2364             "  }\n"
2365             "  ,...\n"
2366             "]\n"
2367 
2368             "\nExamples\n"
2369             + HelpExampleCli("listunspent", "")
2370             + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2371             + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2372         );
2373 
2374     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR));
2375 
2376     int nMinDepth = 1;
2377     if (params.size() > 0)
2378         nMinDepth = params[0].get_int();
2379 
2380     int nMaxDepth = 9999999;
2381     if (params.size() > 1)
2382         nMaxDepth = params[1].get_int();
2383 
2384     set<CBitcoinAddress> setAddress;
2385     if (params.size() > 2) {
2386         UniValue inputs = params[2].get_array();
2387         for (unsigned int idx = 0; idx < inputs.size(); idx++) {
2388             const UniValue& input = inputs[idx];
2389             CBitcoinAddress address(input.get_str());
2390             if (!address.IsValid())
2391                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zetacoin address: ")+input.get_str());
2392             if (setAddress.count(address))
2393                 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
2394            setAddress.insert(address);
2395         }
2396     }
2397 
2398     UniValue results(UniValue::VARR);
2399     vector<COutput> vecOutputs;
2400     assert(pwalletMain != NULL);
2401     LOCK2(cs_main, pwalletMain->cs_wallet);
2402     pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
2403     BOOST_FOREACH(const COutput& out, vecOutputs) {
2404         if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
2405             continue;
2406 
2407         CTxDestination address;
2408         const CScript& scriptPubKey = out.tx->vout[out.i].scriptPubKey;
2409         bool fValidAddress = ExtractDestination(scriptPubKey, address);
2410 
2411         if (setAddress.size() && (!fValidAddress || !setAddress.count(address)))
2412             continue;
2413 
2414         UniValue entry(UniValue::VOBJ);
2415         entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
2416         entry.push_back(Pair("vout", out.i));
2417 
2418         if (fValidAddress) {
2419             entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
2420 
2421             if (pwalletMain->mapAddressBook.count(address))
2422                 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
2423 
2424             if (scriptPubKey.IsPayToScriptHash()) {
2425                 const CScriptID& hash = boost::get<CScriptID>(address);
2426                 CScript redeemScript;
2427                 if (pwalletMain->GetCScript(hash, redeemScript))
2428                     entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
2429             }
2430         }
2431 
2432         entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
2433         entry.push_back(Pair("amount", ValueFromAmount(out.tx->vout[out.i].nValue)));
2434         entry.push_back(Pair("confirmations", out.nDepth));
2435         entry.push_back(Pair("spendable", out.fSpendable));
2436         entry.push_back(Pair("solvable", out.fSolvable));
2437         results.push_back(entry);
2438     }
2439 
2440     return results;
2441 }
2442 
fundrawtransaction(const UniValue & params,bool fHelp)2443 UniValue fundrawtransaction(const UniValue& params, bool fHelp)
2444 {
2445     if (!EnsureWalletIsAvailable(fHelp))
2446         return NullUniValue;
2447 
2448     if (fHelp || params.size() < 1 || params.size() > 2)
2449         throw runtime_error(
2450                             "fundrawtransaction \"hexstring\" ( options )\n"
2451                             "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
2452                             "This will not modify existing inputs, and will add one change output to the outputs.\n"
2453                             "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
2454                             "The inputs added will not be signed, use signrawtransaction for that.\n"
2455                             "Note that all existing inputs must have their previous output transaction be in the wallet.\n"
2456                             "Note that all inputs selected must be of standard form and P2SH scripts must be\n"
2457                             "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
2458                             "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
2459                             "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
2460                             "\nArguments:\n"
2461                             "1. \"hexstring\"           (string, required) The hex string of the raw transaction\n"
2462                             "2. options               (object, optional)\n"
2463                             "   {\n"
2464                             "     \"changeAddress\"     (string, optional, default pool address) The Zetacoin address to receive the change\n"
2465                             "     \"changePosition\"    (numeric, optional, default random) The index of the change output\n"
2466                             "     \"includeWatching\"   (boolean, optional, default false) Also select inputs which are watch only\n"
2467                             "     \"lockUnspents\"      (boolean, optional, default false) Lock selected unspent outputs\n"
2468                             "     \"feeRate\"           (numeric, optional, default not set: makes wallet determine the fee) Set a specific feerate (" + CURRENCY_UNIT + " per KB)\n"
2469                             "   }\n"
2470                             "                         for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
2471                             "\nResult:\n"
2472                             "{\n"
2473                             "  \"hex\":       \"value\", (string)  The resulting raw transaction (hex-encoded string)\n"
2474                             "  \"fee\":       n,         (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n"
2475                             "  \"changepos\": n          (numeric) The position of the added change output, or -1\n"
2476                             "}\n"
2477                             "\"hex\"             \n"
2478                             "\nExamples:\n"
2479                             "\nCreate a transaction with no inputs\n"
2480                             + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
2481                             "\nAdd sufficient unsigned inputs to meet the output value\n"
2482                             + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
2483                             "\nSign the transaction\n"
2484                             + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
2485                             "\nSend the transaction\n"
2486                             + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
2487                             );
2488 
2489     RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
2490 
2491     CTxDestination changeAddress = CNoDestination();
2492     int changePosition = -1;
2493     bool includeWatching = false;
2494     bool lockUnspents = false;
2495     CFeeRate feeRate = CFeeRate(0);
2496     bool overrideEstimatedFeerate = false;
2497 
2498     if (params.size() > 1) {
2499       if (params[1].type() == UniValue::VBOOL) {
2500         // backward compatibility bool only fallback
2501         includeWatching = params[1].get_bool();
2502       }
2503       else {
2504         RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
2505 
2506         UniValue options = params[1];
2507 
2508         RPCTypeCheckObj(options,
2509             {
2510                 {"changeAddress", UniValueType(UniValue::VSTR)},
2511                 {"changePosition", UniValueType(UniValue::VNUM)},
2512                 {"includeWatching", UniValueType(UniValue::VBOOL)},
2513                 {"lockUnspents", UniValueType(UniValue::VBOOL)},
2514                 {"feeRate", UniValueType()}, // will be checked below
2515             },
2516             true, true);
2517 
2518         if (options.exists("changeAddress")) {
2519             CBitcoinAddress address(options["changeAddress"].get_str());
2520 
2521             if (!address.IsValid())
2522                 throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid Zetacoin address");
2523 
2524             changeAddress = address.Get();
2525         }
2526 
2527         if (options.exists("changePosition"))
2528             changePosition = options["changePosition"].get_int();
2529 
2530         if (options.exists("includeWatching"))
2531             includeWatching = options["includeWatching"].get_bool();
2532 
2533         if (options.exists("lockUnspents"))
2534             lockUnspents = options["lockUnspents"].get_bool();
2535 
2536         if (options.exists("feeRate"))
2537         {
2538             feeRate = CFeeRate(AmountFromValue(options["feeRate"]));
2539             overrideEstimatedFeerate = true;
2540         }
2541       }
2542     }
2543 
2544     // parse hex string from parameter
2545     CTransaction origTx;
2546     if (!DecodeHexTx(origTx, params[0].get_str(), true))
2547         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
2548 
2549     if (origTx.vout.size() == 0)
2550         throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
2551 
2552     if (changePosition != -1 && (changePosition < 0 || (unsigned int)changePosition > origTx.vout.size()))
2553         throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
2554 
2555     CMutableTransaction tx(origTx);
2556     CAmount nFeeOut;
2557     string strFailReason;
2558 
2559     if(!pwalletMain->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress))
2560         throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
2561 
2562     UniValue result(UniValue::VOBJ);
2563     result.push_back(Pair("hex", EncodeHexTx(tx)));
2564     result.push_back(Pair("changepos", changePosition));
2565     result.push_back(Pair("fee", ValueFromAmount(nFeeOut)));
2566 
2567     return result;
2568 }
2569 
2570 extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
2571 extern UniValue importprivkey(const UniValue& params, bool fHelp);
2572 extern UniValue importaddress(const UniValue& params, bool fHelp);
2573 extern UniValue importpubkey(const UniValue& params, bool fHelp);
2574 extern UniValue dumpwallet(const UniValue& params, bool fHelp);
2575 extern UniValue importwallet(const UniValue& params, bool fHelp);
2576 extern UniValue importprunedfunds(const UniValue& params, bool fHelp);
2577 extern UniValue removeprunedfunds(const UniValue& params, bool fHelp);
2578 
2579 static const CRPCCommand commands[] =
2580 { //  category              name                        actor (function)           okSafeMode
2581     //  --------------------- ------------------------    -----------------------    ----------
2582     { "rawtransactions",    "fundrawtransaction",       &fundrawtransaction,       false },
2583     { "hidden",             "resendwallettransactions", &resendwallettransactions, true  },
2584     { "wallet",             "abandontransaction",       &abandontransaction,       false },
2585     { "wallet",             "addmultisigaddress",       &addmultisigaddress,       true  },
2586     { "wallet",             "addwitnessaddress",        &addwitnessaddress,        true  },
2587     { "wallet",             "backupwallet",             &backupwallet,             true  },
2588     { "wallet",             "dumpprivkey",              &dumpprivkey,              true  },
2589     { "wallet",             "dumpwallet",               &dumpwallet,               true  },
2590     { "wallet",             "encryptwallet",            &encryptwallet,            true  },
2591     { "wallet",             "getaccountaddress",        &getaccountaddress,        true  },
2592     { "wallet",             "getaccount",               &getaccount,               true  },
2593     { "wallet",             "getaddressesbyaccount",    &getaddressesbyaccount,    true  },
2594     { "wallet",             "getbalance",               &getbalance,               false },
2595     { "wallet",             "getnewaddress",            &getnewaddress,            true  },
2596     { "wallet",             "getrawchangeaddress",      &getrawchangeaddress,      true  },
2597     { "wallet",             "getreceivedbyaccount",     &getreceivedbyaccount,     false },
2598     { "wallet",             "getreceivedbyaddress",     &getreceivedbyaddress,     false },
2599     { "wallet",             "gettransaction",           &gettransaction,           false },
2600     { "wallet",             "getunconfirmedbalance",    &getunconfirmedbalance,    false },
2601     { "wallet",             "getwalletinfo",            &getwalletinfo,            false },
2602     { "wallet",             "importprivkey",            &importprivkey,            true  },
2603     { "wallet",             "importwallet",             &importwallet,             true  },
2604     { "wallet",             "importaddress",            &importaddress,            true  },
2605     { "wallet",             "importprunedfunds",        &importprunedfunds,        true  },
2606     { "wallet",             "importpubkey",             &importpubkey,             true  },
2607     { "wallet",             "keypoolrefill",            &keypoolrefill,            true  },
2608     { "wallet",             "listaccounts",             &listaccounts,             false },
2609     { "wallet",             "listaddressgroupings",     &listaddressgroupings,     false },
2610     { "wallet",             "listlockunspent",          &listlockunspent,          false },
2611     { "wallet",             "listreceivedbyaccount",    &listreceivedbyaccount,    false },
2612     { "wallet",             "listreceivedbyaddress",    &listreceivedbyaddress,    false },
2613     { "wallet",             "listsinceblock",           &listsinceblock,           false },
2614     { "wallet",             "listtransactions",         &listtransactions,         false },
2615     { "wallet",             "listunspent",              &listunspent,              false },
2616     { "wallet",             "lockunspent",              &lockunspent,              true  },
2617     { "wallet",             "move",                     &movecmd,                  false },
2618     { "wallet",             "sendfrom",                 &sendfrom,                 false },
2619     { "wallet",             "sendmany",                 &sendmany,                 false },
2620     { "wallet",             "sendtoaddress",            &sendtoaddress,            false },
2621     { "wallet",             "setaccount",               &setaccount,               true  },
2622     { "wallet",             "settxfee",                 &settxfee,                 true  },
2623     { "wallet",             "signmessage",              &signmessage,              true  },
2624     { "wallet",             "walletlock",               &walletlock,               true  },
2625     { "wallet",             "walletpassphrasechange",   &walletpassphrasechange,   true  },
2626     { "wallet",             "walletpassphrase",         &walletpassphrase,         true  },
2627     { "wallet",             "removeprunedfunds",        &removeprunedfunds,        true  },
2628 };
2629 
RegisterWalletRPCCommands(CRPCTable & tableRPC)2630 void RegisterWalletRPCCommands(CRPCTable &tableRPC)
2631 {
2632     for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
2633         tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
2634 }
2635