Changeset View
Changeset View
Standalone View
Standalone View
src/test/validation_block_tests.cpp
Show First 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | struct TestSubscriber : public CValidationInterface { | ||||
void | void | ||||
BlockDisconnected(const std::shared_ptr<const CBlock> &block) override { | BlockDisconnected(const std::shared_ptr<const CBlock> &block) override { | ||||
BOOST_CHECK_EQUAL(m_expected_tip, block->GetHash()); | BOOST_CHECK_EQUAL(m_expected_tip, block->GetHash()); | ||||
m_expected_tip = block->hashPrevBlock; | m_expected_tip = block->hashPrevBlock; | ||||
} | } | ||||
}; | }; | ||||
std::shared_ptr<CBlock> Block(const Config &config, | std::shared_ptr<CBlock> Block(const Config &config, const CTxMemPool &mempool, | ||||
const BlockHash &prev_hash) { | const BlockHash &prev_hash) { | ||||
static int i = 0; | static int i = 0; | ||||
static uint64_t time = config.GetChainParams().GenesisBlock().nTime; | static uint64_t time = config.GetChainParams().GenesisBlock().nTime; | ||||
CScript pubKey; | CScript pubKey; | ||||
pubKey << i++ << OP_TRUE; | pubKey << i++ << OP_TRUE; | ||||
auto ptemplate = BlockAssembler(config, g_mempool).CreateNewBlock(pubKey); | auto ptemplate = BlockAssembler(config, mempool).CreateNewBlock(pubKey); | ||||
auto pblock = std::make_shared<CBlock>(ptemplate->block); | auto pblock = std::make_shared<CBlock>(ptemplate->block); | ||||
pblock->hashPrevBlock = prev_hash; | pblock->hashPrevBlock = prev_hash; | ||||
pblock->nTime = ++time; | pblock->nTime = ++time; | ||||
CMutableTransaction txCoinbase(*pblock->vtx[0]); | CMutableTransaction txCoinbase(*pblock->vtx[0]); | ||||
txCoinbase.vout.resize(1); | txCoinbase.vout.resize(1); | ||||
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase)); | pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase)); | ||||
return pblock; | return pblock; | ||||
} | } | ||||
std::shared_ptr<CBlock> FinalizeBlock(const Consensus::Params ¶ms, | std::shared_ptr<CBlock> FinalizeBlock(const Consensus::Params ¶ms, | ||||
std::shared_ptr<CBlock> pblock) { | std::shared_ptr<CBlock> pblock) { | ||||
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); | pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); | ||||
while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, params)) { | while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, params)) { | ||||
++(pblock->nNonce); | ++(pblock->nNonce); | ||||
} | } | ||||
return pblock; | return pblock; | ||||
} | } | ||||
// construct a valid block | // construct a valid block | ||||
const std::shared_ptr<const CBlock> GoodBlock(const Config &config, | const std::shared_ptr<const CBlock> GoodBlock(const Config &config, | ||||
const CTxMemPool &mempool, | |||||
const BlockHash &prev_hash) { | const BlockHash &prev_hash) { | ||||
return FinalizeBlock(config.GetChainParams().GetConsensus(), | return FinalizeBlock(config.GetChainParams().GetConsensus(), | ||||
Block(config, prev_hash)); | Block(config, mempool, prev_hash)); | ||||
} | } | ||||
// construct an invalid block (but with a valid header) | // construct an invalid block (but with a valid header) | ||||
const std::shared_ptr<const CBlock> BadBlock(const Config &config, | const std::shared_ptr<const CBlock> BadBlock(const Config &config, | ||||
const CTxMemPool &mempool, | |||||
const BlockHash &prev_hash) { | const BlockHash &prev_hash) { | ||||
auto pblock = Block(config, prev_hash); | auto pblock = Block(config, mempool, prev_hash); | ||||
CMutableTransaction coinbase_spend; | CMutableTransaction coinbase_spend; | ||||
coinbase_spend.vin.push_back( | coinbase_spend.vin.push_back( | ||||
CTxIn(COutPoint(pblock->vtx[0]->GetId(), 0), CScript(), 0)); | CTxIn(COutPoint(pblock->vtx[0]->GetId(), 0), CScript(), 0)); | ||||
coinbase_spend.vout.push_back(pblock->vtx[0]->vout[0]); | coinbase_spend.vout.push_back(pblock->vtx[0]->vout[0]); | ||||
CTransactionRef tx = MakeTransactionRef(coinbase_spend); | CTransactionRef tx = MakeTransactionRef(coinbase_spend); | ||||
pblock->vtx.push_back(tx); | pblock->vtx.push_back(tx); | ||||
auto ret = FinalizeBlock(config.GetChainParams().GetConsensus(), pblock); | auto ret = FinalizeBlock(config.GetChainParams().GetConsensus(), pblock); | ||||
return ret; | return ret; | ||||
} | } | ||||
void BuildChain(const Config &config, const BlockHash &root, int height, | void BuildChain(const Config &config, const CTxMemPool &mempool, | ||||
const BlockHash &root, int height, | |||||
const unsigned int invalid_rate, const unsigned int branch_rate, | const unsigned int invalid_rate, const unsigned int branch_rate, | ||||
const unsigned int max_size, | const unsigned int max_size, | ||||
std::vector<std::shared_ptr<const CBlock>> &blocks) { | std::vector<std::shared_ptr<const CBlock>> &blocks) { | ||||
if (height <= 0 || blocks.size() >= max_size) { | if (height <= 0 || blocks.size() >= max_size) { | ||||
return; | return; | ||||
} | } | ||||
bool gen_invalid = InsecureRandRange(100) < invalid_rate; | bool gen_invalid = InsecureRandRange(100) < invalid_rate; | ||||
bool gen_fork = InsecureRandRange(100) < branch_rate; | bool gen_fork = InsecureRandRange(100) < branch_rate; | ||||
const std::shared_ptr<const CBlock> pblock = | const std::shared_ptr<const CBlock> pblock = | ||||
gen_invalid ? BadBlock(config, root) : GoodBlock(config, root); | gen_invalid ? BadBlock(config, mempool, root) | ||||
: GoodBlock(config, mempool, root); | |||||
blocks.push_back(pblock); | blocks.push_back(pblock); | ||||
if (!gen_invalid) { | if (!gen_invalid) { | ||||
BuildChain(config, pblock->GetHash(), height - 1, invalid_rate, | BuildChain(config, mempool, pblock->GetHash(), height - 1, invalid_rate, | ||||
branch_rate, max_size, blocks); | branch_rate, max_size, blocks); | ||||
} | } | ||||
if (gen_fork) { | if (gen_fork) { | ||||
blocks.push_back(GoodBlock(config, root)); | blocks.push_back(GoodBlock(config, mempool, root)); | ||||
BuildChain(config, blocks.back()->GetHash(), height - 1, invalid_rate, | BuildChain(config, mempool, blocks.back()->GetHash(), height - 1, | ||||
branch_rate, max_size, blocks); | invalid_rate, branch_rate, max_size, blocks); | ||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering) { | BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering) { | ||||
GlobalConfig config; | GlobalConfig config; | ||||
const CChainParams &chainParams = config.GetChainParams(); | const CChainParams &chainParams = config.GetChainParams(); | ||||
// build a large-ish chain that's likely to have some forks | // build a large-ish chain that's likely to have some forks | ||||
std::vector<std::shared_ptr<const CBlock>> blocks; | std::vector<std::shared_ptr<const CBlock>> blocks; | ||||
while (blocks.size() < 50) { | while (blocks.size() < 50) { | ||||
blocks.clear(); | blocks.clear(); | ||||
BuildChain(config, chainParams.GenesisBlock().GetHash(), 100, 15, 10, | BuildChain(config, ::g_mempool, chainParams.GenesisBlock().GetHash(), | ||||
500, blocks); | 100, 15, 10, 500, blocks); | ||||
} | } | ||||
bool ignored; | bool ignored; | ||||
CValidationState state; | CValidationState state; | ||||
std::vector<CBlockHeader> headers; | std::vector<CBlockHeader> headers; | ||||
std::transform( | std::transform( | ||||
blocks.begin(), blocks.end(), std::back_inserter(headers), | blocks.begin(), blocks.end(), std::back_inserter(headers), | ||||
[](std::shared_ptr<const CBlock> b) { return b->GetBlockHeader(); }); | [](std::shared_ptr<const CBlock> b) { return b->GetBlockHeader(); }); | ||||
▲ Show 20 Lines • Show All 60 Lines • Show Last 20 Lines |