diff options
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/blockchain.cpp | 87 | ||||
-rw-r--r-- | src/rpc/client.cpp | 1 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 30 | ||||
-rw-r--r-- | src/rpc/misc.cpp | 53 | ||||
-rw-r--r-- | src/rpc/net.cpp | 24 | ||||
-rw-r--r-- | src/rpc/protocol.h | 4 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 100 | ||||
-rw-r--r-- | src/rpc/safemode.cpp | 14 | ||||
-rw-r--r-- | src/rpc/safemode.h | 12 | ||||
-rw-r--r-- | src/rpc/server.cpp | 8 |
10 files changed, 184 insertions, 149 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 06c68ea27c..238d8c9d95 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -47,8 +47,6 @@ static std::mutex cs_blockchange; static std::condition_variable cond_blockchange; static CUpdatedBlock latestblock; -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); - /* Calculate the difficulty for a given block index, * or the block index of the given chain. */ @@ -159,7 +157,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx return result; } -UniValue getblockcount(const JSONRPCRequest& request) +static UniValue getblockcount(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -176,7 +174,7 @@ UniValue getblockcount(const JSONRPCRequest& request) return chainActive.Height(); } -UniValue getbestblockhash(const JSONRPCRequest& request) +static UniValue getbestblockhash(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -203,7 +201,7 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex) cond_blockchange.notify_all(); } -UniValue waitfornewblock(const JSONRPCRequest& request) +static UniValue waitfornewblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) throw std::runtime_error( @@ -241,7 +239,7 @@ UniValue waitfornewblock(const JSONRPCRequest& request) return ret; } -UniValue waitforblock(const JSONRPCRequest& request) +static UniValue waitforblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( @@ -283,7 +281,7 @@ UniValue waitforblock(const JSONRPCRequest& request) return ret; } -UniValue waitforblockheight(const JSONRPCRequest& request) +static UniValue waitforblockheight(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( @@ -325,7 +323,7 @@ UniValue waitforblockheight(const JSONRPCRequest& request) return ret; } -UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request) +static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 0) { throw std::runtime_error( @@ -340,7 +338,7 @@ UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request) return NullUniValue; } -UniValue getdifficulty(const JSONRPCRequest& request) +static UniValue getdifficulty(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -357,20 +355,26 @@ UniValue getdifficulty(const JSONRPCRequest& request) return GetDifficulty(); } -std::string EntryDescriptionString() +static std::string EntryDescriptionString() { return " \"size\" : n, (numeric) virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted.\n" - " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" - " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority\n" + " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)\n" + " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority (DEPRECATED)\n" " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" " \"height\" : n, (numeric) block height when transaction entered pool\n" " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n" " \"descendantsize\" : n, (numeric) virtual transaction size of in-mempool descendants (including this one)\n" - " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one)\n" + " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) (DEPRECATED)\n" " \"ancestorcount\" : n, (numeric) number of in-mempool ancestor transactions (including this one)\n" " \"ancestorsize\" : n, (numeric) virtual transaction size of in-mempool ancestors (including this one)\n" - " \"ancestorfees\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one)\n" + " \"ancestorfees\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) (DEPRECATED)\n" " \"wtxid\" : hash, (string) hash of serialized transaction, including witness data\n" + " \"fees\" : {\n" + " \"base\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" + " \"modified\" : n, (numeric) transaction fee with fee deltas used for mining priority in " + CURRENCY_UNIT + "\n" + " \"ancestor\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) in " + CURRENCY_UNIT + "\n" + " \"descendant\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) in " + CURRENCY_UNIT + "\n" + " }\n" " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" " \"transactionid\", (string) parent transaction id\n" " ... ]\n" @@ -379,10 +383,17 @@ std::string EntryDescriptionString() " ... ]\n"; } -void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) +static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs) { AssertLockHeld(mempool.cs); + UniValue fees(UniValue::VOBJ); + fees.pushKV("base", ValueFromAmount(e.GetFee())); + fees.pushKV("modified", ValueFromAmount(e.GetModifiedFee())); + fees.pushKV("ancestor", ValueFromAmount(e.GetModFeesWithAncestors())); + fees.pushKV("descendant", ValueFromAmount(e.GetModFeesWithDescendants())); + info.pushKV("fees", fees); + info.pushKV("size", (int)e.GetTxSize()); info.pushKV("fee", ValueFromAmount(e.GetFee())); info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee())); @@ -449,7 +460,7 @@ UniValue mempoolToJSON(bool fVerbose) } } -UniValue getrawmempool(const JSONRPCRequest& request) +static UniValue getrawmempool(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) throw std::runtime_error( @@ -481,7 +492,7 @@ UniValue getrawmempool(const JSONRPCRequest& request) return mempoolToJSON(fVerbose); } -UniValue getmempoolancestors(const JSONRPCRequest& request) +static UniValue getmempoolancestors(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { throw std::runtime_error( @@ -545,7 +556,7 @@ UniValue getmempoolancestors(const JSONRPCRequest& request) } } -UniValue getmempooldescendants(const JSONRPCRequest& request) +static UniValue getmempooldescendants(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { throw std::runtime_error( @@ -609,7 +620,7 @@ UniValue getmempooldescendants(const JSONRPCRequest& request) } } -UniValue getmempoolentry(const JSONRPCRequest& request) +static UniValue getmempoolentry(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) { throw std::runtime_error( @@ -642,7 +653,7 @@ UniValue getmempoolentry(const JSONRPCRequest& request) return info; } -UniValue getblockhash(const JSONRPCRequest& request) +static UniValue getblockhash(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( @@ -667,7 +678,7 @@ UniValue getblockhash(const JSONRPCRequest& request) return pblockindex->GetBlockHash().GetHex(); } -UniValue getblockheader(const JSONRPCRequest& request) +static UniValue getblockheader(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( @@ -726,7 +737,7 @@ UniValue getblockheader(const JSONRPCRequest& request) return blockheaderToJSON(pblockindex); } -UniValue getblock(const JSONRPCRequest& request) +static UniValue getblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( @@ -888,7 +899,7 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) return true; } -UniValue pruneblockchain(const JSONRPCRequest& request) +static UniValue pruneblockchain(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( @@ -929,7 +940,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request) else if (height > chainHeight) throw JSONRPCError(RPC_INVALID_PARAMETER, "Blockchain is shorter than the attempted prune height."); else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) { - LogPrint(BCLog::RPC, "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks."); + LogPrint(BCLog::RPC, "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks.\n"); height = chainHeight - MIN_BLOCKS_TO_KEEP; } @@ -937,7 +948,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request) return uint64_t(height); } -UniValue gettxoutsetinfo(const JSONRPCRequest& request) +static UniValue gettxoutsetinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -947,9 +958,9 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request) "\nResult:\n" "{\n" " \"height\":n, (numeric) The current block height (index)\n" - " \"bestblock\": \"hex\", (string) the best block hash hex\n" - " \"transactions\": n, (numeric) The number of transactions\n" - " \"txouts\": n, (numeric) The number of output transactions\n" + " \"bestblock\": \"hex\", (string) The hash of the block at the tip of the chain\n" + " \"transactions\": n, (numeric) The number of transactions with unspent outputs\n" + " \"txouts\": n, (numeric) The number of unspent transaction outputs\n" " \"bogosize\": n, (numeric) A meaningless metric for UTXO set size\n" " \"hash_serialized_2\": \"hash\", (string) The serialized hash\n" " \"disk_size\": n, (numeric) The estimated size of the chainstate on disk\n" @@ -992,7 +1003,7 @@ UniValue gettxout(const JSONRPCRequest& request) " Note that an unspent output that is spent in the mempool won't appear.\n" "\nResult:\n" "{\n" - " \"bestblock\" : \"hash\", (string) the block hash\n" + " \"bestblock\": \"hash\", (string) The hash of the block at the tip of the chain\n" " \"confirmations\" : n, (numeric) The number of confirmations\n" " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" " \"scriptPubKey\" : { (json object)\n" @@ -1058,7 +1069,7 @@ UniValue gettxout(const JSONRPCRequest& request) return ret; } -UniValue verifychain(const JSONRPCRequest& request) +static UniValue verifychain(const JSONRPCRequest& request) { int nCheckLevel = gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL); int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); @@ -1148,7 +1159,7 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse return rv; } -void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +static void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) { // Deployments with timeout value of 0 are hidden. // A timeout value of 0 guarantees a softfork will never be activated. @@ -1274,7 +1285,7 @@ struct CompareBlocksByHeight } }; -UniValue getchaintips(const JSONRPCRequest& request) +static UniValue getchaintips(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -1391,7 +1402,7 @@ UniValue mempoolInfoToJSON() return ret; } -UniValue getmempoolinfo(const JSONRPCRequest& request) +static UniValue getmempoolinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -1414,7 +1425,7 @@ UniValue getmempoolinfo(const JSONRPCRequest& request) return mempoolInfoToJSON(); } -UniValue preciousblock(const JSONRPCRequest& request) +static UniValue preciousblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( @@ -1452,7 +1463,7 @@ UniValue preciousblock(const JSONRPCRequest& request) return NullUniValue; } -UniValue invalidateblock(const JSONRPCRequest& request) +static UniValue invalidateblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( @@ -1491,7 +1502,7 @@ UniValue invalidateblock(const JSONRPCRequest& request) return NullUniValue; } -UniValue reconsiderblock(const JSONRPCRequest& request) +static UniValue reconsiderblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( @@ -1529,7 +1540,7 @@ UniValue reconsiderblock(const JSONRPCRequest& request) return NullUniValue; } -UniValue getchaintxstats(const JSONRPCRequest& request) +static UniValue getchaintxstats(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 2) throw std::runtime_error( @@ -1603,7 +1614,7 @@ UniValue getchaintxstats(const JSONRPCRequest& request) return ret; } -UniValue savemempool(const JSONRPCRequest& request) +static UniValue savemempool(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) { throw std::runtime_error( diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 34c41b3b6b..475fe1e274 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -38,6 +38,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "sendtoaddress", 5 , "replaceable" }, { "sendtoaddress", 6 , "conf_target" }, { "settxfee", 0, "amount" }, + { "sethdseed", 0, "newkeypool" }, { "getreceivedbyaddress", 1, "minconf" }, { "getreceivedbyaccount", 1, "minconf" }, { "getreceivedbylabel", 1, "minconf" }, diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 313f3310e2..203fac39e2 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -44,7 +44,7 @@ unsigned int ParseConfirmTarget(const UniValue& value) * or from the last difficulty change if 'lookup' is nonpositive. * If 'height' is nonnegative, compute the estimate at the time when a given block was found. */ -UniValue GetNetworkHashPS(int lookup, int height) { +static UniValue GetNetworkHashPS(int lookup, int height) { CBlockIndex *pb = chainActive.Tip(); if (height >= 0 && height < chainActive.Height()) @@ -81,7 +81,7 @@ UniValue GetNetworkHashPS(int lookup, int height) { return workDiff.getdouble() / timeDiff; } -UniValue getnetworkhashps(const JSONRPCRequest& request) +static UniValue getnetworkhashps(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 2) throw std::runtime_error( @@ -116,7 +116,7 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen } unsigned int nExtraNonce = 0; UniValue blockHashes(UniValue::VARR); - while (nHeight < nHeightEnd) + while (nHeight < nHeightEnd && !ShutdownRequested()) { std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript)); if (!pblocktemplate.get()) @@ -151,7 +151,7 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen return blockHashes; } -UniValue generatetoaddress(const JSONRPCRequest& request) +static UniValue generatetoaddress(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) throw std::runtime_error( @@ -185,7 +185,7 @@ UniValue generatetoaddress(const JSONRPCRequest& request) return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false); } -UniValue getmininginfo(const JSONRPCRequest& request) +static UniValue getmininginfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -224,7 +224,7 @@ UniValue getmininginfo(const JSONRPCRequest& request) // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts -UniValue prioritisetransaction(const JSONRPCRequest& request) +static UniValue prioritisetransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 3) throw std::runtime_error( @@ -278,7 +278,7 @@ static UniValue BIP22ValidationResult(const CValidationState& state) return "valid?"; } -std::string gbt_vb_name(const Consensus::DeploymentPos pos) { +static std::string gbt_vb_name(const Consensus::DeploymentPos pos) { const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; std::string s = vbinfo.name; if (!vbinfo.gbt_force) { @@ -287,7 +287,7 @@ std::string gbt_vb_name(const Consensus::DeploymentPos pos) { return s; } -UniValue getblocktemplate(const JSONRPCRequest& request) +static UniValue getblocktemplate(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) throw std::runtime_error( @@ -471,10 +471,10 @@ UniValue getblocktemplate(const JSONRPCRequest& request) { checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1); - WaitableLock lock(csBestBlock); - while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning()) + WaitableLock lock(g_best_block_mutex); + while (g_best_block == hashWatchedChain && IsRPCRunning()) { - if (cvBlockChange.wait_until(lock, checktxtime) == std::cv_status::timeout) + if (g_best_block_cv.wait_until(lock, checktxtime) == std::cv_status::timeout) { // Timeout: Check transactions for update if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP) @@ -695,7 +695,7 @@ protected: } }; -UniValue submitblock(const JSONRPCRequest& request) +static UniValue submitblock(const JSONRPCRequest& request) { // We allow 2 arguments for compliance with BIP22. Argument 2 is ignored. if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { @@ -765,13 +765,13 @@ UniValue submitblock(const JSONRPCRequest& request) return BIP22ValidationResult(sc.state); } -UniValue estimatefee(const JSONRPCRequest& request) +static UniValue estimatefee(const JSONRPCRequest& request) { throw JSONRPCError(RPC_METHOD_DEPRECATED, "estimatefee was removed in v0.17.\n" "Clients should use estimatesmartfee."); } -UniValue estimatesmartfee(const JSONRPCRequest& request) +static UniValue estimatesmartfee(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( @@ -832,7 +832,7 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) return result; } -UniValue estimaterawfee(const JSONRPCRequest& request) +static UniValue estimaterawfee(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 49e865a64a..6772784d3d 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -33,7 +33,7 @@ #include <univalue.h> -UniValue validateaddress(const JSONRPCRequest& request) +static UniValue validateaddress(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( @@ -69,7 +69,7 @@ UniValue validateaddress(const JSONRPCRequest& request) { #ifdef ENABLE_WALLET - if (!::vpwallets.empty() && IsDeprecatedRPCEnabled("validateaddress")) { + if (HasWallets() && IsDeprecatedRPCEnabled("validateaddress")) { ret.pushKVs(getaddressinfo(request)); } #endif @@ -90,7 +90,7 @@ UniValue validateaddress(const JSONRPCRequest& request) // Needed even with !ENABLE_WALLET, to pass (ignored) pointers around class CWallet; -UniValue createmultisig(const JSONRPCRequest& request) +static UniValue createmultisig(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 2 || request.params.size() > 2) { @@ -145,7 +145,7 @@ UniValue createmultisig(const JSONRPCRequest& request) return result; } -UniValue verifymessage(const JSONRPCRequest& request) +static UniValue verifymessage(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 3) throw std::runtime_error( @@ -201,7 +201,7 @@ UniValue verifymessage(const JSONRPCRequest& request) return (pubkey.GetID() == *keyID); } -UniValue signmessagewithprivkey(const JSONRPCRequest& request) +static UniValue signmessagewithprivkey(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 2) throw std::runtime_error( @@ -240,7 +240,7 @@ UniValue signmessagewithprivkey(const JSONRPCRequest& request) return EncodeBase64(vchSig.data(), vchSig.size()); } -UniValue setmocktime(const JSONRPCRequest& request) +static UniValue setmocktime(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( @@ -299,7 +299,7 @@ static std::string RPCMallocInfo() } #endif -UniValue getmemoryinfo(const JSONRPCRequest& request) +static UniValue getmemoryinfo(const JSONRPCRequest& request) { /* Please, avoid using the word "pool" here in the RPC interface or help, * as users will undoubtedly confuse it with the other "memory pool" @@ -346,21 +346,22 @@ UniValue getmemoryinfo(const JSONRPCRequest& request) } } -uint32_t getCategoryMask(UniValue cats) { +static void EnableOrDisableLogCategories(UniValue cats, bool enable) { cats = cats.get_array(); - uint32_t mask = 0; for (unsigned int i = 0; i < cats.size(); ++i) { - uint32_t flag = 0; std::string cat = cats[i].get_str(); - if (!GetLogCategory(&flag, &cat)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat); + + bool success; + if (enable) { + success = g_logger->EnableCategory(cat); + } else { + success = g_logger->DisableCategory(cat); } - if (flag == BCLog::NONE) { - return 0; + + if (!success) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat); } - mask |= flag; } - return mask; } UniValue logging(const JSONRPCRequest& request) @@ -399,25 +400,25 @@ UniValue logging(const JSONRPCRequest& request) ); } - uint32_t originalLogCategories = logCategories; + uint32_t original_log_categories = g_logger->GetCategoryMask(); if (request.params[0].isArray()) { - logCategories |= getCategoryMask(request.params[0]); + EnableOrDisableLogCategories(request.params[0], true); } - if (request.params[1].isArray()) { - logCategories &= ~getCategoryMask(request.params[1]); + EnableOrDisableLogCategories(request.params[1], false); } + uint32_t updated_log_categories = g_logger->GetCategoryMask(); + uint32_t changed_log_categories = original_log_categories ^ updated_log_categories; // Update libevent logging if BCLog::LIBEVENT has changed. // If the library version doesn't allow it, UpdateHTTPServerLogging() returns false, // in which case we should clear the BCLog::LIBEVENT flag. // Throw an error if the user has explicitly asked to change only the libevent // flag and it failed. - uint32_t changedLogCategories = originalLogCategories ^ logCategories; - if (changedLogCategories & BCLog::LIBEVENT) { - if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) { - logCategories &= ~BCLog::LIBEVENT; - if (changedLogCategories == BCLog::LIBEVENT) { + if (changed_log_categories & BCLog::LIBEVENT) { + if (!UpdateHTTPServerLogging(g_logger->WillLogCategory(BCLog::LIBEVENT))) { + g_logger->DisableCategory(BCLog::LIBEVENT); + if (changed_log_categories == BCLog::LIBEVENT) { throw JSONRPCError(RPC_INVALID_PARAMETER, "libevent logging cannot be updated when using libevent before v2.1.1."); } } @@ -432,7 +433,7 @@ UniValue logging(const JSONRPCRequest& request) return result; } -UniValue echo(const JSONRPCRequest& request) +static UniValue echo(const JSONRPCRequest& request) { if (request.fHelp) throw std::runtime_error( diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index fee2b765ba..1530d8578b 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -23,7 +23,7 @@ #include <univalue.h> -UniValue getconnectioncount(const JSONRPCRequest& request) +static UniValue getconnectioncount(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -42,7 +42,7 @@ UniValue getconnectioncount(const JSONRPCRequest& request) return (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL); } -UniValue ping(const JSONRPCRequest& request) +static UniValue ping(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -65,7 +65,7 @@ UniValue ping(const JSONRPCRequest& request) return NullUniValue; } -UniValue getpeerinfo(const JSONRPCRequest& request) +static UniValue getpeerinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -190,7 +190,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) return ret; } -UniValue addnode(const JSONRPCRequest& request) +static UniValue addnode(const JSONRPCRequest& request) { std::string strCommand; if (!request.params[1].isNull()) @@ -237,7 +237,7 @@ UniValue addnode(const JSONRPCRequest& request) return NullUniValue; } -UniValue disconnectnode(const JSONRPCRequest& request) +static UniValue disconnectnode(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() == 0 || request.params.size() >= 3) throw std::runtime_error( @@ -280,7 +280,7 @@ UniValue disconnectnode(const JSONRPCRequest& request) return NullUniValue; } -UniValue getaddednodeinfo(const JSONRPCRequest& request) +static UniValue getaddednodeinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) throw std::runtime_error( @@ -347,7 +347,7 @@ UniValue getaddednodeinfo(const JSONRPCRequest& request) return ret; } -UniValue getnettotals(const JSONRPCRequest& request) +static UniValue getnettotals(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 0) throw std::runtime_error( @@ -413,7 +413,7 @@ static UniValue GetNetworksInfo() return networks; } -UniValue getnetworkinfo(const JSONRPCRequest& request) +static UniValue getnetworkinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -489,7 +489,7 @@ UniValue getnetworkinfo(const JSONRPCRequest& request) return obj; } -UniValue setban(const JSONRPCRequest& request) +static UniValue setban(const JSONRPCRequest& request) { std::string strCommand; if (!request.params[1].isNull()) @@ -553,7 +553,7 @@ UniValue setban(const JSONRPCRequest& request) return NullUniValue; } -UniValue listbanned(const JSONRPCRequest& request) +static UniValue listbanned(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -586,7 +586,7 @@ UniValue listbanned(const JSONRPCRequest& request) return bannedAddresses; } -UniValue clearbanned(const JSONRPCRequest& request) +static UniValue clearbanned(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) throw std::runtime_error( @@ -604,7 +604,7 @@ UniValue clearbanned(const JSONRPCRequest& request) return NullUniValue; } -UniValue setnetworkactive(const JSONRPCRequest& request) +static UniValue setnetworkactive(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) { throw std::runtime_error( diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 4a265735d2..6954aed252 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -46,7 +46,6 @@ enum RPCErrorCode //! General application defined errors RPC_MISC_ERROR = -1, //!< std::exception thrown in command handling - RPC_FORBIDDEN_BY_SAFE_MODE = -2, //!< Server is in safe mode, and command is not allowed in safe mode RPC_TYPE_ERROR = -3, //!< Unexpected type was passed as parameter RPC_INVALID_ADDRESS_OR_KEY = -5, //!< Invalid address or key RPC_OUT_OF_MEMORY = -7, //!< Ran out of memory during operation @@ -88,6 +87,9 @@ enum RPCErrorCode //! Backwards compatible aliases RPC_WALLET_INVALID_ACCOUNT_NAME = RPC_WALLET_INVALID_LABEL_NAME, + + //! Unused reserved codes, kept around for backwards compatibility. Do not reuse. + RPC_FORBIDDEN_BY_SAFE_MODE = -2, //!< Server is in safe mode, and command is not allowed in safe mode }; UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index cc616ce5e6..c5185ca599 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -7,6 +7,7 @@ #include <coins.h> #include <consensus/validation.h> #include <core_io.h> +#include <index/txindex.h> #include <init.h> #include <keystore.h> #include <validation.h> @@ -18,7 +19,6 @@ #include <policy/rbf.h> #include <primitives/transaction.h> #include <rpc/rawtransaction.h> -#include <rpc/safemode.h> #include <rpc/server.h> #include <script/script.h> #include <script/script_error.h> @@ -37,7 +37,7 @@ #include <univalue.h> -void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) +static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) { // Call into TxToUniv() in bitcoin-common to decode the transaction hex. // @@ -47,6 +47,8 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) TxToUniv(tx, uint256(), entry, true, RPCSerializationFlags()); if (!hashBlock.IsNull()) { + LOCK(cs_main); + entry.pushKV("blockhash", hashBlock.GetHex()); CBlockIndex* pindex = LookupBlockIndex(hashBlock); if (pindex) { @@ -61,7 +63,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) } } -UniValue getrawtransaction(const JSONRPCRequest& request) +static UniValue getrawtransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) throw std::runtime_error( @@ -94,6 +96,7 @@ UniValue getrawtransaction(const JSONRPCRequest& request) " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" " \"size\" : n, (numeric) The serialized transaction size\n" " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n" + " \"weight\" : n, (numeric) The transaction's weight (between vsize*4-3 and vsize*4)\n" " \"version\" : n, (numeric) The version\n" " \"locktime\" : ttt, (numeric) The lock time\n" " \"vin\" : [ (array of json objects)\n" @@ -140,8 +143,6 @@ UniValue getrawtransaction(const JSONRPCRequest& request) + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"") ); - LOCK(cs_main); - bool in_active_chain = true; uint256 hash = ParseHashV(request.params[0], "parameter 1"); CBlockIndex* blockindex = nullptr; @@ -158,6 +159,8 @@ UniValue getrawtransaction(const JSONRPCRequest& request) } if (!request.params[2].isNull()) { + LOCK(cs_main); + uint256 blockhash = ParseHashV(request.params[2], "parameter 3"); blockindex = LookupBlockIndex(blockhash); if (!blockindex) { @@ -166,6 +169,11 @@ UniValue getrawtransaction(const JSONRPCRequest& request) in_active_chain = chainActive.Contains(blockindex); } + bool f_txindex_ready = false; + if (g_txindex && !blockindex) { + f_txindex_ready = g_txindex->BlockUntilSyncedToCurrentChain(); + } + CTransactionRef tx; uint256 hash_block; if (!GetTransaction(hash, tx, Params().GetConsensus(), hash_block, true, blockindex)) { @@ -175,10 +183,12 @@ UniValue getrawtransaction(const JSONRPCRequest& request) throw JSONRPCError(RPC_MISC_ERROR, "Block not available"); } errmsg = "No such transaction found in the provided block"; + } else if (!g_txindex) { + errmsg = "No such mempool transaction. Use -txindex to enable blockchain transaction queries"; + } else if (!f_txindex_ready) { + errmsg = "No such mempool transaction. Blockchain transactions are still in the process of being indexed"; } else { - errmsg = fTxIndex - ? "No such mempool or blockchain transaction" - : "No such mempool transaction. Use -txindex to enable blockchain transaction queries"; + errmsg = "No such mempool or blockchain transaction"; } throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errmsg + ". Use gettransaction for wallet transactions."); } @@ -193,7 +203,7 @@ UniValue getrawtransaction(const JSONRPCRequest& request) return result; } -UniValue gettxoutproof(const JSONRPCRequest& request) +static UniValue gettxoutproof(const JSONRPCRequest& request) { if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2)) throw std::runtime_error( @@ -228,19 +238,18 @@ UniValue gettxoutproof(const JSONRPCRequest& request) oneTxid = hash; } - LOCK(cs_main); - CBlockIndex* pblockindex = nullptr; - uint256 hashBlock; - if (!request.params[1].isNull()) - { + if (!request.params[1].isNull()) { + LOCK(cs_main); hashBlock = uint256S(request.params[1].get_str()); pblockindex = LookupBlockIndex(hashBlock); if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } } else { + LOCK(cs_main); + // Loop through txids and try to find which block they're in. Exit loop once a block is found. for (const auto& tx : setTxids) { const Coin& coin = AccessByTxid(*pcoinsTip, tx); @@ -251,6 +260,14 @@ UniValue gettxoutproof(const JSONRPCRequest& request) } } + + // Allow txindex to catch up if we need to query it and before we acquire cs_main. + if (g_txindex && !pblockindex) { + g_txindex->BlockUntilSyncedToCurrentChain(); + } + + LOCK(cs_main); + if (pblockindex == nullptr) { CTransactionRef tx; @@ -280,7 +297,7 @@ UniValue gettxoutproof(const JSONRPCRequest& request) return strHex; } -UniValue verifytxoutproof(const JSONRPCRequest& request) +static UniValue verifytxoutproof(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( @@ -316,7 +333,7 @@ UniValue verifytxoutproof(const JSONRPCRequest& request) return res; } -UniValue createrawtransaction(const JSONRPCRequest& request) +static UniValue createrawtransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) { throw std::runtime_error( @@ -476,7 +493,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) return EncodeHexTx(rawTx); } -UniValue decoderawtransaction(const JSONRPCRequest& request) +static UniValue decoderawtransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( @@ -494,6 +511,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request) " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" " \"size\" : n, (numeric) The transaction size\n" " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n" + " \"weight\" : n, (numeric) The transaction's weight (between vsize*4 - 3 and vsize*4)\n" " \"version\" : n, (numeric) The version\n" " \"locktime\" : ttt, (numeric) The lock time\n" " \"vin\" : [ (array of json objects)\n" @@ -551,7 +569,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request) return result; } -UniValue decodescript(const JSONRPCRequest& request) +static UniValue decodescript(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( @@ -595,6 +613,38 @@ UniValue decodescript(const JSONRPCRequest& request) // P2SH cannot be wrapped in a P2SH. If this script is already a P2SH, // don't return the address for a P2SH of the P2SH. r.pushKV("p2sh", EncodeDestination(CScriptID(script))); + // P2SH and witness programs cannot be wrapped in P2WSH, if this script + // is a witness program, don't return addresses for a segwit programs. + if (type.get_str() == "pubkey" || type.get_str() == "pubkeyhash" || type.get_str() == "multisig" || type.get_str() == "nonstandard") { + txnouttype which_type; + std::vector<std::vector<unsigned char>> solutions_data; + Solver(script, which_type, solutions_data); + // Uncompressed pubkeys cannot be used with segwit checksigs. + // If the script contains an uncompressed pubkey, skip encoding of a segwit program. + if ((which_type == TX_PUBKEY) || (which_type == TX_MULTISIG)) { + for (const auto& solution : solutions_data) { + if ((solution.size() != 1) && !CPubKey(solution).IsCompressed()) { + return r; + } + } + } + UniValue sr(UniValue::VOBJ); + CScript segwitScr; + if (which_type == TX_PUBKEY) { + segwitScr = GetScriptForDestination(WitnessV0KeyHash(Hash160(solutions_data[0].begin(), solutions_data[0].end()))); + } else if (which_type == TX_PUBKEYHASH) { + segwitScr = GetScriptForDestination(WitnessV0KeyHash(solutions_data[0])); + } else { + // Scripts that are not fit for P2WPKH are encoded as P2WSH. + // Newer segwit program versions should be considered when then become available. + uint256 scriptHash; + CSHA256().Write(script.data(), script.size()).Finalize(scriptHash.begin()); + segwitScr = GetScriptForDestination(WitnessV0ScriptHash(scriptHash)); + } + ScriptPubKeyToUniv(segwitScr, sr, true); + sr.pushKV("p2sh-segwit", EncodeDestination(CScriptID(segwitScr))); + r.pushKV("segwit", sr); + } } return r; @@ -617,7 +667,7 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std:: vErrorsRet.push_back(entry); } -UniValue combinerawtransaction(const JSONRPCRequest& request) +static UniValue combinerawtransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) @@ -828,7 +878,7 @@ UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival SignatureData sigdata; // Only sign SIGHASH_SINGLE if there's a corresponding output: if (!fHashSingle || (i < mtx.vout.size())) { - ProduceSignature(MutableTransactionSignatureCreator(keystore, &mtx, i, amount, nHashType), prevPubKey, sigdata); + ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata); } sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(mtx, i)); @@ -856,7 +906,7 @@ UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival return result; } -UniValue signrawtransactionwithkey(const JSONRPCRequest& request) +static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) throw std::runtime_error( @@ -1034,7 +1084,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) } } -UniValue sendrawtransaction(const JSONRPCRequest& request) +static UniValue sendrawtransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( @@ -1057,8 +1107,6 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) + HelpExampleRpc("sendrawtransaction", "\"signedhex\"") ); - ObserveSafeMode(); - std::promise<void> promise; RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); @@ -1131,7 +1179,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) return hashTx.GetHex(); } -UniValue testmempoolaccept(const JSONRPCRequest& request) +static UniValue testmempoolaccept(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { throw std::runtime_error( @@ -1166,8 +1214,6 @@ UniValue testmempoolaccept(const JSONRPCRequest& request) ); } - ObserveSafeMode(); - RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VBOOL}); if (request.params[0].get_array().size() != 1) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Array must contain exactly one raw transaction for now"); diff --git a/src/rpc/safemode.cpp b/src/rpc/safemode.cpp deleted file mode 100644 index 9f3a9d30b8..0000000000 --- a/src/rpc/safemode.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include <rpc/safemode.h> - -#include <rpc/protocol.h> -#include <util.h> -#include <warnings.h> - -void ObserveSafeMode() -{ - std::string warning = GetWarnings("rpc"); - if (warning != "" && !gArgs.GetBoolArg("-disablesafemode", DEFAULT_DISABLE_SAFEMODE)) { - throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, std::string("Safe mode: ") + warning); - } -} - diff --git a/src/rpc/safemode.h b/src/rpc/safemode.h deleted file mode 100644 index 8466d6b2f9..0000000000 --- a/src/rpc/safemode.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2017 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_RPC_SAFEMODE_H -#define BITCOIN_RPC_SAFEMODE_H - -static const bool DEFAULT_DISABLE_SAFEMODE = true; - -void ObserveSafeMode(); - -#endif // BITCOIN_RPC_SAFEMODE_H diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index c7c3b1f0d3..10040b1255 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -23,10 +23,10 @@ #include <memory> // for unique_ptr #include <unordered_map> -static bool fRPCRunning = false; -static bool fRPCInWarmup = true; -static std::string rpcWarmupStatus("RPC server started"); static CCriticalSection cs_rpcWarmup; +static bool fRPCRunning = false; +static bool fRPCInWarmup GUARDED_BY(cs_rpcWarmup) = true; +static std::string rpcWarmupStatus GUARDED_BY(cs_rpcWarmup) = "RPC server started"; /* Timer-creating functions */ static RPCTimerInterface* timerInterface = nullptr; /* Map of name to timer. */ @@ -239,7 +239,7 @@ UniValue stop(const JSONRPCRequest& jsonRequest) return "Bitcoin server stopping"; } -UniValue uptime(const JSONRPCRequest& jsonRequest) +static UniValue uptime(const JSONRPCRequest& jsonRequest) { if (jsonRequest.fHelp || jsonRequest.params.size() > 1) throw std::runtime_error( |