diff options
-rw-r--r-- | doc/release-notes-16060.md | 15 | ||||
-rw-r--r-- | src/chainparams.cpp | 49 | ||||
-rw-r--r-- | src/chainparamsbase.cpp | 1 | ||||
-rw-r--r-- | src/consensus/params.h | 8 | ||||
-rw-r--r-- | src/init.cpp | 9 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 143 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 5 | ||||
-rw-r--r-- | src/test/setup_common.cpp | 2 | ||||
-rw-r--r-- | src/validation.cpp | 31 | ||||
-rw-r--r-- | src/validation.h | 6 | ||||
-rw-r--r-- | src/versionbitsinfo.cpp | 8 | ||||
-rwxr-xr-x | test/functional/feature_bip68_sequence.py | 14 | ||||
-rwxr-xr-x | test/functional/feature_cltv.py | 17 | ||||
-rwxr-xr-x | test/functional/feature_csv_activation.py | 97 | ||||
-rwxr-xr-x | test/functional/feature_dersig.py | 17 | ||||
-rwxr-xr-x | test/functional/feature_nulldummy.py | 2 | ||||
-rwxr-xr-x | test/functional/feature_segwit.py | 6 | ||||
-rwxr-xr-x | test/functional/p2p_compactblocks.py | 4 | ||||
-rwxr-xr-x | test/functional/p2p_segwit.py | 82 | ||||
-rwxr-xr-x | test/functional/rpc_blockchain.py | 26 | ||||
-rw-r--r-- | test/functional/test_framework/util.py | 6 |
21 files changed, 242 insertions, 306 deletions
diff --git a/doc/release-notes-16060.md b/doc/release-notes-16060.md new file mode 100644 index 0000000000..7e150d10e7 --- /dev/null +++ b/doc/release-notes-16060.md @@ -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). diff --git a/src/chainparams.cpp b/src/chainparams.cpp index c24234aeb7..ad766471dc 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -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")) { diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index deb8e0fb57..9b98dff3ca 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -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); } diff --git a/src/consensus/params.h b/src/consensus/params.h index 6c3a201f4f..8263b0fef4 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -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. diff --git a/src/init.cpp b/src/init.cpp index 8870f379fb..d98f7c3767 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -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); } diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e3d5394a2c..bfb6ab6a21 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -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) { - 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; -} + // 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; -static UniValue SoftForkDesc(const std::string &name, int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams) -{ UniValue rv(UniValue::VOBJ); - rv.pushKV("id", name); - rv.pushKV("version", version); - rv.pushKV("reject", SoftForkMajorityDesc(version, pindex, consensusParams)); - 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 BIP9SoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +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); + // 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; + + 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); + bip9.pushKV("statistics", statsUV); } - return rv; -} -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" - " \"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" - " \"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" + " \"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\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; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 92a0e33769..07c2958635 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -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"); diff --git a/src/test/setup_common.cpp b/src/test/setup_common.cpp index 0ff081e472..bbdf1ef830 100644 --- a/src/test/setup_common.cpp +++ b/src/test/setup_common.cpp @@ -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: diff --git a/src/validation.cpp b/src/validation.cpp index 8f44e2565a..74f68a3047 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -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; diff --git a/src/validation.h b/src/validation.h index 65f86e3070..7cf3311f22 100644 --- a/src/validation.h +++ b/src/validation.h @@ -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); diff --git a/src/versionbitsinfo.cpp b/src/versionbitsinfo.cpp index ecf3482927..82df92ac90 100644 --- a/src/versionbitsinfo.cpp +++ b/src/versionbitsinfo.cpp @@ -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, - } }; diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py index f0bf09e172..fe6f9eade1 100755 --- a/test/functional/feature_bip68_sequence.py +++ b/test/functional/feature_bip68_sequence.py @@ -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. diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index af34f9f0db..e00219ca4a 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -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) diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py index 887e9dafa3..6bd321992a 100755 --- a/test/functional/feature_csv_activation.py +++ b/test/functional/feature_csv_activation.py @@ -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: - test_blocks = [] + 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) - self.send_blocks(test_blocks) - - 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) + # Activation height is hardcoded + test_blocks = self.generate_blocks(345) self.send_blocks(test_blocks) + assert not softfork_active(self.nodes[0], 'csv') - # 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 diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py index 067e3be1f4..1bd9586364 100755 --- a/test/functional/feature_dersig.py +++ b/test/functional/feature_dersig.py @@ -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) diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py index 60a703c48f..250dee1528 100755 --- a/test/functional/feature_nulldummy.py +++ b/test/functional/feature_nulldummy.py @@ -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() diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index a71d4071d5..d47065d1cb 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -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", ], ] diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py index eb3336bd3b..7905cf5018 100755 --- a/test/functional/p2p_compactblocks.py +++ b/test/functional/p2p_compactblocks.py @@ -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) diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index dca71aec43..98f6b1d71d 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -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() @@ -536,32 +530,18 @@ class SegWitTest(BitcoinTestFramework): 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() diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index facb05b54c..6c30e05084 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -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") diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 7beddc6407..3d9be0d0a6 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -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: |