Skip to content

Commit 1198e7d

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

File tree

3 files changed

+72
-41
lines changed

3 files changed

+72
-41
lines changed

src/rpc/mining.cpp

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -565,10 +565,10 @@ static UniValue BIP22ValidationResult(const BlockValidationState& state)
565565
return "valid?";
566566
}
567567

568-
static std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
569-
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
570-
std::string s = vbinfo.name;
571-
if (!vbinfo.gbt_force) {
568+
static std::string gbt_force_name(const std::string& name, bool gbt_force)
569+
{
570+
std::string s{name};
571+
if (!gbt_force) {
572572
s.insert(s.begin(), '!');
573573
}
574574
return s;
@@ -898,45 +898,33 @@ static RPCHelpMan getblocktemplate()
898898
}
899899

900900
UniValue vbavailable(UniValue::VOBJ);
901-
for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
902-
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
903-
ThresholdState state = chainman.m_versionbitscache.State(pindexPrev, consensusParams, pos);
904-
switch (state) {
905-
case ThresholdState::DEFINED:
906-
case ThresholdState::FAILED:
907-
// Not exposed to GBT at all
908-
break;
909-
case ThresholdState::LOCKED_IN:
910-
// Ensure bit is set in block version
911-
block.nVersion |= chainman.m_versionbitscache.Mask(consensusParams, pos);
912-
[[fallthrough]];
913-
case ThresholdState::STARTED:
914-
{
915-
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
916-
vbavailable.pushKV(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit);
917-
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
918-
if (!vbinfo.gbt_force) {
919-
// If the client doesn't support this, don't indicate it in the [default] version
920-
block.nVersion &= ~chainman.m_versionbitscache.Mask(consensusParams, pos);
921-
}
922-
}
923-
break;
924-
}
925-
case ThresholdState::ACTIVE:
926-
{
927-
// Add to rules only
928-
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
929-
aRules.push_back(gbt_vb_name(pos));
930-
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
931-
// Not supported by the client; make sure it's safe to proceed
932-
if (!vbinfo.gbt_force) {
933-
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name));
934-
}
935-
}
936-
break;
937-
}
901+
const auto gbtstatus = chainman.m_versionbitscache.GBTStatus(*pindexPrev, consensusParams);
902+
903+
for (const auto& [name, info] : gbtstatus.signalling) {
904+
vbavailable.pushKV(gbt_force_name(name, info.gbt_force), info.bit);
905+
if (!info.gbt_force && !setClientRules.count(name)) {
906+
// If the client doesn't support this, don't indicate it in the [default] version
907+
block.nVersion &= ~info.mask;
938908
}
939909
}
910+
911+
for (const auto& [name, info] : gbtstatus.locked_in) {
912+
block.nVersion |= info.mask;
913+
vbavailable.pushKV(gbt_force_name(name, info.gbt_force), info.bit);
914+
if (!info.gbt_force && !setClientRules.count(name)) {
915+
// If the client doesn't support this, don't indicate it in the [default] version
916+
block.nVersion &= ~info.mask;
917+
}
918+
}
919+
920+
for (const auto& [name, info] : gbtstatus.active) {
921+
aRules.push_back(gbt_force_name(name, info.gbt_force));
922+
if (!info.gbt_force && !setClientRules.count(name)) {
923+
// Not supported by the client; make sure it's safe to proceed
924+
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", name));
925+
}
926+
}
927+
940928
result.pushKV("version", block.nVersion);
941929
result.pushKV("rules", std::move(aRules));
942930
result.pushKV("vbavailable", std::move(vbavailable));

src/versionbits.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <consensus/params.h>
6+
#include <deploymentinfo.h>
67
#include <kernel/chainparams.h>
78
#include <util/check.h>
89
#include <versionbits.h>
@@ -246,6 +247,37 @@ BIP9Info VersionBitsCache::Info(const CBlockIndex& block_index, const Consensus:
246247
return result;
247248
}
248249

250+
BIP9GBTStatus VersionBitsCache::GBTStatus(const CBlockIndex& block_index, const Consensus::Params& params)
251+
{
252+
BIP9GBTStatus result;
253+
254+
LOCK(m_mutex);
255+
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
256+
auto pos = static_cast<Consensus::DeploymentPos>(i);
257+
VersionBitsConditionChecker checker(params, pos);
258+
ThresholdState state = checker.GetStateFor(&block_index, m_caches[pos]);
259+
const VBDeploymentInfo& vbdepinfo = VersionBitsDeploymentInfo[pos];
260+
BIP9GBTStatus::Info gbtinfo{.bit=params.vDeployments[pos].bit, .mask=checker.Mask(), .gbt_force=vbdepinfo.gbt_force};
261+
262+
switch (state) {
263+
case DEFINED:
264+
case FAILED:
265+
// Not exposed to GBT
266+
break;
267+
case STARTED:
268+
result.signalling.try_emplace(vbdepinfo.name, gbtinfo);
269+
break;
270+
case LOCKED_IN:
271+
result.locked_in.try_emplace(vbdepinfo.name, gbtinfo);
272+
break;
273+
case ACTIVE:
274+
result.active.try_emplace(vbdepinfo.name, gbtinfo);
275+
break;
276+
}
277+
}
278+
return result;
279+
}
280+
249281
ThresholdState VersionBitsCache::State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
250282
{
251283
LOCK(m_mutex);

src/versionbits.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ struct BIP9Info {
6666
std::optional<int> active_since;
6767
};
6868

69+
struct BIP9GBTStatus {
70+
struct Info {
71+
int bit;
72+
uint32_t mask;
73+
bool gbt_force;
74+
};
75+
std::map<std::string, const Info, std::less<>> signalling, locked_in, active;
76+
};
77+
6978
/**
7079
* Abstract class that implements BIP9-style threshold logic, and caches results.
7180
*/
@@ -109,6 +118,8 @@ class VersionBitsCache
109118

110119
BIP9Info Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
111120

121+
BIP9GBTStatus GBTStatus(const CBlockIndex& block_index, const Consensus::Params& params) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
122+
112123
/** Get the BIP9 state for a given deployment for the block after pindexPrev. */
113124
ThresholdState State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
114125

0 commit comments

Comments
 (0)