Update License in File Headers
[bitcoinplatinum.git] / src / bitcoinrpc.cpp
blobb32ca9f15d8638b4e7619f5c74753261bf5ff15a
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #include "main.h"
7 #include "wallet.h"
8 #include "db.h"
9 #include "walletdb.h"
10 #include "net.h"
11 #include "init.h"
12 #include "ui_interface.h"
13 #include "bitcoinrpc.h"
15 #undef printf
16 #include <boost/asio.hpp>
17 #include <boost/filesystem.hpp>
18 #include <boost/iostreams/concepts.hpp>
19 #include <boost/iostreams/stream.hpp>
20 #include <boost/algorithm/string.hpp>
21 #include <boost/lexical_cast.hpp>
22 #include <boost/asio/ssl.hpp>
23 #include <boost/filesystem/fstream.hpp>
24 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
26 #define printf OutputDebugStringF
27 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
28 // precompiled in headers.h. The problem might be when the pch file goes over
29 // a certain size around 145MB. If we need access to json_spirit outside this
30 // file, we could use the compiled json_spirit option.
32 using namespace std;
33 using namespace boost;
34 using namespace boost::asio;
35 using namespace json_spirit;
37 void ThreadRPCServer2(void* parg);
39 static std::string strRPCUserColonPass;
41 static int64 nWalletUnlockTime;
42 static CCriticalSection cs_nWalletUnlockTime;
44 extern Value dumpprivkey(const Array& params, bool fHelp);
45 extern Value importprivkey(const Array& params, bool fHelp);
47 const Object emptyobj;
49 void ThreadRPCServer3(void* parg);
51 Object JSONRPCError(int code, const string& message)
53 Object error;
54 error.push_back(Pair("code", code));
55 error.push_back(Pair("message", message));
56 return error;
59 double GetDifficulty(const CBlockIndex* blockindex = NULL)
61 // Floating point number that is a multiple of the minimum difficulty,
62 // minimum difficulty = 1.0.
63 if (blockindex == NULL)
65 if (pindexBest == NULL)
66 return 1.0;
67 else
68 blockindex = pindexBest;
71 int nShift = (blockindex->nBits >> 24) & 0xff;
73 double dDiff =
74 (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
76 while (nShift < 29)
78 dDiff *= 256.0;
79 nShift++;
81 while (nShift > 29)
83 dDiff /= 256.0;
84 nShift--;
87 return dDiff;
91 int64 AmountFromValue(const Value& value)
93 double dAmount = value.get_real();
94 if (dAmount <= 0.0 || dAmount > 21000000.0)
95 throw JSONRPCError(-3, "Invalid amount");
96 int64 nAmount = roundint64(dAmount * COIN);
97 if (!MoneyRange(nAmount))
98 throw JSONRPCError(-3, "Invalid amount");
99 return nAmount;
102 Value ValueFromAmount(int64 amount)
104 return (double)amount / (double)COIN;
107 std::string
108 HexBits(unsigned int nBits)
110 union {
111 int32_t nBits;
112 char cBits[4];
113 } uBits;
114 uBits.nBits = htonl((int32_t)nBits);
115 return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
118 enum DecomposeMode {
119 DM_NONE = 0,
120 DM_HASH,
121 DM_HEX,
122 DM_ASM,
123 DM_OBJ,
126 enum DecomposeMode
127 FindDecompose(const Object& decompositions, const char* pcType, const char* pcDefault)
129 Value val = find_value(decompositions, pcType);
130 std::string strDecompose = (val.type() == null_type) ? pcDefault : val.get_str();
132 if (strDecompose == "no")
133 return DM_NONE;
134 if (strDecompose == "hash")
135 return DM_HASH;
136 if (strDecompose == "hex")
137 return DM_HEX;
138 if (strDecompose == "asm")
139 return DM_ASM;
140 if (strDecompose == "obj")
141 return DM_OBJ;
142 throw JSONRPCError(-18, "Invalid decomposition");
145 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
147 int confirms = wtx.GetDepthInMainChain();
148 entry.push_back(Pair("confirmations", confirms));
149 if (confirms)
151 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
152 entry.push_back(Pair("blockindex", wtx.nIndex));
154 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
155 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
156 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
157 entry.push_back(Pair(item.first, item.second));
160 void
161 ScriptSigToJSON(const CTxIn& txin, Object& out)
163 out.push_back(Pair("asm", txin.scriptSig.ToString()));
164 out.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
166 CTransaction txprev;
167 uint256 hashTxprevBlock;
168 if (!GetTransaction(txin.prevout.hash, txprev, hashTxprevBlock))
169 return;
171 txnouttype type;
172 vector<CBitcoinAddress> addresses;
173 int nRequired;
175 if (!ExtractAddresses(txprev.vout[txin.prevout.n].scriptPubKey, type,
176 addresses, nRequired))
178 out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
179 return;
182 out.push_back(Pair("type", GetTxnOutputType(type)));
183 if (type == TX_MULTISIG)
185 // TODO: Need to handle this specially since not all input addresses are required...
186 return;
189 Array a;
190 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
191 a.push_back(addr.ToString());
192 out.push_back(Pair("addresses", a));
195 void
196 ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
198 txnouttype type;
199 vector<CBitcoinAddress> addresses;
200 int nRequired;
202 out.push_back(Pair("asm", scriptPubKey.ToString()));
203 out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
205 if (!ExtractAddresses(scriptPubKey, type, addresses, nRequired))
207 out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
208 return;
211 out.push_back(Pair("reqSigs", nRequired));
212 out.push_back(Pair("type", GetTxnOutputType(type)));
214 Array a;
215 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
216 a.push_back(addr.ToString());
217 out.push_back(Pair("addresses", a));
220 void TxToJSON(const CTransaction &tx, Object& entry, const Object& decompositions)
222 entry.push_back(Pair("version", tx.nVersion));
223 entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
224 entry.push_back(Pair("size", (boost::int64_t)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
226 enum DecomposeMode decomposeScript = FindDecompose(decompositions, "script", "asm");
228 Array vin;
229 BOOST_FOREACH(const CTxIn& txin, tx.vin)
231 Object in;
232 if (tx.IsCoinBase())
233 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
234 else
236 Object prevout;
237 prevout.push_back(Pair("hash", txin.prevout.hash.GetHex()));
238 prevout.push_back(Pair("n", (boost::int64_t)txin.prevout.n));
239 in.push_back(Pair("prevout", prevout));
240 switch (decomposeScript) {
241 case DM_NONE:
242 break;
243 case DM_HEX:
244 in.push_back(Pair("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
245 break;
246 case DM_ASM:
247 in.push_back(Pair("scriptSig", txin.scriptSig.ToString()));
248 break;
249 case DM_OBJ:
251 Object o;
252 ScriptSigToJSON(txin, o);
253 in.push_back(Pair("scriptSig", o));
254 break;
256 default:
257 throw JSONRPCError(-18, "Invalid script decomposition");
260 in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence));
261 vin.push_back(in);
263 entry.push_back(Pair("vin", vin));
264 Array vout;
265 BOOST_FOREACH(const CTxOut& txout, tx.vout)
267 Object out;
268 out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
269 switch (decomposeScript) {
270 case DM_NONE:
271 break;
272 case DM_HEX:
273 out.push_back(Pair("scriptPubKey", HexStr(txout.scriptPubKey.begin(), txout.scriptPubKey.end())));
274 break;
275 case DM_ASM:
276 out.push_back(Pair("scriptPubKey", txout.scriptPubKey.ToString()));
277 break;
278 case DM_OBJ:
280 Object o;
281 ScriptPubKeyToJSON(txout.scriptPubKey, o);
282 out.push_back(Pair("scriptPubKey", o));
283 break;
285 default:
286 throw JSONRPCError(-18, "Invalid script decomposition");
288 vout.push_back(out);
290 entry.push_back(Pair("vout", vout));
293 void AnyTxToJSON(const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions);
295 string AccountFromValue(const Value& value)
297 string strAccount = value.get_str();
298 if (strAccount == "*")
299 throw JSONRPCError(-11, "Invalid account name");
300 return strAccount;
303 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, const Object& decompositions)
305 Object result;
306 result.push_back(Pair("hash", block.GetHash().GetHex()));
307 CMerkleTx txGen(block.vtx[0]);
308 txGen.SetMerkleBranch(&block);
309 result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain()));
310 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
311 result.push_back(Pair("height", blockindex->nHeight));
312 result.push_back(Pair("version", block.nVersion));
313 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
314 result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
315 result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
316 result.push_back(Pair("bits", HexBits(block.nBits)));
317 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
319 enum DecomposeMode decomposeTxn = FindDecompose(decompositions, "tx", "hash");
320 if (decomposeTxn)
322 Array txs;
323 switch (decomposeTxn) {
324 case DM_OBJ:
325 BOOST_FOREACH (const CTransaction&tx, block.vtx)
327 Object entry;
328 AnyTxToJSON(tx.GetHash(), &tx, entry, decompositions);
329 txs.push_back(entry);
331 break;
332 case DM_HEX:
333 BOOST_FOREACH (const CTransaction&tx, block.vtx)
335 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
336 ssTx << tx;
338 txs.push_back(HexStr(ssTx.begin(), ssTx.end()));
340 break;
341 case DM_HASH:
342 BOOST_FOREACH (const CTransaction&tx, block.vtx)
343 txs.push_back(tx.GetHash().GetHex());
344 break;
345 default:
346 throw JSONRPCError(-18, "Invalid transaction decomposition");
348 result.push_back(Pair("tx", txs));
351 if (blockindex->pprev)
352 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
353 if (blockindex->pnext)
354 result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
355 return result;
362 /// Note: This interface may still be subject to change.
365 string CRPCTable::help(string strCommand) const
367 string strRet;
368 set<rpcfn_type> setDone;
369 for (map<string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
371 const CRPCCommand *pcmd = mi->second;
372 string strMethod = mi->first;
373 // We already filter duplicates, but these deprecated screw up the sort order
374 if (strMethod == "getamountreceived" ||
375 strMethod == "getallreceived" ||
376 strMethod == "getblocknumber" || // deprecated
377 (strMethod.find("label") != string::npos))
378 continue;
379 if (strCommand != "" && strMethod != strCommand)
380 continue;
383 Array params;
384 rpcfn_type pfn = pcmd->actor;
385 if (setDone.insert(pfn).second)
386 (*pfn)(params, true);
388 catch (std::exception& e)
390 // Help text is returned in an exception
391 string strHelp = string(e.what());
392 if (strCommand == "")
393 if (strHelp.find('\n') != string::npos)
394 strHelp = strHelp.substr(0, strHelp.find('\n'));
395 strRet += strHelp + "\n";
398 if (strRet == "")
399 strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
400 strRet = strRet.substr(0,strRet.size()-1);
401 return strRet;
404 Value help(const Array& params, bool fHelp)
406 if (fHelp || params.size() > 1)
407 throw runtime_error(
408 "help [command]\n"
409 "List commands, or get help for a command.");
411 string strCommand;
412 if (params.size() > 0)
413 strCommand = params[0].get_str();
415 return tableRPC.help(strCommand);
419 Value stop(const Array& params, bool fHelp)
421 if (fHelp || params.size() != 0)
422 throw runtime_error(
423 "stop\n"
424 "Stop bitcoin server.");
425 // Shutdown will take long enough that the response should get back
426 QueueShutdown();
427 return "bitcoin server stopping";
431 Value getblockcount(const Array& params, bool fHelp)
433 if (fHelp || params.size() != 0)
434 throw runtime_error(
435 "getblockcount\n"
436 "Returns the number of blocks in the longest block chain.");
438 return nBestHeight;
442 // deprecated
443 Value getblocknumber(const Array& params, bool fHelp)
445 if (fHelp || params.size() != 0)
446 throw runtime_error(
447 "getblocknumber\n"
448 "Deprecated. Use getblockcount.");
450 return nBestHeight;
454 Value getconnectioncount(const Array& params, bool fHelp)
456 if (fHelp || params.size() != 0)
457 throw runtime_error(
458 "getconnectioncount\n"
459 "Returns the number of connections to other nodes.");
461 return (int)vNodes.size();
465 Value getdifficulty(const Array& params, bool fHelp)
467 if (fHelp || params.size() != 0)
468 throw runtime_error(
469 "getdifficulty\n"
470 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
472 return GetDifficulty();
476 Value getgenerate(const Array& params, bool fHelp)
478 if (fHelp || params.size() != 0)
479 throw runtime_error(
480 "getgenerate\n"
481 "Returns true or false.");
483 return GetBoolArg("-gen");
487 Value setgenerate(const Array& params, bool fHelp)
489 if (fHelp || params.size() < 1 || params.size() > 2)
490 throw runtime_error(
491 "setgenerate <generate> [genproclimit]\n"
492 "<generate> is true or false to turn generation on or off.\n"
493 "Generation is limited to [genproclimit] processors, -1 is unlimited.");
495 bool fGenerate = true;
496 if (params.size() > 0)
497 fGenerate = params[0].get_bool();
499 if (params.size() > 1)
501 int nGenProcLimit = params[1].get_int();
502 mapArgs["-genproclimit"] = itostr(nGenProcLimit);
503 if (nGenProcLimit == 0)
504 fGenerate = false;
506 mapArgs["-gen"] = (fGenerate ? "1" : "0");
508 GenerateBitcoins(fGenerate, pwalletMain);
509 return Value::null;
513 Value gethashespersec(const Array& params, bool fHelp)
515 if (fHelp || params.size() != 0)
516 throw runtime_error(
517 "gethashespersec\n"
518 "Returns a recent hashes per second performance measurement while generating.");
520 if (GetTimeMillis() - nHPSTimerStart > 8000)
521 return (boost::int64_t)0;
522 return (boost::int64_t)dHashesPerSec;
526 Value getinfo(const Array& params, bool fHelp)
528 if (fHelp || params.size() != 0)
529 throw runtime_error(
530 "getinfo\n"
531 "Returns an object containing various state info.");
533 Object obj;
534 obj.push_back(Pair("version", (int)CLIENT_VERSION));
535 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
536 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
537 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
538 obj.push_back(Pair("blocks", (int)nBestHeight));
539 obj.push_back(Pair("connections", (int)vNodes.size()));
540 obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
541 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
542 obj.push_back(Pair("testnet", fTestNet));
543 obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
544 obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
545 obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
546 if (pwalletMain->IsCrypted())
547 obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
548 obj.push_back(Pair("errors", GetWarnings("statusbar")));
549 return obj;
553 Value getmininginfo(const Array& params, bool fHelp)
555 if (fHelp || params.size() != 0)
556 throw runtime_error(
557 "getmininginfo\n"
558 "Returns an object containing mining-related information.");
560 Object obj;
561 obj.push_back(Pair("blocks", (int)nBestHeight));
562 obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
563 obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
564 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
565 obj.push_back(Pair("errors", GetWarnings("statusbar")));
566 obj.push_back(Pair("generate", GetBoolArg("-gen")));
567 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
568 obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
569 obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
570 obj.push_back(Pair("testnet", fTestNet));
571 return obj;
575 Value getnewaddress(const Array& params, bool fHelp)
577 if (fHelp || params.size() > 1)
578 throw runtime_error(
579 "getnewaddress [account]\n"
580 "Returns a new bitcoin address for receiving payments. "
581 "If [account] is specified (recommended), it is added to the address book "
582 "so payments received with the address will be credited to [account].");
584 // Parse the account first so we don't generate a key if there's an error
585 string strAccount;
586 if (params.size() > 0)
587 strAccount = AccountFromValue(params[0]);
589 if (!pwalletMain->IsLocked())
590 pwalletMain->TopUpKeyPool();
592 // Generate a new key that is added to wallet
593 std::vector<unsigned char> newKey;
594 if (!pwalletMain->GetKeyFromPool(newKey, false))
595 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
596 CBitcoinAddress address(newKey);
598 pwalletMain->SetAddressBookName(address, strAccount);
600 return address.ToString();
604 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
606 CWalletDB walletdb(pwalletMain->strWalletFile);
608 CAccount account;
609 walletdb.ReadAccount(strAccount, account);
611 bool bKeyUsed = false;
613 // Check if the current key has been used
614 if (!account.vchPubKey.empty())
616 CScript scriptPubKey;
617 scriptPubKey.SetBitcoinAddress(account.vchPubKey);
618 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
619 it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
620 ++it)
622 const CWalletTx& wtx = (*it).second;
623 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
624 if (txout.scriptPubKey == scriptPubKey)
625 bKeyUsed = true;
629 // Generate a new key
630 if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
632 if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
633 throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
635 pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
636 walletdb.WriteAccount(strAccount, account);
639 return CBitcoinAddress(account.vchPubKey);
642 Value getaccountaddress(const Array& params, bool fHelp)
644 if (fHelp || params.size() != 1)
645 throw runtime_error(
646 "getaccountaddress <account>\n"
647 "Returns the current bitcoin address for receiving payments to this account.");
649 // Parse the account first so we don't generate a key if there's an error
650 string strAccount = AccountFromValue(params[0]);
652 Value ret;
654 ret = GetAccountAddress(strAccount).ToString();
656 return ret;
661 Value setaccount(const Array& params, bool fHelp)
663 if (fHelp || params.size() < 1 || params.size() > 2)
664 throw runtime_error(
665 "setaccount <bitcoinaddress> <account>\n"
666 "Sets the account associated with the given address.");
668 CBitcoinAddress address(params[0].get_str());
669 if (!address.IsValid())
670 throw JSONRPCError(-5, "Invalid bitcoin address");
673 string strAccount;
674 if (params.size() > 1)
675 strAccount = AccountFromValue(params[1]);
677 // Detect when changing the account of an address that is the 'unused current key' of another account:
678 if (pwalletMain->mapAddressBook.count(address))
680 string strOldAccount = pwalletMain->mapAddressBook[address];
681 if (address == GetAccountAddress(strOldAccount))
682 GetAccountAddress(strOldAccount, true);
685 pwalletMain->SetAddressBookName(address, strAccount);
687 return Value::null;
691 Value getaccount(const Array& params, bool fHelp)
693 if (fHelp || params.size() != 1)
694 throw runtime_error(
695 "getaccount <bitcoinaddress>\n"
696 "Returns the account associated with the given address.");
698 CBitcoinAddress address(params[0].get_str());
699 if (!address.IsValid())
700 throw JSONRPCError(-5, "Invalid bitcoin address");
702 string strAccount;
703 map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
704 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
705 strAccount = (*mi).second;
706 return strAccount;
710 Value getaddressesbyaccount(const Array& params, bool fHelp)
712 if (fHelp || params.size() != 1)
713 throw runtime_error(
714 "getaddressesbyaccount <account>\n"
715 "Returns the list of addresses for the given account.");
717 string strAccount = AccountFromValue(params[0]);
719 // Find all addresses that have the given account
720 Array ret;
721 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
723 const CBitcoinAddress& address = item.first;
724 const string& strName = item.second;
725 if (strName == strAccount)
726 ret.push_back(address.ToString());
728 return ret;
731 Value settxfee(const Array& params, bool fHelp)
733 if (fHelp || params.size() < 1 || params.size() > 1)
734 throw runtime_error(
735 "settxfee <amount>\n"
736 "<amount> is a real and is rounded to the nearest 0.00000001");
738 // Amount
739 int64 nAmount = 0;
740 if (params[0].get_real() != 0.0)
741 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
743 nTransactionFee = nAmount;
744 return true;
747 Value sendtoaddress(const Array& params, bool fHelp)
749 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
750 throw runtime_error(
751 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
752 "<amount> is a real and is rounded to the nearest 0.00000001\n"
753 "requires wallet passphrase to be set with walletpassphrase first");
754 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
755 throw runtime_error(
756 "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
757 "<amount> is a real and is rounded to the nearest 0.00000001");
759 CBitcoinAddress address(params[0].get_str());
760 if (!address.IsValid())
761 throw JSONRPCError(-5, "Invalid bitcoin address");
763 // Amount
764 int64 nAmount = AmountFromValue(params[1]);
766 // Wallet comments
767 CWalletTx wtx;
768 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
769 wtx.mapValue["comment"] = params[2].get_str();
770 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
771 wtx.mapValue["to"] = params[3].get_str();
773 if (pwalletMain->IsLocked())
774 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
776 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
777 if (strError != "")
778 throw JSONRPCError(-4, strError);
780 return wtx.GetHash().GetHex();
783 Value signmessage(const Array& params, bool fHelp)
785 if (fHelp || params.size() != 2)
786 throw runtime_error(
787 "signmessage <bitcoinaddress> <message>\n"
788 "Sign a message with the private key of an address");
790 if (pwalletMain->IsLocked())
791 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
793 string strAddress = params[0].get_str();
794 string strMessage = params[1].get_str();
796 CBitcoinAddress addr(strAddress);
797 if (!addr.IsValid())
798 throw JSONRPCError(-3, "Invalid address");
800 CKey key;
801 if (!pwalletMain->GetKey(addr, key))
802 throw JSONRPCError(-4, "Private key not available");
804 CDataStream ss(SER_GETHASH, 0);
805 ss << strMessageMagic;
806 ss << strMessage;
808 vector<unsigned char> vchSig;
809 if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
810 throw JSONRPCError(-5, "Sign failed");
812 return EncodeBase64(&vchSig[0], vchSig.size());
815 Value verifymessage(const Array& params, bool fHelp)
817 if (fHelp || params.size() != 3)
818 throw runtime_error(
819 "verifymessage <bitcoinaddress> <signature> <message>\n"
820 "Verify a signed message");
822 string strAddress = params[0].get_str();
823 string strSign = params[1].get_str();
824 string strMessage = params[2].get_str();
826 CBitcoinAddress addr(strAddress);
827 if (!addr.IsValid())
828 throw JSONRPCError(-3, "Invalid address");
830 bool fInvalid = false;
831 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
833 if (fInvalid)
834 throw JSONRPCError(-5, "Malformed base64 encoding");
836 CDataStream ss(SER_GETHASH, 0);
837 ss << strMessageMagic;
838 ss << strMessage;
840 CKey key;
841 if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
842 return false;
844 return (CBitcoinAddress(key.GetPubKey()) == addr);
848 Value getreceivedbyaddress(const Array& params, bool fHelp)
850 if (fHelp || params.size() < 1 || params.size() > 2)
851 throw runtime_error(
852 "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
853 "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
855 // Bitcoin address
856 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
857 CScript scriptPubKey;
858 if (!address.IsValid())
859 throw JSONRPCError(-5, "Invalid bitcoin address");
860 scriptPubKey.SetBitcoinAddress(address);
861 if (!IsMine(*pwalletMain,scriptPubKey))
862 return (double)0.0;
864 // Minimum confirmations
865 int nMinDepth = 1;
866 if (params.size() > 1)
867 nMinDepth = params[1].get_int();
869 // Tally
870 int64 nAmount = 0;
871 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
873 const CWalletTx& wtx = (*it).second;
874 if (wtx.IsCoinBase() || !wtx.IsFinal())
875 continue;
877 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
878 if (txout.scriptPubKey == scriptPubKey)
879 if (wtx.GetDepthInMainChain() >= nMinDepth)
880 nAmount += txout.nValue;
883 return ValueFromAmount(nAmount);
887 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
889 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
891 const CBitcoinAddress& address = item.first;
892 const string& strName = item.second;
893 if (strName == strAccount)
894 setAddress.insert(address);
899 Value getreceivedbyaccount(const Array& params, bool fHelp)
901 if (fHelp || params.size() < 1 || params.size() > 2)
902 throw runtime_error(
903 "getreceivedbyaccount <account> [minconf=1]\n"
904 "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
906 // Minimum confirmations
907 int nMinDepth = 1;
908 if (params.size() > 1)
909 nMinDepth = params[1].get_int();
911 // Get the set of pub keys assigned to account
912 string strAccount = AccountFromValue(params[0]);
913 set<CBitcoinAddress> setAddress;
914 GetAccountAddresses(strAccount, setAddress);
916 // Tally
917 int64 nAmount = 0;
918 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
920 const CWalletTx& wtx = (*it).second;
921 if (wtx.IsCoinBase() || !wtx.IsFinal())
922 continue;
924 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
926 CBitcoinAddress address;
927 if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
928 if (wtx.GetDepthInMainChain() >= nMinDepth)
929 nAmount += txout.nValue;
933 return (double)nAmount / (double)COIN;
937 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
939 int64 nBalance = 0;
941 // Tally wallet transactions
942 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
944 const CWalletTx& wtx = (*it).second;
945 if (!wtx.IsFinal())
946 continue;
948 int64 nGenerated, nReceived, nSent, nFee;
949 wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
951 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
952 nBalance += nReceived;
953 nBalance += nGenerated - nSent - nFee;
956 // Tally internal accounting entries
957 nBalance += walletdb.GetAccountCreditDebit(strAccount);
959 return nBalance;
962 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
964 CWalletDB walletdb(pwalletMain->strWalletFile);
965 return GetAccountBalance(walletdb, strAccount, nMinDepth);
969 Value getbalance(const Array& params, bool fHelp)
971 if (fHelp || params.size() > 2)
972 throw runtime_error(
973 "getbalance [account] [minconf=1]\n"
974 "If [account] is not specified, returns the server's total available balance.\n"
975 "If [account] is specified, returns the balance in the account.");
977 if (params.size() == 0)
978 return ValueFromAmount(pwalletMain->GetBalance());
980 int nMinDepth = 1;
981 if (params.size() > 1)
982 nMinDepth = params[1].get_int();
984 if (params[0].get_str() == "*") {
985 // Calculate total balance a different way from GetBalance()
986 // (GetBalance() sums up all unspent TxOuts)
987 // getbalance and getbalance '*' should always return the same number.
988 int64 nBalance = 0;
989 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
991 const CWalletTx& wtx = (*it).second;
992 if (!wtx.IsFinal())
993 continue;
995 int64 allGeneratedImmature, allGeneratedMature, allFee;
996 allGeneratedImmature = allGeneratedMature = allFee = 0;
997 string strSentAccount;
998 list<pair<CBitcoinAddress, int64> > listReceived;
999 list<pair<CBitcoinAddress, int64> > listSent;
1000 wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
1001 if (wtx.GetDepthInMainChain() >= nMinDepth)
1003 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
1004 nBalance += r.second;
1006 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
1007 nBalance -= r.second;
1008 nBalance -= allFee;
1009 nBalance += allGeneratedMature;
1011 return ValueFromAmount(nBalance);
1014 string strAccount = AccountFromValue(params[0]);
1016 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
1018 return ValueFromAmount(nBalance);
1022 Value movecmd(const Array& params, bool fHelp)
1024 if (fHelp || params.size() < 3 || params.size() > 5)
1025 throw runtime_error(
1026 "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
1027 "Move from one account in your wallet to another.");
1029 string strFrom = AccountFromValue(params[0]);
1030 string strTo = AccountFromValue(params[1]);
1031 int64 nAmount = AmountFromValue(params[2]);
1032 if (params.size() > 3)
1033 // unused parameter, used to be nMinDepth, keep type-checking it though
1034 (void)params[3].get_int();
1035 string strComment;
1036 if (params.size() > 4)
1037 strComment = params[4].get_str();
1039 CWalletDB walletdb(pwalletMain->strWalletFile);
1040 if (!walletdb.TxnBegin())
1041 throw JSONRPCError(-20, "database error");
1043 int64 nNow = GetAdjustedTime();
1045 // Debit
1046 CAccountingEntry debit;
1047 debit.strAccount = strFrom;
1048 debit.nCreditDebit = -nAmount;
1049 debit.nTime = nNow;
1050 debit.strOtherAccount = strTo;
1051 debit.strComment = strComment;
1052 walletdb.WriteAccountingEntry(debit);
1054 // Credit
1055 CAccountingEntry credit;
1056 credit.strAccount = strTo;
1057 credit.nCreditDebit = nAmount;
1058 credit.nTime = nNow;
1059 credit.strOtherAccount = strFrom;
1060 credit.strComment = strComment;
1061 walletdb.WriteAccountingEntry(credit);
1063 if (!walletdb.TxnCommit())
1064 throw JSONRPCError(-20, "database error");
1066 return true;
1070 Value sendfrom(const Array& params, bool fHelp)
1072 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
1073 throw runtime_error(
1074 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
1075 "<amount> is a real and is rounded to the nearest 0.00000001\n"
1076 "requires wallet passphrase to be set with walletpassphrase first");
1077 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
1078 throw runtime_error(
1079 "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
1080 "<amount> is a real and is rounded to the nearest 0.00000001");
1082 string strAccount = AccountFromValue(params[0]);
1083 CBitcoinAddress address(params[1].get_str());
1084 if (!address.IsValid())
1085 throw JSONRPCError(-5, "Invalid bitcoin address");
1086 int64 nAmount = AmountFromValue(params[2]);
1087 int nMinDepth = 1;
1088 if (params.size() > 3)
1089 nMinDepth = params[3].get_int();
1091 CWalletTx wtx;
1092 wtx.strFromAccount = strAccount;
1093 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
1094 wtx.mapValue["comment"] = params[4].get_str();
1095 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
1096 wtx.mapValue["to"] = params[5].get_str();
1098 if (pwalletMain->IsLocked())
1099 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1101 // Check funds
1102 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
1103 if (nAmount > nBalance)
1104 throw JSONRPCError(-6, "Account has insufficient funds");
1106 // Send
1107 string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
1108 if (strError != "")
1109 throw JSONRPCError(-4, strError);
1111 return wtx.GetHash().GetHex();
1115 Value sendmany(const Array& params, bool fHelp)
1117 if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
1118 throw runtime_error(
1119 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
1120 "amounts are double-precision floating point numbers\n"
1121 "requires wallet passphrase to be set with walletpassphrase first");
1122 if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
1123 throw runtime_error(
1124 "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
1125 "amounts are double-precision floating point numbers");
1127 string strAccount = AccountFromValue(params[0]);
1128 Object sendTo = params[1].get_obj();
1129 int nMinDepth = 1;
1130 if (params.size() > 2)
1131 nMinDepth = params[2].get_int();
1133 CWalletTx wtx;
1134 wtx.strFromAccount = strAccount;
1135 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
1136 wtx.mapValue["comment"] = params[3].get_str();
1138 set<CBitcoinAddress> setAddress;
1139 vector<pair<CScript, int64> > vecSend;
1141 int64 totalAmount = 0;
1142 BOOST_FOREACH(const Pair& s, sendTo)
1144 CBitcoinAddress address(s.name_);
1145 if (!address.IsValid())
1146 throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
1148 if (setAddress.count(address))
1149 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
1150 setAddress.insert(address);
1152 CScript scriptPubKey;
1153 scriptPubKey.SetBitcoinAddress(address);
1154 int64 nAmount = AmountFromValue(s.value_);
1155 totalAmount += nAmount;
1157 vecSend.push_back(make_pair(scriptPubKey, nAmount));
1160 if (pwalletMain->IsLocked())
1161 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1163 // Check funds
1164 int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
1165 if (totalAmount > nBalance)
1166 throw JSONRPCError(-6, "Account has insufficient funds");
1168 // Send
1169 CReserveKey keyChange(pwalletMain);
1170 int64 nFeeRequired = 0;
1171 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
1172 if (!fCreated)
1174 if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
1175 throw JSONRPCError(-6, "Insufficient funds");
1176 throw JSONRPCError(-4, "Transaction creation failed");
1178 if (!pwalletMain->CommitTransaction(wtx, keyChange))
1179 throw JSONRPCError(-4, "Transaction commit failed");
1181 return wtx.GetHash().GetHex();
1184 Value addmultisigaddress(const Array& params, bool fHelp)
1186 if (fHelp || params.size() < 2 || params.size() > 3)
1188 string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
1189 "Add a nrequired-to-sign multisignature address to the wallet\"\n"
1190 "each key is a bitcoin address or hex-encoded public key\n"
1191 "If [account] is specified, assign address to [account].";
1192 throw runtime_error(msg);
1195 int nRequired = params[0].get_int();
1196 const Array& keys = params[1].get_array();
1197 string strAccount;
1198 if (params.size() > 2)
1199 strAccount = AccountFromValue(params[2]);
1201 // Gather public keys
1202 if (nRequired < 1)
1203 throw runtime_error("a multisignature address must require at least one key to redeem");
1204 if ((int)keys.size() < nRequired)
1205 throw runtime_error(
1206 strprintf("not enough keys supplied "
1207 "(got %d keys, but need at least %d to redeem)", keys.size(), nRequired));
1208 std::vector<CKey> pubkeys;
1209 pubkeys.resize(keys.size());
1210 for (unsigned int i = 0; i < keys.size(); i++)
1212 const std::string& ks = keys[i].get_str();
1214 // Case 1: bitcoin address and we have full public key:
1215 CBitcoinAddress address(ks);
1216 if (address.IsValid())
1218 if (address.IsScript())
1219 throw runtime_error(
1220 strprintf("%s is a pay-to-script address",ks.c_str()));
1221 std::vector<unsigned char> vchPubKey;
1222 if (!pwalletMain->GetPubKey(address, vchPubKey))
1223 throw runtime_error(
1224 strprintf("no full public key for address %s",ks.c_str()));
1225 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1226 throw runtime_error(" Invalid public key: "+ks);
1229 // Case 2: hex public key
1230 else if (IsHex(ks))
1232 vector<unsigned char> vchPubKey = ParseHex(ks);
1233 if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1234 throw runtime_error(" Invalid public key: "+ks);
1236 else
1238 throw runtime_error(" Invalid public key: "+ks);
1242 // Construct using pay-to-script-hash:
1243 CScript inner;
1244 inner.SetMultisig(nRequired, pubkeys);
1246 uint160 scriptHash = Hash160(inner);
1247 CScript scriptPubKey;
1248 scriptPubKey.SetPayToScriptHash(inner);
1249 pwalletMain->AddCScript(inner);
1250 CBitcoinAddress address;
1251 address.SetScriptHash160(scriptHash);
1253 pwalletMain->SetAddressBookName(address, strAccount);
1254 return address.ToString();
1258 struct tallyitem
1260 int64 nAmount;
1261 int nConf;
1262 tallyitem()
1264 nAmount = 0;
1265 nConf = std::numeric_limits<int>::max();
1269 Value ListReceived(const Array& params, bool fByAccounts)
1271 // Minimum confirmations
1272 int nMinDepth = 1;
1273 if (params.size() > 0)
1274 nMinDepth = params[0].get_int();
1276 // Whether to include empty accounts
1277 bool fIncludeEmpty = false;
1278 if (params.size() > 1)
1279 fIncludeEmpty = params[1].get_bool();
1281 // Tally
1282 map<CBitcoinAddress, tallyitem> mapTally;
1283 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1285 const CWalletTx& wtx = (*it).second;
1287 if (wtx.IsCoinBase() || !wtx.IsFinal())
1288 continue;
1290 int nDepth = wtx.GetDepthInMainChain();
1291 if (nDepth < nMinDepth)
1292 continue;
1294 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1296 CBitcoinAddress address;
1297 if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1298 continue;
1300 tallyitem& item = mapTally[address];
1301 item.nAmount += txout.nValue;
1302 item.nConf = min(item.nConf, nDepth);
1306 // Reply
1307 Array ret;
1308 map<string, tallyitem> mapAccountTally;
1309 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1311 const CBitcoinAddress& address = item.first;
1312 const string& strAccount = item.second;
1313 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1314 if (it == mapTally.end() && !fIncludeEmpty)
1315 continue;
1317 int64 nAmount = 0;
1318 int nConf = std::numeric_limits<int>::max();
1319 if (it != mapTally.end())
1321 nAmount = (*it).second.nAmount;
1322 nConf = (*it).second.nConf;
1325 if (fByAccounts)
1327 tallyitem& item = mapAccountTally[strAccount];
1328 item.nAmount += nAmount;
1329 item.nConf = min(item.nConf, nConf);
1331 else
1333 Object obj;
1334 obj.push_back(Pair("address", address.ToString()));
1335 obj.push_back(Pair("account", strAccount));
1336 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1337 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1338 ret.push_back(obj);
1342 if (fByAccounts)
1344 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1346 int64 nAmount = (*it).second.nAmount;
1347 int nConf = (*it).second.nConf;
1348 Object obj;
1349 obj.push_back(Pair("account", (*it).first));
1350 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1351 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1352 ret.push_back(obj);
1356 return ret;
1359 Value listreceivedbyaddress(const Array& params, bool fHelp)
1361 if (fHelp || params.size() > 2)
1362 throw runtime_error(
1363 "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1364 "[minconf] is the minimum number of confirmations before payments are included.\n"
1365 "[includeempty] whether to include addresses that haven't received any payments.\n"
1366 "Returns an array of objects containing:\n"
1367 " \"address\" : receiving address\n"
1368 " \"account\" : the account of the receiving address\n"
1369 " \"amount\" : total amount received by the address\n"
1370 " \"confirmations\" : number of confirmations of the most recent transaction included");
1372 return ListReceived(params, false);
1375 Value listreceivedbyaccount(const Array& params, bool fHelp)
1377 if (fHelp || params.size() > 2)
1378 throw runtime_error(
1379 "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1380 "[minconf] is the minimum number of confirmations before payments are included.\n"
1381 "[includeempty] whether to include accounts that haven't received any payments.\n"
1382 "Returns an array of objects containing:\n"
1383 " \"account\" : the account of the receiving addresses\n"
1384 " \"amount\" : total amount received by addresses with this account\n"
1385 " \"confirmations\" : number of confirmations of the most recent transaction included");
1387 return ListReceived(params, true);
1390 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1392 int64 nGeneratedImmature, nGeneratedMature, nFee;
1393 string strSentAccount;
1394 list<pair<CBitcoinAddress, int64> > listReceived;
1395 list<pair<CBitcoinAddress, int64> > listSent;
1397 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1399 bool fAllAccounts = (strAccount == string("*"));
1401 // Generated blocks assigned to account ""
1402 if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1404 Object entry;
1405 entry.push_back(Pair("account", string("")));
1406 if (nGeneratedImmature)
1408 entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1409 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1411 else
1413 entry.push_back(Pair("category", "generate"));
1414 entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1416 if (fLong)
1417 WalletTxToJSON(wtx, entry);
1418 ret.push_back(entry);
1421 // Sent
1422 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1424 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1426 Object entry;
1427 entry.push_back(Pair("account", strSentAccount));
1428 entry.push_back(Pair("address", s.first.ToString()));
1429 entry.push_back(Pair("category", "send"));
1430 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1431 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1432 if (fLong)
1433 WalletTxToJSON(wtx, entry);
1434 ret.push_back(entry);
1438 // Received
1439 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1441 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1443 string account;
1444 if (pwalletMain->mapAddressBook.count(r.first))
1445 account = pwalletMain->mapAddressBook[r.first];
1446 if (fAllAccounts || (account == strAccount))
1448 Object entry;
1449 entry.push_back(Pair("account", account));
1450 entry.push_back(Pair("address", r.first.ToString()));
1451 entry.push_back(Pair("category", "receive"));
1452 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1453 if (fLong)
1454 WalletTxToJSON(wtx, entry);
1455 ret.push_back(entry);
1461 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1463 bool fAllAccounts = (strAccount == string("*"));
1465 if (fAllAccounts || acentry.strAccount == strAccount)
1467 Object entry;
1468 entry.push_back(Pair("account", acentry.strAccount));
1469 entry.push_back(Pair("category", "move"));
1470 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1471 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1472 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1473 entry.push_back(Pair("comment", acentry.strComment));
1474 ret.push_back(entry);
1478 Value listtransactions(const Array& params, bool fHelp)
1480 if (fHelp || params.size() > 3)
1481 throw runtime_error(
1482 "listtransactions [account] [count=10] [from=0]\n"
1483 "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1485 string strAccount = "*";
1486 if (params.size() > 0)
1487 strAccount = params[0].get_str();
1488 int nCount = 10;
1489 if (params.size() > 1)
1490 nCount = params[1].get_int();
1491 int nFrom = 0;
1492 if (params.size() > 2)
1493 nFrom = params[2].get_int();
1495 if (nCount < 0)
1496 throw JSONRPCError(-8, "Negative count");
1497 if (nFrom < 0)
1498 throw JSONRPCError(-8, "Negative from");
1500 Array ret;
1501 CWalletDB walletdb(pwalletMain->strWalletFile);
1503 // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1504 typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1505 typedef multimap<int64, TxPair > TxItems;
1506 TxItems txByTime;
1508 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1509 // would make this much faster for applications that do this a lot.
1510 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1512 CWalletTx* wtx = &((*it).second);
1513 txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1515 list<CAccountingEntry> acentries;
1516 walletdb.ListAccountCreditDebit(strAccount, acentries);
1517 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1519 txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1522 // iterate backwards until we have nCount items to return:
1523 for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1525 CWalletTx *const pwtx = (*it).second.first;
1526 if (pwtx != 0)
1527 ListTransactions(*pwtx, strAccount, 0, true, ret);
1528 CAccountingEntry *const pacentry = (*it).second.second;
1529 if (pacentry != 0)
1530 AcentryToJSON(*pacentry, strAccount, ret);
1532 if ((int)ret.size() >= (nCount+nFrom)) break;
1534 // ret is newest to oldest
1536 if (nFrom > (int)ret.size())
1537 nFrom = ret.size();
1538 if ((nFrom + nCount) > (int)ret.size())
1539 nCount = ret.size() - nFrom;
1540 Array::iterator first = ret.begin();
1541 std::advance(first, nFrom);
1542 Array::iterator last = ret.begin();
1543 std::advance(last, nFrom+nCount);
1545 if (last != ret.end()) ret.erase(last, ret.end());
1546 if (first != ret.begin()) ret.erase(ret.begin(), first);
1548 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1550 return ret;
1553 Value listaccounts(const Array& params, bool fHelp)
1555 if (fHelp || params.size() > 1)
1556 throw runtime_error(
1557 "listaccounts [minconf=1]\n"
1558 "Returns Object that has account names as keys, account balances as values.");
1560 int nMinDepth = 1;
1561 if (params.size() > 0)
1562 nMinDepth = params[0].get_int();
1564 map<string, int64> mapAccountBalances;
1565 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1566 if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1567 mapAccountBalances[entry.second] = 0;
1570 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1572 const CWalletTx& wtx = (*it).second;
1573 int64 nGeneratedImmature, nGeneratedMature, nFee;
1574 string strSentAccount;
1575 list<pair<CBitcoinAddress, int64> > listReceived;
1576 list<pair<CBitcoinAddress, int64> > listSent;
1577 wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1578 mapAccountBalances[strSentAccount] -= nFee;
1579 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1580 mapAccountBalances[strSentAccount] -= s.second;
1581 if (wtx.GetDepthInMainChain() >= nMinDepth)
1583 mapAccountBalances[""] += nGeneratedMature;
1584 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1585 if (pwalletMain->mapAddressBook.count(r.first))
1586 mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1587 else
1588 mapAccountBalances[""] += r.second;
1592 list<CAccountingEntry> acentries;
1593 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1594 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1595 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1597 Object ret;
1598 BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1599 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1601 return ret;
1604 Value listsinceblock(const Array& params, bool fHelp)
1606 if (fHelp)
1607 throw runtime_error(
1608 "listsinceblock [blockhash] [target-confirmations]\n"
1609 "Get all transactions in blocks since block [blockhash], or all transactions if omitted");
1611 CBlockIndex *pindex = NULL;
1612 int target_confirms = 1;
1614 if (params.size() > 0)
1616 uint256 blockId = 0;
1618 blockId.SetHex(params[0].get_str());
1619 pindex = CBlockLocator(blockId).GetBlockIndex();
1622 if (params.size() > 1)
1624 target_confirms = params[1].get_int();
1626 if (target_confirms < 1)
1627 throw JSONRPCError(-8, "Invalid parameter");
1630 int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1632 Array transactions;
1634 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1636 CWalletTx tx = (*it).second;
1638 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1639 ListTransactions(tx, "*", 0, true, transactions);
1642 uint256 lastblock;
1644 if (target_confirms == 1)
1646 lastblock = hashBestChain;
1648 else
1650 int target_height = pindexBest->nHeight + 1 - target_confirms;
1652 CBlockIndex *block;
1653 for (block = pindexBest;
1654 block && block->nHeight > target_height;
1655 block = block->pprev) { }
1657 lastblock = block ? block->GetBlockHash() : 0;
1660 Object ret;
1661 ret.push_back(Pair("transactions", transactions));
1662 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1664 return ret;
1667 void
1668 AnyTxToJSON(const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions)
1670 if (pwalletMain->mapWallet.count(hash))
1672 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1674 TxToJSON(wtx, entry, decompositions);
1676 int64 nCredit = wtx.GetCredit();
1677 int64 nDebit = wtx.GetDebit();
1678 int64 nNet = nCredit - nDebit;
1679 int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1681 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1682 if (wtx.IsFromMe())
1683 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1685 WalletTxToJSON(wtx, entry);
1687 Array details;
1688 ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1689 entry.push_back(Pair("details", details));
1691 else
1693 CTransaction tx;
1694 uint256 hashBlock = 0;
1695 if ((!ptx) && GetTransaction(hash, tx, hashBlock))
1696 ptx = &tx;
1697 if (ptx)
1699 entry.push_back(Pair("txid", hash.GetHex()));
1700 TxToJSON(*ptx, entry, decompositions);
1701 if (hashBlock == 0)
1702 entry.push_back(Pair("confirmations", 0));
1703 else
1705 entry.push_back(Pair("blockhash", hashBlock.GetHex()));
1706 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
1707 if (mi != mapBlockIndex.end() && (*mi).second)
1709 CBlockIndex* pindex = (*mi).second;
1710 if (pindex->IsInMainChain())
1712 entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
1713 entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
1715 else
1716 entry.push_back(Pair("confirmations", 0));
1720 else
1721 throw JSONRPCError(-5, "No information available about transaction");
1725 Value gettransaction(const Array& params, bool fHelp)
1727 if (fHelp || params.size() < 1 || params.size() > 2)
1728 throw runtime_error(
1729 "gettransaction <txid> [decompositions]\n"
1730 "Get detailed information about <txid>");
1732 uint256 hash;
1733 hash.SetHex(params[0].get_str());
1735 Object entry;
1737 AnyTxToJSON(hash, NULL, entry,
1738 (params.size() > 1) ? params[1].get_obj() : emptyobj);
1740 return entry;
1744 Value backupwallet(const Array& params, bool fHelp)
1746 if (fHelp || params.size() != 1)
1747 throw runtime_error(
1748 "backupwallet <destination>\n"
1749 "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1751 string strDest = params[0].get_str();
1752 BackupWallet(*pwalletMain, strDest);
1754 return Value::null;
1758 Value keypoolrefill(const Array& params, bool fHelp)
1760 if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1761 throw runtime_error(
1762 "keypoolrefill\n"
1763 "Fills the keypool, requires wallet passphrase to be set.");
1764 if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1765 throw runtime_error(
1766 "keypoolrefill\n"
1767 "Fills the keypool.");
1769 if (pwalletMain->IsLocked())
1770 throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1772 pwalletMain->TopUpKeyPool();
1774 if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1775 throw JSONRPCError(-4, "Error refreshing keypool.");
1777 return Value::null;
1781 void ThreadTopUpKeyPool(void* parg)
1783 pwalletMain->TopUpKeyPool();
1786 void ThreadCleanWalletPassphrase(void* parg)
1788 int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1790 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1792 if (nWalletUnlockTime == 0)
1794 nWalletUnlockTime = nMyWakeTime;
1798 if (nWalletUnlockTime==0)
1799 break;
1800 int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1801 if (nToSleep <= 0)
1802 break;
1804 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1805 Sleep(nToSleep);
1806 ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1808 } while(1);
1810 if (nWalletUnlockTime)
1812 nWalletUnlockTime = 0;
1813 pwalletMain->Lock();
1816 else
1818 if (nWalletUnlockTime < nMyWakeTime)
1819 nWalletUnlockTime = nMyWakeTime;
1822 LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1824 delete (int64*)parg;
1827 Value walletpassphrase(const Array& params, bool fHelp)
1829 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1830 throw runtime_error(
1831 "walletpassphrase <passphrase> <timeout>\n"
1832 "Stores the wallet decryption key in memory for <timeout> seconds.");
1833 if (fHelp)
1834 return true;
1835 if (!pwalletMain->IsCrypted())
1836 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1838 if (!pwalletMain->IsLocked())
1839 throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1841 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1842 SecureString strWalletPass;
1843 strWalletPass.reserve(100);
1844 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1845 // Alternately, find a way to make params[0] mlock()'d to begin with.
1846 strWalletPass = params[0].get_str().c_str();
1848 if (strWalletPass.length() > 0)
1850 if (!pwalletMain->Unlock(strWalletPass))
1851 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1853 else
1854 throw runtime_error(
1855 "walletpassphrase <passphrase> <timeout>\n"
1856 "Stores the wallet decryption key in memory for <timeout> seconds.");
1858 CreateThread(ThreadTopUpKeyPool, NULL);
1859 int64* pnSleepTime = new int64(params[1].get_int64());
1860 CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1862 return Value::null;
1866 Value walletpassphrasechange(const Array& params, bool fHelp)
1868 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1869 throw runtime_error(
1870 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1871 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1872 if (fHelp)
1873 return true;
1874 if (!pwalletMain->IsCrypted())
1875 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1877 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1878 // Alternately, find a way to make params[0] mlock()'d to begin with.
1879 SecureString strOldWalletPass;
1880 strOldWalletPass.reserve(100);
1881 strOldWalletPass = params[0].get_str().c_str();
1883 SecureString strNewWalletPass;
1884 strNewWalletPass.reserve(100);
1885 strNewWalletPass = params[1].get_str().c_str();
1887 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1888 throw runtime_error(
1889 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1890 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1892 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1893 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1895 return Value::null;
1899 Value walletlock(const Array& params, bool fHelp)
1901 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1902 throw runtime_error(
1903 "walletlock\n"
1904 "Removes the wallet encryption key from memory, locking the wallet.\n"
1905 "After calling this method, you will need to call walletpassphrase again\n"
1906 "before being able to call any methods which require the wallet to be unlocked.");
1907 if (fHelp)
1908 return true;
1909 if (!pwalletMain->IsCrypted())
1910 throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1913 LOCK(cs_nWalletUnlockTime);
1914 pwalletMain->Lock();
1915 nWalletUnlockTime = 0;
1918 return Value::null;
1922 Value encryptwallet(const Array& params, bool fHelp)
1924 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1925 throw runtime_error(
1926 "encryptwallet <passphrase>\n"
1927 "Encrypts the wallet with <passphrase>.");
1928 if (fHelp)
1929 return true;
1930 if (pwalletMain->IsCrypted())
1931 throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1933 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1934 // Alternately, find a way to make params[0] mlock()'d to begin with.
1935 SecureString strWalletPass;
1936 strWalletPass.reserve(100);
1937 strWalletPass = params[0].get_str().c_str();
1939 if (strWalletPass.length() < 1)
1940 throw runtime_error(
1941 "encryptwallet <passphrase>\n"
1942 "Encrypts the wallet with <passphrase>.");
1944 if (!pwalletMain->EncryptWallet(strWalletPass))
1945 throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1947 // BDB seems to have a bad habit of writing old data into
1948 // slack space in .dat files; that is bad if the old data is
1949 // unencrypted private keys. So:
1950 QueueShutdown();
1951 return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1955 Value validateaddress(const Array& params, bool fHelp)
1957 if (fHelp || params.size() != 1)
1958 throw runtime_error(
1959 "validateaddress <bitcoinaddress>\n"
1960 "Return information about <bitcoinaddress>.");
1962 CBitcoinAddress address(params[0].get_str());
1963 bool isValid = address.IsValid();
1965 Object ret;
1966 ret.push_back(Pair("isvalid", isValid));
1967 if (isValid)
1969 // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1970 // version of the address:
1971 string currentAddress = address.ToString();
1972 ret.push_back(Pair("address", currentAddress));
1973 if (pwalletMain->HaveKey(address))
1975 ret.push_back(Pair("ismine", true));
1976 std::vector<unsigned char> vchPubKey;
1977 pwalletMain->GetPubKey(address, vchPubKey);
1978 ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1979 CKey key;
1980 key.SetPubKey(vchPubKey);
1981 ret.push_back(Pair("iscompressed", key.IsCompressed()));
1983 else if (pwalletMain->HaveCScript(address.GetHash160()))
1985 ret.push_back(Pair("isscript", true));
1986 CScript subscript;
1987 pwalletMain->GetCScript(address.GetHash160(), subscript);
1988 ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1989 std::vector<CBitcoinAddress> addresses;
1990 txnouttype whichType;
1991 int nRequired;
1992 ExtractAddresses(subscript, whichType, addresses, nRequired);
1993 ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1994 Array a;
1995 BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1996 a.push_back(addr.ToString());
1997 ret.push_back(Pair("addresses", a));
1998 if (whichType == TX_MULTISIG)
1999 ret.push_back(Pair("sigsrequired", nRequired));
2001 else
2002 ret.push_back(Pair("ismine", false));
2003 if (pwalletMain->mapAddressBook.count(address))
2004 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
2006 return ret;
2009 Value getwork(const Array& params, bool fHelp)
2011 if (fHelp || params.size() > 1)
2012 throw runtime_error(
2013 "getwork [data]\n"
2014 "If [data] is not specified, returns formatted hash data to work on:\n"
2015 " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
2016 " \"data\" : block data\n"
2017 " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
2018 " \"target\" : little endian hash target\n"
2019 "If [data] is specified, tries to solve the block and returns true if it was successful.");
2021 if (vNodes.empty())
2022 throw JSONRPCError(-9, "Bitcoin is not connected!");
2024 if (IsInitialBlockDownload())
2025 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
2027 typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
2028 static mapNewBlock_t mapNewBlock; // FIXME: thread safety
2029 static vector<CBlock*> vNewBlock;
2030 static CReserveKey reservekey(pwalletMain);
2032 if (params.size() == 0)
2034 // Update block
2035 static unsigned int nTransactionsUpdatedLast;
2036 static CBlockIndex* pindexPrev;
2037 static int64 nStart;
2038 static CBlock* pblock;
2039 if (pindexPrev != pindexBest ||
2040 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
2042 if (pindexPrev != pindexBest)
2044 // Deallocate old blocks since they're obsolete now
2045 mapNewBlock.clear();
2046 BOOST_FOREACH(CBlock* pblock, vNewBlock)
2047 delete pblock;
2048 vNewBlock.clear();
2050 nTransactionsUpdatedLast = nTransactionsUpdated;
2051 pindexPrev = pindexBest;
2052 nStart = GetTime();
2054 // Create new block
2055 pblock = CreateNewBlock(reservekey);
2056 if (!pblock)
2057 throw JSONRPCError(-7, "Out of memory");
2058 vNewBlock.push_back(pblock);
2061 // Update nTime
2062 pblock->UpdateTime(pindexPrev);
2063 pblock->nNonce = 0;
2065 // Update nExtraNonce
2066 static unsigned int nExtraNonce = 0;
2067 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
2069 // Save
2070 mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
2072 // Prebuild hash buffers
2073 char pmidstate[32];
2074 char pdata[128];
2075 char phash1[64];
2076 FormatHashBuffers(pblock, pmidstate, pdata, phash1);
2078 uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
2080 Object result;
2081 result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
2082 result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
2083 result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
2084 result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
2085 return result;
2087 else
2089 // Parse parameters
2090 vector<unsigned char> vchData = ParseHex(params[0].get_str());
2091 if (vchData.size() != 128)
2092 throw JSONRPCError(-8, "Invalid parameter");
2093 CBlock* pdata = (CBlock*)&vchData[0];
2095 // Byte reverse
2096 for (int i = 0; i < 128/4; i++)
2097 ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
2099 // Get saved block
2100 if (!mapNewBlock.count(pdata->hashMerkleRoot))
2101 return false;
2102 CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
2104 pblock->nTime = pdata->nTime;
2105 pblock->nNonce = pdata->nNonce;
2106 pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
2107 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
2109 return CheckWork(pblock, *pwalletMain, reservekey);
2114 Value getmemorypool(const Array& params, bool fHelp)
2116 if (fHelp || params.size() > 1)
2117 throw runtime_error(
2118 "getmemorypool [data]\n"
2119 "If [data] is not specified, returns data needed to construct a block to work on:\n"
2120 " \"version\" : block version\n"
2121 " \"previousblockhash\" : hash of current highest block\n"
2122 " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
2123 " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
2124 " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
2125 " \"time\" : timestamp appropriate for next block\n"
2126 " \"mintime\" : minimum timestamp appropriate for next block\n"
2127 " \"curtime\" : current timestamp\n"
2128 " \"bits\" : compressed target of next block\n"
2129 "If [data] is specified, tries to solve the block and returns true if it was successful.");
2131 if (params.size() == 0)
2133 if (vNodes.empty())
2134 throw JSONRPCError(-9, "Bitcoin is not connected!");
2136 if (IsInitialBlockDownload())
2137 throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
2139 static CReserveKey reservekey(pwalletMain);
2141 // Update block
2142 static unsigned int nTransactionsUpdatedLast;
2143 static CBlockIndex* pindexPrev;
2144 static int64 nStart;
2145 static CBlock* pblock;
2146 if (pindexPrev != pindexBest ||
2147 (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
2149 nTransactionsUpdatedLast = nTransactionsUpdated;
2150 pindexPrev = pindexBest;
2151 nStart = GetTime();
2153 // Create new block
2154 if(pblock)
2155 delete pblock;
2156 pblock = CreateNewBlock(reservekey);
2157 if (!pblock)
2158 throw JSONRPCError(-7, "Out of memory");
2161 // Update nTime
2162 pblock->UpdateTime(pindexPrev);
2163 pblock->nNonce = 0;
2165 Array transactions;
2166 BOOST_FOREACH(CTransaction tx, pblock->vtx) {
2167 if(tx.IsCoinBase())
2168 continue;
2170 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
2171 ssTx << tx;
2173 transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
2176 Object result;
2177 result.push_back(Pair("version", pblock->nVersion));
2178 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
2179 result.push_back(Pair("transactions", transactions));
2180 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
2181 result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
2182 result.push_back(Pair("time", (int64_t)pblock->nTime));
2183 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
2184 result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
2185 result.push_back(Pair("bits", HexBits(pblock->nBits)));
2187 return result;
2189 else
2191 // Parse parameters
2192 CDataStream ssBlock(ParseHex(params[0].get_str()), SER_NETWORK, PROTOCOL_VERSION);
2193 CBlock pblock;
2194 ssBlock >> pblock;
2196 return ProcessBlock(NULL, &pblock);
2200 Value getblockhash(const Array& params, bool fHelp)
2202 if (fHelp || params.size() != 1)
2203 throw runtime_error(
2204 "getblockhash <index>\n"
2205 "Returns hash of block in best-block-chain at <index>.");
2207 int nHeight = params[0].get_int();
2208 if (nHeight < 0 || nHeight > nBestHeight)
2209 throw runtime_error("Block number out of range.");
2211 CBlock block;
2212 CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
2213 while (pblockindex->nHeight > nHeight)
2214 pblockindex = pblockindex->pprev;
2215 return pblockindex->phashBlock->GetHex();
2218 Value getblock(const Array& params, bool fHelp)
2220 if (fHelp || params.size() < 1 || params.size() > 2)
2221 throw runtime_error(
2222 "getblock <hash> [decompositions]\n"
2223 "Returns details of a block with given block-hash.");
2225 std::string strHash = params[0].get_str();
2226 uint256 hash(strHash);
2228 if (mapBlockIndex.count(hash) == 0)
2229 throw JSONRPCError(-5, "Block not found");
2231 CBlock block;
2232 CBlockIndex* pblockindex = mapBlockIndex[hash];
2233 block.ReadFromDisk(pblockindex, true);
2235 return blockToJSON(block, pblockindex,
2236 (params.size() > 1) ? params[1].get_obj() : emptyobj);
2250 // Call Table
2254 static const CRPCCommand vRPCCommands[] =
2255 { // name function safe mode?
2256 // ------------------------ ----------------------- ----------
2257 { "help", &help, true },
2258 { "stop", &stop, true },
2259 { "getblockcount", &getblockcount, true },
2260 { "getblocknumber", &getblocknumber, true },
2261 { "getconnectioncount", &getconnectioncount, true },
2262 { "getdifficulty", &getdifficulty, true },
2263 { "getgenerate", &getgenerate, true },
2264 { "setgenerate", &setgenerate, true },
2265 { "gethashespersec", &gethashespersec, true },
2266 { "getinfo", &getinfo, true },
2267 { "getmininginfo", &getmininginfo, true },
2268 { "getnewaddress", &getnewaddress, true },
2269 { "getaccountaddress", &getaccountaddress, true },
2270 { "setaccount", &setaccount, true },
2271 { "getaccount", &getaccount, false },
2272 { "getaddressesbyaccount", &getaddressesbyaccount, true },
2273 { "sendtoaddress", &sendtoaddress, false },
2274 { "getreceivedbyaddress", &getreceivedbyaddress, false },
2275 { "getreceivedbyaccount", &getreceivedbyaccount, false },
2276 { "listreceivedbyaddress", &listreceivedbyaddress, false },
2277 { "listreceivedbyaccount", &listreceivedbyaccount, false },
2278 { "backupwallet", &backupwallet, true },
2279 { "keypoolrefill", &keypoolrefill, true },
2280 { "walletpassphrase", &walletpassphrase, true },
2281 { "walletpassphrasechange", &walletpassphrasechange, false },
2282 { "walletlock", &walletlock, true },
2283 { "encryptwallet", &encryptwallet, false },
2284 { "validateaddress", &validateaddress, true },
2285 { "getbalance", &getbalance, false },
2286 { "move", &movecmd, false },
2287 { "sendfrom", &sendfrom, false },
2288 { "sendmany", &sendmany, false },
2289 { "addmultisigaddress", &addmultisigaddress, false },
2290 { "getblock", &getblock, false },
2291 { "getblockhash", &getblockhash, false },
2292 { "gettransaction", &gettransaction, false },
2293 { "listtransactions", &listtransactions, false },
2294 { "signmessage", &signmessage, false },
2295 { "verifymessage", &verifymessage, false },
2296 { "getwork", &getwork, true },
2297 { "listaccounts", &listaccounts, false },
2298 { "settxfee", &settxfee, false },
2299 { "getmemorypool", &getmemorypool, true },
2300 { "listsinceblock", &listsinceblock, false },
2301 { "dumpprivkey", &dumpprivkey, false },
2302 { "importprivkey", &importprivkey, false },
2305 CRPCTable::CRPCTable()
2307 unsigned int vcidx;
2308 for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++)
2310 const CRPCCommand *pcmd;
2312 pcmd = &vRPCCommands[vcidx];
2313 mapCommands[pcmd->name] = pcmd;
2317 const CRPCCommand *CRPCTable::operator[](string name) const
2319 map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
2320 if (it == mapCommands.end())
2321 return NULL;
2322 return (*it).second;
2326 // HTTP protocol
2328 // This ain't Apache. We're just using HTTP header for the length field
2329 // and to be compatible with other JSON-RPC implementations.
2332 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2334 ostringstream s;
2335 s << "POST / HTTP/1.1\r\n"
2336 << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2337 << "Host: 127.0.0.1\r\n"
2338 << "Content-Type: application/json\r\n"
2339 << "Content-Length: " << strMsg.size() << "\r\n"
2340 << "Connection: close\r\n"
2341 << "Accept: application/json\r\n";
2342 BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2343 s << item.first << ": " << item.second << "\r\n";
2344 s << "\r\n" << strMsg;
2346 return s.str();
2349 string rfc1123Time()
2351 char buffer[64];
2352 time_t now;
2353 time(&now);
2354 struct tm* now_gmt = gmtime(&now);
2355 string locale(setlocale(LC_TIME, NULL));
2356 setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2357 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2358 setlocale(LC_TIME, locale.c_str());
2359 return string(buffer);
2362 static string HTTPReply(int nStatus, const string& strMsg, bool keepalive)
2364 if (nStatus == 401)
2365 return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2366 "Date: %s\r\n"
2367 "Server: bitcoin-json-rpc/%s\r\n"
2368 "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2369 "Content-Type: text/html\r\n"
2370 "Content-Length: 296\r\n"
2371 "\r\n"
2372 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2373 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2374 "<HTML>\r\n"
2375 "<HEAD>\r\n"
2376 "<TITLE>Error</TITLE>\r\n"
2377 "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2378 "</HEAD>\r\n"
2379 "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2380 "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2381 const char *cStatus;
2382 if (nStatus == 200) cStatus = "OK";
2383 else if (nStatus == 400) cStatus = "Bad Request";
2384 else if (nStatus == 403) cStatus = "Forbidden";
2385 else if (nStatus == 404) cStatus = "Not Found";
2386 else if (nStatus == 500) cStatus = "Internal Server Error";
2387 else cStatus = "";
2388 return strprintf(
2389 "HTTP/1.1 %d %s\r\n"
2390 "Date: %s\r\n"
2391 "Connection: %s\r\n"
2392 "Content-Length: %d\r\n"
2393 "Content-Type: application/json\r\n"
2394 "Server: bitcoin-json-rpc/%s\r\n"
2395 "\r\n"
2396 "%s",
2397 nStatus,
2398 cStatus,
2399 rfc1123Time().c_str(),
2400 keepalive ? "keep-alive" : "close",
2401 strMsg.size(),
2402 FormatFullVersion().c_str(),
2403 strMsg.c_str());
2406 int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto)
2408 string str;
2409 getline(stream, str);
2410 vector<string> vWords;
2411 boost::split(vWords, str, boost::is_any_of(" "));
2412 if (vWords.size() < 2)
2413 return 500;
2414 proto = 0;
2415 const char *ver = strstr(str.c_str(), "HTTP/1.");
2416 if (ver != NULL)
2417 proto = atoi(ver+7);
2418 return atoi(vWords[1].c_str());
2421 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2423 int nLen = 0;
2424 loop
2426 string str;
2427 std::getline(stream, str);
2428 if (str.empty() || str == "\r")
2429 break;
2430 string::size_type nColon = str.find(":");
2431 if (nColon != string::npos)
2433 string strHeader = str.substr(0, nColon);
2434 boost::trim(strHeader);
2435 boost::to_lower(strHeader);
2436 string strValue = str.substr(nColon+1);
2437 boost::trim(strValue);
2438 mapHeadersRet[strHeader] = strValue;
2439 if (strHeader == "content-length")
2440 nLen = atoi(strValue.c_str());
2443 return nLen;
2446 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2448 mapHeadersRet.clear();
2449 strMessageRet = "";
2451 // Read status
2452 int nProto = 0;
2453 int nStatus = ReadHTTPStatus(stream, nProto);
2455 // Read header
2456 int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2457 if (nLen < 0 || nLen > (int)MAX_SIZE)
2458 return 500;
2460 // Read message
2461 if (nLen > 0)
2463 vector<char> vch(nLen);
2464 stream.read(&vch[0], nLen);
2465 strMessageRet = string(vch.begin(), vch.end());
2468 string sConHdr = mapHeadersRet["connection"];
2470 if ((sConHdr != "close") && (sConHdr != "keep-alive"))
2472 if (nProto >= 1)
2473 mapHeadersRet["connection"] = "keep-alive";
2474 else
2475 mapHeadersRet["connection"] = "close";
2478 return nStatus;
2481 bool HTTPAuthorized(map<string, string>& mapHeaders)
2483 string strAuth = mapHeaders["authorization"];
2484 if (strAuth.substr(0,6) != "Basic ")
2485 return false;
2486 string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2487 string strUserPass = DecodeBase64(strUserPass64);
2488 return strUserPass == strRPCUserColonPass;
2492 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
2493 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2494 // unspecified (HTTP errors and contents of 'error').
2496 // 1.0 spec: http://json-rpc.org/wiki/specification
2497 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2498 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2501 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2503 Object request;
2504 request.push_back(Pair("method", strMethod));
2505 request.push_back(Pair("params", params));
2506 request.push_back(Pair("id", id));
2507 return write_string(Value(request), false) + "\n";
2510 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2512 Object reply;
2513 if (error.type() != null_type)
2514 reply.push_back(Pair("result", Value::null));
2515 else
2516 reply.push_back(Pair("result", result));
2517 reply.push_back(Pair("error", error));
2518 reply.push_back(Pair("id", id));
2519 return write_string(Value(reply), false) + "\n";
2522 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2524 // Send error reply from json-rpc error object
2525 int nStatus = 500;
2526 int code = find_value(objError, "code").get_int();
2527 if (code == -32600) nStatus = 400;
2528 else if (code == -32601) nStatus = 404;
2529 string strReply = JSONRPCReply(Value::null, objError, id);
2530 stream << HTTPReply(nStatus, strReply, false) << std::flush;
2533 bool ClientAllowed(const string& strAddress)
2535 if (strAddress == asio::ip::address_v4::loopback().to_string())
2536 return true;
2537 const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2538 BOOST_FOREACH(string strAllow, vAllow)
2539 if (WildcardMatch(strAddress, strAllow))
2540 return true;
2541 return false;
2545 // IOStream device that speaks SSL but can also speak non-SSL
2547 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2548 public:
2549 SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2551 fUseSSL = fUseSSLIn;
2552 fNeedHandshake = fUseSSLIn;
2555 void handshake(ssl::stream_base::handshake_type role)
2557 if (!fNeedHandshake) return;
2558 fNeedHandshake = false;
2559 stream.handshake(role);
2561 std::streamsize read(char* s, std::streamsize n)
2563 handshake(ssl::stream_base::server); // HTTPS servers read first
2564 if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2565 return stream.next_layer().read_some(asio::buffer(s, n));
2567 std::streamsize write(const char* s, std::streamsize n)
2569 handshake(ssl::stream_base::client); // HTTPS clients write first
2570 if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2571 return asio::write(stream.next_layer(), asio::buffer(s, n));
2573 bool connect(const std::string& server, const std::string& port)
2575 ip::tcp::resolver resolver(stream.get_io_service());
2576 ip::tcp::resolver::query query(server.c_str(), port.c_str());
2577 ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2578 ip::tcp::resolver::iterator end;
2579 boost::system::error_code error = asio::error::host_not_found;
2580 while (error && endpoint_iterator != end)
2582 stream.lowest_layer().close();
2583 stream.lowest_layer().connect(*endpoint_iterator++, error);
2585 if (error)
2586 return false;
2587 return true;
2590 private:
2591 bool fNeedHandshake;
2592 bool fUseSSL;
2593 SSLStream& stream;
2596 class AcceptedConnection
2598 public:
2599 SSLStream sslStream;
2600 SSLIOStreamDevice d;
2601 iostreams::stream<SSLIOStreamDevice> stream;
2603 ip::tcp::endpoint peer;
2605 AcceptedConnection(asio::io_service &io_service, ssl::context &context,
2606 bool fUseSSL) : sslStream(io_service, context), d(sslStream, fUseSSL),
2607 stream(d) { ; }
2610 void ThreadRPCServer(void* parg)
2612 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2615 vnThreadsRunning[THREAD_RPCLISTENER]++;
2616 ThreadRPCServer2(parg);
2617 vnThreadsRunning[THREAD_RPCLISTENER]--;
2619 catch (std::exception& e) {
2620 vnThreadsRunning[THREAD_RPCLISTENER]--;
2621 PrintException(&e, "ThreadRPCServer()");
2622 } catch (...) {
2623 vnThreadsRunning[THREAD_RPCLISTENER]--;
2624 PrintException(NULL, "ThreadRPCServer()");
2626 printf("ThreadRPCServer exited\n");
2629 void ThreadRPCServer2(void* parg)
2631 printf("ThreadRPCServer started\n");
2633 strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2634 if (mapArgs["-rpcpassword"] == "")
2636 unsigned char rand_pwd[32];
2637 RAND_bytes(rand_pwd, 32);
2638 string strWhatAmI = "To use bitcoind";
2639 if (mapArgs.count("-server"))
2640 strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2641 else if (mapArgs.count("-daemon"))
2642 strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2643 ThreadSafeMessageBox(strprintf(
2644 _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2645 "It is recommended you use the following random password:\n"
2646 "rpcuser=bitcoinrpc\n"
2647 "rpcpassword=%s\n"
2648 "(you do not need to remember this password)\n"
2649 "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2650 strWhatAmI.c_str(),
2651 GetConfigFile().string().c_str(),
2652 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2653 _("Error"), wxOK | wxMODAL);
2654 QueueShutdown();
2655 return;
2658 bool fUseSSL = GetBoolArg("-rpcssl");
2659 asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2661 asio::io_service io_service;
2662 ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2663 ip::tcp::acceptor acceptor(io_service);
2666 acceptor.open(endpoint.protocol());
2667 acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2668 acceptor.bind(endpoint);
2669 acceptor.listen(socket_base::max_connections);
2671 catch(boost::system::system_error &e)
2673 ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2674 _("Error"), wxOK | wxMODAL);
2675 QueueShutdown();
2676 return;
2679 ssl::context context(io_service, ssl::context::sslv23);
2680 if (fUseSSL)
2682 context.set_options(ssl::context::no_sslv2);
2684 filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2685 if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2686 if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
2687 else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2689 filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2690 if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2691 if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
2692 else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2694 string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2695 SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2698 loop
2700 // Accept connection
2701 AcceptedConnection *conn =
2702 new AcceptedConnection(io_service, context, fUseSSL);
2704 vnThreadsRunning[THREAD_RPCLISTENER]--;
2705 acceptor.accept(conn->sslStream.lowest_layer(), conn->peer);
2706 vnThreadsRunning[THREAD_RPCLISTENER]++;
2708 if (fShutdown)
2710 delete conn;
2711 return;
2714 // Restrict callers by IP. It is important to
2715 // do this before starting client thread, to filter out
2716 // certain DoS and misbehaving clients.
2717 if (!ClientAllowed(conn->peer.address().to_string()))
2719 // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2720 if (!fUseSSL)
2721 conn->stream << HTTPReply(403, "", false) << std::flush;
2722 delete conn;
2725 // start HTTP client thread
2726 else if (!CreateThread(ThreadRPCServer3, conn)) {
2727 printf("Failed to create RPC server client thread\n");
2728 delete conn;
2733 void ThreadRPCServer3(void* parg)
2735 IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer3(parg));
2736 vnThreadsRunning[THREAD_RPCHANDLER]++;
2737 AcceptedConnection *conn = (AcceptedConnection *) parg;
2739 bool fRun = true;
2740 loop {
2741 if (fShutdown || !fRun)
2743 conn->stream.close();
2744 delete conn;
2745 --vnThreadsRunning[THREAD_RPCHANDLER];
2746 return;
2748 map<string, string> mapHeaders;
2749 string strRequest;
2751 ReadHTTP(conn->stream, mapHeaders, strRequest);
2753 // Check authorization
2754 if (mapHeaders.count("authorization") == 0)
2756 conn->stream << HTTPReply(401, "", false) << std::flush;
2757 break;
2759 if (!HTTPAuthorized(mapHeaders))
2761 printf("ThreadRPCServer incorrect password attempt from %s\n", conn->peer.address().to_string().c_str());
2762 /* Deter brute-forcing short passwords.
2763 If this results in a DOS the user really
2764 shouldn't have their RPC port exposed.*/
2765 if (mapArgs["-rpcpassword"].size() < 20)
2766 Sleep(250);
2768 conn->stream << HTTPReply(401, "", false) << std::flush;
2769 break;
2771 if (mapHeaders["connection"] == "close")
2772 fRun = false;
2774 Value id = Value::null;
2777 // Parse request
2778 Value valRequest;
2779 if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2780 throw JSONRPCError(-32700, "Parse error");
2781 const Object& request = valRequest.get_obj();
2783 // Parse id now so errors from here on will have the id
2784 id = find_value(request, "id");
2786 // Parse method
2787 Value valMethod = find_value(request, "method");
2788 if (valMethod.type() == null_type)
2789 throw JSONRPCError(-32600, "Missing method");
2790 if (valMethod.type() != str_type)
2791 throw JSONRPCError(-32600, "Method must be a string");
2792 string strMethod = valMethod.get_str();
2793 if (strMethod != "getwork" && strMethod != "getmemorypool")
2794 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2796 // Parse params
2797 Value valParams = find_value(request, "params");
2798 Array params;
2799 if (valParams.type() == array_type)
2800 params = valParams.get_array();
2801 else if (valParams.type() == null_type)
2802 params = Array();
2803 else
2804 throw JSONRPCError(-32600, "Params must be an array");
2806 Value result = tableRPC.execute(strMethod, params);
2808 // Send reply
2809 string strReply = JSONRPCReply(result, Value::null, id);
2810 conn->stream << HTTPReply(200, strReply, fRun) << std::flush;
2812 catch (Object& objError)
2814 ErrorReply(conn->stream, objError, id);
2815 break;
2817 catch (std::exception& e)
2819 ErrorReply(conn->stream, JSONRPCError(-32700, e.what()), id);
2820 break;
2824 delete conn;
2825 vnThreadsRunning[THREAD_RPCHANDLER]--;
2828 json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_spirit::Array &params) const
2830 // Find method
2831 const CRPCCommand *pcmd = tableRPC[strMethod];
2832 if (!pcmd)
2833 throw JSONRPCError(-32601, "Method not found");
2835 // Observe safe mode
2836 string strWarning = GetWarnings("rpc");
2837 if (strWarning != "" && !GetBoolArg("-disablesafemode") &&
2838 !pcmd->okSafeMode)
2839 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2843 // Execute
2844 Value result;
2846 LOCK2(cs_main, pwalletMain->cs_wallet);
2847 result = pcmd->actor(params, false);
2849 return result;
2851 catch (std::exception& e)
2853 throw JSONRPCError(-1, e.what());
2858 Object CallRPC(const string& strMethod, const Array& params)
2860 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2861 throw runtime_error(strprintf(
2862 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2863 "If the file does not exist, create it with owner-readable-only file permissions."),
2864 GetConfigFile().string().c_str()));
2866 // Connect to localhost
2867 bool fUseSSL = GetBoolArg("-rpcssl");
2868 asio::io_service io_service;
2869 ssl::context context(io_service, ssl::context::sslv23);
2870 context.set_options(ssl::context::no_sslv2);
2871 SSLStream sslStream(io_service, context);
2872 SSLIOStreamDevice d(sslStream, fUseSSL);
2873 iostreams::stream<SSLIOStreamDevice> stream(d);
2874 if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2875 throw runtime_error("couldn't connect to server");
2877 // HTTP basic authentication
2878 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2879 map<string, string> mapRequestHeaders;
2880 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2882 // Send request
2883 string strRequest = JSONRPCRequest(strMethod, params, 1);
2884 string strPost = HTTPPost(strRequest, mapRequestHeaders);
2885 stream << strPost << std::flush;
2887 // Receive reply
2888 map<string, string> mapHeaders;
2889 string strReply;
2890 int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2891 if (nStatus == 401)
2892 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2893 else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2894 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2895 else if (strReply.empty())
2896 throw runtime_error("no response from server");
2898 // Parse reply
2899 Value valReply;
2900 if (!read_string(strReply, valReply))
2901 throw runtime_error("couldn't parse reply from server");
2902 const Object& reply = valReply.get_obj();
2903 if (reply.empty())
2904 throw runtime_error("expected reply to have result, error and id properties");
2906 return reply;
2912 template<typename T>
2913 void ConvertTo(Value& value)
2915 if (value.type() == str_type)
2917 // reinterpret string as unquoted json value
2918 Value value2;
2919 if (!read_string(value.get_str(), value2))
2920 throw runtime_error("type mismatch");
2921 value = value2.get_value<T>();
2923 else
2925 value = value.get_value<T>();
2929 // Convert strings to command-specific RPC representation
2930 Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
2932 Array params;
2933 BOOST_FOREACH(const std::string &param, strParams)
2934 params.push_back(param);
2936 int n = params.size();
2939 // Special case non-string parameter types
2941 if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
2942 if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2943 if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
2944 if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
2945 if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2946 if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2947 if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2948 if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
2949 if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2950 if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
2951 if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2952 if (strMethod == "getblock" && n > 1) ConvertTo<Object>(params[1]);
2953 if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2954 if (strMethod == "gettransaction" && n > 1) ConvertTo<Object>(params[1]);
2955 if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
2956 if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2957 if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
2958 if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
2959 if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2960 if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2961 if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2962 if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2963 if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
2964 if (strMethod == "sendmany" && n > 1)
2966 string s = params[1].get_str();
2967 Value v;
2968 if (!read_string(s, v) || v.type() != obj_type)
2969 throw runtime_error("type mismatch");
2970 params[1] = v.get_obj();
2972 if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
2973 if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
2974 if (strMethod == "addmultisigaddress" && n > 1)
2976 string s = params[1].get_str();
2977 Value v;
2978 if (!read_string(s, v) || v.type() != array_type)
2979 throw runtime_error("type mismatch "+s);
2980 params[1] = v.get_array();
2982 return params;
2985 int CommandLineRPC(int argc, char *argv[])
2987 string strPrint;
2988 int nRet = 0;
2991 // Skip switches
2992 while (argc > 1 && IsSwitchChar(argv[1][0]))
2994 argc--;
2995 argv++;
2998 // Method
2999 if (argc < 2)
3000 throw runtime_error("too few parameters");
3001 string strMethod = argv[1];
3003 // Parameters default to strings
3004 std::vector<std::string> strParams(&argv[2], &argv[argc]);
3005 Array params = RPCConvertValues(strMethod, strParams);
3007 // Execute
3008 Object reply = CallRPC(strMethod, params);
3010 // Parse reply
3011 const Value& result = find_value(reply, "result");
3012 const Value& error = find_value(reply, "error");
3014 if (error.type() != null_type)
3016 // Error
3017 strPrint = "error: " + write_string(error, false);
3018 int code = find_value(error.get_obj(), "code").get_int();
3019 nRet = abs(code);
3021 else
3023 // Result
3024 if (result.type() == null_type)
3025 strPrint = "";
3026 else if (result.type() == str_type)
3027 strPrint = result.get_str();
3028 else
3029 strPrint = write_string(result, true);
3032 catch (std::exception& e)
3034 strPrint = string("error: ") + e.what();
3035 nRet = 87;
3037 catch (...)
3039 PrintException(NULL, "CommandLineRPC()");
3042 if (strPrint != "")
3044 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
3046 return nRet;
3052 #ifdef TEST
3053 int main(int argc, char *argv[])
3055 #ifdef _MSC_VER
3056 // Turn off microsoft heap dump noise
3057 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
3058 _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
3059 #endif
3060 setbuf(stdin, NULL);
3061 setbuf(stdout, NULL);
3062 setbuf(stderr, NULL);
3066 if (argc >= 2 && string(argv[1]) == "-server")
3068 printf("server ready\n");
3069 ThreadRPCServer(NULL);
3071 else
3073 return CommandLineRPC(argc, argv);
3076 catch (std::exception& e) {
3077 PrintException(&e, "main()");
3078 } catch (...) {
3079 PrintException(NULL, "main()");
3081 return 0;
3083 #endif
3085 const CRPCTable tableRPC;