6#include <chainparams.h>
27#include <boost/test/unit_test.hpp>
44 std::shared_ptr<CBlock>
FinalizeBlock(std::shared_ptr<CBlock> pblock);
45 void BuildChain(
const uint256& root,
int height,
unsigned int invalid_rate,
unsigned int branch_rate,
unsigned int max_size, std::vector<std::shared_ptr<const CBlock>>& blocks);
84 auto block_template{mining->createNewBlock({
87 BOOST_REQUIRE(block_template);
88 auto pblock = std::make_shared<CBlock>(block_template->getBlock());
89 pblock->hashPrevBlock = prev_hash;
90 pblock->nTime = ++time;
96 txCoinbase.
vout.resize(2);
97 txCoinbase.
vout[1].scriptPubKey = P2WSH_OP_TRUE;
98 txCoinbase.
vout[1].nValue = txCoinbase.
vout[0].nValue;
99 txCoinbase.
vout[0].nValue = 0;
100 txCoinbase.
vin[0].scriptWitness.SetNull();
102 const int prev_height{
WITH_LOCK(
::cs_main,
return m_node.chainman->m_blockman.LookupBlockIndex(prev_hash)->nHeight)};
103 txCoinbase.
vin[0].scriptSig =
CScript{} << prev_height + 1 <<
OP_0;
104 txCoinbase.
nLockTime =
static_cast<uint32_t
>(prev_height);
105 pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
113 m_node.chainman->GenerateCoinbaseCommitment(*pblock, prev_block);
138 auto pblock =
Block(prev_hash);
142 coinbase_spend.
vout.push_back(pblock->vtx[0]->vout[0]);
145 pblock->vtx.push_back(tx);
152void MinerTestingSetup::BuildChain(
const uint256& root,
int height,
const unsigned int invalid_rate,
const unsigned int branch_rate,
const unsigned int max_size, std::vector<std::shared_ptr<const CBlock>>& blocks)
154 if (height <= 0 || blocks.size() >= max_size)
return;
156 bool gen_invalid =
m_rng.randrange(100U) < invalid_rate;
157 bool gen_fork =
m_rng.randrange(100U) < branch_rate;
159 const std::shared_ptr<const CBlock> pblock = gen_invalid ?
BadBlock(root) :
GoodBlock(root);
160 blocks.push_back(pblock);
162 BuildChain(pblock->GetHash(), height - 1, invalid_rate, branch_rate, max_size, blocks);
167 BuildChain(blocks.back()->GetHash(), height - 1, invalid_rate, branch_rate, max_size, blocks);
174 std::vector<std::shared_ptr<const CBlock>> blocks;
175 while (blocks.size() < 50) {
182 BOOST_CHECK(
Assert(m_node.chainman)->ProcessNewBlock(std::make_shared<CBlock>(
Params().GenesisBlock()),
true,
true, &ignored));
183 m_node.validation_signals->SyncWithValidationInterfaceQueue();
189 initial_tip = m_node.chainman->ActiveChain().Tip();
191 auto sub = std::make_shared<TestSubscriber>(initial_tip->
GetBlockHash());
192 m_node.validation_signals->RegisterSharedValidationInterface(sub);
197 std::vector<std::thread> threads;
199 for (
int i = 0; i < 10; i++) {
200 threads.emplace_back([&]() {
203 for (
int i = 0; i < 1000; i++) {
204 const auto& block = blocks[insecure.
randrange(blocks.size() - 1)];
205 Assert(m_node.chainman)->ProcessNewBlock(block,
true,
true, &ignored);
209 for (
const auto& block : blocks) {
210 if (block->vtx.size() == 1) {
211 bool processed =
Assert(m_node.chainman)->ProcessNewBlock(block,
true,
true, &ignored);
218 for (
auto&
t : threads) {
221 m_node.validation_signals->SyncWithValidationInterfaceQueue();
223 m_node.validation_signals->UnregisterSharedValidationInterface(sub);
226 BOOST_CHECK_EQUAL(sub->m_expected_tip, m_node.chainman->ActiveChain().Tip()->GetBlockHash());
249 auto ProcessBlock = [&](std::shared_ptr<const CBlock> block) ->
bool {
250 return Assert(m_node.chainman)->ProcessNewBlock(block,
true,
true, &ignored);
255 auto last_mined = GoodBlock(
Params().GenesisBlock().GetHash());
259 for (
int test_runs = 3; test_runs > 0; --test_runs) {
263 const uint256 split_hash{last_mined->hashPrevBlock};
267 std::vector<CTransactionRef> txs;
268 for (
int num_txs = 22; num_txs > 0; --num_txs) {
271 mtx.
vin[0].scriptWitness.stack.push_back(WITNESS_STACK_ELEM_OP_TRUE);
272 mtx.
vout.push_back(last_mined->vtx[0]->vout[1]);
273 mtx.
vout[0].nValue -= 1000;
274 txs.push_back(MakeTransactionRef(mtx));
276 last_mined = GoodBlock(last_mined->GetHash());
282 last_mined = GoodBlock(last_mined->GetHash());
287 const uint256 tip_init{last_mined->GetHash()};
289 std::vector<std::shared_ptr<const CBlock>> reorg;
290 last_mined = GoodBlock(split_hash);
291 reorg.push_back(last_mined);
293 last_mined = GoodBlock(last_mined->GetHash());
294 reorg.push_back(last_mined);
300 for (
const auto& tx : txs) {
313 std::thread rpc_thread{[&]() {
318 LOCK(m_node.mempool->cs);
319 if (m_node.mempool->size() == 0) {
328 assert(m_node.mempool->size() == txs.size());
333 assert(tip_init != m_node.chainman->ActiveChain().Tip()->GetBlockHash());
337 for (
const auto& b : reorg) {
354 auto block_template{mining->createNewBlock({
355 .coinbase_output_script = pubKey,
357 BOOST_REQUIRE(block_template);
358 CBlock pblock{block_template->getBlock()};
370 CTxOut min_plus_one = witness;
377 txCoinbase.
vout.resize(4);
378 txCoinbase.
vout[0] = witness;
379 txCoinbase.
vout[1] = witness;
380 txCoinbase.
vout[2] = min_plus_one;
381 txCoinbase.
vout[3] = invalid;
382 pblock.
vtx[0] = MakeTransactionRef(std::move(txCoinbase));
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
uint256 GetBlockHash() const
const CBlock & GenesisBlock() const
An outpoint - a combination of a transaction hash and an index n into its vout.
Serialized script, used inside transaction inputs and outputs.
An output of a transaction.
Implement this to subscribe to events generated in validation and mempool.
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
void resize(size_type new_size)
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
constexpr size_t MINIMUM_WITNESS_COMMITMENT
Minimum size of a witness commitment structure.
int GetWitnessCommitmentIndex(const CBlock &block)
Compute at which vout of the block's coinbase transaction the witness commitment occurs,...
constexpr int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule).
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(ipc_tests)
std::unique_ptr< Mining > MakeMining(const node::NodeContext &node, bool wait_loaded=true)
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params ¶ms)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
std::shared_ptr< const CTransaction > CTransactionRef
A mutable version of CTransaction.
std::vector< CTxOut > vout
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex) override
Notifies listeners of a block being disconnected Provides the block that was disconnected.
TestSubscriber(uint256 tip)
void BlockConnected(const ChainstateRole &role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex) override
Notifies listeners of a block being connected.
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override
Notifies listeners when the block chain tip advances.
Information about chainstate that notifications are sent from.
std::shared_ptr< const CBlock > BadBlock(const uint256 &prev_hash)
std::shared_ptr< CBlock > Block(const uint256 &prev_hash)
void BuildChain(const uint256 &root, int height, unsigned int invalid_rate, unsigned int branch_rate, unsigned int max_size, std::vector< std::shared_ptr< const CBlock > > &blocks)
std::shared_ptr< const CBlock > GoodBlock(const uint256 &prev_hash)
std::shared_ptr< CBlock > FinalizeBlock(std::shared_ptr< CBlock > pblock)
#define WITH_LOCK(cs, code)
COutPoint ProcessBlock(const NodeContext &node, const std::shared_ptr< CBlock > &block)
Returns the generated coin (or Null if the block was invalid).
bool BuildChain(const NodeContext &node, const CBlockIndex *pindex, const CScript &coinbase_script_pub_key, size_t length, std::vector< std::shared_ptr< CBlock > > &chain)
Build a chain of length coinbase-only blocks on top of pindex (which need not be the active tip,...