Skip to content

Commit dd56166

Browse files
author
MarcoFalke
committed
Merge #11389: Support having SegWit always active in regtest (sipa, ajtowns, jnewbery)
d618458 Have SegWit active by default (Pieter Wuille) 4bd8921 Unit tests for always-active versionbits. (Anthony Towns) d07ee77 Always-active versionbits support (Pieter Wuille) 18e0718 [consensus] Pin P2SH activation to block 173805 on mainnet (John Newbery) 526023a Improve handling of BIP9Deployment limits (Anthony Towns) Pull request description: Most tests shouldn't have to deal with the now-historical SegWit activation transition (and other deployments, but SegWit is certainly the hardest one to accomodate). This PR makes a versionbits starttime of -1 equal to "always active", and enables it by default for SegWit on regtest. Individual tests can override this by using the existing `-vbparams` option. A few unit tests and functional tests are adapted to indeed override vbparams, as they specifically test the transition. This is in preparation for wallet SegWit support, but I thought having earlier eyes on it would be useful. Tree-SHA512: 3f07a7b41cf46476e6c7a5c43244e68c9f41d223482cedaa4c02a3a7b7cd0e90cbd06b84a1f3704620559636a2268f5767d4c52d09c1b354945737046f618fe5
2 parents 6f01dcf + d618458 commit dd56166

16 files changed

+96
-40
lines changed

