mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-13 03:09:37 +01:00
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:
parent
b1e967c3ec
commit
1198e7d2fd
3 changed files with 72 additions and 41 deletions
|
@ -565,10 +565,10 @@ static UniValue BIP22ValidationResult(const BlockValidationState& state)
|
||||||
return "valid?";
|
return "valid?";
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
|
static std::string gbt_force_name(const std::string& name, bool gbt_force)
|
||||||
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
|
{
|
||||||
std::string s = vbinfo.name;
|
std::string s{name};
|
||||||
if (!vbinfo.gbt_force) {
|
if (!gbt_force) {
|
||||||
s.insert(s.begin(), '!');
|
s.insert(s.begin(), '!');
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
@ -898,45 +898,33 @@ static RPCHelpMan getblocktemplate()
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue vbavailable(UniValue::VOBJ);
|
UniValue vbavailable(UniValue::VOBJ);
|
||||||
for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
|
const auto gbtstatus = chainman.m_versionbitscache.GBTStatus(*pindexPrev, consensusParams);
|
||||||
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
|
|
||||||
ThresholdState state = chainman.m_versionbitscache.State(pindexPrev, consensusParams, pos);
|
for (const auto& [name, info] : gbtstatus.signalling) {
|
||||||
switch (state) {
|
vbavailable.pushKV(gbt_force_name(name, info.gbt_force), info.bit);
|
||||||
case ThresholdState::DEFINED:
|
if (!info.gbt_force && !setClientRules.count(name)) {
|
||||||
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
|
// If the client doesn't support this, don't indicate it in the [default] version
|
||||||
block.nVersion &= ~chainman.m_versionbitscache.Mask(consensusParams, pos);
|
block.nVersion &= ~info.mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
case ThresholdState::ACTIVE:
|
}
|
||||||
{
|
|
||||||
// Add to rules only
|
for (const auto& [name, info] : gbtstatus.active) {
|
||||||
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
|
aRules.push_back(gbt_force_name(name, info.gbt_force));
|
||||||
aRules.push_back(gbt_vb_name(pos));
|
if (!info.gbt_force && !setClientRules.count(name)) {
|
||||||
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
|
|
||||||
// Not supported by the client; make sure it's safe to proceed
|
// 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", name));
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.pushKV("version", block.nVersion);
|
result.pushKV("version", block.nVersion);
|
||||||
result.pushKV("rules", std::move(aRules));
|
result.pushKV("rules", std::move(aRules));
|
||||||
result.pushKV("vbavailable", std::move(vbavailable));
|
result.pushKV("vbavailable", std::move(vbavailable));
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <consensus/params.h>
|
#include <consensus/params.h>
|
||||||
|
#include <deploymentinfo.h>
|
||||||
#include <kernel/chainparams.h>
|
#include <kernel/chainparams.h>
|
||||||
#include <util/check.h>
|
#include <util/check.h>
|
||||||
#include <versionbits.h>
|
#include <versionbits.h>
|
||||||
|
@ -246,6 +247,37 @@ BIP9Info VersionBitsCache::Info(const CBlockIndex& block_index, const Consensus:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIP9GBTStatus VersionBitsCache::GBTStatus(const CBlockIndex& block_index, const Consensus::Params& params)
|
||||||
|
{
|
||||||
|
BIP9GBTStatus result;
|
||||||
|
|
||||||
|
LOCK(m_mutex);
|
||||||
|
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
|
||||||
|
auto pos = static_cast<Consensus::DeploymentPos>(i);
|
||||||
|
VersionBitsConditionChecker checker(params, pos);
|
||||||
|
ThresholdState state = checker.GetStateFor(&block_index, m_caches[pos]);
|
||||||
|
const VBDeploymentInfo& vbdepinfo = VersionBitsDeploymentInfo[pos];
|
||||||
|
BIP9GBTStatus::Info gbtinfo{.bit=params.vDeployments[pos].bit, .mask=checker.Mask(), .gbt_force=vbdepinfo.gbt_force};
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case DEFINED:
|
||||||
|
case FAILED:
|
||||||
|
// Not exposed to GBT
|
||||||
|
break;
|
||||||
|
case STARTED:
|
||||||
|
result.signalling.try_emplace(vbdepinfo.name, gbtinfo);
|
||||||
|
break;
|
||||||
|
case LOCKED_IN:
|
||||||
|
result.locked_in.try_emplace(vbdepinfo.name, gbtinfo);
|
||||||
|
break;
|
||||||
|
case ACTIVE:
|
||||||
|
result.active.try_emplace(vbdepinfo.name, gbtinfo);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|
|
@ -66,6 +66,15 @@ struct BIP9Info {
|
||||||
std::optional<int> active_since;
|
std::optional<int> active_since;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BIP9GBTStatus {
|
||||||
|
struct Info {
|
||||||
|
int bit;
|
||||||
|
uint32_t mask;
|
||||||
|
bool gbt_force;
|
||||||
|
};
|
||||||
|
std::map<std::string, const Info, std::less<>> signalling, locked_in, active;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class that implements BIP9-style threshold logic, and caches results.
|
* Abstract class that implements BIP9-style threshold logic, and caches results.
|
||||||
*/
|
*/
|
||||||
|
@ -109,6 +118,8 @@ public:
|
||||||
|
|
||||||
BIP9Info Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
BIP9Info Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
|
||||||
|
|
||||||
|
BIP9GBTStatus GBTStatus(const CBlockIndex& block_index, const Consensus::Params& params) 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