aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2019-08-15 16:02:02 -0400
committerMarcoFalke <falke.marco@gmail.com>2019-08-15 16:02:10 -0400
commit1bf2ff2bf8e8bef3ba21e635aabb1b0964062743 (patch)
tree365d1217fc9886ebf0335c7bdbb94ab834b305a9
parent367b023ae444e7d9641c4a3469f9154461e50e68 (diff)
parente78aaf41f43d0e2ad78fa6d8dad61032c8ef73d0 (diff)
Merge #16060: Bury bip9 deployments
e78aaf41f43d0e2ad78fa6d8dad61032c8ef73d0 [docs] Add release notes for burying bip 9 soft fork deployments (John Newbery) 8319e738f9f118025b332e4fa804d4c31e4113f4 [tests] Add coverage for the content of getblockchaininfo.softforks (James O'Beirne) 0328dcdcfcb56dc8918697716d7686be048ad0b3 [Consensus] Bury segwit deployment (John Newbery) 1c93b9b31c2ab7358f9d55f52dd46340397c906d [Consensus] Bury CSV deployment height (John Newbery) 3862e473f0cb71a762c0306b171b591341d58142 [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 e78aaf41f43d0e2ad78fa6d8dad61032c8ef73d0 ; 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 e78aaf41f43d0e2ad78fa6d8dad61032c8ef73d0 (still didn't check if the mainnet block heights are correct, but the code looks good now) Tree-SHA512: 7e951829106e21a81725f7d3e236eddbb59349189740907bb47e33f5dbf95c43753ac1231f47ae7bee85c8c81b2146afcdfdc11deb1503947f23093a9c399912
-rw-r--r--doc/release-notes-16060.md15
-rw-r--r--src/chainparams.cpp49
-rw-r--r--src/chainparamsbase.cpp1
-rw-r--r--src/consensus/params.h8
-rw-r--r--src/init.cpp9
-rw-r--r--src/rpc/blockchain.cpp143
-rw-r--r--src/rpc/mining.cpp5
-rw-r--r--src/test/setup_common.cpp2
-rw-r--r--src/validation.cpp31
-rw-r--r--src/validation.h6
-rw-r--r--src/versionbitsinfo.cpp8
-rwxr-xr-xtest/functional/feature_bip68_sequence.py14
-rwxr-xr-xtest/functional/feature_cltv.py17
-rwxr-xr-xtest/functional/feature_csv_activation.py97
-rwxr-xr-xtest/functional/feature_dersig.py17
-rwxr-xr-xtest/functional/feature_nulldummy.py2
-rwxr-xr-xtest/functional/feature_segwit.py6
-rwxr-xr-xtest/functional/p2p_compactblocks.py4
-rwxr-xr-xtest/functional/p2p_segwit.py82
-rwxr-xr-xtest/functional/rpc_blockchain.py26
-rw-r--r--test/functional/test_framework/util.py6
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: