Skip to content

Commit

Permalink
Merge pull request #10 from cakedefi/fix_test_2.0
Browse files Browse the repository at this point in the history
PoS tests
  • Loading branch information
uzyn committed Nov 5, 2019
2 parents 1aefa90 + b27c193 commit 20d4555
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 44 deletions.
1 change: 1 addition & 0 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ BITCOIN_TESTS =\
test/pmt_tests.cpp \
test/policyestimator_tests.cpp \
test/pow_tests.cpp \
test/pos_tests.cpp \
test/prevector_tests.cpp \
test/raii_event_tests.cpp \
test/random_tests.cpp \
Expand Down
4 changes: 3 additions & 1 deletion src/consensus/tx_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <primitives/transaction.h>
#include <consensus/validation.h>

extern bool fIsFakeNet;

bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
{
// Basic checks that don't depend on any context
Expand Down Expand Up @@ -43,7 +45,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe

if (tx.IsCoinBase())
{
if (tx.vin[0].scriptSig.size() < 2) // || tx.vin[0].scriptSig.size() > 100 // TODO: (ss) !
if (tx.vin[0].scriptSig.size() < 2 || (fIsFakeNet && tx.vin[0].scriptSig.size() > 100))
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-length");
}
else
Expand Down
2 changes: 1 addition & 1 deletion src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc

bool baseScript = true;

if (pmasternodesview->GetCriminals().size() != 0) {
if (!fIsFakeNet && pmasternodesview->GetCriminals().size() != 0) {
CMasternodesView::CMnCriminals criminals = pmasternodesview->GetCriminals();
CMasternodesView::CMnCriminals::iterator itCriminalMN = criminals.begin();
std::pair<CBlockHeader, CBlockHeader> criminal = itCriminalMN->second;
Expand Down
2 changes: 0 additions & 2 deletions src/test/double_sign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ std::shared_ptr<CBlock> FinalizeBlock(std::shared_ptr<CBlock> pblock, const uint

pblock->stakeModifier = pos::ComputeStakeModifier(prevStakeModifier, minterKey.GetPubKey().GetID());

GenerateCoinbaseCommitment(*pblock, LookupBlockIndex(pblock->hashPrevBlock), Params().GetConsensus());

pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);

do {
Expand Down
211 changes: 211 additions & 0 deletions src/test/pos_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
#include <chainparams.h>
#include <consensus/merkle.h>
#include <masternodes/masternodes.h>
#include <miner.h>
#include <pos.h>
#include <pos_kernel.h>
#include <util/system.h>
#include <script/signingprovider.h>

#include <test/setup_common.h>

#include <boost/test/unit_test.hpp>

static const std::vector<unsigned char> V_OP_TRUE{OP_TRUE};

struct RegtestingSetup : public TestingSetup {
RegtestingSetup() : TestingSetup(CBaseChainParams::REGTEST) {}
};
BOOST_FIXTURE_TEST_SUITE(pos_tests, RegtestingSetup)

std::shared_ptr<CBlock> Block( const uint256& prev_hash, const uint64_t& height, const uint64_t& mintedBlocks)
{
CScript pubKey = CScript() << OP_TRUE;

auto ptemplate = BlockAssembler(Params()).CreateNewBlock(pubKey);
auto pblock = std::make_shared<CBlock>(ptemplate->block);
pblock->hashPrevBlock = prev_hash;

pblock->mintedBlocks = mintedBlocks;
pblock->height = height;

return pblock;
}

std::shared_ptr<CBlock> FinalizeBlock(std::shared_ptr<CBlock> pblock, const uint256& masternodeID, const CKey& minterKey, const uint256& prevStakeModifier)
{
LOCK(cs_main); // For LookupBlockIndex
static uint64_t time = Params().GenesisBlock().nTime;

pblock->stakeModifier = pos::ComputeStakeModifier(prevStakeModifier, minterKey.GetPubKey().GetID());

pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);

pblock->nTime = time + 10;
// do {
// time++;
// pblock->nTime = time;
// } while (!pos::CheckKernelHash(pblock->stakeModifier, pblock->nBits, (int64_t) pblock->nTime, Params().GetConsensus(), masternodeID).hashOk);

BOOST_CHECK(!pos::SignPosBlock(pblock, minterKey));

return pblock;
}

BOOST_AUTO_TEST_CASE(calc_kernel)
{
uint256 stakeModifier = uint256S("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef");
uint256 mnID = uint256S("fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321");
int64_t coinstakeTime = 10000000;
BOOST_CHECK(uint256S("2a30e655ae8018566092750052a01bdef3ad8e1951beb87a9d503e1bcfe4bd2a") ==
pos::CalcKernelHash(stakeModifier, coinstakeTime, mnID, Params().GetConsensus()));

uint32_t target = 0x1effffff;
BOOST_CHECK(pos::CheckKernelHash(stakeModifier, target, coinstakeTime, Params().GetConsensus(), mnID).hashOk);

uint32_t unattainableTarget = 0x00ffffff;
BOOST_CHECK(!pos::CheckKernelHash(stakeModifier, unattainableTarget, coinstakeTime, Params().GetConsensus(), mnID).hashOk);

// CKey key;
// key.MakeNewKey(true); // Need to use compressed keys in segwit or the signing will fail
// FillableSigningProvider keystore;
// BOOST_CHECK(keystore.AddKeyPubKey(key, key.GetPubKey()));
// CKeyID keyID = key.GetPubKey().GetID();
//
// uint256 prevStakeModifier = uint256S("fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321");
// CDataStream ss(SER_GETHASH, 0);
// ss << prevStakeModifier << keyID;
// uint256 targetStakeModifier = Hash(ss.begin(), ss.end());
//
// BOOST_CHECK(pos::ComputeStakeModifier(prevStakeModifier, keyID) == targetStakeModifier);
}

BOOST_AUTO_TEST_CASE(check_stake_modifier)
{
uint256 masternodeID = testMasternodeKeys.begin()->first;
std::map<uint256, TestMasternodeKeys>::const_iterator pos = testMasternodeKeys.find(masternodeID);
BOOST_CHECK(pos != testMasternodeKeys.end());
CKey minterKey = pos->second.operatorKey;

uint256 prev_hash = uint256S("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef");
uint64_t height = 1;
uint64_t mintedBlocks = 1;
std::shared_ptr<CBlock> block = Block(prev_hash, height, mintedBlocks);
BOOST_CHECK(!pos::CheckStakeModifier(::ChainActive().Tip(), *(CBlockHeader*)block.get()));

uint256 prevStakeModifier = Params().GenesisBlock().stakeModifier;
block->stakeModifier = pos::ComputeStakeModifier(prevStakeModifier, minterKey.GetPubKey().GetID());
BOOST_CHECK(!pos::CheckStakeModifier(::ChainActive().Tip(), *(CBlockHeader*)block.get()));

std::shared_ptr<CBlock> correctBlock = FinalizeBlock(
Block(Params().GenesisBlock().GetHash(), height, mintedBlocks),
masternodeID,
minterKey,
prevStakeModifier);
BOOST_CHECK(pos::CheckStakeModifier(::ChainActive().Tip(), *(CBlockHeader*)correctBlock.get()));

correctBlock->sig = {};
BOOST_CHECK(!pos::CheckStakeModifier(::ChainActive().Tip(), *(CBlockHeader*)correctBlock.get()));
}

BOOST_AUTO_TEST_CASE(check_header_signature)
{
uint256 masternodeID = testMasternodeKeys.begin()->first;
std::map<uint256, TestMasternodeKeys>::const_iterator pos = testMasternodeKeys.find(masternodeID);
BOOST_CHECK(pos != testMasternodeKeys.end());
CKey minterKey = pos->second.operatorKey;

BOOST_CHECK(pos::CheckHeaderSignature((CBlockHeader)Params().GenesisBlock()));

uint256 prev_hash = uint256S("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef");
uint64_t height = 1;
uint64_t mintedBlocks = 1;
std::shared_ptr<CBlock> block = Block(prev_hash, height, mintedBlocks);

BOOST_CHECK(!pos::CheckHeaderSignature(*(CBlockHeader*)block.get()));

FinalizeBlock(
block,
masternodeID,
minterKey,
prev_hash);

BOOST_CHECK(pos::CheckHeaderSignature(*(CBlockHeader*)block.get()));

// block->sig[0] = 0xff;
// block->sig[1] = 0xff;
// BOOST_CHECK(!pos::CheckHeaderSignature(*(CBlockHeader*)block.get()));
}

BOOST_AUTO_TEST_CASE(contextual_check_pos)
{
uint256 masternodeID = testMasternodeKeys.begin()->first;
std::map<uint256, TestMasternodeKeys>::const_iterator pos = testMasternodeKeys.find(masternodeID);
BOOST_CHECK(pos != testMasternodeKeys.end());
CKey minterKey = pos->second.operatorKey;

BOOST_CHECK(pos::ContextualCheckProofOfStake((CBlockHeader)Params().GenesisBlock(), Params().GetConsensus(), pmasternodesview.get()));

uint256 prev_hash = uint256S("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef");
uint64_t height = 0;
uint64_t mintedBlocks = 1;
std::shared_ptr<CBlock> block = Block(Params().GenesisBlock().GetHash(), height, mintedBlocks);

BOOST_CHECK(!pos::ContextualCheckProofOfStake(*(CBlockHeader*)block.get(), Params().GetConsensus(), pmasternodesview.get()));

block->height = 1;
BOOST_CHECK(!pos::ContextualCheckProofOfStake(*(CBlockHeader*)block.get(), Params().GetConsensus(), pmasternodesview.get()));

// std::shared_ptr<CBlock> finalizeBlock = FinalizeBlock(
// block,
// masternodeID,
// minterKey,
// prev_hash);
// BOOST_CHECK(pos::ContextualCheckProofOfStake(*(CBlockHeader*)finalizeBlock.get(), Params().GetConsensus(), pmasternodesview.get()));
//
//// block->sig[0] = 0xff;
//// block->sig[1] = 0xff;
//// BOOST_CHECK(!pos::ContextualCheckProofOfStake(*(CBlockHeader*)block.get(), Params().GetConsensus(), pmasternodesview.get()));
//
// block->nBits = 0x0effffff;
// block->sig = {};
// BOOST_CHECK(!pos::SignPosBlock(block, minterKey));
//
// BOOST_CHECK(!pos::ContextualCheckProofOfStake(*(CBlockHeader*)block.get(), Params().GetConsensus(), pmasternodesview.get()));
// block->sig[0] = 0xff;
}

BOOST_AUTO_TEST_CASE(sign_pos_block)
{
uint256 masternodeID = testMasternodeKeys.begin()->first;
std::map<uint256, TestMasternodeKeys>::const_iterator pos = testMasternodeKeys.find(masternodeID);
BOOST_CHECK(pos != testMasternodeKeys.end());
CKey minterKey = pos->second.operatorKey;

uint256 prev_hash = uint256S("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef");
uint64_t height = 1;
uint64_t mintedBlocks = 1;
std::shared_ptr<CBlock> block = Block(prev_hash, height, mintedBlocks);

static uint64_t time = Params().GenesisBlock().nTime;

block->stakeModifier = pos::ComputeStakeModifier(prev_hash, minterKey.GetPubKey().GetID());

block->hashMerkleRoot = BlockMerkleRoot(*block);

BOOST_CHECK(pos::SignPosBlock(block, CKey()) == std::string{"Block signing error"});
BOOST_CHECK(!pos::SignPosBlock(block, minterKey));
BOOST_CHECK_THROW(pos::SignPosBlock(block, minterKey), std::logic_error);

BOOST_CHECK(!pos::CheckProofOfStake(*(CBlockHeader*)block.get(), ::ChainActive().Tip(), Params().GetConsensus(), pmasternodesview.get()));

uint256 prevStakeModifier = Params().GenesisBlock().stakeModifier;
// std::shared_ptr<CBlock> correctBlock = FinalizeBlock(
// Block(Params().GenesisBlock().GetHash(), 1, 1),
// masternodeID,
// minterKey,
// prevStakeModifier);
// BOOST_CHECK(pos::CheckProofOfStake(*(CBlockHeader*)correctBlock.get(), ::ChainActive().Tip(), Params().GetConsensus(), pmasternodesview.get()));
}

BOOST_AUTO_TEST_SUITE_END()
40 changes: 21 additions & 19 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2023,7 +2023,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
control.Add(vChecks);
} else {
std::vector<unsigned char> metadata;
if (CMasternodesView::ExtractCriminalCoinsFromTx(tx, metadata)) {
if (!fIsFakeNet && CMasternodesView::ExtractCriminalCoinsFromTx(tx, metadata)) {
pmasternodesview->BlockedCriminalMnCoins(metadata);
}
}
Expand Down Expand Up @@ -3390,28 +3390,30 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState
}

// Add MintedBlockHeader entity to DB
CKeyID mintersKey;
if (!block.ExtractMinterKey(mintersKey)) {
return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, error("%s: block %s: minters key for external blockHeader not found", __func__, hash.ToString()), REJECT_INVALID, "bad-pos-header");
}
auto it = pmasternodesview->ExistMasternode(CMasternodesView::AuthIndex::ByOperator, mintersKey);
if (!it) {
return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, error("%s: block %s: active masternode for external blockHeader not found", __func__, hash.ToString()), REJECT_INVALID, " ");
}
auto const & nodeId = (*it)->second;
if (!fIsFakeNet) {
CKeyID mintersKey;
if (!block.ExtractMinterKey(mintersKey)) {
return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, error("%s: block %s: minters key for external blockHeader not found", __func__, hash.ToString()), REJECT_INVALID, "bad-pos-header");
}
auto it = pmasternodesview->ExistMasternode(CMasternodesView::AuthIndex::ByOperator, mintersKey);
if (!it) {
return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, error("%s: block %s: active masternode for external blockHeader not found", __func__, hash.ToString()), REJECT_INVALID, " ");
}
auto const & nodeId = (*it)->second;

std::map<uint256, CBlockHeader> blockHeaders{};
std::map <uint256, CBlockHeader> blockHeaders{};

pmasternodesview->FindMintedBlockHeader(nodeId, block.mintedBlocks, blockHeaders, fIsFakeNet);
pmasternodesview->FindMintedBlockHeader(nodeId, block.mintedBlocks, blockHeaders, fIsFakeNet);

auto existingBlockHeader = blockHeaders.find(hash);
if (!blockHeaders.size() || existingBlockHeader == blockHeaders.end()) {
pmasternodesview->WriteMintedBlockHeader(nodeId, block.mintedBlocks, hash, block, fIsFakeNet);
}
auto existingBlockHeader = blockHeaders.find(hash);
if (!blockHeaders.size() || existingBlockHeader == blockHeaders.end()) {
pmasternodesview->WriteMintedBlockHeader(nodeId, block.mintedBlocks, hash, block, fIsFakeNet);
}

for (std::pair<uint256, CBlockHeader> blockHeader : blockHeaders) {
if(!pmasternodesview->CheckDoubleSign(block, blockHeader.second)) {
pmasternodesview->MarkMasternodeAsCriminals(nodeId, block, blockHeader.second);
for (std::pair <uint256, CBlockHeader> blockHeader : blockHeaders) {
if (!pmasternodesview->CheckDoubleSign(block, blockHeader.second)) {
pmasternodesview->MarkMasternodeAsCriminals(nodeId, block, blockHeader.second);
}
}
}

Expand Down
Loading

0 comments on commit 20d4555

Please sign in to comment.