Merge #16060: Bury bip9 deployments

e78aaf41f4 [docs] Add release notes for burying bip 9 soft fork deployments (John Newbery)
8319e738f9 [tests] Add coverage for the content of getblockchaininfo.softforks (James O'Beirne)
0328dcdcfc [Consensus] Bury segwit deployment (John Newbery)
1c93b9b31c [Consensus] Bury CSV deployment height (John Newbery)
3862e473f0 [rpc] Tidy up reporting of buried and ongoing softforks (John Newbery)

Pull request description:

  This hardcodes CSV and segwit activation heights, similar to the BIP 90 buried deployments for BIPs 34, 65 and 66.

  CSV and segwit have been active for over 18 months. Hardcoding the activation height is a code simplification, makes it easier to understand segwit activation status, and reduces technical debt.

  This was originally attempted by jl2012 in #11398 and again by me in #12360.

ACKs for top commit:
  ajtowns:
    ACK e78aaf41f4 ; checked diff to previous acked commit, checked tests still work
  ariard:
    ACK e78aaf4, check diff, run the tests again and successfully activated csv/segwit heights on mainnet as expected.
  MarcoFalke:
    ACK e78aaf41f4 (still didn't check if the mainnet block heights are correct, but the code looks good now)

Tree-SHA512: 7e951829106e21a81725f7d3e236eddbb59349189740907bb47e33f5dbf95c43753ac1231f47ae7bee85c8c81b2146afcdfdc11deb1503947f23093a9c399912
This commit is contained in:
MarcoFalke 2019-08-15 16:02:02 -04:00
commit 1bf2ff2bf8
No known key found for this signature in database
GPG key ID: CE2B75697E69A548
21 changed files with 242 additions and 306 deletions

View file

@ -0,0 +1,15 @@
Low-level RPC changes
----------------------
- Soft fork reporting in the `getblockchaininfo` return object has been
updated. For full details, see the RPC help text. In summary:
- The `bip9_softforks` sub-object is no longer returned
- The `softforks` sub-object now returns an object keyed by soft fork name,
rather than an array
- Each softfork object in the `softforks` object contains a `type` value which
is either `buried` (for soft fork deployments where the activation height is
hard-coded into the client implementation), or `bip9` (for soft fork deployments
where activation is controlled by BIP 9 signaling).
- `getblocktemplate` no longer returns a `rules` array containing `CSV`
and `segwit` (the BIP 9 deployments that are currently in active state).

View file

@ -69,6 +69,8 @@ public:
consensus.BIP34Hash = uint256S("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8");
consensus.BIP65Height = 388381; // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0
consensus.BIP66Height = 363725; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931
consensus.CSVHeight = 419328; // 000000000000000004a1b34462cb8aeebd5799177f7a29cf28f2d1961716b5b5
consensus.SegwitHeight = 481824; // 0000000000000000001c8018d9cb3b742ef25114f27563e3fc4a1902167f9893
consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
@ -80,16 +82,6 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008
// Deployment of BIP68, BIP112, and BIP113.
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
// Deployment of SegWit (BIP141, BIP143, and BIP147)
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1479168000; // November 15th, 2016.
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017.
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000051dc8b82f450202ecb3d471");
@ -183,6 +175,8 @@ public:
consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8");
consensus.BIP65Height = 581885; // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6
consensus.BIP66Height = 330776; // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182
consensus.CSVHeight = 770112; // 00000000025e930139bac5c6c31a403776da130831ab85be56578f3fa75369bb
consensus.SegwitHeight = 834624; // 00000000002b980fcd729daaa248fd9316a5200e9b367f4ff2c42453e84201ca
consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
@ -194,16 +188,6 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008
// Deployment of BIP68, BIP112, and BIP113.
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
// Deployment of SegWit (BIP141, BIP143, and BIP147)
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1462060800; // May 1st 2016
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1493596800; // May 1st 2017
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000007dbe94253893cbd463");
@ -275,6 +259,8 @@ public:
consensus.BIP34Hash = uint256();
consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in functional tests)
consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in functional tests)
consensus.CSVHeight = 432; // CSV activated on regtest (Used in rpc activation tests)
consensus.SegwitHeight = 0; // SEGWIT is always activated on regtest unless overridden
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
@ -285,12 +271,6 @@ public:
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_CSV].bit = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00");
@ -307,7 +287,7 @@ public:
m_assumed_blockchain_size = 0;
m_assumed_chain_state_size = 0;
UpdateVersionBitsParametersFromArgs(args);
UpdateActivationParametersFromArgs(args);
genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
@ -350,11 +330,22 @@ public:
consensus.vDeployments[d].nStartTime = nStartTime;
consensus.vDeployments[d].nTimeout = nTimeout;
}
void UpdateVersionBitsParametersFromArgs(const ArgsManager& args);
void UpdateActivationParametersFromArgs(const ArgsManager& args);
};
void CRegTestParams::UpdateVersionBitsParametersFromArgs(const ArgsManager& args)
void CRegTestParams::UpdateActivationParametersFromArgs(const ArgsManager& args)
{
if (gArgs.IsArgSet("-segwitheight")) {
int64_t height = gArgs.GetArg("-segwitheight", consensus.SegwitHeight);
if (height < -1 || height >= std::numeric_limits<int>::max()) {
throw std::runtime_error(strprintf("Activation height %ld for segwit is out of valid range. Use -1 to disable segwit.", height));
} else if (height == -1) {
LogPrintf("Segwit disabled for testing\n");
height = std::numeric_limits<int>::max();
}
consensus.SegwitHeight = static_cast<int>(height);
}
if (!args.IsArgSet("-vbparams")) return;
for (const std::string& strDeployment : args.GetArgs("-vbparams")) {

View file

@ -19,6 +19,7 @@ void SetupChainParamsBaseOptions()
{
gArgs.AddArg("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
"This is intended for regression testing tools and app development.", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-segwitheight=<n>", "Set the activation height of segwit. -1 to disable. (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-testnet", "Use the test chain", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
}

View file

@ -16,8 +16,6 @@ namespace Consensus {
enum DeploymentPos
{
DEPLOYMENT_TESTDUMMY,
DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
DEPLOYMENT_SEGWIT, // Deployment of BIP141, BIP143, and BIP147.
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp
MAX_VERSION_BITS_DEPLOYMENTS
};
@ -58,6 +56,12 @@ struct Params {
int BIP65Height;
/** Block height at which BIP66 becomes active */
int BIP66Height;
/** Block height at which CSV (BIP68, BIP112 and BIP113) becomes active */
int CSVHeight;
/** Block height at which Segwit (BIP141, BIP143 and BIP147) becomes active.
* Note that segwit v0 script rules are enforced on all blocks except the
* BIP 16 exception blocks. */
int SegwitHeight;
/**
* Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period,
* (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments.

View file

@ -1678,12 +1678,9 @@ bool AppInitMain(InitInterfaces& interfaces)
}
}
if (chainparams.GetConsensus().vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0) {
// Only advertise witness capabilities if they have a reasonable start time.
// This allows us to have the code merged without a defined softfork, by setting its
// end time to 0.
// Note that setting NODE_WITNESS is never required: the only downside from not
// doing so is that after activation, no upgraded nodes will fetch from you.
if (chainparams.GetConsensus().SegwitHeight != std::numeric_limits<int>::max()) {
// Advertise witness capabilities.
// The option to not set NODE_WITNESS is only used in the tests and should be removed.
nLocalServices = ServiceFlags(nLocalServices | NODE_WITNESS);
}

View file

@ -1188,54 +1188,49 @@ static UniValue verifychain(const JSONRPCRequest& request)
Params(), &::ChainstateActive().CoinsTip(), nCheckLevel, nCheckDepth);
}
/** Implementation of IsSuperMajority with better feedback */
static UniValue SoftForkMajorityDesc(int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
static void BuriedForkDescPushBack(UniValue& softforks, const std::string &name, int height) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
// For buried deployments.
// A buried deployment is one where the height of the activation has been hardcoded into
// the client implementation long after the consensus change has activated. See BIP 90.
// Buried deployments with activation height value of
// std::numeric_limits<int>::max() are disabled and thus hidden.
if (height == std::numeric_limits<int>::max()) return;
UniValue rv(UniValue::VOBJ);
bool activated = false;
switch(version)
{
case 2:
activated = pindex->nHeight >= consensusParams.BIP34Height;
break;
case 3:
activated = pindex->nHeight >= consensusParams.BIP66Height;
break;
case 4:
activated = pindex->nHeight >= consensusParams.BIP65Height;
break;
}
rv.pushKV("status", activated);
return rv;
rv.pushKV("type", "buried");
// getblockchaininfo reports the softfork as active from when the chain height is
// one below the activation height
rv.pushKV("active", ::ChainActive().Tip()->nHeight + 1 >= height);
rv.pushKV("height", height);
softforks.pushKV(name, rv);
}
static UniValue SoftForkDesc(const std::string &name, int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
static void BIP9SoftForkDescPushBack(UniValue& softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
UniValue rv(UniValue::VOBJ);
rv.pushKV("id", name);
rv.pushKV("version", version);
rv.pushKV("reject", SoftForkMajorityDesc(version, pindex, consensusParams));
return rv;
}
// For BIP9 deployments.
// Deployments (e.g. testdummy) with timeout value before Jan 1, 2009 are hidden.
// A timeout value of 0 guarantees a softfork will never be activated.
// This is used when merging logic to implement a proposed softfork without a specified deployment schedule.
if (consensusParams.vDeployments[id].nTimeout <= 1230768000) return;
static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
{
UniValue rv(UniValue::VOBJ);
UniValue bip9(UniValue::VOBJ);
const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
switch (thresholdState) {
case ThresholdState::DEFINED: rv.pushKV("status", "defined"); break;
case ThresholdState::STARTED: rv.pushKV("status", "started"); break;
case ThresholdState::LOCKED_IN: rv.pushKV("status", "locked_in"); break;
case ThresholdState::ACTIVE: rv.pushKV("status", "active"); break;
case ThresholdState::FAILED: rv.pushKV("status", "failed"); break;
case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break;
case ThresholdState::STARTED: bip9.pushKV("status", "started"); break;
case ThresholdState::LOCKED_IN: bip9.pushKV("status", "locked_in"); break;
case ThresholdState::ACTIVE: bip9.pushKV("status", "active"); break;
case ThresholdState::FAILED: bip9.pushKV("status", "failed"); break;
}
if (ThresholdState::STARTED == thresholdState)
{
rv.pushKV("bit", consensusParams.vDeployments[id].bit);
bip9.pushKV("bit", consensusParams.vDeployments[id].bit);
}
rv.pushKV("startTime", consensusParams.vDeployments[id].nStartTime);
rv.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
rv.pushKV("since", VersionBitsTipStateSinceHeight(consensusParams, id));
bip9.pushKV("startTime", consensusParams.vDeployments[id].nStartTime);
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
int64_t since_height = VersionBitsTipStateSinceHeight(consensusParams, id);
bip9.pushKV("since", since_height);
if (ThresholdState::STARTED == thresholdState)
{
UniValue statsUV(UniValue::VOBJ);
@ -1245,18 +1240,18 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse
statsUV.pushKV("elapsed", statsStruct.elapsed);
statsUV.pushKV("count", statsStruct.count);
statsUV.pushKV("possible", statsStruct.possible);
rv.pushKV("statistics", statsUV);
}
return rv;
bip9.pushKV("statistics", statsUV);
}
static void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
{
// Deployments with timeout value of 0 are hidden.
// A timeout value of 0 guarantees a softfork will never be activated.
// This is used when softfork codes are merged without specifying the deployment schedule.
if (consensusParams.vDeployments[id].nTimeout > 0)
bip9_softforks.pushKV(VersionBitsDeploymentInfo[id].name, BIP9SoftForkDesc(consensusParams, id));
UniValue rv(UniValue::VOBJ);
rv.pushKV("type", "bip9");
rv.pushKV("bip9", bip9);
if (ThresholdState::ACTIVE == thresholdState) {
rv.pushKV("height", since_height);
}
rv.pushKV("active", ThresholdState::ACTIVE == thresholdState);
softforks.pushKV(name, rv);
}
UniValue getblockchaininfo(const JSONRPCRequest& request)
@ -1280,29 +1275,25 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
" \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n"
" \"automatic_pruning\": xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n"
" \"prune_target_size\": xxxxxx, (numeric) the target size used by pruning (only present if automatic pruning is enabled)\n"
" \"softforks\": [ (array) status of softforks in progress\n"
" {\n"
" \"id\": \"xxxx\", (string) name of softfork\n"
" \"version\": xx, (numeric) block version\n"
" \"reject\": { (object) progress toward rejecting pre-softfork blocks\n"
" \"status\": xx, (boolean) true if threshold reached\n"
" },\n"
" }, ...\n"
" ],\n"
" \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n"
" \"softforks\": { (object) status of softforks\n"
" \"xxxx\" : { (string) name of the softfork\n"
" \"type\": \"xxxx\", (string) one of \"buried\", \"bip9\"\n"
" \"bip9\": { (object) status of bip9 softforks (only for \"bip9\" type)\n"
" \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n"
" \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n"
" \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n"
" \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n"
" \"since\": xx, (numeric) height of the first block to which the status applies\n"
" \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n"
" \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork\n"
" \"period\": xx, (numeric) the length in blocks of the BIP9 signalling period \n"
" \"threshold\": xx, (numeric) the number of blocks with the version bit set required to activate the feature \n"
" \"elapsed\": xx, (numeric) the number of blocks elapsed since the beginning of the current period \n"
" \"count\": xx, (numeric) the number of blocks with the version bit set in the current period \n"
" \"possible\": xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n"
" }\n"
" },\n"
" \"height\": \"xxxxxx\", (numeric) height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)\n"
" \"active\": xx, (boolean) true if the rules are enforced for the mempool and the next block\n"
" }\n"
" }\n"
" \"warnings\" : \"...\", (string) any network and blockchain warnings.\n"
@ -1347,16 +1338,14 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
}
const Consensus::Params& consensusParams = Params().GetConsensus();
UniValue softforks(UniValue::VARR);
UniValue bip9_softforks(UniValue::VOBJ);
softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
for (int pos = Consensus::DEPLOYMENT_CSV; pos != Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++pos) {
BIP9SoftForkDescPushBack(bip9_softforks, consensusParams, static_cast<Consensus::DeploymentPos>(pos));
}
UniValue softforks(UniValue::VOBJ);
BuriedForkDescPushBack(softforks, "bip34", consensusParams.BIP34Height);
BuriedForkDescPushBack(softforks, "bip66", consensusParams.BIP66Height);
BuriedForkDescPushBack(softforks, "bip65", consensusParams.BIP65Height);
BuriedForkDescPushBack(softforks, "csv", consensusParams.CSVHeight);
BuriedForkDescPushBack(softforks, "segwit", consensusParams.SegwitHeight);
BIP9SoftForkDescPushBack(softforks, "testdummy", consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
obj.pushKV("softforks", softforks);
obj.pushKV("bip9_softforks", bip9_softforks);
obj.pushKV("warnings", GetWarnings("statusbar"));
return obj;

View file

@ -482,9 +482,8 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
// TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
}
const struct VBDeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
// GBT must be called with 'segwit' set in the rules
if (setClientRules.count(segwit_info.name) != 1) {
if (setClientRules.count("segwit") != 1) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "getblocktemplate must be called with the segwit rule set (call with {\"rules\": [\"segwit\"]})");
}
@ -521,7 +520,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
pblock->nNonce = 0;
// NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
const bool fPreSegWit = (ThresholdState::ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache));
const bool fPreSegWit = (pindexPrev->nHeight + 1 < consensusParams.SegwitHeight);
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");

View file

@ -125,7 +125,7 @@ TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
{
// CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests.
// TODO: fix the code to support SegWit blocks.
gArgs.ForceSetArg("-vbparams", strprintf("segwit:0:%d", (int64_t)Consensus::BIP9Deployment::NO_TIMEOUT));
gArgs.ForceSetArg("-segwitheight", "432");
SelectParams(CBaseChainParams::REGTEST);
// Generate a 100-block chain:

View file

@ -1648,7 +1648,7 @@ static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_
// environment. See test/functional/p2p-segwit.py.
static bool IsScriptWitnessEnabled(const Consensus::Params& params)
{
return params.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0;
return params.SegwitHeight != std::numeric_limits<int>::max();
}
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
@ -1684,12 +1684,13 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
}
// Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
if (VersionBitsState(pindex->pprev, consensusparams, Consensus::DEPLOYMENT_CSV, versionbitscache) == ThresholdState::ACTIVE) {
// Start enforcing BIP112 (CHECKSEQUENCEVERIFY)
if (pindex->nHeight >= consensusparams.CSVHeight) {
flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
}
if (IsNullDummyEnabled(pindex->pprev, consensusparams)) {
// Start enforcing BIP147 NULLDUMMY (activated simultaneously with segwit)
if (IsWitnessEnabled(pindex->pprev, consensusparams)) {
flags |= SCRIPT_VERIFY_NULLDUMMY;
}
@ -1874,9 +1875,9 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
}
}
// Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
// Start enforcing BIP68 (sequence locks)
int nLockTimeFlags = 0;
if (VersionBitsState(pindex->pprev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV, versionbitscache) == ThresholdState::ACTIVE) {
if (pindex->nHeight >= chainparams.GetConsensus().CSVHeight) {
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE;
}
@ -3088,14 +3089,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
{
LOCK(cs_main);
return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == ThresholdState::ACTIVE);
}
bool IsNullDummyEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
{
LOCK(cs_main);
return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == ThresholdState::ACTIVE);
int height = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
return (height >= params.SegwitHeight);
}
// Compute at which vout of the block's coinbase transaction the witness
@ -3130,7 +3125,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
std::vector<unsigned char> commitment;
int commitpos = GetWitnessCommitmentIndex(block);
std::vector<unsigned char> ret(32, 0x00);
if (consensusParams.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0) {
if (consensusParams.SegwitHeight != std::numeric_limits<int>::max()) {
if (commitpos == -1) {
uint256 witnessroot = BlockWitnessMerkleRoot(block, nullptr);
CHash256().Write(witnessroot.begin(), 32).Write(ret.data(), 32).Finalize(witnessroot.begin());
@ -3228,9 +3223,9 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
{
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
// Start enforcing BIP113 (Median Time Past) using versionbits logic.
// Start enforcing BIP113 (Median Time Past).
int nLockTimeFlags = 0;
if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV, versionbitscache) == ThresholdState::ACTIVE) {
if (nHeight >= consensusParams.CSVHeight) {
assert(pindexPrev != nullptr);
nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;
}
@ -3265,7 +3260,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness reserved value). In case there are
// multiple, the last one is used.
bool fHaveWitness = false;
if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == ThresholdState::ACTIVE) {
if (nHeight >= consensusParams.SegwitHeight) {
int commitpos = GetWitnessCommitmentIndex(block);
if (commitpos != -1) {
bool malleated = false;

View file

@ -383,12 +383,10 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
/** Check a block is completely valid from start to finish (only works on top of our current best block) */
bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Check whether witness commitments are required for block. */
/** Check whether witness commitments are required for a block, and whether to enforce NULLDUMMY (BIP 147) rules.
* Note that transaction witness validation rules are always enforced when P2SH is enforced. */
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
/** Check whether NULLDUMMY (BIP 147) has activated. */
bool IsNullDummyEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
/** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */
bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main);

View file

@ -11,12 +11,4 @@ const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_B
/*.name =*/ "testdummy",
/*.gbt_force =*/ true,
},
{
/*.name =*/ "csv",
/*.gbt_force =*/ true,
},
{
/*.name =*/ "segwit",
/*.gbt_force =*/ true,
}
};

View file

@ -14,8 +14,8 @@ from test_framework.util import (
assert_equal,
assert_greater_than,
assert_raises_rpc_error,
get_bip9_status,
satoshi_round,
softfork_active,
)
SEQUENCE_LOCKTIME_DISABLE_FLAG = (1<<31)
@ -52,7 +52,7 @@ class BIP68Test(BitcoinTestFramework):
self.log.info("Running test sequence-lock-unconfirmed-inputs")
self.test_sequence_lock_unconfirmed_inputs()
self.log.info("Running test BIP68 not consensus before versionbits activation")
self.log.info("Running test BIP68 not consensus before activation")
self.test_bip68_not_consensus()
self.log.info("Activating BIP68 (and 112/113)")
@ -336,12 +336,12 @@ class BIP68Test(BitcoinTestFramework):
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1))
self.nodes[0].generate(10)
# Make sure that BIP68 isn't being used to validate blocks, prior to
# versionbits activation. If more blocks are mined prior to this test
# Make sure that BIP68 isn't being used to validate blocks prior to
# activation height. If more blocks are mined prior to this test
# being run, then it's possible the test has activated the soft fork, and
# this test should be moved to run earlier, or deleted.
def test_bip68_not_consensus(self):
assert get_bip9_status(self.nodes[0], 'csv')['status'] != 'active'
assert not softfork_active(self.nodes[0], 'csv')
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
@ -391,9 +391,9 @@ class BIP68Test(BitcoinTestFramework):
height = self.nodes[0].getblockcount()
assert_greater_than(min_activation_height - height, 2)
self.nodes[0].generate(min_activation_height - height - 2)
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], "locked_in")
assert not softfork_active(self.nodes[0], 'csv')
self.nodes[0].generate(1)
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], "active")
assert softfork_active(self.nodes[0], 'csv')
self.sync_blocks()
# Use self.nodes[1] to test that version 2 transactions are standard.

