Skip to content

Commit b1e967c

Browse files
committed
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.
1 parent 3bd32c2 commit b1e967c

File tree

3 files changed

+85
-46
lines changed

3 files changed

+85
-46
lines changed

src/rpc/blockchain.cpp

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,71 +1215,55 @@ static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softfo
12151215
static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const ChainstateManager& chainman, Consensus::DeploymentPos id)
12161216
{
12171217
// For BIP9 deployments.
1218-
12191218
if (!DeploymentEnabled(chainman, id)) return;
12201219
if (blockindex == nullptr) return;
12211220

1222-
auto get_state_name = [](const ThresholdState state) -> std::string {
1223-
switch (state) {
1224-
case ThresholdState::DEFINED: return "defined";
1225-
case ThresholdState::STARTED: return "started";
1226-
case ThresholdState::LOCKED_IN: return "locked_in";
1227-
case ThresholdState::ACTIVE: return "active";
1228-
case ThresholdState::FAILED: return "failed";
1229-
}
1230-
return "invalid";
1231-
};
1232-
12331221
UniValue bip9(UniValue::VOBJ);
1234-
1235-
const ThresholdState next_state = chainman.m_versionbitscache.State(blockindex, chainman.GetConsensus(), id);
1236-
const ThresholdState current_state = chainman.m_versionbitscache.State(blockindex->pprev, chainman.GetConsensus(), id);
1237-
1238-
const bool has_signal = (ThresholdState::STARTED == current_state || ThresholdState::LOCKED_IN == current_state);
1222+
BIP9Info info{chainman.m_versionbitscache.Info(*blockindex, chainman.GetConsensus(), id)};
1223+
const auto& depparams{chainman.GetConsensus().vDeployments[id]};
12391224

12401225
// BIP9 parameters
1241-
if (has_signal) {
1242-
bip9.pushKV("bit", chainman.GetConsensus().vDeployments[id].bit);
1226+
if (info.stats.has_value()) {
1227+
bip9.pushKV("bit", depparams.bit);
12431228
}
1244-
bip9.pushKV("start_time", chainman.GetConsensus().vDeployments[id].nStartTime);
1245-
bip9.pushKV("timeout", chainman.GetConsensus().vDeployments[id].nTimeout);
1246-
bip9.pushKV("min_activation_height", chainman.GetConsensus().vDeployments[id].min_activation_height);
1229+
bip9.pushKV("start_time", depparams.nStartTime);
1230+
bip9.pushKV("timeout", depparams.nTimeout);
1231+
bip9.pushKV("min_activation_height", depparams.min_activation_height);
12471232

12481233
// BIP9 status
1249-
bip9.pushKV("status", get_state_name(current_state));
1250-
bip9.pushKV("since", chainman.m_versionbitscache.StateSinceHeight(blockindex->pprev, chainman.GetConsensus(), id));
1251-
bip9.pushKV("status_next", get_state_name(next_state));
1234+
bip9.pushKV("status", info.current_state);
1235+
bip9.pushKV("since", info.since);
1236+
bip9.pushKV("status_next", info.next_state);
12521237

12531238
// BIP9 signalling status, if applicable
1254-
if (has_signal) {
1239+
if (info.stats.has_value()) {
12551240
UniValue statsUV(UniValue::VOBJ);
1256-
std::vector<bool> signals;
1257-
BIP9Stats statsStruct = chainman.m_versionbitscache.Statistics(blockindex, chainman.GetConsensus(), id, &signals);
1258-
statsUV.pushKV("period", statsStruct.period);
1259-
statsUV.pushKV("elapsed", statsStruct.elapsed);
1260-
statsUV.pushKV("count", statsStruct.count);
1261-
if (ThresholdState::LOCKED_IN != current_state) {
1262-
statsUV.pushKV("threshold", statsStruct.threshold);
1263-
statsUV.pushKV("possible", statsStruct.possible);
1241+
statsUV.pushKV("period", info.stats->period);
1242+
statsUV.pushKV("elapsed", info.stats->elapsed);
1243+
statsUV.pushKV("count", info.stats->count);
1244+
if (info.stats->threshold > 0 || info.stats->possible) {
1245+
statsUV.pushKV("threshold", info.stats->threshold);
1246+
statsUV.pushKV("possible", info.stats->possible);
12641247
}
12651248
bip9.pushKV("statistics", std::move(statsUV));
12661249

12671250
std::string sig;
1268-
sig.reserve(signals.size());
1269-
for (const bool s : signals) {
1251+
sig.reserve(info.signalling_blocks.size());
1252+
for (const bool s : info.signalling_blocks) {
12701253
sig.push_back(s ? '#' : '-');
12711254
}
12721255
bip9.pushKV("signalling", sig);
12731256
}
12741257

12751258
UniValue rv(UniValue::VOBJ);
12761259
rv.pushKV("type", "bip9");
1277-
if (ThresholdState::ACTIVE == next_state) {
1278-
rv.pushKV("height", chainman.m_versionbitscache.StateSinceHeight(blockindex, chainman.GetConsensus(), id));
1260+
bool is_active = false;
1261+
if (info.active_since.has_value()) {
1262+
rv.pushKV("height", *info.active_since);
1263+
is_active = (*info.active_since <= blockindex->nHeight + 1);
12791264
}
1280-
rv.pushKV("active", ThresholdState::ACTIVE == next_state);
1281-
rv.pushKV("bip9", std::move(bip9));
1282-
1265+
rv.pushKV("active", is_active);
1266+
rv.pushKV("bip9", bip9);
12831267
softforks.pushKV(DeploymentName(id), std::move(rv));
12841268
}
12851269

src/versionbits.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@
99

1010
using enum ThresholdState;
1111

12+
static std::string StateName(ThresholdState state)
13+
{
14+
switch (state) {
15+
case DEFINED: return "defined";
16+
case STARTED: return "started";
17+
case LOCKED_IN: return "locked_in";
18+
case ACTIVE: return "active";
19+
case FAILED: return "failed";
20+
}
21+
return "invalid";
22+
}
23+
1224
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const
1325
{
1426
int nPeriod = Period();
@@ -205,6 +217,35 @@ class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
205217

206218
} // namespace
207219

220+
BIP9Info VersionBitsCache::Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id)
221+
{
222+
BIP9Info result;
223+
224+
const auto current_state = State(block_index.pprev, params, id);
225+
result.current_state = StateName(current_state);
226+
result.since = StateSinceHeight(block_index.pprev, params, id);
227+
228+
const auto next_state = State(&block_index, params, id);
229+
result.next_state = StateName(next_state);
230+
231+
const bool has_signal = (STARTED == current_state || LOCKED_IN == current_state);
232+
if (has_signal) {
233+
result.stats.emplace(Statistics(&block_index, params, id, &result.signalling_blocks));
234+
if (LOCKED_IN == current_state) {
235+
result.stats->threshold = 0;
236+
result.stats->possible = false;
237+
}
238+
}
239+
240+
if (current_state == ACTIVE) {
241+
result.active_since = result.since;
242+
} else if (next_state == ACTIVE) {
243+
result.active_since = block_index.nHeight + 1;
244+
}
245+
246+
return result;
247+
}
248+
208249
ThresholdState VersionBitsCache::State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
209250
{
210251
LOCK(m_mutex);

src/versionbits.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#include <array>
1212
#include <map>
13+
#include <optional>
14+
#include <vector>
1315

1416
class CChainParams;
1517

@@ -43,15 +45,25 @@ typedef std::map<const CBlockIndex*, ThresholdState> ThresholdConditionCache;
4345
/** Display status of an in-progress BIP9 softfork */
4446
struct BIP9Stats {
4547
/** Length of blocks of the BIP9 signalling period */
46-
uint32_t period;
48+
uint32_t period{0};
4749
/** Number of blocks with the version bit set required to activate the softfork */
48-
uint32_t threshold;
50+
uint32_t threshold{0};
4951
/** Number of blocks elapsed since the beginning of the current period */
50-
uint32_t elapsed;
52+
uint32_t elapsed{0};
5153
/** Number of blocks with the version bit set since the beginning of the current period */
52-
uint32_t count;
54+
uint32_t count{0};
5355
/** False if there are not enough blocks left in this period to pass activation threshold */
54-
bool possible;
56+
bool possible{false};
57+
};
58+
59+
/** Detailed status of an enabled BIP9 deployment */
60+
struct BIP9Info {
61+
int since{0};
62+
std::string current_state{};
63+
std::string next_state{};
64+
std::optional<BIP9Stats> stats;
65+
std::vector<bool> signalling_blocks;
66+
std::optional<int> active_since;
5567
};
5668

5769
/**
@@ -95,6 +107,8 @@ class VersionBitsCache
95107

96108
static uint32_t Mask(const Consensus::Params& params, Consensus::DeploymentPos pos);
97109

110+
BIP9Info Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
111+
98112
/** Get the BIP9 state for a given deployment for the block after pindexPrev. */
99113
ThresholdState State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
100114

0 commit comments

Comments
 (0)