Skip to content

Commit 782f6c8

Browse files
SergioDemianLernerlaanwj
authored andcommitted
Add blocksv2 tests
1 parent 0c9ca5b commit 782f6c8

File tree

2 files changed

+270
-0
lines changed

2 files changed

+270
-0
lines changed

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ BITCOIN_TESTS =\
5151
test/key_tests.cpp \
5252
test/main_tests.cpp \
5353
test/miner_tests.cpp \
54+
test/blockv2_tests.cpp \
5455
test/mruset_tests.cpp \
5556
test/multisig_tests.cpp \
5657
test/netbase_tests.cpp \

src/test/blockv2_tests.cpp

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
// Copyright (c) 2011-2014 The Bitcoin Core developers
2+
// Distributed under the MIT/X11 software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include "main.h"
6+
#include "miner.h"
7+
#include "uint256.h"
8+
#include "util.h"
9+
10+
#include <boost/test/unit_test.hpp>
11+
12+
// This test checks the majority rule which states that after 1000 v2 blocks no new v1 block can be part of that branch.
13+
14+
BOOST_AUTO_TEST_SUITE(blockv2_tests)
15+
16+
static CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
17+
18+
static void SetEmptyBlock(CBlock * pblock)
19+
{
20+
pblock->nVersion = 2;
21+
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
22+
pblock->nNonce = 0;
23+
}
24+
25+
static void SetBlockDefaultAttributesAndHeight(CBlock * pblock,bool addHeight,int heightDifference)
26+
{
27+
SetEmptyBlock(pblock);
28+
29+
// Add the coinbase
30+
CMutableTransaction txCoinbase(pblock->vtx[0]);
31+
32+
if (addHeight)
33+
txCoinbase.vin[0].scriptSig = (CScript() << (chainActive.Height()+1+heightDifference) << 0);
34+
else
35+
txCoinbase.vin[0].scriptSig = (CScript() << heightDifference << 0); // At least size 2, this is a protocol spec
36+
37+
txCoinbase.vout[0].scriptPubKey = CScript();
38+
pblock->vtx[0] = CTransaction(txCoinbase);
39+
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
40+
}
41+
42+
void CheckSubsidyHalving(CBlockTemplate * &pblocktemplate, CBlock * &pblock)
43+
{
44+
if ((chainActive.Height()+1) % Params().SubsidyHalvingInterval() == 0)
45+
{
46+
// The RegTest network has a low subsidy halving interval (150) so
47+
// we must recompute the coinbase subsidy if we reach the boundary.
48+
// The unittest network allows modifying this interval. We check it so this
49+
// test can work in any network.
50+
51+
// preserve parent hash
52+
uint256 prevParent = pblock->hashPrevBlock;
53+
delete pblocktemplate;
54+
pblocktemplate = CreateNewBlock(scriptPubKey);
55+
pblock = &pblocktemplate->block; // pointer for convenience
56+
pblock->hashPrevBlock = prevParent;
57+
}
58+
}
59+
60+
void CheckBlockAddedToBestChainSuccessfully(CBlock *pblock)
61+
{
62+
int PreviousHeight;
63+
CValidationState state;
64+
65+
PreviousHeight = chainActive.Height();
66+
BOOST_CHECK(ProcessBlock(state, NULL, pblock));
67+
BOOST_CHECK(state.IsValid());
68+
BOOST_CHECK((PreviousHeight+1) == chainActive.Height()); // to differentiate from orphan blocks, which also get accepted in ProcessBlock()
69+
70+
// Previous checks do not assure the current best chain has pblock as tip. It could be the case that a because
71+
// of a malfunction in the chain reorganization code, a reorganization causes an increase of the chain length, but with another tip.
72+
// So we also check that.
73+
BOOST_CHECK(chainActive.Tip()->GetBlockHash()==pblock->GetHash());
74+
}
75+
76+
BOOST_AUTO_TEST_CASE(Blockv2testcase)
77+
{
78+
assert(Params().NetworkID() == CBaseChainParams::UNITTEST);
79+
ModifiableParams()->setSkipProofOfWorkCheck(true);
80+
81+
// We don't know the state of the block-chain here: it depends on which other tests are run before this test.
82+
// See https://github.com/bitcoin/bitcoin/pull/4688 for a patch that allows the re-creation of the block-chain
83+
// for each testcase that requires it.
84+
85+
// If miner_tests.cpp is run before, the chain will be 100 blocks long, and all of them will be v1
86+
87+
88+
LogPrintf("Blockv2test testcase starts\n");
89+
90+
CBlockTemplate *pblocktemplate;
91+
CScript script;
92+
uint256 hash;
93+
int PreviousHeight;
94+
95+
LOCK(cs_main);
96+
97+
// Simple block creation, nothing special yet.
98+
pblocktemplate = CreateNewBlock(scriptPubKey);
99+
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
100+
101+
LogPrintf("Blockv2test block v1 add begin\n");
102+
103+
////////////////////////////////////////////////////////////////////////////////////////
104+
// First create a block v1, check that it is accepted. The block has an invalid height.
105+
////////////////////////////////////////////////////////////////////////////////////////
106+
SetBlockDefaultAttributesAndHeight(pblock,false,5000);
107+
pblock->nVersion = 1;
108+
CValidationState state1;
109+
PreviousHeight = chainActive.Height();
110+
BOOST_CHECK(ProcessBlock(state1, NULL, pblock));
111+
BOOST_CHECK(state1.IsValid());
112+
BOOST_CHECK((PreviousHeight+1) == chainActive.Height()); // to differentiate from orphan blocks, which also get accepted in ProcessBlock()
113+
pblock->hashPrevBlock = pblock->GetHash(); // update parent
114+
115+
116+
117+
// First check that the supermajority threshold is exactly 1000 blocks
118+
BOOST_CHECK(Params().ToCheckBlockUpgradeMajority()==1000); //
119+
BOOST_CHECK(Params().EnforceBlockUpgradeMajority()==750);
120+
BOOST_CHECK(Params().RejectBlockOutdatedMajority()==950);
121+
122+
// Over the last 1000 blocks, 750 blocks must be v2 to switch to v2-only mode.
123+
// Here we're testing only the last 750, not any subset.
124+
125+
LogPrintf("Blockv2test BIP30 repetition begin\n");
126+
127+
///////////////////////////////////////////////////////////////////////////////////////////////////////
128+
// First, if we try to add a block v2 with the same coinbase tx, we should get
129+
// "bad-txns-BIP30" because the coinbase tx has the same hash as the previous.
130+
// Even if ConnectBlock returns a "bad-txns-BIP30", ActivateBestChainStep clears
131+
// the state, so we get true here and the "bad-txns-BIP30" reason is lost. But this
132+
// is the intended behaviour: Receiving a single block can cause zero or multiple blocks to be
133+
// connected, and ActivateBestChain's responsibility is just switching the best block whatsoever.
134+
// Feedback about failures causes a reject message to be sent to the peer from which we received
135+
// the actual block (not necessarily the same as from whom we got the block that caused the reorg),
136+
// for which we remember the peerid.
137+
// Because we cannot access the failure reason here, we just verify instead that the chain
138+
// height has not been incremented.
139+
//////////////////////////////////////////////////////////////////////////////////////////////////////
140+
141+
CValidationState state7;
142+
PreviousHeight = chainActive.Height();
143+
CheckSubsidyHalving(pblocktemplate,pblock);
144+
SetBlockDefaultAttributesAndHeight(pblock,false,5000); //
145+
pblock->nVersion = 2;
146+
BOOST_CHECK(ProcessBlock(state7, NULL, pblock)); // should we care about the return value?
147+
BOOST_CHECK(state7.IsValid());
148+
BOOST_CHECK(PreviousHeight == chainActive.Height()); // we check the block has not been added.
149+
150+
LogPrintf("Blockv2test 750 v2 blocks begin\n");
151+
152+
////////////////////////////
153+
// Now create 750 v2 blocks
154+
////////////////////////////
155+
156+
for (int i=0;i<750;i++)
157+
{
158+
159+
LogPrintf("Blockv2test block %d begin\n",i);
160+
161+
CheckSubsidyHalving(pblocktemplate,pblock);
162+
163+
// We add a value to the height to make is NOT equal to the actual height.
164+
SetBlockDefaultAttributesAndHeight(pblock,true,1000); // blocks version 2 without height are allowed! for only 750 blocks
165+
pblock->nVersion = 2;
166+
167+
CheckBlockAddedToBestChainSuccessfully(pblock);
168+
pblock->hashPrevBlock = pblock->GetHash(); // update parent
169+
}
170+
171+
LogPrintf("Blockv2test v2 without height rejected begin\n");
172+
173+
/////////////////////////////////////////////////////////////////////////////////////
174+
// Now we try to add a block v2, with an invalid height and it should be rejected.
175+
// We use 2000 as argument heightDifference because is not in the range [1000..1750].
176+
/////////////////////////////////////////////////////////////////////////////////////
177+
CheckSubsidyHalving(pblocktemplate,pblock);
178+
SetBlockDefaultAttributesAndHeight(pblock,true,2000); //
179+
pblock->nVersion = 2;
180+
CValidationState state0;
181+
BOOST_CHECK(ProcessBlock(state0, NULL, pblock)==false);
182+
BOOST_CHECK(!state0.IsValid());
183+
BOOST_CHECK(state0.GetRejectReason()=="bad-cb-height");
184+
// Do not update parent since block has failed
185+
186+
LogPrintf("Blockv2test v2 with height accepted begin\n");
187+
188+
/////////////////////////////////////////////////////////////
189+
// Now we add 200 additional blocks, until we get 950
190+
// (the threshold where v1 blocks are not accepted anymore)
191+
/////////////////////////////////////////////////////////////
192+
for (int i=0;i<200;i++)
193+
{
194+
195+
LogPrintf("Blockv2test v2block %d begin\n",i);
196+
CheckSubsidyHalving(pblocktemplate,pblock);
197+
SetBlockDefaultAttributesAndHeight(pblock,true,0);
198+
pblock->nVersion = 2;
199+
CheckBlockAddedToBestChainSuccessfully(pblock);
200+
pblock->hashPrevBlock = pblock->GetHash(); // update parent
201+
}
202+
203+
204+
LogPrintf("Blockv2test block v1 rejected\n");
205+
206+
/////////////////////////////////////////////////////////////////////////////////////////
207+
// Now we try to add a block v1, it should be rejected, even if it hash the height field
208+
/////////////////////////////////////////////////////////////////////////////////////////
209+
CheckSubsidyHalving(pblocktemplate,pblock);
210+
SetBlockDefaultAttributesAndHeight(pblock,true,0);
211+
pblock->nVersion = 1;
212+
CValidationState state2;
213+
BOOST_CHECK(ProcessBlock(state2, NULL, pblock)==false);
214+
BOOST_CHECK(!state2.IsValid());
215+
BOOST_CHECK(state2.GetRejectReason()=="bad-version");
216+
// Do not update parent since block has failed
217+
218+
////////////////////////////////////////////////////////
219+
// Block time too old check
220+
////////////////////////////////////////////////////////
221+
CheckSubsidyHalving(pblocktemplate,pblock);
222+
SetBlockDefaultAttributesAndHeight(pblock,true,0);
223+
pblock->nVersion = 2;
224+
pblock->nTime = chainActive.Tip()->GetMedianTimePast()-1;
225+
CValidationState state4;
226+
BOOST_CHECK(ProcessBlock(state4, NULL, pblock)==false);
227+
BOOST_CHECK(!state4.IsValid());
228+
BOOST_CHECK(state4.GetRejectReason()=="time-too-old");
229+
// Do not update parent since block has failed
230+
231+
////////////////////////////////////////////////////////
232+
// Adding a non-final coinbase, must modify coinbase
233+
////////////////////////////////////////////////////////
234+
CheckSubsidyHalving(pblocktemplate,pblock);
235+
SetEmptyBlock(pblock);
236+
// Use a mutable coinbase to change nLockTime and nSequence
237+
CMutableTransaction txCoinbase(pblock->vtx[0]);
238+
txCoinbase.vin[0].scriptSig = (CScript() << chainActive.Height() << 0);
239+
txCoinbase.nLockTime = LOCKTIME_THRESHOLD-1; // refers to height
240+
txCoinbase.vin[0].nSequence = 1; // non-zero sequence
241+
pblock->vtx[0] = CTransaction(txCoinbase);
242+
pblock->nVersion = 2;
243+
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
244+
CValidationState state5;
245+
BOOST_CHECK(ProcessBlock(state5, NULL, pblock)==false);
246+
BOOST_CHECK(!state5.IsValid());
247+
BOOST_CHECK(state5.GetRejectReason()=="bad-txns-nonfinal");
248+
// Do not update parent since block has failed
249+
250+
ModifiableParams()->setSkipProofOfWorkCheck(false);
251+
252+
////////////////////////////////////////////////////////////////////////////////
253+
// Just to be sure that proof-of-work skipping is working ok, we submit a block
254+
// without enought proof of work and it must be rejected.
255+
////////////////////////////////////////////////////////////////////////////////
256+
CheckSubsidyHalving(pblocktemplate,pblock);
257+
SetBlockDefaultAttributesAndHeight(pblock,true,0);
258+
pblock->nVersion = 2;
259+
CValidationState state6;
260+
BOOST_CHECK(ProcessBlock(state6, NULL, pblock)==false);
261+
BOOST_CHECK(!state6.IsValid());
262+
BOOST_CHECK(state6.GetRejectReason()=="high-hash");
263+
264+
delete pblocktemplate;
265+
266+
LogPrintf("Blockv2test testcase ends\n");
267+
}
268+
269+
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)