Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport: bitcoin#16333, #21862, #22385, #22550, #22597, #22632, #22718, #22907 - fire up test chains by first block - 2/n #6189

Merged
merged 9 commits into from
Aug 14, 2024
Merged
8 changes: 8 additions & 0 deletions doc/release-notes-6189.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Tests
-----

- For the `regtest` network the activation heights of several softforks were
changed. (dash#6189)
* BIP 34 (blockheight in coinbase) from 500 to 2
* BIP 66 (DERSIG) from 1251 to 102
* BIP 65 (CLTV) from 1351 to 111
6 changes: 3 additions & 3 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,10 +794,10 @@ class CRegTestParams : public CChainParams {
consensus.nGovernanceMinQuorum = 1;
consensus.nGovernanceFilterElements = 100;
consensus.nMasternodeMinimumConfirmations = 1;
consensus.BIP34Height = 500; // BIP34 activated on regtest (Used in functional tests)
consensus.BIP34Height = 2; // BIP34 activated on regtest (Block at height 1 not enforced for testing purposes)
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.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.BIP147Height = 432; // BIP147 activated on regtest (Used in functional tests)
consensus.CSVHeight = 432; // CSV activated on regtest (Used in rpc activation tests)
consensus.DIP0001Height = 2000;
Expand Down
15 changes: 9 additions & 6 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@

namespace Consensus {

enum BuriedDeployment : int16_t
{
/**
* 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.
*/
enum BuriedDeployment : int16_t {
// buried deployments get negative values to avoid overlap with DeploymentPos
DEPLOYMENT_HEIGHTINCB = std::numeric_limits<int16_t>::min(),
DEPLOYMENT_DERSIG,
DEPLOYMENT_CLTV,
Expand All @@ -29,17 +33,16 @@ enum BuriedDeployment : int16_t
DEPLOYMENT_BRR,
DEPLOYMENT_V19,
};
constexpr bool ValidDeployment(BuriedDeployment dep) { return DEPLOYMENT_HEIGHTINCB <= dep && dep <= DEPLOYMENT_V19; }
constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_V19; }

enum DeploymentPos : uint16_t
{
enum DeploymentPos : uint16_t {
DEPLOYMENT_TESTDUMMY,
DEPLOYMENT_V20, // Deployment of EHF, LLMQ Randomness Beacon
DEPLOYMENT_MN_RR, // Deployment of Masternode Reward Location Reallocation
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
MAX_VERSION_BITS_DEPLOYMENTS
};
constexpr bool ValidDeployment(DeploymentPos dep) { return DEPLOYMENT_TESTDUMMY <= dep && dep <= DEPLOYMENT_MN_RR; }
constexpr bool ValidDeployment(DeploymentPos dep) { return dep < MAX_VERSION_BITS_DEPLOYMENTS; }

/**
* Struct for each individual consensus rule change using BIP9.
Expand Down
17 changes: 17 additions & 0 deletions src/deploymentstatus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <consensus/params.h>
#include <versionbits.h>

#include <type_traits>

VersionBitsCache g_versionbitscache;

/* Basic sanity checking for BuriedDeployment/DeploymentPos enums and
Expand All @@ -15,3 +17,18 @@ VersionBitsCache g_versionbitscache;
static_assert(ValidDeployment(Consensus::DEPLOYMENT_TESTDUMMY), "sanity check of DeploymentPos failed (TESTDUMMY not valid)");
static_assert(!ValidDeployment(Consensus::MAX_VERSION_BITS_DEPLOYMENTS), "sanity check of DeploymentPos failed (MAX value considered valid)");
static_assert(!ValidDeployment(static_cast<Consensus::BuriedDeployment>(Consensus::DEPLOYMENT_TESTDUMMY)), "sanity check of BuriedDeployment failed (overlaps with DeploymentPos)");

/* ValidDeployment only checks upper bounds for ensuring validity.
* This checks that the lowest possible value or the type is also a
* (specific) valid deployment so that lower bounds don't need to be checked.
*/

template<typename T, T x>
static constexpr bool is_minimum()
{
using U = typename std::underlying_type<T>::type;
return x == std::numeric_limits<U>::min();
}

static_assert(is_minimum<Consensus::BuriedDeployment, Consensus::DEPLOYMENT_HEIGHTINCB>(), "heightincb is not minimum value for BuriedDeployment");
static_assert(is_minimum<Consensus::DeploymentPos, Consensus::DEPLOYMENT_TESTDUMMY>(), "testdummy is not minimum value for DeploymentPos");
2 changes: 1 addition & 1 deletion src/deploymentstatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ inline bool DeploymentEnabled(const Consensus::Params& params, Consensus::Buried
inline bool DeploymentEnabled(const Consensus::Params& params, Consensus::DeploymentPos dep)
{
assert(Consensus::ValidDeployment(dep));
return params.vDeployments[dep].nTimeout != 0;
return params.vDeployments[dep].nStartTime != Consensus::BIP9Deployment::NEVER_ACTIVE;
}

/** this function is convenient helper for DIP0003 because 'active' and 'enforced' are different statuses for DIP0003 */
Expand Down
4 changes: 2 additions & 2 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ BlockAssembler::Options::Options()
}

BlockAssembler::BlockAssembler(CChainState& chainstate, const NodeContext& node, const CTxMemPool& mempool, const CChainParams& params, const Options& options) :
m_blockman(Assert(node.chainman)->m_blockman),
m_blockman(chainstate.m_blockman),
m_cpoolman(*Assert(node.cpoolman)),
m_chain_helper(*Assert(node.chain_helper)),
m_chain_helper(chainstate.ChainHelper()),
m_chainstate(chainstate),
m_dmnman(*Assert(node.dmnman)),
m_evoDb(*Assert(node.evodb)),
Expand Down
9 changes: 3 additions & 6 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1615,10 +1615,7 @@ static RPCHelpMan verifychain()
static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const Consensus::Params& params, Consensus::BuriedDeployment dep)
{
// 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 (!DeploymentEnabled(params, dep)) return;

UniValue rv(UniValue::VOBJ);
Expand All @@ -1633,8 +1630,8 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue&
static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, const std::unordered_map<uint8_t, int>& signals, UniValue& softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
{
// For BIP9 deployments.
// Deployments that are never active are hidden.
if (consensusParams.vDeployments[id].nStartTime == Consensus::BIP9Deployment::NEVER_ACTIVE) return;

if (!DeploymentEnabled(consensusParams, id)) return;

UniValue bip9(UniValue::VOBJ);
const ThresholdState thresholdState = g_versionbitscache.State(active_chain_tip, consensusParams, id);
Expand Down
6 changes: 3 additions & 3 deletions src/test/util/setup_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,10 +428,10 @@ CBlock TestChainSetup::CreateBlock(
auto cbTx = GetTxPayload<CCbTx>(*block.vtx[0]);
BOOST_ASSERT(cbTx.has_value());
BlockValidationState state;
if (!CalcCbTxMerkleRootMNList(block, m_node.chainman->ActiveChain().Tip(), cbTx->merkleRootMNList, *m_node.dmnman, state, m_node.chainman->ActiveChainstate().CoinsTip())) {
if (!CalcCbTxMerkleRootMNList(block, chainstate.m_chain.Tip(), cbTx->merkleRootMNList, *m_node.dmnman, state, chainstate.CoinsTip())) {
BOOST_ASSERT(false);
}
if (!CalcCbTxMerkleRootQuorums(block, m_node.chainman->ActiveChain().Tip(), *m_node.llmq_ctx->quorum_block_processor, cbTx->merkleRootQuorums, state)) {
if (!CalcCbTxMerkleRootQuorums(block, chainstate.m_chain.Tip(), *m_node.llmq_ctx->quorum_block_processor, cbTx->merkleRootQuorums, state)) {
BOOST_ASSERT(false);
}
CMutableTransaction tmpTx{*block.vtx[0]};
Expand All @@ -443,7 +443,7 @@ CBlock TestChainSetup::CreateBlock(
{
LOCK(cs_main);
unsigned int extraNonce = 0;
IncrementExtraNonce(&block, m_node.chainman->ActiveChain().Tip(), extraNonce);
IncrementExtraNonce(&block, chainstate.m_chain.Tip(), extraNonce);
}

while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
Expand Down
14 changes: 7 additions & 7 deletions src/test/validation_block_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ std::shared_ptr<CBlock> MinerTestingSetup::Block(const uint256& prev_hash)
txCoinbase.vout[1].scriptPubKey = P2SH_OP_TRUE;
txCoinbase.vout[1].nValue = txCoinbase.vout[0].nValue;
txCoinbase.vout[0].nValue = 0;
// Always pad with OP_0 at the end to avoid bad-cb-length error
txCoinbase.vin[0].scriptSig = CScript{} << WITH_LOCK(::cs_main, return m_node.chainman->m_blockman.LookupBlockIndex(prev_hash)->nHeight + 1) << OP_0;
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));

return pblock;
Expand All @@ -92,6 +94,11 @@ std::shared_ptr<CBlock> MinerTestingSetup::FinalizeBlock(std::shared_ptr<CBlock>
++(pblock->nNonce);
}

// submit block header, so that miner can get the block height from the
// global state and the node has the topology of the chain
BlockValidationState ignored;
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlockHeaders({pblock->GetBlockHeader()}, ignored, Params()));

return pblock;
}

Expand Down Expand Up @@ -146,13 +153,6 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
}

bool ignored;
BlockValidationState state;
std::vector<CBlockHeader> headers;
std::transform(blocks.begin(), blocks.end(), std::back_inserter(headers), [](std::shared_ptr<const CBlock> b) { return b->GetBlockHeader(); });

// Process all the headers so we understand the toplogy of the chain
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlockHeaders(headers, state, Params()));

// Connect the genesis block and drain any outstanding events
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(Params(), std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored));
SyncWithValidationInterfaceQueue();
Expand Down
5 changes: 4 additions & 1 deletion test/functional/feature_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,9 @@ def run_test(self):
# b30 has a max-sized coinbase scriptSig.
self.move_tip(23)
b30 = self.next_block(30)
b30.vtx[0].vin[0].scriptSig = b'\x00' * 100
b30.vtx[0].vin[0].scriptSig = bytes(b30.vtx[0].vin[0].scriptSig) # Convert CScript to raw bytes
b30.vtx[0].vin[0].scriptSig += b'\x00' * (100 - len(b30.vtx[0].vin[0].scriptSig)) # Fill with 0s
assert_equal(len(b30.vtx[0].vin[0].scriptSig), 100)
b30.vtx[0].rehash()
b30 = self.update_block(30, [])
self.send_blocks([b30], True)
Expand Down Expand Up @@ -839,6 +841,7 @@ def run_test(self):
b61.vtx[0].rehash()
b61 = self.update_block(61, [])
assert_equal(duplicate_tx.serialize(), b61.vtx[0].serialize())
# BIP30 is always checked on regtest, regardless of the BIP34 activation height
self.send_blocks([b61], success=False, reject_reason='bad-txns-BIP30', reconnect=True)

# Test BIP30 (allow duplicate if spent)
Expand Down
13 changes: 6 additions & 7 deletions test/functional/feature_cltv.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test BIP65 (CHECKLOCKTIMEVERIFY).

Test that the CHECKLOCKTIMEVERIFY soft-fork activates at (regtest) block height
1351.
Test that the CHECKLOCKTIMEVERIFY soft-fork activates.
"""

from test_framework.blocktools import (
CLTV_HEIGHT,
create_block,
create_coinbase,
)
Expand All @@ -34,8 +34,6 @@
MiniWalletMode,
)

CLTV_HEIGHT = 1351


# Helper function to modify a transaction by
# 1) prepending a given script to the scriptSig of vin 0 and
Expand Down Expand Up @@ -66,9 +64,9 @@ def cltv_invalidate(tx, failure_reason):
# +-------------------------------------------------+------------+--------------+
[[OP_CHECKLOCKTIMEVERIFY], None, None],
[[OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP], None, None],
[[CScriptNum(1000), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0, 1296688602], # timestamp of genesis block
[[CScriptNum(1000), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0, 500],
[[CScriptNum(500), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0xffffffff, 500],
[[CScriptNum(100), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0, 1296688602], # timestamp of genesis block
[[CScriptNum(100), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0, 50],
[[CScriptNum(50), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0xffffffff, 50],
][failure_reason]

cltv_modify_tx(tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2])
Expand Down Expand Up @@ -111,6 +109,7 @@ def run_test(self):
self.log.info("Mining %d blocks", CLTV_HEIGHT - 2)
wallet.generate(10)
self.nodes[0].generate(CLTV_HEIGHT - 2 - 10)
assert_equal(self.nodes[0].getblockcount(), CLTV_HEIGHT - 2)

self.log.info("Test that invalid-according-to-CLTV transactions can still appear in a block")

Expand Down
12 changes: 8 additions & 4 deletions test/functional/feature_csv_activation.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from itertools import product

from test_framework.blocktools import (
CSV_ACTIVATION_HEIGHT,
create_block,
create_coinbase,
TIME_GENESIS_BLOCK,
Expand All @@ -63,12 +64,12 @@
TESTING_TX_COUNT = 83 # Number of testing transactions: 1 BIP113 tx, 16 BIP68 txs, 66 BIP112 txs (see comments above)
COINBASE_BLOCK_COUNT = TESTING_TX_COUNT # Number of coinbase blocks we need to generate as inputs for our txs
BASE_RELATIVE_LOCKTIME = 10
CSV_ACTIVATION_HEIGHT = 432
SEQ_DISABLE_FLAG = 1 << 31
SEQ_RANDOM_HIGH_BIT = 1 << 25
SEQ_TYPE_FLAG = 1 << 22
SEQ_RANDOM_LOW_BIT = 1 << 18


def relative_locktime(sdf, srhb, stf, srlb):
"""Returns a locktime with certain bits set."""

Expand All @@ -83,6 +84,7 @@ def relative_locktime(sdf, srhb, stf, srlb):
locktime |= SEQ_RANDOM_LOW_BIT
return locktime


def all_rlt_txs(txs):
return [tx['tx'] for tx in txs]

Expand All @@ -94,6 +96,7 @@ def set_test_params(self):
# Must also set '-maxtipage=600100' to allow syncing from very old blocks
# and '-dip3params=2000:2000' to create pre-dip3 blocks only
self.extra_args = [[
'-peertimeout=999999', # bump because mocktime might cause a disconnect otherwise
'[email protected]',
'-maxtipage=600100', '-dip3params=2000:2000',
'-par=1', # Use only one script thread to get the exact reject reason for testing
Expand Down Expand Up @@ -149,13 +152,13 @@ def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta=0
for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
locktime = relative_locktime(sdf, srhb, stf, srlb)
tx = self.create_self_transfer_from_utxo(bip112inputs[i])
if (varyOP_CSV): # if varying OP_CSV, nSequence is fixed
if varyOP_CSV: # if varying OP_CSV, nSequence is fixed
tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
else: # vary nSequence instead, OP_CSV is fixed
tx.vin[0].nSequence = locktime + locktime_delta
tx.nVersion = txversion
self.miniwallet.sign_tx(tx)
if (varyOP_CSV):
if varyOP_CSV:
tx.vin[0].scriptSig = CScript([locktime, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
else:
tx.vin[0].scriptSig = CScript([BASE_RELATIVE_LOCKTIME, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig)))
Expand Down Expand Up @@ -202,7 +205,7 @@ def run_test(self):
self.tip = int(self.nodes[0].getbestblockhash(), 16)

# Activation height is hardcoded
test_blocks = self.generate_blocks(CSV_ACTIVATION_HEIGHT-5 - COINBASE_BLOCK_COUNT)
test_blocks = self.generate_blocks(CSV_ACTIVATION_HEIGHT - 5 - COINBASE_BLOCK_COUNT)
#test_blocks = self.generate_blocks(345)
self.send_blocks(test_blocks)
assert not softfork_active(self.nodes[0], 'csv')
Expand Down Expand Up @@ -488,5 +491,6 @@ def run_test(self):
self.send_blocks([self.create_test_block(time_txs)])
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())


if __name__ == '__main__':
BIP68_112_113Test().main()
7 changes: 4 additions & 3 deletions test/functional/feature_dersig.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test BIP66 (DER SIG).

Test that the DERSIG soft-fork activates at (regtest) height 1251.
Test the DERSIG soft-fork activation on regtest.
"""

from test_framework.blocktools import (
DERSIG_HEIGHT,
create_block,
create_coinbase,
)
Expand All @@ -24,8 +25,6 @@
MiniWalletMode,
)

DERSIG_HEIGHT = 1251


# A canonical signature consists of:
# <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype>
Expand Down Expand Up @@ -88,8 +87,10 @@ def run_test(self):
block.rehash()
block.solve()

assert_equal(self.nodes[0].getblockcount(), DERSIG_HEIGHT - 2)
self.test_dersig_info(is_active=False) # Not active as of current tip and next block does not need to obey rules
peer.send_and_ping(msg_block(block))
assert_equal(self.nodes[0].getblockcount(), DERSIG_HEIGHT - 1)
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)

