mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-13 03:09:37 +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)
|
static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const ChainstateManager& chainman, Consensus::DeploymentPos id)
|
||||||
{
|
{
|
||||||
// For BIP9 deployments.
|
// For BIP9 deployments.
|
||||||
|
|
||||||
if (!DeploymentEnabled(chainman, id)) return;
|
if (!DeploymentEnabled(chainman, id)) return;
|
||||||
if (blockindex == nullptr) 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);
|
UniValue bip9(UniValue::VOBJ);
|
||||||
|
BIP9Info info{chainman.m_versionbitscache.Info(*blockindex, chainman.GetConsensus(), id)};
|
||||||
const ThresholdState next_state = chainman.m_versionbitscache.State(blockindex, chainman.GetConsensus(), id);
|
const auto& depparams{chainman.GetConsensus().vDeployments[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);
|
|
||||||
|
|
||||||
// BIP9 parameters
|
// BIP9 parameters
|
||||||
if (has_signal) {
|
if (info.stats.has_value()) {
|
||||||
bip9.pushKV("bit", chainman.GetConsensus().vDeployments[id].bit);
|
bip9.pushKV("bit", depparams.bit);
|
||||||
}
|
}
|
||||||
bip9.pushKV("start_time", chainman.GetConsensus().vDeployments[id].nStartTime);
|
bip9.pushKV("start_time", depparams.nStartTime);
|
||||||
bip9.pushKV("timeout", chainman.GetConsensus().vDeployments[id].nTimeout);
|
bip9.pushKV("timeout", depparams.nTimeout);
|
||||||
bip9.pushKV("min_activation_height", chainman.GetConsensus().vDeployments[id].min_activation_height);
|
bip9.pushKV("min_activation_height", depparams.min_activation_height);
|
||||||
|
|
||||||
// BIP9 status
|
// BIP9 status
|
||||||
bip9.pushKV("status", get_state_name(current_state));
|
bip9.pushKV("status", info.current_state);
|
||||||
bip9.pushKV("since", chainman.m_versionbitscache.StateSinceHeight(blockindex->pprev, chainman.GetConsensus(), id));
|
bip9.pushKV("since", info.since);
|
||||||
bip9.pushKV("status_next", get_state_name(next_state));
|
bip9.pushKV("status_next", info.next_state);
|
||||||
|
|
||||||
// BIP9 signalling status, if applicable
|
// BIP9 signalling status, if applicable
|
||||||
if (has_signal) {
|
if (info.stats.has_value()) {
|
||||||
UniValue statsUV(UniValue::VOBJ);
|
UniValue statsUV(UniValue::VOBJ);
|
||||||
std::vector<bool> signals;
|
statsUV.pushKV("period", info.stats->period);
|
||||||
BIP9Stats statsStruct = chainman.m_versionbitscache.Statistics(blockindex, chainman.GetConsensus(), id, &signals);
|
statsUV.pushKV("elapsed", info.stats->elapsed);
|
||||||
statsUV.pushKV("period", statsStruct.period);
|
statsUV.pushKV("count", info.stats->count);
|
||||||
statsUV.pushKV("elapsed", statsStruct.elapsed);
|
if (info.stats->threshold > 0 || info.stats->possible) {
|
||||||
statsUV.pushKV("count", statsStruct.count);
|
statsUV.pushKV("threshold", info.stats->threshold);
|
||||||
if (ThresholdState::LOCKED_IN != current_state) {
|
statsUV.pushKV("possible", info.stats->possible);
|
||||||
statsUV.pushKV("threshold", statsStruct.threshold);
|
|
||||||
statsUV.pushKV("possible", statsStruct.possible);
|
|
||||||
}
|
}
|
||||||
bip9.pushKV("statistics", std::move(statsUV));
|
bip9.pushKV("statistics", std::move(statsUV));
|
||||||
|
|
||||||
std::string sig;
|
std::string sig;
|
||||||
sig.reserve(signals.size());
|
sig.reserve(info.signalling_blocks.size());
|
||||||
for (const bool s : signals) {
|
for (const bool s : info.signalling_blocks) {
|
||||||
sig.push_back(s ? '#' : '-');
|
sig.push_back(s ? '#' : '-');
|
||||||
}
|
}
|
||||||
bip9.pushKV("signalling", sig);
|
bip9.pushKV("signalling", sig);
|
||||||
|
@ -1274,12 +1257,13 @@ static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softfo
|
||||||
|
|
||||||
UniValue rv(UniValue::VOBJ);
|
UniValue rv(UniValue::VOBJ);
|
||||||
rv.pushKV("type", "bip9");
|
rv.pushKV("type", "bip9");
|
||||||
if (ThresholdState::ACTIVE == next_state) {
|
bool is_active = false;
|
||||||
rv.pushKV("height", chainman.m_versionbitscache.StateSinceHeight(blockindex, chainman.GetConsensus(), id));
|
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("active", is_active);
|
||||||
rv.pushKV("bip9", std::move(bip9));
|
rv.pushKV("bip9", bip9);
|
||||||
|
|
||||||
softforks.pushKV(DeploymentName(id), std::move(rv));
|
softforks.pushKV(DeploymentName(id), std::move(rv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,18 @@
|
||||||
|
|
||||||
using enum ThresholdState;
|
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
|
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const
|
||||||
{
|
{
|
||||||
int nPeriod = Period();
|
int nPeriod = Period();
|
||||||
|
@ -205,6 +217,35 @@ public:
|
||||||
|
|
||||||
} // namespace
|
} // 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)
|
ThresholdState VersionBitsCache::State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||||
{
|
{
|
||||||
LOCK(m_mutex);
|
LOCK(m_mutex);
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class CChainParams;
|
class CChainParams;
|
||||||
|
|
||||||
|
@ -43,15 +45,25 @@ typedef std::map<const CBlockIndex*, ThresholdState> ThresholdConditionCache;
|
||||||
/** Display status of an in-progress BIP9 softfork */
|
/** Display status of an in-progress BIP9 softfork */
|
||||||
struct BIP9Stats {
|
struct BIP9Stats {
|
||||||
/** Length of blocks of the BIP9 signalling period */
|
/** 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 */
|
/** 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 */
|
/** 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 */
|
/** 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 */
|
/** 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);
|
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. */
|
/** 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);
|
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