View file

@ -69,14 +69,11 @@ class BIP65Test(BitcoinTestFramework):
self.skip_if_no_wallet()
def test_cltv_info(self, *, is_active):
assert_equal(
next(s for s in self.nodes[0].getblockchaininfo()['softforks'] if s['id'] == 'bip65'),
assert_equal(self.nodes[0].getblockchaininfo()['softforks']['bip65'],
{
"id": "bip65",
"version": 4,
"reject": {
"status": is_active
}
"active": is_active,
"height": CLTV_HEIGHT,
"type": "buried",
},
)
@ -104,9 +101,9 @@ class BIP65Test(BitcoinTestFramework):
block.hashMerkleRoot = block.calc_merkle_root()
block.solve()
self.test_cltv_info(is_active=False)
self.test_cltv_info(is_active=False) # Not active as of current tip and next block does not need to obey rules
self.nodes[0].p2p.send_and_ping(msg_block(block))
self.test_cltv_info(is_active=False) # Not active as of current tip, but next block must obey rules
self.test_cltv_info(is_active=True) # Not active as of current tip, but next block must obey rules
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
self.log.info("Test that blocks must now be at least version 4")
@ -155,7 +152,7 @@ class BIP65Test(BitcoinTestFramework):
block.hashMerkleRoot = block.calc_merkle_root()
block.solve()
self.test_cltv_info(is_active=False) # Not active as of current tip, but next block must obey rules
self.test_cltv_info(is_active=True) # Not active as of current tip, but next block must obey rules
self.nodes[0].p2p.send_and_ping(msg_block(block))
self.test_cltv_info(is_active=True) # Active as of current tip
assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)

