Use a messagebox to display the error when -server is provided without providing...
[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     if (!fTestNet)
990         throw runtime_error("addmultisigaddress available only when running -testnet\n");
991
992     int nRequired = params[0].get_int();
993     const Array& keys = params[1].get_array();
994     string strAccount;
995     if (params.size() > 2)
996         strAccount = AccountFromValue(params[2]);
997
998     // Gather public keys
999     if (nRequired < 1 || keys.size() < nRequired)
1000         throw runtime_error(
1001             strprintf("wrong number of keys"
1002                       "(got %d, need at least %d)", keys.size(), nRequired));
1003     std::vector<CKey> pubkeys;
1004     pubkeys.resize(keys.size());
1005     for (int i = 0; i < keys.size(); i++)
1006     {
1007         const std::string& ks = keys[i].get_str();
1008
1009         // Case 1: bitcoin address and we have full public key:
1010         CBitcoinAddress address(ks);
1011         if (address.IsValid())
1012         {
1013             if (address.IsScript())
1014                 throw runtime_error(
1015                     strprintf("%s is a pay-to-script address",ks.c_str()));
1016             std::vector<unsigned char> vchPubKey;
1017             if (!pwalletMain->GetPubKey(address, vchPubKey))
1018                 throw runtime_error(
1019                     strprintf("no full public key for address %s",ks.c_str()));
1020             if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1021                 throw runtime_error(" Invalid public key: "+ks);
1022         }
1023
1024         // Case 2: hex public key
1025         else if (IsHex(ks))
1026         {
1027             vector<unsigned char> vchPubKey = ParseHex(ks);
1028             if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
1029                 throw runtime_error(" Invalid public key: "+ks);
1030         }
1031         else
1032         {
1033             throw runtime_error(" Invalid public key: "+ks);
1034         }
1035     }
1036
1037     // Construct using pay-to-script-hash:
1038     CScript inner;
1039     inner.SetMultisig(nRequired, pubkeys);
1040
1041     uint160 scriptHash = Hash160(inner);
1042     CScript scriptPubKey;
1043     scriptPubKey.SetPayToScriptHash(inner);
1044     pwalletMain->AddCScript(inner);
1045     CBitcoinAddress address;
1046     address.SetScriptHash160(scriptHash);
1047
1048     pwalletMain->SetAddressBookName(address, strAccount);
1049     return address.ToString();
1050 }
1051
1052
1053 struct tallyitem
1054 {
1055     int64 nAmount;
1056     int nConf;
1057     tallyitem()
1058     {
1059         nAmount = 0;
1060         nConf = std::numeric_limits<int>::max();
1061     }
1062 };
1063
1064 Value ListReceived(const Array& params, bool fByAccounts)
1065 {
1066     // Minimum confirmations
1067     int nMinDepth = 1;
1068     if (params.size() > 0)
1069         nMinDepth = params[0].get_int();
1070
1071     // Whether to include empty accounts
1072     bool fIncludeEmpty = false;
1073     if (params.size() > 1)
1074         fIncludeEmpty = params[1].get_bool();
1075
1076     // Tally
1077     map<CBitcoinAddress, tallyitem> mapTally;
1078     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1079     {
1080         const CWalletTx& wtx = (*it).second;
1081
1082         if (wtx.IsCoinBase() || !wtx.IsFinal())
1083             continue;
1084
1085         int nDepth = wtx.GetDepthInMainChain();
1086         if (nDepth < nMinDepth)
1087             continue;
1088
1089         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1090         {
1091             CBitcoinAddress address;
1092             if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
1093                 continue;
1094
1095             tallyitem& item = mapTally[address];
1096             item.nAmount += txout.nValue;
1097             item.nConf = min(item.nConf, nDepth);
1098         }
1099     }
1100
1101     // Reply
1102     Array ret;
1103     map<string, tallyitem> mapAccountTally;
1104     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
1105     {
1106         const CBitcoinAddress& address = item.first;
1107         const string& strAccount = item.second;
1108         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1109         if (it == mapTally.end() && !fIncludeEmpty)
1110             continue;
1111
1112         int64 nAmount = 0;
1113         int nConf = std::numeric_limits<int>::max();
1114         if (it != mapTally.end())
1115         {
1116             nAmount = (*it).second.nAmount;
1117             nConf = (*it).second.nConf;
1118         }
1119
1120         if (fByAccounts)
1121         {
1122             tallyitem& item = mapAccountTally[strAccount];
1123             item.nAmount += nAmount;
1124             item.nConf = min(item.nConf, nConf);
1125         }
1126         else
1127         {
1128             Object obj;
1129             obj.push_back(Pair("address",       address.ToString()));
1130             obj.push_back(Pair("account",       strAccount));
1131             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1132             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1133             ret.push_back(obj);
1134         }
1135     }
1136
1137     if (fByAccounts)
1138     {
1139         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1140         {
1141             int64 nAmount = (*it).second.nAmount;
1142             int nConf = (*it).second.nConf;
1143             Object obj;
1144             obj.push_back(Pair("account",       (*it).first));
1145             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1146             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1147             ret.push_back(obj);
1148         }
1149     }
1150
1151     return ret;
1152 }
1153
1154 Value listreceivedbyaddress(const Array& params, bool fHelp)
1155 {
1156     if (fHelp || params.size() > 2)
1157         throw runtime_error(
1158             "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
1159             "[minconf] is the minimum number of confirmations before payments are included.\n"
1160             "[includeempty] whether to include addresses that haven't received any payments.\n"
1161             "Returns an array of objects containing:\n"
1162             "  \"address\" : receiving address\n"
1163             "  \"account\" : the account of the receiving address\n"
1164             "  \"amount\" : total amount received by the address\n"
1165             "  \"confirmations\" : number of confirmations of the most recent transaction included");
1166
1167     return ListReceived(params, false);
1168 }
1169
1170 Value listreceivedbyaccount(const Array& params, bool fHelp)
1171 {
1172     if (fHelp || params.size() > 2)
1173         throw runtime_error(
1174             "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
1175             "[minconf] is the minimum number of confirmations before payments are included.\n"
1176             "[includeempty] whether to include accounts that haven't received any payments.\n"
1177             "Returns an array of objects containing:\n"
1178             "  \"account\" : the account of the receiving addresses\n"
1179             "  \"amount\" : total amount received by addresses with this account\n"
1180             "  \"confirmations\" : number of confirmations of the most recent transaction included");
1181
1182     return ListReceived(params, true);
1183 }
1184
1185 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1186 {
1187     int64 nGeneratedImmature, nGeneratedMature, nFee;
1188     string strSentAccount;
1189     list<pair<CBitcoinAddress, int64> > listReceived;
1190     list<pair<CBitcoinAddress, int64> > listSent;
1191
1192     wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1193
1194     bool fAllAccounts = (strAccount == string("*"));
1195
1196     // Generated blocks assigned to account ""
1197     if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1198     {
1199         Object entry;
1200         entry.push_back(Pair("account", string("")));
1201         if (nGeneratedImmature)
1202         {
1203             entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1204             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1205         }
1206         else
1207         {
1208             entry.push_back(Pair("category", "generate"));
1209             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1210         }
1211         if (fLong)
1212             WalletTxToJSON(wtx, entry);
1213         ret.push_back(entry);
1214     }
1215
1216     // Sent
1217     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1218     {
1219         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1220         {
1221             Object entry;
1222             entry.push_back(Pair("account", strSentAccount));
1223             entry.push_back(Pair("address", s.first.ToString()));
1224             entry.push_back(Pair("category", "send"));
1225             entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1226             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1227             if (fLong)
1228                 WalletTxToJSON(wtx, entry);
1229             ret.push_back(entry);
1230         }
1231     }
1232
1233     // Received
1234     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1235         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1236         {
1237             string account;
1238             if (pwalletMain->mapAddressBook.count(r.first))
1239                 account = pwalletMain->mapAddressBook[r.first];
1240             if (fAllAccounts || (account == strAccount))
1241             {
1242                 Object entry;
1243                 entry.push_back(Pair("account", account));
1244                 entry.push_back(Pair("address", r.first.ToString()));
1245                 entry.push_back(Pair("category", "receive"));
1246                 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1247                 if (fLong)
1248                     WalletTxToJSON(wtx, entry);
1249                 ret.push_back(entry);
1250             }
1251         }
1252 }
1253
1254 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1255 {
1256     bool fAllAccounts = (strAccount == string("*"));
1257
1258     if (fAllAccounts || acentry.strAccount == strAccount)
1259     {
1260         Object entry;
1261         entry.push_back(Pair("account", acentry.strAccount));
1262         entry.push_back(Pair("category", "move"));
1263         entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1264         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1265         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1266         entry.push_back(Pair("comment", acentry.strComment));
1267         ret.push_back(entry);
1268     }
1269 }
1270
1271 Value listtransactions(const Array& params, bool fHelp)
1272 {
1273     if (fHelp || params.size() > 3)
1274         throw runtime_error(
1275             "listtransactions [account] [count=10] [from=0]\n"
1276             "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1277
1278     string strAccount = "*";
1279     if (params.size() > 0)
1280         strAccount = params[0].get_str();
1281     int nCount = 10;
1282     if (params.size() > 1)
1283         nCount = params[1].get_int();
1284     int nFrom = 0;
1285     if (params.size() > 2)
1286         nFrom = params[2].get_int();
1287
1288     Array ret;
1289     CWalletDB walletdb(pwalletMain->strWalletFile);
1290
1291     // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1292     typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1293     typedef multimap<int64, TxPair > TxItems;
1294     TxItems txByTime;
1295
1296     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1297     {
1298         CWalletTx* wtx = &((*it).second);
1299         txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1300     }
1301     list<CAccountingEntry> acentries;
1302     walletdb.ListAccountCreditDebit(strAccount, acentries);
1303     BOOST_FOREACH(CAccountingEntry& entry, acentries)
1304     {
1305         txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1306     }
1307
1308     // Now: iterate backwards until we have nCount items to return:
1309     TxItems::reverse_iterator it = txByTime.rbegin();
1310     if (txByTime.size() > nFrom) std::advance(it, nFrom);
1311     for (; it != txByTime.rend(); ++it)
1312     {
1313         CWalletTx *const pwtx = (*it).second.first;
1314         if (pwtx != 0)
1315             ListTransactions(*pwtx, strAccount, 0, true, ret);
1316         CAccountingEntry *const pacentry = (*it).second.second;
1317         if (pacentry != 0)
1318             AcentryToJSON(*pacentry, strAccount, ret);
1319
1320         if (ret.size() >= nCount) break;
1321     }
1322     // ret is now newest to oldest
1323     
1324     // Make sure we return only last nCount items (sends-to-self might give us an extra):
1325     if (ret.size() > nCount)
1326     {
1327         Array::iterator last = ret.begin();
1328         std::advance(last, nCount);
1329         ret.erase(last, ret.end());
1330     }
1331     std::reverse(ret.begin(), ret.end()); // oldest to newest
1332
1333     return ret;
1334 }
1335
1336 Value listaccounts(const Array& params, bool fHelp)
1337 {
1338     if (fHelp || params.size() > 1)
1339         throw runtime_error(
1340             "listaccounts [minconf=1]\n"
1341             "Returns Object that has account names as keys, account balances as values.");
1342
1343     int nMinDepth = 1;
1344     if (params.size() > 0)
1345         nMinDepth = params[0].get_int();
1346
1347     map<string, int64> mapAccountBalances;
1348     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1349         if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1350             mapAccountBalances[entry.second] = 0;
1351     }
1352
1353     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1354     {
1355         const CWalletTx& wtx = (*it).second;
1356         int64 nGeneratedImmature, nGeneratedMature, nFee;
1357         string strSentAccount;
1358         list<pair<CBitcoinAddress, int64> > listReceived;
1359         list<pair<CBitcoinAddress, int64> > listSent;
1360         wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1361         mapAccountBalances[strSentAccount] -= nFee;
1362         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1363             mapAccountBalances[strSentAccount] -= s.second;
1364         if (wtx.GetDepthInMainChain() >= nMinDepth)
1365         {
1366             mapAccountBalances[""] += nGeneratedMature;
1367             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1368                 if (pwalletMain->mapAddressBook.count(r.first))
1369                     mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1370                 else
1371                     mapAccountBalances[""] += r.second;
1372         }
1373     }
1374
1375     list<CAccountingEntry> acentries;
1376     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1377     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1378         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1379
1380     Object ret;
1381     BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1382         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1383     }
1384     return ret;
1385 }
1386
1387 Value listsinceblock(const Array& params, bool fHelp)
1388 {
1389     if (fHelp)
1390         throw runtime_error(
1391             "listsinceblock [blockid] [target-confirmations]\n"
1392             "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1393
1394     CBlockIndex *pindex = NULL;
1395     int target_confirms = 1;
1396
1397     if (params.size() > 0)
1398     {
1399         uint256 blockId = 0;
1400
1401         blockId.SetHex(params[0].get_str());
1402         pindex = CBlockLocator(blockId).GetBlockIndex();
1403     }
1404
1405     if (params.size() > 1)
1406     {
1407         target_confirms = params[1].get_int();
1408
1409         if (target_confirms < 1)
1410             throw JSONRPCError(-8, "Invalid parameter");
1411     }
1412
1413     int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1414
1415     Array transactions;
1416
1417     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1418     {
1419         CWalletTx tx = (*it).second;
1420
1421         if (depth == -1 || tx.GetDepthInMainChain() < depth)
1422             ListTransactions(tx, "*", 0, true, transactions);
1423     }
1424
1425     uint256 lastblock;
1426
1427     if (target_confirms == 1)
1428     {
1429         printf("oops!\n");
1430         lastblock = hashBestChain;
1431     }
1432     else
1433     {
1434         int target_height = pindexBest->nHeight + 1 - target_confirms;
1435
1436         CBlockIndex *block;
1437         for (block = pindexBest;
1438              block && block->nHeight > target_height;
1439              block = block->pprev)  { }
1440
1441         lastblock = block ? block->GetBlockHash() : 0;
1442     }
1443
1444     Object ret;
1445     ret.push_back(Pair("transactions", transactions));
1446     ret.push_back(Pair("lastblock", lastblock.GetHex()));
1447
1448     return ret;
1449 }
1450
1451 Value gettransaction(const Array& params, bool fHelp)
1452 {
1453     if (fHelp || params.size() != 1)
1454         throw runtime_error(
1455             "gettransaction <txid>\n"
1456             "Get detailed information about <txid>");
1457
1458     uint256 hash;
1459     hash.SetHex(params[0].get_str());
1460
1461     Object entry;
1462
1463     if (!pwalletMain->mapWallet.count(hash))
1464         throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1465     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1466
1467     int64 nCredit = wtx.GetCredit();
1468     int64 nDebit = wtx.GetDebit();
1469     int64 nNet = nCredit - nDebit;
1470     int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1471
1472     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1473     if (wtx.IsFromMe())
1474         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1475
1476     WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1477
1478     Array details;
1479     ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1480     entry.push_back(Pair("details", details));
1481
1482     return entry;
1483 }
1484
1485
1486 Value backupwallet(const Array& params, bool fHelp)
1487 {
1488     if (fHelp || params.size() != 1)
1489         throw runtime_error(
1490             "backupwallet <destination>\n"
1491             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1492
1493     string strDest = params[0].get_str();
1494     BackupWallet(*pwalletMain, strDest);
1495
1496     return Value::null;
1497 }
1498
1499
1500 Value keypoolrefill(const Array& params, bool fHelp)
1501 {
1502     if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1503         throw runtime_error(
1504             "keypoolrefill\n"
1505             "Fills the keypool, requires wallet passphrase to be set.");
1506     if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1507         throw runtime_error(
1508             "keypoolrefill\n"
1509             "Fills the keypool.");
1510
1511     if (pwalletMain->IsLocked())
1512         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1513
1514     pwalletMain->TopUpKeyPool();
1515
1516     if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1517         throw JSONRPCError(-4, "Error refreshing keypool.");
1518
1519     return Value::null;
1520 }
1521
1522
1523 void ThreadTopUpKeyPool(void* parg)
1524 {
1525     pwalletMain->TopUpKeyPool();
1526 }
1527
1528 void ThreadCleanWalletPassphrase(void* parg)
1529 {
1530     int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1531
1532     ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1533
1534     if (nWalletUnlockTime == 0)
1535     {
1536         nWalletUnlockTime = nMyWakeTime;
1537
1538         do
1539         {
1540             if (nWalletUnlockTime==0)
1541                 break;
1542             int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1543             if (nToSleep <= 0)
1544                 break;
1545
1546             LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1547             Sleep(nToSleep);
1548             ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1549
1550         } while(1);
1551
1552         if (nWalletUnlockTime)
1553         {
1554             nWalletUnlockTime = 0;
1555             pwalletMain->Lock();
1556         }
1557     }
1558     else
1559     {
1560         if (nWalletUnlockTime < nMyWakeTime)
1561             nWalletUnlockTime = nMyWakeTime;
1562     }
1563
1564     LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1565
1566     delete (int64*)parg;
1567 }
1568
1569 Value walletpassphrase(const Array& params, bool fHelp)
1570 {
1571     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1572         throw runtime_error(
1573             "walletpassphrase <passphrase> <timeout>\n"
1574             "Stores the wallet decryption key in memory for <timeout> seconds.");
1575     if (fHelp)
1576         return true;
1577     if (!pwalletMain->IsCrypted())
1578         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1579
1580     if (!pwalletMain->IsLocked())
1581         throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1582
1583     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1584     SecureString strWalletPass;
1585     strWalletPass.reserve(100);
1586     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1587     // Alternately, find a way to make params[0] mlock()'d to begin with.
1588     strWalletPass = params[0].get_str().c_str();
1589
1590     if (strWalletPass.length() > 0)
1591     {
1592         if (!pwalletMain->Unlock(strWalletPass))
1593             throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1594     }
1595     else
1596         throw runtime_error(
1597             "walletpassphrase <passphrase> <timeout>\n"
1598             "Stores the wallet decryption key in memory for <timeout> seconds.");
1599
1600     CreateThread(ThreadTopUpKeyPool, NULL);
1601     int64* pnSleepTime = new int64(params[1].get_int64());
1602     CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1603
1604     return Value::null;
1605 }
1606
1607
1608 Value walletpassphrasechange(const Array& params, bool fHelp)
1609 {
1610     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1611         throw runtime_error(
1612             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1613             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1614     if (fHelp)
1615         return true;
1616     if (!pwalletMain->IsCrypted())
1617         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1618
1619     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1620     // Alternately, find a way to make params[0] mlock()'d to begin with.
1621     SecureString strOldWalletPass;
1622     strOldWalletPass.reserve(100);
1623     strOldWalletPass = params[0].get_str().c_str();
1624
1625     SecureString strNewWalletPass;
1626     strNewWalletPass.reserve(100);
1627     strNewWalletPass = params[1].get_str().c_str();
1628
1629     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1630         throw runtime_error(
1631             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1632             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1633
1634     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1635         throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1636
1637     return Value::null;
1638 }
1639
1640
1641 Value walletlock(const Array& params, bool fHelp)
1642 {
1643     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1644         throw runtime_error(
1645             "walletlock\n"
1646             "Removes the wallet encryption key from memory, locking the wallet.\n"
1647             "After calling this method, you will need to call walletpassphrase again\n"
1648             "before being able to call any methods which require the wallet to be unlocked.");
1649     if (fHelp)
1650         return true;
1651     if (!pwalletMain->IsCrypted())
1652         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1653
1654     CRITICAL_BLOCK(cs_nWalletUnlockTime)
1655     {
1656         pwalletMain->Lock();
1657         nWalletUnlockTime = 0;
1658     }
1659
1660     return Value::null;
1661 }
1662
1663
1664 Value encryptwallet(const Array& params, bool fHelp)
1665 {
1666     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1667         throw runtime_error(
1668             "encryptwallet <passphrase>\n"
1669             "Encrypts the wallet with <passphrase>.");
1670     if (fHelp)
1671         return true;
1672     if (pwalletMain->IsCrypted())
1673         throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1674
1675     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1676     // Alternately, find a way to make params[0] mlock()'d to begin with.
1677     SecureString strWalletPass;
1678     strWalletPass.reserve(100);
1679     strWalletPass = params[0].get_str().c_str();
1680
1681     if (strWalletPass.length() < 1)
1682         throw runtime_error(
1683             "encryptwallet <passphrase>\n"
1684             "Encrypts the wallet with <passphrase>.");
1685
1686     if (!pwalletMain->EncryptWallet(strWalletPass))
1687         throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1688
1689     // BDB seems to have a bad habit of writing old data into
1690     // slack space in .dat files; that is bad if the old data is
1691     // unencrypted private keys.  So:
1692     QueueShutdown();
1693     return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1694 }
1695
1696
1697 Value validateaddress(const Array& params, bool fHelp)
1698 {
1699     if (fHelp || params.size() != 1)
1700         throw runtime_error(
1701             "validateaddress <bitcoinaddress>\n"
1702             "Return information about <bitcoinaddress>.");
1703
1704     CBitcoinAddress address(params[0].get_str());
1705     bool isValid = address.IsValid();
1706
1707     Object ret;
1708     ret.push_back(Pair("isvalid", isValid));
1709     if (isValid)
1710     {
1711         // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1712         // version of the address:
1713         string currentAddress = address.ToString();
1714         ret.push_back(Pair("address", currentAddress));
1715         if (pwalletMain->HaveKey(address))
1716         {
1717             ret.push_back(Pair("ismine", true));
1718             std::vector<unsigned char> vchPubKey;
1719             pwalletMain->GetPubKey(address, vchPubKey);
1720             ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1721             CKey key;
1722             key.SetPubKey(vchPubKey);
1723             ret.push_back(Pair("iscompressed", key.IsCompressed()));
1724         }
1725         else if (pwalletMain->HaveCScript(address.GetHash160()))
1726         {
1727             ret.push_back(Pair("isscript", true));
1728             CScript subscript;
1729             pwalletMain->GetCScript(address.GetHash160(), subscript);
1730             ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1731             std::vector<CBitcoinAddress> addresses;
1732             txnouttype whichType;
1733             int nRequired;
1734             ExtractAddresses(subscript, whichType, addresses, nRequired);
1735             ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1736             Array a;
1737             BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1738                 a.push_back(addr.ToString());
1739             ret.push_back(Pair("addresses", a));
1740             if (whichType == TX_MULTISIG)
1741                 ret.push_back(Pair("sigsrequired", nRequired));
1742         }
1743         else
1744             ret.push_back(Pair("ismine", false));
1745         if (pwalletMain->mapAddressBook.count(address))
1746             ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1747     }
1748     return ret;
1749 }
1750
1751 Value getwork(const Array& params, bool fHelp)
1752 {
1753     if (fHelp || params.size() > 1)
1754         throw runtime_error(
1755             "getwork [data]\n"
1756             "If [data] is not specified, returns formatted hash data to work on:\n"
1757             "  \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1758             "  \"data\" : block data\n"
1759             "  \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1760             "  \"target\" : little endian hash target\n"
1761             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1762
1763     if (vNodes.empty())
1764         throw JSONRPCError(-9, "Bitcoin is not connected!");
1765
1766     if (IsInitialBlockDownload())
1767         throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1768
1769     typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1770     static mapNewBlock_t mapNewBlock;
1771     static vector<CBlock*> vNewBlock;
1772     static CReserveKey reservekey(pwalletMain);
1773
1774     if (params.size() == 0)
1775     {
1776         // Update block
1777         static unsigned int nTransactionsUpdatedLast;
1778         static CBlockIndex* pindexPrev;
1779         static int64 nStart;
1780         static CBlock* pblock;
1781         if (pindexPrev != pindexBest ||
1782             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1783         {
1784             if (pindexPrev != pindexBest)
1785             {
1786                 // Deallocate old blocks since they're obsolete now
1787                 mapNewBlock.clear();
1788                 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1789                     delete pblock;
1790                 vNewBlock.clear();
1791             }
1792             nTransactionsUpdatedLast = nTransactionsUpdated;
1793             pindexPrev = pindexBest;
1794             nStart = GetTime();
1795
1796             // Create new block
1797             pblock = CreateNewBlock(reservekey);
1798             if (!pblock)
1799                 throw JSONRPCError(-7, "Out of memory");
1800             vNewBlock.push_back(pblock);
1801         }
1802
1803         // Update nTime
1804         pblock->UpdateTime(pindexPrev);
1805         pblock->nNonce = 0;
1806
1807         // Update nExtraNonce
1808         static unsigned int nExtraNonce = 0;
1809         IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1810
1811         // Save
1812         mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1813
1814         // Prebuild hash buffers
1815         char pmidstate[32];
1816         char pdata[128];
1817         char phash1[64];
1818         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1819
1820         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1821
1822         Object result;
1823         result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1824         result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
1825         result.push_back(Pair("hash1",    HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1826         result.push_back(Pair("target",   HexStr(BEGIN(hashTarget), END(hashTarget))));
1827         return result;
1828     }
1829     else
1830     {
1831         // Parse parameters
1832         vector<unsigned char> vchData = ParseHex(params[0].get_str());
1833         if (vchData.size() != 128)
1834             throw JSONRPCError(-8, "Invalid parameter");
1835         CBlock* pdata = (CBlock*)&vchData[0];
1836
1837         // Byte reverse
1838         for (int i = 0; i < 128/4; i++)
1839             ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1840
1841         // Get saved block
1842         if (!mapNewBlock.count(pdata->hashMerkleRoot))
1843             return false;
1844         CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1845
1846         pblock->nTime = pdata->nTime;
1847         pblock->nNonce = pdata->nNonce;
1848         pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1849         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1850
1851         return CheckWork(pblock, *pwalletMain, reservekey);
1852     }
1853 }
1854
1855
1856 Value getmemorypool(const Array& params, bool fHelp)
1857 {
1858     if (fHelp || params.size() > 1)
1859         throw runtime_error(
1860             "getmemorypool [data]\n"
1861             "If [data] is not specified, returns data needed to construct a block to work on:\n"
1862             "  \"version\" : block version\n"
1863             "  \"previousblockhash\" : hash of current highest block\n"
1864             "  \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1865             "  \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1866             "  \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1867             "  \"time\" : timestamp appropriate for next block\n"
1868             "  \"mintime\" : minimum timestamp appropriate for next block\n"
1869             "  \"curtime\" : current timestamp\n"
1870             "  \"bits\" : compressed target of next block\n"
1871             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1872
1873     if (params.size() == 0)
1874     {
1875         if (vNodes.empty())
1876             throw JSONRPCError(-9, "Bitcoin is not connected!");
1877
1878         if (IsInitialBlockDownload())
1879             throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1880
1881         static CReserveKey reservekey(pwalletMain);
1882
1883         // Update block
1884         static unsigned int nTransactionsUpdatedLast;
1885         static CBlockIndex* pindexPrev;
1886         static int64 nStart;
1887         static CBlock* pblock;
1888         if (pindexPrev != pindexBest ||
1889             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1890         {
1891             nTransactionsUpdatedLast = nTransactionsUpdated;
1892             pindexPrev = pindexBest;
1893             nStart = GetTime();
1894
1895             // Create new block
1896             if(pblock)
1897                 delete pblock;
1898             pblock = CreateNewBlock(reservekey);
1899             if (!pblock)
1900                 throw JSONRPCError(-7, "Out of memory");
1901         }
1902
1903         // Update nTime
1904         pblock->UpdateTime(pindexPrev);
1905         pblock->nNonce = 0;
1906
1907         Array transactions;
1908         BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1909             if(tx.IsCoinBase())
1910                 continue;
1911
1912             CDataStream ssTx;
1913             ssTx << tx;
1914
1915             transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1916         }
1917
1918         Object result;
1919         result.push_back(Pair("version", pblock->nVersion));
1920         result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1921         result.push_back(Pair("transactions", transactions));
1922         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1923         result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1924         result.push_back(Pair("time", (int64_t)pblock->nTime));
1925         result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1926         result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1927         result.push_back(Pair("bits", HexBits(pblock->nBits)));
1928
1929         return result;
1930     }
1931     else
1932     {
1933         // Parse parameters
1934         CDataStream ssBlock(ParseHex(params[0].get_str()));
1935         CBlock pblock;
1936         ssBlock >> pblock;
1937
1938         return ProcessBlock(NULL, &pblock);
1939     }
1940 }
1941
1942 Value getblockhash(const Array& params, bool fHelp)
1943 {
1944     if (fHelp || params.size() != 1)
1945         throw runtime_error(
1946             "getblockhash <index>\n"
1947             "Returns hash of block in best-block-chain at <index>.");
1948
1949     int nHeight = params[0].get_int();
1950     if (nHeight < 0 || nHeight > nBestHeight)
1951         throw runtime_error("Block number out of range.");
1952
1953     CBlock block;
1954     CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1955     while (pblockindex->nHeight > nHeight)
1956         pblockindex = pblockindex->pprev;
1957     return pblockindex->phashBlock->GetHex();
1958 }
1959
1960 Value getblock(const Array& params, bool fHelp)
1961 {
1962     if (fHelp || params.size() != 1)
1963         throw runtime_error(
1964             "getblock <hash>\n"
1965             "Returns details of a block with given block-hash.");
1966
1967     std::string strHash = params[0].get_str();
1968     uint256 hash(strHash);
1969
1970     if (mapBlockIndex.count(hash) == 0)
1971         throw JSONRPCError(-5, "Block not found");
1972
1973     CBlock block;
1974     CBlockIndex* pblockindex = mapBlockIndex[hash];
1975     block.ReadFromDisk(pblockindex, true);
1976
1977     return blockToJSON(block, pblockindex);
1978 }
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990 //
1991 // Call Table
1992 //
1993
1994 pair<string, rpcfn_type> pCallTable[] =
1995 {
1996     make_pair("help",                   &help),
1997     make_pair("stop",                   &stop),
1998     make_pair("getblockcount",          &getblockcount),
1999     make_pair("getblocknumber",         &getblocknumber),
2000     make_pair("getconnectioncount",     &getconnectioncount),
2001     make_pair("getdifficulty",          &getdifficulty),
2002     make_pair("getgenerate",            &getgenerate),
2003     make_pair("setgenerate",            &setgenerate),
2004     make_pair("gethashespersec",        &gethashespersec),
2005     make_pair("getinfo",                &getinfo),
2006     make_pair("getmininginfo",          &getmininginfo),
2007     make_pair("getnewaddress",          &getnewaddress),
2008     make_pair("getaccountaddress",      &getaccountaddress),
2009     make_pair("setaccount",             &setaccount),
2010     make_pair("getaccount",             &getaccount),
2011     make_pair("getaddressesbyaccount",  &getaddressesbyaccount),
2012     make_pair("sendtoaddress",          &sendtoaddress),
2013     make_pair("getreceivedbyaddress",   &getreceivedbyaddress),
2014     make_pair("getreceivedbyaccount",   &getreceivedbyaccount),
2015     make_pair("listreceivedbyaddress",  &listreceivedbyaddress),
2016     make_pair("listreceivedbyaccount",  &listreceivedbyaccount),
2017     make_pair("backupwallet",           &backupwallet),
2018     make_pair("keypoolrefill",          &keypoolrefill),
2019     make_pair("walletpassphrase",       &walletpassphrase),
2020     make_pair("walletpassphrasechange", &walletpassphrasechange),
2021     make_pair("walletlock",             &walletlock),
2022     make_pair("encryptwallet",          &encryptwallet),
2023     make_pair("validateaddress",        &validateaddress),
2024     make_pair("getbalance",             &getbalance),
2025     make_pair("move",                   &movecmd),
2026     make_pair("sendfrom",               &sendfrom),
2027     make_pair("sendmany",               &sendmany),
2028     make_pair("addmultisigaddress",     &addmultisigaddress),
2029     make_pair("getblock",               &getblock),
2030     make_pair("getblockhash",           &getblockhash),
2031     make_pair("gettransaction",         &gettransaction),
2032     make_pair("listtransactions",       &listtransactions),
2033     make_pair("signmessage",            &signmessage),
2034     make_pair("verifymessage",          &verifymessage),
2035     make_pair("getwork",                &getwork),
2036     make_pair("listaccounts",           &listaccounts),
2037     make_pair("settxfee",               &settxfee),
2038     make_pair("getmemorypool",          &getmemorypool),
2039     make_pair("listsinceblock",         &listsinceblock),
2040     make_pair("dumpprivkey",            &dumpprivkey),
2041     make_pair("importprivkey",          &importprivkey)
2042 };
2043 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
2044
2045 string pAllowInSafeMode[] =
2046 {
2047     "help",
2048     "stop",
2049     "getblockcount",
2050     "getblocknumber",  // deprecated
2051     "getconnectioncount",
2052     "getdifficulty",
2053     "getgenerate",
2054     "setgenerate",
2055     "gethashespersec",
2056     "getinfo",
2057     "getmininginfo",
2058     "getnewaddress",
2059     "getaccountaddress",
2060     "getaccount",
2061     "getaddressesbyaccount",
2062     "backupwallet",
2063     "keypoolrefill",
2064     "walletpassphrase",
2065     "walletlock",
2066     "validateaddress",
2067     "getwork",
2068     "getmemorypool",
2069 };
2070 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
2071
2072
2073
2074
2075 //
2076 // HTTP protocol
2077 //
2078 // This ain't Apache.  We're just using HTTP header for the length field
2079 // and to be compatible with other JSON-RPC implementations.
2080 //
2081
2082 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2083 {
2084     ostringstream s;
2085     s << "POST / HTTP/1.1\r\n"
2086       << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2087       << "Host: 127.0.0.1\r\n"
2088       << "Content-Type: application/json\r\n"
2089       << "Content-Length: " << strMsg.size() << "\r\n"
2090       << "Connection: close\r\n"
2091       << "Accept: application/json\r\n";
2092     BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2093         s << item.first << ": " << item.second << "\r\n";
2094     s << "\r\n" << strMsg;
2095
2096     return s.str();
2097 }
2098
2099 string rfc1123Time()
2100 {
2101     char buffer[64];
2102     time_t now;
2103     time(&now);
2104     struct tm* now_gmt = gmtime(&now);
2105     string locale(setlocale(LC_TIME, NULL));
2106     setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2107     strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2108     setlocale(LC_TIME, locale.c_str());
2109     return string(buffer);
2110 }
2111
2112 static string HTTPReply(int nStatus, const string& strMsg)
2113 {
2114     if (nStatus == 401)
2115         return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2116             "Date: %s\r\n"
2117             "Server: bitcoin-json-rpc/%s\r\n"
2118             "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2119             "Content-Type: text/html\r\n"
2120             "Content-Length: 296\r\n"
2121             "\r\n"
2122             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2123             "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2124             "<HTML>\r\n"
2125             "<HEAD>\r\n"
2126             "<TITLE>Error</TITLE>\r\n"
2127             "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2128             "</HEAD>\r\n"
2129             "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2130             "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2131     const char *cStatus;
2132          if (nStatus == 200) cStatus = "OK";
2133     else if (nStatus == 400) cStatus = "Bad Request";
2134     else if (nStatus == 403) cStatus = "Forbidden";
2135     else if (nStatus == 404) cStatus = "Not Found";
2136     else if (nStatus == 500) cStatus = "Internal Server Error";
2137     else cStatus = "";
2138     return strprintf(
2139             "HTTP/1.1 %d %s\r\n"
2140             "Date: %s\r\n"
2141             "Connection: close\r\n"
2142             "Content-Length: %d\r\n"
2143             "Content-Type: application/json\r\n"
2144             "Server: bitcoin-json-rpc/%s\r\n"
2145             "\r\n"
2146             "%s",
2147         nStatus,
2148         cStatus,
2149         rfc1123Time().c_str(),
2150         strMsg.size(),
2151         FormatFullVersion().c_str(),
2152         strMsg.c_str());
2153 }
2154
2155 int ReadHTTPStatus(std::basic_istream<char>& stream)
2156 {
2157     string str;
2158     getline(stream, str);
2159     vector<string> vWords;
2160     boost::split(vWords, str, boost::is_any_of(" "));
2161     if (vWords.size() < 2)
2162         return 500;
2163     return atoi(vWords[1].c_str());
2164 }
2165
2166 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2167 {
2168     int nLen = 0;
2169     loop
2170     {
2171         string str;
2172         std::getline(stream, str);
2173         if (str.empty() || str == "\r")
2174             break;
2175         string::size_type nColon = str.find(":");
2176         if (nColon != string::npos)
2177         {
2178             string strHeader = str.substr(0, nColon);
2179             boost::trim(strHeader);
2180             boost::to_lower(strHeader);
2181             string strValue = str.substr(nColon+1);
2182             boost::trim(strValue);
2183             mapHeadersRet[strHeader] = strValue;
2184             if (strHeader == "content-length")
2185                 nLen = atoi(strValue.c_str());
2186         }
2187     }
2188     return nLen;
2189 }
2190
2191 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2192 {
2193     mapHeadersRet.clear();
2194     strMessageRet = "";
2195
2196     // Read status
2197     int nStatus = ReadHTTPStatus(stream);
2198
2199     // Read header
2200     int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2201     if (nLen < 0 || nLen > MAX_SIZE)
2202         return 500;
2203
2204     // Read message
2205     if (nLen > 0)
2206     {
2207         vector<char> vch(nLen);
2208         stream.read(&vch[0], nLen);
2209         strMessageRet = string(vch.begin(), vch.end());
2210     }
2211
2212     return nStatus;
2213 }
2214
2215 bool HTTPAuthorized(map<string, string>& mapHeaders)
2216 {
2217     string strAuth = mapHeaders["authorization"];
2218     if (strAuth.substr(0,6) != "Basic ")
2219         return false;
2220     string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2221     string strUserPass = DecodeBase64(strUserPass64);
2222     return strUserPass == strRPCUserColonPass;
2223 }
2224
2225 //
2226 // JSON-RPC protocol.  Bitcoin speaks version 1.0 for maximum compatibility,
2227 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2228 // unspecified (HTTP errors and contents of 'error').
2229 //
2230 // 1.0 spec: http://json-rpc.org/wiki/specification
2231 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2232 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2233 //
2234
2235 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2236 {
2237     Object request;
2238     request.push_back(Pair("method", strMethod));
2239     request.push_back(Pair("params", params));
2240     request.push_back(Pair("id", id));
2241     return write_string(Value(request), false) + "\n";
2242 }
2243
2244 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2245 {
2246     Object reply;
2247     if (error.type() != null_type)
2248         reply.push_back(Pair("result", Value::null));
2249     else
2250         reply.push_back(Pair("result", result));
2251     reply.push_back(Pair("error", error));
2252     reply.push_back(Pair("id", id));
2253     return write_string(Value(reply), false) + "\n";
2254 }
2255
2256 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2257 {
2258     // Send error reply from json-rpc error object
2259     int nStatus = 500;
2260     int code = find_value(objError, "code").get_int();
2261     if (code == -32600) nStatus = 400;
2262     else if (code == -32601) nStatus = 404;
2263     string strReply = JSONRPCReply(Value::null, objError, id);
2264     stream << HTTPReply(nStatus, strReply) << std::flush;
2265 }
2266
2267 bool ClientAllowed(const string& strAddress)
2268 {
2269     if (strAddress == asio::ip::address_v4::loopback().to_string())
2270         return true;
2271     const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2272     BOOST_FOREACH(string strAllow, vAllow)
2273         if (WildcardMatch(strAddress, strAllow))
2274             return true;
2275     return false;
2276 }
2277
2278 #ifdef USE_SSL
2279 //
2280 // IOStream device that speaks SSL but can also speak non-SSL
2281 //
2282 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2283 public:
2284     SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2285     {
2286         fUseSSL = fUseSSLIn;
2287         fNeedHandshake = fUseSSLIn;
2288     }
2289
2290     void handshake(ssl::stream_base::handshake_type role)
2291     {
2292         if (!fNeedHandshake) return;
2293         fNeedHandshake = false;
2294         stream.handshake(role);
2295     }
2296     std::streamsize read(char* s, std::streamsize n)
2297     {
2298         handshake(ssl::stream_base::server); // HTTPS servers read first
2299         if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2300         return stream.next_layer().read_some(asio::buffer(s, n));
2301     }
2302     std::streamsize write(const char* s, std::streamsize n)
2303     {
2304         handshake(ssl::stream_base::client); // HTTPS clients write first
2305         if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2306         return asio::write(stream.next_layer(), asio::buffer(s, n));
2307     }
2308     bool connect(const std::string& server, const std::string& port)
2309     {
2310         ip::tcp::resolver resolver(stream.get_io_service());
2311         ip::tcp::resolver::query query(server.c_str(), port.c_str());
2312         ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2313         ip::tcp::resolver::iterator end;
2314         boost::system::error_code error = asio::error::host_not_found;
2315         while (error && endpoint_iterator != end)
2316         {
2317             stream.lowest_layer().close();
2318             stream.lowest_layer().connect(*endpoint_iterator++, error);
2319         }
2320         if (error)
2321             return false;
2322         return true;
2323     }
2324
2325 private:
2326     bool fNeedHandshake;
2327     bool fUseSSL;
2328     SSLStream& stream;
2329 };
2330 #endif
2331
2332 void ThreadRPCServer(void* parg)
2333 {
2334     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2335     try
2336     {
2337         vnThreadsRunning[THREAD_RPCSERVER]++;
2338         ThreadRPCServer2(parg);
2339         vnThreadsRunning[THREAD_RPCSERVER]--;
2340     }
2341     catch (std::exception& e) {
2342         vnThreadsRunning[THREAD_RPCSERVER]--;
2343         PrintException(&e, "ThreadRPCServer()");
2344     } catch (...) {
2345         vnThreadsRunning[THREAD_RPCSERVER]--;
2346         PrintException(NULL, "ThreadRPCServer()");
2347     }
2348     printf("ThreadRPCServer exiting\n");
2349 }
2350
2351 void ThreadRPCServer2(void* parg)
2352 {
2353     printf("ThreadRPCServer started\n");
2354
2355     strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2356     if (mapArgs["-rpcpassword"] == "")
2357     {
2358         unsigned char rand_pwd[32];
2359         RAND_bytes(rand_pwd, 32);
2360         string strWhatAmI = "To use bitcoind";
2361         if (mapArgs.count("-server"))
2362             strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2363         else if (mapArgs.count("-daemon"))
2364             strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2365         ThreadSafeMessageBox(strprintf(
2366             _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2367               "It is recommended you use the following random password:\n"
2368               "rpcuser=bitcoinrpc\n"
2369               "rpcpassword=%s\n"
2370               "(you do not need to remember this password)\n"
2371               "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2372                 strWhatAmI.c_str(),
2373                 GetConfigFile().c_str(),
2374                 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2375             _("Error"), wxOK | wxMODAL);
2376         QueueShutdown();
2377         return;
2378     }
2379
2380     bool fUseSSL = GetBoolArg("-rpcssl");
2381     asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2382
2383     asio::io_service io_service;
2384     ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2385     ip::tcp::acceptor acceptor(io_service, endpoint);
2386
2387     acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2388
2389 #ifdef USE_SSL
2390     ssl::context context(io_service, ssl::context::sslv23);
2391     if (fUseSSL)
2392     {
2393         context.set_options(ssl::context::no_sslv2);
2394         filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2395         if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2396         if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2397         else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2398         filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2399         if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2400         if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2401         else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2402
2403         string ciphers = GetArg("-rpcsslciphers",
2404                                          "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2405         SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2406     }
2407 #else
2408     if (fUseSSL)
2409         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2410 #endif
2411
2412     loop
2413     {
2414         // Accept connection
2415 #ifdef USE_SSL
2416         SSLStream sslStream(io_service, context);
2417         SSLIOStreamDevice d(sslStream, fUseSSL);
2418         iostreams::stream<SSLIOStreamDevice> stream(d);
2419 #else
2420         ip::tcp::iostream stream;
2421 #endif
2422
2423         ip::tcp::endpoint peer;
2424         vnThreadsRunning[THREAD_RPCSERVER]--;
2425 #ifdef USE_SSL
2426         acceptor.accept(sslStream.lowest_layer(), peer);
2427 #else
2428         acceptor.accept(*stream.rdbuf(), peer);
2429 #endif
2430         vnThreadsRunning[4]++;
2431         if (fShutdown)
2432             return;
2433
2434         // Restrict callers by IP
2435         if (!ClientAllowed(peer.address().to_string()))
2436         {
2437             // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2438             if (!fUseSSL)
2439                 stream << HTTPReply(403, "") << std::flush;
2440             continue;
2441         }
2442
2443         map<string, string> mapHeaders;
2444         string strRequest;
2445
2446         boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2447         if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2448         {   // Timed out:
2449             acceptor.cancel();
2450             printf("ThreadRPCServer ReadHTTP timeout\n");
2451             continue;
2452         }
2453
2454         // Check authorization
2455         if (mapHeaders.count("authorization") == 0)
2456         {
2457             stream << HTTPReply(401, "") << std::flush;
2458             continue;
2459         }
2460         if (!HTTPAuthorized(mapHeaders))
2461         {
2462             printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2463             /* Deter brute-forcing short passwords.
2464                If this results in a DOS the user really
2465                shouldn't have their RPC port exposed.*/
2466             if (mapArgs["-rpcpassword"].size() < 20)
2467                 Sleep(250);
2468
2469             stream << HTTPReply(401, "") << std::flush;
2470             continue;
2471         }
2472
2473         Value id = Value::null;
2474         try
2475         {
2476             // Parse request
2477             Value valRequest;
2478             if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2479                 throw JSONRPCError(-32700, "Parse error");
2480             const Object& request = valRequest.get_obj();
2481
2482             // Parse id now so errors from here on will have the id
2483             id = find_value(request, "id");
2484
2485             // Parse method
2486             Value valMethod = find_value(request, "method");
2487             if (valMethod.type() == null_type)
2488                 throw JSONRPCError(-32600, "Missing method");
2489             if (valMethod.type() != str_type)
2490                 throw JSONRPCError(-32600, "Method must be a string");
2491             string strMethod = valMethod.get_str();
2492             if (strMethod != "getwork" && strMethod != "getmemorypool")
2493                 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2494
2495             // Parse params
2496             Value valParams = find_value(request, "params");
2497             Array params;
2498             if (valParams.type() == array_type)
2499                 params = valParams.get_array();
2500             else if (valParams.type() == null_type)
2501                 params = Array();
2502             else
2503                 throw JSONRPCError(-32600, "Params must be an array");
2504
2505             // Find method
2506             map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2507             if (mi == mapCallTable.end())
2508                 throw JSONRPCError(-32601, "Method not found");
2509
2510             // Observe safe mode
2511             string strWarning = GetWarnings("rpc");
2512             if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2513                 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2514
2515             try
2516             {
2517                 // Execute
2518                 Value result;
2519                 CRITICAL_BLOCK(cs_main)
2520                 CRITICAL_BLOCK(pwalletMain->cs_wallet)
2521                     result = (*(*mi).second)(params, false);
2522
2523                 // Send reply
2524                 string strReply = JSONRPCReply(result, Value::null, id);
2525                 stream << HTTPReply(200, strReply) << std::flush;
2526             }
2527             catch (std::exception& e)
2528             {
2529                 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2530             }
2531         }
2532         catch (Object& objError)
2533         {
2534             ErrorReply(stream, objError, id);
2535         }
2536         catch (std::exception& e)
2537         {
2538             ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2539         }
2540     }
2541 }
2542
2543
2544
2545
2546 Object CallRPC(const string& strMethod, const Array& params)
2547 {
2548     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2549         throw runtime_error(strprintf(
2550             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2551               "If the file does not exist, create it with owner-readable-only file permissions."),
2552                 GetConfigFile().c_str()));
2553
2554     // Connect to localhost
2555     bool fUseSSL = GetBoolArg("-rpcssl");
2556 #ifdef USE_SSL
2557     asio::io_service io_service;
2558     ssl::context context(io_service, ssl::context::sslv23);
2559     context.set_options(ssl::context::no_sslv2);
2560     SSLStream sslStream(io_service, context);
2561     SSLIOStreamDevice d(sslStream, fUseSSL);
2562     iostreams::stream<SSLIOStreamDevice> stream(d);
2563     if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2564         throw runtime_error("couldn't connect to server");
2565 #else
2566     if (fUseSSL)
2567         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2568
2569     ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2570     if (stream.fail())
2571         throw runtime_error("couldn't connect to server");
2572 #endif
2573
2574
2575     // HTTP basic authentication
2576     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2577     map<string, string> mapRequestHeaders;
2578     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2579
2580     // Send request
2581     string strRequest = JSONRPCRequest(strMethod, params, 1);
2582     string strPost = HTTPPost(strRequest, mapRequestHeaders);
2583     stream << strPost << std::flush;
2584
2585     // Receive reply
2586     map<string, string> mapHeaders;
2587     string strReply;
2588     int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2589     if (nStatus == 401)
2590         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2591     else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2592         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2593     else if (strReply.empty())
2594         throw runtime_error("no response from server");
2595
2596     // Parse reply
2597     Value valReply;
2598     if (!read_string(strReply, valReply))
2599         throw runtime_error("couldn't parse reply from server");
2600     const Object& reply = valReply.get_obj();
2601     if (reply.empty())
2602         throw runtime_error("expected reply to have result, error and id properties");
2603
2604     return reply;
2605 }
2606
2607
2608
2609
2610 template<typename T>
2611 void ConvertTo(Value& value)
2612 {
2613     if (value.type() == str_type)
2614     {
2615         // reinterpret string as unquoted json value
2616         Value value2;
2617         if (!read_string(value.get_str(), value2))
2618             throw runtime_error("type mismatch");
2619         value = value2.get_value<T>();
2620     }
2621     else
2622     {
2623         value = value.get_value<T>();
2624     }
2625 }
2626
2627 int CommandLineRPC(int argc, char *argv[])
2628 {
2629     string strPrint;
2630     int nRet = 0;
2631     try
2632     {
2633         // Skip switches
2634         while (argc > 1 && IsSwitchChar(argv[1][0]))
2635         {
2636             argc--;
2637             argv++;
2638         }
2639
2640         // Method
2641         if (argc < 2)
2642             throw runtime_error("too few parameters");
2643         string strMethod = argv[1];
2644
2645         // Parameters default to strings
2646         Array params;
2647         for (int i = 2; i < argc; i++)
2648             params.push_back(argv[i]);
2649         int n = params.size();
2650
2651         //
2652         // Special case non-string parameter types
2653         //
2654         if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);
2655         if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
2656         if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);
2657         if (strMethod == "settxfee"               && n > 0) ConvertTo<double>(params[0]);
2658         if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2659         if (strMethod == "getreceivedbyaccount"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2660         if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2661         if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);
2662         if (strMethod == "listreceivedbyaccount"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2663         if (strMethod == "listreceivedbyaccount"  && n > 1) ConvertTo<bool>(params[1]);
2664         if (strMethod == "getbalance"             && n > 1) ConvertTo<boost::int64_t>(params[1]);
2665         if (strMethod == "getblockhash"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2666         if (strMethod == "move"                   && n > 2) ConvertTo<double>(params[2]);
2667         if (strMethod == "move"                   && n > 3) ConvertTo<boost::int64_t>(params[3]);
2668         if (strMethod == "sendfrom"               && n > 2) ConvertTo<double>(params[2]);
2669         if (strMethod == "sendfrom"               && n > 3) ConvertTo<boost::int64_t>(params[3]);
2670         if (strMethod == "listtransactions"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2671         if (strMethod == "listtransactions"       && n > 2) ConvertTo<boost::int64_t>(params[2]);
2672         if (strMethod == "listaccounts"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2673         if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2674         if (strMethod == "listsinceblock"         && n > 1) ConvertTo<boost::int64_t>(params[1]);
2675         if (strMethod == "sendmany"               && n > 1)
2676         {
2677             string s = params[1].get_str();
2678             Value v;
2679             if (!read_string(s, v) || v.type() != obj_type)
2680                 throw runtime_error("type mismatch");
2681             params[1] = v.get_obj();
2682         }
2683         if (strMethod == "sendmany"                && n > 2) ConvertTo<boost::int64_t>(params[2]);
2684         if (strMethod == "addmultisigaddress"      && n > 0) ConvertTo<boost::int64_t>(params[0]);
2685         if (strMethod == "addmultisigaddress"      && n > 1)
2686         {
2687             string s = params[1].get_str();
2688             Value v;
2689             if (!read_string(s, v) || v.type() != array_type)
2690                 throw runtime_error("type mismatch "+s);
2691             params[1] = v.get_array();
2692         }
2693
2694         // Execute
2695         Object reply = CallRPC(strMethod, params);
2696
2697         // Parse reply
2698         const Value& result = find_value(reply, "result");
2699         const Value& error  = find_value(reply, "error");
2700
2701         if (error.type() != null_type)
2702         {
2703             // Error
2704             strPrint = "error: " + write_string(error, false);
2705             int code = find_value(error.get_obj(), "code").get_int();
2706             nRet = abs(code);
2707         }
2708         else
2709         {
2710             // Result
2711             if (result.type() == null_type)
2712                 strPrint = "";
2713             else if (result.type() == str_type)
2714                 strPrint = result.get_str();
2715             else
2716                 strPrint = write_string(result, true);
2717         }
2718     }
2719     catch (std::exception& e)
2720     {
2721         strPrint = string("error: ") + e.what();
2722         nRet = 87;
2723     }
2724     catch (...)
2725     {
2726         PrintException(NULL, "CommandLineRPC()");
2727     }
2728
2729     if (strPrint != "")
2730     {
2731         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2732     }
2733     return nRet;
2734 }
2735
2736
2737
2738
2739 #ifdef TEST
2740 int main(int argc, char *argv[])
2741 {
2742 #ifdef _MSC_VER
2743     // Turn off microsoft heap dump noise
2744     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2745     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2746 #endif
2747     setbuf(stdin, NULL);
2748     setbuf(stdout, NULL);
2749     setbuf(stderr, NULL);
2750
2751     try
2752     {
2753         if (argc >= 2 && string(argv[1]) == "-server")
2754         {
2755             printf("server ready\n");
2756             ThreadRPCServer(NULL);
2757         }
2758         else
2759         {
2760             return CommandLineRPC(argc, argv);
2761         }
2762     }
2763     catch (std::exception& e) {
2764         PrintException(&e, "main()");
2765     } catch (...) {
2766         PrintException(NULL, "main()");
2767     }
2768     return 0;
2769 }
2770 #endif