bitcoind changes to stop storing settings in wallet.dat.
[novacoin.git] / src / bitcoinrpc.cpp
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 license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "headers.h"
7 #include "db.h"
8 #include "net.h"
9 #include "init.h"
10 #undef printf
11 #include <boost/asio.hpp>
12 #include <boost/filesystem.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <boost/lexical_cast.hpp>
17 #ifdef USE_SSL
18 #include <boost/asio/ssl.hpp> 
19 #include <boost/filesystem.hpp>
20 #include <boost/filesystem/fstream.hpp>
21 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
22 #endif
23 #include "json/json_spirit_reader_template.h"
24 #include "json/json_spirit_writer_template.h"
25 #include "json/json_spirit_utils.h"
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.
31
32 using namespace std;
33 using namespace boost;
34 using namespace boost::asio;
35 using namespace json_spirit;
36
37 void ThreadRPCServer2(void* parg);
38 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
39 extern map<string, rpcfn_type> mapCallTable;
40
41 static std::string strRPCUserColonPass;
42
43 static int64 nWalletUnlockTime;
44 static CCriticalSection cs_nWalletUnlockTime;
45
46 extern Value dumpprivkey(const Array& params, bool fHelp);
47 extern Value importprivkey(const Array& params, bool fHelp);
48
49 Object JSONRPCError(int code, const string& message)
50 {
51     Object error;
52     error.push_back(Pair("code", code));
53     error.push_back(Pair("message", message));
54     return error;
55 }
56
57
58 void PrintConsole(const std::string &format, ...)
59 {
60     char buffer[50000];
61     int limit = sizeof(buffer);
62     va_list arg_ptr;
63     va_start(arg_ptr, format);
64     int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
65     va_end(arg_ptr);
66     if (ret < 0 || ret >= limit)
67     {
68         ret = limit - 1;
69         buffer[limit-1] = 0;
70     }
71     printf("%s", buffer);
72     fprintf(stdout, "%s", buffer);
73 }
74
75 double GetDifficulty(const CBlockIndex* blockindex = NULL)
76 {
77     // Floating point number that is a multiple of the minimum difficulty,
78     // minimum difficulty = 1.0.
79     if (blockindex == NULL)
80     {
81         if (pindexBest == NULL)
82             return 1.0;
83         else
84             blockindex = pindexBest;
85     }
86
87     int nShift = (blockindex->nBits >> 24) & 0xff;
88
89     double dDiff =
90         (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
91
92     while (nShift < 29)
93     {
94         dDiff *= 256.0;
95         nShift++;
96     }
97     while (nShift > 29)
98     {
99         dDiff /= 256.0;
100         nShift--;
101     }
102
103     return dDiff;
104 }
105
106
107 int64 AmountFromValue(const Value& value)
108 {
109     double dAmount = value.get_real();
110     if (dAmount <= 0.0 || dAmount > 21000000.0)
111         throw JSONRPCError(-3, "Invalid amount");
112     int64 nAmount = roundint64(dAmount * COIN);
113     if (!MoneyRange(nAmount))
114         throw JSONRPCError(-3, "Invalid amount");
115     return nAmount;
116 }
117
118 Value ValueFromAmount(int64 amount)
119 {
120     return (double)amount / (double)COIN;
121 }
122
123 std::string
124 HexBits(unsigned int nBits)
125 {
126     union {
127         int32_t nBits;
128         char cBits[4];
129     } uBits;
130     uBits.nBits = htonl((int32_t)nBits);
131     return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
132 }
133
134 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
135 {
136     int confirms = wtx.GetDepthInMainChain();
137     entry.push_back(Pair("confirmations", confirms));
138     if (confirms)
139     {
140         entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
141         entry.push_back(Pair("blockindex", wtx.nIndex));
142     }
143     entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
144     entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
145     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
146         entry.push_back(Pair(item.first, item.second));
147 }
148
149 string AccountFromValue(const Value& value)
150 {
151     string strAccount = value.get_str();
152     if (strAccount == "*")
153         throw JSONRPCError(-11, "Invalid account name");
154     return strAccount;
155 }
156
157 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
158 {
159     Object result;
160     result.push_back(Pair("hash", block.GetHash().GetHex()));
161     result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
162     result.push_back(Pair("height", blockindex->nHeight));
163     result.push_back(Pair("version", block.nVersion));
164     result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
165     result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
166     result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
167     result.push_back(Pair("bits", HexBits(block.nBits)));
168     result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
169     Array txhashes;
170     BOOST_FOREACH (const CTransaction&tx, block.vtx)
171         txhashes.push_back(tx.GetHash().GetHex());
172     result.push_back(Pair("tx", txhashes));
173
174     if (blockindex->pprev)
175         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
176     if (blockindex->pnext)
177         result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
178     return result;
179 }
180
181
182
183 ///
184 /// Note: This interface may still be subject to change.
185 ///
186
187
188 Value help(const Array& params, bool fHelp)
189 {
190     if (fHelp || params.size() > 1)
191         throw runtime_error(
192             "help [command]\n"
193             "List commands, or get help for a command.");
194
195     string strCommand;
196     if (params.size() > 0)
197         strCommand = params[0].get_str();
198
199     string strRet;
200     set<rpcfn_type> setDone;
201     for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
202     {
203         string strMethod = (*mi).first;
204         // We already filter duplicates, but these deprecated screw up the sort order
205         if (strMethod == "getamountreceived" ||
206             strMethod == "getallreceived" ||
207             strMethod == "getblocknumber" || // deprecated
208             (strMethod.find("label") != string::npos))
209             continue;
210         if (strCommand != "" && strMethod != strCommand)
211             continue;
212         try
213         {
214             Array params;
215             rpcfn_type pfn = (*mi).second;
216             if (setDone.insert(pfn).second)
217                 (*pfn)(params, true);
218         }
219         catch (std::exception& e)
220         {
221             // Help text is returned in an exception
222             string strHelp = string(e.what());
223             if (strCommand == "")
224                 if (strHelp.find('\n') != -1)
225                     strHelp = strHelp.substr(0, strHelp.find('\n'));
226             strRet += strHelp + "\n";
227         }
228     }
229     if (strRet == "")
230         strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
231     strRet = strRet.substr(0,strRet.size()-1);
232     return strRet;
233 }
234
235
236 Value stop(const Array& params, bool fHelp)
237 {
238     if (fHelp || params.size() != 0)
239         throw runtime_error(
240             "stop\n"
241             "Stop bitcoin server.");
242 #ifndef QT_GUI
243     // Shutdown will take long enough that the response should get back
244     CreateThread(Shutdown, NULL);
245     return "bitcoin server stopping";
246 #else
247     throw runtime_error("NYI: cannot shut down GUI with RPC command");
248 #endif
249 }
250
251
252 Value getblockcount(const Array& params, bool fHelp)
253 {
254     if (fHelp || params.size() != 0)
255         throw runtime_error(
256             "getblockcount\n"
257             "Returns the number of blocks in the longest block chain.");
258
259     return nBestHeight;
260 }
261
262
263 // deprecated
264 Value getblocknumber(const Array& params, bool fHelp)
265 {
266     if (fHelp || params.size() != 0)
267         throw runtime_error(
268             "getblocknumber\n"
269             "Deprecated.  Use getblockcount.");
270
271     return nBestHeight;
272 }
273
274
275 Value getconnectioncount(const Array& params, bool fHelp)
276 {
277     if (fHelp || params.size() != 0)
278         throw runtime_error(
279             "getconnectioncount\n"
280             "Returns the number of connections to other nodes.");
281
282     return (int)vNodes.size();
283 }
284
285
286 Value getdifficulty(const Array& params, bool fHelp)
287 {
288     if (fHelp || params.size() != 0)
289         throw runtime_error(
290             "getdifficulty\n"
291             "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
292
293     return GetDifficulty();
294 }
295
296
297 Value getgenerate(const Array& params, bool fHelp)
298 {
299     if (fHelp || params.size() != 0)
300         throw runtime_error(
301             "getgenerate\n"
302             "Returns true or false.");
303
304     return GetBoolArg("-gen");
305 }
306
307
308 Value setgenerate(const Array& params, bool fHelp)
309 {
310     if (fHelp || params.size() < 1 || params.size() > 2)
311         throw runtime_error(
312             "setgenerate <generate> [genproclimit]\n"
313             "<generate> is true or false to turn generation on or off.\n"
314             "Generation is limited to [genproclimit] processors, -1 is unlimited.");
315
316     bool fGenerate = true;
317     if (params.size() > 0)
318         fGenerate = params[0].get_bool();
319
320     if (params.size() > 1)
321     {
322         int nGenProcLimit = params[1].get_int();
323         mapArgs["-genproclimit"] = itostr(nGenProcLimit);
324         if (nGenProcLimit == 0)
325             fGenerate = false;
326     }
327     mapArgs["-gen"] = (fGenerate ? "1" : "0");
328
329     GenerateBitcoins(fGenerate, pwalletMain);
330     return Value::null;
331 }
332
333
334 Value gethashespersec(const Array& params, bool fHelp)
335 {
336     if (fHelp || params.size() != 0)
337         throw runtime_error(
338             "gethashespersec\n"
339             "Returns a recent hashes per second performance measurement while generating.");
340
341     if (GetTimeMillis() - nHPSTimerStart > 8000)
342         return (boost::int64_t)0;
343     return (boost::int64_t)dHashesPerSec;
344 }
345
346
347 Value getinfo(const Array& params, bool fHelp)
348 {
349     if (fHelp || params.size() != 0)
350         throw runtime_error(
351             "getinfo\n"
352             "Returns an object containing various state info.");
353
354     Object obj;
355     obj.push_back(Pair("version",       (int)CLIENT_VERSION));
356     obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
357     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
358     obj.push_back(Pair("blocks",        (int)nBestHeight));
359     obj.push_back(Pair("connections",   (int)vNodes.size()));
360     obj.push_back(Pair("proxy",         (fUseProxy ? addrProxy.ToStringIPPort() : string())));
361     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
362     obj.push_back(Pair("testnet",       fTestNet));
363     obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
364     obj.push_back(Pair("keypoolsize",   pwalletMain->GetKeyPoolSize()));
365     obj.push_back(Pair("paytxfee",      ValueFromAmount(nTransactionFee)));
366     if (pwalletMain->IsCrypted())
367         obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
368     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
369     return obj;
370 }
371
372
373 Value getmininginfo(const Array& params, bool fHelp)
374 {
375     if (fHelp || params.size() != 0)
376         throw runtime_error(
377             "getmininginfo\n"
378             "Returns an object containing mining-related information.");
379
380     Object obj;
381     obj.push_back(Pair("blocks",        (int)nBestHeight));
382     obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
383     obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
384     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
385     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
386     obj.push_back(Pair("generate",      GetBoolArg("-gen")));
387     obj.push_back(Pair("genproclimit",  (int)GetArg("-genproclimit", -1)));
388     obj.push_back(Pair("hashespersec",  gethashespersec(params, false)));
389     obj.push_back(Pair("pooledtx",      (uint64_t)nPooledTx));
390     obj.push_back(Pair("testnet",       fTestNet));
391     return obj;
392 }
393
394
395 Value getnewaddress(const Array& params, bool fHelp)
396 {
397     if (fHelp || params.size() > 1)
398         throw runtime_error(
399             "getnewaddress [account]\n"
400             "Returns a new bitcoin address for receiving payments.  "
401             "If [account] is specified (recommended), it is added to the address book "
402             "so payments received with the address will be credited to [account].");
403
404     // Parse the account first so we don't generate a key if there's an error
405     string strAccount;
406     if (params.size() > 0)
407         strAccount = AccountFromValue(params[0]);
408
409     if (!pwalletMain->IsLocked())
410         pwalletMain->TopUpKeyPool();
411
412     // Generate a new key that is added to wallet
413     std::vector<unsigned char> newKey;
414     if (!pwalletMain->GetKeyFromPool(newKey, false))
415         throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
416     CBitcoinAddress address(newKey);
417
418     pwalletMain->SetAddressBookName(address, strAccount);
419
420     return address.ToString();
421 }
422
423
424 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
425 {
426     CWalletDB walletdb(pwalletMain->strWalletFile);
427
428     CAccount account;
429     walletdb.ReadAccount(strAccount, account);
430
431     bool bKeyUsed = false;
432
433     // Check if the current key has been used
434     if (!account.vchPubKey.empty())
435     {
436         CScript scriptPubKey;
437         scriptPubKey.SetBitcoinAddress(account.vchPubKey);
438         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
439              it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
440              ++it)
441         {
442             const CWalletTx& wtx = (*it).second;
443             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
444                 if (txout.scriptPubKey == scriptPubKey)
445                     bKeyUsed = true;
446         }
447     }
448
449     // Generate a new key
450     if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
451     {
452         if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
453             throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
454
455         pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
456         walletdb.WriteAccount(strAccount, account);
457     }
458
459     return CBitcoinAddress(account.vchPubKey);
460 }
461
462 Value getaccountaddress(const Array& params, bool fHelp)
463 {
464     if (fHelp || params.size() != 1)
465         throw runtime_error(
466             "getaccountaddress <account>\n"
467             "Returns the current bitcoin address for receiving payments to this account.");
468
469     // Parse the account first so we don't generate a key if there's an error
470     string strAccount = AccountFromValue(params[0]);
471
472     Value ret;
473
474     ret = GetAccountAddress(strAccount).ToString();
475
476     return ret;
477 }
478
479
480
481 Value setaccount(const Array& params, bool fHelp)
482 {
483     if (fHelp || params.size() < 1 || params.size() > 2)
484         throw runtime_error(
485             "setaccount <bitcoinaddress> <account>\n"
486             "Sets the account associated with the given address.");
487
488     CBitcoinAddress address(params[0].get_str());
489     if (!address.IsValid())
490         throw JSONRPCError(-5, "Invalid bitcoin address");
491
492
493     string strAccount;
494     if (params.size() > 1)
495         strAccount = AccountFromValue(params[1]);
496
497     // Detect when changing the account of an address that is the 'unused current key' of another account:
498     if (pwalletMain->mapAddressBook.count(address))
499     {
500         string strOldAccount = pwalletMain->mapAddressBook[address];
501         if (address == GetAccountAddress(strOldAccount))
502             GetAccountAddress(strOldAccount, true);
503     }
504
505     pwalletMain->SetAddressBookName(address, strAccount);
506
507     return Value::null;
508 }
509
510
511 Value getaccount(const Array& params, bool fHelp)
512 {
513     if (fHelp || params.size() != 1)
514         throw runtime_error(
515             "getaccount <bitcoinaddress>\n"
516             "Returns the account associated with the given address.");
517
518     CBitcoinAddress address(params[0].get_str());
519     if (!address.IsValid())
520         throw JSONRPCError(-5, "Invalid bitcoin address");
521
522     string strAccount;
523     map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
524     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
525         strAccount = (*mi).second;
526     return strAccount;
527 }
528
529
530 Value getaddressesbyaccount(const Array& params, bool fHelp)
531 {
532     if (fHelp || params.size() != 1)
533         throw runtime_error(
534             "getaddressesbyaccount <account>\n"
535             "Returns the list of addresses for the given account.");
536
537     string strAccount = AccountFromValue(params[0]);
538
539     // Find all addresses that have the given account
540     Array ret;
541     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
542     {
543         const CBitcoinAddress& address = item.first;
544         const string& strName = item.second;
545         if (strName == strAccount)
546             ret.push_back(address.ToString());
547     }
548     return ret;
549 }
550
551 Value settxfee(const Array& params, bool fHelp)
552 {
553     if (fHelp || params.size() < 1 || params.size() > 1)
554         throw runtime_error(
555             "settxfee <amount>\n"
556             "<amount> is a real and is rounded to the nearest 0.00000001");
557
558     // Amount
559     int64 nAmount = 0;
560     if (params[0].get_real() != 0.0)
561         nAmount = AmountFromValue(params[0]);        // rejects 0.0 amounts
562
563     nTransactionFee = nAmount;
564     return true;
565 }
566
567 Value sendtoaddress(const Array& params, bool fHelp)
568 {
569     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
570         throw runtime_error(
571             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
572             "<amount> is a real and is rounded to the nearest 0.00000001\n"
573             "requires wallet passphrase to be set with walletpassphrase first");
574     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
575         throw runtime_error(
576             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
577             "<amount> is a real and is rounded to the nearest 0.00000001");
578
579     CBitcoinAddress address(params[0].get_str());
580     if (!address.IsValid())
581         throw JSONRPCError(-5, "Invalid bitcoin address");
582
583     // Amount
584     int64 nAmount = AmountFromValue(params[1]);
585
586     // Wallet comments
587     CWalletTx wtx;
588     if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
589         wtx.mapValue["comment"] = params[2].get_str();
590     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
591         wtx.mapValue["to"]      = params[3].get_str();
592
593     if (pwalletMain->IsLocked())
594         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
595
596     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
597     if (strError != "")
598         throw JSONRPCError(-4, strError);
599
600     return wtx.GetHash().GetHex();
601 }
602
603 Value signmessage(const Array& params, bool fHelp)
604 {
605     if (fHelp || params.size() != 2)
606         throw runtime_error(
607             "signmessage <bitcoinaddress> <message>\n"
608             "Sign a message with the private key of an address");
609
610     if (pwalletMain->IsLocked())
611         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
612
613     string strAddress = params[0].get_str();
614     string strMessage = params[1].get_str();
615
616     CBitcoinAddress addr(strAddress);
617     if (!addr.IsValid())
618         throw JSONRPCError(-3, "Invalid address");
619
620     CKey key;
621     if (!pwalletMain->GetKey(addr, key))
622         throw JSONRPCError(-4, "Private key not available");
623
624     CDataStream ss(SER_GETHASH);
625     ss << strMessageMagic;
626     ss << strMessage;
627
628     vector<unsigned char> vchSig;
629     if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
630         throw JSONRPCError(-5, "Sign failed");
631
632     return EncodeBase64(&vchSig[0], vchSig.size());
633 }
634
635 Value verifymessage(const Array& params, bool fHelp)
636 {
637     if (fHelp || params.size() != 3)
638         throw runtime_error(
639             "verifymessage <bitcoinaddress> <signature> <message>\n"
640             "Verify a signed message");
641
642     string strAddress  = params[0].get_str();
643     string strSign     = params[1].get_str();
644     string strMessage  = params[2].get_str();
645
646     CBitcoinAddress addr(strAddress);
647     if (!addr.IsValid())
648         throw JSONRPCError(-3, "Invalid address");
649
650     bool fInvalid = false;
651     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
652
653     if (fInvalid)
654         throw JSONRPCError(-5, "Malformed base64 encoding");
655
656     CDataStream ss(SER_GETHASH);
657     ss << strMessageMagic;
658     ss << strMessage;
659
660     CKey key;
661     if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
662         return false;
663
664     return (CBitcoinAddress(key.GetPubKey()) == addr);
665 }
666
667
668 Value getreceivedbyaddress(const Array& params, bool fHelp)
669 {
670     if (fHelp || params.size() < 1 || params.size() > 2)
671         throw runtime_error(
672             "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
673             "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
674
675     // Bitcoin address
676     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
677     CScript scriptPubKey;
678     if (!address.IsValid())
679         throw JSONRPCError(-5, "Invalid bitcoin address");
680     scriptPubKey.SetBitcoinAddress(address);
681     if (!IsMine(*pwalletMain,scriptPubKey))
682         return (double)0.0;
683
684     // Minimum confirmations
685     int nMinDepth = 1;
686     if (params.size() > 1)
687         nMinDepth = params[1].get_int();
688
689     // Tally
690     int64 nAmount = 0;
691     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
692     {
693         const CWalletTx& wtx = (*it).second;
694         if (wtx.IsCoinBase() || !wtx.IsFinal())
695             continue;
696
697         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
698             if (txout.scriptPubKey == scriptPubKey)
699                 if (wtx.GetDepthInMainChain() >= nMinDepth)
700                     nAmount += txout.nValue;
701     }
702
703     return  ValueFromAmount(nAmount);
704 }
705
706
707 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
708 {
709     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
710     {
711         const CBitcoinAddress& address = item.first;
712         const string& strName = item.second;
713         if (strName == strAccount)
714             setAddress.insert(address);
715     }
716 }
717
718
719 Value getreceivedbyaccount(const Array& params, bool fHelp)
720 {
721     if (fHelp || params.size() < 1 || params.size() > 2)
722         throw runtime_error(
723             "getreceivedbyaccount <account> [minconf=1]\n"
724             "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
725
726     // Minimum confirmations
727     int nMinDepth = 1;
728     if (params.size() > 1)
729         nMinDepth = params[1].get_int();
730
731     // Get the set of pub keys assigned to account
732     string strAccount = AccountFromValue(params[0]);
733     set<CBitcoinAddress> setAddress;
734     GetAccountAddresses(strAccount, setAddress);
735
736     // Tally
737     int64 nAmount = 0;
738     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
739     {
740         const CWalletTx& wtx = (*it).second;
741         if (wtx.IsCoinBase() || !wtx.IsFinal())
742             continue;
743
744         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
745         {
746             CBitcoinAddress address;
747             if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
748                 if (wtx.GetDepthInMainChain() >= nMinDepth)
749                     nAmount += txout.nValue;
750         }
751     }
752
753     return (double)nAmount / (double)COIN;
754 }
755
756
757 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
758 {
759     int64 nBalance = 0;
760
761     // Tally wallet transactions
762     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
763     {
764         const CWalletTx& wtx = (*it).second;
765         if (!wtx.IsFinal())
766             continue;
767
768         int64 nGenerated, nReceived, nSent, nFee;
769         wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
770
771         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
772             nBalance += nReceived;
773         nBalance += nGenerated - nSent - nFee;
774     }
775
776     // Tally internal accounting entries
777     nBalance += walletdb.GetAccountCreditDebit(strAccount);
778
779     return nBalance;
780 }
781
782 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
783 {
784     CWalletDB walletdb(pwalletMain->strWalletFile);
785     return GetAccountBalance(walletdb, strAccount, nMinDepth);
786 }
787
788
789 Value getbalance(const Array& params, bool fHelp)
790 {
791     if (fHelp || params.size() > 2)
792         throw runtime_error(
793             "getbalance [account] [minconf=1]\n"
794             "If [account] is not specified, returns the server's total available balance.\n"
795             "If [account] is specified, returns the balance in the account.");
796
797     if (params.size() == 0)
798         return  ValueFromAmount(pwalletMain->GetBalance());
799
800     int nMinDepth = 1;
801     if (params.size() > 1)
802         nMinDepth = params[1].get_int();
803
804     if (params[0].get_str() == "*") {
805         // Calculate total balance a different way from GetBalance()
806         // (GetBalance() sums up all unspent TxOuts)
807         // getbalance and getbalance '*' should always return the same number.
808         int64 nBalance = 0;
809         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
810         {
811             const CWalletTx& wtx = (*it).second;
812             if (!wtx.IsFinal())
813                 continue;
814
815             int64 allGeneratedImmature, allGeneratedMature, allFee;
816             allGeneratedImmature = allGeneratedMature = allFee = 0;
817             string strSentAccount;
818             list<pair<CBitcoinAddress, int64> > listReceived;
819             list<pair<CBitcoinAddress, int64> > listSent;
820             wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
821             if (wtx.GetDepthInMainChain() >= nMinDepth)
822                 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
823                     nBalance += r.second;
824             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
825                 nBalance -= r.second;
826             nBalance -= allFee;
827             nBalance += allGeneratedMature;
828         }
829         return  ValueFromAmount(nBalance);
830     }
831
832     string strAccount = AccountFromValue(params[0]);
833
834     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
835
836     return ValueFromAmount(nBalance);
837 }
838
839
840 Value movecmd(const Array& params, bool fHelp)
841 {
842     if (fHelp || params.size() < 3 || params.size() > 5)
843         throw runtime_error(
844             "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
845             "Move from one account in your wallet to another.");
846
847     string strFrom = AccountFromValue(params[0]);
848     string strTo = AccountFromValue(params[1]);
849     int64 nAmount = AmountFromValue(params[2]);
850     if (params.size() > 3)
851         // unused parameter, used to be nMinDepth, keep type-checking it though
852         (void)params[3].get_int();
853     string strComment;
854     if (params.size() > 4)
855         strComment = params[4].get_str();
856
857     CWalletDB walletdb(pwalletMain->strWalletFile);
858     walletdb.TxnBegin();
859
860     int64 nNow = GetAdjustedTime();
861
862     // Debit
863     CAccountingEntry debit;
864     debit.strAccount = strFrom;
865     debit.nCreditDebit = -nAmount;
866     debit.nTime = nNow;
867     debit.strOtherAccount = strTo;
868     debit.strComment = strComment;
869     walletdb.WriteAccountingEntry(debit);
870
871     // Credit
872     CAccountingEntry credit;
873     credit.strAccount = strTo;
874     credit.nCreditDebit = nAmount;
875     credit.nTime = nNow;
876     credit.strOtherAccount = strFrom;
877     credit.strComment = strComment;
878     walletdb.WriteAccountingEntry(credit);
879
880     walletdb.TxnCommit();
881
882     return true;
883 }
884
885
886 Value sendfrom(const Array& params, bool fHelp)
887 {
888     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
889         throw runtime_error(
890             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
891             "<amount> is a real and is rounded to the nearest 0.00000001\n"
892             "requires wallet passphrase to be set with walletpassphrase first");
893     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
894         throw runtime_error(
895             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
896             "<amount> is a real and is rounded to the nearest 0.00000001");
897
898     string strAccount = AccountFromValue(params[0]);
899     CBitcoinAddress address(params[1].get_str());
900     if (!address.IsValid())
901         throw JSONRPCError(-5, "Invalid bitcoin address");
902     int64 nAmount = AmountFromValue(params[2]);
903     int nMinDepth = 1;
904     if (params.size() > 3)
905         nMinDepth = params[3].get_int();
906
907     CWalletTx wtx;
908     wtx.strFromAccount = strAccount;
909     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
910         wtx.mapValue["comment"] = params[4].get_str();
911     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
912         wtx.mapValue["to"]      = params[5].get_str();
913
914     if (pwalletMain->IsLocked())
915         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
916
917     // Check funds
918     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
919     if (nAmount > nBalance)
920         throw JSONRPCError(-6, "Account has insufficient funds");
921
922     // Send
923     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
924     if (strError != "")
925         throw JSONRPCError(-4, strError);
926
927     return wtx.GetHash().GetHex();
928 }
929
930
931 Value sendmany(const Array& params, bool fHelp)
932 {
933     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
934         throw runtime_error(
935             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
936             "amounts are double-precision floating point numbers\n"
937             "requires wallet passphrase to be set with walletpassphrase first");
938     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
939         throw runtime_error(
940             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
941             "amounts are double-precision floating point numbers");
942
943     string strAccount = AccountFromValue(params[0]);
944     Object sendTo = params[1].get_obj();
945     int nMinDepth = 1;
946     if (params.size() > 2)
947         nMinDepth = params[2].get_int();
948
949     CWalletTx wtx;
950     wtx.strFromAccount = strAccount;
951     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
952         wtx.mapValue["comment"] = params[3].get_str();
953
954     set<CBitcoinAddress> setAddress;
955     vector<pair<CScript, int64> > vecSend;
956
957     int64 totalAmount = 0;
958     BOOST_FOREACH(const Pair& s, sendTo)
959     {
960         CBitcoinAddress address(s.name_);
961         if (!address.IsValid())
962             throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
963
964         if (setAddress.count(address))
965             throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
966         setAddress.insert(address);
967
968         CScript scriptPubKey;
969         scriptPubKey.SetBitcoinAddress(address);
970         int64 nAmount = AmountFromValue(s.value_); 
971         totalAmount += nAmount;
972
973         vecSend.push_back(make_pair(scriptPubKey, nAmount));
974     }
975
976     if (pwalletMain->IsLocked())
977         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
978
979     // Check funds
980     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
981     if (totalAmount > nBalance)
982         throw JSONRPCError(-6, "Account has insufficient funds");
983
984     // Send
985     CReserveKey keyChange(pwalletMain);
986     int64 nFeeRequired = 0;
987     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
988     if (!fCreated)
989     {
990         if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
991             throw JSONRPCError(-6, "Insufficient funds");
992         throw JSONRPCError(-4, "Transaction creation failed");
993     }
994     if (!pwalletMain->CommitTransaction(wtx, keyChange))
995         throw JSONRPCError(-4, "Transaction commit failed");
996
997     return wtx.GetHash().GetHex();
998 }
999
1000 Value addmultisigaddress(const Array& params, bool fHelp)
1001 {
1002     if (fHelp || params.size() < 2 || params.size() > 3)
1003     {
1004         string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
1005             "Add a nrequired-to-sign multisignature address to the wallet\"\n"
1006             "each key is a bitcoin address or hex-encoded public key\n"
1007             "If [account] is specified, assign address to [account].";
1008         throw runtime_error(msg);
1009     }
1010     if (!fTestNet)
1011         throw runtime_error("addmultisigaddress available only when running -testnet\n");
1012
1013     int nRequired = params[0].get_int();
1014     const Array& keys = params[1].get_array();
1015     string strAccount;
1016     if (params.size() > 2)
1017         strAccount = AccountFromValue(params[2]);
1018
1019     // Gather public keys
1020     if (nRequired < 1 || keys.size() < nRequired)
1021         throw runtime_error(
1022             strprintf("wrong number of keys"
1023                       "(got %d, need at least %d)", keys.size(), nRequired));
1024     std::vector<CKey> pubkeys;
1025     pubkeys.resize(keys.size());
1026     for (int i = 0; i < keys.size(); i++)
1027     {
1028         const std::string& ks = keys[i].get_str();
1029
1030         // Case 1: bitcoin address and we have full public key:
1031         CBitcoinAddress address(ks);
1032         if (address.IsValid())
1033         {
1034             if (address.IsScript())
1035                 throw runtime_error(
1036                     strprintf("%s is a pay-to-script address",ks.c_str()));
1037             std::vector<unsigned char> vchPubKey;
1038             if (!pwalletMain->GetPubKey(address, vchPubKey))
1039                 throw runtime_error(
1040                     strprintf("no full public key for address %s",ks.c_str()));
1041             if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1042                 throw runtime_error(" Invalid public key: "+ks);
1043         }
1044
1045         // Case 2: hex public key
1046         else if (IsHex(ks))
1047         {
1048             vector<unsigned char> vchPubKey = ParseHex(ks);
1049             if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1050                 throw runtime_error(" Invalid public key: "+ks);
1051         }
1052         else
1053         {
1054             throw runtime_error(" Invalid public key: "+ks);
1055         }
1056     }
1057
1058     // Construct using pay-to-script-hash:
1059     CScript inner;
1060     inner.SetMultisig(nRequired, pubkeys);
1061
1062     uint160 scriptHash = Hash160(inner);
1063     CScript scriptPubKey;
1064     scriptPubKey.SetPayToScriptHash(inner);
1065     pwalletMain->AddCScript(inner);
1066     CBitcoinAddress address;
1067     address.SetScriptHash160(scriptHash);
1068
1069     pwalletMain->SetAddressBookName(address, strAccount);
1070     return address.ToString();
1071 }
1072
1073
1074 struct tallyitem
1075 {
1076     int64 nAmount;
1077     int nConf;
1078     tallyitem()
1079     {
1080         nAmount = 0;
1081         nConf = std::numeric_limits<int>::max();
1082     }
1083 };
1084
1085 Value ListReceived(const Array& params, bool fByAccounts)
1086 {
1087     // Minimum confirmations
1088     int nMinDepth = 1;
1089     if (params.size() > 0)
1090         nMinDepth = params[0].get_int();
1091
1092     // Whether to include empty accounts
1093     bool fIncludeEmpty = false;
1094     if (params.size() > 1)
1095         fIncludeEmpty = params[1].get_bool();
1096
1097     // Tally
1098     map<CBitcoinAddress, tallyitem> mapTally;
1099     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1100     {
1101         const CWalletTx& wtx = (*it).second;
1102
1103         if (wtx.IsCoinBase() || !wtx.IsFinal())
1104             continue;
1105
1106         int nDepth = wtx.GetDepthInMainChain();
1107         if (nDepth < nMinDepth)
1108             continue;
1109
1110         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1111         {
1112             CBitcoinAddress address;
1113             if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1114                 continue;
1115
1116             tallyitem& item = mapTally[address];
1117             item.nAmount += txout.nValue;
1118             item.nConf = min(item.nConf, nDepth);
1119         }
1120     }
1121
1122     // Reply
1123     Array ret;
1124     map<string, tallyitem> mapAccountTally;
1125     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1126     {
1127         const CBitcoinAddress& address = item.first;
1128         const string& strAccount = item.second;
1129         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1130         if (it == mapTally.end() && !fIncludeEmpty)
1131             continue;
1132
1133         int64 nAmount = 0;
1134         int nConf = std::numeric_limits<int>::max();
1135         if (it != mapTally.end())
1136         {
1137             nAmount = (*it).second.nAmount;
1138             nConf = (*it).second.nConf;
1139         }
1140
1141         if (fByAccounts)
1142         {
1143             tallyitem& item = mapAccountTally[strAccount];
1144             item.nAmount += nAmount;
1145             item.nConf = min(item.nConf, nConf);
1146         }
1147         else
1148         {
1149             Object obj;
1150             obj.push_back(Pair("address",       address.ToString()));
1151             obj.push_back(Pair("account",       strAccount));
1152             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1153             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1154             ret.push_back(obj);
1155         }
1156     }
1157
1158     if (fByAccounts)
1159     {
1160         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1161         {
1162             int64 nAmount = (*it).second.nAmount;
1163             int nConf = (*it).second.nConf;
1164             Object obj;
1165             obj.push_back(Pair("account",       (*it).first));
1166             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1167             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1168             ret.push_back(obj);
1169         }
1170     }
1171
1172     return ret;
1173 }
1174
1175 Value listreceivedbyaddress(const Array& params, bool fHelp)
1176 {
1177     if (fHelp || params.size() > 2)
1178         throw runtime_error(
1179             "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1180             "[minconf] is the minimum number of confirmations before payments are included.\n"
1181             "[includeempty] whether to include addresses that haven't received any payments.\n"
1182             "Returns an array of objects containing:\n"
1183             "  \"address\" : receiving address\n"
1184             "  \"account\" : the account of the receiving address\n"
1185             "  \"amount\" : total amount received by the address\n"
1186             "  \"confirmations\" : number of confirmations of the most recent transaction included");
1187
1188     return ListReceived(params, false);
1189 }
1190
1191 Value listreceivedbyaccount(const Array& params, bool fHelp)
1192 {
1193     if (fHelp || params.size() > 2)
1194         throw runtime_error(
1195             "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1196             "[minconf] is the minimum number of confirmations before payments are included.\n"
1197             "[includeempty] whether to include accounts that haven't received any payments.\n"
1198             "Returns an array of objects containing:\n"
1199             "  \"account\" : the account of the receiving addresses\n"
1200             "  \"amount\" : total amount received by addresses with this account\n"
1201             "  \"confirmations\" : number of confirmations of the most recent transaction included");
1202
1203     return ListReceived(params, true);
1204 }
1205
1206 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1207 {
1208     int64 nGeneratedImmature, nGeneratedMature, nFee;
1209     string strSentAccount;
1210     list<pair<CBitcoinAddress, int64> > listReceived;
1211     list<pair<CBitcoinAddress, int64> > listSent;
1212
1213     wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1214
1215     bool fAllAccounts = (strAccount == string("*"));
1216
1217     // Generated blocks assigned to account ""
1218     if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1219     {
1220         Object entry;
1221         entry.push_back(Pair("account", string("")));
1222         if (nGeneratedImmature)
1223         {
1224             entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1225             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1226         }
1227         else
1228         {
1229             entry.push_back(Pair("category", "generate"));
1230             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1231         }
1232         if (fLong)
1233             WalletTxToJSON(wtx, entry);
1234         ret.push_back(entry);
1235     }
1236
1237     // Sent
1238     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1239     {
1240         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1241         {
1242             Object entry;
1243             entry.push_back(Pair("account", strSentAccount));
1244             entry.push_back(Pair("address", s.first.ToString()));
1245             entry.push_back(Pair("category", "send"));
1246             entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1247             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1248             if (fLong)
1249                 WalletTxToJSON(wtx, entry);
1250             ret.push_back(entry);
1251         }
1252     }
1253
1254     // Received
1255     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1256         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1257         {
1258             string account;
1259             if (pwalletMain->mapAddressBook.count(r.first))
1260                 account = pwalletMain->mapAddressBook[r.first];
1261             if (fAllAccounts || (account == strAccount))
1262             {
1263                 Object entry;
1264                 entry.push_back(Pair("account", account));
1265                 entry.push_back(Pair("address", r.first.ToString()));
1266                 entry.push_back(Pair("category", "receive"));
1267                 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1268                 if (fLong)
1269                     WalletTxToJSON(wtx, entry);
1270                 ret.push_back(entry);
1271             }
1272         }
1273 }
1274
1275 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1276 {
1277     bool fAllAccounts = (strAccount == string("*"));
1278
1279     if (fAllAccounts || acentry.strAccount == strAccount)
1280     {
1281         Object entry;
1282         entry.push_back(Pair("account", acentry.strAccount));
1283         entry.push_back(Pair("category", "move"));
1284         entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1285         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1286         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1287         entry.push_back(Pair("comment", acentry.strComment));
1288         ret.push_back(entry);
1289     }
1290 }
1291
1292 Value listtransactions(const Array& params, bool fHelp)
1293 {
1294     if (fHelp || params.size() > 3)
1295         throw runtime_error(
1296             "listtransactions [account] [count=10] [from=0]\n"
1297             "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1298
1299     string strAccount = "*";
1300     if (params.size() > 0)
1301         strAccount = params[0].get_str();
1302     int nCount = 10;
1303     if (params.size() > 1)
1304         nCount = params[1].get_int();
1305     int nFrom = 0;
1306     if (params.size() > 2)
1307         nFrom = params[2].get_int();
1308
1309     Array ret;
1310     CWalletDB walletdb(pwalletMain->strWalletFile);
1311
1312     // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1313     typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1314     typedef multimap<int64, TxPair > TxItems;
1315     TxItems txByTime;
1316
1317     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1318     {
1319         CWalletTx* wtx = &((*it).second);
1320         txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1321     }
1322     list<CAccountingEntry> acentries;
1323     walletdb.ListAccountCreditDebit(strAccount, acentries);
1324     BOOST_FOREACH(CAccountingEntry& entry, acentries)
1325     {
1326         txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1327     }
1328
1329     // Now: iterate backwards until we have nCount items to return:
1330     TxItems::reverse_iterator it = txByTime.rbegin();
1331     if (txByTime.size() > nFrom) std::advance(it, nFrom);
1332     for (; it != txByTime.rend(); ++it)
1333     {
1334         CWalletTx *const pwtx = (*it).second.first;
1335         if (pwtx != 0)
1336             ListTransactions(*pwtx, strAccount, 0, true, ret);
1337         CAccountingEntry *const pacentry = (*it).second.second;
1338         if (pacentry != 0)
1339             AcentryToJSON(*pacentry, strAccount, ret);
1340
1341         if (ret.size() >= nCount) break;
1342     }
1343     // ret is now newest to oldest
1344     
1345     // Make sure we return only last nCount items (sends-to-self might give us an extra):
1346     if (ret.size() > nCount)
1347     {
1348         Array::iterator last = ret.begin();
1349         std::advance(last, nCount);
1350         ret.erase(last, ret.end());
1351     }
1352     std::reverse(ret.begin(), ret.end()); // oldest to newest
1353
1354     return ret;
1355 }
1356
1357 Value listaccounts(const Array& params, bool fHelp)
1358 {
1359     if (fHelp || params.size() > 1)
1360         throw runtime_error(
1361             "listaccounts [minconf=1]\n"
1362             "Returns Object that has account names as keys, account balances as values.");
1363
1364     int nMinDepth = 1;
1365     if (params.size() > 0)
1366         nMinDepth = params[0].get_int();
1367
1368     map<string, int64> mapAccountBalances;
1369     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1370         if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1371             mapAccountBalances[entry.second] = 0;
1372     }
1373
1374     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1375     {
1376         const CWalletTx& wtx = (*it).second;
1377         int64 nGeneratedImmature, nGeneratedMature, nFee;
1378         string strSentAccount;
1379         list<pair<CBitcoinAddress, int64> > listReceived;
1380         list<pair<CBitcoinAddress, int64> > listSent;
1381         wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1382         mapAccountBalances[strSentAccount] -= nFee;
1383         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1384             mapAccountBalances[strSentAccount] -= s.second;
1385         if (wtx.GetDepthInMainChain() >= nMinDepth)
1386         {
1387             mapAccountBalances[""] += nGeneratedMature;
1388             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1389                 if (pwalletMain->mapAddressBook.count(r.first))
1390                     mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1391                 else
1392                     mapAccountBalances[""] += r.second;
1393         }
1394     }
1395
1396     list<CAccountingEntry> acentries;
1397     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1398     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1399         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1400
1401     Object ret;
1402     BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1403         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1404     }
1405     return ret;
1406 }
1407
1408 Value listsinceblock(const Array& params, bool fHelp)
1409 {
1410     if (fHelp)
1411         throw runtime_error(
1412             "listsinceblock [blockid] [target-confirmations]\n"
1413             "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1414
1415     CBlockIndex *pindex = NULL;
1416     int target_confirms = 1;
1417
1418     if (params.size() > 0)
1419     {
1420         uint256 blockId = 0;
1421
1422         blockId.SetHex(params[0].get_str());
1423         pindex = CBlockLocator(blockId).GetBlockIndex();
1424     }
1425
1426     if (params.size() > 1)
1427     {
1428         target_confirms = params[1].get_int();
1429
1430         if (target_confirms < 1)
1431             throw JSONRPCError(-8, "Invalid parameter");
1432     }
1433
1434     int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1435
1436     Array transactions;
1437
1438     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1439     {
1440         CWalletTx tx = (*it).second;
1441
1442         if (depth == -1 || tx.GetDepthInMainChain() < depth)
1443             ListTransactions(tx, "*", 0, true, transactions);
1444     }
1445
1446     uint256 lastblock;
1447
1448     if (target_confirms == 1)
1449     {
1450         printf("oops!\n");
1451         lastblock = hashBestChain;
1452     }
1453     else
1454     {
1455         int target_height = pindexBest->nHeight + 1 - target_confirms;
1456
1457         CBlockIndex *block;
1458         for (block = pindexBest;
1459              block && block->nHeight > target_height;
1460              block = block->pprev)  { }
1461
1462         lastblock = block ? block->GetBlockHash() : 0;
1463     }
1464
1465     Object ret;
1466     ret.push_back(Pair("transactions", transactions));
1467     ret.push_back(Pair("lastblock", lastblock.GetHex()));
1468
1469     return ret;
1470 }
1471
1472 Value gettransaction(const Array& params, bool fHelp)
1473 {
1474     if (fHelp || params.size() != 1)
1475         throw runtime_error(
1476             "gettransaction <txid>\n"
1477             "Get detailed information about <txid>");
1478
1479     uint256 hash;
1480     hash.SetHex(params[0].get_str());
1481
1482     Object entry;
1483
1484     if (!pwalletMain->mapWallet.count(hash))
1485         throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1486     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1487
1488     int64 nCredit = wtx.GetCredit();
1489     int64 nDebit = wtx.GetDebit();
1490     int64 nNet = nCredit - nDebit;
1491     int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1492
1493     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1494     if (wtx.IsFromMe())
1495         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1496
1497     WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1498
1499     Array details;
1500     ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1501     entry.push_back(Pair("details", details));
1502
1503     return entry;
1504 }
1505
1506
1507 Value backupwallet(const Array& params, bool fHelp)
1508 {
1509     if (fHelp || params.size() != 1)
1510         throw runtime_error(
1511             "backupwallet <destination>\n"
1512             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1513
1514     string strDest = params[0].get_str();
1515     BackupWallet(*pwalletMain, strDest);
1516
1517     return Value::null;
1518 }
1519
1520
1521 Value keypoolrefill(const Array& params, bool fHelp)
1522 {
1523     if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1524         throw runtime_error(
1525             "keypoolrefill\n"
1526             "Fills the keypool, requires wallet passphrase to be set.");
1527     if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1528         throw runtime_error(
1529             "keypoolrefill\n"
1530             "Fills the keypool.");
1531
1532     if (pwalletMain->IsLocked())
1533         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1534
1535     pwalletMain->TopUpKeyPool();
1536
1537     if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1538         throw JSONRPCError(-4, "Error refreshing keypool.");
1539
1540     return Value::null;
1541 }
1542
1543
1544 void ThreadTopUpKeyPool(void* parg)
1545 {
1546     pwalletMain->TopUpKeyPool();
1547 }
1548
1549 void ThreadCleanWalletPassphrase(void* parg)
1550 {
1551     int64 nMyWakeTime = GetTimeMillis() + *((int*)parg) * 1000;
1552
1553     ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1554
1555     if (nWalletUnlockTime == 0)
1556     {
1557         nWalletUnlockTime = nMyWakeTime;
1558
1559         do
1560         {
1561             if (nWalletUnlockTime==0)
1562                 break;
1563             int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1564             if (nToSleep <= 0)
1565                 break;
1566
1567             LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1568             Sleep(nToSleep);
1569             ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1570
1571         } while(1);
1572
1573         if (nWalletUnlockTime)
1574         {
1575             nWalletUnlockTime = 0;
1576             pwalletMain->Lock();
1577         }
1578     }
1579     else
1580     {
1581         if (nWalletUnlockTime < nMyWakeTime)
1582             nWalletUnlockTime = nMyWakeTime;
1583     }
1584
1585     LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1586
1587     delete (int*)parg;
1588 }
1589
1590 Value walletpassphrase(const Array& params, bool fHelp)
1591 {
1592     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1593         throw runtime_error(
1594             "walletpassphrase <passphrase> <timeout>\n"
1595             "Stores the wallet decryption key in memory for <timeout> seconds.");
1596     if (fHelp)
1597         return true;
1598     if (!pwalletMain->IsCrypted())
1599         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1600
1601     if (!pwalletMain->IsLocked())
1602         throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1603
1604     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1605     SecureString strWalletPass;
1606     strWalletPass.reserve(100);
1607     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1608     // Alternately, find a way to make params[0] mlock()'d to begin with.
1609     strWalletPass = params[0].get_str().c_str();
1610
1611     if (strWalletPass.length() > 0)
1612     {
1613         if (!pwalletMain->Unlock(strWalletPass))
1614             throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1615     }
1616     else
1617         throw runtime_error(
1618             "walletpassphrase <passphrase> <timeout>\n"
1619             "Stores the wallet decryption key in memory for <timeout> seconds.");
1620
1621     CreateThread(ThreadTopUpKeyPool, NULL);
1622     int* pnSleepTime = new int(params[1].get_int());
1623     CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1624
1625     return Value::null;
1626 }
1627
1628
1629 Value walletpassphrasechange(const Array& params, bool fHelp)
1630 {
1631     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1632         throw runtime_error(
1633             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1634             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1635     if (fHelp)
1636         return true;
1637     if (!pwalletMain->IsCrypted())
1638         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1639
1640     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1641     // Alternately, find a way to make params[0] mlock()'d to begin with.
1642     SecureString strOldWalletPass;
1643     strOldWalletPass.reserve(100);
1644     strOldWalletPass = params[0].get_str().c_str();
1645
1646     SecureString strNewWalletPass;
1647     strNewWalletPass.reserve(100);
1648     strNewWalletPass = params[1].get_str().c_str();
1649
1650     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1651         throw runtime_error(
1652             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1653             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1654
1655     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1656         throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1657
1658     return Value::null;
1659 }
1660
1661
1662 Value walletlock(const Array& params, bool fHelp)
1663 {
1664     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1665         throw runtime_error(
1666             "walletlock\n"
1667             "Removes the wallet encryption key from memory, locking the wallet.\n"
1668             "After calling this method, you will need to call walletpassphrase again\n"
1669             "before being able to call any methods which require the wallet to be unlocked.");
1670     if (fHelp)
1671         return true;
1672     if (!pwalletMain->IsCrypted())
1673         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1674
1675     CRITICAL_BLOCK(cs_nWalletUnlockTime)
1676     {
1677         pwalletMain->Lock();
1678         nWalletUnlockTime = 0;
1679     }
1680
1681     return Value::null;
1682 }
1683
1684
1685 Value encryptwallet(const Array& params, bool fHelp)
1686 {
1687     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1688         throw runtime_error(
1689             "encryptwallet <passphrase>\n"
1690             "Encrypts the wallet with <passphrase>.");
1691     if (fHelp)
1692         return true;
1693     if (pwalletMain->IsCrypted())
1694         throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1695
1696 #ifdef QT_GUI
1697     // shutting down via RPC while the GUI is running does not work (yet):
1698     throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
1699 #endif
1700
1701     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1702     // Alternately, find a way to make params[0] mlock()'d to begin with.
1703     SecureString strWalletPass;
1704     strWalletPass.reserve(100);
1705     strWalletPass = params[0].get_str().c_str();
1706
1707     if (strWalletPass.length() < 1)
1708         throw runtime_error(
1709             "encryptwallet <passphrase>\n"
1710             "Encrypts the wallet with <passphrase>.");
1711
1712     if (!pwalletMain->EncryptWallet(strWalletPass))
1713         throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1714
1715     // BDB seems to have a bad habit of writing old data into
1716     // slack space in .dat files; that is bad if the old data is
1717     // unencrypted private keys.  So:
1718     CreateThread(Shutdown, NULL);
1719     return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1720 }
1721
1722
1723 Value validateaddress(const Array& params, bool fHelp)
1724 {
1725     if (fHelp || params.size() != 1)
1726         throw runtime_error(
1727             "validateaddress <bitcoinaddress>\n"
1728             "Return information about <bitcoinaddress>.");
1729
1730     CBitcoinAddress address(params[0].get_str());
1731     bool isValid = address.IsValid();
1732
1733     Object ret;
1734     ret.push_back(Pair("isvalid", isValid));
1735     if (isValid)
1736     {
1737         // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1738         // version of the address:
1739         string currentAddress = address.ToString();
1740         ret.push_back(Pair("address", currentAddress));
1741         if (pwalletMain->HaveKey(address))
1742         {
1743             ret.push_back(Pair("ismine", true));
1744             std::vector<unsigned char> vchPubKey;
1745             pwalletMain->GetPubKey(address, vchPubKey);
1746             ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1747             CKey key;
1748             key.SetPubKey(vchPubKey);
1749             ret.push_back(Pair("iscompressed", key.IsCompressed()));
1750         }
1751         else if (pwalletMain->HaveCScript(address.GetHash160()))
1752         {
1753             ret.push_back(Pair("isscript", true));
1754             CScript subscript;
1755             pwalletMain->GetCScript(address.GetHash160(), subscript);
1756             ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1757             std::vector<CBitcoinAddress> addresses;
1758             txnouttype whichType;
1759             int nRequired;
1760             ExtractAddresses(subscript, whichType, addresses, nRequired);
1761             ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1762             Array a;
1763             BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1764                 a.push_back(addr.ToString());
1765             ret.push_back(Pair("addresses", a));
1766             if (whichType == TX_MULTISIG)
1767                 ret.push_back(Pair("sigsrequired", nRequired));
1768         }
1769         else
1770             ret.push_back(Pair("ismine", false));
1771         if (pwalletMain->mapAddressBook.count(address))
1772             ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1773     }
1774     return ret;
1775 }
1776
1777 Value getwork(const Array& params, bool fHelp)
1778 {
1779     if (fHelp || params.size() > 1)
1780         throw runtime_error(
1781             "getwork [data]\n"
1782             "If [data] is not specified, returns formatted hash data to work on:\n"
1783             "  \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1784             "  \"data\" : block data\n"
1785             "  \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1786             "  \"target\" : little endian hash target\n"
1787             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1788
1789     if (vNodes.empty())
1790         throw JSONRPCError(-9, "Bitcoin is not connected!");
1791
1792     if (IsInitialBlockDownload())
1793         throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1794
1795     typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1796     static mapNewBlock_t mapNewBlock;
1797     static vector<CBlock*> vNewBlock;
1798     static CReserveKey reservekey(pwalletMain);
1799
1800     if (params.size() == 0)
1801     {
1802         // Update block
1803         static unsigned int nTransactionsUpdatedLast;
1804         static CBlockIndex* pindexPrev;
1805         static int64 nStart;
1806         static CBlock* pblock;
1807         if (pindexPrev != pindexBest ||
1808             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1809         {
1810             if (pindexPrev != pindexBest)
1811             {
1812                 // Deallocate old blocks since they're obsolete now
1813                 mapNewBlock.clear();
1814                 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1815                     delete pblock;
1816                 vNewBlock.clear();
1817             }
1818             nTransactionsUpdatedLast = nTransactionsUpdated;
1819             pindexPrev = pindexBest;
1820             nStart = GetTime();
1821
1822             // Create new block
1823             pblock = CreateNewBlock(reservekey);
1824             if (!pblock)
1825                 throw JSONRPCError(-7, "Out of memory");
1826             vNewBlock.push_back(pblock);
1827         }
1828
1829         // Update nTime
1830         pblock->UpdateTime(pindexPrev);
1831         pblock->nNonce = 0;
1832
1833         // Update nExtraNonce
1834         static unsigned int nExtraNonce = 0;
1835         IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1836
1837         // Save
1838         mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1839
1840         // Prebuild hash buffers
1841         char pmidstate[32];
1842         char pdata[128];
1843         char phash1[64];
1844         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1845
1846         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1847
1848         Object result;
1849         result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1850         result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
1851         result.push_back(Pair("hash1",    HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1852         result.push_back(Pair("target",   HexStr(BEGIN(hashTarget), END(hashTarget))));
1853         return result;
1854     }
1855     else
1856     {
1857         // Parse parameters
1858         vector<unsigned char> vchData = ParseHex(params[0].get_str());
1859         if (vchData.size() != 128)
1860             throw JSONRPCError(-8, "Invalid parameter");
1861         CBlock* pdata = (CBlock*)&vchData[0];
1862
1863         // Byte reverse
1864         for (int i = 0; i < 128/4; i++)
1865             ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1866
1867         // Get saved block
1868         if (!mapNewBlock.count(pdata->hashMerkleRoot))
1869             return false;
1870         CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1871
1872         pblock->nTime = pdata->nTime;
1873         pblock->nNonce = pdata->nNonce;
1874         pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1875         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1876
1877         return CheckWork(pblock, *pwalletMain, reservekey);
1878     }
1879 }
1880
1881
1882 Value getmemorypool(const Array& params, bool fHelp)
1883 {
1884     if (fHelp || params.size() > 1)
1885         throw runtime_error(
1886             "getmemorypool [data]\n"
1887             "If [data] is not specified, returns data needed to construct a block to work on:\n"
1888             "  \"version\" : block version\n"
1889             "  \"previousblockhash\" : hash of current highest block\n"
1890             "  \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1891             "  \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1892             "  \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1893             "  \"time\" : timestamp appropriate for next block\n"
1894             "  \"mintime\" : minimum timestamp appropriate for next block\n"
1895             "  \"curtime\" : current timestamp\n"
1896             "  \"bits\" : compressed target of next block\n"
1897             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1898
1899     if (params.size() == 0)
1900     {
1901         if (vNodes.empty())
1902             throw JSONRPCError(-9, "Bitcoin is not connected!");
1903
1904         if (IsInitialBlockDownload())
1905             throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1906
1907         static CReserveKey reservekey(pwalletMain);
1908
1909         // Update block
1910         static unsigned int nTransactionsUpdatedLast;
1911         static CBlockIndex* pindexPrev;
1912         static int64 nStart;
1913         static CBlock* pblock;
1914         if (pindexPrev != pindexBest ||
1915             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1916         {
1917             nTransactionsUpdatedLast = nTransactionsUpdated;
1918             pindexPrev = pindexBest;
1919             nStart = GetTime();
1920
1921             // Create new block
1922             if(pblock)
1923                 delete pblock;
1924             pblock = CreateNewBlock(reservekey);
1925             if (!pblock)
1926                 throw JSONRPCError(-7, "Out of memory");
1927         }
1928
1929         // Update nTime
1930         pblock->UpdateTime(pindexPrev);
1931         pblock->nNonce = 0;
1932
1933         Array transactions;
1934         BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1935             if(tx.IsCoinBase())
1936                 continue;
1937
1938             CDataStream ssTx;
1939             ssTx << tx;
1940
1941             transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1942         }
1943
1944         Object result;
1945         result.push_back(Pair("version", pblock->nVersion));
1946         result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1947         result.push_back(Pair("transactions", transactions));
1948         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1949         result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1950         result.push_back(Pair("time", (int64_t)pblock->nTime));
1951         result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1952         result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1953         result.push_back(Pair("bits", HexBits(pblock->nBits)));
1954
1955         return result;
1956     }
1957     else
1958     {
1959         // Parse parameters
1960         CDataStream ssBlock(ParseHex(params[0].get_str()));
1961         CBlock pblock;
1962         ssBlock >> pblock;
1963
1964         return ProcessBlock(NULL, &pblock);
1965     }
1966 }
1967
1968 Value getblockhash(const Array& params, bool fHelp)
1969 {
1970     if (fHelp || params.size() != 1)
1971         throw runtime_error(
1972             "getblockhash <index>\n"
1973             "Returns hash of block in best-block-chain at <index>.");
1974
1975     int nHeight = params[0].get_int();
1976     if (nHeight < 0 || nHeight > nBestHeight)
1977         throw runtime_error("Block number out of range.");
1978
1979     CBlock block;
1980     CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1981     while (pblockindex->nHeight > nHeight)
1982         pblockindex = pblockindex->pprev;
1983     return pblockindex->phashBlock->GetHex();
1984 }
1985
1986 Value getblock(const Array& params, bool fHelp)
1987 {
1988     if (fHelp || params.size() != 1)
1989         throw runtime_error(
1990             "getblock <hash>\n"
1991             "Returns details of a block with given block-hash.");
1992
1993     std::string strHash = params[0].get_str();
1994     uint256 hash(strHash);
1995
1996     if (mapBlockIndex.count(hash) == 0)
1997         throw JSONRPCError(-5, "Block not found");
1998
1999     CBlock block;
2000     CBlockIndex* pblockindex = mapBlockIndex[hash];
2001     block.ReadFromDisk(pblockindex, true);
2002
2003     return blockToJSON(block, pblockindex);
2004 }
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016 //
2017 // Call Table
2018 //
2019
2020 pair<string, rpcfn_type> pCallTable[] =
2021 {
2022     make_pair("help",                   &help),
2023     make_pair("stop",                   &stop),
2024     make_pair("getblockcount",          &getblockcount),
2025     make_pair("getblocknumber",         &getblocknumber),
2026     make_pair("getconnectioncount",     &getconnectioncount),
2027     make_pair("getdifficulty",          &getdifficulty),
2028     make_pair("getgenerate",            &getgenerate),
2029     make_pair("setgenerate",            &setgenerate),
2030     make_pair("gethashespersec",        &gethashespersec),
2031     make_pair("getinfo",                &getinfo),
2032     make_pair("getmininginfo",          &getmininginfo),
2033     make_pair("getnewaddress",          &getnewaddress),
2034     make_pair("getaccountaddress",      &getaccountaddress),
2035     make_pair("setaccount",             &setaccount),
2036     make_pair("getaccount",             &getaccount),
2037     make_pair("getaddressesbyaccount",  &getaddressesbyaccount),
2038     make_pair("sendtoaddress",          &sendtoaddress),
2039     make_pair("getreceivedbyaddress",   &getreceivedbyaddress),
2040     make_pair("getreceivedbyaccount",   &getreceivedbyaccount),
2041     make_pair("listreceivedbyaddress",  &listreceivedbyaddress),
2042     make_pair("listreceivedbyaccount",  &listreceivedbyaccount),
2043     make_pair("backupwallet",           &backupwallet),
2044     make_pair("keypoolrefill",          &keypoolrefill),
2045     make_pair("walletpassphrase",       &walletpassphrase),
2046     make_pair("walletpassphrasechange", &walletpassphrasechange),
2047     make_pair("walletlock",             &walletlock),
2048     make_pair("encryptwallet",          &encryptwallet),
2049     make_pair("validateaddress",        &validateaddress),
2050     make_pair("getbalance",             &getbalance),
2051     make_pair("move",                   &movecmd),
2052     make_pair("sendfrom",               &sendfrom),
2053     make_pair("sendmany",               &sendmany),
2054     make_pair("addmultisigaddress",     &addmultisigaddress),
2055     make_pair("getblock",               &getblock),
2056     make_pair("getblockhash",           &getblockhash),
2057     make_pair("gettransaction",         &gettransaction),
2058     make_pair("listtransactions",       &listtransactions),
2059     make_pair("signmessage",            &signmessage),
2060     make_pair("verifymessage",          &verifymessage),
2061     make_pair("getwork",                &getwork),
2062     make_pair("listaccounts",           &listaccounts),
2063     make_pair("settxfee",               &settxfee),
2064     make_pair("getmemorypool",          &getmemorypool),
2065     make_pair("listsinceblock",         &listsinceblock),
2066     make_pair("dumpprivkey",            &dumpprivkey),
2067     make_pair("importprivkey",          &importprivkey)
2068 };
2069 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2070
2071 string pAllowInSafeMode[] =
2072 {
2073     "help",
2074     "stop",
2075     "getblockcount",
2076     "getblocknumber",  // deprecated
2077     "getconnectioncount",
2078     "getdifficulty",
2079     "getgenerate",
2080     "setgenerate",
2081     "gethashespersec",
2082     "getinfo",
2083     "getmininginfo",
2084     "getnewaddress",
2085     "getaccountaddress",
2086     "getaccount",
2087     "getaddressesbyaccount",
2088     "backupwallet",
2089     "keypoolrefill",
2090     "walletpassphrase",
2091     "walletlock",
2092     "validateaddress",
2093     "getwork",
2094     "getmemorypool",
2095 };
2096 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2097
2098
2099
2100
2101 //
2102 // HTTP protocol
2103 //
2104 // This ain't Apache.  We're just using HTTP header for the length field
2105 // and to be compatible with other JSON-RPC implementations.
2106 //
2107
2108 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2109 {
2110     ostringstream s;
2111     s << "POST / HTTP/1.1\r\n"
2112       << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2113       << "Host: 127.0.0.1\r\n"
2114       << "Content-Type: application/json\r\n"
2115       << "Content-Length: " << strMsg.size() << "\r\n"
2116       << "Connection: close\r\n"
2117       << "Accept: application/json\r\n";
2118     BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2119         s << item.first << ": " << item.second << "\r\n";
2120     s << "\r\n" << strMsg;
2121
2122     return s.str();
2123 }
2124
2125 string rfc1123Time()
2126 {
2127     char buffer[64];
2128     time_t now;
2129     time(&now);
2130     struct tm* now_gmt = gmtime(&now);
2131     string locale(setlocale(LC_TIME, NULL));
2132     setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2133     strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2134     setlocale(LC_TIME, locale.c_str());
2135     return string(buffer);
2136 }
2137
2138 static string HTTPReply(int nStatus, const string& strMsg)
2139 {
2140     if (nStatus == 401)
2141         return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2142             "Date: %s\r\n"
2143             "Server: bitcoin-json-rpc/%s\r\n"
2144             "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2145             "Content-Type: text/html\r\n"
2146             "Content-Length: 296\r\n"
2147             "\r\n"
2148             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2149             "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2150             "<HTML>\r\n"
2151             "<HEAD>\r\n"
2152             "<TITLE>Error</TITLE>\r\n"
2153             "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2154             "</HEAD>\r\n"
2155             "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2156             "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2157     const char *cStatus;
2158          if (nStatus == 200) cStatus = "OK";
2159     else if (nStatus == 400) cStatus = "Bad Request";
2160     else if (nStatus == 403) cStatus = "Forbidden";
2161     else if (nStatus == 404) cStatus = "Not Found";
2162     else if (nStatus == 500) cStatus = "Internal Server Error";
2163     else cStatus = "";
2164     return strprintf(
2165             "HTTP/1.1 %d %s\r\n"
2166             "Date: %s\r\n"
2167             "Connection: close\r\n"
2168             "Content-Length: %d\r\n"
2169             "Content-Type: application/json\r\n"
2170             "Server: bitcoin-json-rpc/%s\r\n"
2171             "\r\n"
2172             "%s",
2173         nStatus,
2174         cStatus,
2175         rfc1123Time().c_str(),
2176         strMsg.size(),
2177         FormatFullVersion().c_str(),
2178         strMsg.c_str());
2179 }
2180
2181 int ReadHTTPStatus(std::basic_istream<char>& stream)
2182 {
2183     string str;
2184     getline(stream, str);
2185     vector<string> vWords;
2186     boost::split(vWords, str, boost::is_any_of(" "));
2187     if (vWords.size() < 2)
2188         return 500;
2189     return atoi(vWords[1].c_str());
2190 }
2191
2192 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2193 {
2194     int nLen = 0;
2195     loop
2196     {
2197         string str;
2198         std::getline(stream, str);
2199         if (str.empty() || str == "\r")
2200             break;
2201         string::size_type nColon = str.find(":");
2202         if (nColon != string::npos)
2203         {
2204             string strHeader = str.substr(0, nColon);
2205             boost::trim(strHeader);
2206             boost::to_lower(strHeader);
2207             string strValue = str.substr(nColon+1);
2208             boost::trim(strValue);
2209             mapHeadersRet[strHeader] = strValue;
2210             if (strHeader == "content-length")
2211                 nLen = atoi(strValue.c_str());
2212         }
2213     }
2214     return nLen;
2215 }
2216
2217 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2218 {
2219     mapHeadersRet.clear();
2220     strMessageRet = "";
2221
2222     // Read status
2223     int nStatus = ReadHTTPStatus(stream);
2224
2225     // Read header
2226     int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2227     if (nLen < 0 || nLen > MAX_SIZE)
2228         return 500;
2229
2230     // Read message
2231     if (nLen > 0)
2232     {
2233         vector<char> vch(nLen);
2234         stream.read(&vch[0], nLen);
2235         strMessageRet = string(vch.begin(), vch.end());
2236     }
2237
2238     return nStatus;
2239 }
2240
2241 bool HTTPAuthorized(map<string, string>& mapHeaders)
2242 {
2243     string strAuth = mapHeaders["authorization"];
2244     if (strAuth.substr(0,6) != "Basic ")
2245         return false;
2246     string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2247     string strUserPass = DecodeBase64(strUserPass64);
2248     return strUserPass == strRPCUserColonPass;
2249 }
2250
2251 //
2252 // JSON-RPC protocol.  Bitcoin speaks version 1.0 for maximum compatibility,
2253 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2254 // unspecified (HTTP errors and contents of 'error').
2255 //
2256 // 1.0 spec: http://json-rpc.org/wiki/specification
2257 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2258 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2259 //
2260
2261 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2262 {
2263     Object request;
2264     request.push_back(Pair("method", strMethod));
2265     request.push_back(Pair("params", params));
2266     request.push_back(Pair("id", id));
2267     return write_string(Value(request), false) + "\n";
2268 }
2269
2270 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2271 {
2272     Object reply;
2273     if (error.type() != null_type)
2274         reply.push_back(Pair("result", Value::null));
2275     else
2276         reply.push_back(Pair("result", result));
2277     reply.push_back(Pair("error", error));
2278     reply.push_back(Pair("id", id));
2279     return write_string(Value(reply), false) + "\n";
2280 }
2281
2282 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2283 {
2284     // Send error reply from json-rpc error object
2285     int nStatus = 500;
2286     int code = find_value(objError, "code").get_int();
2287     if (code == -32600) nStatus = 400;
2288     else if (code == -32601) nStatus = 404;
2289     string strReply = JSONRPCReply(Value::null, objError, id);
2290     stream << HTTPReply(nStatus, strReply) << std::flush;
2291 }
2292
2293 bool ClientAllowed(const string& strAddress)
2294 {
2295     if (strAddress == asio::ip::address_v4::loopback().to_string())
2296         return true;
2297     const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2298     BOOST_FOREACH(string strAllow, vAllow)
2299         if (WildcardMatch(strAddress, strAllow))
2300             return true;
2301     return false;
2302 }
2303
2304 #ifdef USE_SSL
2305 //
2306 // IOStream device that speaks SSL but can also speak non-SSL
2307 //
2308 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2309 public:
2310     SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2311     {
2312         fUseSSL = fUseSSLIn;
2313         fNeedHandshake = fUseSSLIn;
2314     }
2315
2316     void handshake(ssl::stream_base::handshake_type role)
2317     {
2318         if (!fNeedHandshake) return;
2319         fNeedHandshake = false;
2320         stream.handshake(role);
2321     }
2322     std::streamsize read(char* s, std::streamsize n)
2323     {
2324         handshake(ssl::stream_base::server); // HTTPS servers read first
2325         if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2326         return stream.next_layer().read_some(asio::buffer(s, n));
2327     }
2328     std::streamsize write(const char* s, std::streamsize n)
2329     {
2330         handshake(ssl::stream_base::client); // HTTPS clients write first
2331         if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2332         return asio::write(stream.next_layer(), asio::buffer(s, n));
2333     }
2334     bool connect(const std::string& server, const std::string& port)
2335     {
2336         ip::tcp::resolver resolver(stream.get_io_service());
2337         ip::tcp::resolver::query query(server.c_str(), port.c_str());
2338         ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2339         ip::tcp::resolver::iterator end;
2340         boost::system::error_code error = asio::error::host_not_found;
2341         while (error && endpoint_iterator != end)
2342         {
2343             stream.lowest_layer().close();
2344             stream.lowest_layer().connect(*endpoint_iterator++, error);
2345         }
2346         if (error)
2347             return false;
2348         return true;
2349     }
2350
2351 private:
2352     bool fNeedHandshake;
2353     bool fUseSSL;
2354     SSLStream& stream;
2355 };
2356 #endif
2357
2358 void ThreadRPCServer(void* parg)
2359 {
2360     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2361     try
2362     {
2363         vnThreadsRunning[THREAD_RPCSERVER]++;
2364         ThreadRPCServer2(parg);
2365         vnThreadsRunning[THREAD_RPCSERVER]--;
2366     }
2367     catch (std::exception& e) {
2368         vnThreadsRunning[THREAD_RPCSERVER]--;
2369         PrintException(&e, "ThreadRPCServer()");
2370     } catch (...) {
2371         vnThreadsRunning[THREAD_RPCSERVER]--;
2372         PrintException(NULL, "ThreadRPCServer()");
2373     }
2374     printf("ThreadRPCServer exiting\n");
2375 }
2376
2377 void ThreadRPCServer2(void* parg)
2378 {
2379     printf("ThreadRPCServer started\n");
2380
2381     strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2382     if (mapArgs["-rpcpassword"] == "")
2383     {
2384         unsigned char rand_pwd[32];
2385         RAND_bytes(rand_pwd, 32);
2386         string strWhatAmI = "To use bitcoind";
2387         if (mapArgs.count("-server"))
2388             strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2389         else if (mapArgs.count("-daemon"))
2390             strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2391         PrintConsole(
2392             _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
2393               "It is recommended you use the following random password:\n"
2394               "rpcuser=bitcoinrpc\n"
2395               "rpcpassword=%s\n"
2396               "(you do not need to remember this password)\n"
2397               "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2398                 strWhatAmI.c_str(),
2399                 GetConfigFile().c_str(),
2400                 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
2401 #ifndef QT_GUI
2402         CreateThread(Shutdown, NULL);
2403 #endif
2404         return;
2405     }
2406
2407     bool fUseSSL = GetBoolArg("-rpcssl");
2408     asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2409
2410     asio::io_service io_service;
2411     ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2412     ip::tcp::acceptor acceptor(io_service, endpoint);
2413
2414     acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2415
2416 #ifdef USE_SSL
2417     ssl::context context(io_service, ssl::context::sslv23);
2418     if (fUseSSL)
2419     {
2420         context.set_options(ssl::context::no_sslv2);
2421         filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2422         if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2423         if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2424         else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2425         filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2426         if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2427         if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2428         else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2429
2430         string ciphers = GetArg("-rpcsslciphers",
2431                                          "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2432         SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2433     }
2434 #else
2435     if (fUseSSL)
2436         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2437 #endif
2438
2439     loop
2440     {
2441         // Accept connection
2442 #ifdef USE_SSL
2443         SSLStream sslStream(io_service, context);
2444         SSLIOStreamDevice d(sslStream, fUseSSL);
2445         iostreams::stream<SSLIOStreamDevice> stream(d);
2446 #else
2447         ip::tcp::iostream stream;
2448 #endif
2449
2450         ip::tcp::endpoint peer;
2451         vnThreadsRunning[THREAD_RPCSERVER]--;
2452 #ifdef USE_SSL
2453         acceptor.accept(sslStream.lowest_layer(), peer);
2454 #else
2455         acceptor.accept(*stream.rdbuf(), peer);
2456 #endif
2457         vnThreadsRunning[4]++;
2458         if (fShutdown)
2459             return;
2460
2461         // Restrict callers by IP
2462         if (!ClientAllowed(peer.address().to_string()))
2463         {
2464             // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2465             if (!fUseSSL)
2466                 stream << HTTPReply(403, "") << std::flush;
2467             continue;
2468         }
2469
2470         map<string, string> mapHeaders;
2471         string strRequest;
2472
2473         boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2474         if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2475         {   // Timed out:
2476             acceptor.cancel();
2477             printf("ThreadRPCServer ReadHTTP timeout\n");
2478             continue;
2479         }
2480
2481         // Check authorization
2482         if (mapHeaders.count("authorization") == 0)
2483         {
2484             stream << HTTPReply(401, "") << std::flush;
2485             continue;
2486         }
2487         if (!HTTPAuthorized(mapHeaders))
2488         {
2489             printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2490             /* Deter brute-forcing short passwords.
2491                If this results in a DOS the user really
2492                shouldn't have their RPC port exposed.*/
2493             if (mapArgs["-rpcpassword"].size() < 20)
2494                 Sleep(250);
2495
2496             stream << HTTPReply(401, "") << std::flush;
2497             continue;
2498         }
2499
2500         Value id = Value::null;
2501         try
2502         {
2503             // Parse request
2504             Value valRequest;
2505             if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2506                 throw JSONRPCError(-32700, "Parse error");
2507             const Object& request = valRequest.get_obj();
2508
2509             // Parse id now so errors from here on will have the id
2510             id = find_value(request, "id");
2511
2512             // Parse method
2513             Value valMethod = find_value(request, "method");
2514             if (valMethod.type() == null_type)
2515                 throw JSONRPCError(-32600, "Missing method");
2516             if (valMethod.type() != str_type)
2517                 throw JSONRPCError(-32600, "Method must be a string");
2518             string strMethod = valMethod.get_str();
2519             if (strMethod != "getwork" && strMethod != "getmemorypool")
2520                 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2521
2522             // Parse params
2523             Value valParams = find_value(request, "params");
2524             Array params;
2525             if (valParams.type() == array_type)
2526                 params = valParams.get_array();
2527             else if (valParams.type() == null_type)
2528                 params = Array();
2529             else
2530                 throw JSONRPCError(-32600, "Params must be an array");
2531
2532             // Find method
2533             map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2534             if (mi == mapCallTable.end())
2535                 throw JSONRPCError(-32601, "Method not found");
2536
2537             // Observe safe mode
2538             string strWarning = GetWarnings("rpc");
2539             if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2540                 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2541
2542             try
2543             {
2544                 // Execute
2545                 Value result;
2546                 CRITICAL_BLOCK(cs_main)
2547                 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2548                     result = (*(*mi).second)(params, false);
2549
2550                 // Send reply
2551                 string strReply = JSONRPCReply(result, Value::null, id);
2552                 stream << HTTPReply(200, strReply) << std::flush;
2553             }
2554             catch (std::exception& e)
2555             {
2556                 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2557             }
2558         }
2559         catch (Object& objError)
2560         {
2561             ErrorReply(stream, objError, id);
2562         }
2563         catch (std::exception& e)
2564         {
2565             ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2566         }
2567     }
2568 }
2569
2570
2571
2572
2573 Object CallRPC(const string& strMethod, const Array& params)
2574 {
2575     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2576         throw runtime_error(strprintf(
2577             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2578               "If the file does not exist, create it with owner-readable-only file permissions."),
2579                 GetConfigFile().c_str()));
2580
2581     // Connect to localhost
2582     bool fUseSSL = GetBoolArg("-rpcssl");
2583 #ifdef USE_SSL
2584     asio::io_service io_service;
2585     ssl::context context(io_service, ssl::context::sslv23);
2586     context.set_options(ssl::context::no_sslv2);
2587     SSLStream sslStream(io_service, context);
2588     SSLIOStreamDevice d(sslStream, fUseSSL);
2589     iostreams::stream<SSLIOStreamDevice> stream(d);
2590     if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2591         throw runtime_error("couldn't connect to server");
2592 #else
2593     if (fUseSSL)
2594         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2595
2596     ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2597     if (stream.fail())
2598         throw runtime_error("couldn't connect to server");
2599 #endif
2600
2601
2602     // HTTP basic authentication
2603     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2604     map<string, string> mapRequestHeaders;
2605     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2606
2607     // Send request
2608     string strRequest = JSONRPCRequest(strMethod, params, 1);
2609     string strPost = HTTPPost(strRequest, mapRequestHeaders);
2610     stream << strPost << std::flush;
2611
2612     // Receive reply
2613     map<string, string> mapHeaders;
2614     string strReply;
2615     int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2616     if (nStatus == 401)
2617         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2618     else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2619         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2620     else if (strReply.empty())
2621         throw runtime_error("no response from server");
2622
2623     // Parse reply
2624     Value valReply;
2625     if (!read_string(strReply, valReply))
2626         throw runtime_error("couldn't parse reply from server");
2627     const Object& reply = valReply.get_obj();
2628     if (reply.empty())
2629         throw runtime_error("expected reply to have result, error and id properties");
2630
2631     return reply;
2632 }
2633
2634
2635
2636
2637 template<typename T>
2638 void ConvertTo(Value& value)
2639 {
2640     if (value.type() == str_type)
2641     {
2642         // reinterpret string as unquoted json value
2643         Value value2;
2644         if (!read_string(value.get_str(), value2))
2645             throw runtime_error("type mismatch");
2646         value = value2.get_value<T>();
2647     }
2648     else
2649     {
2650         value = value.get_value<T>();
2651     }
2652 }
2653
2654 int CommandLineRPC(int argc, char *argv[])
2655 {
2656     string strPrint;
2657     int nRet = 0;
2658     try
2659     {
2660         // Skip switches
2661         while (argc > 1 && IsSwitchChar(argv[1][0]))
2662         {
2663             argc--;
2664             argv++;
2665         }
2666
2667         // Method
2668         if (argc < 2)
2669             throw runtime_error("too few parameters");
2670         string strMethod = argv[1];
2671
2672         // Parameters default to strings
2673         Array params;
2674         for (int i = 2; i < argc; i++)
2675             params.push_back(argv[i]);
2676         int n = params.size();
2677
2678         //
2679         // Special case non-string parameter types
2680         //
2681         if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);
2682         if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
2683         if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);
2684         if (strMethod == "settxfee"               && n > 0) ConvertTo<double>(params[0]);
2685         if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2686         if (strMethod == "getreceivedbyaccount"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2687         if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2688         if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);
2689         if (strMethod == "listreceivedbyaccount"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2690         if (strMethod == "listreceivedbyaccount"  && n > 1) ConvertTo<bool>(params[1]);
2691         if (strMethod == "getbalance"             && n > 1) ConvertTo<boost::int64_t>(params[1]);
2692         if (strMethod == "getblockhash"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2693         if (strMethod == "move"                   && n > 2) ConvertTo<double>(params[2]);
2694         if (strMethod == "move"                   && n > 3) ConvertTo<boost::int64_t>(params[3]);
2695         if (strMethod == "sendfrom"               && n > 2) ConvertTo<double>(params[2]);
2696         if (strMethod == "sendfrom"               && n > 3) ConvertTo<boost::int64_t>(params[3]);
2697         if (strMethod == "listtransactions"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2698         if (strMethod == "listtransactions"       && n > 2) ConvertTo<boost::int64_t>(params[2]);
2699         if (strMethod == "listaccounts"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2700         if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2701         if (strMethod == "listsinceblock"         && n > 1) ConvertTo<boost::int64_t>(params[1]);
2702         if (strMethod == "sendmany"               && n > 1)
2703         {
2704             string s = params[1].get_str();
2705             Value v;
2706             if (!read_string(s, v) || v.type() != obj_type)
2707                 throw runtime_error("type mismatch");
2708             params[1] = v.get_obj();
2709         }
2710         if (strMethod == "sendmany"                && n > 2) ConvertTo<boost::int64_t>(params[2]);
2711         if (strMethod == "addmultisigaddress"      && n > 0) ConvertTo<boost::int64_t>(params[0]);
2712         if (strMethod == "addmultisigaddress"      && n > 1)
2713         {
2714             string s = params[1].get_str();
2715             Value v;
2716             if (!read_string(s, v) || v.type() != array_type)
2717                 throw runtime_error("type mismatch "+s);
2718             params[1] = v.get_array();
2719         }
2720
2721         // Execute
2722         Object reply = CallRPC(strMethod, params);
2723
2724         // Parse reply
2725         const Value& result = find_value(reply, "result");
2726         const Value& error  = find_value(reply, "error");
2727
2728         if (error.type() != null_type)
2729         {
2730             // Error
2731             strPrint = "error: " + write_string(error, false);
2732             int code = find_value(error.get_obj(), "code").get_int();
2733             nRet = abs(code);
2734         }
2735         else
2736         {
2737             // Result
2738             if (result.type() == null_type)
2739                 strPrint = "";
2740             else if (result.type() == str_type)
2741                 strPrint = result.get_str();
2742             else
2743                 strPrint = write_string(result, true);
2744         }
2745     }
2746     catch (std::exception& e)
2747     {
2748         strPrint = string("error: ") + e.what();
2749         nRet = 87;
2750     }
2751     catch (...)
2752     {
2753         PrintException(NULL, "CommandLineRPC()");
2754     }
2755
2756     if (strPrint != "")
2757     {
2758         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2759     }
2760     return nRet;
2761 }
2762
2763
2764
2765
2766 #ifdef TEST
2767 int main(int argc, char *argv[])
2768 {
2769 #ifdef _MSC_VER
2770     // Turn off microsoft heap dump noise
2771     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2772     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2773 #endif
2774     setbuf(stdin, NULL);
2775     setbuf(stdout, NULL);
2776     setbuf(stderr, NULL);
2777
2778     try
2779     {
2780         if (argc >= 2 && string(argv[1]) == "-server")
2781         {
2782             printf("server ready\n");
2783             ThreadRPCServer(NULL);
2784         }
2785         else
2786         {
2787             return CommandLineRPC(argc, argv);
2788         }
2789     }
2790     catch (std::exception& e) {
2791         PrintException(&e, "main()");
2792     } catch (...) {
2793         PrintException(NULL, "main()");
2794     }
2795     return 0;
2796 }
2797 #endif