1 // Aleth: Ethereum C++ client, tools and libraries.
2 // Copyright 2015-2019 Aleth Authors.
3 // Licensed under the GNU General Public License, Version 3.
4
5 /// @file
6 /// Incapsulation of libetehreum blockchain logic into test classes
7 /// that manage block/transaction import and test mining.
8 #include <libdevcore/DBFactory.h>
9 #include <libdevcore/TransientDirectory.h>
10 #include <libethashseal/Ethash.h>
11 #include <libethashseal/GenesisInfo.h>
12 #include <libethcore/SealEngine.h>
13 #include <libethereum/Block.h>
14 #include <libethereum/BlockChain.h>
15 #include <libethereum/GenesisInfo.h>
16 #include <libethereum/TransactionQueue.h>
17 #include <libethereum/ValidationSchemes.h>
18 #include <test/tools/libtesteth/BlockChainHelper.h>
19 #include <test/tools/libtesteth/TestHelper.h>
20
21 using namespace std;
22 using namespace json_spirit;
23 using namespace dev;
24 using namespace dev::eth;
25 namespace fs = boost::filesystem;
26
27 namespace dev
28 {
29 namespace test
30 {
TestTransaction(mObject const & _o)31 TestTransaction::TestTransaction(mObject const& _o) : m_jsonTransaction(_o)
32 {
33 ImportTest::importTransaction(_o, m_transaction); // check that json structure is valid
34 }
35
TestBlock()36 TestBlock::TestBlock()
37 {
38 m_dirty = false;
39 m_blockHeader.setTimestamp(0); // Create a valid header.
40 }
41
TestBlock(mObject const & _blockObj)42 TestBlock::TestBlock(mObject const& _blockObj) : TestBlock()
43 {
44 const mObject emptyState;
45 initBlockFromJsonHeader(_blockObj, emptyState);
46 }
47
TestBlock(mObject const & _blockHeader,mObject const & _stateObj)48 TestBlock::TestBlock(mObject const& _blockHeader, mObject const& _stateObj) : TestBlock()
49 {
50 initBlockFromJsonHeader(_blockHeader, _stateObj);
51 }
52
TestBlock(std::string const & _blockRLP)53 TestBlock::TestBlock(std::string const& _blockRLP) : TestBlock()
54 {
55 m_bytes = importByteArray(_blockRLP);
56
57 RLP root(m_bytes);
58 m_blockHeader = BlockHeader(m_bytes);
59
60 m_transactionQueue.clear();
61 m_testTransactions.clear();
62 for (auto const& tr : root[1])
63 {
64 Transaction tx(tr.data(), CheckTransaction::Everything);
65 TestTransaction testTx(tx);
66 m_transactionQueue.import(tx.rlp());
67 m_testTransactions.push_back(testTx);
68 }
69
70 for (auto const& uRLP : root[2])
71 {
72 BlockHeader uBl(uRLP.data(), HeaderData);
73 TestBlock uncle;
74 uncle.setBlockHeader(uBl);
75 m_uncles.push_back(uncle);
76 }
77 }
78
TestBlock(TestBlock const & _original)79 TestBlock::TestBlock(TestBlock const& _original)
80 {
81 populateFrom(_original);
82 }
83
operator =(TestBlock const & _original)84 TestBlock& TestBlock::operator=(TestBlock const& _original)
85 {
86 populateFrom(_original);
87 return *this;
88 }
89
initBlockFromJsonHeader(mObject const & _blockHeader,mObject const & _stateObj)90 void TestBlock::initBlockFromJsonHeader(mObject const& _blockHeader, mObject const& _stateObj)
91 {
92 if (dev::db::isDiskDatabase())
93 m_tempDirState = std::unique_ptr<TransientDirectory>(new TransientDirectory());
94
95 const fs::path tempDirPath = m_tempDirState.get() ? m_tempDirState.get()->path() : "";
96
97 m_state = std::unique_ptr<State>(new State(0,
98 OverlayDB(State::openDB(tempDirPath, h256{}, WithExisting::Kill)),
99 BaseState::Empty));
100 ImportTest::importState(_stateObj, *m_state.get());
101 m_state.get()->commit(State::CommitBehaviour::KeepEmptyAccounts);
102
103 json_spirit::mObject state = _stateObj;
104 dev::test::replaceCodeInState(state);
105
106 for (auto const& account : state)
107 {
108 auto const& accountJson = account.second.get_obj();
109 validation::validateAccountObj(accountJson);
110 }
111 m_accountMap = jsonToAccountMap(json_spirit::write_string(json_spirit::mValue(state), false));
112
113 m_blockHeader =
114 constructBlock(_blockHeader, _stateObj.size() ? m_state.get()->rootHash() : h256{});
115 recalcBlockHeaderBytes();
116 }
117
setState(State const & _state)118 void TestBlock::setState(State const& _state)
119 {
120 copyStateFrom(_state);
121 }
122
addTransaction(TestTransaction const & _tr)123 void TestBlock::addTransaction(TestTransaction const& _tr)
124 {
125 m_testTransactions.push_back(_tr);
126 if (m_transactionQueue.import(_tr.transaction().rlp()) != ImportResult::Success)
127 cnote << TestOutputHelper::get().testName() + " Test block failed importing transaction\n";
128 recalcBlockHeaderBytes();
129 }
130
addUncle(TestBlock const & _uncle)131 void TestBlock::addUncle(TestBlock const& _uncle)
132 {
133 m_uncles.push_back(_uncle);
134 recalcBlockHeaderBytes();
135 }
136
setUncles(vector<TestBlock> const & _uncles)137 void TestBlock::setUncles(vector<TestBlock> const& _uncles)
138 {
139 m_uncles.clear();
140 m_uncles = _uncles;
141 recalcBlockHeaderBytes();
142 }
143
premineUpdate(BlockHeader & _blockInfo)144 void TestBlock::premineUpdate(BlockHeader& _blockInfo)
145 {
146 // alter blockheader with defined fields before actual mining
147
148 if (m_premineUpdate.count("parentHash") > 0)
149 _blockInfo.setParentHash(m_blockHeader.parentHash());
150 if (m_premineUpdate.count("coinbase") > 0)
151 _blockInfo.setAuthor(m_blockHeader.author());
152
153 if (m_premineUpdate.count("uncleHash") > 0 || m_premineUpdate.count("stateRoot") > 0 ||
154 m_premineUpdate.count("transactionsTrie") > 0 || m_premineUpdate.count("receiptTrie") > 0)
155 _blockInfo.setRoots(m_premineUpdate.count("transactionsTrie") > 0 ?
156 m_blockHeader.transactionsRoot() :
157 _blockInfo.transactionsRoot(),
158 m_premineUpdate.count("receiptTrie") > 0 ? m_blockHeader.receiptsRoot() :
159 _blockInfo.receiptsRoot(),
160 m_premineUpdate.count("uncleHash") > 0 ? m_blockHeader.sha3Uncles() :
161 _blockInfo.sha3Uncles(),
162 m_premineUpdate.count("stateRoot") > 0 ? m_blockHeader.stateRoot() :
163 _blockInfo.stateRoot());
164
165 if (m_premineUpdate.count("bloom") > 0)
166 _blockInfo.setLogBloom(m_blockHeader.logBloom());
167 if (m_premineUpdate.count("difficulty") > 0)
168 _blockInfo.setDifficulty(m_blockHeader.difficulty());
169 if (m_premineUpdate.count("number") > 0)
170 _blockInfo.setNumber(m_blockHeader.number());
171 if (m_premineUpdate.count("gasLimit") > 0)
172 _blockInfo.setGasLimit(m_blockHeader.gasLimit());
173 if (m_premineUpdate.count("gasUsed") > 0)
174 _blockInfo.setGasUsed(m_blockHeader.gasUsed());
175 if (m_premineUpdate.count("timestamp") > 0)
176 _blockInfo.setTimestamp(m_blockHeader.timestamp());
177 if (m_premineUpdate.count("extraData") > 0)
178 _blockInfo.setExtraData(m_blockHeader.extraData());
179
180 m_premineHeader =
181 _blockInfo; // needed for check that any altered fields are altered in mined block as well
182 }
183
mine(TestBlockChain const & _bc)184 void TestBlock::mine(TestBlockChain const& _bc)
185 {
186 TestBlock const& genesisBlock = _bc.testGenesis();
187 OverlayDB const& genesisDB = genesisBlock.state().db();
188
189 BlockChain const& blockchain = _bc.getInterface();
190
191 Block block = blockchain.genesisBlock(genesisDB);
192 block.setAuthor(genesisBlock.beneficiary());
193
194 // set some header data before mining from original blockheader
195 BlockHeader& blockInfo = *const_cast<BlockHeader*>(&block.info());
196
197 try
198 {
199 ZeroGasPricer gp;
200 block.sync(blockchain); // sync block with blockchain
201
202 premineUpdate(blockInfo);
203
204 size_t transactionsOnImport = m_transactionQueue.topTransactions(100).size();
205 block.sync(blockchain, m_transactionQueue,
206 gp); //!!! Invalid transactions could be dropped from queue here!!!
207 // if (transactionsOnImport > m_transactionQueue.topTransactions(1000).size())
208 // BOOST_ERROR(TestOutputHelper::get().testName() + " Dropped invalid Transactions before
209 // mining!");
210 cnote << "Mining block difficulty of: " << block.info().difficulty();
211 dev::eth::mine(block, blockchain, blockchain.sealEngine());
212 blockchain.sealEngine()->verify(CheckNothingNew, block.info());
213 if (transactionsOnImport > block.pending().size())
214 cnote << TestOutputHelper::get().testName() +
215 " Dropped invalid Transactions when mining!";
216
217 // renew the TestBlock transactions
218 m_transactionQueue.clear();
219 for (size_t i = 0; i < block.pending().size(); i++)
220 m_transactionQueue.import(block.pending()[i]);
221 }
222 catch (Exception const& _e)
223 {
224 cnote << TestOutputHelper::get().testName() +
225 " block sync or mining did throw an exception: "
226 << diagnostic_information(_e);
227 return;
228 }
229 catch (std::exception const& _e)
230 {
231 cnote << TestOutputHelper::get().testName() +
232 " block sync or mining did throw an exception: "
233 << _e.what();
234 return;
235 }
236
237 size_t validTransactions = block.pending().size();
238 m_receipts = RLPStream(validTransactions);
239 for (size_t i = 0; i < validTransactions; i++)
240 {
241 const dev::bytes receipt = block.receipt(i).rlp();
242 m_receipts.appendRaw(receipt);
243 }
244
245 m_blockHeader = BlockHeader(block.blockData());
246 cnote << "Mined TrRoot: " << m_blockHeader.transactionsRoot();
247 copyStateFrom(block.state());
248
249 // Invalid uncles are dropped when mining. but we restore the hash to produce block with invalid
250 // uncles (for later test when importing to blockchain)
251 if (m_uncles.size())
252 {
253 // Fill info with uncles
254 RLPStream uncleStream;
255 uncleStream.appendList(m_uncles.size());
256 for (unsigned i = 0; i < m_uncles.size(); ++i)
257 {
258 RLPStream uncleRlp;
259 m_uncles[i].blockHeader().streamRLP(uncleRlp);
260 uncleStream.appendRaw(uncleRlp.out());
261 }
262
263 if (m_blockHeader.sha3Uncles() != sha3(uncleStream.out()))
264 cnote << "Some uncles been rejected when mining a test block!";
265 m_blockHeader.setSha3Uncles(sha3(uncleStream.out()));
266 updateNonce(_bc);
267 }
268 else
269 recalcBlockHeaderBytes();
270 }
271
setBlockHeader(BlockHeader const & _header)272 void TestBlock::setBlockHeader(BlockHeader const& _header)
273 {
274 m_blockHeader = _header;
275 recalcBlockHeaderBytes();
276 }
277
278 /// Test Block Private
constructBlock(mObject const & _o,h256 const & _stateRoot)279 BlockHeader TestBlock::constructBlock(mObject const& _o, h256 const& _stateRoot)
280 {
281 BlockHeader ret;
282 try
283 {
284 const dev::bytes c_blockRLP = createBlockRLPFromFields(_o, _stateRoot);
285 ret = BlockHeader(c_blockRLP, HeaderData);
286 // cdebug << "Block constructed of hash" << ret.hash() << "(without:" <<
287 //ret.hash(WithoutSeal) << ")";
288 }
289 catch (Exception const& _e)
290 {
291 cnote << TestOutputHelper::get().testName() + " block population did throw an exception: "
292 << diagnostic_information(_e);
293 }
294 catch (std::exception const& _e)
295 {
296 BOOST_ERROR(TestOutputHelper::get().testName() + " Failed block population with Exception: "
297 << _e.what());
298 }
299 catch (...)
300 {
301 BOOST_ERROR(TestOutputHelper::get().testName() +
302 " block population did throw an unknown exception\n");
303 }
304 return ret;
305 }
306
createBlockRLPFromFields(mObject const & _tObj,h256 const & _stateRoot)307 dev::bytes TestBlock::createBlockRLPFromFields(mObject const& _tObj, h256 const& _stateRoot)
308 {
309 RLPStream rlpStream;
310 rlpStream.appendList(_tObj.count("hash") > 0 ? (_tObj.size() - 1) : _tObj.size());
311
312 if (_tObj.count("parentHash"))
313 rlpStream << importByteArray(_tObj.at("parentHash").get_str());
314
315 if (_tObj.count("uncleHash"))
316 rlpStream << importByteArray(_tObj.at("uncleHash").get_str());
317
318 if (_tObj.count("coinbase"))
319 rlpStream << importByteArray(_tObj.at("coinbase").get_str());
320
321 if (_stateRoot)
322 rlpStream << _stateRoot;
323 else if (_tObj.count("stateRoot"))
324 rlpStream << importByteArray(_tObj.at("stateRoot").get_str());
325
326 if (_tObj.count("transactionsTrie"))
327 rlpStream << importByteArray(_tObj.at("transactionsTrie").get_str());
328
329 if (_tObj.count("receiptTrie"))
330 rlpStream << importByteArray(_tObj.at("receiptTrie").get_str());
331
332 if (_tObj.count("bloom"))
333 rlpStream << importByteArray(_tObj.at("bloom").get_str());
334
335 if (_tObj.count("difficulty"))
336 rlpStream << bigint(_tObj.at("difficulty").get_str());
337
338 if (_tObj.count("number"))
339 rlpStream << bigint(_tObj.at("number").get_str());
340
341 if (_tObj.count("gasLimit"))
342 rlpStream << bigint(_tObj.at("gasLimit").get_str());
343
344 if (_tObj.count("gasUsed"))
345 rlpStream << bigint(_tObj.at("gasUsed").get_str());
346
347 if (_tObj.count("timestamp"))
348 rlpStream << bigint(_tObj.at("timestamp").get_str());
349
350 if (_tObj.count("extraData"))
351 rlpStream << fromHex(_tObj.at("extraData").get_str());
352
353 if (_tObj.count("mixHash"))
354 rlpStream << importByteArray(_tObj.at("mixHash").get_str());
355
356 if (_tObj.count("nonce"))
357 rlpStream << importByteArray(_tObj.at("nonce").get_str());
358
359 return rlpStream.out();
360 }
361
updateNonce(TestBlockChain const & _bc)362 void TestBlock::updateNonce(TestBlockChain const& _bc)
363 {
364 if (((BlockHeader)m_blockHeader).difficulty() == 0)
365 BOOST_TEST_MESSAGE(
366 "Trying to mine a block with 0 difficulty! " + TestOutputHelper::get().testName());
367 else
368 {
369 // do not verify blockheader for validity here
370 dev::eth::mine(m_blockHeader, _bc.getInterface().sealEngine(), false);
371 }
372
373 recalcBlockHeaderBytes();
374 }
375
verify(TestBlockChain const & _bc) const376 void TestBlock::verify(TestBlockChain const& _bc) const
377 {
378 if (m_dirty) // TestBlock have incorrect blockheader for testing purposes
379 return;
380
381 try
382 {
383 _bc.getInterface().sealEngine()->verify(
384 CheckNothingNew, m_blockHeader, BlockHeader(), &m_bytes);
385 }
386 catch (Exception const& _e)
387 {
388 u256 const& daoHardfork = _bc.getInterface().sealEngine()->chainParams().daoHardforkBlock;
389 if ((m_blockHeader.number() >= daoHardfork && m_blockHeader.number() <= daoHardfork + 9) ||
390 m_blockHeader.number() == 0)
391 {
392 string exWhat{_e.what()};
393 string exExpect = "InvalidTransactionsRoot";
394 BOOST_REQUIRE_MESSAGE(exWhat.find(exExpect) != string::npos,
395 TestOutputHelper::get().testName() +
396 "block import expected another exeption: " + exExpect);
397 }
398 else
399 BOOST_ERROR(TestOutputHelper::get().testName() + toString(m_blockHeader.number()) +
400 " BlockHeader Verification failed: "
401 << boost::current_exception_diagnostic_information());
402 }
403 catch (...)
404 {
405 BOOST_ERROR(TestOutputHelper::get().testName() + " BlockHeader Verification failed: "
406 << boost::current_exception_diagnostic_information());
407 }
408 }
409
410 // Form bytestream of a block with [header transactions uncles]
recalcBlockHeaderBytes()411 void TestBlock::recalcBlockHeaderBytes()
412 {
413 Transactions txList;
414 for (auto const& txi : m_transactionQueue.topTransactions(std::numeric_limits<unsigned>::max()))
415 txList.push_back(txi);
416 RLPStream txStream;
417 txStream.appendList(txList.size());
418 for (unsigned i = 0; i < txList.size(); ++i)
419 {
420 RLPStream txrlp;
421 txList[i].streamRLP(txrlp);
422 txStream.appendRaw(txrlp.out());
423 }
424
425 RLPStream uncleStream;
426 uncleStream.appendList(m_uncles.size());
427 for (unsigned i = 0; i < m_uncles.size(); ++i)
428 {
429 RLPStream uncleRlp;
430 m_uncles[i].blockHeader().streamRLP(uncleRlp);
431 uncleStream.appendRaw(uncleRlp.out());
432 }
433
434 RLPStream blHeaderStream;
435 m_blockHeader.streamRLP(blHeaderStream, WithSeal);
436
437 RLPStream ret(3);
438 ret.appendRaw(blHeaderStream.out()); // block header
439 ret.appendRaw(txStream.out()); // transactions
440 ret.appendRaw(uncleStream.out()); // uncles
441 m_bytes = ret.out();
442 }
443
copyStateFrom(State const & _state)444 void TestBlock::copyStateFrom(State const& _state)
445 {
446 // WEIRD WAY TO COPY STATE AS COPY CONSTRUCTOR FOR STATE NOT IMPLEMENTED CORRECTLY (they would
447 // share the same DB)
448 if (dev::db::isDiskDatabase())
449 m_tempDirState.reset(new TransientDirectory());
450
451 fs::path tempDirPath = m_tempDirState.get() ? m_tempDirState.get()->path() : "";
452 m_state.reset(new State(0,
453 OverlayDB(State::openDB(tempDirPath, h256{}, WithExisting::Kill)),
454 BaseState::Empty));
455 json_spirit::mObject obj = fillJsonWithState(_state);
456 ImportTest::importState(obj, *m_state.get());
457 }
458
clearState()459 void TestBlock::clearState()
460 {
461 m_state.reset(0);
462 m_tempDirState.reset(0);
463 for (size_t i = 0; i < m_uncles.size(); i++)
464 m_uncles.at(i).clearState();
465 }
466
populateFrom(TestBlock const & _original)467 void TestBlock::populateFrom(TestBlock const& _original)
468 {
469 try
470 {
471 copyStateFrom(_original.state()); // copy state if it is defined in _original
472 }
473 catch (BlockStateUndefined const& _ex)
474 {
475 clog(VerbosityDebug, "net") << _ex.what() << " copying block with null state";
476 }
477 m_testTransactions = _original.testTransactions();
478 m_transactionQueue.clear();
479 TransactionQueue const& trQueue = _original.transactionQueue();
480 for (auto const& txi : trQueue.topTransactions(std::numeric_limits<unsigned>::max()))
481 m_transactionQueue.import(txi.rlp());
482
483 m_uncles = _original.uncles();
484 m_blockHeader = _original.blockHeader();
485 m_bytes = _original.bytes();
486 m_accountMap = _original.accountMap();
487 m_dirty = false;
488 }
489
TestBlockChain(TestBlock const & _genesisBlock,MiningType _mining)490 TestBlockChain::TestBlockChain(TestBlock const& _genesisBlock, MiningType _mining)
491 {
492 reset(_genesisBlock, _mining);
493 }
494
reset(TestBlock const & _genesisBlock,MiningType _mining)495 void TestBlockChain::reset(TestBlock const& _genesisBlock, MiningType _mining)
496 {
497 if (dev::db::isDiskDatabase())
498 m_tempDirBlockchain.reset(new TransientDirectory);
499
500 fs::path tempDirBlockchainPath = m_tempDirBlockchain.get() ? m_tempDirBlockchain.get()->path() : "";
501 ChainParams p = ChainParams(genesisInfo(TestBlockChain::s_sealEngineNetwork),
502 _genesisBlock.bytes(), _genesisBlock.accountMap());
503 if (_mining == MiningType::ForceEthash)
504 p.sealEngineName = eth::Ethash::name();
505 else if (_mining == MiningType::ForceNoProof)
506 p.sealEngineName = eth::NoProof::name();
507
508 m_blockChain.reset(new BlockChain(p, tempDirBlockchainPath, WithExisting::Kill));
509 if (!m_blockChain->isKnown(BlockHeader::headerHashFromBlock(_genesisBlock.bytes())))
510 {
511 cdebug << "Not known:" << BlockHeader::headerHashFromBlock(_genesisBlock.bytes())
512 << BlockHeader(p.genesisBlock()).hash();
513 cdebug << "Genesis block not known!";
514 cdebug << "This should never happen.";
515 assert(false);
516 }
517 m_lastBlock = m_genesisBlock = _genesisBlock;
518 }
519
addBlock(TestBlock const & _block)520 bool TestBlockChain::addBlock(TestBlock const& _block)
521 {
522 while (true)
523 {
524 try
525 {
526 _block.verify(*this); // check that block header match TestBlock contents
527 m_blockChain.get()->import(_block.bytes(), m_genesisBlock.state().db());
528 break;
529 }
530 catch (FutureTime const&)
531 {
532 std::this_thread::sleep_for(std::chrono::milliseconds(100));
533 break;
534 }
535 }
536
537 // Imported and best
538 if (_block.bytes() == m_blockChain.get()->block())
539 {
540 m_lastBlock = _block;
541
542 // overwrite state in case _block had no State defined (e.x. created from RLP)
543 OverlayDB const& genesisDB = m_genesisBlock.state().db();
544 Block block = (m_blockChain.get()->genesisBlock(genesisDB));
545 block.sync(*m_blockChain.get());
546
547 State st(block.state());
548 st.setRoot(block.info().stateRoot());
549 m_lastBlock.setState(st);
550 return true;
551 }
552
553 return false;
554 }
555
syncUncles(vector<TestBlock> const & uncles)556 vector<TestBlock> TestBlockChain::syncUncles(vector<TestBlock> const& uncles)
557 {
558 vector<TestBlock> validUncles;
559 if (uncles.size() == 0)
560 return validUncles;
561
562 BlockQueue uncleBlockQueue;
563 BlockChain& blockchain = *m_blockChain.get();
564 uncleBlockQueue.setChain(blockchain);
565
566 for (size_t i = 0; i < uncles.size(); i++)
567 {
568 try
569 {
570 uncleBlockQueue.import(&uncles.at(i).bytes(), false);
571 std::this_thread::sleep_for(std::chrono::seconds(1)); // wait until block is verified
572 validUncles.push_back(uncles.at(i));
573 }
574 catch (...)
575 {
576 cnote << "error in importing uncle! This produces an invalid block (May be by purpose "
577 "for testing).";
578 }
579 }
580
581 blockchain.sync(uncleBlockQueue, m_genesisBlock.state().db(), (unsigned)4);
582 return validUncles;
583 }
584
defaultTransaction(u256 const & _nonce,u256 const & _gasPrice,u256 const & _gasLimit,bytes const & _data)585 TestTransaction TestTransaction::defaultTransaction(
586 u256 const& _nonce, u256 const& _gasPrice, u256 const& _gasLimit, bytes const& _data)
587 {
588 json_spirit::mObject txObj;
589 txObj["data"] = toHexPrefixed(_data);
590 txObj["gasLimit"] = toString(_gasLimit);
591 txObj["gasPrice"] = toString(_gasPrice);
592 txObj["nonce"] = toString(_nonce);
593 txObj["secretKey"] = "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8";
594 txObj["to"] = "0x095e7baea6a6c7c4c2dfeb977efac326af552d87";
595 txObj["value"] = "100";
596
597 return TestTransaction(txObj);
598 }
599
defaultZeroTransaction(u256 const & _gasLimit,bytes const & _data)600 TestTransaction TestTransaction::defaultZeroTransaction(u256 const& _gasLimit, bytes const& _data)
601 {
602 json_spirit::mObject txObj;
603 txObj["data"] = toHexPrefixed(_data);
604 txObj["gasLimit"] = toString(_gasLimit);
605 txObj["gasPrice"] = toString(0);
606 txObj["nonce"] = toString(0);
607 txObj["v"] = toString(1);
608 txObj["r"] = toString(0);
609 txObj["s"] = toString(0);
610 txObj["to"] = "0x095e7baea6a6c7c4c2dfeb977efac326af552d87";
611 txObj["value"] = "0";
612
613 return TestTransaction(txObj);
614 }
615
defaultAccountMap()616 AccountMap TestBlockChain::defaultAccountMap()
617 {
618 AccountMap ret;
619 ret[Address("a94f5374fce5edbc8e2a8697c15331677e6ebf0b")] = Account(0, 10000000000);
620 return ret;
621 }
622
defaultGenesisBlockJson()623 json_spirit::mObject TestBlockChain::defaultGenesisBlockJson()
624 {
625 json_spirit::mObject blockObj;
626 blockObj["bloom"] =
627 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
628 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
629 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
630 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
631 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
632 "00000000000000000000000000000000000000000000000000000000000000";
633 blockObj["coinbase"] = "0x8888f1f195afa192cfee860698584c030f4c9db1";
634 blockObj["difficulty"] = "131072";
635 blockObj["extraData"] = "0x42";
636 blockObj["gasLimit"] = "3141592";
637 blockObj["gasUsed"] = "0";
638 blockObj["mixHash"] = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421";
639 blockObj["nonce"] = "0x0102030405060708";
640 blockObj["number"] = "0";
641 blockObj["parentHash"] = "0x0000000000000000000000000000000000000000000000000000000000000000";
642 blockObj["receiptTrie"] = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421";
643 blockObj["stateRoot"] = "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a";
644 blockObj["timestamp"] = "0x54c98c81";
645 blockObj["transactionsTrie"] =
646 "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421";
647 blockObj["uncleHash"] = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347";
648 return blockObj;
649 }
650
defaultGenesisBlock(u256 const & _gasLimit)651 TestBlock TestBlockChain::defaultGenesisBlock(u256 const& _gasLimit)
652 {
653 json_spirit::mObject blockObj = defaultGenesisBlockJson();
654 blockObj["gasLimit"] = toString(_gasLimit);
655
656 json_spirit::mObject accountObj;
657 accountObj["balance"] = "10000000000";
658 accountObj["nonce"] = "1"; //=1for nonce too low exception check
659 accountObj["code"] = "";
660 accountObj["storage"] = json_spirit::mObject();
661
662 json_spirit::mObject accountMapObj;
663 accountMapObj["a94f5374fce5edbc8e2a8697c15331677e6ebf0b"] = accountObj;
664
665 return TestBlock(blockObj, accountMapObj);
666 }
667 }
668 }
669