Merge #16060: Bury bip9 deployments
e78aaf41f4
[docs] Add release notes for burying bip 9 soft fork deployments (John Newbery)8319e738f9
[tests] Add coverage for the content of getblockchaininfo.softforks (James O'Beirne)0328dcdcfc
[Consensus] Bury segwit deployment (John Newbery)1c93b9b31c
[Consensus] Bury CSV deployment height (John Newbery)3862e473f0
[rpc] Tidy up reporting of buried and ongoing softforks (John Newbery) Pull request description: This hardcodes CSV and segwit activation heights, similar to the BIP 90 buried deployments for BIPs 34, 65 and 66. CSV and segwit have been active for over 18 months. Hardcoding the activation height is a code simplification, makes it easier to understand segwit activation status, and reduces technical debt. This was originally attempted by jl2012 in #11398 and again by me in #12360. ACKs for top commit: ajtowns: ACKe78aaf41f4
; checked diff to previous acked commit, checked tests still work ariard: ACKe78aaf4
, check diff, run the tests again and successfully activated csv/segwit heights on mainnet as expected. MarcoFalke: ACKe78aaf41f4
(still didn't check if the mainnet block heights are correct, but the code looks good now) Tree-SHA512: 7e951829106e21a81725f7d3e236eddbb59349189740907bb47e33f5dbf95c43753ac1231f47ae7bee85c8c81b2146afcdfdc11deb1503947f23093a9c399912
This commit is contained in:
commit
1bf2ff2bf8
21 changed files with 242 additions and 306 deletions
15
doc/release-notes-16060.md
Normal file
15
doc/release-notes-16060.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
Low-level RPC changes
|
||||
----------------------
|
||||
|
||||
- Soft fork reporting in the `getblockchaininfo` return object has been
|
||||
updated. For full details, see the RPC help text. In summary:
|
||||
- The `bip9_softforks` sub-object is no longer returned
|
||||
- The `softforks` sub-object now returns an object keyed by soft fork name,
|
||||
rather than an array
|
||||
- Each softfork object in the `softforks` object contains a `type` value which
|
||||
is either `buried` (for soft fork deployments where the activation height is
|
||||
hard-coded into the client implementation), or `bip9` (for soft fork deployments
|
||||
where activation is controlled by BIP 9 signaling).
|
||||
|
||||
- `getblocktemplate` no longer returns a `rules` array containing `CSV`
|
||||
and `segwit` (the BIP 9 deployments that are currently in active state).
|
|
@ -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")) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1188,54 +1188,49 @@ static UniValue verifychain(const JSONRPCRequest& request)
|
|||
Params(), &::ChainstateActive().CoinsTip(), nCheckLevel, nCheckDepth);
|
||||
}
|
||||
|
||||
/** Implementation of IsSuperMajority with better feedback */
|
||||
static UniValue SoftForkMajorityDesc(int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
|
||||
static void BuriedForkDescPushBack(UniValue& softforks, const std::string &name, int height) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
// For buried deployments.
|
||||
// A buried deployment is one where the height of the activation has been hardcoded into
|
||||
// the client implementation long after the consensus change has activated. See BIP 90.
|
||||
// Buried deployments with activation height value of
|
||||
// std::numeric_limits<int>::max() are disabled and thus hidden.
|
||||
if (height == std::numeric_limits<int>::max()) return;
|
||||
|
||||
UniValue rv(UniValue::VOBJ);
|
||||
bool activated = false;
|
||||
switch(version)
|
||||
{
|
||||
case 2:
|
||||
activated = pindex->nHeight >= consensusParams.BIP34Height;
|
||||
break;
|
||||
case 3:
|
||||
activated = pindex->nHeight >= consensusParams.BIP66Height;
|
||||
break;
|
||||
case 4:
|
||||
activated = pindex->nHeight >= consensusParams.BIP65Height;
|
||||
break;
|
||||
}
|
||||
rv.pushKV("status", activated);
|
||||
return rv;
|
||||
rv.pushKV("type", "buried");
|
||||
// getblockchaininfo reports the softfork as active from when the chain height is
|
||||
// one below the activation height
|
||||
rv.pushKV("active", ::ChainActive().Tip()->nHeight + 1 >= height);
|
||||
rv.pushKV("height", height);
|
||||
softforks.pushKV(name, rv);
|
||||
}
|
||||
|
||||
static UniValue SoftForkDesc(const std::string &name, int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
|
||||
static void BIP9SoftForkDescPushBack(UniValue& softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
UniValue rv(UniValue::VOBJ);
|
||||
rv.pushKV("id", name);
|
||||
rv.pushKV("version", version);
|
||||
rv.pushKV("reject", SoftForkMajorityDesc(version, pindex, consensusParams));
|
||||
return rv;
|
||||
}
|
||||
// For BIP9 deployments.
|
||||
// Deployments (e.g. testdummy) with timeout value before Jan 1, 2009 are hidden.
|
||||
// A timeout value of 0 guarantees a softfork will never be activated.
|
||||
// This is used when merging logic to implement a proposed softfork without a specified deployment schedule.
|
||||
if (consensusParams.vDeployments[id].nTimeout <= 1230768000) return;
|
||||
|
||||
static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
|
||||
{
|
||||
UniValue rv(UniValue::VOBJ);
|
||||
UniValue bip9(UniValue::VOBJ);
|
||||
const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
|
||||
switch (thresholdState) {
|
||||
case ThresholdState::DEFINED: rv.pushKV("status", "defined"); break;
|
||||
case ThresholdState::STARTED: rv.pushKV("status", "started"); break;
|
||||
case ThresholdState::LOCKED_IN: rv.pushKV("status", "locked_in"); break;
|
||||
case ThresholdState::ACTIVE: rv.pushKV("status", "active"); break;
|
||||
case ThresholdState::FAILED: rv.pushKV("status", "failed"); break;
|
||||
case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break;
|
||||
case ThresholdState::STARTED: bip9.pushKV("status", "started"); break;
|
||||
case ThresholdState::LOCKED_IN: bip9.pushKV("status", "locked_in"); break;
|
||||
case ThresholdState::ACTIVE: bip9.pushKV("status", "active"); break;
|
||||
case ThresholdState::FAILED: bip9.pushKV("status", "failed"); break;
|
||||
}
|
||||
if (ThresholdState::STARTED == thresholdState)
|
||||
{
|
||||
rv.pushKV("bit", consensusParams.vDeployments[id].bit);
|
||||
bip9.pushKV("bit", consensusParams.vDeployments[id].bit);
|
||||
}
|
||||
rv.pushKV("startTime", consensusParams.vDeployments[id].nStartTime);
|
||||
rv.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
|
||||
rv.pushKV("since", VersionBitsTipStateSinceHeight(consensusParams, id));
|
||||
bip9.pushKV("startTime", consensusParams.vDeployments[id].nStartTime);
|
||||
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
|
||||
int64_t since_height = VersionBitsTipStateSinceHeight(consensusParams, id);
|
||||
bip9.pushKV("since", since_height);
|
||||
if (ThresholdState::STARTED == thresholdState)
|
||||
{
|
||||
UniValue statsUV(UniValue::VOBJ);
|
||||
|
@ -1245,18 +1240,18 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse
|
|||
statsUV.pushKV("elapsed", statsStruct.elapsed);
|
||||
statsUV.pushKV("count", statsStruct.count);
|
||||
statsUV.pushKV("possible", statsStruct.possible);
|
||||
rv.pushKV("statistics", statsUV);
|
||||
}
|
||||
return rv;
|
||||
bip9.pushKV("statistics", statsUV);
|
||||
}
|
||||
|
||||
static void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
|
||||
{
|
||||
// Deployments with timeout value of 0 are hidden.
|
||||
// A timeout value of 0 guarantees a softfork will never be activated.
|
||||
// This is used when softfork codes are merged without specifying the deployment schedule.
|
||||
if (consensusParams.vDeployments[id].nTimeout > 0)
|
||||
bip9_softforks.pushKV(VersionBitsDeploymentInfo[id].name, BIP9SoftForkDesc(consensusParams, id));
|
||||
UniValue rv(UniValue::VOBJ);
|
||||
rv.pushKV("type", "bip9");
|
||||
rv.pushKV("bip9", bip9);
|
||||
if (ThresholdState::ACTIVE == thresholdState) {
|
||||
rv.pushKV("height", since_height);
|
||||
}
|
||||
rv.pushKV("active", ThresholdState::ACTIVE == thresholdState);
|
||||
|
||||
softforks.pushKV(name, rv);
|
||||
}
|
||||
|
||||
UniValue getblockchaininfo(const JSONRPCRequest& request)
|
||||
|
@ -1280,29 +1275,25 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
|
|||
" \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n"
|
||||
" \"automatic_pruning\": xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n"
|
||||
" \"prune_target_size\": xxxxxx, (numeric) the target size used by pruning (only present if automatic pruning is enabled)\n"
|
||||
" \"softforks\": [ (array) status of softforks in progress\n"
|
||||
" {\n"
|
||||
" \"id\": \"xxxx\", (string) name of softfork\n"
|
||||
" \"version\": xx, (numeric) block version\n"
|
||||
" \"reject\": { (object) progress toward rejecting pre-softfork blocks\n"
|
||||
" \"status\": xx, (boolean) true if threshold reached\n"
|
||||
" },\n"
|
||||
" }, ...\n"
|
||||
" ],\n"
|
||||
" \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n"
|
||||
" \"softforks\": { (object) status of softforks\n"
|
||||
" \"xxxx\" : { (string) name of the softfork\n"
|
||||
" \"type\": \"xxxx\", (string) one of \"buried\", \"bip9\"\n"
|
||||
" \"bip9\": { (object) status of bip9 softforks (only for \"bip9\" type)\n"
|
||||
" \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n"
|
||||
" \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n"
|
||||
" \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n"
|
||||
" \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n"
|
||||
" \"since\": xx, (numeric) height of the first block to which the status applies\n"
|
||||
" \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n"
|
||||
" \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork\n"
|
||||
" \"period\": xx, (numeric) the length in blocks of the BIP9 signalling period \n"
|
||||
" \"threshold\": xx, (numeric) the number of blocks with the version bit set required to activate the feature \n"
|
||||
" \"elapsed\": xx, (numeric) the number of blocks elapsed since the beginning of the current period \n"
|
||||
" \"count\": xx, (numeric) the number of blocks with the version bit set in the current period \n"
|
||||
" \"possible\": xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n"
|
||||
" }\n"
|
||||
" },\n"
|
||||
" \"height\": \"xxxxxx\", (numeric) height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)\n"
|
||||
" \"active\": xx, (boolean) true if the rules are enforced for the mempool and the next block\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" \"warnings\" : \"...\", (string) any network and blockchain warnings.\n"
|
||||
|
@ -1347,16 +1338,14 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
|
|||
}
|
||||
|
||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||
UniValue softforks(UniValue::VARR);
|
||||
UniValue bip9_softforks(UniValue::VOBJ);
|
||||
softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
|
||||
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
|
||||
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
|
||||
for (int pos = Consensus::DEPLOYMENT_CSV; pos != Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++pos) {
|
||||
BIP9SoftForkDescPushBack(bip9_softforks, consensusParams, static_cast<Consensus::DeploymentPos>(pos));
|
||||
}
|
||||
UniValue softforks(UniValue::VOBJ);
|
||||
BuriedForkDescPushBack(softforks, "bip34", consensusParams.BIP34Height);
|
||||
BuriedForkDescPushBack(softforks, "bip66", consensusParams.BIP66Height);
|
||||
BuriedForkDescPushBack(softforks, "bip65", consensusParams.BIP65Height);
|
||||
BuriedForkDescPushBack(softforks, "csv", consensusParams.CSVHeight);
|
||||
BuriedForkDescPushBack(softforks, "segwit", consensusParams.SegwitHeight);
|
||||
BIP9SoftForkDescPushBack(softforks, "testdummy", consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
|
||||
obj.pushKV("softforks", softforks);
|
||||
obj.pushKV("bip9_softforks", bip9_softforks);
|
||||
|
||||
obj.pushKV("warnings", GetWarnings("statusbar"));
|
||||
return obj;
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -2,23 +2,17 @@
|
|||
# Copyright (c) 2015-2019 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test activation of the first version bits soft fork.
|
||||
"""Test CSV soft fork activation.
|
||||
|
||||
This soft fork will activate the following BIPS:
|
||||
BIP 68 - nSequence relative lock times
|
||||
BIP 112 - CHECKSEQUENCEVERIFY
|
||||
BIP 113 - MedianTimePast semantics for nLockTime
|
||||
|
||||
regtest lock-in with 108/144 block signalling
|
||||
activation after a further 144 blocks
|
||||
|
||||
mine 82 blocks whose coinbases will be used to generate inputs for our tests
|
||||
mine 61 blocks to transition from DEFINED to STARTED
|
||||
mine 144 blocks only 100 of which are signaling readiness in order to fail to change state this period
|
||||
mine 144 blocks with 108 signaling and verify STARTED->LOCKED_IN
|
||||
mine 140 blocks and seed block chain with the 82 inputs will use for our tests at height 572
|
||||
mine 3 blocks and verify still at LOCKED_IN and test that enforcement has not triggered
|
||||
mine 1 block and test that enforcement has triggered (which triggers ACTIVE)
|
||||
mine 345 blocks and seed block chain with the 82 inputs will use for our tests at height 427
|
||||
mine 2 blocks and verify soft fork not yet activated
|
||||
mine 1 block and test that soft fork is activated (rules enforced for next block)
|
||||
Test BIP 113 is enforced
|
||||
Mine 4 blocks so next height is 580 and test BIP 68 is enforced for time and height
|
||||
Mine 1 block so next height is 581 and test BIP 68 now passes time but not height
|
||||
|
@ -58,11 +52,12 @@ from test_framework.script import (
|
|||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
get_bip9_status,
|
||||
hex_str_to_bytes,
|
||||
softfork_active,
|
||||
)
|
||||
|
||||
BASE_RELATIVE_LOCKTIME = 10
|
||||
CSV_ACTIVATION_HEIGHT = 432
|
||||
SEQ_DISABLE_FLAG = 1 << 31
|
||||
SEQ_RANDOM_HIGH_BIT = 1 << 25
|
||||
SEQ_TYPE_FLAG = 1 << 22
|
||||
|
@ -148,20 +143,19 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def generate_blocks(self, number, version, test_blocks=None):
|
||||
if test_blocks is None:
|
||||
def generate_blocks(self, number):
|
||||
test_blocks = []
|
||||
for i in range(number):
|
||||
block = self.create_test_block([], version)
|
||||
block = self.create_test_block([])
|
||||
test_blocks.append(block)
|
||||
self.last_block_time += 600
|
||||
self.tip = block.sha256
|
||||
self.tipheight += 1
|
||||
return test_blocks
|
||||
|
||||
def create_test_block(self, txs, version=536870912):
|
||||
def create_test_block(self, txs):
|
||||
block = create_block(self.tip, create_coinbase(self.tipheight + 1), self.last_block_time + 600)
|
||||
block.nVersion = version
|
||||
block.nVersion = 4
|
||||
block.vtx.extend(txs)
|
||||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
block.rehash()
|
||||
|
@ -187,45 +181,14 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||
self.tip = int(self.nodes[0].getbestblockhash(), 16)
|
||||
self.nodeaddress = self.nodes[0].getnewaddress()
|
||||
|
||||
self.log.info("Test that the csv softfork is DEFINED")
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined')
|
||||
test_blocks = self.generate_blocks(61, 4)
|
||||
# Activation height is hardcoded
|
||||
test_blocks = self.generate_blocks(345)
|
||||
self.send_blocks(test_blocks)
|
||||
assert not softfork_active(self.nodes[0], 'csv')
|
||||
|
||||
self.log.info("Advance from DEFINED to STARTED, height = 143")
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
|
||||
|
||||
self.log.info("Fail to achieve LOCKED_IN")
|
||||
# 100 out of 144 signal bit 0. Use a variety of bits to simulate multiple parallel softforks
|
||||
|
||||
test_blocks = self.generate_blocks(50, 536870913) # 0x20000001 (signalling ready)
|
||||
test_blocks = self.generate_blocks(20, 4, test_blocks) # 0x00000004 (signalling not)
|
||||
test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready)
|
||||
test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not)
|
||||
self.send_blocks(test_blocks)
|
||||
|
||||
self.log.info("Failed to advance past STARTED, height = 287")
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
|
||||
|
||||
self.log.info("Generate blocks to achieve LOCK-IN")
|
||||
# 108 out of 144 signal bit 0 to achieve lock-in
|
||||
# using a variety of bits to simulate multiple parallel softforks
|
||||
test_blocks = self.generate_blocks(58, 536870913) # 0x20000001 (signalling ready)
|
||||
test_blocks = self.generate_blocks(26, 4, test_blocks) # 0x00000004 (signalling not)
|
||||
test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready)
|
||||
test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not)
|
||||
self.send_blocks(test_blocks)
|
||||
|
||||
self.log.info("Advanced from STARTED to LOCKED_IN, height = 431")
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
|
||||
|
||||
# Generate 140 more version 4 blocks
|
||||
test_blocks = self.generate_blocks(140, 4)
|
||||
self.send_blocks(test_blocks)
|
||||
|
||||
# Inputs at height = 572
|
||||
# Inputs at height = 431
|
||||
#
|
||||
# Put inputs for all tests in the chain at height 572 (tip now = 571) (time increases by 600s per block)
|
||||
# Put inputs for all tests in the chain at height 431 (tip now = 430) (time increases by 600s per block)
|
||||
# Note we reuse inputs for v1 and v2 txs so must test these separately
|
||||
# 16 normal inputs
|
||||
bip68inputs = []
|
||||
|
@ -255,7 +218,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||
bip113input = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
|
||||
|
||||
self.nodes[0].setmocktime(self.last_block_time + 600)
|
||||
inputblockhash = self.nodes[0].generate(1)[0] # 1 block generated for inputs to be in chain at height 572
|
||||
inputblockhash = self.nodes[0].generate(1)[0] # 1 block generated for inputs to be in chain at height 431
|
||||
self.nodes[0].setmocktime(0)
|
||||
self.tip = int(inputblockhash, 16)
|
||||
self.tipheight += 1
|
||||
|
@ -263,11 +226,12 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||
assert_equal(len(self.nodes[0].getblock(inputblockhash, True)["tx"]), 82 + 1)
|
||||
|
||||
# 2 more version 4 blocks
|
||||
test_blocks = self.generate_blocks(2, 4)
|
||||
test_blocks = self.generate_blocks(2)
|
||||
self.send_blocks(test_blocks)
|
||||
|
||||
self.log.info("Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575)")
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
|
||||
assert_equal(self.tipheight, CSV_ACTIVATION_HEIGHT - 2)
|
||||
self.log.info("Height = {}, CSV not yet active (will activate for block {}, not {})".format(self.tipheight, CSV_ACTIVATION_HEIGHT, CSV_ACTIVATION_HEIGHT - 1))
|
||||
assert not softfork_active(self.nodes[0], 'csv')
|
||||
|
||||
# Test both version 1 and version 2 transactions for all tests
|
||||
# BIP113 test transaction will be modified before each use to put in appropriate block time
|
||||
|
@ -340,10 +304,11 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||
self.send_blocks([self.create_test_block(success_txs)])
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
# 1 more version 4 block to get us to height 575 so the fork should now be active for the next block
|
||||
test_blocks = self.generate_blocks(1, 4)
|
||||
# 1 more version 4 block to get us to height 432 so the fork should now be active for the next block
|
||||
assert not softfork_active(self.nodes[0], 'csv')
|
||||
test_blocks = self.generate_blocks(1)
|
||||
self.send_blocks(test_blocks)
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'active')
|
||||
assert softfork_active(self.nodes[0], 'csv')
|
||||
|
||||
self.log.info("Post-Soft Fork Tests.")
|
||||
|
||||
|
@ -364,8 +329,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||
self.send_blocks([self.create_test_block([bip113tx])])
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
# Next block height = 580 after 4 blocks of random version
|
||||
test_blocks = self.generate_blocks(4, 1234)
|
||||
# Next block height = 437 after 4 blocks of random version
|
||||
test_blocks = self.generate_blocks(4)
|
||||
self.send_blocks(test_blocks)
|
||||
|
||||
self.log.info("BIP 68 tests")
|
||||
|
@ -392,8 +357,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||
for tx in bip68heighttxs:
|
||||
self.send_blocks([self.create_test_block([tx])], success=False)
|
||||
|
||||
# Advance one block to 581
|
||||
test_blocks = self.generate_blocks(1, 1234)
|
||||
# Advance one block to 438
|
||||
test_blocks = self.generate_blocks(1)
|
||||
self.send_blocks(test_blocks)
|
||||
|
||||
# Height txs should fail and time txs should now pass 9 * 600 > 10 * 512
|
||||
|
@ -403,8 +368,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||
for tx in bip68heighttxs:
|
||||
self.send_blocks([self.create_test_block([tx])], success=False)
|
||||
|
||||
# Advance one block to 582
|
||||
test_blocks = self.generate_blocks(1, 1234)
|
||||
# Advance one block to 439
|
||||
test_blocks = self.generate_blocks(1)
|
||||
self.send_blocks(test_blocks)
|
||||
|
||||
# All BIP 68 txs should pass
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -76,7 +76,7 @@ from test_framework.util import (
|
|||
assert_equal,
|
||||
connect_nodes,
|
||||
disconnect_nodes,
|
||||
get_bip9_status,
|
||||
softfork_active,
|
||||
hex_str_to_bytes,
|
||||
assert_raises_rpc_error,
|
||||
)
|
||||
|
@ -88,6 +88,8 @@ VB_TOP_BITS = 0x20000000
|
|||
|
||||
MAX_SIGOP_COST = 80000
|
||||
|
||||
SEGWIT_HEIGHT = 120
|
||||
|
||||
class UTXO():
|
||||
"""Used to keep track of anyone-can-spend outputs that we can use in the tests."""
|
||||
def __init__(self, sha256, n, value):
|
||||
|
@ -185,9 +187,9 @@ class SegWitTest(BitcoinTestFramework):
|
|||
self.num_nodes = 3
|
||||
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
|
||||
self.extra_args = [
|
||||
["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-vbparams=segwit:0:999999999999"],
|
||||
["-whitelist=127.0.0.1", "-acceptnonstdtxn=0", "-vbparams=segwit:0:999999999999"],
|
||||
["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-vbparams=segwit:0:0"],
|
||||
["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-segwitheight={}".format(SEGWIT_HEIGHT)],
|
||||
["-whitelist=127.0.0.1", "-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT)],
|
||||
["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-segwitheight=-1"]
|
||||
]
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
|
@ -231,26 +233,18 @@ class SegWitTest(BitcoinTestFramework):
|
|||
# Keep a place to store utxo's that can be used in later tests
|
||||
self.utxo = []
|
||||
|
||||
# Segwit status 'defined'
|
||||
self.segwit_status = 'defined'
|
||||
self.log.info("Starting tests before segwit activation")
|
||||
self.segwit_active = False
|
||||
|
||||
self.test_non_witness_transaction()
|
||||
self.test_unnecessary_witness_before_segwit_activation()
|
||||
self.test_v0_outputs_arent_spendable()
|
||||
self.test_block_relay()
|
||||
self.advance_to_segwit_started()
|
||||
|
||||
# Segwit status 'started'
|
||||
|
||||
self.test_getblocktemplate_before_lockin()
|
||||
self.advance_to_segwit_lockin()
|
||||
|
||||
# Segwit status 'locked_in'
|
||||
|
||||
self.test_unnecessary_witness_before_segwit_activation()
|
||||
self.test_witness_tx_relay_before_segwit_activation()
|
||||
self.test_block_relay()
|
||||
self.test_standardness_v0()
|
||||
|
||||
self.log.info("Advancing to segwit activation")
|
||||
self.advance_to_segwit_active()
|
||||
|
||||
# Segwit status 'active'
|
||||
|
@ -282,15 +276,15 @@ class SegWitTest(BitcoinTestFramework):
|
|||
def subtest(func): # noqa: N805
|
||||
"""Wraps the subtests for logging and state assertions."""
|
||||
def func_wrapper(self, *args, **kwargs):
|
||||
self.log.info("Subtest: {} (Segwit status = {})".format(func.__name__, self.segwit_status))
|
||||
self.log.info("Subtest: {} (Segwit active = {})".format(func.__name__, self.segwit_active))
|
||||
# Assert segwit status is as expected
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], self.segwit_status)
|
||||
assert_equal(softfork_active(self.nodes[0], 'segwit'), self.segwit_active)
|
||||
func(self, *args, **kwargs)
|
||||
# Each subtest should leave some utxos for the next subtest
|
||||
assert self.utxo
|
||||
self.sync_blocks()
|
||||
# Assert segwit status is as expected at end of subtest
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], self.segwit_status)
|
||||
assert_equal(softfork_active(self.nodes[0], 'segwit'), self.segwit_active)
|
||||
|
||||
return func_wrapper
|
||||
|
||||
|
@ -392,7 +386,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
|
||||
# Check that we can getdata for witness blocks or regular blocks,
|
||||
# and the right thing happens.
|
||||
if self.segwit_status != 'active':
|
||||
if not self.segwit_active:
|
||||
# Before activation, we should be able to request old blocks with
|
||||
# or without witness, and they should be the same.
|
||||
chain_height = self.nodes[0].getblockcount()
|
||||
|
@ -535,33 +529,19 @@ class SegWitTest(BitcoinTestFramework):
|
|||
self.utxo.pop(0)
|
||||
self.utxo.append(UTXO(txid, 2, value))
|
||||
|
||||
@subtest
|
||||
def advance_to_segwit_started(self):
|
||||
"""Mine enough blocks for segwit's vb state to be 'started'."""
|
||||
height = self.nodes[0].getblockcount()
|
||||
# Will need to rewrite the tests here if we are past the first period
|
||||
assert height < VB_PERIOD - 1
|
||||
# Advance to end of period, status should now be 'started'
|
||||
self.nodes[0].generate(VB_PERIOD - height - 1)
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
|
||||
self.segwit_status = 'started'
|
||||
|
||||
@subtest
|
||||
def test_getblocktemplate_before_lockin(self):
|
||||
txid = int(self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1), 16)
|
||||
|
||||
for node in [self.nodes[0], self.nodes[2]]:
|
||||
gbt_results = node.getblocktemplate({"rules": ["segwit"]})
|
||||
block_version = gbt_results['version']
|
||||
if node == self.nodes[2]:
|
||||
# If this is a non-segwit node, we should not get a witness
|
||||
# commitment, nor a version bit signalling segwit.
|
||||
assert_equal(block_version & (1 << VB_WITNESS_BIT), 0)
|
||||
# commitment.
|
||||
assert 'default_witness_commitment' not in gbt_results
|
||||
else:
|
||||
# For segwit-aware nodes, check the version bit and the witness
|
||||
# commitment are correct.
|
||||
assert block_version & (1 << VB_WITNESS_BIT) != 0
|
||||
# For segwit-aware nodes, check the witness
|
||||
# commitment is correct.
|
||||
assert 'default_witness_commitment' in gbt_results
|
||||
witness_commitment = gbt_results['default_witness_commitment']
|
||||
|
||||
|
@ -571,18 +551,9 @@ class SegWitTest(BitcoinTestFramework):
|
|||
script = get_witness_script(witness_root, 0)
|
||||
assert_equal(witness_commitment, script.hex())
|
||||
|
||||
@subtest
|
||||
def advance_to_segwit_lockin(self):
|
||||
"""Mine enough blocks to lock in segwit, but don't activate."""
|
||||
height = self.nodes[0].getblockcount()
|
||||
# Advance to end of period, and verify lock-in happens at the end
|
||||
self.nodes[0].generate(VB_PERIOD - 1)
|
||||
height = self.nodes[0].getblockcount()
|
||||
assert (height % VB_PERIOD) == VB_PERIOD - 2
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
|
||||
# Clear out the mempool
|
||||
self.nodes[0].generate(1)
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
|
||||
self.segwit_status = 'locked_in'
|
||||
self.sync_blocks()
|
||||
|
||||
@subtest
|
||||
def test_witness_tx_relay_before_segwit_activation(self):
|
||||
|
@ -686,7 +657,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
tx3.wit.vtxinwit.append(CTxInWitness())
|
||||
tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
|
||||
tx3.rehash()
|
||||
if self.segwit_status != 'active':
|
||||
if not self.segwit_active:
|
||||
# Just check mempool acceptance, but don't add the transaction to the mempool, since witness is disallowed
|
||||
# in blocks and the tx is impossible to mine right now.
|
||||
assert_equal(self.nodes[0].testmempoolaccept([tx3.serialize_with_witness().hex()]), [{'txid': tx3.hash, 'allowed': True}])
|
||||
|
@ -707,12 +678,13 @@ class SegWitTest(BitcoinTestFramework):
|
|||
@subtest
|
||||
def advance_to_segwit_active(self):
|
||||
"""Mine enough blocks to activate segwit."""
|
||||
assert not softfork_active(self.nodes[0], 'segwit')
|
||||
height = self.nodes[0].getblockcount()
|
||||
self.nodes[0].generate(VB_PERIOD - (height % VB_PERIOD) - 2)
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
|
||||
self.nodes[0].generate(SEGWIT_HEIGHT - height - 2)
|
||||
assert not softfork_active(self.nodes[0], 'segwit')
|
||||
self.nodes[0].generate(1)
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'active')
|
||||
self.segwit_status = 'active'
|
||||
assert softfork_active(self.nodes[0], 'segwit')
|
||||
self.segwit_active = True
|
||||
|
||||
@subtest
|
||||
def test_p2sh_witness(self):
|
||||
|
@ -1924,13 +1896,13 @@ class SegWitTest(BitcoinTestFramework):
|
|||
|
||||
# Restart with the new binary
|
||||
self.stop_node(2)
|
||||
self.start_node(2, extra_args=["-vbparams=segwit:0:999999999999"])
|
||||
self.start_node(2, extra_args=["-segwitheight={}".format(SEGWIT_HEIGHT)])
|
||||
connect_nodes(self.nodes[0], 2)
|
||||
|
||||
self.sync_blocks()
|
||||
|
||||
# Make sure that this peer thinks segwit has activated.
|
||||
assert get_bip9_status(self.nodes[2], 'segwit')['status'] == "active"
|
||||
assert softfork_active(self.nodes[2], 'segwit')
|
||||
|
||||
# Make sure this peer's blocks match those of node0.
|
||||
height = self.nodes[2].getblockcount()
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue