versionbits: Move BIP9 status logic for getblocktemplate 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 the appropriate
output for getblocktemplate.
This commit is contained in:
Anthony Towns
2023-12-09 08:09:36 +10:00
parent b1e967c3ec
commit 1198e7d2fd
3 changed files with 72 additions and 41 deletions

View File

@@ -565,10 +565,10 @@ static UniValue BIP22ValidationResult(const BlockValidationState& state)
return "valid?";
}
static std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
std::string s = vbinfo.name;
if (!vbinfo.gbt_force) {
static std::string gbt_force_name(const std::string& name, bool gbt_force)
{
std::string s{name};
if (!gbt_force) {
s.insert(s.begin(), '!');
}
return s;
@@ -898,45 +898,33 @@ static RPCHelpMan getblocktemplate()
}
UniValue vbavailable(UniValue::VOBJ);
for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
ThresholdState state = chainman.m_versionbitscache.State(pindexPrev, consensusParams, pos);
switch (state) {
case ThresholdState::DEFINED:
case ThresholdState::FAILED:
// Not exposed to GBT at all
break;
case ThresholdState::LOCKED_IN:
// Ensure bit is set in block version
block.nVersion |= chainman.m_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
block.nVersion &= ~chainman.m_versionbitscache.Mask(consensusParams, pos);
}
}
break;
}
case ThresholdState::ACTIVE:
{
// Add to rules only
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
aRules.push_back(gbt_vb_name(pos));
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
// Not supported by the client; make sure it's safe to proceed
if (!vbinfo.gbt_force) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name));
}
}
break;
}
const auto gbtstatus = chainman.m_versionbitscache.GBTStatus(*pindexPrev, consensusParams);
for (const auto& [name, info] : gbtstatus.signalling) {
vbavailable.pushKV(gbt_force_name(name, info.gbt_force), info.bit);
if (!info.gbt_force && !setClientRules.count(name)) {
// If the client doesn't support this, don't indicate it in the [default] version
block.nVersion &= ~info.mask;
}
}
for (const auto& [name, info] : gbtstatus.locked_in) {
block.nVersion |= info.mask;
vbavailable.pushKV(gbt_force_name(name, info.gbt_force), info.bit);
if (!info.gbt_force && !setClientRules.count(name)) {
// If the client doesn't support this, don't indicate it in the [default] version
block.nVersion &= ~info.mask;
}
}
for (const auto& [name, info] : gbtstatus.active) {
aRules.push_back(gbt_force_name(name, info.gbt_force));
if (!info.gbt_force && !setClientRules.count(name)) {
// Not supported by the client; make sure it's safe to proceed
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", name));
}
}
result.pushKV("version", block.nVersion);
result.pushKV("rules", std::move(aRules));
result.pushKV("vbavailable", std::move(vbavailable));