From fd826130a0a4e67fdc26f8064f4ecb4ff79b3333 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 1 Dec 2021 17:46:21 +1000 Subject: rpc: move softfork info from getblockchaininfo to getdeploymentinfo --- src/rpc/blockchain.cpp | 109 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 80 insertions(+), 29 deletions(-) (limited to 'src/rpc') diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 827b3a7da3..303fd2d70d 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1400,7 +1400,7 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& UniValue rv(UniValue::VOBJ); rv.pushKV("type", "buried"); - // getblockchaininfo reports the softfork as active from when the chain height is + // getdeploymentinfo reports the softfork as active from when the chain height is // one below the activation height rv.pushKV("active", DeploymentActiveAfter(active_chain_tip, params, dep)); rv.pushKV("height", params.DeploymentHeight(dep)); @@ -1455,8 +1455,16 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks.pushKV(DeploymentName(id), rv); } +namespace { +/* TODO: when -dprecatedrpc=softforks is removed, drop these */ +UniValue DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consensusParams); +extern const std::vector RPCHelpForDeployment; +} + +// used by rest.cpp:rest_chaininfo, so cannot be static RPCHelpMan getblockchaininfo() { + /* TODO: from v24, remove -deprecatedrpc=softforks */ return RPCHelpMan{"getblockchaininfo", "Returns an object containing various state info regarding blockchain processing.\n", {}, @@ -1478,31 +1486,11 @@ RPCHelpMan getblockchaininfo() {RPCResult::Type::NUM, "pruneheight", /*optional=*/true, "lowest-height complete block stored (only present if pruning is enabled)"}, {RPCResult::Type::BOOL, "automatic_pruning", /*optional=*/true, "whether automatic pruning is enabled (only present if pruning is enabled)"}, {RPCResult::Type::NUM, "prune_target_size", /*optional=*/true, "the target size used by pruning (only present if automatic pruning is enabled)"}, - {RPCResult::Type::OBJ_DYN, "softforks", "status of softforks", + {RPCResult::Type::OBJ_DYN, "softforks", "(DEPRECATED, returned only if config option -deprecatedrpc=softforks is passed) status of softforks", { {RPCResult::Type::OBJ, "xxxx", "name of the softfork", - { - {RPCResult::Type::STR, "type", "one of \"buried\", \"bip9\""}, - {RPCResult::Type::OBJ, "bip9", /*optional=*/true, "status of bip9 softforks (only for \"bip9\" type)", - { - {RPCResult::Type::STR, "status", "one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\""}, - {RPCResult::Type::NUM, "bit", /*optional=*/true, "the bit (0-28) in the block version field used to signal this softfork (only for \"started\" and \"locked_in\" status)"}, - {RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"}, - {RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"}, - {RPCResult::Type::NUM, "since", "height of the first block to which the status applies"}, - {RPCResult::Type::NUM, "min_activation_height", "minimum height of blocks for which the rules may be enforced"}, - {RPCResult::Type::OBJ, "statistics", /*optional=*/true, "numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)", - { - {RPCResult::Type::NUM, "period", "the length in blocks of the signalling period"}, - {RPCResult::Type::NUM, "threshold", /*optional=*/true, "the number of blocks with the version bit set required to activate the feature (only for \"started\" status)"}, - {RPCResult::Type::NUM, "elapsed", "the number of blocks elapsed since the beginning of the current period"}, - {RPCResult::Type::NUM, "count", "the number of blocks with the version bit set in the current period"}, - {RPCResult::Type::BOOL, "possible", /*optional=*/true, "returns false if there are not enough blocks left in this period to pass activation threshold (only for \"started\" status)"}, - }}, - }}, - {RPCResult::Type::NUM, "height", /*optional=*/true, "height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"}, - {RPCResult::Type::BOOL, "active", "true if the rules are enforced for the mempool and the next block"}, - }}, + RPCHelpForDeployment + }, }}, {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"}, }}, @@ -1549,7 +1537,43 @@ RPCHelpMan getblockchaininfo() } } - const Consensus::Params& consensusParams = Params().GetConsensus(); + if (IsDeprecatedRPCEnabled("softforks")) { + const Consensus::Params& consensusParams = Params().GetConsensus(); + obj.pushKV("softforks", DeploymentInfo(tip, consensusParams)); + } + + obj.pushKV("warnings", GetWarnings(false).original); + return obj; +}, + }; +} + +namespace { +const std::vector RPCHelpForDeployment{ + {RPCResult::Type::STR, "type", "one of \"buried\", \"bip9\""}, + {RPCResult::Type::OBJ, "bip9", /*optional=*/true, "status of bip9 softforks (only for \"bip9\" type)", + { + {RPCResult::Type::STR, "status", "one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\""}, + {RPCResult::Type::NUM, "bit", /*optional=*/true, "the bit (0-28) in the block version field used to signal this softfork (only for \"started\" and \"locked_in\" status)"}, + {RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"}, + {RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"}, + {RPCResult::Type::NUM, "since", "height of the first block to which the status applies"}, + {RPCResult::Type::NUM, "min_activation_height", "minimum height of blocks for which the rules may be enforced"}, + {RPCResult::Type::OBJ, "statistics", /*optional=*/true, "numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)", + { + {RPCResult::Type::NUM, "period", "the length in blocks of the signalling period"}, + {RPCResult::Type::NUM, "threshold", /*optional=*/true, "the number of blocks with the version bit set required to activate the feature (only for \"started\" status)"}, + {RPCResult::Type::NUM, "elapsed", "the number of blocks elapsed since the beginning of the current period"}, + {RPCResult::Type::NUM, "count", "the number of blocks with the version bit set in the current period"}, + {RPCResult::Type::BOOL, "possible", /*optional=*/true, "returns false if there are not enough blocks left in this period to pass activation threshold (only for \"started\" status)"}, + }}, + }}, + {RPCResult::Type::NUM, "height", /*optional=*/true, "height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"}, + {RPCResult::Type::BOOL, "active", "true if the rules are enforced for the mempool and the next block"}, +}; + +UniValue DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consensusParams) +{ UniValue softforks(UniValue::VOBJ); SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB); SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_DERSIG); @@ -1558,11 +1582,37 @@ RPCHelpMan getblockchaininfo() SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_SEGWIT); SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_TESTDUMMY); SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_TAPROOT); - obj.pushKV("softforks", softforks); + return softforks; +} +} // anon namespace - obj.pushKV("warnings", GetWarnings(false).original); - return obj; -}, +static RPCHelpMan getdeploymentinfo() +{ + return RPCHelpMan{"getdeploymentinfo", + "Returns an object containing various state info regarding soft-forks.", + {}, + RPCResult{ + RPCResult::Type::OBJ, "", "", { + {RPCResult::Type::OBJ, "deployments", "", { + {RPCResult::Type::OBJ, "xxxx", "name of the deployment", RPCHelpForDeployment} + }}, + } + }, + RPCExamples{ HelpExampleCli("getdeploymentinfo", "") + HelpExampleRpc("getdeploymentinfo", "") }, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue + { + ChainstateManager& chainman = EnsureAnyChainman(request.context); + LOCK(cs_main); + CChainState& active_chainstate = chainman.ActiveChainstate(); + + const CBlockIndex* tip = active_chainstate.m_chain.Tip(); + CHECK_NONFATAL(tip); + const Consensus::Params& consensusParams = Params().GetConsensus(); + + UniValue deploymentinfo(UniValue::VOBJ); + deploymentinfo.pushKV("deployments", DeploymentInfo(tip, consensusParams)); + return deploymentinfo; + }, }; } @@ -2716,6 +2766,7 @@ static const CRPCCommand commands[] = { "blockchain", &getblockheader, }, { "blockchain", &getchaintips, }, { "blockchain", &getdifficulty, }, + { "blockchain", &getdeploymentinfo, }, { "blockchain", &getmempoolancestors, }, { "blockchain", &getmempooldescendants, }, { "blockchain", &getmempoolentry, }, -- cgit v1.2.3 From 7f15c1841b98de6931a7ac68e16635a05d3e96cf Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 12 Nov 2021 07:56:12 +1000 Subject: rpc: getdeploymentinfo: allow specifying a blockhash other than tip --- src/rpc/blockchain.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/rpc') diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 303fd2d70d..42993c47f5 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1590,7 +1590,9 @@ static RPCHelpMan getdeploymentinfo() { return RPCHelpMan{"getdeploymentinfo", "Returns an object containing various state info regarding soft-forks.", - {}, + { + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Default{"chain tip"}, "The block hash at which to query fork state"}, + }, RPCResult{ RPCResult::Type::OBJ, "", "", { {RPCResult::Type::OBJ, "deployments", "", { @@ -1605,8 +1607,18 @@ static RPCHelpMan getdeploymentinfo() LOCK(cs_main); CChainState& active_chainstate = chainman.ActiveChainstate(); - const CBlockIndex* tip = active_chainstate.m_chain.Tip(); - CHECK_NONFATAL(tip); + const CBlockIndex* tip; + if (request.params[0].isNull()) { + tip = active_chainstate.m_chain.Tip(); + CHECK_NONFATAL(tip); + } else { + uint256 hash(ParseHashV(request.params[0], "blockhash")); + tip = chainman.m_blockman.LookupBlockIndex(hash); + if (!tip) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + } + } + const Consensus::Params& consensusParams = Params().GetConsensus(); UniValue deploymentinfo(UniValue::VOBJ); -- cgit v1.2.3 From a7469bcd35692d56f57e91b3f21d30855bdf6531 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 14 Nov 2021 07:55:34 +1000 Subject: rpc: getdeploymentinfo: change stats to always refer to current period On a period boundary, getdeploymentinfo (and previously getblockchaininfo) would report the status and statistics for the next block rather than the current block. Change this to always report the status/statistics of the current block, but add status-next to report the status for the next block. --- src/rpc/blockchain.cpp | 58 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 21 deletions(-) (limited to 'src/rpc') diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 42993c47f5..dc5c91fe8a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1412,45 +1412,60 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& // For BIP9 deployments. if (!DeploymentEnabled(consensusParams, id)) return; + if (active_chain_tip == nullptr) return; + + auto get_state_name = [](const ThresholdState state) -> std::string { + switch (state) { + case ThresholdState::DEFINED: return "defined"; + case ThresholdState::STARTED: return "started"; + case ThresholdState::LOCKED_IN: return "locked_in"; + case ThresholdState::ACTIVE: return "active"; + case ThresholdState::FAILED: return "failed"; + } + return "invalid"; + }; UniValue bip9(UniValue::VOBJ); - const ThresholdState thresholdState = g_versionbitscache.State(active_chain_tip, consensusParams, id); - switch (thresholdState) { - case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break; - case ThresholdState::STARTED: bip9.pushKV("status", "started"); break; - case ThresholdState::LOCKED_IN: bip9.pushKV("status", "locked_in"); break; - case ThresholdState::ACTIVE: bip9.pushKV("status", "active"); break; - case ThresholdState::FAILED: bip9.pushKV("status", "failed"); break; - } - const bool has_signal = (ThresholdState::STARTED == thresholdState || ThresholdState::LOCKED_IN == thresholdState); + + const ThresholdState next_state = g_versionbitscache.State(active_chain_tip, consensusParams, id); + const ThresholdState current_state = g_versionbitscache.State(active_chain_tip->pprev, consensusParams, id); + + const bool has_signal = (ThresholdState::STARTED == current_state || ThresholdState::LOCKED_IN == current_state); + + // BIP9 parameters if (has_signal) { bip9.pushKV("bit", consensusParams.vDeployments[id].bit); } bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime); bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout); - int64_t since_height = g_versionbitscache.StateSinceHeight(active_chain_tip, consensusParams, id); - bip9.pushKV("since", since_height); + bip9.pushKV("min_activation_height", consensusParams.vDeployments[id].min_activation_height); + + // BIP9 status + bip9.pushKV("status", get_state_name(current_state)); + bip9.pushKV("since", g_versionbitscache.StateSinceHeight(active_chain_tip->pprev, consensusParams, id)); + bip9.pushKV("status-next", get_state_name(next_state)); + + // BIP9 signalling status, if applicable if (has_signal) { UniValue statsUV(UniValue::VOBJ); BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, consensusParams, id); statsUV.pushKV("period", statsStruct.period); statsUV.pushKV("elapsed", statsStruct.elapsed); statsUV.pushKV("count", statsStruct.count); - if (ThresholdState::LOCKED_IN != thresholdState) { + if (ThresholdState::LOCKED_IN != current_state) { statsUV.pushKV("threshold", statsStruct.threshold); statsUV.pushKV("possible", statsStruct.possible); } bip9.pushKV("statistics", statsUV); } - bip9.pushKV("min_activation_height", consensusParams.vDeployments[id].min_activation_height); UniValue rv(UniValue::VOBJ); rv.pushKV("type", "bip9"); - rv.pushKV("bip9", bip9); - if (ThresholdState::ACTIVE == thresholdState) { - rv.pushKV("height", since_height); + if (ThresholdState::ACTIVE == next_state) { + rv.pushKV("height", g_versionbitscache.StateSinceHeight(active_chain_tip, consensusParams, id)); } - rv.pushKV("active", ThresholdState::ACTIVE == thresholdState); + rv.pushKV("active", ThresholdState::ACTIVE == next_state); + rv.pushKV("bip9", bip9); softforks.pushKV(DeploymentName(id), rv); } @@ -1551,14 +1566,17 @@ RPCHelpMan getblockchaininfo() namespace { const std::vector RPCHelpForDeployment{ {RPCResult::Type::STR, "type", "one of \"buried\", \"bip9\""}, + {RPCResult::Type::NUM, "height", /*optional=*/true, "height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"}, + {RPCResult::Type::BOOL, "active", "true if the rules are enforced for the mempool and the next block"}, {RPCResult::Type::OBJ, "bip9", /*optional=*/true, "status of bip9 softforks (only for \"bip9\" type)", { - {RPCResult::Type::STR, "status", "one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\""}, {RPCResult::Type::NUM, "bit", /*optional=*/true, "the bit (0-28) in the block version field used to signal this softfork (only for \"started\" and \"locked_in\" status)"}, {RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"}, {RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"}, - {RPCResult::Type::NUM, "since", "height of the first block to which the status applies"}, {RPCResult::Type::NUM, "min_activation_height", "minimum height of blocks for which the rules may be enforced"}, + {RPCResult::Type::STR, "status", "bip9 status of specified block (one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\")"}, + {RPCResult::Type::NUM, "since", "height of the first block to which the status applies"}, + {RPCResult::Type::STR, "status-next", "bip9 status of next block"}, {RPCResult::Type::OBJ, "statistics", /*optional=*/true, "numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)", { {RPCResult::Type::NUM, "period", "the length in blocks of the signalling period"}, @@ -1568,8 +1586,6 @@ const std::vector RPCHelpForDeployment{ {RPCResult::Type::BOOL, "possible", /*optional=*/true, "returns false if there are not enough blocks left in this period to pass activation threshold (only for \"started\" status)"}, }}, }}, - {RPCResult::Type::NUM, "height", /*optional=*/true, "height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"}, - {RPCResult::Type::BOOL, "active", "true if the rules are enforced for the mempool and the next block"}, }; UniValue DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consensusParams) -- cgit v1.2.3 From 376c0c6dae2bebbb3e1352377e71fb1996d09f64 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 14 Nov 2021 08:44:40 +1000 Subject: rpc: getdeploymentinfo: include block hash/height --- src/rpc/blockchain.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/rpc') diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index dc5c91fe8a..32cb65679e 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1611,6 +1611,8 @@ static RPCHelpMan getdeploymentinfo() }, RPCResult{ RPCResult::Type::OBJ, "", "", { + {RPCResult::Type::STR, "hash", "requested block hash (or tip)"}, + {RPCResult::Type::NUM, "height", "requested block height (or tip)"}, {RPCResult::Type::OBJ, "deployments", "", { {RPCResult::Type::OBJ, "xxxx", "name of the deployment", RPCHelpForDeployment} }}, @@ -1638,6 +1640,8 @@ static RPCHelpMan getdeploymentinfo() const Consensus::Params& consensusParams = Params().GetConsensus(); UniValue deploymentinfo(UniValue::VOBJ); + deploymentinfo.pushKV("hash", tip->GetBlockHash().ToString()); + deploymentinfo.pushKV("height", tip->nHeight); deploymentinfo.pushKV("deployments", DeploymentInfo(tip, consensusParams)); return deploymentinfo; }, -- cgit v1.2.3 From 240cad09baefcf363cce36a4b2795122adfce27f Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 12 Nov 2021 07:14:21 +1000 Subject: rpc: getdeploymentinfo: include signalling info --- src/rpc/blockchain.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/rpc') diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 32cb65679e..c1a73944de 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1448,7 +1448,8 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& // BIP9 signalling status, if applicable if (has_signal) { UniValue statsUV(UniValue::VOBJ); - BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, consensusParams, id); + std::vector signals; + BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, consensusParams, id, &signals); statsUV.pushKV("period", statsStruct.period); statsUV.pushKV("elapsed", statsStruct.elapsed); statsUV.pushKV("count", statsStruct.count); @@ -1457,6 +1458,13 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& statsUV.pushKV("possible", statsStruct.possible); } bip9.pushKV("statistics", statsUV); + + std::string sig; + sig.reserve(signals.size()); + for (const bool s : signals) { + sig.push_back(s ? '#' : '-'); + } + bip9.pushKV("signalling", sig); } UniValue rv(UniValue::VOBJ); @@ -1585,6 +1593,7 @@ const std::vector RPCHelpForDeployment{ {RPCResult::Type::NUM, "count", "the number of blocks with the version bit set in the current period"}, {RPCResult::Type::BOOL, "possible", /*optional=*/true, "returns false if there are not enough blocks left in this period to pass activation threshold (only for \"started\" status)"}, }}, + {RPCResult::Type::STR, "signalling", "indicates blocks that signalled with a # and blocks that did not with a -"}, }}, }; -- cgit v1.2.3