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