From 7ed7a9a2539bb5e548643bdca920471bc5c0b0a4 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 12 Mar 2015 09:16:32 +0100 Subject: [PATCH 01/10] create random state tests --- test/CMakeLists.txt | 5 + test/TestHelper.cpp | 32 +++--- test/createRandomStateTest.cpp | 186 +++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 16 deletions(-) create mode 100644 test/createRandomStateTest.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 292f62a03..83f61c769 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) list(REMOVE_ITEM SRC_LIST "./createRandomTest.cpp") +list(REMOVE_ITEM SRC_LIST "./createRandomStateTest.cpp") list(REMOVE_ITEM SRC_LIST "./checkRandomTest.cpp") if (NOT JSONRPC) @@ -18,6 +19,7 @@ include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) add_executable(createRandomTest createRandomTest.cpp vm.cpp TestHelper.cpp) +add_executable(createRandomStateTest createRandomStateTest.cpp state.cpp TestHelper.cpp) add_executable(checkRandomTest checkRandomTest.cpp vm.cpp TestHelper.cpp) target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) @@ -38,6 +40,9 @@ endif() target_link_libraries(createRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(createRandomTest ethereum) target_link_libraries(createRandomTest ethcore) +target_link_libraries(createRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) +target_link_libraries(createRandomStateTest ethereum) +target_link_libraries(createRandomStateTest ethcore) target_link_libraries(checkRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(checkRandomTest ethereum) target_link_libraries(checkRandomTest ethcore) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 9ac64107d..4d5563415 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -84,12 +84,12 @@ ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller) : m_statePre(Add void ImportTest::importEnv(json_spirit::mObject& _o) { - BOOST_REQUIRE(_o.count("previousHash") > 0); - BOOST_REQUIRE(_o.count("currentGasLimit") > 0); - BOOST_REQUIRE(_o.count("currentDifficulty") > 0); - BOOST_REQUIRE(_o.count("currentTimestamp") > 0); - BOOST_REQUIRE(_o.count("currentCoinbase") > 0); - BOOST_REQUIRE(_o.count("currentNumber") > 0); + assert(_o.count("previousHash") > 0); + assert(_o.count("currentGasLimit") > 0); + assert(_o.count("currentDifficulty") > 0); + assert(_o.count("currentTimestamp") > 0); + assert(_o.count("currentCoinbase") > 0); + assert(_o.count("currentNumber") > 0); m_environment.previousBlock.hash = h256(_o["previousHash"].get_str()); m_environment.currentBlock.number = toInt(_o["currentNumber"]); @@ -108,10 +108,10 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state) { json_spirit::mObject o = i.second.get_obj(); - BOOST_REQUIRE(o.count("balance") > 0); - BOOST_REQUIRE(o.count("nonce") > 0); - BOOST_REQUIRE(o.count("storage") > 0); - BOOST_REQUIRE(o.count("code") > 0); + assert(o.count("balance") > 0); + assert(o.count("nonce") > 0); + assert(o.count("storage") > 0); + assert(o.count("code") > 0); if (bigint(o["balance"].get_str()) >= c_max256plus1) BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'balance' is equal or greater than 2**256") ); @@ -144,12 +144,12 @@ void ImportTest::importTransaction(json_spirit::mObject& _o) { if (_o.count("secretKey") > 0) { - BOOST_REQUIRE(_o.count("nonce") > 0); - BOOST_REQUIRE(_o.count("gasPrice") > 0); - BOOST_REQUIRE(_o.count("gasLimit") > 0); - BOOST_REQUIRE(_o.count("to") > 0); - BOOST_REQUIRE(_o.count("value") > 0); - BOOST_REQUIRE(_o.count("data") > 0); + assert(_o.count("nonce") > 0); + assert(_o.count("gasPrice") > 0); + assert(_o.count("gasLimit") > 0); + assert(_o.count("to") > 0); + assert(_o.count("value") > 0); + assert(_o.count("data") > 0); if (bigint(_o["nonce"].get_str()) >= c_max256plus1) BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'nonce' is equal or greater than 2**256") ); diff --git a/test/createRandomStateTest.cpp b/test/createRandomStateTest.cpp new file mode 100644 index 000000000..2743ad191 --- /dev/null +++ b/test/createRandomStateTest.cpp @@ -0,0 +1,186 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file createRandomStateTest.cpp + * @author Christoph Jentzsch + * @date 2015 + * Creating a random state test. + */ + +#include +#include +#include + +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-parameter" +#include +#include +#include +#include +#include +#include +#include +#include "TestHelper.h" +#include "vm.h" + +using namespace std; +using namespace json_spirit; +using namespace dev; + +void doStateTests(json_spirit::mValue& _v); + +int main(int argc, char *argv[]) +{ + g_logVerbosity = 0; + + // create random code + + boost::random::mt19937 gen; + + auto now = chrono::steady_clock::now().time_since_epoch(); + auto timeSinceEpoch = chrono::duration_cast(now).count(); + gen.seed(static_cast(timeSinceEpoch)); + boost::random::uniform_int_distribution<> lengthOfCodeDist(2, 16); + boost::random::uniform_int_distribution<> opcodeDist(0, 255); + boost::random::uniform_int_distribution<> BlockInfoOpcodeDist(0x40, 0x45); + boost::random::variate_generator > randGen(gen, opcodeDist); + boost::random::variate_generator > randGenBlockInfoOpcode(gen, BlockInfoOpcodeDist); + + int lengthOfCode = lengthOfCodeDist(gen); + string randomCode; + + for (int i = 0; i < lengthOfCode; ++i) + { + if (i < 8 && (randGen() < 192)) + { + randomCode += toHex(toCompactBigEndian((uint8_t)randGenBlockInfoOpcode())); + continue; + } + + uint8_t opcode = randGen(); + // disregard all invalid commands, except of one (0x0c) + if ((dev::eth::isValidInstruction(dev::eth::Instruction(opcode)) || (randGen() > 250))) + randomCode += toHex(toCompactBigEndian(opcode)); + else + i--; + } + + string const s = R"( + { + "randomStatetest" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "code" : "0x6001600101600055", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "400000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000" + } + } + } +)"; + + + cout << "the test: " << s << endl; + + mValue v; + read_string(s, v); + + // insert new random code + v.get_obj().find("randomStatetest")->second.get_obj().find("pre")->second.get_obj().begin()->second.get_obj()["code"] = "0x" + randomCode + (randGen() > 128 ? "55" : ""); + + // fill test + doStateTests(v); + + // stream to output for further handling by the bash script + cout << json_spirit::write_string(v, true); + + return 0; +} + +void doStateTests(json_spirit::mValue& _v) +{ + try{ + for (auto& i: _v.get_obj()) + { + cerr << i.first << endl; + mObject& o = i.second.get_obj(); + + assert(o.count("env") > 0); + assert(o.count("pre") > 0); + assert(o.count("transaction") > 0); + + test::ImportTest importer(o, true); + + eth::State theState = importer.m_statePre; + bytes tx = importer.m_transaction.rlp(); + bytes output; + + try + { + theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), tx, &output); + } + catch (Exception const& _e) + { + cnote << "state execution did throw an exception: " << diagnostic_information(_e); + theState.commit(); + } + catch (std::exception const& _e) + { + cnote << "state execution did throw an exception: " << _e.what(); + } +#if ETH_FATDB + importer.exportTest(output, theState); +#else + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off")); +#endif + } + } + catch (Exception const& _e) + { + cout << "problem: " << diagnostic_information(_e); + } +} + From 0fa604edd82f4f06fc8d955dd664e9dcf98ce4f3 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 12 Mar 2015 11:01:06 +0100 Subject: [PATCH 02/10] add check random state test for jit --- test/CMakeLists.txt | 25 +- test/checkRandomStateTest.cpp | 219 ++++++++++++++++++ ...ckRandomTest.cpp => checkRandomVMTest.cpp} | 0 test/createRandomStateTest.cpp | 158 ++++++------- ...eRandomTest.cpp => createRandomVMTest.cpp} | 0 test/state.cpp | 33 +++ 6 files changed, 342 insertions(+), 93 deletions(-) create mode 100644 test/checkRandomStateTest.cpp rename test/{checkRandomTest.cpp => checkRandomVMTest.cpp} (100%) rename test/{createRandomTest.cpp => createRandomVMTest.cpp} (100%) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 83f61c769..45f83e5e3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,9 +1,10 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) -list(REMOVE_ITEM SRC_LIST "./createRandomTest.cpp") +list(REMOVE_ITEM SRC_LIST "./createRandomVMTest.cpp") list(REMOVE_ITEM SRC_LIST "./createRandomStateTest.cpp") -list(REMOVE_ITEM SRC_LIST "./checkRandomTest.cpp") +list(REMOVE_ITEM SRC_LIST "./checkRandomVMTest.cpp") +list(REMOVE_ITEM SRC_LIST "./checkRandomStateTest.cpp") if (NOT JSONRPC) list(REMOVE_ITEM SRC_LIST "./AccountHolder.cpp") @@ -18,9 +19,10 @@ include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) -add_executable(createRandomTest createRandomTest.cpp vm.cpp TestHelper.cpp) +add_executable(createRandomVMTest createRandomVMTest.cpp vm.cpp TestHelper.cpp) add_executable(createRandomStateTest createRandomStateTest.cpp state.cpp TestHelper.cpp) -add_executable(checkRandomTest checkRandomTest.cpp vm.cpp TestHelper.cpp) +add_executable(checkRandomVMTest checkRandomVMTest.cpp vm.cpp TestHelper.cpp) +add_executable(checkRandomStateTest checkRandomStateTest.cpp state.cpp TestHelper.cpp) target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(testeth ${CURL_LIBRARIES}) @@ -37,13 +39,16 @@ if (JSONRPC) target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES}) endif() -target_link_libraries(createRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) -target_link_libraries(createRandomTest ethereum) -target_link_libraries(createRandomTest ethcore) +target_link_libraries(createRandomVMTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) +target_link_libraries(createRandomVMTest ethereum) +target_link_libraries(createRandomVMTest ethcore) target_link_libraries(createRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(createRandomStateTest ethereum) target_link_libraries(createRandomStateTest ethcore) -target_link_libraries(checkRandomTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) -target_link_libraries(checkRandomTest ethereum) -target_link_libraries(checkRandomTest ethcore) +target_link_libraries(checkRandomVMTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) +target_link_libraries(checkRandomVMTest ethereum) +target_link_libraries(checkRandomVMTest ethcore) +target_link_libraries(checkRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) +target_link_libraries(checkRandomStateTest ethereum) +target_link_libraries(checkRandomStateTest ethcore) diff --git a/test/checkRandomStateTest.cpp b/test/checkRandomStateTest.cpp new file mode 100644 index 000000000..29ccc2eb0 --- /dev/null +++ b/test/checkRandomStateTest.cpp @@ -0,0 +1,219 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file checkRandomTest.cpp + * @author Christoph Jentzsch + * @date 2015 + * Check a random test and return 0/1 for success or failure. To be used for efficiency in the random test simulation. + */ + +#include +#include +#include +#include +#include "TestHelper.h" +#include "vm.h" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +using namespace std; +using namespace json_spirit; +using namespace dev::test; +using namespace dev; + +bool doStateTest(mValue& v); + +int main(int argc, char *argv[]) +{ + g_logVerbosity = 0; + bool ret = false; + + try + { + mValue v; + string s; + for (int i = 1; i < argc; ++i) + s += argv[i]; + if (asserts(s.length() > 0)) + { + cout << "Content of argument is empty\n"; + return 1; + } + read_string(s, v); + ret = doStateTest(v); + } + catch (Exception const& _e) + { + cout << "Failed test with Exception: " << diagnostic_information(_e) << endl; + ret = false; + } + catch (std::exception const& _e) + { + cout << "Failed test with Exception: " << _e.what() << endl; + ret = false; + } + return ret; +} + +bool doStateTest(mValue& v) +{ + eth::VMFactory::setKind(eth::VMKind::JIT); + + for (auto& i: v.get_obj()) + { + //cerr << i.first << endl; + mObject& o = i.second.get_obj(); + + assert(o.count("env") > 0); + assert(o.count("pre") > 0); + assert(o.count("transaction") > 0); + + ImportTest importer(o, false); + + eth::State theState = importer.m_statePre; + bytes tx = importer.m_transaction.rlp(); + bytes output; + + try + { + theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output); + } + catch (Exception const& _e) + { + cnote << "state execution did throw an exception: " << diagnostic_information(_e); + theState.commit(); + } + catch (std::exception const& _e) + { + cnote << "state execution did throw an exception: " << _e.what(); + } + + assert(o.count("post") > 0); + assert(o.count("out") > 0); + + + //checkOutput(output, o); + int j = 0; + if (o["out"].type() == array_type) + for (auto const& d: o["out"].get_array()) + { + if (asserts(output[j] == toInt(d))) + { + cout << "Output byte [" << j << "] different!"; + return 1; + } + ++j; + } + else if (o["out"].get_str().find("0x") == 0) + { + if (asserts(output == fromHex(o["out"].get_str().substr(2)))) + return 1; + } + else + { + if (asserts(output == fromHex(o["out"].get_str()))) + return 1; + } + + + // check logs + //checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs); + eth::LogEntries logs = theState.pending().size() ? theState.log(0) : eth::LogEntries(); + + //checkLog(logs, importer.m_environment.sub.logs); + { + if (assertsEqual(logs.size(), importer.m_environment.sub.logs.size())) + return 1; + + for (size_t i = 0; i < logs.size(); ++i) + { + if (assertsEqual(logs[i].address, importer.m_environment.sub.logs[i].address)) + return 1; + if (assertsEqual(logs[i].topics, importer.m_environment.sub.logs[i].topics)) + return 1; + if (asserts(logs[i].data == importer.m_environment.sub.logs[i].data)) + return 1; + } + } + + // check addresses +#if ETH_FATDB + auto expectedAddrs = importer.m_statePost.addresses(); + auto resultAddrs = theState.addresses(); + for (auto& expectedPair : expectedAddrs) + { + auto& expectedAddr = expectedPair.first; + auto resultAddrIt = resultAddrs.find(expectedAddr); + if (resultAddrIt == resultAddrs.end()) + BOOST_ERROR("Missing expected address " << expectedAddr); + else + { + BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) == theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr)); + BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) == theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr)); + BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code"); + + //checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr); + + map _resultStore = theState.storage(expectedAddr); + + for (auto&& expectedStorePair : importer.m_statePost.storage(expectedAddr)) + { + auto& expectedStoreKey = expectedStorePair.first; + auto resultStoreIt = _resultStore.find(expectedStoreKey); + if (resultStoreIt == _resultStore.end()) + { + cout << expectedAddr << ": missing store key " << expectedStoreKey << endl; + return 1; + } + else + { + auto& expectedStoreValue = expectedStorePair.second; + auto& resultStoreValue = resultStoreIt->second; + if (asserts(expectedStoreValue == resultStoreValue)) + { + cout << expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue << endl; + return 1; + } + } + } + if (assertsEqual(_resultStore.size(), importer.m_statePost.storage(expectedAddr).size())) + return 1; + for (auto&& resultStorePair: _resultStore) + { + if (!importer.m_statePost.storage(expectedAddr).count(resultStorePair.first)) + { + cout << expectedAddr << ": unexpected store key " << resultStorePair.first << endl; + return 1; + } + } + } + } + //checkAddresses >(expectedAddrs, resultAddrs); + for (auto& resultPair : resultAddrs) + { + auto& resultAddr = resultPair.first; + auto expectedAddrIt = expectedAddrs.find(resultAddr); + if (expectedAddrIt == expectedAddrs.end()) + return 1; + } + if(expectedAddrs != resultAddrs) + return 1; + +#endif + if(theState.rootHash() != h256(o["postStateRoot"].get_str()), "wrong post state root") + return 1; + } + return 0; +} diff --git a/test/checkRandomTest.cpp b/test/checkRandomVMTest.cpp similarity index 100% rename from test/checkRandomTest.cpp rename to test/checkRandomVMTest.cpp diff --git a/test/createRandomStateTest.cpp b/test/createRandomStateTest.cpp index 2743ad191..06a332e0e 100644 --- a/test/createRandomStateTest.cpp +++ b/test/createRandomStateTest.cpp @@ -82,57 +82,53 @@ int main(int argc, char *argv[]) i--; } - string const s = R"( - { - "randomStatetest" : { - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "1000000", - "currentNumber" : "0", - "currentTimestamp" : 1, - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "1000000000000000000", - "code" : "0x6001600101600055", - "nonce" : "0", - "storage" : { - } - }, - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000000000", - "code" : "0x", - "nonce" : "0", - "storage" : { - } - } - }, - "transaction" : { - "data" : "", - "gasLimit" : "400000", - "gasPrice" : "1", - "nonce" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", - "value" : "100000" - } - } - } + string const s = R"( + { + "randomStatetest" : { + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "256", + "currentGasLimit" : "1000000", + "currentNumber" : "0", + "currentTimestamp" : 1, + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "code" : "0x6001600101600055", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "code" : "0x", + "nonce" : "0", + "storage" : { + } + } + }, + "transaction" : { + "data" : "", + "gasLimit" : "400000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000" + } + } + } )"; - - - cout << "the test: " << s << endl; - - mValue v; + mValue v; read_string(s, v); // insert new random code - v.get_obj().find("randomStatetest")->second.get_obj().find("pre")->second.get_obj().begin()->second.get_obj()["code"] = "0x" + randomCode + (randGen() > 128 ? "55" : ""); + v.get_obj().find("randomStatetest")->second.get_obj().find("pre")->second.get_obj().begin()->second.get_obj()["code"] = "0x" + randomCode + (randGen() > 128 ? "55" : ""); - // fill test - doStateTests(v); + // fill test + doStateTests(v); // stream to output for further handling by the bash script cout << json_spirit::write_string(v, true); @@ -142,45 +138,41 @@ int main(int argc, char *argv[]) void doStateTests(json_spirit::mValue& _v) { - try{ - for (auto& i: _v.get_obj()) - { - cerr << i.first << endl; - mObject& o = i.second.get_obj(); - - assert(o.count("env") > 0); - assert(o.count("pre") > 0); - assert(o.count("transaction") > 0); - - test::ImportTest importer(o, true); - - eth::State theState = importer.m_statePre; - bytes tx = importer.m_transaction.rlp(); - bytes output; - - try - { - theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), tx, &output); - } - catch (Exception const& _e) - { - cnote << "state execution did throw an exception: " << diagnostic_information(_e); - theState.commit(); - } - catch (std::exception const& _e) - { - cnote << "state execution did throw an exception: " << _e.what(); - } + eth::VMFactory::setKind(eth::VMKind::Interpreter); + + for (auto& i: _v.get_obj()) + { + //cerr << i.first << endl; + mObject& o = i.second.get_obj(); + + assert(o.count("env") > 0); + assert(o.count("pre") > 0); + assert(o.count("transaction") > 0); + + test::ImportTest importer(o, true); + + eth::State theState = importer.m_statePre; + bytes tx = importer.m_transaction.rlp(); + bytes output; + + try + { + theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), tx, &output); + } + catch (Exception const& _e) + { + cnote << "state execution did throw an exception: " << diagnostic_information(_e); + theState.commit(); + } + catch (std::exception const& _e) + { + cnote << "state execution did throw an exception: " << _e.what(); + } #if ETH_FATDB - importer.exportTest(output, theState); + importer.exportTest(output, theState); #else - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off")); + cout << "You can not fill tests when FATDB is switched off"; #endif - } - } - catch (Exception const& _e) - { - cout << "problem: " << diagnostic_information(_e); - } + } } diff --git a/test/createRandomTest.cpp b/test/createRandomVMTest.cpp similarity index 100% rename from test/createRandomTest.cpp rename to test/createRandomVMTest.cpp diff --git a/test/state.cpp b/test/state.cpp index 5202aff22..1c8f4301a 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -251,6 +251,39 @@ BOOST_AUTO_TEST_CASE(stCreateTest) } } +BOOST_AUTO_TEST_CASE(stRandom) +{ + string testPath = dev::test::getTestPath(); + testPath += "/StateTests/RandomTests"; + + vector testFiles; + boost::filesystem::directory_iterator iterator(testPath); + for(; iterator != boost::filesystem::directory_iterator(); ++iterator) + if (boost::filesystem::is_regular_file(iterator->path()) && iterator->path().extension() == ".json") + testFiles.push_back(iterator->path()); + + for (auto& path: testFiles) + { + try + { + cnote << "Testing ..." << path.filename(); + json_spirit::mValue v; + string s = asString(dev::contents(path.string())); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + path.string() + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); + json_spirit::read_string(s, v); + dev::test::doStateTests(v, false); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed test with Exception: " << _e.what()); + } + } +} + BOOST_AUTO_TEST_CASE(userDefinedFileState) { dev::test::userDefinedTest("--singletest", dev::test::doStateTests); From 741194a2f50c317d221015f730aa6b9410cc7278 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 12 Mar 2015 11:36:46 +0100 Subject: [PATCH 03/10] remove boost test lib macros from check random state test --- test/checkRandomStateTest.cpp | 42 ++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/test/checkRandomStateTest.cpp b/test/checkRandomStateTest.cpp index 29ccc2eb0..90a88d57e 100644 --- a/test/checkRandomStateTest.cpp +++ b/test/checkRandomStateTest.cpp @@ -73,7 +73,6 @@ bool doStateTest(mValue& v) for (auto& i: v.get_obj()) { - //cerr << i.first << endl; mObject& o = i.second.get_obj(); assert(o.count("env") > 0); @@ -103,7 +102,6 @@ bool doStateTest(mValue& v) assert(o.count("post") > 0); assert(o.count("out") > 0); - //checkOutput(output, o); int j = 0; if (o["out"].type() == array_type) @@ -132,20 +130,17 @@ bool doStateTest(mValue& v) //checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs); eth::LogEntries logs = theState.pending().size() ? theState.log(0) : eth::LogEntries(); - //checkLog(logs, importer.m_environment.sub.logs); + if (assertsEqual(logs.size(), importer.m_environment.sub.logs.size())) + return 1; + + for (size_t i = 0; i < logs.size(); ++i) { - if (assertsEqual(logs.size(), importer.m_environment.sub.logs.size())) + if (assertsEqual(logs[i].address, importer.m_environment.sub.logs[i].address)) + return 1; + if (assertsEqual(logs[i].topics, importer.m_environment.sub.logs[i].topics)) + return 1; + if (asserts(logs[i].data == importer.m_environment.sub.logs[i].data)) return 1; - - for (size_t i = 0; i < logs.size(); ++i) - { - if (assertsEqual(logs[i].address, importer.m_environment.sub.logs[i].address)) - return 1; - if (assertsEqual(logs[i].topics, importer.m_environment.sub.logs[i].topics)) - return 1; - if (asserts(logs[i].data == importer.m_environment.sub.logs[i].data)) - return 1; - } } // check addresses @@ -160,12 +155,23 @@ bool doStateTest(mValue& v) BOOST_ERROR("Missing expected address " << expectedAddr); else { - BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) == theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr)); - BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) == theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr)); - BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code"); + if (importer.m_statePost.balance(expectedAddr) != theState.balance(expectedAddr)) + { + cout << expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr); + return 1; + } + if (importer.m_statePost.transactionsFrom(expectedAddr) != theState.transactionsFrom(expectedAddr)) + { + cout << expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr); + return 1; + } + if (importer.m_statePost.code(expectedAddr) != theState.code(expectedAddr)) + { + cout << expectedAddr << ": incorrect code"; + return 1; + } //checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr); - map _resultStore = theState.storage(expectedAddr); for (auto&& expectedStorePair : importer.m_statePost.storage(expectedAddr)) From 77ea8e2fce1e7cf6e11d3deccc50da469c25f84d Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 12 Mar 2015 11:42:16 +0100 Subject: [PATCH 04/10] remove unneccessary dependencies --- test/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 45f83e5e3..d7761b8d3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,9 +20,9 @@ include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) add_executable(createRandomVMTest createRandomVMTest.cpp vm.cpp TestHelper.cpp) -add_executable(createRandomStateTest createRandomStateTest.cpp state.cpp TestHelper.cpp) +add_executable(createRandomStateTest createRandomStateTest.cpp TestHelper.cpp) add_executable(checkRandomVMTest checkRandomVMTest.cpp vm.cpp TestHelper.cpp) -add_executable(checkRandomStateTest checkRandomStateTest.cpp state.cpp TestHelper.cpp) +add_executable(checkRandomStateTest checkRandomStateTest.cpp TestHelper.cpp) target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(testeth ${CURL_LIBRARIES}) From 38a8a25322c037ab5fdd6b23beb6e08a33d80018 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 12 Mar 2015 11:54:11 +0100 Subject: [PATCH 05/10] style fix --- test/checkRandomStateTest.cpp | 12 +++++++----- test/checkRandomVMTest.cpp | 6 +++--- test/createRandomVMTest.cpp | 6 +++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/test/checkRandomStateTest.cpp b/test/checkRandomStateTest.cpp index 90a88d57e..4c07c3cf9 100644 --- a/test/checkRandomStateTest.cpp +++ b/test/checkRandomStateTest.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file checkRandomTest.cpp +/** @file checkRandomStateTest.cpp * @author Christoph Jentzsch * @date 2015 * Check a random test and return 0/1 for success or failure. To be used for efficiency in the random test simulation. @@ -33,7 +33,7 @@ using namespace json_spirit; using namespace dev::test; using namespace dev; -bool doStateTest(mValue& v); +bool doStateTest(mValue& _v); int main(int argc, char *argv[]) { @@ -67,11 +67,11 @@ int main(int argc, char *argv[]) return ret; } -bool doStateTest(mValue& v) +bool doStateTest(mValue& _v) { eth::VMFactory::setKind(eth::VMKind::JIT); - for (auto& i: v.get_obj()) + for (auto& i: _v.get_obj()) { mObject& o = i.second.get_obj(); @@ -152,7 +152,9 @@ bool doStateTest(mValue& v) auto& expectedAddr = expectedPair.first; auto resultAddrIt = resultAddrs.find(expectedAddr); if (resultAddrIt == resultAddrs.end()) - BOOST_ERROR("Missing expected address " << expectedAddr); + { + cout << "Missing expected address " << expectedAddr; + return 1; else { if (importer.m_statePost.balance(expectedAddr) != theState.balance(expectedAddr)) diff --git a/test/checkRandomVMTest.cpp b/test/checkRandomVMTest.cpp index e3442d438..c96357714 100644 --- a/test/checkRandomVMTest.cpp +++ b/test/checkRandomVMTest.cpp @@ -32,7 +32,7 @@ using namespace json_spirit; using namespace dev::test; using namespace dev; -bool doVMTest(mValue& v); +bool doVMTest(mValue& _v); int main(int argc, char *argv[]) { @@ -66,11 +66,11 @@ int main(int argc, char *argv[]) return ret; } -bool doVMTest(mValue& v) +bool doVMTest(mValue& _v) { eth::VMFactory::setKind(eth::VMKind::JIT); - for (auto& i: v.get_obj()) + for (auto& i: _v.get_obj()) { cnote << i.first; mObject& o = i.second.get_obj(); diff --git a/test/createRandomVMTest.cpp b/test/createRandomVMTest.cpp index 55e023759..de81099fe 100644 --- a/test/createRandomVMTest.cpp +++ b/test/createRandomVMTest.cpp @@ -41,7 +41,7 @@ using namespace std; using namespace json_spirit; using namespace dev; -void doMyTests(json_spirit::mValue& v); +void doMyTests(json_spirit::mValue& _v); int main(int argc, char *argv[]) { @@ -127,11 +127,11 @@ int main(int argc, char *argv[]) return 0; } -void doMyTests(json_spirit::mValue& v) +void doMyTests(json_spirit::mValue& _v) { eth::VMFactory::setKind(eth::VMKind::Interpreter); - for (auto& i: v.get_obj()) + for (auto& i: _v.get_obj()) { cnote << i.first; mObject& o = i.second.get_obj(); From 20654a1f71f0b871635e2babd6e5c024c1bf36b0 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 12 Mar 2015 12:49:52 +0100 Subject: [PATCH 06/10] random state test optmization --- test/checkRandomStateTest.cpp | 1 + test/createRandomStateTest.cpp | 15 +++++++++++---- test/stSystemOperationsTestFiller.json | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/test/checkRandomStateTest.cpp b/test/checkRandomStateTest.cpp index 4c07c3cf9..ed12b7dc4 100644 --- a/test/checkRandomStateTest.cpp +++ b/test/checkRandomStateTest.cpp @@ -155,6 +155,7 @@ bool doStateTest(mValue& _v) { cout << "Missing expected address " << expectedAddr; return 1; + } else { if (importer.m_statePost.balance(expectedAddr) != theState.balance(expectedAddr)) diff --git a/test/createRandomStateTest.cpp b/test/createRandomStateTest.cpp index 06a332e0e..6b24f1216 100644 --- a/test/createRandomStateTest.cpp +++ b/test/createRandomStateTest.cpp @@ -87,10 +87,10 @@ int main(int argc, char *argv[]) "randomStatetest" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "256", - "currentGasLimit" : "1000000", + "currentDifficulty" : "0x945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", "currentNumber" : "0", - "currentTimestamp" : 1, + "currentTimestamp" : "1", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" }, "pre" : { @@ -101,6 +101,13 @@ int main(int argc, char *argv[]) "storage" : { } }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "46", + "code" : "0x6000355415600957005b60203560003555", + "nonce" : "0", + "storage" : { + } + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "code" : "0x", @@ -110,7 +117,7 @@ int main(int argc, char *argv[]) } }, "transaction" : { - "data" : "", + "data" : "0x42", "gasLimit" : "400000", "gasPrice" : "1", "nonce" : "0", diff --git a/test/stSystemOperationsTestFiller.json b/test/stSystemOperationsTestFiller.json index 7460ca94e..e26308e28 100644 --- a/test/stSystemOperationsTestFiller.json +++ b/test/stSystemOperationsTestFiller.json @@ -389,7 +389,7 @@ "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "1000000000000000000", "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALL 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 64 0) }", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALL 100000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 64 0) }", "storage": {} }, "945304eb96065b2a98b57a48a06ae28d285a71b5" : { @@ -410,7 +410,7 @@ "transaction" : { "nonce" : "0", "gasPrice" : "1", - "gasLimit" : "30000", + "gasLimit" : "300000", "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", "value" : "100000", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", From d3ed076f01cd1bd6b32f6363cfa6e9f0bf6ab67d Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 12 Mar 2015 14:33:00 +0100 Subject: [PATCH 07/10] style --- test/checkRandomStateTest.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/checkRandomStateTest.cpp b/test/checkRandomStateTest.cpp index ed12b7dc4..9cd42dfd3 100644 --- a/test/checkRandomStateTest.cpp +++ b/test/checkRandomStateTest.cpp @@ -125,8 +125,6 @@ bool doStateTest(mValue& _v) return 1; } - - // check logs //checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs); eth::LogEntries logs = theState.pending().size() ? theState.log(0) : eth::LogEntries(); @@ -219,7 +217,6 @@ bool doStateTest(mValue& _v) } if(expectedAddrs != resultAddrs) return 1; - #endif if(theState.rootHash() != h256(o["postStateRoot"].get_str()), "wrong post state root") return 1; From f20a3e10fba202948f63e070c71357edd7226e5c Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 12 Mar 2015 17:44:57 +0100 Subject: [PATCH 08/10] bugfix --- test/checkRandomStateTest.cpp | 5 ++++- test/createRandomStateTest.cpp | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/checkRandomStateTest.cpp b/test/checkRandomStateTest.cpp index 9cd42dfd3..601ef1ca9 100644 --- a/test/checkRandomStateTest.cpp +++ b/test/checkRandomStateTest.cpp @@ -218,8 +218,11 @@ bool doStateTest(mValue& _v) if(expectedAddrs != resultAddrs) return 1; #endif - if(theState.rootHash() != h256(o["postStateRoot"].get_str()), "wrong post state root") + if(theState.rootHash() != h256(o["postStateRoot"].get_str())) + { + cout << "wrong post state root" << endl; return 1; + } } return 0; } diff --git a/test/createRandomStateTest.cpp b/test/createRandomStateTest.cpp index 6b24f1216..f9baa0091 100644 --- a/test/createRandomStateTest.cpp +++ b/test/createRandomStateTest.cpp @@ -86,8 +86,8 @@ int main(int argc, char *argv[]) { "randomStatetest" : { "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentCoinbase" : "945304eb96065b2a98b57a48a06ae28d285a71b5", + "currentDifficulty" : "5623894562375", "currentGasLimit" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", "currentNumber" : "0", "currentTimestamp" : "1", From 76bd23b61d94771053029b399c16a2e99608078a Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 12 Mar 2015 19:01:09 +0100 Subject: [PATCH 09/10] style --- test/createRandomStateTest.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/createRandomStateTest.cpp b/test/createRandomStateTest.cpp index f9baa0091..13b622bb1 100644 --- a/test/createRandomStateTest.cpp +++ b/test/createRandomStateTest.cpp @@ -58,10 +58,8 @@ int main(int argc, char *argv[]) boost::random::uniform_int_distribution<> lengthOfCodeDist(2, 16); boost::random::uniform_int_distribution<> opcodeDist(0, 255); boost::random::uniform_int_distribution<> BlockInfoOpcodeDist(0x40, 0x45); - boost::random::variate_generator > randGen(gen, opcodeDist); - boost::random::variate_generator > randGenBlockInfoOpcode(gen, BlockInfoOpcodeDist); + boost::random::variate_generator > randGen(gen, opcodeDist); + boost::random::variate_generator > randGenBlockInfoOpcode(gen, BlockInfoOpcodeDist); int lengthOfCode = lengthOfCodeDist(gen); string randomCode; From 77f9a58c61695ad265008065e3c8a693b23c1f39 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 12 Mar 2015 19:03:07 +0100 Subject: [PATCH 10/10] style --- test/checkRandomStateTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/checkRandomStateTest.cpp b/test/checkRandomStateTest.cpp index 601ef1ca9..17e785f60 100644 --- a/test/checkRandomStateTest.cpp +++ b/test/checkRandomStateTest.cpp @@ -215,10 +215,10 @@ bool doStateTest(mValue& _v) if (expectedAddrIt == expectedAddrs.end()) return 1; } - if(expectedAddrs != resultAddrs) + if (expectedAddrs != resultAddrs) return 1; #endif - if(theState.rootHash() != h256(o["postStateRoot"].get_str())) + if (theState.rootHash() != h256(o["postStateRoot"].get_str())) { cout << "wrong post state root" << endl; return 1;