Line data Source code
1 : // Copyright (c) 2011-2014 The Bitcoin Core developers
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #include "chainparams.h"
6 : #include "coins.h"
7 : #include "consensus/validation.h"
8 : #include "main.h"
9 : #include "miner.h"
10 : #include "pubkey.h"
11 : #include "script/standard.h"
12 : #include "txmempool.h"
13 : #include "uint256.h"
14 : #include "util.h"
15 : #include "utilstrencodings.h"
16 :
17 : #include "test/test_bitcoin.h"
18 :
19 : #include <boost/test/unit_test.hpp>
20 :
21 1 : BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup)
22 :
23 : static
24 : struct {
25 : unsigned char extranonce;
26 : unsigned int nonce;
27 : } blockinfo[] = {
28 : {4, 0xa4a3e223}, {2, 0x15c32f9e}, {1, 0x0375b547}, {1, 0x7004a8a5},
29 : {2, 0xce440296}, {2, 0x52cfe198}, {1, 0x77a72cd0}, {2, 0xbb5d6f84},
30 : {2, 0x83f30c2c}, {1, 0x48a73d5b}, {1, 0xef7dcd01}, {2, 0x6809c6c4},
31 : {2, 0x0883ab3c}, {1, 0x087bbbe2}, {2, 0x2104a814}, {2, 0xdffb6daa},
32 : {1, 0xee8a0a08}, {2, 0xba4237c1}, {1, 0xa70349dc}, {1, 0x344722bb},
33 : {3, 0xd6294733}, {2, 0xec9f5c94}, {2, 0xca2fbc28}, {1, 0x6ba4f406},
34 : {2, 0x015d4532}, {1, 0x6e119b7c}, {2, 0x43e8f314}, {2, 0x27962f38},
35 : {2, 0xb571b51b}, {2, 0xb36bee23}, {2, 0xd17924a8}, {2, 0x6bc212d9},
36 : {1, 0x630d4948}, {2, 0x9a4c4ebb}, {2, 0x554be537}, {1, 0xd63ddfc7},
37 : {2, 0xa10acc11}, {1, 0x759a8363}, {2, 0xfb73090d}, {1, 0xe82c6a34},
38 : {1, 0xe33e92d7}, {3, 0x658ef5cb}, {2, 0xba32ff22}, {5, 0x0227a10c},
39 : {1, 0xa9a70155}, {5, 0xd096d809}, {1, 0x37176174}, {1, 0x830b8d0f},
40 : {1, 0xc6e3910e}, {2, 0x823f3ca8}, {1, 0x99850849}, {1, 0x7521fb81},
41 : {1, 0xaacaabab}, {1, 0xd645a2eb}, {5, 0x7aea1781}, {5, 0x9d6e4b78},
42 : {1, 0x4ce90fd8}, {1, 0xabdc832d}, {6, 0x4a34f32a}, {2, 0xf2524c1c},
43 : {2, 0x1bbeb08a}, {1, 0xad47f480}, {1, 0x9f026aeb}, {1, 0x15a95049},
44 : {2, 0xd1cb95b2}, {2, 0xf84bbda5}, {1, 0x0fa62cd1}, {1, 0xe05f9169},
45 : {1, 0x78d194a9}, {5, 0x3e38147b}, {5, 0x737ba0d4}, {1, 0x63378e10},
46 : {1, 0x6d5f91cf}, {2, 0x88612eb8}, {2, 0xe9639484}, {1, 0xb7fabc9d},
47 : {2, 0x19b01592}, {1, 0x5a90dd31}, {2, 0x5bd7e028}, {2, 0x94d00323},
48 : {1, 0xa9b9c01a}, {1, 0x3a40de61}, {1, 0x56e7eec7}, {5, 0x859f7ef6},
49 : {1, 0xfd8e5630}, {1, 0x2b0c9f7f}, {1, 0xba700e26}, {1, 0x7170a408},
50 : {1, 0x70de86a8}, {1, 0x74d64cd5}, {1, 0x49e738a1}, {2, 0x6910b602},
51 : {0, 0x643c565f}, {1, 0x54264b3f}, {2, 0x97ea6396}, {2, 0x55174459},
52 : {2, 0x03e8779a}, {1, 0x98f34d8f}, {1, 0xc07b2b07}, {1, 0xdfe29668},
53 : {1, 0x3141c7c1}, {1, 0xb3b595f4}, {1, 0x735abf08}, {5, 0x623bfbce},
54 : {2, 0xd351e722}, {1, 0xf4ca48c9}, {1, 0x5b19c670}, {1, 0xa164bf0e},
55 : {2, 0xbbbeb305}, {2, 0xfe1c810a},
56 : };
57 :
58 : // NOTE: These tests rely on CreateNewBlock doing its own self-validation!
59 6 : BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
60 : {
61 4 : CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
62 : CBlockTemplate *pblocktemplate;
63 1 : CMutableTransaction tx,tx2;
64 : CScript script;
65 : uint256 hash;
66 :
67 1 : LOCK(cs_main);
68 1 : fCheckpointsEnabled = false;
69 :
70 : // Simple block creation, nothing special yet:
71 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
72 :
73 : // We can't make transactions until we have inputs
74 : // Therefore, load 100 blocks :)
75 : std::vector<CTransaction*>txFirst;
76 111 : for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i)
77 : {
78 110 : CBlock *pblock = &pblocktemplate->block; // pointer for convenience
79 110 : pblock->nVersion = 1;
80 110 : pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
81 110 : CMutableTransaction txCoinbase(pblock->vtx[0]);
82 110 : txCoinbase.nVersion = 1;
83 220 : txCoinbase.vin[0].scriptSig = CScript();
84 110 : txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce);
85 110 : txCoinbase.vin[0].scriptSig.push_back(chainActive.Height());
86 220 : txCoinbase.vout[0].scriptPubKey = CScript();
87 220 : pblock->vtx[0] = CTransaction(txCoinbase);
88 220 : if (txFirst.size() < 2)
89 2 : txFirst.push_back(new CTransaction(pblock->vtx[0]));
90 110 : pblock->hashMerkleRoot = pblock->ComputeMerkleRoot();
91 110 : pblock->nNonce = blockinfo[i].nonce;
92 110 : CValidationState state;
93 880 : BOOST_CHECK(ProcessNewBlock(state, NULL, pblock, true, NULL));
94 990 : BOOST_CHECK(state.IsValid());
95 110 : pblock->hashPrevBlock = pblock->GetHash();
96 : }
97 1 : delete pblocktemplate;
98 :
99 : // Just to make sure we can still make simple blocks
100 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
101 1 : delete pblocktemplate;
102 :
103 : // block sigops > limit: 1000 CHECKMULTISIG + 1
104 2 : tx.vin.resize(1);
105 : // NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG
106 2 : tx.vin[0].scriptSig = CScript() << OP_0 << OP_0 << OP_0 << OP_NOP << OP_CHECKMULTISIG << OP_1;
107 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
108 1 : tx.vin[0].prevout.n = 0;
109 2 : tx.vout.resize(1);
110 1 : tx.vout[0].nValue = 5000000000LL;
111 1002 : for (unsigned int i = 0; i < 1001; ++i)
112 : {
113 1001 : tx.vout[0].nValue -= 1000000;
114 1001 : hash = tx.GetHash();
115 3003 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
116 1001 : tx.vin[0].prevout.hash = hash;
117 : }
118 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
119 1 : delete pblocktemplate;
120 1 : mempool.clear();
121 :
122 : // block size > limit
123 2 : tx.vin[0].scriptSig = CScript();
124 : // 18 * (520char + DROP) + OP_1 = 9433 bytes
125 2 : std::vector<unsigned char> vchData(520);
126 19 : for (unsigned int i = 0; i < 18; ++i)
127 18 : tx.vin[0].scriptSig << vchData << OP_DROP;
128 1 : tx.vin[0].scriptSig << OP_1;
129 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
130 1 : tx.vout[0].nValue = 5000000000LL;
131 129 : for (unsigned int i = 0; i < 128; ++i)
132 : {
133 128 : tx.vout[0].nValue -= 10000000;
134 128 : hash = tx.GetHash();
135 384 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
136 128 : tx.vin[0].prevout.hash = hash;
137 : }
138 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
139 1 : delete pblocktemplate;
140 1 : mempool.clear();
141 :
142 : // orphan in mempool
143 1 : hash = tx.GetHash();
144 3 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
145 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
146 1 : delete pblocktemplate;
147 1 : mempool.clear();
148 :
149 : // child with higher priority than parent
150 2 : tx.vin[0].scriptSig = CScript() << OP_1;
151 1 : tx.vin[0].prevout.hash = txFirst[1]->GetHash();
152 1 : tx.vout[0].nValue = 4900000000LL;
153 1 : hash = tx.GetHash();
154 3 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
155 1 : tx.vin[0].prevout.hash = hash;
156 2 : tx.vin.resize(2);
157 2 : tx.vin[1].scriptSig = CScript() << OP_1;
158 1 : tx.vin[1].prevout.hash = txFirst[0]->GetHash();
159 1 : tx.vin[1].prevout.n = 0;
160 1 : tx.vout[0].nValue = 5900000000LL;
161 1 : hash = tx.GetHash();
162 3 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
163 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
164 1 : delete pblocktemplate;
165 1 : mempool.clear();
166 :
167 : // coinbase in mempool
168 2 : tx.vin.resize(1);
169 1 : tx.vin[0].prevout.SetNull();
170 2 : tx.vin[0].scriptSig = CScript() << OP_0 << OP_1;
171 1 : tx.vout[0].nValue = 0;
172 1 : hash = tx.GetHash();
173 3 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
174 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
175 1 : delete pblocktemplate;
176 1 : mempool.clear();
177 :
178 : // invalid (pre-p2sh) txn in mempool
179 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
180 1 : tx.vin[0].prevout.n = 0;
181 2 : tx.vin[0].scriptSig = CScript() << OP_1;
182 1 : tx.vout[0].nValue = 4900000000LL;
183 2 : script = CScript() << OP_0;
184 4 : tx.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(script));
185 1 : hash = tx.GetHash();
186 3 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
187 1 : tx.vin[0].prevout.hash = hash;
188 4 : tx.vin[0].scriptSig = CScript() << (std::vector<unsigned char>)script;
189 1 : tx.vout[0].nValue -= 1000000;
190 1 : hash = tx.GetHash();
191 3 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
192 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
193 1 : delete pblocktemplate;
194 1 : mempool.clear();
195 :
196 : // double spend txn pair in mempool
197 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
198 2 : tx.vin[0].scriptSig = CScript() << OP_1;
199 1 : tx.vout[0].nValue = 4900000000LL;
200 2 : tx.vout[0].scriptPubKey = CScript() << OP_1;
201 1 : hash = tx.GetHash();
202 3 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
203 2 : tx.vout[0].scriptPubKey = CScript() << OP_2;
204 1 : hash = tx.GetHash();
205 3 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
206 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
207 1 : delete pblocktemplate;
208 1 : mempool.clear();
209 :
210 : // subsidy changing
211 1 : int nHeight = chainActive.Height();
212 1 : chainActive.Tip()->nHeight = 209999;
213 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
214 1 : delete pblocktemplate;
215 1 : chainActive.Tip()->nHeight = 210000;
216 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
217 1 : delete pblocktemplate;
218 1 : chainActive.Tip()->nHeight = nHeight;
219 :
220 : // non-final txs in mempool
221 1 : SetMockTime(chainActive.Tip()->GetMedianTimePast()+1);
222 :
223 : // height locked
224 1 : tx.vin[0].prevout.hash = txFirst[0]->GetHash();
225 2 : tx.vin[0].scriptSig = CScript() << OP_1;
226 1 : tx.vin[0].nSequence = 0;
227 1 : tx.vout[0].nValue = 4900000000LL;
228 2 : tx.vout[0].scriptPubKey = CScript() << OP_1;
229 1 : tx.nLockTime = chainActive.Tip()->nHeight+1;
230 1 : hash = tx.GetHash();
231 3 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
232 9 : BOOST_CHECK(!CheckFinalTx(tx));
233 :
234 : // time locked
235 2 : tx2.vin.resize(1);
236 1 : tx2.vin[0].prevout.hash = txFirst[1]->GetHash();
237 1 : tx2.vin[0].prevout.n = 0;
238 2 : tx2.vin[0].scriptSig = CScript() << OP_1;
239 1 : tx2.vin[0].nSequence = 0;
240 2 : tx2.vout.resize(1);
241 1 : tx2.vout[0].nValue = 4900000000LL;
242 2 : tx2.vout[0].scriptPubKey = CScript() << OP_1;
243 1 : tx2.nLockTime = chainActive.Tip()->GetMedianTimePast()+1;
244 1 : hash = tx2.GetHash();
245 3 : mempool.addUnchecked(hash, CTxMemPoolEntry(tx2, 11, GetTime(), 111.0, 11));
246 9 : BOOST_CHECK(!CheckFinalTx(tx2));
247 :
248 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
249 :
250 : // Neither tx should have make it into the template.
251 6 : BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 1);
252 1 : delete pblocktemplate;
253 :
254 : // However if we advance height and time by one, both will.
255 1 : chainActive.Tip()->nHeight++;
256 1 : SetMockTime(chainActive.Tip()->GetMedianTimePast()+2);
257 :
258 : // FIXME: we should *actually* create a new block so the following test
259 : // works; CheckFinalTx() isn't fooled by monkey-patching nHeight.
260 : //BOOST_CHECK(CheckFinalTx(tx));
261 : //BOOST_CHECK(CheckFinalTx(tx2));
262 :
263 8 : BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
264 6 : BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3);
265 1 : delete pblocktemplate;
266 :
267 1 : chainActive.Tip()->nHeight--;
268 1 : SetMockTime(0);
269 1 : mempool.clear();
270 :
271 18 : BOOST_FOREACH(CTransaction *tx, txFirst)
272 4 : delete tx;
273 :
274 1 : fCheckpointsEnabled = true;
275 1 : }
276 :
277 3 : BOOST_AUTO_TEST_SUITE_END()
|