Fabcoin Core  0.16.2
P2P Digital Currency
ImportTest.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
27 using namespace dev;
28 using namespace dev::test;
29 using namespace std;
30 
31 ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller, testType testTemplate):
32  m_statePre(0, OverlayDB(), eth::BaseState::Empty),
33  m_statePost(0, OverlayDB(), eth::BaseState::Empty),
34  m_testObject(_o),
35  m_testType(testTemplate)
36 {
38  {
39  importEnv(_o["env"].get_obj());
40  importTransaction(_o["transaction"].get_obj());
41  importState(_o["pre"].get_obj(), m_statePre);
42  if (!isFiller && m_testType == testType::StateTests)
43  {
44  if (_o.count("post"))
45  importState(_o["post"].get_obj(), m_statePost);
46  else
47  importState(_o["postState"].get_obj(), m_statePost);
48  m_logsExpected = importLog(_o["logs"].get_array());
49  }
50  }
51 }
52 
54 {
56  {
58  std::pair<eth::State, ImportTest::execOutput> out = executeTransaction(network, m_envInfo, m_statePre, m_transaction);
59  m_statePost = out.first;
60  m_logs = out.second.second.log();
61  return out.second.first.output;
62  }
64  {
65  vector<eth::Network> networks;
66  if (!Options::get().singleTestNet.empty())
67  {
68  networks.push_back(stringToNetId(Options::get().singleTestNet));
69  }
70  else
71  {
72  networks.push_back(eth::Network::FrontierTest);
73  networks.push_back(eth::Network::HomesteadTest);
74  networks.push_back(eth::Network::EIP150Test);
75  networks.push_back(eth::Network::EIP158Test);
76  networks.push_back(eth::Network::MetropolisTest);
77  }
78 
80  vector<transactionToExecute> transactionResults;
81  for (size_t j = 0; j < networks.size(); j++)
82  {
83  for (size_t i = 0; i < m_transactions.size(); i++)
84  {
85  eth::Network network = networks[j];
86  std::pair<eth::State, ImportTest::execOutput> out = executeTransaction(network, m_envInfo, m_statePre, m_transactions[i].transaction);
87  m_transactions[i].postState = out.first;
88  m_transactions[i].netId = network;
89  transactionResults.push_back(m_transactions[i]);
90 
91  if (Options::get().fillchain)
92  {
93  json_spirit::mObject testObj;
94  testObj["network"] = netIdToString(networks[j]);
95  string postfix = "_d" + toString(m_transactions[i].dataInd);
96  postfix += "g" + toString(m_transactions[i].gasInd);
97  postfix += "v" + toString(m_transactions[i].valInd);
98  postfix += "_" + netIdToString(networks[j]);
99  string testname = TestOutputHelper::testName() + postfix;
100 
102  genesisObj["coinbase"] = toString(m_envInfo.author());
103  genesisObj["gasLimit"] = toCompactHex(m_envInfo.gasLimit(), HexPrefix::Add);
104  genesisObj["timestamp"] = toCompactHex(m_envInfo.timestamp() - 50, HexPrefix::Add);
105  testObj["genesisBlockHeader"] = genesisObj;
106  testObj["pre"] = fillJsonWithState(m_statePre);
107 
109  AccountMaskMap m = std::unordered_map<Address, AccountMask>();
110  StateAndMap smap {s, m};
111  TrExpectSection search {m_transactions[i], smap};
112  vector<size_t> stateIndexesToPrint; //not used
113  // look if there is an expect section that match this transaction
114 
115  if (m_testObject.count("expect"))
116  for (auto const& exp: m_testObject["expect"].get_array())
117  {
118  TrExpectSection* search2 = &search;
119  checkGeneralTestSectionSearch(exp.get_obj(), stateIndexesToPrint, "", search2);
120  if (search.second.first.addresses().size() != 0) //if match in the expect sections for this tr found
121  {
122  //replace expected mining reward (in state tests it is 0)
123  json_spirit::mObject obj = fillJsonWithState(search2->second.first, search2->second.second);
124  for (auto& adr: obj)
125  {
126  if (adr.first == toString(m_envInfo.author()))
127  {
128  if (adr.second.get_obj().count("balance"))
129  {
130  u256 expectCoinbaseBalance = toInt(adr.second.get_obj()["balance"]);
131  expectCoinbaseBalance += u256("5000000000000000000");
132  adr.second.get_obj()["balance"] = toCompactHex(expectCoinbaseBalance, HexPrefix::Add);
133  }
134  }
135  }
136  testObj["expect"] = obj;
137  break;
138  }
139  }
140 
141  json_spirit::mObject rewriteHeader;
142  rewriteHeader["gasLimit"] = toCompactHex(m_envInfo.gasLimit(), HexPrefix::Add);
143  rewriteHeader["difficulty"] = toCompactHex(m_envInfo.difficulty(), HexPrefix::Add);
144  rewriteHeader["timestamp"] = toCompactHex(m_envInfo.timestamp(), HexPrefix::Add);
145  rewriteHeader["updatePoW"] = "1";
146 
147  json_spirit::mArray blocksArr;
148  json_spirit::mArray transcArr;
149  transcArr.push_back(fillJsonWithTransaction(m_transactions[i].transaction));
150  json_spirit::mObject blocksObj;
151  blocksObj["blockHeaderPremine"] = rewriteHeader;
152  blocksObj["transactions"] = transcArr;
153  blocksObj["uncleHeaders"] = json_spirit::mArray();
154  blocksArr.push_back(blocksObj);
155  testObj["blocks"] = blocksArr;
156  json[testname] = testObj;
157  }
158  }
159  }
160 
161  if (Options::get().fillchain)
162  {
163  string tmpFillerName = getTestPath() + "/src/GenStateTestAsBcTemp/" + TestOutputHelper::caseName() + "/" + TestOutputHelper::testName() + "Filler.json";
164  writeFile(tmpFillerName, asBytes(json_spirit::write_string((json_spirit::mValue)json, true)));
165  dev::test::executeTests(TestOutputHelper::testName(), "/BlockchainTests/GeneralStateTests/" + TestOutputHelper::caseName(),
166  "/GenStateTestAsBcTemp/" + TestOutputHelper::caseName(), dev::test::doBlockchainTests);
167  }
168 
169  m_transactions.clear();
170  m_transactions = transactionResults;
171  return bytes();
172  }
173 
174  BOOST_ERROR("Error when executing test ImportTest::executeTest()");
175  return bytes();
176 }
177 
178 std::pair<eth::State, ImportTest::execOutput> ImportTest::executeTransaction(eth::Network const _sealEngineNetwork, eth::EnvInfo const& _env, eth::State const& _preState, eth::Transaction const& _tr)
179 {
180  eth::State initialState = _preState;
181  try
182  {
183  unique_ptr<SealEngineFace> se(ChainParams(genesisInfo(_sealEngineNetwork)).createSealEngine());
184  bool removeEmptyAccounts = m_envInfo.number() >= se->chainParams().u256Param("EIP158ForkBlock");
185  ImportTest::execOutput execOut = initialState.execute(_env, *se.get(), _tr);
186  initialState.commit(removeEmptyAccounts ? State::CommitBehaviour::RemoveEmptyAccounts : State::CommitBehaviour::KeepEmptyAccounts);
187  return std::pair<eth::State, ImportTest::execOutput>(initialState, execOut);
188  }
189  catch (Exception const& _e)
190  {
191  cnote << "Exception: " << diagnostic_information(_e);
192  }
193  catch (std::exception const& _e)
194  {
195  cnote << "state execution exception: " << _e.what();
196  }
197 
198  initialState.commit(State::CommitBehaviour::KeepEmptyAccounts);
199  ExecutionResult emptyRes;
200  LogEntries emptyLogs;
201  ImportTest::execOutput execOut = make_pair(emptyRes, TransactionReceipt(h256(), u256(), emptyLogs));
202  return std::pair<eth::State, ImportTest::execOutput>(initialState, execOut);
203 }
204 
206 {
207  static const set<string> hashes {"bloom" , "coinbase", "hash", "mixHash", "parentHash", "receiptTrie",
208  "stateRoot", "transactionsTrie", "uncleHash", "currentCoinbase",
209  "previousHash", "to", "address", "caller", "origin", "secretKey", "data"};
210 
211  for (auto& i: _o)
212  {
213  std::string key = i.first;
214  if (hashes.count(key))
215  continue;
216 
217  std::string str;
218  json_spirit::mValue value = i.second;
219 
220  if (value.type() == json_spirit::int_type)
221  str = toString(value.get_int());
222  else if (value.type() == json_spirit::str_type)
223  str = value.get_str();
224  else continue;
225 
226  _o[key] = (str.substr(0, 2) == "0x") ? str : toCompactHex(toInt(str), HexPrefix::Add, 1);
227  }
228  return _o;
229 }
230 
232 {
233  BOOST_REQUIRE(_o.count("currentGasLimit") > 0);
234  BOOST_REQUIRE(_o.count("currentDifficulty") > 0);
235  BOOST_REQUIRE(_o.count("currentNumber") > 0);
236  BOOST_REQUIRE(_o.count("currentTimestamp") > 0);
237  BOOST_REQUIRE(_o.count("currentCoinbase") > 0);
238  auto gasLimit = toInt(_o["currentGasLimit"]);
239  BOOST_REQUIRE(gasLimit <= std::numeric_limits<int64_t>::max());
240  m_envInfo.setGasLimit(gasLimit.convert_to<int64_t>());
241  m_envInfo.setDifficulty(toInt(_o["currentDifficulty"]));
242  m_envInfo.setNumber(toInt(_o["currentNumber"]));
243  m_envInfo.setTimestamp(toInt(_o["currentTimestamp"]));
244  m_envInfo.setAuthor(Address(_o["currentCoinbase"].get_str()));
246 }
247 
248 // import state from not fully declared json_spirit::mObject, writing to _stateOptionsMap which fields were defined in json
249 void ImportTest::importState(json_spirit::mObject const& _o, State& _state, AccountMaskMap& o_mask)
250 {
251  //Compile LLL code of the test Fillers using external call to lllc
252  json_spirit::mObject o = _o;
254  std::string jsondata = json_spirit::write_string((json_spirit::mValue)o, false);
255  _state.populateFrom(jsonToAccountMap(jsondata, 0, &o_mask));
256 }
257 
258 void ImportTest::importState(json_spirit::mObject const& _o, State& _state)
259 {
260  AccountMaskMap mask;
261  importState(_o, _state, mask);
262  for (auto const& i: mask)
263  //check that every parameter was declared in state object
264  if (!i.second.allSet())
265  BOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!"));
266 }
267 
269 {
270  if (_o.count("secretKey") > 0)
271  {
272  BOOST_REQUIRE(_o.count("nonce") > 0);
273  BOOST_REQUIRE(_o.count("gasPrice") > 0);
274  BOOST_REQUIRE(_o.count("gasLimit") > 0);
275  BOOST_REQUIRE(_o.count("to") > 0);
276  BOOST_REQUIRE(_o.count("value") > 0);
277  BOOST_REQUIRE(_o.count("data") > 0);
278 
279  if (bigint(_o.at("nonce").get_str()) >= c_max256plus1)
280  BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'nonce' is equal or greater than 2**256") );
281  if (bigint(_o.at("gasPrice").get_str()) >= c_max256plus1)
282  BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasPrice' is equal or greater than 2**256") );
283  if (bigint(_o.at("gasLimit").get_str()) >= c_max256plus1)
284  BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasLimit' is equal or greater than 2**256") );
285  if (bigint(_o.at("value").get_str()) >= c_max256plus1)
286  BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'value' is equal or greater than 2**256") );
287 
288  o_tr = _o.at("to").get_str().empty() ?
289  Transaction(toInt(_o.at("value")), toInt(_o.at("gasPrice")), toInt(_o.at("gasLimit")), importData(_o), toInt(_o.at("nonce")), Secret(_o.at("secretKey").get_str())) :
290  Transaction(toInt(_o.at("value")), toInt(_o.at("gasPrice")), toInt(_o.at("gasLimit")), Address(_o.at("to").get_str()), importData(_o), toInt(_o.at("nonce")), Secret(_o.at("secretKey").get_str()));
291  }
292  else
293  {
294  BOOST_REQUIRE(_o.count("nonce"));
295  BOOST_REQUIRE(_o.count("gasPrice"));
296  BOOST_REQUIRE(_o.count("gasLimit"));
297  BOOST_REQUIRE(_o.count("to"));
298  BOOST_REQUIRE(_o.count("value"));
299  BOOST_REQUIRE(_o.count("data"));
300  BOOST_REQUIRE(_o.count("v"));
301  BOOST_REQUIRE(_o.count("r"));
302  BOOST_REQUIRE(_o.count("s"));
303 
304  RLPStream transactionRLPStream = createRLPStreamFromTransactionFields(_o);
305  RLP transactionRLP(transactionRLPStream.out());
306  try
307  {
308  o_tr = Transaction(transactionRLP.data(), CheckTransaction::Everything);
309  }
310  catch (InvalidSignature)
311  {
312  // create unsigned transaction
313  o_tr = _o.at("to").get_str().empty() ?
314  Transaction(toInt(_o.at("value")), toInt(_o.at("gasPrice")), toInt(_o.at("gasLimit")), importData(_o), toInt(_o.at("nonce"))) :
315  Transaction(toInt(_o.at("value")), toInt(_o.at("gasPrice")), toInt(_o.at("gasLimit")), Address(_o.at("to").get_str()), importData(_o), toInt(_o.at("nonce")));
316  }
317  catch (Exception& _e)
318  {
319  cnote << "invalid transaction" << boost::diagnostic_information(_e);
320  }
321  }
322 }
323 
325 {
326  if (m_testType == testType::StateTests) //Import a single transaction
328  else if (m_testType == testType::GeneralStateTest) //Parse extended transaction
329  {
330  BOOST_REQUIRE(o_tr.count("gasLimit") > 0);
331  size_t dataVectorSize = o_tr.at("data").get_array().size();
332  size_t gasVectorSize = o_tr.at("gasLimit").get_array().size();
333  size_t valueVectorSize = o_tr.at("value").get_array().size();
334 
335  for (size_t d = 0; d < dataVectorSize; d++)
336  for (size_t g = 0; g < gasVectorSize; g++)
337  for (size_t v = 0; v < valueVectorSize; v++)
338  {
339  json_spirit::mValue gas = o_tr.at("gasLimit").get_array().at(g);
340  json_spirit::mValue value = o_tr.at("value").get_array().at(v);
341  json_spirit::mValue data = o_tr.at("data").get_array().at(d);
342 
343  json_spirit::mObject o_tr_tmp = o_tr;
344  o_tr_tmp["data"] = data;
345  o_tr_tmp["gasLimit"] = gas;
346  o_tr_tmp["value"] = value;
347 
348  importTransaction(o_tr_tmp, m_transaction);
349 
350  transactionToExecute execData(d, g, v, m_transaction);
351  m_transactions.push_back(execData);
352  }
353  }
354 }
355 
356 int ImportTest::compareStates(State const& _stateExpect, State const& _statePost, AccountMaskMap const _expectedStateOptions, WhenError _throw)
357 {
358  bool wasError = false;
359  #define CHECK(a,b) \
360  { \
361  if (_throw == WhenError::Throw) \
362  { \
363  BOOST_CHECK_MESSAGE(a, b); \
364  if (!a) \
365  return 1; \
366  } \
367  else \
368  { \
369  BOOST_WARN_MESSAGE(a,b); \
370  if (!a) \
371  wasError = true; \
372  } \
373  }
374 
375  for (auto const& a: _stateExpect.addresses())
376  {
377  AccountMask addressOptions(true);
378  if(_expectedStateOptions.size())
379  {
380  try
381  {
382  addressOptions = _expectedStateOptions.at(a.first);
383  }
384  catch(std::out_of_range const&)
385  {
386  BOOST_ERROR(TestOutputHelper::testName() + "expectedStateOptions map does not match expectedState in checkExpectedState!");
387  break;
388  }
389  }
390 
391  if (addressOptions.shouldExist())
392  {
393  CHECK(_statePost.addressInUse(a.first), TestOutputHelper::testName() + "Compare States: " << a.first << " missing expected address!");
394  }
395  else
396  {
397  CHECK(!_statePost.addressInUse(a.first), TestOutputHelper::testName() + "Compare States: " << a.first << " address not expected to exist!");
398  }
399 
400  if (_statePost.addressInUse(a.first))
401  {
402 
403  if (addressOptions.hasBalance())
404  CHECK((_stateExpect.balance(a.first) == _statePost.balance(a.first)),
405  TestOutputHelper::testName() + "Check State: " << a.first << ": incorrect balance " << _statePost.balance(a.first) << ", expected " << _stateExpect.balance(a.first));
406 
407  if (addressOptions.hasNonce())
408  CHECK((_stateExpect.getNonce(a.first) == _statePost.getNonce(a.first)),
409  TestOutputHelper::testName() + "Check State: " << a.first << ": incorrect nonce " << _statePost.getNonce(a.first) << ", expected " << _stateExpect.getNonce(a.first));
410 
411  if (addressOptions.hasStorage())
412  {
413  map<h256, pair<u256, u256>> stateStorage = _statePost.storage(a.first);
414  for (auto const& s: _stateExpect.storage(a.first))
415  CHECK((stateStorage[s.first] == s.second),
416  TestOutputHelper::testName() + "Check State: " << a.first << ": incorrect storage [" << toCompactHex(s.second.first, HexPrefix::Add) << "] = " << toCompactHex(stateStorage[s.first].second, HexPrefix::Add) << ", expected [" << toCompactHex(s.second.first, HexPrefix::Add) << "] = " << toCompactHex(s.second.second, HexPrefix::Add));
417 
418  //Check for unexpected storage values
419  map<h256, pair<u256, u256>> expectedStorage = _stateExpect.storage(a.first);
420  for (auto const& s: _statePost.storage(a.first))
421  CHECK((expectedStorage[s.first] == s.second),
422  TestOutputHelper::testName() + "Check State: " << a.first << ": incorrect storage [" << toCompactHex(s.second.first, HexPrefix::Add) << "] = " << toCompactHex(s.second.second, HexPrefix::Add) << ", expected [" << toCompactHex(s.second.first, HexPrefix::Add) << "] = " << toCompactHex(expectedStorage[s.first].second, HexPrefix::Add));
423  }
424 
425  if (addressOptions.hasCode())
426  CHECK((_stateExpect.code(a.first) == _statePost.code(a.first)),
427  TestOutputHelper::testName() + "Check State: " << a.first << ": incorrect code '" << toHex(_statePost.code(a.first)) << "', expected '" << toHex(_stateExpect.code(a.first)) << "'");
428  }
429  }
430 
431  return wasError;
432 }
433 
434 void parseJsonStrValueIntoVector(json_spirit::mValue const& _json, vector<string>& _out)
435 {
436  if (_json.type() == json_spirit::array_type)
437  {
438  for (auto const& val: _json.get_array())
439  _out.push_back(val.get_str());
440  }
441  else
442  _out.push_back(_json.get_str());
443 }
444 
445 void parseJsonIntValueIntoVector(json_spirit::mValue const& _json, vector<int>& _out)
446 {
447  if (_json.type() == json_spirit::array_type)
448  {
449  for (auto const& val: _json.get_array())
450  _out.push_back(val.get_int());
451  }
452  else
453  _out.push_back(_json.get_int());
454 }
455 
456 template<class T>
457 bool inArray(vector<T> const& _array, const T _val)
458 {
459  for (size_t i = 0; i < _array.size(); i++)
460  if (_array[i] == _val)
461  return true;
462  return false;
463 }
464 
465 void ImportTest::checkGeneralTestSection(json_spirit::mObject const& _expects, vector<size_t>& _errorTransactions, string const& _network) const
466 {
467  checkGeneralTestSectionSearch(_expects, _errorTransactions, _network, NULL);
468 }
469 
470 void ImportTest::checkGeneralTestSectionSearch(json_spirit::mObject const& _expects, vector<size_t>& _errorTransactions, string const& _network, TrExpectSection* _search) const
471 {
472  vector<int> d;
473  vector<int> g;
474  vector<int> v;
475  vector<string> network;
476  if (_network.empty())
477  parseJsonStrValueIntoVector(_expects.at("network"), network);
478  else
479  network.push_back(_network);
480 
481  BOOST_CHECK_MESSAGE(network.size() > 0, TestOutputHelper::testName() + "Network array not set!");
484  for(size_t i=0; i<network.size(); i++)
485  BOOST_CHECK_MESSAGE(inArray(allowednetworks, network.at(i)), TestOutputHelper::testName() + "Specified Network not found: " + network.at(i));
486 
487  if (_expects.count("indexes"))
488  {
489  json_spirit::mObject const& indexes = _expects.at("indexes").get_obj();
490  parseJsonIntValueIntoVector(indexes.at("data"), d);
491  parseJsonIntValueIntoVector(indexes.at("gas"), g);
492  parseJsonIntValueIntoVector(indexes.at("value"), v);
493  BOOST_CHECK_MESSAGE(d.size() > 0 && g.size() > 0 && v.size() > 0, TestOutputHelper::testName() + "Indexes arrays not set!");
494  }
495  else
496  BOOST_ERROR(TestOutputHelper::testName() + "indexes section not set!");
497 
498  bool foundResults = false;
499  std::vector<transactionToExecute> lookTransactions;
500  if (_search)
501  lookTransactions.push_back(_search->first);
502  else
503  lookTransactions = m_transactions;
504  for(size_t i = 0; i < lookTransactions.size(); i++)
505  {
506  transactionToExecute t = lookTransactions[i];
507  if (inArray(network, netIdToString(t.netId)) || network[0] == "ALL")
508  if ((inArray(d, t.dataInd) || d[0] == -1) && (inArray(g, t.gasInd) || g[0] == -1) && (inArray(v, t.valInd) || v[0] == -1))
509  {
510  string trInfo = netIdToString(t.netId) + " data: " + toString(t.dataInd) + " gas: " + toString(t.gasInd) + " val: " + toString(t.valInd);
511  if (_expects.count("result"))
512  {
513  Options const& opt = Options::get();
514  //filter transactions if a specific index set in options
515  if ((opt.trDataIndex != -1 && opt.trDataIndex != t.dataInd) ||
516  (opt.trGasIndex != -1 && opt.trGasIndex != t.gasInd) ||
517  (opt.trValueIndex != -1 && opt.trValueIndex != t.valInd))
518  continue;
519 
520  State postState = t.postState;
521  eth::AccountMaskMap stateMap;
522  State expectState(0, OverlayDB(), eth::BaseState::Empty);
523  importState(_expects.at("result").get_obj(), expectState, stateMap);
524  if (_search)
525  {
526  _search->second.first = expectState;
527  _search->second.second = stateMap;
528  return;
529  }
530  int errcode = compareStates(expectState, postState, stateMap, Options::get().checkstate ? WhenError::Throw : WhenError::DontThrow);
531  if (errcode > 0)
532  {
533  cerr << trInfo << std::endl;
534  _errorTransactions.push_back(i);
535  }
536  }
537  else if (_expects.count("hash"))
538  BOOST_CHECK_MESSAGE(_expects.at("hash").get_str() == toHex(t.postState.rootHash().asBytes()), TestOutputHelper::testName() + "Expected another postState hash! " + trInfo);
539  else
540  BOOST_ERROR(TestOutputHelper::testName() + "Expect section or postState missing some fields!");
541 
542  foundResults = true;
543 
544  //if a single transaction check then stop once found
545  if (network[0] != "ALL" && d[0] != -1 && g[0] != -1 && v[0] != -1)
546  if (network.size() == 1 && d.size() == 1 && g.size() == 1 && v.size() == 1)
547  break;
548  }
549  }
550  if (!_search) //search for a single transaction in one of the expect sections then don't need this output.
551  BOOST_CHECK_MESSAGE(foundResults, TestOutputHelper::testName() + "Expect results was not found in test execution!");
552 }
553 
554 int ImportTest::exportTest(bytes const& _output)
555 {
556  int err = 0;
558  {
559  vector<size_t> stateIndexesToPrint;
560  if (m_testObject.count("expect") > 0)
561  {
562  for (auto const& exp: m_testObject["expect"].get_array())
563  checkGeneralTestSection(exp.get_obj(), stateIndexesToPrint);
564  m_testObject.erase(m_testObject.find("expect"));
565  }
566 
567  size_t k = 0;
568  std::map<string, json_spirit::mArray> postState;
569  for(size_t i = 0; i < m_transactions.size(); i++)
570  {
573  obj["data"] = m_transactions[i].dataInd;
574  obj["gas"] = m_transactions[i].gasInd;
575  obj["value"] = m_transactions[i].valInd;
576  obj2["indexes"] = obj;
577  obj2["hash"] = toHex(m_transactions[i].postState.rootHash().asBytes());
578  if (stateIndexesToPrint.size())
579  if (i == stateIndexesToPrint[k] && Options::get().checkstate)
580  {
581  obj2["postState"] = fillJsonWithState(m_transactions[i].postState);
582  k++;
583  }
584  postState[netIdToString(m_transactions[i].netId)].push_back(obj2);
585  }
586 
588  for(std::map<string, json_spirit::mArray>::iterator it = postState.begin(); it != postState.end(); ++it)
589  obj[it->first] = it->second;
590 
591  m_testObject["post"] = obj;
592  }
593  else
594  {
595 
596  // export output
597  m_testObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add);
598 
599  // compare expected output with post output
600  if (m_testObject.count("expectOut") > 0)
601  {
602  std::string warning = "Check State: Error! Unexpected output: " + m_testObject["out"].get_str() + " Expected: " + m_testObject["expectOut"].get_str();
603  if (Options::get().checkstate)
604  {
605  bool statement = (m_testObject["out"].get_str() == m_testObject["expectOut"].get_str());
606  BOOST_CHECK_MESSAGE(statement, warning);
607  if (!statement)
608  err = 1;
609  }
610  else
611  BOOST_WARN_MESSAGE(m_testObject["out"].get_str() == m_testObject["expectOut"].get_str(), warning);
612 
613  m_testObject.erase(m_testObject.find("expectOut"));
614  }
615 
616  // export logs
617  m_testObject["logs"] = exportLog(m_logs);
618 
619  // compare expected state with post state
620  if (m_testObject.count("expect") > 0)
621  {
622  eth::AccountMaskMap stateMap;
623  State expectState(0, OverlayDB(), eth::BaseState::Empty);
624  importState(m_testObject["expect"].get_obj(), expectState, stateMap);
625  compareStates(expectState, m_statePost, stateMap, Options::get().checkstate ? WhenError::Throw : WhenError::DontThrow);
626  m_testObject.erase(m_testObject.find("expect"));
627  }
628 
629  // export post state
631  m_testObject["postStateRoot"] = toHex(m_statePost.rootHash().asBytes());
632  }
633 
634  // export pre state
636  m_testObject["env"] = makeAllFieldsHex(m_testObject["env"].get_obj());
637  m_testObject["transaction"] = makeAllFieldsHex(m_testObject["transaction"].get_obj());
638  return err;
639 }
bool addressInUse(Address const &_address) const
Check if the address is in use.
Definition: State.cpp:245
u256 balance(Address const &_id) const
Get an account&#39;s balance.
Definition: State.cpp:266
std::string toCompactHex(u256 val, HexPrefix prefix=HexPrefix::DontAdd, unsigned _min=0)
Definition: CommonData.h:175
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
std::string toHex(T const &_data, int _w=2, HexPrefix _prefix=HexPrefix::DontAdd)
Definition: CommonData.h:54
Helper class for managing data when running state tests.
string netIdToString(eth::Network _netId)
Definition: TestHelper.cpp:93
bytes importData(json_spirit::mObject const &_o)
Definition: TestHelper.cpp:226
void commit(CommitBehaviour _commitBehaviour)
Commit all changes waiting in the address cache to the DB.
Definition: State.cpp:210
u256 const & timestamp() const
Definition: ExtVMFace.h:239
Homestead + EIP150 Rules active from block 0 For BlockchainTests.
static Options const & get(int argc=0, char **argv=0)
Get reference to options The first time used, options are parsed with argc, argv. ...
Definition: Options.cpp:203
Fixture class for boost output when running testeth.
Network
The network id.
Definition: GenesisInfo.h:34
void writeFile(std::string const &_file, bytesConstRef _data, bool _writeDeleteRename=false)
Write the given binary data into the given file, replacing the file if it pre-exists.
Definition: CommonIO.cpp:107
#define T(i, x)
std::pair< transactionToExecute, StateAndMap > TrExpectSection
Definition: ImportTest.h:84
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<>> bigint
Definition: Common.h:121
int64_t gasLimit() const
Definition: ExtVMFace.h:241
bool hasBalance() const
Definition: Account.h:225
static std::string const & testName()
h160 Address
An Ethereum address: 20 bytes.
Definition: Common.h:62
#define g(i)
Definition: sha.cpp:735
Address const & author() const
Definition: ExtVMFace.h:238
SecureFixedHash< 32 > Secret
Definition: Common.h:35
std::pair< eth::ExecutionResult, eth::TransactionReceipt > execOutput
Definition: ImportTest.h:64
int trValueIndex
GeneralState value.
Definition: Options.h:61
std::hash for asio::adress
Definition: Common.h:323
void setGasLimit(int64_t _v)
Definition: ExtVMFace.h:249
std::string toString(string32 const &_s)
Make normal string from fixed-length string.
Definition: CommonData.cpp:141
WhenError
Definition: CommonData.h:39
ImportTest(json_spirit::mObject &_o, bool isFiller, testType testTemplate=testType::StateTests)
Definition: ImportTest.cpp:31
Description of the result of executing a transaction.
Definition: Transaction.h:69
u256 const & number() const
Definition: ExtVMFace.h:237
Model of an Ethereum state, essentially a facade for the trie.
Definition: State.h:161
void populateFrom(AccountMap const &_map)
Populate the state from the given AccountMap. Just uses dev::eth::commit().
Definition: State.cpp:115
Homestead + EIP150 + EIP158 Rules active from block 0.
static std::string const & caseName()
Class for handling testeth custom options.
void checkGeneralTestSection(json_spirit::mObject const &_expects, std::vector< size_t > &_errorTransactions, std::string const &_network="") const
Definition: ImportTest.cpp:465
const Array & get_array() const
json_spirit::mObject fillJsonWithTransaction(Transaction const &_txn)
Definition: TestHelper.cpp:124
static int compareStates(eth::State const &_stateExpect, eth::State const &_statePost, eth::AccountMaskMap const _expectedStateOptions=eth::AccountMaskMap(), WhenError _throw=WhenError::Throw)
Definition: ImportTest.cpp:356
#define a(i)
bool hasCode() const
Definition: Account.h:227
eth::EnvInfo m_envInfo
Definition: ImportTest.h:67
Value_type type() const
#define CHECK(a, b)
static void importState(json_spirit::mObject const &_o, eth::State &_state)
Base class for all exceptions.
Definition: Exceptions.h:39
mConfig::Array_type mArray
std::pair< ExecutionResult, TransactionReceipt > execute(EnvInfo const &_envInfo, SealEngineFace const &_sealEngine, Transaction const &_t, Permanence _p=Permanence::Committed, OnOpFunc const &_onOp=OnOpFunc())
Execute a given transaction.
Definition: State.cpp:515
void parseJsonIntValueIntoVector(json_spirit::mValue const &_json, vector< int > &_out)
Definition: ImportTest.cpp:445
BaseState
Definition: State.h:76
RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject const &_tObj)
Definition: TestHelper.cpp:499
ExecStats::duration max
Definition: ExecStats.cpp:36
eth::Transaction m_transaction
Definition: ImportTest.h:68
json_spirit::mArray exportLog(eth::LogEntries _logs)
Definition: TestHelper.cpp:176
void setLastHashes(LastHashes &&_lh)
Definition: ExtVMFace.h:250
void setTimestamp(u256 const &_v)
Definition: ExtVMFace.h:247
std::vector< byte > bytes
Definition: Common.h:75
std::string getTestPath()
Definition: Common.cpp:35
Just test the Homestead-era characteristics "forever" (no Frontier portion).
json_spirit::mObject & m_testObject
Definition: ImportTest.h:87
u256 storage(Address const &_contract, u256 const &_memory) const
Get the value of a storage position of an account.
Definition: State.cpp:353
u256 getNonce(Address const &_addr) const
Get the account nonce – the number of transactions it has sent.
Definition: State.cpp:345
u256 const & difficulty() const
Definition: ExtVMFace.h:240
std::unordered_map< Address, u256 > addresses() const
Definition: State.cpp:220
bytes asBytes(std::string const &_b)
Converts a string to a byte array containing the string&#39;s (byte) data.
Definition: CommonData.h:92
std::pair< eth::State, eth::AccountMaskMap > StateAndMap
Definition: ImportTest.h:83
void setNumber(u256 const &_v)
Definition: ExtVMFace.h:245
bytes const & code(Address const &_addr) const
Get the code of an account.
Definition: State.cpp:423
FixedHash< 32 > h256
Definition: FixedHash.h:340
json_spirit::mObject fillJsonWithState(State const &_state)
Definition: TestHelper.cpp:139
const String_type & get_str() const
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
Definition: Common.h:125
bool checkstate
Throw error when checking test states.
Definition: Options.h:48
Just test the Frontier-era characteristics "forever" (no Homestead portion).
Encodes a transaction, ready to be exported to or freshly imported from RLP.
Definition: Transaction.h:84
std::unordered_map< Address, AccountMask > AccountMaskMap
Definition: Account.h:240
int trGasIndex
GeneralState gas.
Definition: Options.h:60
mConfig::Object_type mObject
h256 rootHash() const
The hash of the root of our state tree.
Definition: State.h:288
bytes asBytes() const
Definition: FixedHash.h:145
void replaceLLLinState(json_spirit::mObject &_o)
Definition: TestHelper.cpp:237
std::string const & genesisInfo(Network _n)
Definition: GenesisInfo.cpp:37
Value_type::String_type write_string(const Value_type &value, bool pretty)
int trDataIndex
GeneralState data.
Definition: Options.h:59
static json_spirit::mObject defaultGenesisBlockJson()
#define cnote
Definition: Log.h:303
void importEnv(json_spirit::mObject &_o)
Definition: ImportTest.cpp:231
void parseJsonStrValueIntoVector(json_spirit::mValue const &_json, vector< string > &_out)
Definition: ImportTest.cpp:434
eth::State m_statePre
Definition: ImportTest.h:58
LastHashes lastHashes(u256 _currentBlockNumber)
Definition: TestHelper.cpp:544
AccountMap jsonToAccountMap(std::string const &_json, u256 const &_defaultNonce=0, AccountMaskMap *o_mask=nullptr, PrecompiledContractMap *o_precompiled=nullptr)
Definition: Account.cpp:50
std::vector< transactionToExecute > m_transactions
Definition: ImportTest.h:82
boost::error_info< struct tag_comment, std::string > errinfo_comment
Definition: Assertions.h:78
bool hasStorage() const
Definition: Account.h:228
int exportTest(bytes const &_output)
Definition: ImportTest.cpp:554
An Empty class.
Definition: misc.h:184
void setAuthor(Address const &_v)
Definition: ExtVMFace.h:246
All fork rules + Metropolis active from block 0.
bool inArray(vector< T > const &_array, const T _val)
Definition: ImportTest.cpp:457
void doBlockchainTests(json_spirit::mValue &_v, bool _fillin)
void executeTests(const string &_name, const string &_testPathAppendix, const string &_fillerPathAppendix, std::function< void(json_spirit::mValue &, bool)> doTests, bool _addFillerSuffix)
Definition: TestHelper.cpp:434
eth::State m_statePost
Definition: ImportTest.h:59
#define d(i)
Definition: sha.cpp:732
eth::LogEntries m_logsExpected
Definition: ImportTest.h:61
void setDifficulty(u256 const &_v)
Definition: ExtVMFace.h:248
eth::LogEntries m_logs
Definition: ImportTest.h:60
std::string get_str(std::string::const_iterator begin, std::string::const_iterator end)
static void importTransaction(json_spirit::mObject const &_o, eth::Transaction &o_tr)
Class for writing to an RLP bytestream.
Definition: RLP.h:383
eth::Network stringToNetId(string const &_netname)
Definition: TestHelper.cpp:107
bool fulloutput
Replace large output to just it&#39;s length.
Definition: Options.h:49
uint8_t const * data
Definition: sha3.h:19
bool shouldExist() const
Definition: Account.h:229
Class for interpreting Recursive Linear-Prefix Data.
Definition: RLP.h:64
static json_spirit::mObject & makeAllFieldsHex(json_spirit::mObject &_o)
Definition: ImportTest.cpp:205
LogEntries importLog(json_spirit::mArray &_a)
Definition: TestHelper.cpp:298
void checkGeneralTestSectionSearch(json_spirit::mObject const &_expects, std::vector< size_t > &_errorTransactions, std::string const &_network="", TrExpectSection *_search=NULL) const
Definition: ImportTest.cpp:470
Normal Frontier/Homestead/DAO/EIP150/EIP158/Metropolis chain.
u256 toInt(json_spirit::mValue const &_v)
Definition: TestHelper.cpp:195
bigint const c_max256plus1
Definition: TestHelper.h:61
std::vector< LogEntry > LogEntries
Definition: ExtVMFace.h:110
Helper functions to work with json::spirit and test files.
bool hasNonce() const
Definition: Account.h:226
std::pair< eth::State, execOutput > executeTransaction(eth::Network const _sealEngineNetwork, eth::EnvInfo const &_env, eth::State const &_preState, eth::Transaction const &_tr)
Definition: ImportTest.cpp:178