Skip to content

Commit

Permalink
Simplify versionbits for heretical deployments
Browse files Browse the repository at this point in the history
  • Loading branch information
ajtowns committed May 23, 2022
1 parent 710adad commit afdbd68
Show file tree
Hide file tree
Showing 15 changed files with 82 additions and 1,151 deletions.
6 changes: 2 additions & 4 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,7 @@ BITCOIN_TESTS =\
test/validation_chainstatemanager_tests.cpp \
test/validation_flush_tests.cpp \
test/validation_tests.cpp \
test/validationinterface_tests.cpp \
test/versionbits_tests.cpp
test/validationinterface_tests.cpp

if ENABLE_WALLET
BITCOIN_TESTS += \
Expand Down Expand Up @@ -318,8 +317,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/tx_pool.cpp \
test/fuzz/txrequest.cpp \
test/fuzz/utxo_snapshot.cpp \
test/fuzz/validation_load_mempool.cpp \
test/fuzz/versionbits.cpp
test/fuzz/validation_load_mempool.cpp
endif # ENABLE_FUZZ_BINARY

nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
Expand Down
33 changes: 12 additions & 21 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,8 @@ class CMainParams : public CChainParams {
consensus.nRuleChangeActivationThreshold = 1815; // 90% of 2016
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::InquisitionDeployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::InquisitionDeployment::NO_TIMEOUT;

consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000002927cdceccbd5209e81e80db");
consensus.defaultAssumeValid = uint256S("0x000000000000000000052d314a259755ca65944e68df6b12a067ea8f1f5a7091"); // 724466
Expand Down Expand Up @@ -196,9 +195,8 @@ class CTestNetParams : public CChainParams {
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::InquisitionDeployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::InquisitionDeployment::NO_TIMEOUT;

consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000064728c7be6fe4b2f961");
consensus.defaultAssumeValid = uint256S("0x00000000000163cfb1f97c4e4098a3692c8053ad9cab5ad9c86b338b5c00b8b7"); // 2143398
Expand Down Expand Up @@ -330,9 +328,8 @@ class SigNetParams : public CChainParams {
consensus.MinBIP9WarningHeight = 0;
consensus.powLimit = uint256S("00000377ae000000000000000000000000000000000000000000000000000000");
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::InquisitionDeployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::InquisitionDeployment::NO_TIMEOUT;

// message start is defined as the first 4 bytes of the sha256d of the block script
CHashWriter h(SER_DISK, 0);
Expand Down Expand Up @@ -395,8 +392,7 @@ class CRegTestParams : public CChainParams {

consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::InquisitionDeployment::NO_TIMEOUT;

consensus.nMinimumChainWork = uint256{};
consensus.defaultAssumeValid = uint256{};
Expand Down Expand Up @@ -461,11 +457,10 @@ class CRegTestParams : public CChainParams {
/**
* Allows modifying the Version Bits regtest parameters.
*/
void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int min_activation_height)
void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
{
consensus.vDeployments[d].nStartTime = nStartTime;
consensus.vDeployments[d].nTimeout = nTimeout;
consensus.vDeployments[d].min_activation_height = min_activation_height;
}
void UpdateActivationParametersFromArgs(const ArgsManager& args);
};
Expand Down Expand Up @@ -510,26 +505,22 @@ void CRegTestParams::UpdateActivationParametersFromArgs(const ArgsManager& args)
for (const std::string& strDeployment : args.GetArgs("-vbparams")) {
std::vector<std::string> vDeploymentParams;
boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":"));
if (vDeploymentParams.size() < 3 || 4 < vDeploymentParams.size()) {
throw std::runtime_error("Version bits parameters malformed, expecting deployment:start:end[:min_activation_height]");
if (vDeploymentParams.size() < 3 || 3 < vDeploymentParams.size()) {
throw std::runtime_error("Version bits parameters malformed, expecting deployment:start:end");
}
int64_t nStartTime, nTimeout;
int min_activation_height = 0;
if (!ParseInt64(vDeploymentParams[1], &nStartTime)) {
throw std::runtime_error(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1]));
}
if (!ParseInt64(vDeploymentParams[2], &nTimeout)) {
throw std::runtime_error(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2]));
}
if (vDeploymentParams.size() >= 4 && !ParseInt32(vDeploymentParams[3], &min_activation_height)) {
throw std::runtime_error(strprintf("Invalid min_activation_height (%s)", vDeploymentParams[3]));
}
bool found = false;
for (int j=0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
if (vDeploymentParams[0] == VersionBitsDeploymentInfo[j].name) {
UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout, min_activation_height);
UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
found = true;
LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld, min_activation_height=%d\n", vDeploymentParams[0], nStartTime, nTimeout, min_activation_height);
LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
break;
}
}
Expand Down
9 changes: 2 additions & 7 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,13 @@ constexpr bool ValidDeployment(DeploymentPos dep) { return dep < MAX_VERSION_BIT
/**
* Struct for each individual consensus rule change using BIP9.
*/
struct BIP9Deployment {
struct InquisitionDeployment {
/** Bit position to select the particular bit in nVersion. */
int bit;
/** Start MedianTime for version bits miner confirmation. Can be a date in the past */
int64_t nStartTime;
/** Timeout/expiry MedianTime for the deployment attempt. */
int64_t nTimeout;
/** If lock in occurs, delay activation until at least this block
* height. Note that activation will only occur on a retarget
* boundary.
*/
int min_activation_height{0};

/** Constant for nTimeout very far in the future. */
static constexpr int64_t NO_TIMEOUT = std::numeric_limits<int64_t>::max();
Expand Down Expand Up @@ -97,7 +92,7 @@ struct Params {
*/
uint32_t nRuleChangeActivationThreshold;
uint32_t nMinerConfirmationWindow;
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS];
InquisitionDeployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS];
/** Proof of work parameters */
uint256 powLimit;
bool fPowAllowMinDifficultyBlocks;
Expand Down
5 changes: 3 additions & 2 deletions src/deploymentstatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus
inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos dep)
{
assert(Consensus::ValidDeployment(dep));
return ThresholdState::ACTIVE == g_versionbitscache.State(pindexPrev, params, dep);
const auto state = g_versionbitscache.State(pindexPrev, params, dep);
return state == ThresholdState::ACTIVE || state == ThresholdState::DEACTIVATING;
}

/** Determine if a deployment is active for this block */
Expand All @@ -49,7 +50,7 @@ inline bool DeploymentEnabled(const Consensus::Params& params, Consensus::Buried
inline bool DeploymentEnabled(const Consensus::Params& params, Consensus::DeploymentPos dep)
{
assert(Consensus::ValidDeployment(dep));
return params.vDeployments[dep].nStartTime != Consensus::BIP9Deployment::NEVER_ACTIVE;
return params.vDeployments[dep].nStartTime != Consensus::InquisitionDeployment::NEVER_ACTIVE;
}

#endif // BITCOIN_DEPLOYMENTSTATUS_H
39 changes: 6 additions & 33 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1455,10 +1455,10 @@ static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softfo
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";
case ThresholdState::DEACTIVATING: return "deactivating";
case ThresholdState::ABANDONED: return "abandoned";
}
return "invalid";
};
Expand All @@ -1468,50 +1468,23 @@ static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softfo
const ThresholdState next_state = g_versionbitscache.State(blockindex, consensusParams, id);
const ThresholdState current_state = g_versionbitscache.State(blockindex->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("bit", consensusParams.vDeployments[id].bit);
bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime);
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
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(blockindex->pprev, consensusParams, id));
bip9.pushKV("status_next", get_state_name(next_state));