View file

@ -2,23 +2,17 @@
# Copyright (c) 2015-2019 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test activation of the first version bits soft fork.
"""Test CSV soft fork activation.
This soft fork will activate the following BIPS:
BIP 68 - nSequence relative lock times
BIP 112 - CHECKSEQUENCEVERIFY
BIP 113 - MedianTimePast semantics for nLockTime
regtest lock-in with 108/144 block signalling
activation after a further 144 blocks
mine 82 blocks whose coinbases will be used to generate inputs for our tests
mine 61 blocks to transition from DEFINED to STARTED
mine 144 blocks only 100 of which are signaling readiness in order to fail to change state this period
mine 144 blocks with 108 signaling and verify STARTED->LOCKED_IN
mine 140 blocks and seed block chain with the 82 inputs will use for our tests at height 572
mine 3 blocks and verify still at LOCKED_IN and test that enforcement has not triggered
mine 1 block and test that enforcement has triggered (which triggers ACTIVE)
mine 345 blocks and seed block chain with the 82 inputs will use for our tests at height 427
mine 2 blocks and verify soft fork not yet activated
mine 1 block and test that soft fork is activated (rules enforced for next block)
Test BIP 113 is enforced
Mine 4 blocks so next height is 580 and test BIP 68 is enforced for time and height
Mine 1 block so next height is 581 and test BIP 68 now passes time but not height
@ -58,11 +52,12 @@ from test_framework.script import (
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
get_bip9_status,
hex_str_to_bytes,
softfork_active,
)
BASE_RELATIVE_LOCKTIME = 10
CSV_ACTIVATION_HEIGHT = 432
SEQ_DISABLE_FLAG = 1 << 31
SEQ_RANDOM_HIGH_BIT = 1 << 25
SEQ_TYPE_FLAG = 1 << 22
@ -148,20 +143,19 @@ class BIP68_112_113Test(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
def generate_blocks(self, number, version, test_blocks=None):
if test_blocks is None:
def generate_blocks(self, number):
test_blocks = []
for i in range(number):
block = self.create_test_block([], version)
block = self.create_test_block([])
test_blocks.append(block)
self.last_block_time += 600
self.tip = block.sha256
self.tipheight += 1
return test_blocks
def create_test_block(self, txs, version=536870912):
def create_test_block(self, txs):
block = create_block(self.tip, create_coinbase(self.tipheight + 1), self.last_block_time + 600)
block.nVersion = version
block.nVersion = 4
block.vtx.extend(txs)
block.hashMerkleRoot = block.calc_merkle_root()
block.rehash()
@ -187,45 +181,14 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.tip = int(self.nodes[0].getbestblockhash(), 16)
self.nodeaddress = self.nodes[0].getnewaddress()
self.log.info("Test that the csv softfork is DEFINED")
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined')
test_blocks = self.generate_blocks(61, 4)
# Activation height is hardcoded
test_blocks = self.generate_blocks(345)
self.send_blocks(test_blocks)
assert not softfork_active(self.nodes[0], 'csv')
self.log.info("Advance from DEFINED to STARTED, height = 143")
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
self.log.info("Fail to achieve LOCKED_IN")
# 100 out of 144 signal bit 0. Use a variety of bits to simulate multiple parallel softforks
test_blocks = self.generate_blocks(50, 536870913) # 0x20000001 (signalling ready)
test_blocks = self.generate_blocks(20, 4, test_blocks) # 0x00000004 (signalling not)
test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready)
test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not)
self.send_blocks(test_blocks)
self.log.info("Failed to advance past STARTED, height = 287")
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
self.log.info("Generate blocks to achieve LOCK-IN")
# 108 out of 144 signal bit 0 to achieve lock-in
# using a variety of bits to simulate multiple parallel softforks
test_blocks = self.generate_blocks(58, 536870913) # 0x20000001 (signalling ready)
test_blocks = self.generate_blocks(26, 4, test_blocks) # 0x00000004 (signalling not)
test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready)
test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not)
self.send_blocks(test_blocks)
self.log.info("Advanced from STARTED to LOCKED_IN, height = 431")
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
# Generate 140 more version 4 blocks
test_blocks = self.generate_blocks(140, 4)
self.send_blocks(test_blocks)
# Inputs at height = 572
# Inputs at height = 431
#
# Put inputs for all tests in the chain at height 572 (tip now = 571) (time increases by 600s per block)
# Put inputs for all tests in the chain at height 431 (tip now = 430) (time increases by 600s per block)
# Note we reuse inputs for v1 and v2 txs so must test these separately
# 16 normal inputs
bip68inputs = []
@ -255,7 +218,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
bip113input = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
self.nodes[0].setmocktime(self.last_block_time + 600)
inputblockhash = self.nodes[0].generate(1)[0] # 1 block generated for inputs to be in chain at height 572
inputblockhash = self.nodes[0].generate(1)[0] # 1 block generated for inputs to be in chain at height 431
self.nodes[0].setmocktime(0)
self.tip = int(inputblockhash, 16)
self.tipheight += 1
@ -263,11 +226,12 @@ class BIP68_112_113Test(BitcoinTestFramework):
assert_equal(len(self.nodes[0].getblock(inputblockhash, True)["tx"]), 82 + 1)
# 2 more version 4 blocks
test_blocks = self.generate_blocks(2, 4)
test_blocks = self.generate_blocks(2)
self.send_blocks(test_blocks)
self.log.info("Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575)")
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
assert_equal(self.tipheight, CSV_ACTIVATION_HEIGHT - 2)
self.log.info("Height = {}, CSV not yet active (will activate for block {}, not {})".format(self.tipheight, CSV_ACTIVATION_HEIGHT, CSV_ACTIVATION_HEIGHT - 1))
assert not softfork_active(self.nodes[0], 'csv')
# Test both version 1 and version 2 transactions for all tests
# BIP113 test transaction will be modified before each use to put in appropriate block time
@ -340,10 +304,11 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.send_blocks([self.create_test_block(success_txs)])
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
# 1 more version 4 block to get us to height 575 so the fork should now be active for the next block
test_blocks = self.generate_blocks(1, 4)
# 1 more version 4 block to get us to height 432 so the fork should now be active for the next block
assert not softfork_active(self.nodes[0], 'csv')
test_blocks = self.generate_blocks(1)
self.send_blocks(test_blocks)
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'active')
assert softfork_active(self.nodes[0], 'csv')
self.log.info("Post-Soft Fork Tests.")
@ -364,8 +329,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.send_blocks([self.create_test_block([bip113tx])])
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
# Next block height = 580 after 4 blocks of random version
test_blocks = self.generate_blocks(4, 1234)
# Next block height = 437 after 4 blocks of random version
test_blocks = self.generate_blocks(4)
self.send_blocks(test_blocks)
self.log.info("BIP 68 tests")
@ -392,8 +357,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
for tx in bip68heighttxs:
self.send_blocks([self.create_test_block([tx])], success=False)
# Advance one block to 581
test_blocks = self.generate_blocks(1, 1234)
# Advance one block to 438
test_blocks = self.generate_blocks(1)
self.send_blocks(test_blocks)
# Height txs should fail and time txs should now pass 9 * 600 > 10 * 512
@ -403,8 +368,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
for tx in bip68heighttxs:
self.send_blocks([self.create_test_block([tx])], success=False)
# Advance one block to 582
test_blocks = self.generate_blocks(1, 1234)
# Advance one block to 439
test_blocks = self.generate_blocks(1)
self.send_blocks(test_blocks)
# All BIP 68 txs should pass

View file

@ -52,14 +52,11 @@ class BIP66Test(BitcoinTestFramework):
self.skip_if_no_wallet()
def test_dersig_info(self, *, is_active):
assert_equal(
next(s for s in self.nodes[0].getblockchaininfo()['softforks'] if s['id'] == 'bip66'),
assert_equal(self.nodes[0].getblockchaininfo()['softforks']['bip66'],
{
"id": "bip66",
"version": 3,
"reject": {
"status": is_active
}
"active": is_active,
"height": DERSIG_HEIGHT,
"type": "buried",
},
)
@ -88,9 +85,9 @@ class BIP66Test(BitcoinTestFramework):
block.rehash()
block.solve()
self.test_dersig_info(is_active=False)
self.test_dersig_info(is_active=False) # Not active as of current tip and next block does not need to obey rules
self.nodes[0].p2p.send_and_ping(msg_block(block))
self.test_dersig_info(is_active=False) # Not active as of current tip, but next block must obey rules
self.test_dersig_info(is_active=True) # Not active as of current tip, but next block must obey rules
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
self.log.info("Test that blocks must now be at least version 3")
@ -144,7 +141,7 @@ class BIP66Test(BitcoinTestFramework):
block.rehash()
block.solve()
self.test_dersig_info(is_active=False) # Not active as of current tip, but next block must obey rules
self.test_dersig_info(is_active=True) # Not active as of current tip, but next block must obey rules
self.nodes[0].p2p.send_and_ping(msg_block(block))
self.test_dersig_info(is_active=True) # Active as of current tip
assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)

View file

@ -41,7 +41,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.setup_clean_chain = True
# This script tests NULLDUMMY activation, which is part of the 'segwit' deployment, so we go through
# normal segwit activation here (and don't use the default always-on behaviour).
self.extra_args = [['-whitelist=127.0.0.1', '-vbparams=segwit:0:999999999999', '-addresstype=legacy']]
self.extra_args = [['-whitelist=127.0.0.1', '-segwitheight=432', '-addresstype=legacy']]
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()

View file

@ -55,20 +55,20 @@ class SegWitTest(BitcoinTestFramework):
[
"-acceptnonstdtxn=1",
"-rpcserialversion=0",
"-vbparams=segwit:0:999999999999",
"-segwitheight=432",
"-addresstype=legacy",
],
[
"-acceptnonstdtxn=1",
"-blockversion=4",
"-rpcserialversion=1",
"-vbparams=segwit:0:999999999999",
"-segwitheight=432",
"-addresstype=legacy",
],
[
"-acceptnonstdtxn=1",
"-blockversion=536870915",
"-vbparams=segwit:0:999999999999",
"-segwitheight=432",
"-addresstype=legacy",
],
]

View file

@ -14,7 +14,7 @@ from test_framework.messages import BlockTransactions, BlockTransactionsRequest,
from test_framework.mininode import mininode_lock, P2PInterface
from test_framework.script import CScript, OP_TRUE, OP_DROP
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, get_bip9_status, wait_until
from test_framework.util import assert_equal, wait_until, softfork_active
# TestP2PConn: A peer we use to send messages to bitcoind, and store responses.
class TestP2PConn(P2PInterface):
@ -803,7 +803,7 @@ class CompactBlocksTest(BitcoinTestFramework):
# We will need UTXOs to construct transactions in later tests.
self.make_utxos()
assert_equal(get_bip9_status(self.nodes[0], "segwit")["status"], 'active')
assert softfork_active(self.nodes[0], "segwit")
self.log.info("Testing SENDCMPCT p2p message... ")
self.test_sendcmpct(self.segwit_node, old_node=self.old_node)

View file

@ -76,7 +76,7 @@ from test_framework.util import (
assert_equal,
connect_nodes,
disconnect_nodes,
get_bip9_status,
softfork_active,
hex_str_to_bytes,
assert_raises_rpc_error,
)
@ -88,6 +88,8 @@ VB_TOP_BITS = 0x20000000
MAX_SIGOP_COST = 80000
SEGWIT_HEIGHT = 120
class UTXO():
"""Used to keep track of anyone-can-spend outputs that we can use in the tests."""
def __init__(self, sha256, n, value):
@ -185,9 +187,9 @@ class SegWitTest(BitcoinTestFramework):
self.num_nodes = 3
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
self.extra_args = [
["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-vbparams=segwit:0:999999999999"],
["-whitelist=127.0.0.1", "-acceptnonstdtxn=0", "-vbparams=segwit:0:999999999999"],
["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-vbparams=segwit:0:0"],
["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-segwitheight={}".format(SEGWIT_HEIGHT)],
["-whitelist=127.0.0.1", "-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT)],
["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-segwitheight=-1"]
]
def skip_test_if_missing_module(self):
@ -231,26 +233,18 @@ class SegWitTest(BitcoinTestFramework):
# Keep a place to store utxo's that can be used in later tests
self.utxo = []
# Segwit status 'defined'
self.segwit_status = 'defined'
self.log.info("Starting tests before segwit activation")
self.segwit_active = False
self.test_non_witness_transaction()
self.test_unnecessary_witness_before_segwit_activation()
self.test_v0_outputs_arent_spendable()
self.test_block_relay()
self.advance_to_segwit_started()
# Segwit status 'started'
self.test_getblocktemplate_before_lockin()
self.advance_to_segwit_lockin()
# Segwit status 'locked_in'
self.test_unnecessary_witness_before_segwit_activation()
self.test_witness_tx_relay_before_segwit_activation()
self.test_block_relay()
self.test_standardness_v0()
self.log.info("Advancing to segwit activation")
self.advance_to_segwit_active()
# Segwit status 'active'
@ -282,15 +276,15 @@ class SegWitTest(BitcoinTestFramework):
def subtest(func): # noqa: N805
"""Wraps the subtests for logging and state assertions."""
def func_wrapper(self, *args, **kwargs):
self.log.info("Subtest: {} (Segwit status = {})".format(func.__name__, self.segwit_status))
self.log.info("Subtest: {} (Segwit active = {})".format(func.__name__, self.segwit_active))
# Assert segwit status is as expected
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], self.segwit_status)
assert_equal(softfork_active(self.nodes[0], 'segwit'), self.segwit_active)
func(self, *args, **kwargs)
# Each subtest should leave some utxos for the next subtest
assert self.utxo
self.sync_blocks()
# Assert segwit status is as expected at end of subtest
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], self.segwit_status)
assert_equal(softfork_active(self.nodes[0], 'segwit'), self.segwit_active)
return func_wrapper
@ -392,7 +386,7 @@ class SegWitTest(BitcoinTestFramework):
# Check that we can getdata for witness blocks or regular blocks,
# and the right thing happens.
if self.segwit_status != 'active':
if not self.segwit_active:
# Before activation, we should be able to request old blocks with
# or without witness, and they should be the same.
chain_height = self.nodes[0].getblockcount()
@ -535,33 +529,19 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop(0)
self.utxo.append(UTXO(txid, 2, value))
@subtest
def advance_to_segwit_started(self):
"""Mine enough blocks for segwit's vb state to be 'started'."""
height = self.nodes[0].getblockcount()
# Will need to rewrite the tests here if we are past the first period
assert height < VB_PERIOD - 1
# Advance to end of period, status should now be 'started'
self.nodes[0].generate(VB_PERIOD - height - 1)
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
self.segwit_status = 'started'
@subtest
def test_getblocktemplate_before_lockin(self):
txid = int(self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1), 16)
for node in [self.nodes[0], self.nodes[2]]:
gbt_results = node.getblocktemplate({"rules": ["segwit"]})
block_version = gbt_results['version']
if node == self.nodes[2]:
# If this is a non-segwit node, we should not get a witness
# commitment, nor a version bit signalling segwit.
assert_equal(block_version & (1 << VB_WITNESS_BIT), 0)
# commitment.
assert 'default_witness_commitment' not in gbt_results
else:
# For segwit-aware nodes, check the version bit and the witness
# commitment are correct.
assert block_version & (1 << VB_WITNESS_BIT) != 0
# For segwit-aware nodes, check the witness
# commitment is correct.
assert 'default_witness_commitment' in gbt_results
witness_commitment = gbt_results['default_witness_commitment']
@ -571,18 +551,9 @@ class SegWitTest(BitcoinTestFramework):
script = get_witness_script(witness_root, 0)
assert_equal(witness_commitment, script.hex())
@subtest
def advance_to_segwit_lockin(self):
"""Mine enough blocks to lock in segwit, but don't activate."""
height = self.nodes[0].getblockcount()
# Advance to end of period, and verify lock-in happens at the end
self.nodes[0].generate(VB_PERIOD - 1)
height = self.nodes[0].getblockcount()
assert (height % VB_PERIOD) == VB_PERIOD - 2
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
# Clear out the mempool
self.nodes[0].generate(1)
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
self.segwit_status = 'locked_in'
self.sync_blocks()
@subtest
def test_witness_tx_relay_before_segwit_activation(self):
@ -686,7 +657,7 @@ class SegWitTest(BitcoinTestFramework):
tx3.wit.vtxinwit.append(CTxInWitness())
tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
tx3.rehash()
if self.segwit_status != 'active':
if not self.segwit_active:
# Just check mempool acceptance, but don't add the transaction to the mempool, since witness is disallowed
# in blocks and the tx is impossible to mine right now.
assert_equal(self.nodes[0].testmempoolaccept([tx3.serialize_with_witness().hex()]), [{'txid': tx3.hash, 'allowed': True}])
@ -707,12 +678,13 @@ class SegWitTest(BitcoinTestFramework):
@subtest
def advance_to_segwit_active(self):
"""Mine enough blocks to activate segwit."""
assert not softfork_active(self.nodes[0], 'segwit')
height = self.nodes[0].getblockcount()
self.nodes[0].generate(VB_PERIOD - (height % VB_PERIOD) - 2)
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
self.nodes[0].generate(SEGWIT_HEIGHT - height - 2)
assert not softfork_active(self.nodes[0], 'segwit')
self.nodes[0].generate(1)
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'active')
self.segwit_status = 'active'
assert softfork_active(self.nodes[0], 'segwit')
self.segwit_active = True
@subtest
def test_p2sh_witness(self):
@ -1924,13 +1896,13 @@ class SegWitTest(BitcoinTestFramework):
# Restart with the new binary
self.stop_node(2)
self.start_node(2, extra_args=["-vbparams=segwit:0:999999999999"])
self.start_node(2, extra_args=["-segwitheight={}".format(SEGWIT_HEIGHT)])
connect_nodes(self.nodes[0], 2)
self.sync_blocks()
# Make sure that this peer thinks segwit has activated.
assert get_bip9_status(self.nodes[2], 'segwit')['status'] == "active"
assert softfork_active(self.nodes[2], 'segwit')
# Make sure this peer's blocks match those of node0.
height = self.nodes[2].getblockcount()