src/chainparams.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class CMainParams : public CChainParams {
7575
CMainParams() {
7676
strNetworkID = "main";
7777
consensus.nSubsidyHalvingInterval = 210000;
78+
consensus.BIP16Height = 173805; // 00000000000000ce80a7e057163a4db1d5ad7b20fb6f598c9597b9665c8fb0d4 - April 1, 2012
7879
consensus.BIP34Height = 227931;
7980
consensus.BIP34Hash = uint256S("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8");
8081
consensus.BIP65Height = 388381; // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0
@@ -181,6 +182,7 @@ class CTestNetParams : public CChainParams {
181182
CTestNetParams() {
182183
strNetworkID = "test";
183184
consensus.nSubsidyHalvingInterval = 210000;
185+
consensus.BIP16Height = 514; // 00000000040b4e986385315e14bee30ad876d8b47f748025b26683116d21aa65
184186
consensus.BIP34Height = 21111;
185187
consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8");
186188
consensus.BIP65Height = 581885; // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6
@@ -270,6 +272,7 @@ class CRegTestParams : public CChainParams {
270272
CRegTestParams() {
271273
strNetworkID = "regtest";
272274
consensus.nSubsidyHalvingInterval = 150;
275+
consensus.BIP16Height = 0; // always enforce P2SH BIP16 on regtest
273276
consensus.BIP34Height = 100000000; // BIP34 has not activated on regtest (far in the future so block v1 are not rejected in tests)
274277
consensus.BIP34Hash = uint256();
275278
consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests)
@@ -283,13 +286,13 @@ class CRegTestParams : public CChainParams {
283286
consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016)
284287
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
285288
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0;
286-
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 999999999999ULL;
289+
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
287290
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
288291
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0;
289-
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 999999999999ULL;
292+
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
290293
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
291-
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 0;
292-
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 999999999999ULL;
294+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
295+
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
293296

294297
// The best chain should have at least this much work.
295298
consensus.nMinimumChainWork = uint256S("0x00");

src/consensus/params.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define BITCOIN_CONSENSUS_PARAMS_H
88

99
#include "uint256.h"
10+
#include <limits>
1011
#include <map>
1112
#include <string>
1213

@@ -31,6 +32,15 @@ struct BIP9Deployment {
3132
int64_t nStartTime;
3233
/** Timeout/expiry MedianTime for the deployment attempt. */
3334
int64_t nTimeout;
35+
36+
/** Constant for nTimeout very far in the future. */
37+
static constexpr int64_t NO_TIMEOUT = std::numeric_limits<int64_t>::max();
38+
39+
/** Special value for nStartTime indicating that the deployment is always active.
40+
* This is useful for testing, as it means tests don't need to deal with the activation
41+
* process (which takes at least 3 BIP9 intervals). Only tests that specifically test the
42+
* behaviour during activation cannot use this. */
43+
static constexpr int64_t ALWAYS_ACTIVE = -1;
3444
};
3545

3646
/**
@@ -39,6 +49,8 @@ struct BIP9Deployment {
3949
struct Params {
4050
uint256 hashGenesisBlock;
4151
int nSubsidyHalvingInterval;
52+
/** Block height at which BIP16 becomes active */
53+
int BIP16Height;
4254
/** Block height and hash at which BIP34 becomes active */
4355
int BIP34Height;
4456
uint256 BIP34Hash;

src/test/miner_tests.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -335,23 +335,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
335335
BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
336336
mempool.clear();
337337

338-
// invalid (pre-p2sh) txn in mempool, template creation fails
339-
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
340-
tx.vin[0].prevout.n = 0;
341-
tx.vin[0].scriptSig = CScript() << OP_1;
342-
tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE;
343-
script = CScript() << OP_0;
344-
tx.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(script));
345-
hash = tx.GetHash();
346-
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
347-
tx.vin[0].prevout.hash = hash;
348-
tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
349-
tx.vout[0].nValue -= LOWFEE;
350-
hash = tx.GetHash();
351-
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
352-
BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
353-
mempool.clear();
354-
355338
// double spend txn pair in mempool, template creation fails
356339
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
357340
tx.vin[0].scriptSig = CScript() << OP_1;
@@ -391,6 +374,24 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
391374
chainActive.SetTip(next);
392375
}
393376
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
377+
378+
// invalid p2sh txn in mempool, template creation fails
379+
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
380+
tx.vin[0].prevout.n = 0;
381+
tx.vin[0].scriptSig = CScript() << OP_1;
382+
tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE;
383+
script = CScript() << OP_0;
384+
tx.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(script));
385+
hash = tx.GetHash();
386+
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
387+
tx.vin[0].prevout.hash = hash;
388+
tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
389+
tx.vout[0].nValue -= LOWFEE;
390+
hash = tx.GetHash();
391+
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
392+
BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
393+
mempool.clear();
394+
394395
// Delete the dummy blocks again.
395396
while (chainActive.Tip()->nHeight > nHeight) {
396397
CBlockIndex* del = chainActive.Tip();

src/test/test_bitcoin.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ TestingSetup::~TestingSetup()
118118

119119
TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
120120
{
121+
// CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests.
122+
// TODO: fix the code to support SegWit blocks.
123+
UpdateVersionBitsParameters(Consensus::DEPLOYMENT_SEGWIT, 0, Consensus::BIP9Deployment::NO_TIMEOUT);
121124
// Generate a 100-block chain:
122125
coinbaseKey.MakeNewKey(true);
123126
CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;

src/test/versionbits_tests.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ class TestConditionChecker : public AbstractThresholdConditionChecker
3232
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, paramsDummy, cache); }
3333
};
3434

35+
class TestAlwaysActiveConditionChecker : public TestConditionChecker
36+
{
37+
public:
38+
int64_t BeginTime(const Consensus::Params& params) const override { return Consensus::BIP9Deployment::ALWAYS_ACTIVE; }
39+
};
40+
3541
#define CHECKERS 6
3642

3743
class VersionBitsTester
@@ -43,6 +49,8 @@ class VersionBitsTester
4349
// The first one performs all checks, the second only 50%, the third only 25%, etc...
4450
// This is to test whether lack of cached information leads to the same results.
4551
TestConditionChecker checker[CHECKERS];
52+
// Another 6 that assume always active activation
53+
TestAlwaysActiveConditionChecker checker_always[CHECKERS];
4654

4755
// Test counter (to identify failures)
4856
int num;
@@ -56,6 +64,7 @@ class VersionBitsTester
5664
}
5765
for (unsigned int i = 0; i < CHECKERS; i++) {
5866
checker[i] = TestConditionChecker();
67+
checker_always[i] = TestAlwaysActiveConditionChecker();
5968
}
6069
vpblock.clear();
6170
return *this;
@@ -82,6 +91,7 @@ class VersionBitsTester
8291
for (int i = 0; i < CHECKERS; i++) {
8392
if (InsecureRandBits(i) == 0) {
8493
BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()) == height, strprintf("Test %i for StateSinceHeight", num));
94+
BOOST_CHECK_MESSAGE(checker_always[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()) == 0, strprintf("Test %i for StateSinceHeight (always active)", num));
8595
}
8696
}
8797
num++;
@@ -92,6 +102,7 @@ class VersionBitsTester
92102
for (int i = 0; i < CHECKERS; i++) {
93103
if (InsecureRandBits(i) == 0) {
94104
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_DEFINED, strprintf("Test %i for DEFINED", num));
105+
BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
95106
}
96107
}
97108
num++;
@@ -102,6 +113,7 @@ class VersionBitsTester
102113
for (int i = 0; i < CHECKERS; i++) {
103114
if (InsecureRandBits(i) == 0) {
104115
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_STARTED, strprintf("Test %i for STARTED", num));
116+
BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
105117
}
106118
}
107119
num++;
@@ -112,6 +124,7 @@ class VersionBitsTester
112124
for (int i = 0; i < CHECKERS; i++) {
113125
if (InsecureRandBits(i) == 0) {
114126
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_LOCKED_IN, strprintf("Test %i for LOCKED_IN", num));
127+
BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
115128
}
116129
}
117130
num++;
@@ -122,6 +135,7 @@ class VersionBitsTester
122135
for (int i = 0; i < CHECKERS; i++) {
123136
if (InsecureRandBits(i) == 0) {
124137
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE", num));
138+
BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
125139
}
126140
}
127141
num++;
@@ -132,6 +146,7 @@ class VersionBitsTester
132146
for (int i = 0; i < CHECKERS; i++) {
133147
if (InsecureRandBits(i) == 0) {
134148
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_FAILED, strprintf("Test %i for FAILED", num));
149+
BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
135150
}
136151
}
137152
num++;

