dash/src/versionbits.cpp

224 lines
8.6 KiB
C++
Raw Normal View History

// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "versionbits.h"
Align with btc 0.12 (#1409) * Implement BIP 9 GBT changes - BIP9DeploymentInfo struct for static deployment info - VersionBitsDeploymentInfo: Avoid C++11ism by commenting parameter names - getblocktemplate: Make sure to set deployments in the version if it is LOCKED_IN - In this commit, all rules are considered required for clients to support * qa/rpc-tests: bip9-softforks: Add tests for getblocktemplate versionbits updates * getblocktemplate: Explicitly handle the distinction between GBT-affecting softforks vs not * getblocktemplate: Use version/force mutation to support pre-BIP9 clients * Don't use floating point Github-Pull: #8317 Rebased-From: 477777f2503e3a56a267556f0fc5091042d93340 * Send tip change notification from invalidateblock This change is needed to prevent sync_blocks timeouts in the mempool_reorg test after the sync_blocks update in the upcoming commit "[qa] Change sync_blocks to pick smarter maxheight". This change was initially suggested by Suhas Daftuar <sdaftuar@chaincode.com> in https://github.com/bitcoin/bitcoin/pull/8680#r78209060 Github-Pull: #9196 Rebased-From: 67c6326abd1788e6f411feb4f44b69774e76aae2 * torcontrol: Explicitly request RSA1024 private key When generating a new service key, explicitly request a RSA1024 one. The bitcoin P2P protocol has no support for the longer hidden service names that will come with ed25519 keys, until it does, we depend on the old hidden service type so make this explicit. See #9214. Github-Pull: #9234 Rebased-From: 7d3b627395582ae7c9d54ebdbc68096d7042162b * Bugfix: FRT: don't terminate when keypool is empty Github-Pull: #9295 Rebased-From: c24a4f5981d47d55aa9e4eb40294832a4d38fb80 * add fundrawtransaction test on a locked wallet with empty keypool Github-Pull: #9295 Rebased-From: 1a6eacbf3b7e3d5941fec1154079bbc4678ce861
2017-04-11 12:53:54 +02:00
#include "consensus/params.h"
const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
{
/*.name =*/ "testdummy",
/*.gbt_force =*/ true,
/*.check_mn_protocol =*/ false,
Align with btc 0.12 (#1409) * Implement BIP 9 GBT changes - BIP9DeploymentInfo struct for static deployment info - VersionBitsDeploymentInfo: Avoid C++11ism by commenting parameter names - getblocktemplate: Make sure to set deployments in the version if it is LOCKED_IN - In this commit, all rules are considered required for clients to support * qa/rpc-tests: bip9-softforks: Add tests for getblocktemplate versionbits updates * getblocktemplate: Explicitly handle the distinction between GBT-affecting softforks vs not * getblocktemplate: Use version/force mutation to support pre-BIP9 clients * Don't use floating point Github-Pull: #8317 Rebased-From: 477777f2503e3a56a267556f0fc5091042d93340 * Send tip change notification from invalidateblock This change is needed to prevent sync_blocks timeouts in the mempool_reorg test after the sync_blocks update in the upcoming commit "[qa] Change sync_blocks to pick smarter maxheight". This change was initially suggested by Suhas Daftuar <sdaftuar@chaincode.com> in https://github.com/bitcoin/bitcoin/pull/8680#r78209060 Github-Pull: #9196 Rebased-From: 67c6326abd1788e6f411feb4f44b69774e76aae2 * torcontrol: Explicitly request RSA1024 private key When generating a new service key, explicitly request a RSA1024 one. The bitcoin P2P protocol has no support for the longer hidden service names that will come with ed25519 keys, until it does, we depend on the old hidden service type so make this explicit. See #9214. Github-Pull: #9234 Rebased-From: 7d3b627395582ae7c9d54ebdbc68096d7042162b * Bugfix: FRT: don't terminate when keypool is empty Github-Pull: #9295 Rebased-From: c24a4f5981d47d55aa9e4eb40294832a4d38fb80 * add fundrawtransaction test on a locked wallet with empty keypool Github-Pull: #9295 Rebased-From: 1a6eacbf3b7e3d5941fec1154079bbc4678ce861
2017-04-11 12:53:54 +02:00
},
{
/*.name =*/ "csv",
/*.gbt_force =*/ true,
/*.check_mn_protocol =*/ false,
},
{
/*.name =*/ "dip0001",
/*.gbt_force =*/ true,
/*.check_mn_protocol =*/ true,
2018-01-30 20:18:51 +01:00
},
{
/*.name =*/ "bip147",
/*.gbt_force =*/ true,
/*.check_mn_protocol =*/ false,
2018-02-14 21:31:42 +01:00
},
{
/*.name =*/ "dip0003",
/*.gbt_force =*/ true,
/*.check_mn_protocol =*/ false,
},
{
/*.name =*/ "dip0008",
/*.gbt_force =*/ true,
/*.check_mn_protocol =*/ false,
Align with btc 0.12 (#1409) * Implement BIP 9 GBT changes - BIP9DeploymentInfo struct for static deployment info - VersionBitsDeploymentInfo: Avoid C++11ism by commenting parameter names - getblocktemplate: Make sure to set deployments in the version if it is LOCKED_IN - In this commit, all rules are considered required for clients to support * qa/rpc-tests: bip9-softforks: Add tests for getblocktemplate versionbits updates * getblocktemplate: Explicitly handle the distinction between GBT-affecting softforks vs not * getblocktemplate: Use version/force mutation to support pre-BIP9 clients * Don't use floating point Github-Pull: #8317 Rebased-From: 477777f2503e3a56a267556f0fc5091042d93340 * Send tip change notification from invalidateblock This change is needed to prevent sync_blocks timeouts in the mempool_reorg test after the sync_blocks update in the upcoming commit "[qa] Change sync_blocks to pick smarter maxheight". This change was initially suggested by Suhas Daftuar <sdaftuar@chaincode.com> in https://github.com/bitcoin/bitcoin/pull/8680#r78209060 Github-Pull: #9196 Rebased-From: 67c6326abd1788e6f411feb4f44b69774e76aae2 * torcontrol: Explicitly request RSA1024 private key When generating a new service key, explicitly request a RSA1024 one. The bitcoin P2P protocol has no support for the longer hidden service names that will come with ed25519 keys, until it does, we depend on the old hidden service type so make this explicit. See #9214. Github-Pull: #9234 Rebased-From: 7d3b627395582ae7c9d54ebdbc68096d7042162b * Bugfix: FRT: don't terminate when keypool is empty Github-Pull: #9295 Rebased-From: c24a4f5981d47d55aa9e4eb40294832a4d38fb80 * add fundrawtransaction test on a locked wallet with empty keypool Github-Pull: #9295 Rebased-From: 1a6eacbf3b7e3d5941fec1154079bbc4678ce861
2017-04-11 12:53:54 +02:00
}
};
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
{
int nPeriod = Period(params);
int nThreshold = Threshold(params);
int64_t nTimeStart = BeginTime(params);
int64_t nTimeTimeout = EndTime(params);
// A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
if (pindexPrev != NULL) {
pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
}
// Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
std::vector<const CBlockIndex*> vToCompute;
while (cache.count(pindexPrev) == 0) {
if (pindexPrev == NULL) {
// The genesis block is by definition defined.
cache[pindexPrev] = THRESHOLD_DEFINED;
break;
}
if (pindexPrev->GetMedianTimePast() < nTimeStart) {
// Optimization: don't recompute down further, as we know every earlier block will be before the start time
cache[pindexPrev] = THRESHOLD_DEFINED;
break;
}
vToCompute.push_back(pindexPrev);
pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
}
// At this point, cache[pindexPrev] is known
assert(cache.count(pindexPrev));
ThresholdState state = cache[pindexPrev];
// Now walk forward and compute the state of descendants of pindexPrev
while (!vToCompute.empty()) {
ThresholdState stateNext = state;
pindexPrev = vToCompute.back();
vToCompute.pop_back();
switch (state) {
case THRESHOLD_DEFINED: {
if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
stateNext = THRESHOLD_FAILED;
} else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
stateNext = THRESHOLD_STARTED;
}
break;
}
case THRESHOLD_STARTED: {
if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
stateNext = THRESHOLD_FAILED;
break;
}
// We need to count
const CBlockIndex* pindexCount = pindexPrev;
int count = 0;
for (int i = 0; i < nPeriod; i++) {
if (Condition(pindexCount, params)) {
count++;
}
pindexCount = pindexCount->pprev;
}
if (count >= nThreshold) {
stateNext = THRESHOLD_LOCKED_IN;
}
break;
}
case THRESHOLD_LOCKED_IN: {
// Always progresses into ACTIVE.
stateNext = THRESHOLD_ACTIVE;
break;
}
case THRESHOLD_FAILED:
case THRESHOLD_ACTIVE: {
// Nothing happens, these are terminal states.
break;
}
}
cache[pindexPrev] = state = stateNext;
}
return state;
}
int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
{
const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
// BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
if (initialState == THRESHOLD_DEFINED) {
return 0;
}
const int nPeriod = Period(params);
// A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
// To ease understanding of the following height calculation, it helps to remember that
// right now pindexPrev points to the block prior to the block that we are computing for, thus:
// if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
// if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
// The parent of the genesis block is represented by NULL.
pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
while (previousPeriodParent != NULL && GetStateFor(previousPeriodParent, params, cache) == initialState) {
pindexPrev = previousPeriodParent;
previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
}
// Adjust the result because right now we point to the parent block.
return pindexPrev->nHeight + 1;
}
int AbstractThresholdConditionChecker::CountBlocksInWindow(const CBlockIndex* pindex, const Consensus::Params& params) const
{
int nPeriod = Period(params);
int nStopHeight = pindex->nHeight - (pindex->nHeight % nPeriod) - 1;
const CBlockIndex* pindexCount = pindex;
int count = 0;
while (pindexCount && pindexCount->nHeight != nStopHeight) {
if (Condition(pindexCount, params)) {
count++;
}
pindexCount = pindexCount->pprev;
}
return count;
}
namespace
{
/**
* Class to implement versionbits logic.
*/
class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
private:
const Consensus::DeploymentPos id;
protected:
int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
int64_t EndTime(const Consensus::Params& params) const override { return params.vDeployments[id].nTimeout; }
int Period(const Consensus::Params& params) const override { return params.vDeployments[id].nWindowSize ? params.vDeployments[id].nWindowSize : params.nMinerConfirmationWindow; }
int Threshold(const Consensus::Params& params) const override { return params.vDeployments[id].nThreshold ? params.vDeployments[id].nThreshold : params.nRuleChangeActivationThreshold; }
bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
{
return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
}
public:
VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
};
}
ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
{
return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
}
int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
{
return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]);
}
int VersionBitsCountBlocksInWindow(const CBlockIndex* pindex, const Consensus::Params& params, Consensus::DeploymentPos pos)
{
return VersionBitsConditionChecker(pos).CountBlocksInWindow(pindex, params);
}
uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos)
{
return VersionBitsConditionChecker(pos).Mask(params);
}
void VersionBitsCache::Clear()
{
for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
caches[d].clear();
}
}