diff --git a/CMakeLists.txt b/CMakeLists.txt index b95d9fbe3..57f018dba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,58 +86,106 @@ endif () if (${TARGET_PLATFORM} STREQUAL "w64") else () - # Look for available Crypto++ version and if it is >= 5.6.2 - find_path(ID cryptlib.h - /usr/include/cryptopp - /usr/include/crypto++ - /usr/local/include/cryptopp - /usr/local/include/crypto++ - /opt/local/include/cryptopp - /opt/local/include/crypto++ - ) - find_library(LS NAMES cryptoppeth cryptopp - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - ) - - if(ID AND LS) - message(STATUS "Found Crypto++: ${ID}, ${LS}") - set(_CRYPTOPP_VERSION_HEADER ${ID}/config.h) - if(EXISTS ${_CRYPTOPP_VERSION_HEADER}) - file(STRINGS ${_CRYPTOPP_VERSION_HEADER} _CRYPTOPP_VERSION REGEX "^#define CRYPTOPP_VERSION[ \t]+[0-9]+$") - string(REGEX REPLACE "^#define CRYPTOPP_VERSION[ \t]+([0-9]+)" "\\1" _CRYPTOPP_VERSION ${_CRYPTOPP_VERSION}) - if(${_CRYPTOPP_VERSION} LESS 562) - message(STATUS "System Crypto++ version found is smaller than 5.6.2.") - else() - set(CRYPTOPP_INCLUDE_DIR ${ID} CACHE FILEPATH "" FORCE) - set(CRYPTOPP_LIBRARIES ${LS} CACHE FILEPATH "" FORCE) - set(CRYPTOPP_FOUND TRUE) - message(STATUS "System Crypto++ found and version greater or equal to 5.6.2") - endif() - endif() - endif() - - if(NOT CRYPTOPP_FOUND) - set(CRYPTOPP_INCLUDE_DIR "../cryptopp562" CACHE FILEPATH "" FORCE) - find_library(LSLOC NAMES cryptoppeth cryptopp - PATHS ../cryptopp562 - NO_DEFAULT_PATH - ) - set(CRYPTOPP_LIBRARIES ${LSLOC} CACHE FILEPATH "" FORCE) - message(STATUS "System Crypto++ not found, broken or too old. We use ${LSLOC}") - endif() - - # Not really worth caching. We want to reevaluate anyway. - mark_as_advanced(CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARIES) - - # Always "found", given last block. - include_directories(${CRYPTOPP_INCLUDE_DIR}) + # Look for available Crypto++ version and if it is >= 5.6.2 + find_path(ID cryptlib.h + /usr/include/cryptopp + /usr/include/crypto++ + /usr/local/include/cryptopp + /usr/local/include/crypto++ + /opt/local/include/cryptopp + /opt/local/include/crypto++ + ) + find_library(LS NAMES cryptoppeth cryptopp + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + ) + + if(ID AND LS) + message(STATUS "Found Crypto++: ${ID}, ${LS}") + set(_CRYPTOPP_VERSION_HEADER ${ID}/config.h) + if(EXISTS ${_CRYPTOPP_VERSION_HEADER}) + file(STRINGS ${_CRYPTOPP_VERSION_HEADER} _CRYPTOPP_VERSION REGEX "^#define CRYPTOPP_VERSION[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define CRYPTOPP_VERSION[ \t]+([0-9]+)" "\\1" _CRYPTOPP_VERSION ${_CRYPTOPP_VERSION}) + if(${_CRYPTOPP_VERSION} LESS 562) + message(STATUS "System Crypto++ version found is smaller than 5.6.2.") + else() + set(CRYPTOPP_INCLUDE_DIR ${ID} CACHE FILEPATH "" FORCE) + set(CRYPTOPP_LIBRARIES ${LS} CACHE FILEPATH "" FORCE) + set(CRYPTOPP_FOUND TRUE) + message(STATUS "System Crypto++ found and version greater or equal to 5.6.2") + endif() + endif() + endif() + + if(NOT CRYPTOPP_FOUND) + set(CRYPTOPP_INCLUDE_DIR "../cryptopp562" CACHE FILEPATH "" FORCE) + find_library(LSLOC NAMES cryptoppeth cryptopp + PATHS ../cryptopp562 + NO_DEFAULT_PATH + ) + set(CRYPTOPP_LIBRARIES ${LSLOC} CACHE FILEPATH "" FORCE) + message(STATUS "System Crypto++ not found, broken or too old. We use ${LSLOC}") + endif() + + # Not really worth caching. We want to reevaluate anyway. + mark_as_advanced(CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARIES) + + # Always "found", given last block. + include_directories(${CRYPTOPP_INCLUDE_DIR}) if(NOT APPLE) link_directories(${CRYPTOPP_LIBRARIES}) endif() + + find_path( LEVELDB_ID leveldb/db.h + /usr/include + /usr/local/include + ) + if ( LEVELDB_ID ) + message(STATUS "Found LevelDB Headers") + else () + message(FATAL_ERROR "Failed to find the LevelDB headers") + endif () + + # Check for accessory dev libraries leveldb and miniupnpc + find_library( LEVELDB_LS NAMES leveldb + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + if ( LEVELDB_LS ) + message(STATUS "Found LevelDB Library: ${LEVELDB_LS}") + else () + message(FATAL_ERROR "Failed to find the LevelDB Library!") + endif () + + find_path( MINIUPNPC_ID miniupnpc/miniwget.h + /usr/include/miniupnpc + /usr/local/include/miniupnpc + ) + if ( MINIUPNPC_ID ) + message(STATUS "Found miniupnpc headers") + else () + message(FATAL_ERROR "Failed to find the miniupnpc headers!") + endif () + + find_library( MINIUPNPC_LS NAMES miniupnpc + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + if ( MINIUPNPC_LS ) + message(STATUS "Found miniupnpc library: ${MINIUPNPC_LS}") + else () + message(FATAL_ERROR "Failed to find the miniupnpc library!") + endif () + endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") @@ -154,12 +202,12 @@ add_subdirectory(test) add_subdirectory(eth) if ("${TARGET_PLATFORM}" STREQUAL "w64") else () - add_subdirectory(neth) + add_subdirectory(neth) endif () if (NOT HEADLESS) - add_subdirectory(libqethereum) - add_subdirectory(alethzero) - add_subdirectory(walleth) + add_subdirectory(libqethereum) + add_subdirectory(alethzero) + add_subdirectory(walleth) endif () enable_testing() diff --git a/libethereum/Instruction.cpp b/libethereum/Instruction.cpp index 5f11f33af..3fd81b695 100644 --- a/libethereum/Instruction.cpp +++ b/libethereum/Instruction.cpp @@ -115,89 +115,89 @@ const std::map eth::c_instructions = }; const std::map eth::c_instructionInfo = -{ - { Instruction::STOP, { "STOP", 0, 0, 0 } }, - { Instruction::ADD, { "ADD", 0, 2, 1 } }, - { Instruction::SUB, { "SUB", 0, 2, 1 } }, - { Instruction::MUL, { "MUL", 0, 2, 1 } }, - { Instruction::DIV, { "DIV", 0, 2, 1 } }, - { Instruction::SDIV, { "SDIV", 0, 2, 1 } }, - { Instruction::MOD, { "MOD", 0, 2, 1 } }, - { Instruction::SMOD, { "SMOD", 0, 2, 1 } }, - { Instruction::EXP, { "EXP", 0, 2, 1 } }, - { Instruction::NEG, { "NEG", 0, 1, 1 } }, - { Instruction::LT, { "LT", 0, 2, 1 } }, - { Instruction::GT, { "GT", 0, 2, 1 } }, - { Instruction::EQ, { "EQ", 0, 2, 1 } }, - { Instruction::NOT, { "NOT", 0, 1, 1 } }, - { Instruction::AND, { "AND", 0, 2, 1 } }, - { Instruction::OR, { "OR", 0, 2, 1 } }, - { Instruction::XOR, { "XOR", 0, 2, 1 } }, - { Instruction::BYTE, { "BYTE", 0, 2, 1 } }, - { Instruction::SHA3, { "SHA3", 0, 2, 1 } }, - { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1 } }, - { Instruction::BALANCE, { "BALANCE", 0, 1, 1 } }, - { Instruction::ORIGIN, { "ORIGIN", 0, 1, 1 } }, - { Instruction::CALLER, { "CALLER", 0, 0, 1 } }, - { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1 } }, +{ // Add, Args, Ret + { Instruction::STOP, { "STOP", 0, 0, 0 } }, + { Instruction::ADD, { "ADD", 0, 2, 1 } }, + { Instruction::SUB, { "SUB", 0, 2, 1 } }, + { Instruction::MUL, { "MUL", 0, 2, 1 } }, + { Instruction::DIV, { "DIV", 0, 2, 1 } }, + { Instruction::SDIV, { "SDIV", 0, 2, 1 } }, + { Instruction::MOD, { "MOD", 0, 2, 1 } }, + { Instruction::SMOD, { "SMOD", 0, 2, 1 } }, + { Instruction::EXP, { "EXP", 0, 2, 1 } }, + { Instruction::NEG, { "NEG", 0, 1, 1 } }, + { Instruction::LT, { "LT", 0, 2, 1 } }, + { Instruction::GT, { "GT", 0, 2, 1 } }, + { Instruction::EQ, { "EQ", 0, 2, 1 } }, + { Instruction::NOT, { "NOT", 0, 1, 1 } }, + { Instruction::AND, { "AND", 0, 2, 1 } }, + { Instruction::OR, { "OR", 0, 2, 1 } }, + { Instruction::XOR, { "XOR", 0, 2, 1 } }, + { Instruction::BYTE, { "BYTE", 0, 2, 1 } }, + { Instruction::SHA3, { "SHA3", 0, 2, 1 } }, + { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1 } }, + { Instruction::BALANCE, { "BALANCE", 0, 1, 1 } }, + { Instruction::ORIGIN, { "ORIGIN", 0, 1, 1 } }, + { Instruction::CALLER, { "CALLER", 0, 0, 1 } }, + { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1 } }, { Instruction::CALLDATALOAD, { "CALLDATALOAD", 0, 1, 1 } }, { Instruction::CALLDATASIZE, { "CALLDATASIZE", 0, 0, 1 } }, - { Instruction::GASPRICE, { "BASEFEE", 0, 0, 1 } }, - { Instruction::PREVHASH, { "PREVHASH", 0, 0, 1 } }, - { Instruction::COINBASE, { "COINBASE", 0, 0, 1 } }, - { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1 } }, - { Instruction::NUMBER, { "NUMBER", 0, 0, 1 } }, - { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1 } }, - { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1 } }, - { Instruction::POP, { "POP", 0, 1, 0 } }, - { Instruction::DUP, { "DUP", 0, 1, 2 } }, - { Instruction::SWAP, { "SWAP", 0, 2, 2 } }, - { Instruction::MLOAD, { "MLOAD", 0, 1, 1 } }, - { Instruction::MSTORE, { "MSTORE", 0, 2, 0 } }, - { Instruction::MSTORE8, { "MSTORE8", 0, 2, 0 } }, - { Instruction::SLOAD, { "SLOAD", 0, 1, 1 } }, - { Instruction::SSTORE, { "SSTORE", 0, 2, 0 } }, - { Instruction::JUMP, { "JUMP", 0, 1, 0 } }, - { Instruction::JUMPI, { "JUMPI", 0, 2, 0 } }, - { Instruction::PC, { "PC", 0, 0, 1 } }, - { Instruction::MEMSIZE, { "MEMSIZE", 0, 0, 1 } }, - { Instruction::GAS, { "GAS", 0, 0, 1 } }, - { Instruction::PUSH1, { "PUSH1", 1, 0, 1 } }, - { Instruction::PUSH2, { "PUSH2", 2, 0, 1 } }, - { Instruction::PUSH3, { "PUSH3", 3, 0, 1 } }, - { Instruction::PUSH4, { "PUSH4", 4, 0, 1 } }, - { Instruction::PUSH5, { "PUSH5", 5, 0, 1 } }, - { Instruction::PUSH6, { "PUSH6", 6, 0, 1 } }, - { Instruction::PUSH7, { "PUSH7", 7, 0, 1 } }, - { Instruction::PUSH8, { "PUSH8", 8, 0, 1 } }, - { Instruction::PUSH9, { "PUSH9", 9, 0, 1 } }, - { Instruction::PUSH10, { "PUSH10", 10, 0, 1 } }, - { Instruction::PUSH11, { "PUSH11", 11, 0, 1 } }, - { Instruction::PUSH12, { "PUSH12", 12, 0, 1 } }, - { Instruction::PUSH13, { "PUSH13", 13, 0, 1 } }, - { Instruction::PUSH14, { "PUSH14", 14, 0, 1 } }, - { Instruction::PUSH15, { "PUSH15", 15, 0, 1 } }, - { Instruction::PUSH16, { "PUSH16", 16, 0, 1 } }, - { Instruction::PUSH17, { "PUSH17", 17, 0, 1 } }, - { Instruction::PUSH18, { "PUSH18", 18, 0, 1 } }, - { Instruction::PUSH19, { "PUSH19", 19, 0, 1 } }, - { Instruction::PUSH20, { "PUSH20", 20, 0, 1 } }, - { Instruction::PUSH21, { "PUSH21", 21, 0, 1 } }, - { Instruction::PUSH22, { "PUSH22", 22, 0, 1 } }, - { Instruction::PUSH23, { "PUSH23", 23, 0, 1 } }, - { Instruction::PUSH24, { "PUSH24", 24, 0, 1 } }, - { Instruction::PUSH25, { "PUSH25", 25, 0, 1 } }, - { Instruction::PUSH26, { "PUSH26", 26, 0, 1 } }, - { Instruction::PUSH27, { "PUSH27", 27, 0, 1 } }, - { Instruction::PUSH28, { "PUSH28", 28, 0, 1 } }, - { Instruction::PUSH29, { "PUSH29", 29, 0, 1 } }, - { Instruction::PUSH30, { "PUSH30", 30, 0, 1 } }, - { Instruction::PUSH31, { "PUSH31", 31, 0, 1 } }, - { Instruction::PUSH32, { "PUSH32", 32, 0, 1 } }, - { Instruction::CREATE, { "CREATE", 0, 3, 1 } }, - { Instruction::CALL, { "CALL", 0, 7, 1 } }, - { Instruction::RETURN, { "RETURN", 0, 2, 0 } }, - { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} } + { Instruction::GASPRICE, { "BASEFEE", 0, 0, 1 } }, + { Instruction::PREVHASH, { "PREVHASH", 0, 0, 1 } }, + { Instruction::COINBASE, { "COINBASE", 0, 0, 1 } }, + { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1 } }, + { Instruction::NUMBER, { "NUMBER", 0, 0, 1 } }, + { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1 } }, + { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1 } }, + { Instruction::POP, { "POP", 0, 1, 0 } }, + { Instruction::DUP, { "DUP", 0, 1, 2 } }, + { Instruction::SWAP, { "SWAP", 0, 2, 2 } }, + { Instruction::MLOAD, { "MLOAD", 0, 1, 1 } }, + { Instruction::MSTORE, { "MSTORE", 0, 2, 0 } }, + { Instruction::MSTORE8, { "MSTORE8", 0, 2, 0 } }, + { Instruction::SLOAD, { "SLOAD", 0, 1, 1 } }, + { Instruction::SSTORE, { "SSTORE", 0, 2, 0 } }, + { Instruction::JUMP, { "JUMP", 0, 1, 0 } }, + { Instruction::JUMPI, { "JUMPI", 0, 2, 0 } }, + { Instruction::PC, { "PC", 0, 0, 1 } }, + { Instruction::MEMSIZE, { "MEMSIZE", 0, 0, 1 } }, + { Instruction::GAS, { "GAS", 0, 0, 1 } }, + { Instruction::PUSH1, { "PUSH1", 1, 0, 1 } }, + { Instruction::PUSH2, { "PUSH2", 2, 0, 1 } }, + { Instruction::PUSH3, { "PUSH3", 3, 0, 1 } }, + { Instruction::PUSH4, { "PUSH4", 4, 0, 1 } }, + { Instruction::PUSH5, { "PUSH5", 5, 0, 1 } }, + { Instruction::PUSH6, { "PUSH6", 6, 0, 1 } }, + { Instruction::PUSH7, { "PUSH7", 7, 0, 1 } }, + { Instruction::PUSH8, { "PUSH8", 8, 0, 1 } }, + { Instruction::PUSH9, { "PUSH9", 9, 0, 1 } }, + { Instruction::PUSH10, { "PUSH10", 10, 0, 1 } }, + { Instruction::PUSH11, { "PUSH11", 11, 0, 1 } }, + { Instruction::PUSH12, { "PUSH12", 12, 0, 1 } }, + { Instruction::PUSH13, { "PUSH13", 13, 0, 1 } }, + { Instruction::PUSH14, { "PUSH14", 14, 0, 1 } }, + { Instruction::PUSH15, { "PUSH15", 15, 0, 1 } }, + { Instruction::PUSH16, { "PUSH16", 16, 0, 1 } }, + { Instruction::PUSH17, { "PUSH17", 17, 0, 1 } }, + { Instruction::PUSH18, { "PUSH18", 18, 0, 1 } }, + { Instruction::PUSH19, { "PUSH19", 19, 0, 1 } }, + { Instruction::PUSH20, { "PUSH20", 20, 0, 1 } }, + { Instruction::PUSH21, { "PUSH21", 21, 0, 1 } }, + { Instruction::PUSH22, { "PUSH22", 22, 0, 1 } }, + { Instruction::PUSH23, { "PUSH23", 23, 0, 1 } }, + { Instruction::PUSH24, { "PUSH24", 24, 0, 1 } }, + { Instruction::PUSH25, { "PUSH25", 25, 0, 1 } }, + { Instruction::PUSH26, { "PUSH26", 26, 0, 1 } }, + { Instruction::PUSH27, { "PUSH27", 27, 0, 1 } }, + { Instruction::PUSH28, { "PUSH28", 28, 0, 1 } }, + { Instruction::PUSH29, { "PUSH29", 29, 0, 1 } }, + { Instruction::PUSH30, { "PUSH30", 30, 0, 1 } }, + { Instruction::PUSH31, { "PUSH31", 31, 0, 1 } }, + { Instruction::PUSH32, { "PUSH32", 32, 0, 1 } }, + { Instruction::CREATE, { "CREATE", 0, 3, 1 } }, + { Instruction::CALL, { "CALL", 0, 7, 1 } }, + { Instruction::RETURN, { "RETURN", 0, 2, 0 } }, + { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} } }; static string readQuoted(char const*& o_d, char const* _e) diff --git a/test/crypto.cpp b/test/crypto.cpp index 7896a0b13..5dac1fced 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -26,9 +26,38 @@ #include #include #include +#include + using namespace std; using namespace eth; + +BOOST_AUTO_TEST_CASE(crypto_tests) +{ + cnote << "Testing Crypto..."; + secp256k1_start(); + + KeyPair p(Secret(fromHex("3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4"))); + BOOST_REQUIRE(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f"))); + BOOST_REQUIRE(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))); + { + Transaction t; + t.nonce = 0; + t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")); + t.value = 1000; + cnote << RLP(t.rlp(false)); + cnote << toHex(t.rlp(false)); + cnote << t.sha3(false); + t.sign(p.secret()); + cnote << RLP(t.rlp(true)); + cnote << toHex(t.rlp(true)); + cnote << t.sha3(true); + BOOST_REQUIRE(t.sender() == p.address()); + } + +} + + int cryptoTest() { cnote << "Testing Crypto..."; diff --git a/test/hexPrefix.cpp b/test/hexPrefix.cpp index 0db8e75e9..a3de61d2e 100644 --- a/test/hexPrefix.cpp +++ b/test/hexPrefix.cpp @@ -24,47 +24,29 @@ #include "JsonSpiritHeaders.h" #include "TrieCommon.h" #include "Log.h" +#include + using namespace std; using namespace eth; namespace js = json_spirit; -namespace eth -{ - -template <> class UnitTest<3> +BOOST_AUTO_TEST_CASE(hexPrefix_test) { -public: - int operator()() + cnote << "Testing Hex-Prefix-Encode..."; + js::mValue v; + string s = asString(contents("../../tests/hexencodetest.json")); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content from 'hexencodetest.json' is empty. Have you cloned the 'tests' repo branch develop?"); + js::read_string(s, v); + for (auto& i: v.get_obj()) { - js::mValue v; - string s = asString(contents("../../tests/hexencodetest.json")); - js::read_string(s, v); - bool passed = true; - for (auto& i: v.get_obj()) - { - js::mObject& o = i.second.get_obj(); - cnote << i.first; - bytes v; - for (auto& i: o["seq"].get_array()) - v.push_back((byte)i.get_int()); - auto e = hexPrefixEncode(v, o["term"].get_bool()); - if (!o["out"].is_null() && o["out"].get_str() != toHex(e)) - { - cwarn << "Test failed."; - cwarn << "Test says:" << o["out"].get_str(); - cwarn << "Impl says:" << toHex(e); - passed = false; - } - } - return passed ? 0 : 1; + js::mObject& o = i.second.get_obj(); + cnote << i.first; + bytes v; + for (auto& i: o["seq"].get_array()) + v.push_back((byte)i.get_int()); + auto e = hexPrefixEncode(v, o["term"].get_bool()); + BOOST_REQUIRE( ! o["out"].is_null() ); + BOOST_CHECK( o["out"].get_str() == toHex(e) ); } - -}; - } -int hexPrefixTest() -{ - cnote << "Testing Hex-Prefix-Encode..."; - return UnitTest<3>()(); -} diff --git a/test/main.cpp b/test/main.cpp index 4cfb71ced..4205c6a44 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -45,14 +45,10 @@ BOOST_AUTO_TEST_CASE(basic_tests) std::cout << sha3(s.out()) << std::endl;*/ int r = 0; - r += hexPrefixTest(); - r += rlpTest(); - r += trieTest(); - r += vmTest(); - r += cryptoTest(); // TODO: Put in tests repo. + // r += daggerTest(); // r += stateTest(); // r += peerTest(argc, argv); - BOOST_REQUIRE(!r); +// BOOST_REQUIRE(!r); } diff --git a/test/rlp.cpp b/test/rlp.cpp index f6c244423..1271d7ff9 100644 --- a/test/rlp.cpp +++ b/test/rlp.cpp @@ -21,69 +21,173 @@ */ #include +#include #include "JsonSpiritHeaders.h" #include #include +#include +#include +#include + using namespace std; using namespace eth; namespace js = json_spirit; -namespace eth -{ - -template <> class UnitTest<2> +namespace eth { -public: - static void buildRLP(js::mValue& _v, RLPStream& _rlp) + namespace test { - if (_v.type() == js::array_type) + static void buildRLP(js::mValue& _v, RLPStream& _rlp) { - RLPStream s; - for (auto& i: _v.get_array()) - buildRLP(i, s); - _rlp.appendList(s.out()); + if (_v.type() == js::array_type) + { + RLPStream s; + for (auto& i: _v.get_array()) + buildRLP(i, s); + _rlp.appendList(s.out()); + } + else if (_v.type() == js::int_type) + _rlp.append(_v.get_uint64()); + else if (_v.type() == js::str_type) + { + auto s = _v.get_str(); + if (s.size() && s[0] == '#') + _rlp.append(bigint(s.substr(1))); + else + _rlp.append(s); + } } - else if (_v.type() == js::int_type) - _rlp.append(_v.get_uint64()); - else if (_v.type() == js::str_type) + + static void getRLPTestCases(js::mValue& v) { - auto s = _v.get_str(); - if (s.size() && s[0] == '#') - _rlp.append(bigint(s.substr(1))); - else - _rlp.append(s); - } - } + string s = asString(contents("../../tests/rlptest.json")); + BOOST_REQUIRE_MESSAGE( s.length() > 0, + "Contents of 'rlptest.json' is empty. Have you cloned the 'tests' repo branch develop?"); + js::read_string(s, v); + } - int operator()() - { - js::mValue v; - string s = asString(contents("../../tests/rlptest.json")); - js::read_string(s, v); - bool passed = true; - for (auto& i: v.get_obj()) + static void checkRLPTestCase(js::mObject& o) + { + BOOST_REQUIRE( o.count("in") > 0 ); + BOOST_REQUIRE( o.count("out") > 0 ); + BOOST_REQUIRE(!o["out"].is_null()); + } + + static void checkRLPAgainstJson(js::mValue& v, RLP& u) { - js::mObject& o = i.second.get_obj(); - cnote << i.first; - RLPStream s; - buildRLP(o["in"], s); - if (!o["out"].is_null() && o["out"].get_str() != toHex(s.out())) - { - cwarn << "Test failed."; - cwarn << "Test says:" << o["out"].get_str(); - cwarn << "Impl says:" << toHex(s.out()); - passed = false; - } - } - return passed ? 0 : 1; + if ( v.type() == js::str_type ) + { + const std::string& expectedText = v.get_str(); + if ( expectedText.front() == '#' ) + { + // Deal with bigint instead of a raw string + std::string bigIntStr = expectedText.substr(1,expectedText.length()-1); + std::stringstream bintStream(bigIntStr); + bigint val; + bintStream >> val; + BOOST_CHECK( !u.isList() ); + BOOST_CHECK( !u.isNull() ); + BOOST_CHECK( u ); // operator bool() + BOOST_CHECK(u == val); + } + else + { + BOOST_CHECK( !u.isList() ); + BOOST_CHECK( !u.isNull() ); + BOOST_CHECK( u.isData() ); + BOOST_CHECK( u ); + BOOST_CHECK( u.size() == expectedText.length() ); + BOOST_CHECK(u == expectedText); + } + } + else if ( v.type() == js::int_type ) + { + const int expectedValue = v.get_int(); + BOOST_CHECK( u.isInt() ); + BOOST_CHECK( !u.isList() ); + BOOST_CHECK( !u.isNull() ); + BOOST_CHECK( u ); // operator bool() + BOOST_CHECK(u == expectedValue); + } + else if ( v.type() == js::array_type ) + { + BOOST_CHECK( u.isList() ); + BOOST_CHECK( !u.isInt() ); + BOOST_CHECK( !u.isData() ); + js::mArray& arr = v.get_array(); + BOOST_CHECK( u.itemCount() == arr.size() ); + uint i; + for( i = 0; i < arr.size(); i++ ) + { + RLP item = u[i]; + checkRLPAgainstJson(arr[i], item); + } + } + else + { + BOOST_ERROR("Invalid Javascript object!"); + } + + } } +} + -}; +BOOST_AUTO_TEST_CASE(rlp_encoding_test) +{ + cnote << "Testing RLP Encoding..."; + js::mValue v; + eth::test::getRLPTestCases(v); + + for (auto& i: v.get_obj()) + { + js::mObject& o = i.second.get_obj(); + cnote << i.first; + eth::test::checkRLPTestCase(o); + + RLPStream s; + eth::test::buildRLP(o["in"], s); + + std::string expectedText(o["out"].get_str()); + std::transform(expectedText.begin(), expectedText.end(), expectedText.begin(), ::tolower ); + + const std::string& computedText = toHex(s.out()); + + std::stringstream msg; + msg << "Encoding Failed: expected: " << expectedText << std::endl; + msg << " But Computed: " << computedText; + + BOOST_CHECK_MESSAGE( + expectedText == computedText, + msg.str() + ); + } } -int rlpTest() +BOOST_AUTO_TEST_CASE(rlp_decoding_test) { - cnote << "Testing RLP..."; - return UnitTest<2>()(); + cnote << "Testing RLP decoding..."; + // Uses the same test cases as encoding but in reverse. + // We read into the string of hex values, convert to bytes, + // and then compare the output structure to the json of the + // input object. + js::mValue v; + eth::test::getRLPTestCases(v); + for (auto& i: v.get_obj()) + { + js::mObject& o = i.second.get_obj(); + cnote << i.first; + eth::test::checkRLPTestCase(o); + + js::mValue& inputData = o["in"]; + bytes payloadToDecode = fromHex(o["out"].get_str()); + + RLP payload(payloadToDecode); + + eth::test::checkRLPAgainstJson(inputData, payload); + + } } + + diff --git a/test/trie.cpp b/test/trie.cpp index 5e3cfcb6c..785bcc728 100644 --- a/test/trie.cpp +++ b/test/trie.cpp @@ -26,56 +26,56 @@ #include #include "TrieHash.h" #include "MemTrie.h" +#include + using namespace std; using namespace eth; namespace js = json_spirit; -namespace eth -{ +namespace eth +{ + namespace test + { + static unsigned fac(unsigned _i) + { + return _i > 2 ? _i * fac(_i - 1) : _i; + } -unsigned fac(unsigned _i) { return _i > 2 ? _i * fac(_i - 1) : _i; } + } +} -template <> class UnitTest<4> + +BOOST_AUTO_TEST_CASE(trie_tests) { -public: - int operator()() + cnote << "Testing Trie..."; + + js::mValue v; + string s = asString(contents("../../tests/trietest.json")); + BOOST_REQUIRE_MESSAGE( s.length() > 0, "Contents of 'trietest.json' is empty. Have you cloned the 'tests' repo branch develop?"); + js::read_string(s, v); + for (auto& i: v.get_obj()) { - js::mValue v; - string s = asString(contents("../../tests/trietest.json")); - js::read_string(s, v); - bool passed = true; - for (auto& i: v.get_obj()) + js::mObject& o = i.second.get_obj(); + cnote << i.first; + vector> ss; + for (auto& i: o["in"].get_obj()) + ss.push_back(make_pair(i.first, i.second.get_str())); + for (unsigned j = 0; j < eth::test::fac((unsigned)ss.size()); ++j) { - js::mObject& o = i.second.get_obj(); - cnote << i.first; - vector> ss; - for (auto& i: o["in"].get_obj()) - ss.push_back(make_pair(i.first, i.second.get_str())); - for (unsigned j = 0; j < fac((unsigned)ss.size()); ++j) - { - next_permutation(ss.begin(), ss.end()); - BasicMap m; - GenericTrieDB t(&m); - t.init(); - for (auto const& k: ss) - t.insert(k.first, k.second); - if (!o["root"].is_null() && o["root"].get_str() != toHex(t.root().asArray())) - { - cwarn << "Test failed on permutation " << j; - cwarn << "Test says:" << o["root"].get_str(); - cwarn << "Impl says:" << toHex(t.root().asArray()); - passed = false; - } - } + next_permutation(ss.begin(), ss.end()); + BasicMap m; + GenericTrieDB t(&m); + t.init(); + for (auto const& k: ss) + t.insert(k.first, k.second); + BOOST_REQUIRE(!o["root"].is_null()); + BOOST_CHECK(o["root"].get_str() == toHex(t.root().asArray()) ); } - return passed ? 0 : 1; } - -}; - } + inline h256 stringMapHash256(StringMap const& _s) { return hash256(_s); @@ -83,8 +83,6 @@ inline h256 stringMapHash256(StringMap const& _s) int trieTest() { - cnote << "Testing Trie..."; - return UnitTest<4>()(); // More tests... { diff --git a/test/vm.cpp b/test/vm.cpp index a0b268639..a3242b573 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -27,12 +27,13 @@ #include #include #include "JsonSpiritHeaders.h" +#include + using namespace std; using namespace json_spirit; using namespace eth; -namespace eth -{ +namespace eth { namespace test { class FakeExtVM: public ExtVMFace { @@ -135,6 +136,12 @@ public: void importEnv(mObject& _o) { + BOOST_REQUIRE(_o.count("previousHash") > 0 ); + BOOST_REQUIRE(_o.count("previousNonce") > 0 ); + BOOST_REQUIRE(_o.count("currentDifficulty") > 0 ); + BOOST_REQUIRE(_o.count("currentTimestamp") > 0 ); + BOOST_REQUIRE(_o.count("currentCoinbase") > 0 ); + previousBlock.hash = h256(_o["previousHash"].get_str()); previousBlock.nonce = h256(_o["previousNonce"].get_str()); currentBlock.difficulty = toInt(_o["currentDifficulty"]); @@ -228,6 +235,10 @@ public: for (auto const& i: _o) { mObject o = i.second.get_obj(); + BOOST_REQUIRE(o.count("balance") > 0 ); + BOOST_REQUIRE(o.count("nonce") > 0 ); + BOOST_REQUIRE(o.count("store") > 0 ); + auto& a = addresses[Address(i.first)]; get<0>(a) = toInt(o["balance"]); get<1>(a) = toInt(o["nonce"]); @@ -249,6 +260,7 @@ public: mObject exportExec() { + mObject ret; ret["address"] = toString(myAddress); ret["caller"] = toString(caller); @@ -264,6 +276,13 @@ public: void importExec(mObject& _o) { + BOOST_REQUIRE(_o.count("address")> 0); + BOOST_REQUIRE(_o.count("caller") > 0); + BOOST_REQUIRE(_o.count("origin") > 0); + BOOST_REQUIRE(_o.count("value") > 0); + BOOST_REQUIRE(_o.count("gasPrice") > 0); + BOOST_REQUIRE(_o.count("data") > 0 ); + myAddress = Address(_o["address"].get_str()); caller = Address(_o["caller"].get_str()); origin = Address(_o["origin"].get_str()); @@ -297,6 +316,9 @@ public: for (mValue& v: _txs) { auto tx = v.get_obj(); + BOOST_REQUIRE(tx.count("destination") > 0); + BOOST_REQUIRE(tx.count("value") > 0 ); + BOOST_REQUIRE(tx.count("data") > 0 ); Transaction t; t.receiveAddress = Address(tx["destination"].get_str()); t.value = toInt(tx["value"]); @@ -311,37 +333,20 @@ public: bytes thisTxData; }; -#define CREATE_TESTS 0 - -template <> class UnitTest<1> -{ -public: - int operator()() + void doTests(json_spirit::mValue& v, bool _fillin) { - json_spirit::mValue v; -#if CREATE_TESTS - string s = asString(contents("../../cpp-ethereum/test/vmtests.json")); - json_spirit::read_string(s, v); - bool passed = doTests(v, true); - cout << json_spirit::write_string(v, true) << endl; -#else - string s = asString(contents("../../tests/vmtests.json")); - json_spirit::read_string(s, v); - bool passed = doTests(v, false); -#endif - return passed ? 0 : 1; - } - - bool doTests(json_spirit::mValue& v, bool _fillin) - { - bool passed = true; for (auto& i: v.get_obj()) + { cnote << i.first; mObject& o = i.second.get_obj(); + BOOST_REQUIRE( o.count("env") > 0 ); + BOOST_REQUIRE( o.count("pre") > 0 ); + BOOST_REQUIRE( o.count("exec") > 0 ); + VM vm; - FakeExtVM fev; + eth::test::FakeExtVM fev; fev.importEnv(o["env"].get_obj()); fev.importState(o["pre"].get_obj()); @@ -365,37 +370,44 @@ public: } else { - FakeExtVM test; + BOOST_REQUIRE( o.count("post") > 0 ); + BOOST_REQUIRE( o.count("txs") > 0 ); + BOOST_REQUIRE( o.count("out") > 0 ); + + eth::test::FakeExtVM test; test.importState(o["post"].get_obj()); test.importTxs(o["txs"].get_array()); int i = 0; for (auto const& d: o["out"].get_array()) { - if (output[i] != FakeExtVM::toInt(d)) - { - cwarn << "Test failed: output byte" << i << "different."; - passed = false; - } + BOOST_CHECK_MESSAGE( output[i] == FakeExtVM::toInt(d), "Output byte [" << i << "] different!"); ++i; } - - if (test.addresses != fev.addresses) - { - cwarn << "Test failed: state different."; - passed = false; - } - if (test.txs != fev.txs) - { - cwarn << "Test failed: tx list different:"; - cwarn << test.txs; - cwarn << fev.txs; - passed = false; - } + BOOST_CHECK( test.addresses == fev.addresses); + BOOST_CHECK( test.txs == fev.txs ); } } - return passed; } +} } // Namespace Close +BOOST_AUTO_TEST_CASE(vm_tests) +{ + try + { + cnote << "Testing VM..."; + json_spirit::mValue v; + string s = asString(contents("../../tests/vmtests.json")); + BOOST_REQUIRE_MESSAGE( s.length() > 0, "Contents of 'vmtests.json' is empty. Have you cloned the 'tests' repo branch develop?" ); + json_spirit::read_string(s, v); + eth::test::doTests(v, false); + } + catch( std::exception& e) + { + BOOST_ERROR("Failed VM Test with Exception: " << e.what()); + } +} + +#if 0 string makeTestCase() { json_spirit::mObject o; @@ -427,9 +439,5 @@ public: } -int vmTest() -{ - cnote << "Testing VM..."; - return UnitTest<1>()(); -} +#endif