Merge 8e9801bfc4 into merged_master (Bitcoin PR bitcoin/bitcoin#22818)

This commit is contained in:
Byron Hambly 2023-04-24 07:13:42 +00:00
commit 13fb374543
19 changed files with 98 additions and 91 deletions

View file

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

View file

@ -566,12 +566,12 @@ public:
consensus.signet_challenge.clear();
consensus.nSubsidyHalvingInterval = 150;
consensus.BIP16Exception = uint256();
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.BIP65Height = 111; // BIP65 activated on regtest (Block at height 110 and earlier not enforced for testing purposes)
consensus.BIP66Height = 102; // BIP66 activated on regtest (Block at height 101 and earlier not enforced for testing purposes)
consensus.CSVHeight = 432; // CSV activated on regtest (Used in rpc activation tests)
consensus.SegwitHeight = 0; // SEGWIT is always activated on regtest unless overridden
consensus.BIP65Height = 1; // Always active unless overridden
consensus.BIP66Height = 1; // Always active unless overridden
consensus.CSVHeight = 1; // Always active unless overridden
consensus.SegwitHeight = 1; // Always active unless overridden
consensus.MinBIP9WarningHeight = 0;
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
@ -685,15 +685,38 @@ public:
void UpdateActivationParametersFromArgs(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 == "segwit") {
consensus.SegwitHeight = 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)
{
if (args.IsArgSet("-segwitheight")) {
int64_t height = args.GetArg("-segwitheight", consensus.SegwitHeight);
if (height < 0 || height >= std::numeric_limits<int>::max()) {
throw std::runtime_error(strprintf("Activation height %ld for segwit is out of valid range.", height));
}
consensus.SegwitHeight = static_cast<int>(height);
}
MaybeUpdateHeights(args, consensus);
if (!args.IsArgSet("-vbparams")) return;

View file

@ -25,7 +25,7 @@ void SetupChainParamsBaseOptions(ArgsManager& argsman)
argsman.AddArg("-chain=<chain>", "Use the chain <chain> (default: liquidv1). Reserved values: main, test, signet, regtest, liquidv1, liquidv1test", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
argsman.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. Equivalent to -chain=regtest.", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-segwitheight=<n>", "Set the activation height of segwit. (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-testactivationheight=name@height.", "Set the activation height of 'name' (segwit, bip34, dersig, cltv, csv). (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-testnet", "Use the test chain. Equivalent to -chain=test.", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-vbparams=deployment:start:end[:min_activation_height]", "Use given start/end times and min_activation_height for specified version bits deployment (regtest or custom only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-seednode=<ip>", "Use specified node as seed node. This option can be specified multiple times to connect to multiple nodes. (custom only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);

View file

@ -14,6 +14,11 @@
#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,
@ -21,7 +26,7 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
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
// validated going into the memory pool does not allow
@ -162,7 +167,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
// that we would pass again with a different set of flags.

View file

@ -230,7 +230,8 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::string& fedp
}
}
TestChain100Setup::TestChain100Setup()
TestChain100Setup::TestChain100Setup(const std::vector<const char*>& extra_args)
: TestingSetup{CBaseChainParams::REGTEST, extra_args}
{
SetMockTime(1598887952);
constexpr std::array<unsigned char, 32> vchKey = {
@ -346,11 +347,6 @@ CMutableTransaction TestChain100Setup::CreateValidMempoolTransaction(CTransactio
return mempool_txn;
}
TestChain100Setup::~TestChain100Setup()
{
gArgs.ForceSetArg("-segwitheight", "0");
}
CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction& tx) const
{
return FromTx(MakeTransactionRef(tx));

View file

@ -113,8 +113,8 @@ class CScript;
/**
* Testing fixture that pre-creates a 100-block REGTEST-mode block chain
*/
struct TestChain100Setup : public RegTestingSetup {
TestChain100Setup();
struct TestChain100Setup : public TestingSetup {
TestChain100Setup(const std::vector<const char*>& extra_args = {});
/**
* Create a new block with just given transactions, coinbase paying to
@ -156,8 +156,6 @@ struct TestChain100Setup : public RegTestingSetup {
CAmount output_amount = CAmount(1 * COIN),
bool submit = true);
~TestChain100Setup();
std::vector<CTransactionRef> m_coinbase_txns; // For convenience, coinbase transactions
CKey coinbaseKey; // private/public key needed to spend coinbase transactions
};

View file

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

View file

@ -82,7 +82,10 @@ class FullBlockTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
self.extra_args = [['-acceptnonstdtxn=1']] # This is a consensus block test, we don't care about tx policy
self.extra_args = [[
'-acceptnonstdtxn=1', # This is a consensus block test, we don't care about tx policy
'-testactivationheight=bip34@2',
]]
def run_test(self):
node = self.nodes[0] # convenience reference to the node

View file

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

View file

@ -41,7 +41,6 @@ from itertools import product
import time
from test_framework.blocktools import (
CSV_ACTIVATION_HEIGHT,
create_block,
create_coinbase,
)
@ -88,12 +87,17 @@ def relative_locktime(sdf, srhb, stf, srlb):
def all_rlt_txs(txs):
return [tx['tx'] for tx in txs]
CSV_ACTIVATION_HEIGHT = 432
class BIP68_112_113Test(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
self.extra_args = [[
'-whitelist=noban@127.0.0.1',
f'-testactivationheight=csv@{CSV_ACTIVATION_HEIGHT}',
'-par=1', # Use only one script thread to get the exact reject reason for testing
]]
self.supports_cli = False

View file

@ -8,7 +8,6 @@ Test the DERSIG soft-fork activation on regtest.
"""
from test_framework.blocktools import (
DERSIG_HEIGHT,
create_block,
create_coinbase,
)
@ -42,10 +41,14 @@ def unDERify(tx):
tx.vin[0].scriptSig = CScript(newscript)
DERSIG_HEIGHT = 102
class BIP66Test(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.extra_args = [[
f'-testactivationheight=dersig@{DERSIG_HEIGHT}',
'-whitelist=noban@127.0.0.1',
'-par=1', # Use only one script thread to get the exact log msg for testing
]]
@ -83,7 +86,6 @@ class BIP66Test(BitcoinTestFramework):
tip = self.nodes[0].getbestblockhash()
block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1
block = create_block(int(tip, 16), create_coinbase(DERSIG_HEIGHT - 1), block_time)
block.nVersion = 2
block.vtx.append(spendtx)
block.hashMerkleRoot = block.calc_merkle_root()
block.rehash()
@ -110,7 +112,7 @@ class BIP66Test(BitcoinTestFramework):
peer.sync_with_ping()
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])
unDERify(spendtx)
@ -139,7 +141,7 @@ class BIP66Test(BitcoinTestFramework):
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
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.hashMerkleRoot = block.calc_merkle_root()
block.rehash()

View file

@ -53,7 +53,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
# 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 = [[
f'-segwitheight={COINBASE_MATURITY + 5}',
f'-testactivationheight=segwit@{COINBASE_MATURITY + 5}',
'-addresstype=legacy',
'-par=1', # Use only one script thread to get the exact reject reason for testing
]]

View file

@ -16,7 +16,7 @@ class SegwitUpgradeTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
self.extra_args = [["-segwitheight=10"]]
self.extra_args = [["-testactivationheight=segwit@10"]]
def run_test(self):
"""A pre-segwit node with insufficiently validated blocks needs to redownload blocks"""
@ -37,14 +37,14 @@ class SegwitUpgradeTest(BitcoinTestFramework):
# Restarting the node (with segwit activation height set to 5) should result in a shutdown
# because the blockchain consists of 3 insufficiently validated blocks per segwit consensus rules.
node.assert_start_raises_init_error(
extra_args=["-segwitheight=5"],
extra_args=["-testactivationheight=segwit@5"],
expected_msg=": Witness data for blocks after height 5 requires "
f"validation. Please restart with -reindex..{os.linesep}"
"Please restart with -reindex or -reindex-chainstate to recover.",
)
# As directed, the user restarts the node with -reindex
self.start_node(0, extra_args=["-reindex", "-segwitheight=5"])
self.start_node(0, extra_args=["-reindex", "-testactivationheight=segwit@5"])
# With the segwit consensus rules, the node is able to validate only up to block 4
assert_equal(node.getblockcount(), 4)

View file

@ -79,18 +79,18 @@ class SegWitTest(BitcoinTestFramework):
[
"-acceptnonstdtxn=1",
"-rpcserialversion=0",
"-segwitheight=432",
"-testactivationheight=segwit@432",
"-addresstype=legacy",
],
[
"-acceptnonstdtxn=1",
"-rpcserialversion=1",
"-segwitheight=432",
"-testactivationheight=segwit@432",
"-addresstype=legacy",
],
[
"-acceptnonstdtxn=1",
"-segwitheight=432",
"-testactivationheight=segwit@432",
"-addresstype=legacy",
],
]

View file

@ -88,10 +88,6 @@ from test_framework.util import (
)
from test_framework import util
# The versionbit bit used to signal activation of SegWit
VB_WITNESS_BIT = 1
VB_TOP_BITS = 0x20000000
MAX_SIGOP_COST = 80000
SEGWIT_HEIGHT = 120
@ -201,8 +197,8 @@ class SegWitTest(BitcoinTestFramework):
self.num_nodes = 2
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
self.extra_args = [
["-acceptnonstdtxn=1", "-segwitheight={}".format(SEGWIT_HEIGHT), "-whitelist=noban@127.0.0.1"],
["-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT)],
["-acceptnonstdtxn=1", f"-testactivationheight=segwit@{SEGWIT_HEIGHT}", "-whitelist=noban@127.0.0.1"],
["-acceptnonstdtxn=0", f"-testactivationheight=segwit@{SEGWIT_HEIGHT}"],
]
self.supports_cli = False
@ -211,13 +207,13 @@ class SegWitTest(BitcoinTestFramework):
# Helper functions
def build_next_block(self, version=4):
def build_next_block(self):
"""Build a block on top of node0's tip."""
tip = self.nodes[0].getbestblockhash()
height = self.nodes[0].getblockcount() + 1
block_time = self.nodes[0].getblockheader(tip)["mediantime"] + 1
block = create_block(int(tip, 16), create_coinbase(height), block_time)
block.nVersion = version
block.nVersion = 4
block.rehash()
return block
@ -304,7 +300,7 @@ class SegWitTest(BitcoinTestFramework):
# Mine a block with an anyone-can-spend coinbase,
# let it mature, then try to spend it.
block = self.build_next_block(version=1)
block = self.build_next_block()
block.solve()
self.test_node.send_and_ping(msg_no_witness_block(block)) # make sure the block was processed
txid = block.vtx[0].sha256
@ -344,8 +340,8 @@ class SegWitTest(BitcoinTestFramework):
tx.rehash()
assert tx.sha256 != tx.calc_sha256(with_witness=True)
# Construct a segwit-signaling block that includes the transaction.
block = self.build_next_block(version=(VB_TOP_BITS | (1 << VB_WITNESS_BIT)))
# Construct a block that includes the transaction.
block = self.build_next_block()
self.update_witness_block_with_transactions(block, [tx])
# Sending witness data before activation is not allowed (anti-spam
# rule).
@ -372,7 +368,7 @@ class SegWitTest(BitcoinTestFramework):
# test_node has set NODE_WITNESS, so all getdata requests should be for
# witness blocks.
# Test announcing a block via inv results in a getdata, and that
# announcing a version 4 or random VB block with a header results in a getdata
# announcing a block with a header results in a getdata
block1 = self.build_next_block()
block1.solve()
@ -380,19 +376,13 @@ class SegWitTest(BitcoinTestFramework):
assert self.test_node.last_message["getdata"].inv[0].type == blocktype
test_witness_block(self.nodes[0], self.test_node, block1, True)
block2 = self.build_next_block(version=4)
block2 = self.build_next_block()
block2.solve()
self.test_node.announce_block_and_wait_for_getdata(block2, use_header=True)
assert self.test_node.last_message["getdata"].inv[0].type == blocktype
test_witness_block(self.nodes[0], self.test_node, block2, True)
block3 = self.build_next_block(version=(VB_TOP_BITS | (1 << 15)))
block3.solve()
self.test_node.announce_block_and_wait_for_getdata(block3, use_header=True)
assert self.test_node.last_message["getdata"].inv[0].type == blocktype
test_witness_block(self.nodes[0], self.test_node, block3, True)
# Check that we can getdata for witness blocks or regular blocks,
# and the right thing happens.
if not self.segwit_active:
@ -437,7 +427,7 @@ class SegWitTest(BitcoinTestFramework):
assert_equal(rpc_details["weight"], block.get_weight())
# Upgraded node should not ask for blocks from unupgraded
block4 = self.build_next_block(version=4)
block4 = self.build_next_block()
block4.solve()
self.old_node.getdataset = set()

View file

@ -28,8 +28,6 @@ import subprocess
from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE
from test_framework.blocktools import (
CLTV_HEIGHT,
DERSIG_HEIGHT,
create_block,
create_coinbase,
TIME_GENESIS_BLOCK,
@ -142,11 +140,11 @@ class BlockchainTest(BitcoinTestFramework):
assert_greater_than(res['size_on_disk'], 0)
assert_equal(res['softforks'], {
'bip34': {'type': 'buried', 'active': True, 'height': 2},
'bip66': {'type': 'buried', 'active': True, 'height': DERSIG_HEIGHT},
'bip65': {'type': 'buried', 'active': True, 'height': CLTV_HEIGHT},
'csv': {'type': 'buried', 'active': False, 'height': 432},
'segwit': {'type': 'buried', 'active': True, 'height': 0},
'bip34': {'type': 'buried', 'active': True, 'height': 1},
'bip66': {'type': 'buried', 'active': True, 'height': 1},
'bip65': {'type': 'buried', 'active': True, 'height': 1},
'csv': {'type': 'buried', 'active': True, 'height': 1},
'segwit': {'type': 'buried', 'active': True, 'height': 1},
'dynafed': {
'type': 'bip9',
'bip9': {

View file

@ -6,7 +6,6 @@
from test_framework.blocktools import (
COINBASE_MATURITY,
CSV_ACTIVATION_HEIGHT,
)
from test_framework.address import (
script_to_p2sh,
@ -18,7 +17,6 @@ from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
find_vout_for_address,
generate_to_height,
)
from test_framework.messages import (
CTxInWitness,
@ -285,7 +283,6 @@ class SignRawTransactionsTest(BitcoinTestFramework):
getcontext().prec = 8
# Make sure CSV is active
generate_to_height(self, self.nodes[0], CSV_ACTIVATION_HEIGHT)
assert self.nodes[0].getblockchaininfo()['softforks']['csv']['active']
# Create a P2WSH script with CSV

View file

@ -55,11 +55,6 @@ TIME_GENESIS_BLOCK = 1296688602
# Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
COINBASE_MATURITY = 100
# Soft-fork activation heights
DERSIG_HEIGHT = 102 # BIP 66
CLTV_HEIGHT = 111 # BIP 65
CSV_ACTIVATION_HEIGHT = 432
# From BIP141
WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"

View file

@ -584,17 +584,6 @@ def mine_large_block(test_framework, node, utxos=None):
test_framework.generate(node, 1)
def generate_to_height(test_framework, 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(test_framework.generate(node, nblocks))
assert_equal(node.getblockcount(), target_height)
def find_vout_for_address(node, txid, addr):
"""
Locate the vout index of the given transaction sending to the