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