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 ¶ms, 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