// BIP9 signalling status, if applicable
if (has_signal) {
UniValue statsUV(UniValue::VOBJ);
std::vector<bool> signals;
BIP9Stats statsStruct = g_versionbitscache.Statistics(blockindex, consensusParams, 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);
}
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);
rv.pushKV("type", "bip9");
rv.pushKV("type", "inquisition");
if (ThresholdState::ACTIVE == next_state) {
rv.pushKV("height", g_versionbitscache.StateSinceHeight(blockindex, consensusParams, id));
}
rv.pushKV("active", ThresholdState::ACTIVE == next_state);
rv.pushKV("bip9", bip9);
rv.pushKV("active", ThresholdState::ACTIVE == next_state || ThresholdState::DEACTIVATING == next_state);
rv.pushKV("inquisition", bip9);

softforks.pushKV(DeploymentName(id), rv);
}
Expand Down
20 changes: 3 additions & 17 deletions src/rpc/mining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -856,26 +856,12 @@ static RPCHelpMan getblocktemplate()
ThresholdState state = g_versionbitscache.State(pindexPrev, consensusParams, pos);
switch (state) {
case ThresholdState::DEFINED:
case ThresholdState::FAILED:
// Not exposed to GBT at all
break;
case ThresholdState::ABANDONED:
case ThresholdState::LOCKED_IN:
// Ensure bit is set in block version
pblock->nVersion |= g_versionbitscache.Mask(consensusParams, pos);
[[fallthrough]];
case ThresholdState::STARTED:
{
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
vbavailable.pushKV(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit);
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
if (!vbinfo.gbt_force) {
// If the client doesn't support this, don't indicate it in the [default] version
pblock->nVersion &= ~g_versionbitscache.Mask(consensusParams, pos);
}
}
// Not exposed to GBT at all
break;
}
case ThresholdState::ACTIVE:
case ThresholdState::DEACTIVATING:
{
// Add to rules only
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
Expand Down
Loading

0 comments on commit afdbd68

Please sign in to comment.