1 // Aleth: Ethereum C++ client, tools and libraries.
2 // Copyright 2017-2019 Aleth Authors.
3 // Licensed under the GNU General Public License, Version 3.
4
5 /// @file
6 /// Helper functions to work with json::spirit and test files
7 #include "TestHelper.h"
8 #include "Options.h"
9 #include "TestOutputHelper.h"
10 #include "wast2wasm.h"
11
12 #include <libdevcore/JsonUtils.h>
13 #include <libethashseal/EthashCPUMiner.h>
14 #include <libethereum/Client.h>
15
16 #include <aleth/buildinfo.h>
17
18 #include <yaml-cpp/yaml.h>
19 #include <boost/algorithm/string/trim.hpp>
20 #include <boost/filesystem/path.hpp>
21 #include <set>
22 #include <string>
23
24 using namespace std;
25 using namespace dev::eth;
26 namespace fs = boost::filesystem;
27
28 namespace dev
29 {
30 namespace eth
31 {
mine(Client & _c,int _numBlocks)32 void mine(Client& _c, int _numBlocks)
33 {
34 int sealedBlocks = 0;
35 auto sealHandler = _c.setOnBlockSealed([_numBlocks, &sealedBlocks, &_c](bytes const&) {
36 if (++sealedBlocks == _numBlocks)
37 _c.stopSealing();
38 });
39
40 int importedBlocks = 0;
41 std::promise<void> allBlocksImported;
42 auto chainChangedHandler = _c.setOnChainChanged(
43 [_numBlocks, &importedBlocks, &allBlocksImported](h256s const&, h256s const& _newBlocks) {
44 importedBlocks += _newBlocks.size();
45 if (importedBlocks == _numBlocks)
46 allBlocksImported.set_value();
47 });
48
49 _c.startSealing();
50 allBlocksImported.get_future().wait();
51 }
52
mine(Block & s,BlockChain const & _bc,SealEngineFace * _sealer)53 void mine(Block& s, BlockChain const& _bc, SealEngineFace* _sealer)
54 {
55 EthashCPUMiner::setNumInstances(1);
56 s.commitToSeal(_bc, s.info().extraData());
57 Notified<bytes> sealed;
58 _sealer->onSealGenerated([&](bytes const& sealedHeader) { sealed = sealedHeader; });
59 _sealer->generateSeal(s.info());
60 sealed.waitNot({});
61 _sealer->onSealGenerated([](bytes const&) {});
62 s.sealBlock(sealed);
63 }
64
mine(BlockHeader & _bi,SealEngineFace * _sealer,bool _verify)65 void mine(BlockHeader& _bi, SealEngineFace* _sealer, bool _verify)
66 {
67 Notified<bytes> sealed;
68 _sealer->onSealGenerated([&](bytes const& sealedHeader) { sealed = sealedHeader; });
69 _sealer->generateSeal(_bi);
70 sealed.waitNot({});
71 _sealer->onSealGenerated([](bytes const&) {});
72 _bi = BlockHeader(sealed, HeaderData);
73 // cdebug << "Block mined" << Ethash::boundary(_bi).hex() <<
74 // Ethash::nonce(_bi) << _bi.hash(WithoutSeal).hex();
75 if (_verify) // sometimes it is needed to mine incorrect blockheaders for
76 // testing
77 _sealer->verify(CheckNothingNew, _bi);
78 }
79
80 }
81
82 namespace test
83 {
84
netIdToString(eth::Network _netId)85 string netIdToString(eth::Network _netId)
86 {
87 switch (_netId)
88 {
89 case eth::Network::FrontierTest:
90 return "Frontier";
91 case eth::Network::HomesteadTest:
92 return "Homestead";
93 case eth::Network::EIP150Test:
94 return "EIP150";
95 case eth::Network::EIP158Test:
96 return "EIP158";
97 case eth::Network::ByzantiumTest:
98 return "Byzantium";
99 case eth::Network::ConstantinopleTest:
100 return "Constantinople";
101 case eth::Network::ConstantinopleFixTest:
102 return "ConstantinopleFix";
103 case eth::Network::IstanbulTest:
104 return "Istanbul";
105 case eth::Network::FrontierToHomesteadAt5:
106 return "FrontierToHomesteadAt5";
107 case eth::Network::HomesteadToDaoAt5:
108 return "HomesteadToDaoAt5";
109 case eth::Network::HomesteadToEIP150At5:
110 return "HomesteadToEIP150At5";
111 case eth::Network::EIP158ToByzantiumAt5:
112 return "EIP158ToByzantiumAt5";
113 case eth::Network::ByzantiumToConstantinopleFixAt5:
114 return "ByzantiumToConstantinopleFixAt5";
115 case eth::Network::TransitionnetTest:
116 return "TransitionNet";
117 default:
118 return "other";
119 }
120 return "unknown";
121 }
122
stringToNetId(string const & _netname)123 eth::Network stringToNetId(string const& _netname)
124 {
125 // Networks that used in .json tests
126 static vector<eth::Network> const networks{
127 {eth::Network::FrontierTest, eth::Network::HomesteadTest, eth::Network::EIP150Test,
128 eth::Network::EIP158Test, eth::Network::ByzantiumTest, eth::Network::ConstantinopleTest,
129 eth::Network::ConstantinopleFixTest, eth::Network::IstanbulTest,
130 eth::Network::FrontierToHomesteadAt5, eth::Network::HomesteadToDaoAt5,
131 eth::Network::HomesteadToEIP150At5, eth::Network::EIP158ToByzantiumAt5,
132 eth::Network::ByzantiumToConstantinopleFixAt5, eth::Network::TransitionnetTest}};
133
134 for (auto const& net : networks)
135 if (netIdToString(net) == _netname)
136 return net;
137
138 BOOST_ERROR(TestOutputHelper::get().testName() + " network not found: " + _netname);
139 return eth::Network::FrontierTest;
140 }
141
getNetworks()142 set<eth::Network> const& getNetworks()
143 {
144 // Networks for the test case execution when filling the tests
145 static set<eth::Network> const networks{
146 {eth::Network::FrontierTest, eth::Network::HomesteadTest, eth::Network::EIP150Test,
147 eth::Network::EIP158Test, eth::Network::ByzantiumTest, eth::Network::ConstantinopleTest,
148 eth::Network::ConstantinopleFixTest, eth::Network::IstanbulTest}};
149 return networks;
150 }
151
152 /// translate network names in expect section field
153 /// >Homestead to EIP150, EIP158, Byzantium, ...
154 /// <=Homestead to Frontier, Homestead
translateNetworks(set<string> const & _networks)155 set<string> translateNetworks(set<string> const& _networks)
156 {
157 // construct vector with test network names in a right order (from Frontier to Homestead ... to
158 // Constantinople)
159 vector<string> forks;
160 for (auto const& net : getNetworks())
161 forks.push_back(test::netIdToString(net));
162
163 set<string> out;
164 for (auto const& net : _networks)
165 {
166 bool isNetworkTranslated = false;
167 string possibleNet = net.substr(1, net.length() - 1);
168 vector<string>::iterator it = std::find(forks.begin(), forks.end(), possibleNet);
169
170 if (it != forks.end() && net.size() > 1)
171 {
172 if (net[0] == '>')
173 {
174 while (++it != forks.end())
175 {
176 out.emplace(*it);
177 isNetworkTranslated = true;
178 }
179 }
180 else if (net[0] == '<')
181 {
182 while (it != forks.begin())
183 {
184 out.emplace(*(--it));
185 isNetworkTranslated = true;
186 }
187 }
188 }
189
190 possibleNet = net.substr(2, net.length() - 2);
191 it = std::find(forks.begin(), forks.end(), possibleNet);
192 if (it != forks.end() && net.size() > 2)
193 {
194 if (net[0] == '>' && net[1] == '=')
195 {
196 while (it != forks.end())
197 {
198 out.emplace(*(it++));
199 isNetworkTranslated = true;
200 }
201 }
202 else if (net[0] == '<' && net[1] == '=')
203 {
204 out.emplace(*it);
205 isNetworkTranslated = true;
206 while (it != forks.begin())
207 out.emplace(*(--it));
208 }
209 }
210
211 // if nothing has been inserted, just push the untranslated network as is
212 if (!isNetworkTranslated)
213 {
214 ImportTest::checkAllowedNetwork(net);
215 out.emplace(net);
216 }
217 }
218 return out;
219 }
220
exportLog(eth::LogEntries const & _logs)221 string exportLog(eth::LogEntries const& _logs)
222 {
223 RLPStream s;
224 s.appendList(_logs.size());
225 for (LogEntry const& l : _logs)
226 l.streamRLP(s);
227 return toHexPrefixed(sha3(s.out()));
228 }
229
toU256(json_spirit::mValue const & _v)230 u256 toU256(json_spirit::mValue const& _v)
231 {
232 switch (_v.type())
233 {
234 case json_spirit::str_type:
235 return u256(_v.get_str());
236 case json_spirit::int_type:
237 return (u256)_v.get_uint64();
238 case json_spirit::bool_type:
239 return (u256)(uint64_t)_v.get_bool();
240 case json_spirit::real_type:
241 return (u256)(uint64_t)_v.get_real();
242 default:
243 cwarn << "Bad type for scalar: " << _v.type();
244 }
245 return 0;
246 }
247
toInt64(json_spirit::mValue const & _v)248 int64_t toInt64(json_spirit::mValue const& _v)
249 {
250 int64_t n = 0;
251 switch (_v.type())
252 {
253 case json_spirit::str_type:
254 n = std::stoll(_v.get_str(), nullptr, 0);
255 break;
256 case json_spirit::int_type:
257 n = _v.get_int64();
258 break;
259 default:
260 cwarn << "Bad type for scalar: " << _v.type();
261 }
262 return n;
263 }
264
toUint64(json_spirit::mValue const & _v)265 uint64_t toUint64(json_spirit::mValue const& _v)
266 {
267 uint64_t n = 0;
268 switch (_v.type())
269 {
270 case json_spirit::str_type:
271 {
272 long long readval = std::stoll(_v.get_str(), nullptr, 0);
273 if (readval < 0)
274 BOOST_THROW_EXCEPTION(UnexpectedNegative() << errinfo_comment(
275 "TestOutputHelper::toUint64: unexpected negative value: " +
276 std::to_string(readval)));
277 n = readval;
278 }
279 break;
280 case json_spirit::int_type:
281 n = _v.get_uint64();
282 break;
283 default:
284 cwarn << "Bad type for scalar: " << _v.type();
285 }
286 return n;
287 }
288
toByte(json_spirit::mValue const & _v)289 byte toByte(json_spirit::mValue const& _v)
290 {
291 switch (_v.type())
292 {
293 case json_spirit::str_type:
294 return (byte)stoi(_v.get_str());
295 case json_spirit::int_type:
296 return (byte)_v.get_uint64();
297 case json_spirit::bool_type:
298 return (byte)_v.get_bool();
299 case json_spirit::real_type:
300 return (byte)_v.get_real();
301 default:
302 cwarn << "Bad type for scalar: " << _v.type();
303 }
304 return 0;
305 }
306
importByteArray(string const & _str)307 bytes importByteArray(string const& _str)
308 {
309 checkHexHasEvenLength(_str);
310 return fromHex(_str.substr(0, 2) == "0x" ? _str.substr(2) : _str, WhenError::Throw);
311 }
312
processDataOrCode(json_spirit::mObject const & _o,string const & nodeName)313 bytes processDataOrCode(json_spirit::mObject const& _o, string const& nodeName)
314 {
315 bytes ret;
316 if (_o.count(nodeName) == 0)
317 return bytes();
318 if (_o.at(nodeName).type() == json_spirit::str_type)
319 if (_o.at(nodeName).get_str().find("0x") != 0)
320 ret = fromHex(replaceCode(_o.at(nodeName).get_str()));
321 else
322 ret = importByteArray(_o.at(nodeName).get_str());
323 else if (_o.at(nodeName).type() == json_spirit::array_type)
324 {
325 for (auto const& j : _o.at(nodeName).get_array())
326 ret.push_back(toByte(j));
327 }
328 return ret;
329 }
330
importData(json_spirit::mObject const & _o)331 bytes importData(json_spirit::mObject const& _o)
332 {
333 return processDataOrCode(_o, "data");
334 }
335
replaceCode(string const & _code)336 string replaceCode(string const& _code)
337 {
338 if (_code == "")
339 return "0x";
340 if (_code.substr(0, 2) == "0x" && _code.size() >= 2)
341 {
342 checkHexHasEvenLength(_code);
343 return _code;
344 }
345 if (_code.find("(module") == 0)
346 return wast2wasm(_code);
347
348 string compiledCode = compileLLL(_code);
349 if (_code.size() > 0)
350 BOOST_REQUIRE_MESSAGE(compiledCode.size() > 0,
351 "Bytecode is missing! '" + _code + "' " + TestOutputHelper::get().testName());
352 return compiledCode;
353 }
354
replaceCodeInState(json_spirit::mObject & _o)355 void replaceCodeInState(json_spirit::mObject& _o)
356 {
357 json_spirit::mObject& fieldsObj = _o.count("alloc") ?
358 _o["alloc"].get_obj() :
359 _o.count("accounts") ? _o["accounts"].get_obj() : _o;
360 for (auto& account : fieldsObj)
361 {
362 auto obj = account.second.get_obj();
363 if (obj.count("code") && obj["code"].type() == json_spirit::str_type)
364 obj["code"] = replaceCode(obj["code"].get_str());
365 account.second = obj;
366 }
367 }
368
getFiles(fs::path const & _dirPath,set<string> const _extentionMask,string const & _particularFile)369 vector<fs::path> getFiles(
370 fs::path const& _dirPath, set<string> const _extentionMask, string const& _particularFile)
371 {
372 vector<fs::path> files;
373 for (auto const& ext : _extentionMask)
374 {
375 if (!_particularFile.empty())
376 {
377 fs::path file = _dirPath / (_particularFile + ext);
378 if (fs::exists(file))
379 files.push_back(file);
380 }
381 else
382 {
383 using fsIterator = fs::directory_iterator;
384 for (fsIterator it(_dirPath); it != fsIterator(); ++it)
385 {
386 if (fs::is_regular_file(it->path()) && it->path().extension() == ext)
387 files.push_back(it->path());
388 }
389 }
390 }
391 return files;
392 }
393
convertYamlNodeToJson(YAML::Node _node)394 json_spirit::mValue convertYamlNodeToJson(YAML::Node _node)
395 {
396 if (_node.IsNull())
397 return json_spirit::mValue();
398
399 if (_node.IsScalar())
400 {
401 if (_node.Tag() == "tag:yaml.org,2002:int")
402 return _node.as<int>();
403 else
404 return _node.as<string>();
405 }
406
407 if (_node.IsMap())
408 {
409 json_spirit::mObject jObject;
410 for (auto const& i : _node)
411 jObject.emplace(i.first.as<string>(), convertYamlNodeToJson(i.second));
412 return jObject;
413 }
414
415 if (_node.IsSequence())
416 {
417 json_spirit::mArray jArray;
418 for (size_t i = 0; i < _node.size(); i++)
419 jArray.emplace_back(convertYamlNodeToJson(_node[i]));
420 return jArray;
421 }
422
423 BOOST_ERROR("Error parsing YAML node. Element type not defined!");
424 return json_spirit::mValue();
425 }
426
427 /// this function is here so not to include <YAML.h> in other .cpp files
parseYamlToJson(string const & _string)428 json_spirit::mValue parseYamlToJson(string const& _string)
429 {
430 YAML::Node testFile = YAML::Load(_string);
431 return convertYamlNodeToJson(testFile);
432 }
433
executeCmd(string const & _command)434 string executeCmd(string const& _command)
435 {
436 #if defined(_WIN32)
437 BOOST_ERROR("executeCmd() has not been implemented for Windows.");
438 return "";
439 #else
440 string out;
441 char output[1024];
442 FILE* fp = popen(_command.c_str(), "r");
443 if (fp == NULL)
444 BOOST_ERROR("Failed to run " + _command);
445 if (fgets(output, sizeof(output) - 1, fp) == NULL)
446 BOOST_ERROR("Reading empty result for " + _command);
447 else
448 {
449 while (true)
450 {
451 out += string(output);
452 if (fgets(output, sizeof(output) - 1, fp) == NULL)
453 break;
454 }
455 }
456
457 int exitCode = pclose(fp);
458 if (exitCode != 0)
459 BOOST_ERROR("The command '" + _command + "' exited with " + toString(exitCode) + " code.");
460 return boost::trim_copy(out);
461 #endif
462 }
463
compileLLL(string const & _code)464 string compileLLL(string const& _code)
465 {
466 #if defined(_WIN32)
467 BOOST_ERROR("LLL compilation only supported on posix systems.");
468 return "";
469 #else
470 fs::path path(fs::temp_directory_path() / fs::unique_path());
471 writeFile(path.string(), _code);
472 // NOTE: this will abort if execution failed
473 string result = executeCmd(string("lllc ") + path.string());
474 fs::remove(path);
475 result = "0x" + result;
476 checkHexHasEvenLength(result);
477 return result;
478 #endif
479 }
480
checkHexHasEvenLength(string const & _str)481 void checkHexHasEvenLength(string const& _str)
482 {
483 if (_str.size() % 2)
484 BOOST_ERROR(TestOutputHelper::get().testName() +
485 " An odd-length hex string represents a byte sequence: " + _str);
486 }
487
importCode(json_spirit::mObject const & _o)488 bytes importCode(json_spirit::mObject const& _o)
489 {
490 return processDataOrCode(_o, "code");
491 }
492
importLog(json_spirit::mArray const & _a)493 LogEntries importLog(json_spirit::mArray const& _a)
494 {
495 LogEntries logEntries;
496 for (auto const& l : _a)
497 {
498 json_spirit::mObject o = l.get_obj();
499 BOOST_REQUIRE(o.count("address") > 0);
500 BOOST_REQUIRE(o.count("topics") > 0);
501 BOOST_REQUIRE(o.count("data") > 0);
502 BOOST_REQUIRE(o.count("bloom") > 0);
503 LogEntry log;
504 log.address = Address(o.at("address").get_str());
505 for (auto const& t : o.at("topics").get_array())
506 log.topics.push_back(h256(t.get_str()));
507 log.data = importData(o);
508 logEntries.push_back(log);
509 }
510 return logEntries;
511 }
512
checkOutput(bytesConstRef _output,json_spirit::mObject const & _o)513 void checkOutput(bytesConstRef _output, json_spirit::mObject const& _o)
514 {
515 int j = 0;
516 auto expectedOutput = _o.at("out").get_str();
517
518 if (expectedOutput.find("#") == 0)
519 BOOST_CHECK(_output.size() == toU256(expectedOutput.substr(1)));
520 else if (_o.at("out").type() == json_spirit::array_type)
521 for (auto const& d : _o.at("out").get_array())
522 {
523 BOOST_CHECK_MESSAGE(_output[j] == toU256(d), "Output byte [" << j << "] different!");
524 ++j;
525 }
526 else if (expectedOutput.find("0x") == 0)
527 BOOST_CHECK(_output.contentsEqual(fromHex(expectedOutput.substr(2))));
528 else
529 BOOST_CHECK(_output.contentsEqual(fromHex(expectedOutput)));
530 }
531
checkStorage(map<u256,u256> const & _expectedStore,map<u256,u256> const & _resultStore,Address const & _expectedAddr)532 void checkStorage(map<u256, u256> const& _expectedStore, map<u256, u256> const& _resultStore,
533 Address const& _expectedAddr)
534 {
535 for (auto&& expectedStorePair : _expectedStore)
536 {
537 auto& expectedStoreKey = expectedStorePair.first;
538 auto resultStoreIt = _resultStore.find(expectedStoreKey);
539 if (resultStoreIt == _resultStore.end())
540 BOOST_ERROR(_expectedAddr << ": missing store key " << expectedStoreKey);
541 else
542 {
543 auto& expectedStoreValue = expectedStorePair.second;
544 auto& resultStoreValue = resultStoreIt->second;
545 BOOST_CHECK_MESSAGE(expectedStoreValue == resultStoreValue,
546 _expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue
547 << ", expected " << expectedStoreValue);
548 }
549 }
550 BOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size());
551 for (auto&& resultStorePair : _resultStore)
552 {
553 if (!_expectedStore.count(resultStorePair.first))
554 BOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first);
555 }
556 }
557
checkCallCreates(eth::Transactions const & _resultCallCreates,eth::Transactions const & _expectedCallCreates)558 void checkCallCreates(
559 eth::Transactions const& _resultCallCreates, eth::Transactions const& _expectedCallCreates)
560 {
561 BOOST_REQUIRE_EQUAL(_resultCallCreates.size(), _expectedCallCreates.size());
562
563 for (size_t i = 0; i < _resultCallCreates.size(); ++i)
564 {
565 BOOST_CHECK(_resultCallCreates[i].data() == _expectedCallCreates[i].data());
566 BOOST_CHECK(
567 _resultCallCreates[i].receiveAddress() == _expectedCallCreates[i].receiveAddress());
568 BOOST_CHECK(_resultCallCreates[i].gas() == _expectedCallCreates[i].gas());
569 BOOST_CHECK(_resultCallCreates[i].value() == _expectedCallCreates[i].value());
570 }
571 }
572
requireJsonFields(json_spirit::mObject const & _o,string const & _section,map<string,json_spirit::Value_type> const & _validationMap)573 void requireJsonFields(json_spirit::mObject const& _o, string const& _section,
574 map<string, json_spirit::Value_type> const& _validationMap)
575 {
576 // check for unexpected fiedls
577 for (auto const field : _o)
578 BOOST_CHECK_MESSAGE(_validationMap.count(field.first),
579 field.first + " should not be declared in " + _section + " section!");
580
581 // check field types with validation map
582 for (auto const vmap : _validationMap)
583 {
584 BOOST_REQUIRE_MESSAGE(
585 _o.count(vmap.first) > 0, vmap.first + " not found in " + _section + " section!");
586 BOOST_REQUIRE_MESSAGE(_o.at(vmap.first).type() == vmap.second,
587 _section + " " + vmap.first + " expected to be " + jsonTypeAsString(vmap.second) +
588 ", but set to " + jsonTypeAsString(_o.at(vmap.first).type()));
589 }
590 }
591
prepareVersionString()592 string prepareVersionString()
593 {
594 return string{"testeth "} + aleth_get_buildinfo()->project_version;
595 }
596
prepareLLLCVersionString()597 string prepareLLLCVersionString()
598 {
599 string result = test::executeCmd("lllc --version");
600 string::size_type pos = result.rfind("Version");
601 if (pos != string::npos)
602 return result.substr(pos, result.length());
603 return "Error getting LLLC Version";
604 }
605
606 // A simple C++ implementation of the Levenshtein distance algorithm to measure the amount of
607 // difference between two strings. https://gist.github.com/TheRayTracer/2644387
levenshteinDistance(char const * _s,size_t _n,char const * _t,size_t _m)608 size_t levenshteinDistance(char const* _s, size_t _n, char const* _t, size_t _m)
609 {
610 ++_n;
611 ++_m;
612 size_t* d = new size_t[_n * _m];
613
614 memset(d, 0, sizeof(size_t) * _n * _m);
615 for (size_t i = 1, im = 0; i < _m; ++i, ++im)
616 {
617 for (size_t j = 1, jn = 0; j < _n; ++j, ++jn)
618 {
619 if (_s[jn] == _t[im])
620 d[(i * _n) + j] = d[((i - 1) * _n) + (j - 1)];
621 else
622 {
623 d[(i * _n) + j] = min(d[(i - 1) * _n + j] + 1, /* A deletion. */
624 min(d[i * _n + (j - 1)] + 1, /* An insertion. */
625 d[(i - 1) * _n + (j - 1)] + 1)); /* A substitution. */
626 }
627 }
628 }
629
630 size_t r = d[_n * _m - 1];
631 delete[] d;
632 return r;
633 }
634
testSuggestions(vector<string> const & _testList,std::string const & _sMinusTArg)635 std::vector<std::string> testSuggestions(
636 vector<string> const& _testList, std::string const& _sMinusTArg)
637 {
638 vector<string> ret;
639 size_t allTestsElementIndex = 0;
640 // <index in availableTests, compared distance>
641 typedef std::pair<size_t, size_t> NameDistance;
642 // Use `vector` here because `set` does not work with sort
643 std::vector<NameDistance> distanceMap;
644 for (auto& it : _testList)
645 {
646 int const dist = test::levenshteinDistance(
647 _sMinusTArg.c_str(), _sMinusTArg.size(), it.c_str(), it.size());
648 distanceMap.emplace_back(allTestsElementIndex++, dist);
649 }
650 std::sort(distanceMap.begin(), distanceMap.end(),
651 [](NameDistance const& _a, NameDistance const& _b) { return _a.second < _b.second; });
652 for (size_t i = 0; i < 3 && i < distanceMap.size(); i++)
653 ret.push_back(_testList[distanceMap[i].first]);
654 return ret;
655 }
656
copyFile(fs::path const & _source,fs::path const & _destination)657 void copyFile(fs::path const& _source, fs::path const& _destination)
658 {
659 fs::ifstream src(_source, ios::binary);
660 fs::ofstream dst(_destination, ios::binary);
661 dst << src.rdbuf();
662 }
663
createRLPStreamFromTransactionFields(json_spirit::mObject const & _tObj)664 RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject const& _tObj)
665 {
666 // Construct Rlp of the given transaction
667 RLPStream rlpStream;
668 rlpStream.appendList(_tObj.size());
669
670 if (_tObj.count("nonce"))
671 rlpStream << bigint(_tObj.at("nonce").get_str());
672
673 if (_tObj.count("gasPrice"))
674 rlpStream << bigint(_tObj.at("gasPrice").get_str());
675
676 if (_tObj.count("gasLimit"))
677 rlpStream << bigint(_tObj.at("gasLimit").get_str());
678
679 if (_tObj.count("to"))
680 {
681 if (_tObj.at("to").get_str().empty())
682 rlpStream << "";
683 else
684 rlpStream << importByteArray(_tObj.at("to").get_str());
685 }
686
687 if (_tObj.count("value"))
688 rlpStream << bigint(_tObj.at("value").get_str());
689
690 if (_tObj.count("data"))
691 rlpStream << importData(_tObj);
692
693 if (_tObj.count("v"))
694 rlpStream << bigint(_tObj.at("v").get_str());
695
696 if (_tObj.count("r"))
697 rlpStream << bigint(_tObj.at("r").get_str());
698
699 if (_tObj.count("s"))
700 rlpStream << bigint(_tObj.at("s").get_str());
701
702 if (_tObj.count("extrafield"))
703 rlpStream << bigint(_tObj.at("extrafield").get_str());
704
705 return rlpStream;
706 }
707
constructHeader(h256 const & _parentHash,h256 const & _sha3Uncles,Address const & _author,h256 const & _stateRoot,h256 const & _transactionsRoot,h256 const & _receiptsRoot,dev::eth::LogBloom const & _logBloom,u256 const & _difficulty,u256 const & _number,u256 const & _gasLimit,u256 const & _gasUsed,u256 const & _timestamp,bytes const & _extraData)708 dev::eth::BlockHeader constructHeader(h256 const& _parentHash, h256 const& _sha3Uncles,
709 Address const& _author, h256 const& _stateRoot, h256 const& _transactionsRoot,
710 h256 const& _receiptsRoot, dev::eth::LogBloom const& _logBloom, u256 const& _difficulty,
711 u256 const& _number, u256 const& _gasLimit, u256 const& _gasUsed, u256 const& _timestamp,
712 bytes const& _extraData)
713 {
714 RLPStream rlpStream(15);
715
716 rlpStream << _parentHash << _sha3Uncles << _author << _stateRoot << _transactionsRoot
717 << _receiptsRoot << _logBloom << _difficulty << _number << _gasLimit << _gasUsed
718 << _timestamp << _extraData << h256{} << eth::Nonce{};
719
720 return BlockHeader(rlpStream.out(), HeaderData);
721 }
722
updateEthashSeal(dev::eth::BlockHeader & _header,h256 const & _mixHash,h64 const & _nonce)723 void updateEthashSeal(dev::eth::BlockHeader& _header, h256 const& _mixHash, h64 const& _nonce)
724 {
725 Ethash::setNonce(_header, _nonce);
726 Ethash::setMixHash(_header, _mixHash);
727 }
728
729 namespace
730 {
731 Listener* g_listener;
732 }
733
registerListener(Listener & _listener)734 void Listener::registerListener(Listener& _listener)
735 {
736 g_listener = &_listener;
737 }
738
notifySuiteStarted(string const & _name)739 void Listener::notifySuiteStarted(string const& _name)
740 {
741 if (g_listener)
742 g_listener->suiteStarted(_name);
743 }
744
notifyTestStarted(string const & _name)745 void Listener::notifyTestStarted(string const& _name)
746 {
747 if (g_listener)
748 g_listener->testStarted(_name);
749 }
750
notifyTestFinished(int64_t _gasUsed)751 void Listener::notifyTestFinished(int64_t _gasUsed)
752 {
753 if (g_listener)
754 g_listener->testFinished(_gasUsed);
755 }
756 }
757 } // namespaces
758