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