test: Add util to mine invalid blocks

With the current utils it is only possible to mine valid blocks. This
commit adds new util methods to mine invalid blocks.
This commit is contained in:
MarcoFalke
2023-05-02 17:17:10 +02:00
parent 7b45d171f5
commit fa846ee074
4 changed files with 53 additions and 11 deletions

View File

@@ -6,19 +6,22 @@
#include <chainparams.h>
#include <consensus/merkle.h>
#include <consensus/validation.h>
#include <key_io.h>
#include <node/context.h>
#include <pow.h>
#include <primitives/transaction.h>
#include <script/standard.h>
#include <test/util/script.h>
#include <util/check.h>
#include <validation.h>
#include <validationinterface.h>
#include <versionbits.h>
using node::BlockAssembler;
using node::NodeContext;
CTxIn generatetoaddress(const NodeContext& node, const std::string& address)
COutPoint generatetoaddress(const NodeContext& node, const std::string& address)
{
const auto dest = DecodeDestination(address);
assert(IsValidDestination(dest));
@@ -58,19 +61,52 @@ std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const
return ret;
}
CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
COutPoint MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
{
auto block = PrepareBlock(node, coinbase_scriptPubKey);
auto valid = MineBlock(node, block);
assert(!valid.IsNull());
return valid;
}
struct BlockValidationStateCatcher : public CValidationInterface {
const uint256 m_hash;
std::optional<BlockValidationState> m_state;
BlockValidationStateCatcher(const uint256& hash)
: m_hash{hash},
m_state{} {}
protected:
void BlockChecked(const CBlock& block, const BlockValidationState& state) override
{
if (block.GetHash() != m_hash) return;
m_state = state;
}
};
COutPoint MineBlock(const NodeContext& node, std::shared_ptr<CBlock>& block)
{
while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
++block->nNonce;
assert(block->nNonce);
}
bool processed{Assert(node.chainman)->ProcessNewBlock(block, true, true, nullptr)};
assert(processed);
auto& chainman{*Assert(node.chainman)};
const auto old_height = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight());
bool new_block;
BlockValidationStateCatcher bvsc{block->GetHash()};
RegisterValidationInterface(&bvsc);
const bool processed{chainman.ProcessNewBlock(block, true, true, &new_block)};
const bool duplicate{!new_block && processed};
assert(!duplicate);
UnregisterValidationInterface(&bvsc);
SyncWithValidationInterfaceQueue();
const bool was_valid{bvsc.m_state && bvsc.m_state->IsValid()};
assert(old_height + was_valid == WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight()));
return CTxIn{block->vtx[0]->GetHash(), 0};
if (was_valid) return {block->vtx[0]->GetHash(), 0};
return {};
}
std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey,