Merge bitcoin/bitcoin#22818: test: Activate all regtest softforks at height 1, unless overridden

fa4db8671bb604e11b43a837f91de8866226f166 test: Activate all regtest softforks at height 1, unless overridden (MarcoFalke)
faad1e5ffda255aecf1b0ea2152cd4f6805e678f Introduce -testactivationheight=name@height setting (MarcoFalke)
fadb2ef2fa8561882db463f35df9b8a0e9609658 test: Add extra_args argument to TestChain100Setup constructor (MarcoFalke)
faa46986aaec69e4cf016101ae517ce8778e2ac5 test: Remove version argument from build_next_block in p2p_segwit test (MarcoFalke)
fa086ef5398b5ffded86e4f0d6633c523cb774e9 test: Remove unused ~TestChain100Setup (MarcoFalke)

Pull request description:

  All softforks that are active at the tip of mainnet, should also be active from genesis in regtest. Otherwise their rules might not be enforced in user testing, thus making their testing less useful.

  To still allow tests to check pre-softfork rules, a runtime argument can change the activation height.

ACKs for top commit:
  laanwj:
    Code review ACK fa4db8671bb604e11b43a837f91de8866226f166
  theStack:
    re-ACK fa4db8671bb604e11b43a837f91de8866226f166

Tree-SHA512: 6397d46ff56ebc48c007a4cda633904d6ac085bc76b4ecf83097c546c7eec93ac0c44b88083b2611b9091c8d1fb8ee1e314065de078ef15e922c015de7ade8bf
This commit is contained in:
merge-script 2021-09-24 14:04:51 +02:00 committed by Konstantin Akimov
parent df07c38151
commit d1676b0280
No known key found for this signature in database
GPG Key ID: 2176C4A5D01EA524
15 changed files with 90 additions and 46 deletions

View File

@ -2,7 +2,5 @@ Tests
----- -----
- For the `regtest` network the activation heights of several softforks were - For the `regtest` network the activation heights of several softforks were
changed. (dash#6189) set to block height 1. They can be changed by the runtime setting
* BIP 34 (blockheight in coinbase) from 500 to 2 `-testactivationheight=name@height`. (dash#6214)
* BIP 66 (DERSIG) from 1251 to 102
* BIP 65 (CLTV) from 1351 to 111

View File

@ -794,12 +794,12 @@ public:
consensus.nGovernanceMinQuorum = 1; consensus.nGovernanceMinQuorum = 1;
consensus.nGovernanceFilterElements = 100; consensus.nGovernanceFilterElements = 100;
consensus.nMasternodeMinimumConfirmations = 1; consensus.nMasternodeMinimumConfirmations = 1;
consensus.BIP34Height = 2; // BIP34 activated on regtest (Block at height 1 not enforced for testing purposes) consensus.BIP34Height = 1; // Always active unless overridden
consensus.BIP34Hash = uint256(); consensus.BIP34Hash = uint256();
consensus.BIP65Height = 111; // BIP65 activated on regtest (Block at height 110 and earlier not enforced for testing purposes) consensus.BIP65Height = 1; // Always active unless overridden
consensus.BIP66Height = 102; // BIP66 activated on regtest (Block at height 101 and earlier not enforced for testing purposes) consensus.BIP66Height = 1; // Always active unless overridden
consensus.BIP147Height = 432; // BIP147 activated on regtest (Used in functional tests) consensus.BIP147Height = 1; // Always active unless overridden
consensus.CSVHeight = 432; // CSV activated on regtest (Used in rpc activation tests) consensus.CSVHeight = 1; // Always active unless overridden
consensus.DIP0001Height = 2000; consensus.DIP0001Height = 2000;
consensus.DIP0003Height = 432; consensus.DIP0003Height = 432;
consensus.DIP0003EnforcementHeight = 500; consensus.DIP0003EnforcementHeight = 500;
@ -1031,8 +1031,39 @@ public:
void UpdateLLMQInstantSendDIP0024FromArgs(const ArgsManager& args); void UpdateLLMQInstantSendDIP0024FromArgs(const ArgsManager& args);
}; };
static void MaybeUpdateHeights(const ArgsManager& args, Consensus::Params& consensus)
{
for (const std::string& arg : args.GetArgs("-testactivationheight")) {
const auto found{arg.find('@')};
if (found == std::string::npos) {
throw std::runtime_error(strprintf("Invalid format (%s) for -testactivationheight=name@height.", arg));
}
const auto name{arg.substr(0, found)};
const auto value{arg.substr(found + 1)};
int32_t height;
if (!ParseInt32(value, &height) || height < 0 || height >= std::numeric_limits<int>::max()) {
throw std::runtime_error(strprintf("Invalid height value (%s) for -testactivationheight=name@height.", arg));
}
if (name == "bip147") {
consensus.BIP147Height = int{height};
} else if (name == "bip34") {
consensus.BIP34Height = int{height};
} else if (name == "dersig") {
consensus.BIP66Height = int{height};
} else if (name == "cltv") {
consensus.BIP65Height = int{height};
} else if (name == "csv") {
consensus.CSVHeight = int{height};
} else {
throw std::runtime_error(strprintf("Invalid name (%s) for -testactivationheight=name@height.", arg));
}
}
}
void CRegTestParams::UpdateActivationParametersFromArgs(const ArgsManager& args) void CRegTestParams::UpdateActivationParametersFromArgs(const ArgsManager& args)
{ {
MaybeUpdateHeights(args, consensus);
if (!args.IsArgSet("-vbparams")) return; if (!args.IsArgSet("-vbparams")) return;
for (const std::string& strDeployment : args.GetArgs("-vbparams")) { for (const std::string& strDeployment : args.GetArgs("-vbparams")) {

View File

@ -22,6 +22,7 @@ void SetupChainParamsBaseOptions(ArgsManager& argsman)
argsman.AddArg("-dip3params=<activation>:<enforcement>", "Override DIP3 activation and enforcement heights (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-dip3params=<activation>:<enforcement>", "Override DIP3 activation and enforcement heights (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-dip8params=<activation>", "Override DIP8 activation height (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-dip8params=<activation>", "Override DIP8 activation height (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-bip147height=<activation>", "Override BIP147 activation height (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-bip147height=<activation>", "Override BIP147 activation height (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-testactivationheight=name@height.", "Set the activation height of 'name' (bip147, bip34, dersig, cltv, csv). (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-highsubsidyblocks=<n>", "The number of blocks with a higher than normal subsidy to mine at the start of a chain. Block after that height will have fixed subsidy base. (default: 0, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-highsubsidyblocks=<n>", "The number of blocks with a higher than normal subsidy to mine at the start of a chain. Block after that height will have fixed subsidy base. (default: 0, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-highsubsidyfactor=<n>", "The factor to multiply the normal block subsidy by while in the highsubsidyblocks window of a chain (default: 1, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-highsubsidyfactor=<n>", "The factor to multiply the normal block subsidy by while in the highsubsidyblocks window of a chain (default: 1, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-llmqchainlocks=<quorum name>", "Override the default LLMQ type used for ChainLocks. Allows using ChainLocks with smaller LLMQs. (default: llmq_devnet, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-llmqchainlocks=<quorum name>", "Override the default LLMQ type used for ChainLocks. Allows using ChainLocks with smaller LLMQs. (default: llmq_devnet, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);

View File

@ -12,11 +12,16 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
struct Dersig100Setup : public TestChain100Setup {
Dersig100Setup()
: TestChain100Setup{{"-testactivationheight=dersig@102"}} {}
};
bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks); bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks);
BOOST_AUTO_TEST_SUITE(txvalidationcache_tests) BOOST_AUTO_TEST_SUITE(txvalidationcache_tests)
BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup)
{ {
// Make sure skipping validation of transactions that were // Make sure skipping validation of transactions that were
// validated going into the memory pool does not allow // validated going into the memory pool does not allow
@ -144,7 +149,7 @@ static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t fail
} }
} }
BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) BOOST_FIXTURE_TEST_CASE(checkinputs_test, Dersig100Setup)
{ {
// Test that passing CheckInputScripts with one set of script flags doesn't imply // Test that passing CheckInputScripts with one set of script flags doesn't imply
// that we would pass again with a different set of flags. // that we would pass again with a different set of flags.

View File

@ -306,6 +306,11 @@ TestingSetup::~TestingSetup()
m_node.banman.reset(); m_node.banman.reset();
} }
TestChain100Setup::TestChain100Setup(const std::vector<const char*>& extra_args)
: TestChainSetup{100, extra_args}
{
}
TestChainSetup::TestChainSetup(int num_blocks, const std::vector<const char*>& extra_args) TestChainSetup::TestChainSetup(int num_blocks, const std::vector<const char*>& extra_args)
: RegTestingSetup(extra_args) : RegTestingSetup(extra_args)
{ {

View File

@ -177,7 +177,7 @@ struct TestChainSetup : public RegTestingSetup
* Testing fixture that pre-creates a 100-block REGTEST-mode block chain * Testing fixture that pre-creates a 100-block REGTEST-mode block chain
*/ */
struct TestChain100Setup : public TestChainSetup { struct TestChain100Setup : public TestChainSetup {
TestChain100Setup() : TestChainSetup(100) {} TestChain100Setup(const std::vector<const char*>& extra_args = {});
}; };
struct TestChainDIP3Setup : public TestChainSetup struct TestChainDIP3Setup : public TestChainSetup

View File

@ -38,8 +38,14 @@ class BIP68Test(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.num_nodes = 2 self.num_nodes = 2
self.extra_args = [ self.extra_args = [
["-acceptnonstdtxn=1"], [
["-acceptnonstdtxn=0"], '-testactivationheight=csv@432',
"-acceptnonstdtxn=1",
],
[
'-testactivationheight=csv@432',
"-acceptnonstdtxn=0",
],
] ]
def skip_test_if_missing_module(self): def skip_test_if_missing_module(self):

View File

@ -83,7 +83,11 @@ class FullBlockTest(BitcoinTestFramework):
# which causes RPC to hang, so we need to increase RPC timeouts # which causes RPC to hang, so we need to increase RPC timeouts
self.rpc_timeout = 180 self.rpc_timeout = 180
# Must set '-dip3params=2000:2000' to create pre-dip3 blocks only # Must set '-dip3params=2000:2000' to create pre-dip3 blocks only
self.extra_args = [['-dip3params=2000:2000', '-acceptnonstdtxn=1']] # This is a consensus block test, we don't care about tx policy self.extra_args = [[
'-dip3params=2000:2000',
'-acceptnonstdtxn=1', # This is a consensus block test, we don't care about tx policy
'-testactivationheight=bip34@2',
]]
def setup_nodes(self): def setup_nodes(self):
self.add_nodes(self.num_nodes, self.extra_args) self.add_nodes(self.num_nodes, self.extra_args)

View File

@ -8,7 +8,6 @@ Test that the CHECKLOCKTIMEVERIFY soft-fork activates.
""" """
from test_framework.blocktools import ( from test_framework.blocktools import (
CLTV_HEIGHT,
create_block, create_block,
create_coinbase, create_coinbase,
) )
@ -79,10 +78,14 @@ def cltv_validate(tx, height):
cltv_modify_tx(tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2]) cltv_modify_tx(tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2])
CLTV_HEIGHT = 111
class BIP65Test(BitcoinTestFramework): class BIP65Test(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.num_nodes = 1 self.num_nodes = 1
self.extra_args = [[ self.extra_args = [[
f'-testactivationheight=cltv@{CLTV_HEIGHT}',
'-whitelist=noban@127.0.0.1', '-whitelist=noban@127.0.0.1',
'-dip3params=9000:9000', '-dip3params=9000:9000',
'-par=1', # Use only one script thread to get the exact reject reason for testing '-par=1', # Use only one script thread to get the exact reject reason for testing

View File

@ -40,7 +40,6 @@ bip112tx_emptystack - test empty stack (= no argument) OP_CSV
from itertools import product from itertools import product
from test_framework.blocktools import ( from test_framework.blocktools import (
CSV_ACTIVATION_HEIGHT,
create_block, create_block,
create_coinbase, create_coinbase,
TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK,
@ -89,6 +88,9 @@ def all_rlt_txs(txs):
return [tx['tx'] for tx in txs] return [tx['tx'] for tx in txs]
CSV_ACTIVATION_HEIGHT = 432
class BIP68_112_113Test(BitcoinTestFramework): class BIP68_112_113Test(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.num_nodes = 1 self.num_nodes = 1
@ -98,6 +100,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
'-peertimeout=999999', # bump because mocktime might cause a disconnect otherwise '-peertimeout=999999', # bump because mocktime might cause a disconnect otherwise
'-whitelist=noban@127.0.0.1', '-whitelist=noban@127.0.0.1',
'-dip3params=2000:2000', '-dip3params=2000:2000',
f'-testactivationheight=csv@{CSV_ACTIVATION_HEIGHT}',
'-par=1', # Use only one script thread to get the exact reject reason for testing '-par=1', # Use only one script thread to get the exact reject reason for testing
]] ]]
self.supports_cli = False self.supports_cli = False

View File

@ -8,7 +8,6 @@ Test the DERSIG soft-fork activation on regtest.
""" """
from test_framework.blocktools import ( from test_framework.blocktools import (
DERSIG_HEIGHT,
create_block, create_block,
create_coinbase, create_coinbase,
) )
@ -43,10 +42,18 @@ def unDERify(tx):
tx.vin[0].scriptSig = CScript(newscript) tx.vin[0].scriptSig = CScript(newscript)
DERSIG_HEIGHT = 102
class BIP66Test(BitcoinTestFramework): class BIP66Test(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.num_nodes = 1 self.num_nodes = 1
self.extra_args = [['-whitelist=noban@127.0.0.1', '-dip3params=9000:9000', '-par=1', '-vbparams=v20:0:999999999999:0:480:384:288:5:0']] # Use only one script thread to get the exact reject reason for testing self.extra_args = [[
f'-testactivationheight=dersig@{DERSIG_HEIGHT}',
'-whitelist=noban@127.0.0.1',
'-dip3params=9000:9000',
'-par=1', # Use only one script thread to get the exact log msg for testing
'-vbparams=v20:0:999999999999:0:480:384:288:5:0']]
self.setup_clean_chain = True self.setup_clean_chain = True
self.rpc_timeout = 240 self.rpc_timeout = 240
@ -81,7 +88,6 @@ class BIP66Test(BitcoinTestFramework):
tip = self.nodes[0].getbestblockhash() tip = self.nodes[0].getbestblockhash()
block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1 block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1
block = create_block(int(tip, 16), create_coinbase(DERSIG_HEIGHT - 1), block_time) block = create_block(int(tip, 16), create_coinbase(DERSIG_HEIGHT - 1), block_time)
block.nVersion = 2
block.vtx.append(spendtx) block.vtx.append(spendtx)
block.hashMerkleRoot = block.calc_merkle_root() block.hashMerkleRoot = block.calc_merkle_root()
block.rehash() block.rehash()
@ -108,7 +114,7 @@ class BIP66Test(BitcoinTestFramework):
peer.sync_with_ping() peer.sync_with_ping()
self.log.info("Test that transactions with non-DER signatures cannot appear in a block") self.log.info("Test that transactions with non-DER signatures cannot appear in a block")
block.nVersion = 3 block.nVersion = 4
spendtx = self.create_tx(self.coinbase_txids[1]) spendtx = self.create_tx(self.coinbase_txids[1])
unDERify(spendtx) unDERify(spendtx)
@ -129,7 +135,7 @@ class BIP66Test(BitcoinTestFramework):
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
peer.sync_with_ping() peer.sync_with_ping()
self.log.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted") self.log.info("Test that a block with a DERSIG-compliant transaction is accepted")
block.vtx[1] = self.create_tx(self.coinbase_txids[1]) block.vtx[1] = self.create_tx(self.coinbase_txids[1])
block.hashMerkleRoot = block.calc_merkle_root() block.hashMerkleRoot = block.calc_merkle_root()
block.rehash() block.rehash()

View File

@ -50,7 +50,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.extra_args = [[ self.extra_args = [[
'-whitelist=127.0.0.1', '-whitelist=127.0.0.1',
'-dip3params=105:105', '-dip3params=105:105',
'-bip147height=105', f'-testactivationheight=bip147@{COINBASE_MATURITY + 5}',
'-par=1', # Use only one script thread to get the exact reject reason for testing '-par=1', # Use only one script thread to get the exact reject reason for testing
]] * 2 ]] * 2

View File

@ -27,8 +27,6 @@ import subprocess
from test_framework.address import ADDRESS_BCRT1_P2SH_OP_TRUE from test_framework.address import ADDRESS_BCRT1_P2SH_OP_TRUE
from test_framework.blocktools import ( from test_framework.blocktools import (
CLTV_HEIGHT,
DERSIG_HEIGHT,
create_block, create_block,
create_coinbase, create_coinbase,
TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK,
@ -144,11 +142,11 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(res['prune_target_size'], 576716800) assert_equal(res['prune_target_size'], 576716800)
assert_greater_than(res['size_on_disk'], 0) assert_greater_than(res['size_on_disk'], 0)
assert_equal(res['softforks'], { assert_equal(res['softforks'], {
'bip34': {'type': 'buried', 'active': True, 'height': 2}, 'bip34': {'type': 'buried', 'active': True, 'height': 1},
'bip66': {'type': 'buried', 'active': True, 'height': DERSIG_HEIGHT}, 'bip66': {'type': 'buried', 'active': True, 'height': 1},
'bip65': {'type': 'buried', 'active': True, 'height': CLTV_HEIGHT}, 'bip65': {'type': 'buried', 'active': True, 'height': 1},
'bip147': { 'type': 'buried', 'active': False, 'height': 432}, 'bip147': { 'type': 'buried', 'active': True, 'height': 1},
'csv': {'type': 'buried', 'active': False, 'height': 432}, 'csv': {'type': 'buried', 'active': True, 'height': 1},
'dip0001': { 'type': 'buried', 'active': False, 'height': 2000}, 'dip0001': { 'type': 'buried', 'active': False, 'height': 2000},
'dip0003': { 'type': 'buried', 'active': False, 'height': 432}, 'dip0003': { 'type': 'buried', 'active': False, 'height': 432},
'dip0008': { 'type': 'buried', 'active': False, 'height': 432}, 'dip0008': { 'type': 'buried', 'active': False, 'height': 432},

View File

@ -35,11 +35,6 @@ TIME_GENESIS_BLOCK = 1417713337
# Coinbase transaction outputs can only be spent after this number of new blocks (network rule) # Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
COINBASE_MATURITY = 100 COINBASE_MATURITY = 100
# Soft-fork activation heights
DERSIG_HEIGHT = 102 # BIP 66
CLTV_HEIGHT = 111 # BIP 65
CSV_ACTIVATION_HEIGHT = 432
NORMAL_GBT_REQUEST_PARAMS = {"rules": []} # type: ignore[var-annotated] NORMAL_GBT_REQUEST_PARAMS = {"rules": []} # type: ignore[var-annotated]
VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4 VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4

View File

@ -601,17 +601,6 @@ def mine_large_block(node, utxos=None):
node.generate(1) node.generate(1)
def generate_to_height(node, target_height):
"""Generates blocks until a given target block height has been reached.
To prevent timeouts, only up to 200 blocks are generated per RPC call.
Can be used to activate certain soft-forks (e.g. CSV, CLTV)."""
current_height = node.getblockcount()
while current_height < target_height:
nblocks = min(200, target_height - current_height)
current_height += len(node.generate(nblocks))
assert_equal(node.getblockcount(), target_height)
def find_vout_for_address(node, txid, addr): def find_vout_for_address(node, txid, addr):
""" """
Locate the vout index of the given transaction sending to the Locate the vout index of the given transaction sending to the