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