mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-12 18:44:59 +01:00
versionbits: Move getdeploymentinfo logic to versionbits
Rather than having the RPC code have knowledge about how BIP9 is implemented, create a reporting function in the versionbits code, and limit the RPC code to coverting the result of that into Univalue/JSON.
This commit is contained in:
parent
3bd32c2055
commit
b1e967c3ec
3 changed files with 85 additions and 46 deletions
|
@ -1215,58 +1215,41 @@ static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softfo
|
|||
static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const ChainstateManager& chainman, Consensus::DeploymentPos id)
|
||||
{
|
||||
// For BIP9 deployments.
|
||||
|
||||
if (!DeploymentEnabled(chainman, id)) return;
|
||||
if (blockindex == 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 next_state = chainman.m_versionbitscache.State(blockindex, chainman.GetConsensus(), id);
|
||||
const ThresholdState current_state = chainman.m_versionbitscache.State(blockindex->pprev, chainman.GetConsensus(), id);
|
||||
|
||||
const bool has_signal = (ThresholdState::STARTED == current_state || ThresholdState::LOCKED_IN == current_state);
|
||||
BIP9Info info{chainman.m_versionbitscache.Info(*blockindex, chainman.GetConsensus(), id)};
|
||||
const auto& depparams{chainman.GetConsensus().vDeployments[id]};
|
||||
|
||||
// BIP9 parameters
|
||||
if (has_signal) {
|
||||
bip9.pushKV("bit", chainman.GetConsensus().vDeployments[id].bit);
|
||||
if (info.stats.has_value()) {
|
||||
bip9.pushKV("bit", depparams.bit);
|
||||
}
|
||||
bip9.pushKV("start_time", chainman.GetConsensus().vDeployments[id].nStartTime);
|
||||
bip9.pushKV("timeout", chainman.GetConsensus().vDeployments[id].nTimeout);
|
||||
bip9.pushKV("min_activation_height", chainman.GetConsensus().vDeployments[id].min_activation_height);
|
||||
bip9.pushKV("start_time", depparams.nStartTime);
|
||||
bip9.pushKV("timeout", depparams.nTimeout);
|
||||
bip9.pushKV("min_activation_height", depparams.min_activation_height);
|
||||
|
||||
// BIP9 status
|
||||
bip9.pushKV("status", get_state_name(current_state));
|
||||
bip9.pushKV("since", chainman.m_versionbitscache.StateSinceHeight(blockindex->pprev, chainman.GetConsensus(), id));
|
||||
bip9.pushKV("status_next", get_state_name(next_state));
|
||||
bip9.pushKV("status", info.current_state);
|
||||
bip9.pushKV("since", info.since);
|
||||
bip9.pushKV("status_next", info.next_state);
|
||||
|
||||
// BIP9 signalling status, if applicable
|
||||
if (has_signal) {
|
||||
if (info.stats.has_value()) {
|
||||
UniValue statsUV(UniValue::VOBJ);
|
||||
std::vector<bool> signals;
|
||||
BIP9Stats statsStruct = chainman.m_versionbitscache.Statistics(blockindex, chainman.GetConsensus(), id, &signals);
|
||||
statsUV.pushKV("period", statsStruct.period);
|
||||
statsUV.pushKV("elapsed", statsStruct.elapsed);
|
||||
statsUV.pushKV("count", statsStruct.count);
|
||||
if (ThresholdState::LOCKED_IN != current_state) {
|
||||
statsUV.pushKV("threshold", statsStruct.threshold);
|
||||
statsUV.pushKV("possible", statsStruct.possible);
|
||||
statsUV.pushKV("period", info.stats->period);
|
||||
statsUV.pushKV("elapsed", info.stats->elapsed);
|
||||
statsUV.pushKV("count", info.stats->count);
|
||||
if (info.stats->threshold > 0 || info.stats->possible) {
|
||||
statsUV.pushKV("threshold", info.stats->threshold);
|
||||
statsUV.pushKV("possible", info.stats->possible);
|
||||
}
|
||||
bip9.pushKV("statistics", std::move(statsUV));
|
||||
|
||||
std::string sig;
|
||||
sig.reserve(signals.size());
|
||||
for (const bool s : signals) {
|
||||
sig.reserve(info.signalling_blocks.size());
|
||||
for (const bool s : info.signalling_blocks) {
|
||||
sig.push_back(s ? '#' : '-');
|
||||
}
|
||||
bip9.pushKV("signalling", sig);
|
||||
|
@ -1274,12 +1257,13 @@ static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softfo
|
|||
|
||||
UniValue rv(UniValue::VOBJ);
|
||||
rv.pushKV("type", "bip9");
|
||||
if (ThresholdState::ACTIVE == next_state) {
|
||||
rv.pushKV("height", chainman.m_versionbitscache.StateSinceHeight(blockindex, chainman.GetConsensus(), id));
|
||||
bool is_active = false;
|
||||
if (info.active_since.has_value()) {
|
||||
rv.pushKV("height", *info.active_since);
|
||||
is_active = (*info.active_since <= blockindex->nHeight + 1);
|
||||
}
|
||||
rv.pushKV("active", ThresholdState::ACTIVE == next_state);
|
||||
rv.pushKV("bip9", std::move(bip9));
|
||||
|
||||
rv.pushKV("active", is_active);
|
||||
rv.pushKV("bip9", bip9);
|
||||
softforks.pushKV(DeploymentName(id), std::move(rv));
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,18 @@
|
|||
|
||||
using enum ThresholdState;
|
||||
|
||||
static std::string StateName(ThresholdState state)
|
||||
{
|
||||
switch (state) {
|
||||
case DEFINED: return "defined";
|
||||
case STARTED: return "started";
|
||||
case LOCKED_IN: return "locked_in";
|
||||
case ACTIVE: return "active";
|
||||
case FAILED: return "failed";
|
||||
}
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const
|
||||
{
|
||||
int nPeriod = Period();
|
||||
|
@ -205,6 +217,35 @@ public:
|
|||
|
||||
} // namespace
|
||||
|
||||
BIP9Info VersionBitsCache::Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id)
|
||||
{
|
||||
BIP9Info result;
|
||||
|
||||
const auto current_state = State(block_index.pprev, params, id);
|
||||
result.current_state = StateName(current_state);
|
||||
result.since = StateSinceHeight(block_index.pprev, params, id);
|
||||
|
||||
const auto next_state = State(&block_index, params, id);
|
||||
result.next_state = StateName(next_state);
|
||||
|
||||
const bool has_signal = (STARTED == current_state || LOCKED_IN == current_state);
|
||||
if (has_signal) {
|
||||
result.stats.emplace(Statistics(&block_index, params, id, &result.signalling_blocks));
|
||||
if (LOCKED_IN == current_state) {
|
||||
result.stats->threshold = 0;
|
||||
result.stats->possible = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_state == ACTIVE) {
|
||||
result.active_since = result.since;
|
||||
} else if (next_state == ACTIVE) {
|
||||
result.active_since = block_index.nHeight + 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ThresholdState VersionBitsCache::State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||
{
|
||||
LOCK(m_mutex);
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
class CChainParams;
|
||||
|
||||
|
@ -43,15 +45,25 @@ typedef std::map<const CBlockIndex*, ThresholdState> ThresholdConditionCache;
|
|||
/** Display status of an in-progress BIP9 softfork */
|
||||
struct BIP9Stats {
|
||||
/** Length of blocks of the BIP9 signalling period */
|
||||
uint32_t period;
|
||||
uint32_t period{0};
|
||||
/** Number of blocks with the version bit set required to activate the softfork */
|
||||
uint32_t threshold;
|
||||
uint32_t threshold{0};
|
||||
/** Number of blocks elapsed since the beginning of the current period */
|
||||
uint32_t elapsed;
|
||||
uint32_t elapsed{0};
|
||||
/** Number of blocks with the version bit set since the beginning of the current period */
|
||||
uint32_t count;
|
||||
uint32_t count{0};
|
||||
/** False if there are not enough blocks left in this period to pass activation threshold */
|
||||
bool possible;
|
||||
bool possible{false};
|
||||
};
|
||||
|
||||
/** Detailed status of an enabled BIP9 deployment */
|
||||
struct BIP9Info {
|
||||
int since{0};
|
||||
std::string current_state{};
|
||||
std::string next_state{};
|
||||
std::optional<BIP9Stats> stats;
|
||||
std::vector<bool> signalling_blocks;
|
||||
std::optional<int> active_since;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -95,6 +107,8 @@ public:
|
|||
|
||||
static uint32_t Mask(const Consensus::Params& params, Consensus::DeploymentPos pos);
|
||||
|
||||
BIP9Info Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
||||
|
||||
/** Get the BIP9 state for a given deployment for the block after pindexPrev. */
|
||||
ThresholdState State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue