Suggested corrections on comments, variable names.
Also new test case testing the PoW skip in UNITTEST.
This commit is contained in:
parent
a25fd6be13
commit
5e2e7fcb99
@ -215,7 +215,7 @@ public:
|
|||||||
static CRegTestParams regTestParams;
|
static CRegTestParams regTestParams;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Regression test
|
// Unit test
|
||||||
//
|
//
|
||||||
class CUnitTestParams : public CMainParams, public CModifiableParams {
|
class CUnitTestParams : public CMainParams, public CModifiableParams {
|
||||||
public:
|
public:
|
||||||
@ -242,9 +242,9 @@ public:
|
|||||||
virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority) { nEnforceBlockUpgradeMajority=anEnforceBlockUpgradeMajority; }
|
virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority) { nEnforceBlockUpgradeMajority=anEnforceBlockUpgradeMajority; }
|
||||||
virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority) { nRejectBlockOutdatedMajority=anRejectBlockOutdatedMajority; }
|
virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority) { nRejectBlockOutdatedMajority=anRejectBlockOutdatedMajority; }
|
||||||
virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority) { nToCheckBlockUpgradeMajority=anToCheckBlockUpgradeMajority; }
|
virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority) { nToCheckBlockUpgradeMajority=anToCheckBlockUpgradeMajority; }
|
||||||
virtual void setDefaultCheckMemPool(bool aDefaultCheckMemPool) { fDefaultCheckMemPool=aDefaultCheckMemPool; }
|
virtual void setDefaultCheckMemPool(bool afDefaultCheckMemPool) { fDefaultCheckMemPool=afDefaultCheckMemPool; }
|
||||||
virtual void setAllowMinDifficultyBlocks(bool aAllowMinDifficultyBlocks) { fAllowMinDifficultyBlocks=aAllowMinDifficultyBlocks; }
|
virtual void setAllowMinDifficultyBlocks(bool afAllowMinDifficultyBlocks) { fAllowMinDifficultyBlocks=afAllowMinDifficultyBlocks; }
|
||||||
virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck) { fSkipProofOfWorkCheck = aSkipProofOfWorkCheck; }
|
virtual void setSkipProofOfWorkCheck(bool afSkipProofOfWorkCheck) { fSkipProofOfWorkCheck = afSkipProofOfWorkCheck; }
|
||||||
};
|
};
|
||||||
static CUnitTestParams unitTestParams;
|
static CUnitTestParams unitTestParams;
|
||||||
|
|
||||||
|
@ -2304,8 +2304,8 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex
|
|||||||
nHeight = pindexPrev->nHeight+1;
|
nHeight = pindexPrev->nHeight+1;
|
||||||
|
|
||||||
// Check proof of work
|
// Check proof of work
|
||||||
if (!Params().SkipProofOfWorkCheck())
|
if ((!Params().SkipProofOfWorkCheck()) &&
|
||||||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block))
|
(block.nBits != GetNextWorkRequired(pindexPrev, &block)))
|
||||||
return state.DoS(100, error("AcceptBlock() : incorrect proof of work"),
|
return state.DoS(100, error("AcceptBlock() : incorrect proof of work"),
|
||||||
REJECT_INVALID, "bad-diffbits");
|
REJECT_INVALID, "bad-diffbits");
|
||||||
|
|
||||||
|
@ -9,33 +9,34 @@
|
|||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
// Tests the majority rule which states that after 1000 v2 blocks no v1 block can go
|
// This test cheecks the majority rule which states that after 1000 v2 blocks no new v1 block can be part of that branch.
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(blockv2_tests)
|
BOOST_AUTO_TEST_SUITE(blockv2_tests)
|
||||||
|
|
||||||
static CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
|
static CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
|
||||||
|
|
||||||
static void SetEmptyBlock(CBlock * pblock)
|
static void SetEmptyBlock(CBlock * pblock)
|
||||||
{
|
{
|
||||||
pblock->nVersion = 2;
|
pblock->nVersion = 2;
|
||||||
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
|
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
|
||||||
pblock->nNonce = 0;
|
pblock->nNonce = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetBlockDefaultAttributesAndHeight(CBlock * pblock,bool addHeight,int difValue)
|
static void SetBlockDefaultAttributesAndHeight(CBlock * pblock,bool addHeight,int heightDifference)
|
||||||
{
|
{
|
||||||
SetEmptyBlock(pblock);
|
SetEmptyBlock(pblock);
|
||||||
|
|
||||||
// Add the coinbase
|
// Add the coinbase
|
||||||
CMutableTransaction txCoinbase(pblock->vtx[0]);
|
CMutableTransaction txCoinbase(pblock->vtx[0]);
|
||||||
|
|
||||||
if (addHeight)
|
if (addHeight)
|
||||||
txCoinbase.vin[0].scriptSig = (CScript() << (chainActive.Height()+1+difValue) << 0);
|
txCoinbase.vin[0].scriptSig = (CScript() << (chainActive.Height()+1+heightDifference) << 0);
|
||||||
else
|
else
|
||||||
txCoinbase.vin[0].scriptSig = (CScript() << difValue << 0); // At least size 2, this is a protocol spec
|
txCoinbase.vin[0].scriptSig = (CScript() << heightDifference << 0); // At least size 2, this is a protocol spec
|
||||||
|
|
||||||
txCoinbase.vout[0].scriptPubKey = CScript();
|
txCoinbase.vout[0].scriptPubKey = CScript();
|
||||||
pblock->vtx[0] = CTransaction(txCoinbase);
|
pblock->vtx[0] = CTransaction(txCoinbase);
|
||||||
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckSubsidyHalving(CBlockTemplate * &pblocktemplate, CBlock * &pblock)
|
void CheckSubsidyHalving(CBlockTemplate * &pblocktemplate, CBlock * &pblock)
|
||||||
@ -44,6 +45,8 @@ void CheckSubsidyHalving(CBlockTemplate * &pblocktemplate, CBlock * &pblock)
|
|||||||
{
|
{
|
||||||
// The RegTest network has a low subsidy halving interval (150) so
|
// The RegTest network has a low subsidy halving interval (150) so
|
||||||
// we must recompute the coinbase subsidy if we reach the boundary.
|
// we must recompute the coinbase subsidy if we reach the boundary.
|
||||||
|
// The unittest network allows modifying this interval. We check it so this
|
||||||
|
// test can work in any network.
|
||||||
|
|
||||||
// preserve parent hash
|
// preserve parent hash
|
||||||
uint256 prevParent = pblock->hashPrevBlock;
|
uint256 prevParent = pblock->hashPrevBlock;
|
||||||
@ -54,6 +57,22 @@ void CheckSubsidyHalving(CBlockTemplate * &pblocktemplate, CBlock * &pblock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckBlockAddedToBestChainSuccessfully(CBlock *pblock)
|
||||||
|
{
|
||||||
|
int PreviousHeight;
|
||||||
|
CValidationState state;
|
||||||
|
|
||||||
|
PreviousHeight = chainActive.Height();
|
||||||
|
BOOST_CHECK(ProcessBlock(state, NULL, pblock));
|
||||||
|
BOOST_CHECK(state.IsValid());
|
||||||
|
BOOST_CHECK((PreviousHeight+1) == chainActive.Height()); // to differentiate from orphan blocks, which also get accepted in ProcessBlock()
|
||||||
|
|
||||||
|
// Previous checks do not assure the current best chain has pblock as tip. It could be the case that a because
|
||||||
|
// of a malfunction in the chain reorganization code, a reorganization causes an increase of the chain length, but with another tip.
|
||||||
|
// So we also check that.
|
||||||
|
BOOST_CHECK(chainActive.Tip()->GetBlockHash()==pblock->GetHash());
|
||||||
|
}
|
||||||
|
|
||||||
void Blockv2test()
|
void Blockv2test()
|
||||||
{
|
{
|
||||||
assert(Params().NetworkID() == CBaseChainParams::UNITTEST);
|
assert(Params().NetworkID() == CBaseChainParams::UNITTEST);
|
||||||
@ -73,16 +92,17 @@ void Blockv2test()
|
|||||||
uint256 hash;
|
uint256 hash;
|
||||||
int PreviousHeight;
|
int PreviousHeight;
|
||||||
|
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
|
|
||||||
// Simple block creation, nothing special yet.
|
// Simple block creation, nothing special yet.
|
||||||
pblocktemplate = CreateNewBlock(scriptPubKey);
|
pblocktemplate = CreateNewBlock(scriptPubKey);
|
||||||
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
||||||
|
|
||||||
LogPrintf("Blockv2test block v1 add begin\n");
|
LogPrintf("Blockv2test block v1 add begin\n");
|
||||||
// First create a block v1, check that it is accepted. The block has an invalid height
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// First create a block v1, check that it is accepted. The block has an invalid height.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
SetBlockDefaultAttributesAndHeight(pblock,false,5000);
|
SetBlockDefaultAttributesAndHeight(pblock,false,5000);
|
||||||
pblock->nVersion = 1;
|
pblock->nVersion = 1;
|
||||||
CValidationState state1;
|
CValidationState state1;
|
||||||
@ -93,7 +113,6 @@ void Blockv2test()
|
|||||||
pblock->hashPrevBlock = pblock->GetHash(); // update parent
|
pblock->hashPrevBlock = pblock->GetHash(); // update parent
|
||||||
|
|
||||||
|
|
||||||
// Now create exactly 1000 blocks v2
|
|
||||||
|
|
||||||
// First check that the supermajority threshold is exactly 1000 blocks
|
// First check that the supermajority threshold is exactly 1000 blocks
|
||||||
BOOST_CHECK(Params().ToCheckBlockUpgradeMajority()==1000); //
|
BOOST_CHECK(Params().ToCheckBlockUpgradeMajority()==1000); //
|
||||||
@ -105,11 +124,19 @@ void Blockv2test()
|
|||||||
|
|
||||||
LogPrintf("Blockv2test BIP30 repetition begin\n");
|
LogPrintf("Blockv2test BIP30 repetition begin\n");
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// First, if we try to add a block v2 with the same coinbase tx, we should get
|
// First, if we try to add a block v2 with the same coinbase tx, we should get
|
||||||
// "bad-txns-BIP30" because the coinbase tx has the same hash as the previous.
|
// "bad-txns-BIP30" because the coinbase tx has the same hash as the previous.
|
||||||
// Unluckily, even if ConnectBlock returns a "bad-txns-BIP30", ActivateBestChainStep clears
|
// Even if ConnectBlock returns a "bad-txns-BIP30", ActivateBestChainStep clears
|
||||||
// the state, so we get true here and the "bad-txns-BIP30" reason is lost.
|
// the state, so we get true here and the "bad-txns-BIP30" reason is lost. But this
|
||||||
// We verify instead that the chain height has not been incremented.
|
// is the intended behaviour: Receiving a single block can cause zero or multiple blocks to be
|
||||||
|
// connected, and ActivateBestChain's responsibility is just switching the best block whatsoever.
|
||||||
|
// Feedback about failures causes a reject message to be sent to the peer from which we received
|
||||||
|
// the actual block (not necessarily the same as from whom we got the block that caused the reorg),
|
||||||
|
// for which we remember the peerid.
|
||||||
|
// Because we cannot access the failure reason here, we just verify instead that the chain
|
||||||
|
// height has not been incremented.
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
CValidationState state7;
|
CValidationState state7;
|
||||||
PreviousHeight = chainActive.Height();
|
PreviousHeight = chainActive.Height();
|
||||||
@ -121,6 +148,11 @@ void Blockv2test()
|
|||||||
BOOST_CHECK(PreviousHeight == chainActive.Height()); // we check the block has not been added.
|
BOOST_CHECK(PreviousHeight == chainActive.Height()); // we check the block has not been added.
|
||||||
|
|
||||||
LogPrintf("Blockv2test 750 v2 blocks begin\n");
|
LogPrintf("Blockv2test 750 v2 blocks begin\n");
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
// Now create 750 v2 blocks
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
for (int i=0;i<750;i++)
|
for (int i=0;i<750;i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -131,18 +163,17 @@ void Blockv2test()
|
|||||||
// We add a value to the height to make is NOT equal to the actual height.
|
// We add a value to the height to make is NOT equal to the actual height.
|
||||||
SetBlockDefaultAttributesAndHeight(pblock,true,1000); // blocks version 2 without height are allowed! for only 750 blocks
|
SetBlockDefaultAttributesAndHeight(pblock,true,1000); // blocks version 2 without height are allowed! for only 750 blocks
|
||||||
pblock->nVersion = 2;
|
pblock->nVersion = 2;
|
||||||
CValidationState state;
|
|
||||||
|
|
||||||
PreviousHeight = chainActive.Height();
|
CheckBlockAddedToBestChainSuccessfully(pblock);
|
||||||
BOOST_CHECK(ProcessBlock(state, NULL, pblock));
|
|
||||||
BOOST_CHECK(state.IsValid());
|
|
||||||
BOOST_CHECK((PreviousHeight+1) == chainActive.Height()); // to differentiate from orphan blocks, which also get accepted in ProcessBlock()
|
|
||||||
pblock->hashPrevBlock = pblock->GetHash(); // update parent
|
pblock->hashPrevBlock = pblock->GetHash(); // update parent
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrintf("Blockv2test v2 without height rejected begin\n");
|
LogPrintf("Blockv2test v2 without height rejected begin\n");
|
||||||
|
|
||||||
// Now we try to add a block v2, with an invalid height and it should be rejected. We use 2000 because is not in the range [1000..1750].
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Now we try to add a block v2, with an invalid height and it should be rejected.
|
||||||
|
// We use 2000 as argument heightDifference because is not in the range [1000..1750].
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
CheckSubsidyHalving(pblocktemplate,pblock);
|
CheckSubsidyHalving(pblocktemplate,pblock);
|
||||||
SetBlockDefaultAttributesAndHeight(pblock,true,2000); //
|
SetBlockDefaultAttributesAndHeight(pblock,true,2000); //
|
||||||
pblock->nVersion = 2;
|
pblock->nVersion = 2;
|
||||||
@ -154,8 +185,10 @@ void Blockv2test()
|
|||||||
|
|
||||||
LogPrintf("Blockv2test v2 with height accepted begin\n");
|
LogPrintf("Blockv2test v2 with height accepted begin\n");
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////
|
||||||
// Now we add a block with height, must be ok.
|
// Now we add 200 additional blocks, until we get 950
|
||||||
|
// (the threshold where v1 blocks are not accepted anymore)
|
||||||
|
/////////////////////////////////////////////////////////////
|
||||||
for (int i=0;i<200;i++)
|
for (int i=0;i<200;i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -163,19 +196,16 @@ void Blockv2test()
|
|||||||
CheckSubsidyHalving(pblocktemplate,pblock);
|
CheckSubsidyHalving(pblocktemplate,pblock);
|
||||||
SetBlockDefaultAttributesAndHeight(pblock,true,0);
|
SetBlockDefaultAttributesAndHeight(pblock,true,0);
|
||||||
pblock->nVersion = 2;
|
pblock->nVersion = 2;
|
||||||
CValidationState state;
|
CheckBlockAddedToBestChainSuccessfully(pblock);
|
||||||
PreviousHeight = chainActive.Height();
|
|
||||||
BOOST_CHECK(ProcessBlock(state, NULL, pblock));
|
|
||||||
BOOST_CHECK(state.IsValid());
|
|
||||||
BOOST_CHECK((PreviousHeight+1) == chainActive.Height()); // to differentiate from orphan blocks, which also get accepted in ProcessBlock()
|
|
||||||
|
|
||||||
pblock->hashPrevBlock = pblock->GetHash(); // update parent
|
pblock->hashPrevBlock = pblock->GetHash(); // update parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LogPrintf("Blockv2test block v1 rejected\n");
|
LogPrintf("Blockv2test block v1 rejected\n");
|
||||||
// Now we add 200 additional blocks, until we get 950 (the threshold were v1 blocks are not accepted anymore)
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Now we try to add a block v1, it should be rejected, even if it hash the height field
|
// Now we try to add a block v1, it should be rejected, even if it hash the height field
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
CheckSubsidyHalving(pblocktemplate,pblock);
|
CheckSubsidyHalving(pblocktemplate,pblock);
|
||||||
SetBlockDefaultAttributesAndHeight(pblock,true,0);
|
SetBlockDefaultAttributesAndHeight(pblock,true,0);
|
||||||
pblock->nVersion = 1;
|
pblock->nVersion = 1;
|
||||||
@ -185,11 +215,9 @@ void Blockv2test()
|
|||||||
BOOST_CHECK(state2.GetRejectReason()=="bad-version");
|
BOOST_CHECK(state2.GetRejectReason()=="bad-version");
|
||||||
// Do not update parent since block has failed
|
// Do not update parent since block has failed
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Some other missing tests, added here as bonus...
|
|
||||||
|
|
||||||
// Block time too old check
|
// Block time too old check
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
CheckSubsidyHalving(pblocktemplate,pblock);
|
CheckSubsidyHalving(pblocktemplate,pblock);
|
||||||
SetBlockDefaultAttributesAndHeight(pblock,true,0);
|
SetBlockDefaultAttributesAndHeight(pblock,true,0);
|
||||||
pblock->nVersion = 2;
|
pblock->nVersion = 2;
|
||||||
@ -200,7 +228,9 @@ void Blockv2test()
|
|||||||
BOOST_CHECK(state4.GetRejectReason()=="time-too-old");
|
BOOST_CHECK(state4.GetRejectReason()=="time-too-old");
|
||||||
// Do not update parent since block has failed
|
// Do not update parent since block has failed
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
// Adding a non-final coinbase, must modify coinbase
|
// Adding a non-final coinbase, must modify coinbase
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
CheckSubsidyHalving(pblocktemplate,pblock);
|
CheckSubsidyHalving(pblocktemplate,pblock);
|
||||||
SetEmptyBlock(pblock);
|
SetEmptyBlock(pblock);
|
||||||
// Use a mutable coinbase to change nLockTime and nSequence
|
// Use a mutable coinbase to change nLockTime and nSequence
|
||||||
@ -217,10 +247,23 @@ void Blockv2test()
|
|||||||
BOOST_CHECK(state5.GetRejectReason()=="bad-txns-nonfinal");
|
BOOST_CHECK(state5.GetRejectReason()=="bad-txns-nonfinal");
|
||||||
// Do not update parent since block has failed
|
// Do not update parent since block has failed
|
||||||
|
|
||||||
|
ModifiableParams()->setSkipProofOfWorkCheck(false);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Just to be sure that proof-of-work skipping is working ok, we submit a block
|
||||||
|
// without enought proof of work and it must be rejected.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CheckSubsidyHalving(pblocktemplate,pblock);
|
||||||
|
SetBlockDefaultAttributesAndHeight(pblock,true,0);
|
||||||
|
pblock->nVersion = 2;
|
||||||
|
CValidationState state6;
|
||||||
|
BOOST_CHECK(ProcessBlock(state6, NULL, pblock)==false);
|
||||||
|
BOOST_CHECK(!state6.IsValid());
|
||||||
|
BOOST_CHECK(state6.GetRejectReason()=="high-hash");
|
||||||
|
|
||||||
delete pblocktemplate;
|
delete pblocktemplate;
|
||||||
|
|
||||||
ModifiableParams()->setSkipProofOfWorkCheck(false);
|
|
||||||
LogPrintf("Blockv2test testcase ends\n");
|
LogPrintf("Blockv2test testcase ends\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user