src/validation.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,11 +1611,12 @@ static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS];
16111611
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) {
16121612
AssertLockHeld(cs_main);
16131613

1614-
// BIP16 didn't become active until Apr 1 2012
1615-
int64_t nBIP16SwitchTime = 1333238400;
1616-
bool fStrictPayToScriptHash = (pindex->GetBlockTime() >= nBIP16SwitchTime);
1614+
unsigned int flags = SCRIPT_VERIFY_NONE;
16171615

1618-
unsigned int flags = fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE;
1616+
// Start enforcing P2SH (BIP16)
1617+
if (pindex->nHeight >= consensusparams.BIP16Height) {
1618+
flags |= SCRIPT_VERIFY_P2SH;
1619+
}
16191620

16201621
// Start enforcing the DERSIG (BIP66) rule
16211622
if (pindex->nHeight >= consensusparams.BIP66Height) {

src/versionbits.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
2727
int64_t nTimeStart = BeginTime(params);
2828
int64_t nTimeTimeout = EndTime(params);
2929

30+
// Check if this deployment is always active.
31+
if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
32+
return THRESHOLD_ACTIVE;
33+
}
34+
3035
// A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
3136
if (pindexPrev != nullptr) {
3237
pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
@@ -136,6 +141,11 @@ BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockI
136141

137142
int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
138143
{
144+
int64_t start_time = BeginTime(params);
145+
if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
146+
return 0;
147+
}
148+
139149
const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
140150

141151
// BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."

test/functional/nulldummy.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ class NULLDUMMYTest(BitcoinTestFramework):
4040
def set_test_params(self):
4141
self.num_nodes = 1
4242
self.setup_clean_chain = True
43-
self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness']]
43+
# This script tests NULLDUMMY activation, which is part of the 'segwit' deployment, so we go through
44+
# normal segwit activation here (and don't use the default always-on behaviour).
45+
self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness', '-vbparams=segwit:0:999999999999']]
4446

4547
def run_test(self):
4648
self.address = self.nodes[0].getnewaddress()

test/functional/p2p-compactblocks.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ def set_test_params(self):
9393
self.setup_clean_chain = True
9494
# Node0 = pre-segwit, node1 = segwit-aware
9595
self.num_nodes = 2
96-
self.extra_args = [["-vbparams=segwit:0:0"], ["-txindex"]]
96+
# This test was written assuming SegWit is activated using BIP9 at height 432 (3x confirmation window).
97+
# TODO: Rewrite this test to support SegWit being always active.
98+
self.extra_args = [["-vbparams=segwit:0:0"], ["-vbparams=segwit:0:999999999999", "-txindex"]]
9799
self.utxos = []
98100

99101
def build_block_on_tip(self, node, segwit=False):

test/functional/p2p-segwit.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ class SegWitTest(BitcoinTestFramework):
111111
def set_test_params(self):
112112
self.setup_clean_chain = True
113113
self.num_nodes = 3
114-
self.extra_args = [["-whitelist=127.0.0.1"], ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0"], ["-whitelist=127.0.0.1", "-vbparams=segwit:0:0"]]
114+
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
115+
self.extra_args = [["-whitelist=127.0.0.1", "-vbparams=segwit:0:999999999999"], ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0", "-vbparams=segwit:0:999999999999"], ["-whitelist=127.0.0.1", "-vbparams=segwit:0:0"]]
115116

116117
def setup_network(self):
117118
self.setup_nodes()
@@ -1493,7 +1494,7 @@ def test_upgrade_after_activation(self, node_id):
14931494

14941495
# Restart with the new binary
14951496
self.stop_node(node_id)
1496-
self.start_node(node_id, extra_args=[])
1497+
self.start_node(node_id, extra_args=["-vbparams=segwit:0:999999999999"])
14971498
connect_nodes(self.nodes[0], node_id)
14981499

14991500
sync_blocks(self.nodes)

0 commit comments

Comments
 (0)