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