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