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