diff options
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/blockchain.cpp | 123 | ||||
-rw-r--r-- | src/rpc/client.cpp | 12 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 56 | ||||
-rw-r--r-- | src/rpc/mining.h | 2 | ||||
-rw-r--r-- | src/rpc/misc.cpp | 102 | ||||
-rw-r--r-- | src/rpc/net.cpp | 50 | ||||
-rw-r--r-- | src/rpc/protocol.cpp | 15 | ||||
-rw-r--r-- | src/rpc/protocol.h | 2 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 160 | ||||
-rw-r--r-- | src/rpc/safemode.cpp | 8 | ||||
-rw-r--r-- | src/rpc/server.cpp | 31 | ||||
-rw-r--r-- | src/rpc/server.h | 8 |
12 files changed, 324 insertions, 245 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 874645f653..15d4c27750 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -3,28 +3,28 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/blockchain.h" - -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "coins.h" -#include "consensus/validation.h" -#include "validation.h" -#include "core_io.h" -#include "policy/feerate.h" -#include "policy/policy.h" -#include "primitives/transaction.h" -#include "rpc/server.h" -#include "streams.h" -#include "sync.h" -#include "txdb.h" -#include "txmempool.h" -#include "util.h" -#include "utilstrencodings.h" -#include "hash.h" -#include "warnings.h" +#include <rpc/blockchain.h> + +#include <amount.h> +#include <chain.h> +#include <chainparams.h> +#include <checkpoints.h> +#include <coins.h> +#include <consensus/validation.h> +#include <validation.h> +#include <core_io.h> +#include <policy/feerate.h> +#include <policy/policy.h> +#include <primitives/transaction.h> +#include <rpc/server.h> +#include <streams.h> +#include <sync.h> +#include <txdb.h> +#include <txmempool.h> +#include <util.h> +#include <utilstrencodings.h> +#include <hash.h> +#include <warnings.h> #include <stdint.h> @@ -78,6 +78,7 @@ double GetDifficulty(const CBlockIndex* blockindex) UniValue blockheaderToJSON(const CBlockIndex* blockindex) { + AssertLockHeld(cs_main); UniValue result(UniValue::VOBJ); result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); int confirmations = -1; @@ -106,6 +107,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails) { + AssertLockHeld(cs_main); UniValue result(UniValue::VOBJ); result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); int confirmations = -1; @@ -926,7 +928,7 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request) CCoinsStats stats; FlushStateToDisk(); - if (GetUTXOStats(pcoinsdbview, stats)) { + if (GetUTXOStats(pcoinsdbview.get(), stats)) { ret.push_back(Pair("height", (int64_t)stats.nHeight)); ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); @@ -994,7 +996,7 @@ UniValue gettxout(const JSONRPCRequest& request) Coin coin; if (fMempool) { LOCK(mempool.cs); - CCoinsViewMemPool view(pcoinsTip, mempool); + CCoinsViewMemPool view(pcoinsTip.get(), mempool); if (!view.GetCoin(out, coin) || mempool.isSpent(out)) { return NullUniValue; } @@ -1046,7 +1048,7 @@ UniValue verifychain(const JSONRPCRequest& request) if (!request.params[1].isNull()) nCheckDepth = request.params[1].get_int(); - return CVerifyDB().VerifyDB(Params(), pcoinsTip, nCheckLevel, nCheckDepth); + return CVerifyDB().VerifyDB(Params(), pcoinsTip.get(), nCheckLevel, nCheckDepth); } /** Implementation of IsSuperMajority with better feedback */ @@ -1111,13 +1113,13 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse return rv; } -void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +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. // This is used when softfork codes are merged without specifying the deployment schedule. if (consensusParams.vDeployments[id].nTimeout > 0) - bip9_softforks.push_back(Pair(name, BIP9SoftForkDesc(consensusParams, id))); + bip9_softforks.push_back(Pair(VersionBitsDeploymentInfo[id].name, BIP9SoftForkDesc(consensusParams, id))); } UniValue getblockchaininfo(const JSONRPCRequest& request) @@ -1128,45 +1130,46 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) "Returns an object containing various state info regarding blockchain processing.\n" "\nResult:\n" "{\n" - " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" - " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" - " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" - " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" - " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" - " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n" + " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" + " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" + " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" + " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" + " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" + " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n" " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" - " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" - " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" - " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" - " \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n" - " \"automatic_pruning\": xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n" + " \"initialblockdownload\": xxxx, (bool) (debug information) estimate of whether this node is in Initial Block Download mode.\n" + " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" + " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" + " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" + " \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n" + " \"automatic_pruning\": xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n" " \"prune_target_size\": xxxxxx, (numeric) the target size used by pruning (only present if automatic pruning is enabled)\n" - " \"softforks\": [ (array) status of softforks in progress\n" + " \"softforks\": [ (array) status of softforks in progress\n" " {\n" - " \"id\": \"xxxx\", (string) name of softfork\n" - " \"version\": xx, (numeric) block version\n" - " \"reject\": { (object) progress toward rejecting pre-softfork blocks\n" - " \"status\": xx, (boolean) true if threshold reached\n" + " \"id\": \"xxxx\", (string) name of softfork\n" + " \"version\": xx, (numeric) block version\n" + " \"reject\": { (object) progress toward rejecting pre-softfork blocks\n" + " \"status\": xx, (boolean) true if threshold reached\n" " },\n" " }, ...\n" " ],\n" - " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" - " \"xxxx\" : { (string) name of the softfork\n" - " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" - " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" - " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" - " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" - " \"since\": xx, (numeric) height of the first block to which the status applies\n" - " \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n" - " \"period\": xx, (numeric) the length in blocks of the BIP9 signalling period \n" - " \"threshold\": xx, (numeric) the number of blocks with the version bit set required to activate the feature \n" - " \"elapsed\": xx, (numeric) the number of blocks elapsed since the beginning of the current period \n" - " \"count\": xx, (numeric) the number of blocks with the version bit set in the current period \n" - " \"possible\": xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n" + " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" + " \"xxxx\" : { (string) name of the softfork\n" + " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" + " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" + " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" + " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" + " \"since\": xx, (numeric) height of the first block to which the status applies\n" + " \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n" + " \"period\": xx, (numeric) the length in blocks of the BIP9 signalling period \n" + " \"threshold\": xx, (numeric) the number of blocks with the version bit set required to activate the feature \n" + " \"elapsed\": xx, (numeric) the number of blocks elapsed since the beginning of the current period \n" + " \"count\": xx, (numeric) the number of blocks with the version bit set in the current period \n" + " \"possible\": xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n" " }\n" " }\n" " }\n" - " \"warnings\" : \"...\", (string) any network and blockchain warnings.\n" + " \"warnings\" : \"...\", (string) any network and blockchain warnings.\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblockchaininfo", "") @@ -1183,6 +1186,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast())); obj.push_back(Pair("verificationprogress", GuessVerificationProgress(Params().TxData(), chainActive.Tip()))); + obj.push_back(Pair("initialblockdownload", IsInitialBlockDownload())); obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); obj.push_back(Pair("size_on_disk", CalculateCurrentUsage())); obj.push_back(Pair("pruned", fPruneMode)); @@ -1210,8 +1214,9 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV); - BIP9SoftForkDescPushBack(bip9_softforks, "segwit", consensusParams, Consensus::DEPLOYMENT_SEGWIT); + for (int pos = Consensus::DEPLOYMENT_CSV; pos != Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++pos) { + BIP9SoftForkDescPushBack(bip9_softforks, consensusParams, static_cast<Consensus::DeploymentPos>(pos)); + } obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index f54f24e2a7..e641493e1e 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -3,15 +3,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/client.h" -#include "rpc/protocol.h" -#include "util.h" +#include <rpc/client.h> +#include <rpc/protocol.h> +#include <util.h> #include <set> #include <stdint.h> -#include <univalue.h> - class CRPCConvertParam { public: @@ -93,11 +91,13 @@ static const CRPCConvertParam vRPCConvertParams[] = { "createrawtransaction", 1, "outputs" }, { "createrawtransaction", 2, "locktime" }, { "createrawtransaction", 3, "replaceable" }, + { "decoderawtransaction", 1, "iswitness" }, { "signrawtransaction", 1, "prevtxs" }, { "signrawtransaction", 2, "privkeys" }, { "sendrawtransaction", 1, "allowhighfees" }, { "combinerawtransaction", 0, "txs" }, { "fundrawtransaction", 1, "options" }, + { "fundrawtransaction", 2, "iswitness" }, { "gettxout", 1, "n" }, { "gettxout", 2, "include_mempool" }, { "gettxoutproof", 0, "txids" }, @@ -141,6 +141,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "echojson", 7, "arg7" }, { "echojson", 8, "arg8" }, { "echojson", 9, "arg9" }, + { "rescanblockchain", 0, "start_height"}, + { "rescanblockchain", 1, "stop_height"}, }; class CRPCConvertTable diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index f79439f038..d003be4954 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -3,34 +3,32 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "base58.h" -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "consensus/consensus.h" -#include "consensus/params.h" -#include "consensus/validation.h" -#include "core_io.h" -#include "init.h" -#include "validation.h" -#include "miner.h" -#include "net.h" -#include "policy/fees.h" -#include "pow.h" -#include "rpc/blockchain.h" -#include "rpc/mining.h" -#include "rpc/server.h" -#include "txmempool.h" -#include "util.h" -#include "utilstrencodings.h" -#include "validationinterface.h" -#include "warnings.h" +#include <base58.h> +#include <amount.h> +#include <chain.h> +#include <chainparams.h> +#include <consensus/consensus.h> +#include <consensus/params.h> +#include <consensus/validation.h> +#include <core_io.h> +#include <init.h> +#include <validation.h> +#include <miner.h> +#include <net.h> +#include <policy/fees.h> +#include <pow.h> +#include <rpc/blockchain.h> +#include <rpc/mining.h> +#include <rpc/server.h> +#include <txmempool.h> +#include <util.h> +#include <utilstrencodings.h> +#include <validationinterface.h> +#include <warnings.h> #include <memory> #include <stdint.h> -#include <univalue.h> - unsigned int ParseConfirmTarget(const UniValue& value) { int target = value.get_int(); @@ -455,7 +453,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) { // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions uint256 hashWatchedChain; - boost::system_time checktxtime; + std::chrono::steady_clock::time_point checktxtime; unsigned int nTransactionsUpdatedLastLP; if (lpval.isStr()) @@ -476,17 +474,17 @@ UniValue getblocktemplate(const JSONRPCRequest& request) // Release the wallet and main lock while waiting LEAVE_CRITICAL_SECTION(cs_main); { - checktxtime = boost::get_system_time() + boost::posix_time::minutes(1); + checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1); - boost::unique_lock<boost::mutex> lock(csBestBlock); + WaitableLock lock(csBestBlock); while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning()) { - if (!cvBlockChange.timed_wait(lock, checktxtime)) + if (cvBlockChange.wait_until(lock, checktxtime) == std::cv_status::timeout) { // Timeout: Check transactions for update if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP) break; - checktxtime += boost::posix_time::seconds(10); + checktxtime += std::chrono::seconds(10); } } } diff --git a/src/rpc/mining.h b/src/rpc/mining.h index 868d7002b5..8d46273159 100644 --- a/src/rpc/mining.h +++ b/src/rpc/mining.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_RPC_MINING_H #define BITCOIN_RPC_MINING_H -#include "script/script.h" +#include <script/script.h> #include <univalue.h> diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 521b49e2a7..327af2e237 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -3,27 +3,27 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "base58.h" -#include "chain.h" -#include "clientversion.h" -#include "core_io.h" -#include "crypto/ripemd160.h" -#include "init.h" -#include "validation.h" -#include "httpserver.h" -#include "net.h" -#include "netbase.h" -#include "rpc/blockchain.h" -#include "rpc/server.h" -#include "timedata.h" -#include "util.h" -#include "utilstrencodings.h" +#include <base58.h> +#include <chain.h> +#include <clientversion.h> +#include <core_io.h> +#include <crypto/ripemd160.h> +#include <init.h> +#include <validation.h> +#include <httpserver.h> +#include <net.h> +#include <netbase.h> +#include <rpc/blockchain.h> +#include <rpc/server.h> +#include <timedata.h> +#include <util.h> +#include <utilstrencodings.h> #ifdef ENABLE_WALLET -#include "wallet/rpcwallet.h" -#include "wallet/wallet.h" -#include "wallet/walletdb.h" +#include <wallet/rpcwallet.h> +#include <wallet/wallet.h> +#include <wallet/walletdb.h> #endif -#include "warnings.h" +#include <warnings.h> #include <stdint.h> #ifdef HAVE_MALLOC_INFO @@ -187,17 +187,24 @@ UniValue validateaddress(const JSONRPCRequest& request) ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name)); } if (pwallet) { - const auto& meta = pwallet->mapKeyMetadata; - const CKeyID *keyID = boost::get<CKeyID>(&dest); - auto it = keyID ? meta.find(*keyID) : meta.end(); - if (it == meta.end()) { - it = meta.find(CScriptID(scriptPubKey)); + const CKeyMetadata* meta = nullptr; + if (const CKeyID* key_id = boost::get<CKeyID>(&dest)) { + auto it = pwallet->mapKeyMetadata.find(*key_id); + if (it != pwallet->mapKeyMetadata.end()) { + meta = &it->second; + } + } + if (!meta) { + auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey)); + if (it != pwallet->m_script_metadata.end()) { + meta = &it->second; + } } - if (it != meta.end()) { - ret.push_back(Pair("timestamp", it->second.nCreateTime)); - if (!it->second.hdKeypath.empty()) { - ret.push_back(Pair("hdkeypath", it->second.hdKeypath)); - ret.push_back(Pair("hdmasterkeyid", it->second.hdMasterKeyID.GetHex())); + if (meta) { + ret.push_back(Pair("timestamp", meta->nCreateTime)); + if (!meta->hdKeypath.empty()) { + ret.push_back(Pair("hdkeypath", meta->hdKeypath)); + ret.push_back(Pair("hdmasterkeyid", meta->hdMasterKeyID.GetHex())); } } } @@ -533,6 +540,9 @@ uint32_t getCategoryMask(UniValue cats) { if (!GetLogCategory(&flag, &cat)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat); } + if (flag == BCLog::NONE) { + return 0; + } mask |= flag; } return mask; @@ -542,16 +552,32 @@ UniValue logging(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 2) { throw std::runtime_error( - "logging [include,...] <exclude>\n" + "logging ( <include> <exclude> )\n" "Gets and sets the logging configuration.\n" - "When called without an argument, returns the list of categories that are currently being debug logged.\n" - "When called with arguments, adds or removes categories from debug logging.\n" + "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n" + "When called with arguments, adds or removes categories from debug logging and return the lists above.\n" + "The arguments are evaluated in order \"include\", \"exclude\".\n" + "If an item is both included and excluded, it will thus end up being excluded.\n" "The valid logging categories are: " + ListLogCategories() + "\n" - "libevent logging is configured on startup and cannot be modified by this RPC during runtime." - "Arguments:\n" - "1. \"include\" (array of strings) add debug logging for these categories.\n" - "2. \"exclude\" (array of strings) remove debug logging for these categories.\n" - "\nResult: <categories> (string): a list of the logging categories that are active.\n" + "In addition, the following are available as category names with special meanings:\n" + " - \"all\", \"1\" : represent all logging categories.\n" + " - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n" + "\nArguments:\n" + "1. \"include\" (array of strings, optional) A json array of categories to add debug logging\n" + " [\n" + " \"category\" (string) the valid logging category\n" + " ,...\n" + " ]\n" + "2. \"exclude\" (array of strings, optional) A json array of categories to remove debug logging\n" + " [\n" + " \"category\" (string) the valid logging category\n" + " ,...\n" + " ]\n" + "\nResult:\n" + "{ (json object where keys are the logging categories, and values indicates its status\n" + " \"category\": 0|1, (numeric) if being debug logged or not. 0:inactive, 1:active\n" + " ...\n" + "}\n" "\nExamples:\n" + HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"") @@ -608,6 +634,7 @@ static const CRPCCommand commands[] = { // category name actor (function) argNames // --------------------- ------------------------ ----------------------- ---------- { "control", "getmemoryinfo", &getmemoryinfo, {"mode"} }, + { "control", "logging", &logging, {"include", "exclude"}}, { "util", "validateaddress", &validateaddress, {"address"} }, /* uses wallet if enabled */ { "util", "createmultisig", &createmultisig, {"nrequired","keys"} }, { "util", "verifymessage", &verifymessage, {"address","signature","message"} }, @@ -617,7 +644,6 @@ static const CRPCCommand commands[] = { "hidden", "setmocktime", &setmocktime, {"timestamp"}}, { "hidden", "echo", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, { "hidden", "echojson", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, - { "hidden", "logging", &logging, {"include", "exclude"}}, }; void RegisterMiscRPCCommands(CRPCTable &t) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index a3d3df26a3..9de249855c 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -2,24 +2,24 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/server.h" - -#include "chainparams.h" -#include "clientversion.h" -#include "core_io.h" -#include "validation.h" -#include "net.h" -#include "net_processing.h" -#include "netbase.h" -#include "policy/policy.h" -#include "protocol.h" -#include "sync.h" -#include "timedata.h" -#include "ui_interface.h" -#include "util.h" -#include "utilstrencodings.h" -#include "version.h" -#include "warnings.h" +#include <rpc/server.h> + +#include <chainparams.h> +#include <clientversion.h> +#include <core_io.h> +#include <validation.h> +#include <net.h> +#include <net_processing.h> +#include <netbase.h> +#include <policy/policy.h> +#include <rpc/protocol.h> +#include <sync.h> +#include <timedata.h> +#include <ui_interface.h> +#include <util.h> +#include <utilstrencodings.h> +#include <version.h> +#include <warnings.h> #include <univalue.h> @@ -92,7 +92,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) " \"version\": v, (numeric) The peer version, such as 7001\n" " \"subver\": \"/Satoshi:0.8.5/\", (string) The string version\n" " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n" - " \"addnode\": true|false, (boolean) Whether connection was due to addnode and is using an addnode slot\n" + " \"addnode\": true|false, (boolean) Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n" " \"startingheight\": n, (numeric) The starting height (block) of the peer\n" " \"banscore\": n, (numeric) The ban score\n" " \"synced_headers\": n, (numeric) The last header we have in common with this peer\n" @@ -156,7 +156,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) // their ver message. obj.push_back(Pair("subver", stats.cleanSubVer)); obj.push_back(Pair("inbound", stats.fInbound)); - obj.push_back(Pair("addnode", stats.fAddnode)); + obj.push_back(Pair("addnode", stats.m_manual_connection)); obj.push_back(Pair("startingheight", stats.nStartingHeight)); if (fStateStats) { obj.push_back(Pair("banscore", statestats.nMisbehavior)); @@ -201,6 +201,8 @@ UniValue addnode(const JSONRPCRequest& request) "addnode \"node\" \"add|remove|onetry\"\n" "\nAttempts to add or remove a node from the addnode list.\n" "Or try a connection to a node once.\n" + "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n" + "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n" "\nArguments:\n" "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n" "2. \"command\" (string, required) 'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once\n" @@ -217,7 +219,7 @@ UniValue addnode(const JSONRPCRequest& request) if (strCommand == "onetry") { CAddress addr; - g_connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str()); + g_connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), false, false, true); return NullUniValue; } @@ -569,11 +571,11 @@ UniValue listbanned(const JSONRPCRequest& request) g_connman->GetBanned(banMap); UniValue bannedAddresses(UniValue::VARR); - for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++) + for (const auto& entry : banMap) { - CBanEntry banEntry = (*it).second; + const CBanEntry& banEntry = entry.second; UniValue rec(UniValue::VOBJ); - rec.push_back(Pair("address", (*it).first.ToString())); + rec.push_back(Pair("address", entry.first.ToString())); rec.push_back(Pair("banned_until", banEntry.nBanUntil)); rec.push_back(Pair("ban_created", banEntry.nCreateTime)); rec.push_back(Pair("ban_reason", banEntry.banReasonToString())); diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index 1f4ae75b18..d999a08d74 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -3,16 +3,15 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/protocol.h" +#include <rpc/protocol.h> -#include "random.h" -#include "tinyformat.h" -#include "util.h" -#include "utilstrencodings.h" -#include "utiltime.h" -#include "version.h" +#include <random.h> +#include <tinyformat.h> +#include <util.h> +#include <utilstrencodings.h> +#include <utiltime.h> +#include <version.h> -#include <stdint.h> #include <fstream> /** diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index cb668f3db9..4b9bd41994 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_RPCPROTOCOL_H #define BITCOIN_RPCPROTOCOL_H -#include "fs.h" +#include <fs.h> #include <list> #include <map> diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d860dbc244..1049131d5e 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -3,33 +3,35 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "base58.h" -#include "chain.h" -#include "coins.h" -#include "consensus/validation.h" -#include "core_io.h" -#include "init.h" -#include "keystore.h" -#include "validation.h" -#include "merkleblock.h" -#include "net.h" -#include "policy/policy.h" -#include "policy/rbf.h" -#include "primitives/transaction.h" -#include "rpc/safemode.h" -#include "rpc/server.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "script/standard.h" -#include "txmempool.h" -#include "uint256.h" -#include "utilstrencodings.h" +#include <base58.h> +#include <chain.h> +#include <coins.h> +#include <consensus/validation.h> +#include <core_io.h> +#include <init.h> +#include <keystore.h> +#include <validation.h> +#include <validationinterface.h> +#include <merkleblock.h> +#include <net.h> +#include <policy/policy.h> +#include <policy/rbf.h> +#include <primitives/transaction.h> +#include <rpc/safemode.h> +#include <rpc/server.h> +#include <script/script.h> +#include <script/script_error.h> +#include <script/sign.h> +#include <script/standard.h> +#include <txmempool.h> +#include <uint256.h> +#include <utilstrencodings.h> #ifdef ENABLE_WALLET -#include "wallet/rpcwallet.h" -#include "wallet/wallet.h" +#include <wallet/rpcwallet.h> +#include <wallet/wallet.h> #endif +#include <future> #include <stdint.h> #include <univalue.h> @@ -62,12 +64,15 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) UniValue getrawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) throw std::runtime_error( - "getrawtransaction \"txid\" ( verbose )\n" + "getrawtransaction \"txid\" ( verbose \"blockhash\" )\n" "\nNOTE: By default this function only works for mempool transactions. If the -txindex option is\n" - "enabled, it also works for blockchain transactions.\n" + "enabled, it also works for blockchain transactions. If the block which contains the transaction\n" + "is known, its hash can be provided even for nodes without -txindex. Note that if a blockhash is\n" + "provided, only that block will be searched and if the transaction is in the mempool or other\n" + "blocks, or if this node does not have the given block available, the transaction will not be found.\n" "DEPRECATED: for now, it also works for transactions with unspent outputs.\n" "\nReturn the raw transaction data.\n" @@ -76,13 +81,15 @@ UniValue getrawtransaction(const JSONRPCRequest& request) "\nArguments:\n" "1. \"txid\" (string, required) The transaction id\n" - "2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object\n" + "2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object\n" + "3. \"blockhash\" (string, optional) The block in which to look for the transaction\n" "\nResult (if verbose is not set or set to false):\n" "\"data\" (string) The serialized, hex-encoded data for 'txid'\n" "\nResult (if verbose is set to true):\n" "{\n" + " \"in_active_chain\": b, (bool) Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)\n" " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n" " \"txid\" : \"id\", (string) The transaction id (same as provided)\n" " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" @@ -130,42 +137,56 @@ UniValue getrawtransaction(const JSONRPCRequest& request) + HelpExampleCli("getrawtransaction", "\"mytxid\"") + HelpExampleCli("getrawtransaction", "\"mytxid\" true") + HelpExampleRpc("getrawtransaction", "\"mytxid\", true") + + HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"") + + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"") ); LOCK(cs_main); + bool in_active_chain = true; uint256 hash = ParseHashV(request.params[0], "parameter 1"); + CBlockIndex* blockindex = nullptr; // Accept either a bool (true) or a num (>=1) to indicate verbose output. bool fVerbose = false; if (!request.params[1].isNull()) { - if (request.params[1].isNum()) { - if (request.params[1].get_int() != 0) { - fVerbose = true; - } - } - else if(request.params[1].isBool()) { - if(request.params[1].isTrue()) { - fVerbose = true; - } - } - else { - throw JSONRPCError(RPC_TYPE_ERROR, "Invalid type provided. Verbose parameter must be a boolean."); + fVerbose = request.params[1].isNum() ? (request.params[1].get_int() != 0) : request.params[1].get_bool(); + } + + if (!request.params[2].isNull()) { + uint256 blockhash = ParseHashV(request.params[2], "parameter 3"); + BlockMap::iterator it = mapBlockIndex.find(blockhash); + if (it == mapBlockIndex.end()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found"); } + blockindex = it->second; + in_active_chain = chainActive.Contains(blockindex); } CTransactionRef tx; - uint256 hashBlock; - if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string(fTxIndex ? "No such mempool or blockchain transaction" - : "No such mempool transaction. Use -txindex to enable blockchain transaction queries") + - ". Use gettransaction for wallet transactions."); + uint256 hash_block; + if (!GetTransaction(hash, tx, Params().GetConsensus(), hash_block, true, blockindex)) { + std::string errmsg; + if (blockindex) { + if (!(blockindex->nStatus & BLOCK_HAVE_DATA)) { + throw JSONRPCError(RPC_MISC_ERROR, "Block not available"); + } + errmsg = "No such transaction found in the provided block"; + } else { + errmsg = fTxIndex + ? "No such mempool or blockchain transaction" + : "No such mempool transaction. Use -txindex to enable blockchain transaction queries"; + } + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errmsg + ". Use gettransaction for wallet transactions."); + } - if (!fVerbose) + if (!fVerbose) { return EncodeHexTx(*tx, RPCSerializationFlags()); + } UniValue result(UniValue::VOBJ); - TxToJSON(*tx, hashBlock, result); + if (blockindex) result.push_back(Pair("in_active_chain", in_active_chain)); + TxToJSON(*tx, hash_block, result); return result; } @@ -328,7 +349,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"data\\\":\\\"00010203\\\"}\"") ); - RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ, UniValue::VNUM}, true); + RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ, UniValue::VNUM, UniValue::VBOOL}, true); if (request.params[0].isNull() || request.params[1].isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null"); @@ -420,13 +441,15 @@ UniValue createrawtransaction(const JSONRPCRequest& request) UniValue decoderawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( - "decoderawtransaction \"hexstring\"\n" + "decoderawtransaction \"hexstring\" ( iswitness )\n" "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n" "\nArguments:\n" "1. \"hexstring\" (string, required) The transaction hex string\n" + "2. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction\n" + " If iswitness is not present, heuristic tests will be used in decoding\n" "\nResult:\n" "{\n" @@ -474,12 +497,16 @@ UniValue decoderawtransaction(const JSONRPCRequest& request) ); LOCK(cs_main); - RPCTypeCheck(request.params, {UniValue::VSTR}); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); CMutableTransaction mtx; - if (!DecodeHexTx(mtx, request.params[0].get_str(), true)) + bool try_witness = request.params[1].isNull() ? true : request.params[1].get_bool(); + bool try_no_witness = request.params[1].isNull() ? true : !request.params[1].get_bool(); + + if (!DecodeHexTx(mtx, request.params[0].get_str(), try_no_witness, try_witness)) { throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + } UniValue result(UniValue::VOBJ); TxToUniv(CTransaction(std::move(mtx)), uint256(), result, false); @@ -917,7 +944,9 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) ); ObserveSafeMode(); - LOCK(cs_main); + + std::promise<void> promise; + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); // parse hex string from parameter @@ -931,6 +960,8 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) if (!request.params[1].isNull() && request.params[1].get_bool()) nMaxRawTxFee = 0; + { // cs_main scope + LOCK(cs_main); CCoinsViewCache &view = *pcoinsTip; bool fHaveChain = false; for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) { @@ -952,10 +983,28 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) } throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason()); } + } else { + // If wallet is enabled, ensure that the wallet has been made aware + // of the new transaction prior to returning. This prevents a race + // where a user might call sendrawtransaction with a transaction + // to/from their wallet, immediately call some wallet RPC, and get + // a stale result because callbacks have not yet been processed. + CallFunctionInValidationInterfaceQueue([&promise] { + promise.set_value(); + }); } } else if (fHaveChain) { throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain"); + } else { + // Make sure we don't block forever if re-sending + // a transaction already in mempool. + promise.set_value(); } + + } // cs_main + + promise.get_future().wait(); + if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -964,15 +1013,16 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) { pnode->PushInventory(inv); }); + return hashTx.GetHex(); } static const CRPCCommand commands[] = { // category name actor (function) argNames // --------------------- ------------------------ ----------------------- ---------- - { "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose"} }, + { "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose","blockhash"} }, { "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime","replaceable"} }, - { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring"} }, + { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring","iswitness"} }, { "rawtransactions", "decodescript", &decodescript, {"hexstring"} }, { "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","allowhighfees"} }, { "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} }, diff --git a/src/rpc/safemode.cpp b/src/rpc/safemode.cpp index 24770ad47f..9f3a9d30b8 100644 --- a/src/rpc/safemode.cpp +++ b/src/rpc/safemode.cpp @@ -1,8 +1,8 @@ -#include "safemode.h" +#include <rpc/safemode.h> -#include "rpc/protocol.h" -#include "util.h" -#include "warnings.h" +#include <rpc/protocol.h> +#include <util.h> +#include <warnings.h> void ObserveSafeMode() { diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index a73b697e01..2e7e0ba474 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -3,18 +3,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpc/server.h" +#include <rpc/server.h> -#include "base58.h" -#include "fs.h" -#include "init.h" -#include "random.h" -#include "sync.h" -#include "ui_interface.h" -#include "util.h" -#include "utilstrencodings.h" - -#include <univalue.h> +#include <base58.h> +#include <fs.h> +#include <init.h> +#include <random.h> +#include <sync.h> +#include <ui_interface.h> +#include <util.h> +#include <utilstrencodings.h> #include <boost/bind.hpp> #include <boost/signals2/signal.hpp> @@ -160,8 +158,8 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& std::set<rpcfn_type> setDone; std::vector<std::pair<std::string, const CRPCCommand*> > vCommands; - for (std::map<std::string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi) - vCommands.push_back(make_pair(mi->second->category + mi->first, mi->second)); + for (const auto& entry : mapCommands) + vCommands.push_back(make_pair(entry.second->category + entry.first, entry.second)); sort(vCommands.begin(), vCommands.end()); JSONRPCRequest jreq(helpreq); @@ -389,11 +387,10 @@ bool IsDeprecatedRPCEnabled(const std::string& method) return find(enabled_methods.begin(), enabled_methods.end(), method) != enabled_methods.end(); } -static UniValue JSONRPCExecOne(const UniValue& req) +static UniValue JSONRPCExecOne(JSONRPCRequest jreq, const UniValue& req) { UniValue rpc_result(UniValue::VOBJ); - JSONRPCRequest jreq; try { jreq.parse(req); @@ -413,11 +410,11 @@ static UniValue JSONRPCExecOne(const UniValue& req) return rpc_result; } -std::string JSONRPCExecBatch(const UniValue& vReq) +std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq) { UniValue ret(UniValue::VARR); for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++) - ret.push_back(JSONRPCExecOne(vReq[reqIdx])); + ret.push_back(JSONRPCExecOne(jreq, vReq[reqIdx])); return ret.write() + "\n"; } diff --git a/src/rpc/server.h b/src/rpc/server.h index 31d6304271..cd201bf316 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -6,9 +6,9 @@ #ifndef BITCOIN_RPCSERVER_H #define BITCOIN_RPCSERVER_H -#include "amount.h" -#include "rpc/protocol.h" -#include "uint256.h" +#include <amount.h> +#include <rpc/protocol.h> +#include <uint256.h> #include <list> #include <map> @@ -191,7 +191,7 @@ extern std::string HelpExampleRpc(const std::string& methodname, const std::stri bool StartRPC(); void InterruptRPC(); void StopRPC(); -std::string JSONRPCExecBatch(const UniValue& vReq); +std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq); // Retrieves any serialization flags requested in command line argument int RPCSerializationFlags(); |