Expand Down
8 changes: 5 additions & 3 deletions test/functional/rpc_blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

from test_framework.address import ADDRESS_BCRT1_P2SH_OP_TRUE
from test_framework.blocktools import (
CLTV_HEIGHT,
DERSIG_HEIGHT,
create_block,
create_coinbase,
TIME_GENESIS_BLOCK,
Expand Down Expand Up @@ -142,9 +144,9 @@ def _test_getblockchaininfo(self):
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},
'bip34': {'type': 'buried', 'active': True, 'height': 2},
'bip66': {'type': 'buried', 'active': True, 'height': DERSIG_HEIGHT},
'bip65': {'type': 'buried', 'active': True, 'height': CLTV_HEIGHT},
'bip147': { 'type': 'buried', 'active': False, 'height': 432},
'csv': {'type': 'buried', 'active': False, 'height': 432},
'dip0001': { 'type': 'buried', 'active': False, 'height': 2000},
Expand Down
9 changes: 8 additions & 1 deletion test/functional/test_framework/blocktools.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,21 @@
# 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

NORMAL_GBT_REQUEST_PARAMS = {"rules": []} # type: ignore[var-annotated]

VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4

def create_block(hashprev=None, coinbase=None, ntime=None, *, version=None, tmpl=None, txlist=None, dip4_activated=False, v20_activated=False):
"""Create a block (with regtest difficulty)."""
block = CBlock()
if tmpl is None:
tmpl = {}
block.nVersion = version or tmpl.get('version') or 1
block.nVersion = version or tmpl.get('version') or VERSIONBITS_LAST_OLD_BLOCK_VERSION
block.nTime = ntime or tmpl.get('curtime') or int(time.time() + 600)
block.hashPrevBlock = hashprev or int(tmpl['previousblockhash'], 0x10)
if tmpl and not tmpl.get('bits') is None:
Expand Down
Loading
Loading