View file

@ -78,7 +78,6 @@ class BlockchainTest(BitcoinTestFramework):
keys = [
'bestblockhash',
'bip9_softforks',
'blocks',
'chain',
'chainwork',
@ -124,6 +123,31 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(res['prune_target_size'], 576716800)
assert_greater_than(res['size_on_disk'], 0)
assert_equal(res['softforks'], {
'bip34': {'type': 'buried', 'active': False, 'height': 500},
'bip66': {'type': 'buried', 'active': False, 'height': 1251},
'bip65': {'type': 'buried', 'active': False, 'height': 1351},
'csv': {'type': 'buried', 'active': False, 'height': 432},
'segwit': {'type': 'buried', 'active': True, 'height': 0},
'testdummy': {
'type': 'bip9',
'bip9': {
'status': 'started',
'bit': 28,
'startTime': 0,
'timeout': 0x7fffffffffffffff, # testdummy does not have a timeout so is set to the max int64 value
'since': 144,
'statistics': {
'period': 144,
'threshold': 108,
'elapsed': 57,
'count': 57,
'possible': True,
},
},
'active': False}
})
def _test_getchaintxstats(self):
self.log.info("Test getchaintxstats")

View file

@ -335,9 +335,9 @@ def delete_cookie_file(datadir, chain):
logger.debug("Deleting leftover cookie file")
os.remove(os.path.join(datadir, chain, ".cookie"))
def get_bip9_status(node, key):
info = node.getblockchaininfo()
return info['bip9_softforks'][key]
def softfork_active(node, key):
"""Return whether a softfork is active."""
return node.getblockchaininfo()['softforks'][key]['active']
def set_node_times(nodes, t):
for node in nodes: