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