mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-07-03 12:11:52 +02:00
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.
This commit is contained in:
@ -1412,45 +1412,60 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue&
|
|||||||
// For BIP9 deployments.
|
// For BIP9 deployments.
|
||||||
|
|
||||||
if (!DeploymentEnabled(consensusParams, id)) return;
|
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);
|
UniValue bip9(UniValue::VOBJ);
|
||||||
const ThresholdState thresholdState = g_versionbitscache.State(active_chain_tip, consensusParams, id);
|
|
||||||
switch (thresholdState) {
|
const ThresholdState next_state = g_versionbitscache.State(active_chain_tip, consensusParams, id);
|
||||||
case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break;
|
const ThresholdState current_state = g_versionbitscache.State(active_chain_tip->pprev, consensusParams, id);
|
||||||
case ThresholdState::STARTED: bip9.pushKV("status", "started"); break;
|
|
||||||
case ThresholdState::LOCKED_IN: bip9.pushKV("status", "locked_in"); break;
|
const bool has_signal = (ThresholdState::STARTED == current_state || ThresholdState::LOCKED_IN == current_state);
|
||||||
case ThresholdState::ACTIVE: bip9.pushKV("status", "active"); break;
|
|
||||||
case ThresholdState::FAILED: bip9.pushKV("status", "failed"); break;
|
// BIP9 parameters
|
||||||
}
|
|
||||||
const bool has_signal = (ThresholdState::STARTED == thresholdState || ThresholdState::LOCKED_IN == thresholdState);
|
|
||||||
if (has_signal) {
|
if (has_signal) {
|
||||||
bip9.pushKV("bit", consensusParams.vDeployments[id].bit);
|
bip9.pushKV("bit", consensusParams.vDeployments[id].bit);
|
||||||
}
|
}
|
||||||
bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime);
|
bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime);
|
||||||
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
|
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
|
||||||
int64_t since_height = g_versionbitscache.StateSinceHeight(active_chain_tip, consensusParams, id);
|
bip9.pushKV("min_activation_height", consensusParams.vDeployments[id].min_activation_height);
|
||||||
bip9.pushKV("since", since_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) {
|
if (has_signal) {
|
||||||
UniValue statsUV(UniValue::VOBJ);
|
UniValue statsUV(UniValue::VOBJ);
|
||||||
BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, consensusParams, id);
|
BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, consensusParams, id);
|
||||||
statsUV.pushKV("period", statsStruct.period);
|
statsUV.pushKV("period", statsStruct.period);
|
||||||
statsUV.pushKV("elapsed", statsStruct.elapsed);
|
statsUV.pushKV("elapsed", statsStruct.elapsed);
|
||||||
statsUV.pushKV("count", statsStruct.count);
|
statsUV.pushKV("count", statsStruct.count);
|
||||||
if (ThresholdState::LOCKED_IN != thresholdState) {
|
if (ThresholdState::LOCKED_IN != current_state) {
|
||||||
statsUV.pushKV("threshold", statsStruct.threshold);
|
statsUV.pushKV("threshold", statsStruct.threshold);
|
||||||
statsUV.pushKV("possible", statsStruct.possible);
|
statsUV.pushKV("possible", statsStruct.possible);
|
||||||
}
|
}
|
||||||
bip9.pushKV("statistics", statsUV);
|
bip9.pushKV("statistics", statsUV);
|
||||||
}
|
}
|
||||||
bip9.pushKV("min_activation_height", consensusParams.vDeployments[id].min_activation_height);
|
|
||||||
|
|
||||||
UniValue rv(UniValue::VOBJ);
|
UniValue rv(UniValue::VOBJ);
|
||||||
rv.pushKV("type", "bip9");
|
rv.pushKV("type", "bip9");
|
||||||
rv.pushKV("bip9", bip9);
|
if (ThresholdState::ACTIVE == next_state) {
|
||||||
if (ThresholdState::ACTIVE == thresholdState) {
|
rv.pushKV("height", g_versionbitscache.StateSinceHeight(active_chain_tip, consensusParams, id));
|
||||||
rv.pushKV("height", since_height);
|
|
||||||
}
|
}
|
||||||
rv.pushKV("active", ThresholdState::ACTIVE == thresholdState);
|
rv.pushKV("active", ThresholdState::ACTIVE == next_state);
|
||||||
|
rv.pushKV("bip9", bip9);
|
||||||
|
|
||||||
softforks.pushKV(DeploymentName(id), rv);
|
softforks.pushKV(DeploymentName(id), rv);
|
||||||
}
|
}
|
||||||
@ -1551,14 +1566,17 @@ RPCHelpMan getblockchaininfo()
|
|||||||
namespace {
|
namespace {
|
||||||
const std::vector<RPCResult> RPCHelpForDeployment{
|
const std::vector<RPCResult> RPCHelpForDeployment{
|
||||||
{RPCResult::Type::STR, "type", "one of \"buried\", \"bip9\""},
|
{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::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, "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, "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_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::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::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, "period", "the length in blocks of the signalling period"},
|
||||||
@ -1568,8 +1586,6 @@ const std::vector<RPCResult> 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::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 DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consensusParams)
|
||||||
|
@ -51,7 +51,7 @@ public:
|
|||||||
|
|
||||||
ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, dummy_params, m_cache); }
|
ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, dummy_params, m_cache); }
|
||||||
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, dummy_params, m_cache); }
|
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, dummy_params, m_cache); }
|
||||||
BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateStatisticsFor(pindexPrev, dummy_params); }
|
BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindex) const { return AbstractThresholdConditionChecker::GetStateStatisticsFor(pindex, dummy_params); }
|
||||||
|
|
||||||
bool Condition(int32_t version) const
|
bool Condition(int32_t version) const
|
||||||
{
|
{
|
||||||
@ -220,7 +220,13 @@ FUZZ_TARGET_INIT(versionbits, initialize)
|
|||||||
CBlockIndex* prev = blocks.tip();
|
CBlockIndex* prev = blocks.tip();
|
||||||
const int exp_since = checker.GetStateSinceHeightFor(prev);
|
const int exp_since = checker.GetStateSinceHeightFor(prev);
|
||||||
const ThresholdState exp_state = checker.GetStateFor(prev);
|
const ThresholdState exp_state = checker.GetStateFor(prev);
|
||||||
BIP9Stats last_stats = checker.GetStateStatisticsFor(prev);
|
|
||||||
|
// get statistics from end of previous period, then reset
|
||||||
|
BIP9Stats last_stats;
|
||||||
|
last_stats.period = period;
|
||||||
|
last_stats.threshold = threshold;
|
||||||
|
last_stats.count = last_stats.elapsed = 0;
|
||||||
|
last_stats.possible = (period >= threshold);
|
||||||
|
|
||||||
int prev_next_height = (prev == nullptr ? 0 : prev->nHeight + 1);
|
int prev_next_height = (prev == nullptr ? 0 : prev->nHeight + 1);
|
||||||
assert(exp_since <= prev_next_height);
|
assert(exp_since <= prev_next_height);
|
||||||
@ -241,9 +247,6 @@ FUZZ_TARGET_INIT(versionbits, initialize)
|
|||||||
assert(state == exp_state);
|
assert(state == exp_state);
|
||||||
assert(since == exp_since);
|
assert(since == exp_since);
|
||||||
|
|
||||||
// GetStateStatistics may crash when state is not STARTED
|
|
||||||
if (state != ThresholdState::STARTED) continue;
|
|
||||||
|
|
||||||
// check that after mining this block stats change as expected
|
// check that after mining this block stats change as expected
|
||||||
const BIP9Stats stats = checker.GetStateStatisticsFor(current_block);
|
const BIP9Stats stats = checker.GetStateStatisticsFor(current_block);
|
||||||
assert(stats.period == period);
|
assert(stats.period == period);
|
||||||
@ -265,14 +268,12 @@ FUZZ_TARGET_INIT(versionbits, initialize)
|
|||||||
CBlockIndex* current_block = blocks.mine_block(signal);
|
CBlockIndex* current_block = blocks.mine_block(signal);
|
||||||
assert(checker.Condition(current_block) == signal);
|
assert(checker.Condition(current_block) == signal);
|
||||||
|
|
||||||
// GetStateStatistics is safe on a period boundary
|
|
||||||
// and has progressed to a new period
|
|
||||||
const BIP9Stats stats = checker.GetStateStatisticsFor(current_block);
|
const BIP9Stats stats = checker.GetStateStatisticsFor(current_block);
|
||||||
assert(stats.period == period);
|
assert(stats.period == period);
|
||||||
assert(stats.threshold == threshold);
|
assert(stats.threshold == threshold);
|
||||||
assert(stats.elapsed == 0);
|
assert(stats.elapsed == period);
|
||||||
assert(stats.count == 0);
|
assert(stats.count == blocks_sig);
|
||||||
assert(stats.possible == true);
|
assert(stats.possible == (stats.count + period >= stats.elapsed + threshold));
|
||||||
|
|
||||||
// More interesting is whether the state changed.
|
// More interesting is whether the state changed.
|
||||||
const ThresholdState state = checker.GetStateFor(current_block);
|
const ThresholdState state = checker.GetStateFor(current_block);
|
||||||
|
@ -105,22 +105,23 @@ BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockI
|
|||||||
stats.period = Period(params);
|
stats.period = Period(params);
|
||||||
stats.threshold = Threshold(params);
|
stats.threshold = Threshold(params);
|
||||||
|
|
||||||
if (pindex == nullptr)
|
if (pindex == nullptr) return stats;
|
||||||
return stats;
|
|
||||||
|
|
||||||
// Find beginning of period
|
// Find beginning of period
|
||||||
const CBlockIndex* pindexEndOfPrevPeriod = pindex->GetAncestor(pindex->nHeight - ((pindex->nHeight + 1) % stats.period));
|
int start_height = pindex->nHeight - (pindex->nHeight % stats.period);
|
||||||
stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight;
|
|
||||||
|
|
||||||
// Count from current block to beginning of period
|
// Count from current block to beginning of period
|
||||||
|
int elapsed = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
const CBlockIndex* currentIndex = pindex;
|
const CBlockIndex* currentIndex = pindex;
|
||||||
while (pindexEndOfPrevPeriod->nHeight != currentIndex->nHeight){
|
for(;;) {
|
||||||
if (Condition(currentIndex, params))
|
++elapsed;
|
||||||
count++;
|
if (Condition(currentIndex, params)) ++count;
|
||||||
|
if (currentIndex->nHeight <= start_height) break;
|
||||||
currentIndex = currentIndex->pprev;
|
currentIndex = currentIndex->pprev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stats.elapsed = elapsed;
|
||||||
stats.count = count;
|
stats.count = count;
|
||||||
stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
|
stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
|
||||||
|
|
||||||
@ -196,9 +197,9 @@ ThresholdState VersionBitsCache::State(const CBlockIndex* pindexPrev, const Cons
|
|||||||
return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
|
return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
BIP9Stats VersionBitsCache::Statistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
BIP9Stats VersionBitsCache::Statistics(const CBlockIndex* pindex, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||||
{
|
{
|
||||||
return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params);
|
return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindex, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VersionBitsCache::StateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
int VersionBitsCache::StateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
|
||||||
|
@ -64,7 +64,7 @@ protected:
|
|||||||
virtual int Threshold(const Consensus::Params& params) const =0;
|
virtual int Threshold(const Consensus::Params& params) const =0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Returns the numerical statistics of an in-progress BIP9 softfork in the current period */
|
/** Returns the numerical statistics of an in-progress BIP9 softfork in the period including pindex */
|
||||||
BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params) const;
|
BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params) const;
|
||||||
/** Returns the state for pindex A based on parent pindexPrev B. Applies any state transition if conditions are present.
|
/** Returns the state for pindex A based on parent pindexPrev B. Applies any state transition if conditions are present.
|
||||||
* Caches state from first block of period. */
|
* Caches state from first block of period. */
|
||||||
@ -82,8 +82,8 @@ private:
|
|||||||
ThresholdConditionCache m_caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] GUARDED_BY(m_mutex);
|
ThresholdConditionCache m_caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] GUARDED_BY(m_mutex);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Get the numerical statistics for a given deployment for the signalling period that includes the block after pindexPrev. */
|
/** Get the numerical statistics for a given deployment for the signalling period that includes pindex. */
|
||||||
static BIP9Stats Statistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos);
|
static BIP9Stats Statistics(const CBlockIndex* pindex, const Consensus::Params& params, Consensus::DeploymentPos pos);
|
||||||
|
|
||||||
static uint32_t Mask(const Consensus::Params& params, Consensus::DeploymentPos pos);
|
static uint32_t Mask(const Consensus::Params& params, Consensus::DeploymentPos pos);
|
||||||
|
|
||||||
|
@ -72,7 +72,6 @@ class BlockchainTest(BitcoinTestFramework):
|
|||||||
self.restart_node(0, extra_args=['-stopatheight=207', '-prune=1']) # Set extra args with pruning after rescan is complete
|
self.restart_node(0, extra_args=['-stopatheight=207', '-prune=1']) # Set extra args with pruning after rescan is complete
|
||||||
|
|
||||||
self._test_getblockchaininfo()
|
self._test_getblockchaininfo()
|
||||||
self._test_getdeploymentinfo()
|
|
||||||
self._test_getchaintxstats()
|
self._test_getchaintxstats()
|
||||||
self._test_gettxoutsetinfo()
|
self._test_gettxoutsetinfo()
|
||||||
self._test_getblockheader()
|
self._test_getblockheader()
|
||||||
@ -81,6 +80,7 @@ class BlockchainTest(BitcoinTestFramework):
|
|||||||
self._test_stopatheight()
|
self._test_stopatheight()
|
||||||
self._test_waitforblockheight()
|
self._test_waitforblockheight()
|
||||||
self._test_getblock()
|
self._test_getblock()
|
||||||
|
self._test_getdeploymentinfo()
|
||||||
assert self.nodes[0].verifychain(4, 0)
|
assert self.nodes[0].verifychain(4, 0)
|
||||||
|
|
||||||
def mine_chain(self):
|
def mine_chain(self):
|
||||||
@ -160,11 +160,6 @@ class BlockchainTest(BitcoinTestFramework):
|
|||||||
self.start_node(0, extra_args=[
|
self.start_node(0, extra_args=[
|
||||||
'-stopatheight=207',
|
'-stopatheight=207',
|
||||||
'-prune=550',
|
'-prune=550',
|
||||||
'-testactivationheight=bip34@2',
|
|
||||||
'-testactivationheight=dersig@3',
|
|
||||||
'-testactivationheight=cltv@4',
|
|
||||||
'-testactivationheight=csv@5',
|
|
||||||
'-testactivationheight=segwit@6',
|
|
||||||
])
|
])
|
||||||
|
|
||||||
res = self.nodes[0].getblockchaininfo()
|
res = self.nodes[0].getblockchaininfo()
|
||||||
@ -178,11 +173,10 @@ class BlockchainTest(BitcoinTestFramework):
|
|||||||
assert_equal(res['prune_target_size'], 576716800)
|
assert_equal(res['prune_target_size'], 576716800)
|
||||||
assert_greater_than(res['size_on_disk'], 0)
|
assert_greater_than(res['size_on_disk'], 0)
|
||||||
|
|
||||||
def _test_getdeploymentinfo(self):
|
def check_signalling_deploymentinfo_result(self, gdi_result, height, blockhash, status_next):
|
||||||
self.log.info("Test getdeploymentinfo")
|
assert height >= 144 and height <= 287
|
||||||
|
|
||||||
res = self.nodes[0].getdeploymentinfo()
|
assert_equal(gdi_result, {
|
||||||
assert_equal(res, {
|
|
||||||
"deployments": {
|
"deployments": {
|
||||||
'bip34': {'type': 'buried', 'active': True, 'height': 2},
|
'bip34': {'type': 'buried', 'active': True, 'height': 2},
|
||||||
'bip66': {'type': 'buried', 'active': True, 'height': 3},
|
'bip66': {'type': 'buried', 'active': True, 'height': 3},
|
||||||
@ -192,30 +186,32 @@ class BlockchainTest(BitcoinTestFramework):
|
|||||||
'testdummy': {
|
'testdummy': {
|
||||||
'type': 'bip9',
|
'type': 'bip9',
|
||||||
'bip9': {
|
'bip9': {
|
||||||
'status': 'started',
|
|
||||||
'bit': 28,
|
'bit': 28,
|
||||||
'start_time': 0,
|
'start_time': 0,
|
||||||
'timeout': 0x7fffffffffffffff, # testdummy does not have a timeout so is set to the max int64 value
|
'timeout': 0x7fffffffffffffff, # testdummy does not have a timeout so is set to the max int64 value
|
||||||
|
'min_activation_height': 0,
|
||||||
|
'status': 'started',
|
||||||
|
'status-next': status_next,
|
||||||
'since': 144,
|
'since': 144,
|
||||||
'statistics': {
|
'statistics': {
|
||||||
'period': 144,
|
'period': 144,
|
||||||
'threshold': 108,
|
'threshold': 108,
|
||||||
'elapsed': HEIGHT - 143,
|
'elapsed': height - 143,
|
||||||
'count': HEIGHT - 143,
|
'count': height - 143,
|
||||||
'possible': True,
|
'possible': True,
|
||||||
},
|
},
|
||||||
'min_activation_height': 0,
|
|
||||||
},
|
},
|
||||||
'active': False
|
'active': False
|
||||||
},
|
},
|
||||||
'taproot': {
|
'taproot': {
|
||||||
'type': 'bip9',
|
'type': 'bip9',
|
||||||
'bip9': {
|
'bip9': {
|
||||||
'status': 'active',
|
|
||||||
'start_time': -1,
|
'start_time': -1,
|
||||||
'timeout': 9223372036854775807,
|
'timeout': 9223372036854775807,
|
||||||
'since': 0,
|
|
||||||
'min_activation_height': 0,
|
'min_activation_height': 0,
|
||||||
|
'status': 'active',
|
||||||
|
'status-next': 'active',
|
||||||
|
'since': 0,
|
||||||
},
|
},
|
||||||
'height': 0,
|
'height': 0,
|
||||||
'active': True
|
'active': True
|
||||||
@ -223,6 +219,31 @@ class BlockchainTest(BitcoinTestFramework):
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def _test_getdeploymentinfo(self):
|
||||||
|
# Note: continues past -stopatheight height, so must be invoked
|
||||||
|
# after _test_stopatheight
|
||||||
|
|
||||||
|
self.log.info("Test getdeploymentinfo")
|
||||||
|
self.stop_node(0)
|
||||||
|
self.start_node(0, extra_args=[
|
||||||
|
'-testactivationheight=bip34@2',
|
||||||
|
'-testactivationheight=dersig@3',
|
||||||
|
'-testactivationheight=cltv@4',
|
||||||
|
'-testactivationheight=csv@5',
|
||||||
|
'-testactivationheight=segwit@6',
|
||||||
|
])
|
||||||
|
|
||||||
|
gbci207 = self.nodes[0].getblockchaininfo()
|
||||||
|
self.check_signalling_deploymentinfo_result(self.nodes[0].getdeploymentinfo(), gbci207["blocks"], gbci207["bestblockhash"], "started")
|
||||||
|
|
||||||
|
# block just prior to lock in
|
||||||
|
self.generate(self.wallet, 287 - gbci207["blocks"])
|
||||||
|
gbci287 = self.nodes[0].getblockchaininfo()
|
||||||
|
self.check_signalling_deploymentinfo_result(self.nodes[0].getdeploymentinfo(), gbci287["blocks"], gbci287["bestblockhash"], "locked_in")
|
||||||
|
|
||||||
|
# calling with an explicit hash works
|
||||||
|
self.check_signalling_deploymentinfo_result(self.nodes[0].getdeploymentinfo(gbci207["bestblockhash"]), gbci207["blocks"], gbci207["bestblockhash"], "started")
|
||||||
|
|
||||||
def _test_getchaintxstats(self):
|
def _test_getchaintxstats(self):
|
||||||
self.log.info("Test getchaintxstats")
|
self.log.info("Test getchaintxstats")
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user