X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fbitcoinrpc.cpp;h=93c9b4110a05d78686f7c5614bf402d689c2d138;hb=3a05f1d2ce45d5d9fbbd7b1b897f3c6e32f58720;hp=8a98d7fca30c66d2c86a3e940b11da21e60777c3;hpb=79fc752b6104b796aa5e0a8a8b6d2822fb0f3299;p=novacoin.git diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 8a98d7f..93c9b41 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -9,9 +9,11 @@ #include "init.h" #undef printf #include +#include #include #include #include +#include #ifdef USE_SSL #include #include @@ -36,9 +38,13 @@ void ThreadRPCServer2(void* parg); typedef Value(*rpcfn_type)(const Array& params, bool fHelp); extern map mapCallTable; +static std::string strRPCUserColonPass; + static int64 nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; +extern Value dumpprivkey(const Array& params, bool fHelp); +extern Value importprivkey(const Array& params, bool fHelp); Object JSONRPCError(int code, const string& message) { @@ -48,22 +54,35 @@ Object JSONRPCError(int code, const string& message) return error; } - -void PrintConsole(const std::string &format, ...) +double GetDifficulty(const CBlockIndex* blockindex = NULL) { - char buffer[50000]; - int limit = sizeof(buffer); - va_list arg_ptr; - va_start(arg_ptr, format); - int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr); - va_end(arg_ptr); - if (ret < 0 || ret >= limit) + // Floating point number that is a multiple of the minimum difficulty, + // minimum difficulty = 1.0. + if (blockindex == NULL) + { + if (pindexBest == NULL) + return 1.0; + else + blockindex = pindexBest; + } + + int nShift = (blockindex->nBits >> 24) & 0xff; + + double dDiff = + (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff); + + while (nShift < 29) + { + dDiff *= 256.0; + nShift++; + } + while (nShift > 29) { - ret = limit - 1; - buffer[limit-1] = 0; + dDiff /= 256.0; + nShift--; } - printf("%s", buffer); - fprintf(stdout, "%s", buffer); + + return dDiff; } @@ -83,9 +102,26 @@ Value ValueFromAmount(int64 amount) return (double)amount / (double)COIN; } +std::string +HexBits(unsigned int nBits) +{ + union { + int32_t nBits; + char cBits[4]; + } uBits; + uBits.nBits = htonl((int32_t)nBits); + return HexStr(BEGIN(uBits.cBits), END(uBits.cBits)); +} + void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { - entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain())); + int confirms = wtx.GetDepthInMainChain(); + entry.push_back(Pair("confirmations", confirms)); + if (confirms) + { + entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex())); + entry.push_back(Pair("blockindex", wtx.nIndex)); + } entry.push_back(Pair("txid", wtx.GetHash().GetHex())); entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime())); BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue) @@ -100,6 +136,30 @@ string AccountFromValue(const Value& value) return strAccount; } +Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) +{ + Object result; + result.push_back(Pair("hash", block.GetHash().GetHex())); + result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK))); + result.push_back(Pair("height", blockindex->nHeight)); + result.push_back(Pair("version", block.nVersion)); + result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); + result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime())); + result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce)); + result.push_back(Pair("bits", HexBits(block.nBits))); + result.push_back(Pair("difficulty", GetDifficulty(blockindex))); + Array txhashes; + BOOST_FOREACH (const CTransaction&tx, block.vtx) + txhashes.push_back(tx.GetHash().GetHex()); + result.push_back(Pair("tx", txhashes)); + + if (blockindex->pprev) + result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); + if (blockindex->pnext) + result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex())); + return result; +} + /// @@ -126,6 +186,7 @@ Value help(const Array& params, bool fHelp) // We already filter duplicates, but these deprecated screw up the sort order if (strMethod == "getamountreceived" || strMethod == "getallreceived" || + strMethod == "getblocknumber" || // deprecated (strMethod.find("label") != string::npos)) continue; if (strCommand != "" && strMethod != strCommand) @@ -142,7 +203,7 @@ Value help(const Array& params, bool fHelp) // Help text is returned in an exception string strHelp = string(e.what()); if (strCommand == "") - if (strHelp.find('\n') != -1) + if (strHelp.find('\n') != string::npos) strHelp = strHelp.substr(0, strHelp.find('\n')); strRet += strHelp + "\n"; } @@ -181,12 +242,13 @@ Value getblockcount(const Array& params, bool fHelp) } +// deprecated Value getblocknumber(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getblocknumber\n" - "Returns the block number of the latest block in the longest block chain."); + "Deprecated. Use getblockcount."); return nBestHeight; } @@ -203,32 +265,6 @@ Value getconnectioncount(const Array& params, bool fHelp) } -double GetDifficulty() -{ - // Floating point number that is a multiple of the minimum difficulty, - // minimum difficulty = 1.0. - - if (pindexBest == NULL) - return 1.0; - int nShift = (pindexBest->nBits >> 24) & 0xff; - - double dDiff = - (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff); - - while (nShift < 29) - { - dDiff *= 256.0; - nShift++; - } - while (nShift > 29) - { - dDiff /= 256.0; - nShift--; - } - - return dDiff; -} - Value getdifficulty(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -247,7 +283,7 @@ Value getgenerate(const Array& params, bool fHelp) "getgenerate\n" "Returns true or false."); - return (bool)fGenerateBitcoins; + return GetBoolArg("-gen"); } @@ -266,13 +302,11 @@ Value setgenerate(const Array& params, bool fHelp) if (params.size() > 1) { int nGenProcLimit = params[1].get_int(); - fLimitProcessors = (nGenProcLimit != -1); - WriteSetting("fLimitProcessors", fLimitProcessors); - if (nGenProcLimit != -1) - WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit); + mapArgs["-genproclimit"] = itostr(nGenProcLimit); if (nGenProcLimit == 0) fGenerate = false; } + mapArgs["-gen"] = (fGenerate ? "1" : "0"); GenerateBitcoins(fGenerate, pwalletMain); return Value::null; @@ -300,15 +334,14 @@ Value getinfo(const Array& params, bool fHelp) "Returns an object containing various state info."); Object obj; - obj.push_back(Pair("version", (int)VERSION)); + obj.push_back(Pair("version", (int)CLIENT_VERSION)); + obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); + obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); obj.push_back(Pair("blocks", (int)nBestHeight)); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string()))); - obj.push_back(Pair("generate", (bool)fGenerateBitcoins)); - obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); - obj.push_back(Pair("hashespersec", gethashespersec(params, false))); obj.push_back(Pair("testnet", fTestNet)); obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize())); @@ -320,6 +353,28 @@ Value getinfo(const Array& params, bool fHelp) } +Value getmininginfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getmininginfo\n" + "Returns an object containing mining-related information."); + + Object obj; + obj.push_back(Pair("blocks", (int)nBestHeight)); + obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize)); + obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx)); + obj.push_back(Pair("difficulty", (double)GetDifficulty())); + obj.push_back(Pair("errors", GetWarnings("statusbar"))); + obj.push_back(Pair("generate", GetBoolArg("-gen"))); + obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); + obj.push_back(Pair("hashespersec", gethashespersec(params, false))); + obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx)); + obj.push_back(Pair("testnet", fTestNet)); + return obj; +} + + Value getnewaddress(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) @@ -528,8 +583,6 @@ Value sendtoaddress(const Array& params, bool fHelp) return wtx.GetHash().GetHex(); } -static const string strMessageMagic = "Bitcoin Signed Message:\n"; - Value signmessage(const Array& params, bool fHelp) { if (fHelp || params.size() != 2) @@ -591,7 +644,7 @@ Value verifymessage(const Array& params, bool fHelp) if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig)) return false; - return (key.GetAddress() == addr); + return (CBitcoinAddress(key.GetPubKey()) == addr); } @@ -658,7 +711,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) if (params.size() > 1) nMinDepth = params[1].get_int(); - // Get the set of pub keys that have the label + // Get the set of pub keys assigned to account string strAccount = AccountFromValue(params[0]); set setAddress; GetAccountAddresses(strAccount, setAddress); @@ -674,7 +727,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) BOOST_FOREACH(const CTxOut& txout, wtx.vout) { CBitcoinAddress address; - if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address)) + if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address)) if (wtx.GetDepthInMainChain() >= nMinDepth) nAmount += txout.nValue; } @@ -787,7 +840,8 @@ Value movecmd(const Array& params, bool fHelp) strComment = params[4].get_str(); CWalletDB walletdb(pwalletMain->strWalletFile); - walletdb.TxnBegin(); + if (!walletdb.TxnBegin()) + throw JSONRPCError(-20, "database error"); int64 nNow = GetAdjustedTime(); @@ -809,7 +863,8 @@ Value movecmd(const Array& params, bool fHelp) credit.strComment = strComment; walletdb.WriteAccountingEntry(credit); - walletdb.TxnCommit(); + if (!walletdb.TxnCommit()) + throw JSONRPCError(-20, "database error"); return true; } @@ -929,6 +984,81 @@ Value sendmany(const Array& params, bool fHelp) return wtx.GetHash().GetHex(); } +Value addmultisigaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 2 || params.size() > 3) + { + string msg = "addmultisigaddress <'[\"key\",\"key\"]'> [account]\n" + "Add a nrequired-to-sign multisignature address to the wallet\"\n" + "each key is a bitcoin address or hex-encoded public key\n" + "If [account] is specified, assign address to [account]."; + throw runtime_error(msg); + } + if (!fTestNet) + throw runtime_error("addmultisigaddress available only when running -testnet\n"); + + int nRequired = params[0].get_int(); + const Array& keys = params[1].get_array(); + string strAccount; + if (params.size() > 2) + strAccount = AccountFromValue(params[2]); + + // Gather public keys + if (nRequired < 1) + throw runtime_error("a multisignature address must require at least one key to redeem"); + if (keys.size() < nRequired) + throw runtime_error( + strprintf("not enough keys supplied " + "(got %d keys, but need at least %d to redeem)", keys.size(), nRequired)); + std::vector pubkeys; + pubkeys.resize(keys.size()); + for (unsigned int i = 0; i < keys.size(); i++) + { + const std::string& ks = keys[i].get_str(); + + // Case 1: bitcoin address and we have full public key: + CBitcoinAddress address(ks); + if (address.IsValid()) + { + if (address.IsScript()) + throw runtime_error( + strprintf("%s is a pay-to-script address",ks.c_str())); + std::vector vchPubKey; + if (!pwalletMain->GetPubKey(address, vchPubKey)) + throw runtime_error( + strprintf("no full public key for address %s",ks.c_str())); + if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey)) + throw runtime_error(" Invalid public key: "+ks); + } + + // Case 2: hex public key + else if (IsHex(ks)) + { + vector vchPubKey = ParseHex(ks); + if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey)) + throw runtime_error(" Invalid public key: "+ks); + } + else + { + throw runtime_error(" Invalid public key: "+ks); + } + } + + // Construct using pay-to-script-hash: + CScript inner; + inner.SetMultisig(nRequired, pubkeys); + + uint160 scriptHash = Hash160(inner); + CScript scriptPubKey; + scriptPubKey.SetPayToScriptHash(inner); + pwalletMain->AddCScript(inner); + CBitcoinAddress address; + address.SetScriptHash160(scriptHash); + + pwalletMain->SetAddressBookName(address, strAccount); + return address.ToString(); +} + struct tallyitem { @@ -937,7 +1067,7 @@ struct tallyitem tallyitem() { nAmount = 0; - nConf = INT_MAX; + nConf = std::numeric_limits::max(); } }; @@ -958,6 +1088,7 @@ Value ListReceived(const Array& params, bool fByAccounts) for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; + if (wtx.IsCoinBase() || !wtx.IsFinal()) continue; @@ -968,7 +1099,7 @@ Value ListReceived(const Array& params, bool fByAccounts) BOOST_FOREACH(const CTxOut& txout, wtx.vout) { CBitcoinAddress address; - if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid()) + if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid()) continue; tallyitem& item = mapTally[address]; @@ -989,7 +1120,7 @@ Value ListReceived(const Array& params, bool fByAccounts) continue; int64 nAmount = 0; - int nConf = INT_MAX; + int nConf = std::numeric_limits::max(); if (it != mapTally.end()) { nAmount = (*it).second.nAmount; @@ -1008,7 +1139,7 @@ Value ListReceived(const Array& params, bool fByAccounts) obj.push_back(Pair("address", address.ToString())); obj.push_back(Pair("account", strAccount)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); - obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf))); + obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); ret.push_back(obj); } } @@ -1022,7 +1153,7 @@ Value ListReceived(const Array& params, bool fByAccounts) Object obj; obj.push_back(Pair("account", (*it).first)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); - obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf))); + obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); ret.push_back(obj); } } @@ -1067,6 +1198,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe string strSentAccount; list > listReceived; list > listSent; + wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount); bool fAllAccounts = (strAccount == string("*")); @@ -1276,8 +1408,8 @@ Value listsinceblock(const Array& params, bool fHelp) { if (fHelp) throw runtime_error( - "listsinceblock [blockid] [target-confirmations]\n" - "Get all transactions in blocks since block [blockid], or all transactions if omitted"); + "listsinceblock [blockhash] [target-confirmations]\n" + "Get all transactions in blocks since block [blockhash], or all transactions if omitted"); CBlockIndex *pindex = NULL; int target_confirms = 1; @@ -1314,7 +1446,6 @@ Value listsinceblock(const Array& params, bool fHelp) if (target_confirms == 1) { - printf("oops!\n"); lastblock = hashBestChain; } else @@ -1605,14 +1736,42 @@ Value validateaddress(const Array& params, bool fHelp) // version of the address: string currentAddress = address.ToString(); ret.push_back(Pair("address", currentAddress)); - ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0))); + if (pwalletMain->HaveKey(address)) + { + ret.push_back(Pair("ismine", true)); + std::vector vchPubKey; + pwalletMain->GetPubKey(address, vchPubKey); + ret.push_back(Pair("pubkey", HexStr(vchPubKey))); + CKey key; + key.SetPubKey(vchPubKey); + ret.push_back(Pair("iscompressed", key.IsCompressed())); + } + else if (pwalletMain->HaveCScript(address.GetHash160())) + { + ret.push_back(Pair("isscript", true)); + CScript subscript; + pwalletMain->GetCScript(address.GetHash160(), subscript); + ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript))); + std::vector addresses; + txnouttype whichType; + int nRequired; + ExtractAddresses(subscript, whichType, addresses, nRequired); + ret.push_back(Pair("script", GetTxnOutputType(whichType))); + Array a; + BOOST_FOREACH(const CBitcoinAddress& addr, addresses) + a.push_back(addr.ToString()); + ret.push_back(Pair("addresses", a)); + if (whichType == TX_MULTISIG) + ret.push_back(Pair("sigsrequired", nRequired)); + } + else + ret.push_back(Pair("ismine", false)); if (pwalletMain->mapAddressBook.count(address)) ret.push_back(Pair("account", pwalletMain->mapAddressBook[address])); } return ret; } - Value getwork(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) @@ -1728,7 +1887,10 @@ Value getmemorypool(const Array& params, bool fHelp) " \"previousblockhash\" : hash of current highest block\n" " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n" " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n" + " \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n" " \"time\" : timestamp appropriate for next block\n" + " \"mintime\" : minimum timestamp appropriate for next block\n" + " \"curtime\" : current timestamp\n" " \"bits\" : compressed target of next block\n" "If [data] is specified, tries to solve the block and returns true if it was successful."); @@ -1782,14 +1944,11 @@ Value getmemorypool(const Array& params, bool fHelp) result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); result.push_back(Pair("transactions", transactions)); result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); + result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()))); result.push_back(Pair("time", (int64_t)pblock->nTime)); - - union { - int32_t nBits; - char cBits[4]; - } uBits; - uBits.nBits = htonl((int32_t)pblock->nBits); - result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits)))); + result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); + result.push_back(Pair("curtime", (int64_t)GetAdjustedTime())); + result.push_back(Pair("bits", HexBits(pblock->nBits))); return result; } @@ -1804,6 +1963,44 @@ Value getmemorypool(const Array& params, bool fHelp) } } +Value getblockhash(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getblockhash \n" + "Returns hash of block in best-block-chain at ."); + + int nHeight = params[0].get_int(); + if (nHeight < 0 || nHeight > nBestHeight) + throw runtime_error("Block number out of range."); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hashBestChain]; + while (pblockindex->nHeight > nHeight) + pblockindex = pblockindex->pprev; + return pblockindex->phashBlock->GetHex(); +} + +Value getblock(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getblock \n" + "Returns details of a block with given block-hash."); + + std::string strHash = params[0].get_str(); + uint256 hash(strHash); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(-5, "Block not found"); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + block.ReadFromDisk(pblockindex, true); + + return blockToJSON(block, pblockindex); +} + @@ -1830,6 +2027,7 @@ pair pCallTable[] = make_pair("setgenerate", &setgenerate), make_pair("gethashespersec", &gethashespersec), make_pair("getinfo", &getinfo), + make_pair("getmininginfo", &getmininginfo), make_pair("getnewaddress", &getnewaddress), make_pair("getaccountaddress", &getaccountaddress), make_pair("setaccount", &setaccount), @@ -1851,15 +2049,20 @@ pair pCallTable[] = make_pair("move", &movecmd), make_pair("sendfrom", &sendfrom), make_pair("sendmany", &sendmany), + make_pair("addmultisigaddress", &addmultisigaddress), + make_pair("getblock", &getblock), + make_pair("getblockhash", &getblockhash), make_pair("gettransaction", &gettransaction), make_pair("listtransactions", &listtransactions), - make_pair("signmessage", &signmessage), - make_pair("verifymessage", &verifymessage), + make_pair("signmessage", &signmessage), + make_pair("verifymessage", &verifymessage), make_pair("getwork", &getwork), make_pair("listaccounts", &listaccounts), make_pair("settxfee", &settxfee), make_pair("getmemorypool", &getmemorypool), - make_pair("listsinceblock", &listsinceblock), + make_pair("listsinceblock", &listsinceblock), + make_pair("dumpprivkey", &dumpprivkey), + make_pair("importprivkey", &importprivkey) }; map mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0])); @@ -1868,13 +2071,14 @@ string pAllowInSafeMode[] = "help", "stop", "getblockcount", - "getblocknumber", + "getblocknumber", // deprecated "getconnectioncount", "getdifficulty", "getgenerate", "setgenerate", "gethashespersec", "getinfo", + "getmininginfo", "getnewaddress", "getaccountaddress", "getaccount", @@ -2039,12 +2243,7 @@ bool HTTPAuthorized(map& mapHeaders) return false; string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64); string strUserPass = DecodeBase64(strUserPass64); - string::size_type nColon = strUserPass.find(":"); - if (nColon == string::npos) - return false; - string strUser = strUserPass.substr(0, nColon); - string strPassword = strUserPass.substr(nColon+1); - return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]); + return strUserPass == strRPCUserColonPass; } // @@ -2159,15 +2358,15 @@ void ThreadRPCServer(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg)); try { - vnThreadsRunning[4]++; + vnThreadsRunning[THREAD_RPCSERVER]++; ThreadRPCServer2(parg); - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; } catch (std::exception& e) { - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; PrintException(&e, "ThreadRPCServer()"); } catch (...) { - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; PrintException(NULL, "ThreadRPCServer()"); } printf("ThreadRPCServer exiting\n"); @@ -2181,7 +2380,8 @@ void ThreadRPCServer2(void* parg) { printf("ThreadRPCServer started\n"); - if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "") + strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; + if (mapArgs["-rpcpassword"] == "") { unsigned char rand_pwd[32]; RAND_bytes(rand_pwd, 32); @@ -2191,7 +2391,7 @@ void ThreadRPCServer2(void* parg) else if (mapArgs.count("-daemon")) strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\""); ThreadSafeMessageBox(strprintf( - _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n" + _("%s, you must set a rpcpassword in the configuration file:\n %s\n" "It is recommended you use the following random password:\n" "rpcuser=bitcoinrpc\n" "rpcpassword=%s\n" @@ -2225,7 +2425,7 @@ void ThreadRPCServer2(void* parg) acceptor.bind(endpoint); acceptor.listen(socket_base::max_connections); } - catch(system::system_error &e) + catch(boost::system::system_error &e) { HACK_SHUTDOWN = true; ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()), @@ -2269,7 +2469,7 @@ void ThreadRPCServer2(void* parg) #endif ip::tcp::endpoint peer; - vnThreadsRunning[4]--; + vnThreadsRunning[THREAD_RPCSERVER]--; #ifdef USE_SSL acceptor.accept(sslStream.lowest_layer(), peer); #else @@ -2510,6 +2710,7 @@ int CommandLineRPC(int argc, char *argv[]) if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo(params[0]); if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo(params[1]); if (strMethod == "getbalance" && n > 1) ConvertTo(params[1]); + if (strMethod == "getblockhash" && n > 0) ConvertTo(params[0]); if (strMethod == "move" && n > 2) ConvertTo(params[2]); if (strMethod == "move" && n > 3) ConvertTo(params[3]); if (strMethod == "sendfrom" && n > 2) ConvertTo(params[2]); @@ -2528,6 +2729,15 @@ int CommandLineRPC(int argc, char *argv[]) params[1] = v.get_obj(); } if (strMethod == "sendmany" && n > 2) ConvertTo(params[2]); + if (strMethod == "addmultisigaddress" && n > 0) ConvertTo(params[0]); + if (strMethod == "addmultisigaddress" && n > 1) + { + string s = params[1].get_str(); + Value v; + if (!read_string(s, v) || v.type() != array_type) + throw runtime_error("type mismatch "+s); + params[1] = v.get_array(); + } // Execute Object reply = CallRPC(strMethod, params);