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