From 272bd3c60c17fbe2444abcb816bc831f1382afe7 Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 23 Mar 2015 15:26:48 +0100 Subject: [PATCH 01/35] gracefully handle old pingnode packet --- net.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net.cpp b/net.cpp index 23ad0fb4a..2ecfafb82 100644 --- a/net.cpp +++ b/net.cpp @@ -145,6 +145,17 @@ public: bool success = false; }; +BOOST_AUTO_TEST_CASE(badPingNodePacket) +{ + // test old versino of pingNode packet w/new + RLPStream s; + s.appendList(3); s << "1.1.1.1" << 30303 << std::chrono::duration_cast((std::chrono::system_clock::now() + chrono::seconds(60)).time_since_epoch()).count(); + + PingNode p((bi::udp::endpoint())); + BOOST_REQUIRE_NO_THROW(p = PingNode::fromBytesConstRef(bi::udp::endpoint(), bytesConstRef(&s.out()))); + BOOST_REQUIRE(p.version = 0); +} + BOOST_AUTO_TEST_CASE(test_neighbours_packet) { KeyPair k = KeyPair::create(); From e6a1ca28e5ff0fa59b6e4f3f033c84fd76a111cf Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 23 Mar 2015 15:31:03 +0100 Subject: [PATCH 02/35] fix test typo --- net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net.cpp b/net.cpp index 2ecfafb82..7ba2d8a12 100644 --- a/net.cpp +++ b/net.cpp @@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(badPingNodePacket) PingNode p((bi::udp::endpoint())); BOOST_REQUIRE_NO_THROW(p = PingNode::fromBytesConstRef(bi::udp::endpoint(), bytesConstRef(&s.out()))); - BOOST_REQUIRE(p.version = 0); + BOOST_REQUIRE(p.version == 0); } BOOST_AUTO_TEST_CASE(test_neighbours_packet) From 158666a2c5306436c5eedc96fb56c1861d842fce Mon Sep 17 00:00:00 2001 From: winsvega Date: Mon, 23 Mar 2015 17:52:34 +0300 Subject: [PATCH 03/35] Transaction Data Must Be Array +libsecp256k1test --- ttTransactionTestFiller.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ttTransactionTestFiller.json b/ttTransactionTestFiller.json index 105b64abc..4f8005c5f 100644 --- a/ttTransactionTestFiller.json +++ b/ttTransactionTestFiller.json @@ -511,6 +511,7 @@ "s" : "0x8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3" } }, + "unpadedRValue": { "transaction": { "nonce": "13", @@ -523,5 +524,19 @@ "v": "28", "value": "" } + }, + + "libsecp256k1test": { + "transaction": { + "nonce": "", + "gasPrice": "0x09184e72a000", + "gasLimit": "0x1388", + "to": "", + "data": "", + "r": "44", + "s": "4", + "v": "27", + "value": "" + } } } From 1806dcf33cc56760786375bddf1a82b5d07d41ac Mon Sep 17 00:00:00 2001 From: winsvega Date: Mon, 23 Mar 2015 23:50:04 +0300 Subject: [PATCH 04/35] Exceptions --- transaction.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/transaction.cpp b/transaction.cpp index 77f6ecdaf..4c57326ba 100644 --- a/transaction.cpp +++ b/transaction.cpp @@ -48,6 +48,13 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) if (!txFromRlp.signature().isValid()) BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") ); } + catch(Exception const& _e) + { + cnote << i.first; + cnote << "Transaction Exception: " << diagnostic_information(_e); + BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!"); + continue; + } catch(...) { BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!"); From 0934d0e943765c7c87cf1b3da43aa876f4f1e469 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 19 Mar 2015 18:11:58 +0100 Subject: [PATCH 05/35] Code generation part 2. --- SolidityOptimizer.cpp | 163 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 140 insertions(+), 23 deletions(-) diff --git a/SolidityOptimizer.cpp b/SolidityOptimizer.cpp index 85b77d210..9c6a4e361 100644 --- a/SolidityOptimizer.cpp +++ b/SolidityOptimizer.cpp @@ -26,8 +26,11 @@ #include #include #include +#include +#include using namespace std; +using namespace dev::eth; namespace dev { @@ -41,16 +44,21 @@ class OptimizerTestFramework: public ExecutionFramework public: OptimizerTestFramework() { } /// Compiles the source code with and without optimizing. - void compileBothVersions(unsigned _expectedSizeDecrease, std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "") { + void compileBothVersions( + std::string const& _sourceCode, + u256 const& _value = 0, + std::string const& _contractName = "" + ) + { m_optimize = false; bytes nonOptimizedBytecode = compileAndRun(_sourceCode, _value, _contractName); m_nonOptimizedContract = m_contractAddress; m_optimize = true; bytes optimizedBytecode = compileAndRun(_sourceCode, _value, _contractName); - int sizeDiff = nonOptimizedBytecode.size() - optimizedBytecode.size(); - BOOST_CHECK_MESSAGE(sizeDiff == int(_expectedSizeDecrease), "Bytecode shrank by " - + boost::lexical_cast(sizeDiff) + " bytes, expected: " - + boost::lexical_cast(_expectedSizeDecrease)); + BOOST_CHECK_MESSAGE( + nonOptimizedBytecode.size() > optimizedBytecode.size(), + "Optimizer did not reduce bytecode size." + ); m_optimizedContract = m_contractAddress; } @@ -81,24 +89,11 @@ BOOST_AUTO_TEST_CASE(smoke_test) return a; } })"; - compileBothVersions(29, sourceCode); + compileBothVersions(sourceCode); compareVersions("f(uint256)", u256(7)); } -BOOST_AUTO_TEST_CASE(large_integers) -{ - char const* sourceCode = R"( - contract test { - function f() returns (uint a, uint b) { - a = 0x234234872642837426347000000; - b = 0x10000000000000000000000002; - } - })"; - compileBothVersions(36, sourceCode); - compareVersions("f()"); -} - -BOOST_AUTO_TEST_CASE(invariants) +BOOST_AUTO_TEST_CASE(identities) { char const* sourceCode = R"( contract test { @@ -106,7 +101,7 @@ BOOST_AUTO_TEST_CASE(invariants) return int(0) | (int(1) * (int(0) ^ (0 + a))); } })"; - compileBothVersions(41, sourceCode); + compileBothVersions(sourceCode); compareVersions("f(uint256)", u256(0x12334664)); } @@ -120,7 +115,7 @@ BOOST_AUTO_TEST_CASE(unused_expressions) data; } })"; - compileBothVersions(36, sourceCode); + compileBothVersions(sourceCode); compareVersions("f()"); } @@ -135,10 +130,132 @@ BOOST_AUTO_TEST_CASE(constant_folding_both_sides) return 98 ^ (7 * ((1 | (x | 1000)) * 40) ^ 102); } })"; - compileBothVersions(37, sourceCode); + compileBothVersions(sourceCode); compareVersions("f(uint256)"); } +BOOST_AUTO_TEST_CASE(storage_access) +{ + char const* sourceCode = R"( + contract test { + uint8[40] data; + function f(uint x) returns (uint y) { + data[2] = data[7] = uint8(x); + data[4] = data[2] * 10 + data[3]; + } + } + )"; + compileBothVersions(sourceCode); + compareVersions("f(uint256)"); +} + +BOOST_AUTO_TEST_CASE(array_copy) +{ + char const* sourceCode = R"( + contract test { + bytes2[] data1; + bytes5[] data2; + function f(uint x) returns (uint l, uint y) { + for (uint i = 0; i < msg.data.length; ++i) + data1[i] = msg.data[i]; + data2 = data1; + l = data2.length; + y = uint(data2[x]); + } + } + )"; + compileBothVersions(sourceCode); + compareVersions("f(uint256)", 0); + compareVersions("f(uint256)", 10); + compareVersions("f(uint256)", 36); +} + +BOOST_AUTO_TEST_CASE(function_calls) +{ + char const* sourceCode = R"( + contract test { + function f1(uint x) returns (uint) { return x*x; } + function f(uint x) returns (uint) { return f1(7+x) - this.f1(x**9); } + } + )"; + compileBothVersions(sourceCode); + compareVersions("f(uint256)", 0); + compareVersions("f(uint256)", 10); + compareVersions("f(uint256)", 36); +} + +BOOST_AUTO_TEST_CASE(cse_intermediate_swap) +{ + eth::CommonSubexpressionEliminator cse; + AssemblyItems input{ + Instruction::SWAP1, Instruction::POP, Instruction::ADD, u256(0), Instruction::SWAP1, + Instruction::SLOAD, Instruction::SWAP1, u256(100), Instruction::EXP, Instruction::SWAP1, + Instruction::DIV, u256(0xff), Instruction::AND + }; + BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); + AssemblyItems output = cse.getOptimizedItems(); + BOOST_CHECK(!output.empty()); +} + +BOOST_AUTO_TEST_CASE(cse_negative_stack_access) +{ + eth::CommonSubexpressionEliminator cse; + AssemblyItems input{AssemblyItem(Instruction::DUP2), AssemblyItem(u256(0))}; + BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); + AssemblyItems output = cse.getOptimizedItems(); + BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); +} + +BOOST_AUTO_TEST_CASE(cse_negative_stack_end) +{ + eth::CommonSubexpressionEliminator cse; + AssemblyItems input{ + AssemblyItem(Instruction::ADD) + }; + BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); + AssemblyItems output = cse.getOptimizedItems(); + BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); +} + +BOOST_AUTO_TEST_CASE(cse_intermediate_negative_stack) +{ + eth::CommonSubexpressionEliminator cse; + AssemblyItems input{ + AssemblyItem(Instruction::ADD), + AssemblyItem(u256(1)), + AssemblyItem(Instruction::DUP2) + }; + BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); + AssemblyItems output = cse.getOptimizedItems(); + BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); +} + +BOOST_AUTO_TEST_CASE(cse_pop) +{ + eth::CommonSubexpressionEliminator cse; + AssemblyItems input{ + AssemblyItem(Instruction::POP) + }; + BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); + AssemblyItems output = cse.getOptimizedItems(); + BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); +} + +BOOST_AUTO_TEST_CASE(cse_unneeded_items) +{ + eth::CommonSubexpressionEliminator cse; + AssemblyItems input{ + AssemblyItem(Instruction::ADD), + AssemblyItem(Instruction::SWAP1), + AssemblyItem(Instruction::POP), + AssemblyItem(u256(7)), + AssemblyItem(u256(8)), + }; + BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); + AssemblyItems output = cse.getOptimizedItems(); + BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); +} + BOOST_AUTO_TEST_SUITE_END() } From 94e4f410e9fd9257b7ccddcc8ce3b6d4c68798f9 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 25 Mar 2015 10:59:46 +0100 Subject: [PATCH 06/35] ClientBase tests --- CMakeLists.txt | 24 ++++++ ClientBase.cpp | 202 +++++++++++++++++++++++++++++++++++++++++++++++++ TestHelper.cpp | 16 ---- TestHelper.h | 2 +- TestUtils.cpp | 130 +++++++++++++++++++++++++++++++ TestUtils.h | 82 ++++++++++++++++++++ 6 files changed, 439 insertions(+), 17 deletions(-) create mode 100644 ClientBase.cpp create mode 100644 TestUtils.cpp create mode 100644 TestUtils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ef292c2bb..66b95adad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ target_link_libraries(testeth ethereum) target_link_libraries(testeth ethcore) target_link_libraries(testeth secp256k1) target_link_libraries(testeth solidity) +target_link_libraries(testeth testutils) if (NOT HEADLESS AND NOT JUSTTESTS) target_link_libraries(testeth webthree) target_link_libraries(testeth natspec) @@ -42,13 +43,36 @@ endif() target_link_libraries(createRandomVMTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(createRandomVMTest ethereum) target_link_libraries(createRandomVMTest ethcore) +target_link_libraries(createRandomVMTest testutils) target_link_libraries(createRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(createRandomStateTest ethereum) target_link_libraries(createRandomStateTest ethcore) +target_link_libraries(createRandomStateTest testutils) target_link_libraries(checkRandomVMTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(checkRandomVMTest ethereum) target_link_libraries(checkRandomVMTest ethcore) +target_link_libraries(checkRandomVMTest testutils) target_link_libraries(checkRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) target_link_libraries(checkRandomStateTest ethereum) target_link_libraries(checkRandomStateTest ethcore) +target_link_libraries(checkRandomStateTest testutils) + +enable_testing() +set(CTEST_OUTPUT_ON_FAILURE TRUE) + +include(EthUtils) + +eth_add_test(ClientBase + ARGS --eth_testfile=BlockTests/bcJS_API_Test --eth_threads=1 + ARGS --eth_testfile=BlockTests/bcJS_API_Test --eth_threads=3 + ARGS --eth_testfile=BlockTests/bcJS_API_Test --eth_threads=10 + ARGS --eth_testfile=BlockTests/bcValidBlockTest --eth_threads=1 + ARGS --eth_testfile=BlockTests/bcValidBlockTest --eth_threads=3 + ARGS --eth_testfile=BlockTests/bcValidBlockTest --eth_threads=10 +) + +eth_add_test(JsonRpc + ARGS --eth_testfile=BlockTests/bcJS_API_Test + ARGS --eth_testfile=BlockTests/bcValidBlockTest +) diff --git a/ClientBase.cpp b/ClientBase.cpp new file mode 100644 index 000000000..2197ac830 --- /dev/null +++ b/ClientBase.cpp @@ -0,0 +1,202 @@ +/* + 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 ClientBase.cpp + * @author Marek Kotewicz + * @date 2015 + */ + +#include +#include +#include "TestUtils.h" + +using namespace std; +using namespace dev; +using namespace dev::eth; +using namespace dev::test; + +BOOST_FIXTURE_TEST_SUITE(ClientBase, ParallelClientBaseFixture) + +BOOST_AUTO_TEST_CASE(blocks) +{ + enumerateClients([](Json::Value const& _json, dev::eth::ClientBase& _client) -> void + { + for (string const& name: _json["postState"].getMemberNames()) + { + Json::Value o = _json["postState"][name]; + Address address(name); + + // balanceAt + u256 expectedBalance = u256(o["balance"].asString()); + u256 balance = _client.balanceAt(address); + ETH_CHECK_EQUAL(expectedBalance, balance); + + // countAt + u256 expectedCount = u256(o["nonce"].asString()); + u256 count = _client.countAt(address); + ETH_CHECK_EQUAL(expectedCount, count); + + // stateAt + for (string const& pos: o["storage"].getMemberNames()) + { + u256 expectedState = u256(o["storage"][pos].asString()); + u256 state = _client.stateAt(address, u256(pos)); + ETH_CHECK_EQUAL(expectedState, state); + } + + // codeAt + bytes expectedCode = fromHex(o["code"].asString()); + bytes code = _client.codeAt(address); + ETH_CHECK_EQUAL_COLLECTIONS(expectedCode.begin(), expectedCode.end(), + code.begin(), code.end()); + } + + // number + unsigned expectedNumber = _json["blocks"].size(); + unsigned number = _client.number(); + ETH_CHECK_EQUAL(expectedNumber, number); + + u256 totalDifficulty = u256(_json["genesisBlockHeader"]["difficulty"].asString()); + for (Json::Value const& block: _json["blocks"]) + { + Json::Value blockHeader = block["blockHeader"]; + Json::Value uncles = block["uncleHeaders"]; + Json::Value transactions = block["transactions"]; + h256 blockHash = h256(fromHex(blockHeader["hash"].asString())); + + // just update the difficulty + for (Json::Value const& uncle: uncles) + { + totalDifficulty += u256(uncle["difficulty"].asString()); + } + + // hashFromNumber + h256 expectedHashFromNumber = h256(fromHex(blockHeader["hash"].asString())); + h256 hashFromNumber = _client.hashFromNumber(jsToInt(blockHeader["number"].asString())); + ETH_CHECK_EQUAL(expectedHashFromNumber, hashFromNumber); + + // blockInfo + auto compareBlockInfos = [](Json::Value const& _b, BlockInfo _blockInfo) -> void + { + LogBloom expectedBlockInfoBloom = LogBloom(fromHex(_b["bloom"].asString())); + Address expectedBlockInfoCoinbase = Address(fromHex(_b["coinbase"].asString())); + u256 expectedBlockInfoDifficulty = u256(_b["difficulty"].asString()); + bytes expectedBlockInfoExtraData = fromHex(_b["extraData"].asString()); + u256 expectedBlockInfoGasLimit = u256(_b["gasLimit"].asString()); + u256 expectedBlockInfoGasUsed = u256(_b["gasUsed"].asString()); + h256 expectedBlockInfoHash = h256(fromHex(_b["hash"].asString())); + h256 expectedBlockInfoMixHash = h256(fromHex(_b["mixHash"].asString())); + Nonce expectedBlockInfoNonce = Nonce(fromHex(_b["nonce"].asString())); + u256 expectedBlockInfoNumber = u256(_b["number"].asString()); + h256 expectedBlockInfoParentHash = h256(fromHex(_b["parentHash"].asString())); + h256 expectedBlockInfoReceiptsRoot = h256(fromHex(_b["receiptTrie"].asString())); + u256 expectedBlockInfoTimestamp = u256(_b["timestamp"].asString()); + h256 expectedBlockInfoTransactionsRoot = h256(fromHex(_b["transactionsTrie"].asString())); + h256 expectedBlockInfoUncldeHash = h256(fromHex(_b["uncleHash"].asString())); + ETH_CHECK_EQUAL(expectedBlockInfoBloom, _blockInfo.logBloom); + ETH_CHECK_EQUAL(expectedBlockInfoCoinbase, _blockInfo.coinbaseAddress); + ETH_CHECK_EQUAL(expectedBlockInfoDifficulty, _blockInfo.difficulty); + ETH_CHECK_EQUAL_COLLECTIONS(expectedBlockInfoExtraData.begin(), expectedBlockInfoExtraData.end(), + _blockInfo.extraData.begin(), _blockInfo.extraData.end()); + ETH_CHECK_EQUAL(expectedBlockInfoGasLimit, _blockInfo.gasLimit); + ETH_CHECK_EQUAL(expectedBlockInfoGasUsed, _blockInfo.gasUsed); + ETH_CHECK_EQUAL(expectedBlockInfoHash, _blockInfo.hash); + ETH_CHECK_EQUAL(expectedBlockInfoMixHash, _blockInfo.mixHash); + ETH_CHECK_EQUAL(expectedBlockInfoNonce, _blockInfo.nonce); + ETH_CHECK_EQUAL(expectedBlockInfoNumber, _blockInfo.number); + ETH_CHECK_EQUAL(expectedBlockInfoParentHash, _blockInfo.parentHash); + ETH_CHECK_EQUAL(expectedBlockInfoReceiptsRoot, _blockInfo.receiptsRoot); + ETH_CHECK_EQUAL(expectedBlockInfoTimestamp, _blockInfo.timestamp); + ETH_CHECK_EQUAL(expectedBlockInfoTransactionsRoot, _blockInfo.transactionsRoot); + ETH_CHECK_EQUAL(expectedBlockInfoUncldeHash, _blockInfo.sha3Uncles); + }; + + BlockInfo blockInfo = _client.blockInfo(blockHash); + compareBlockInfos(blockHeader, blockInfo); + + // blockDetails + unsigned expectedBlockDetailsNumber = jsToInt(blockHeader["number"].asString()); + totalDifficulty += u256(blockHeader["difficulty"].asString()); + BlockDetails blockDetails = _client.blockDetails(blockHash); + ETH_CHECK_EQUAL(expectedBlockDetailsNumber, blockDetails.number); + ETH_CHECK_EQUAL(totalDifficulty, blockDetails.totalDifficulty); + + auto compareTransactions = [](Json::Value const& _t, Transaction _transaction) -> void + { + bytes expectedTransactionData = fromHex(_t["data"].asString()); + u256 expectedTransactionGasLimit = u256(_t["gasLimit"].asString()); + u256 expectedTransactionGasPrice = u256(_t["gasPrice"].asString()); + u256 expectedTransactionNonce = u256(_t["nonce"].asString()); + u256 expectedTransactionSignatureR = h256(fromHex(_t["r"].asString())); + u256 expectedTransactionSignatureS = h256(fromHex(_t["s"].asString())); +// unsigned expectedTransactionSignatureV = jsToInt(t["v"].asString()); + + ETH_CHECK_EQUAL_COLLECTIONS(expectedTransactionData.begin(), expectedTransactionData.end(), + _transaction.data().begin(), _transaction.data().end()); + ETH_CHECK_EQUAL(expectedTransactionGasLimit, _transaction.gas()); + ETH_CHECK_EQUAL(expectedTransactionGasPrice, _transaction.gasPrice()); + ETH_CHECK_EQUAL(expectedTransactionNonce, _transaction.nonce()); + ETH_CHECK_EQUAL(expectedTransactionSignatureR, _transaction.signature().r); + ETH_CHECK_EQUAL(expectedTransactionSignatureS, _transaction.signature().s); +// ETH_CHECK_EQUAL(expectedTransactionSignatureV, _transaction.signature().v); // 27 === 0x0, 28 === 0x1, not sure why + }; + + Transactions ts = _client.transactions(blockHash); + TransactionHashes tHashes = _client.transactionHashes(blockHash); + unsigned tsCount = _client.transactionCount(blockHash); + + ETH_REQUIRE(transactions.size() == ts.size()); + ETH_REQUIRE(transactions.size() == tHashes.size()); + + // transactionCount + ETH_CHECK_EQUAL(transactions.size(), tsCount); + + for (unsigned i = 0; i < tsCount; i++) + { + Json::Value t = transactions[i]; + + // transaction (by block hash and transaction index) + Transaction transaction = _client.transaction(blockHash, i); + compareTransactions(t, transaction); + + // transaction (by hash) + Transaction transactionByHash = _client.transaction(transaction.sha3()); + compareTransactions(t, transactionByHash); + + // transactions + compareTransactions(t, ts[i]); + + // transactionHashes + ETH_CHECK_EQUAL(transaction.sha3(), tHashes[i]); + } + + // uncleCount + unsigned usCount = _client.uncleCount(blockHash); + ETH_CHECK_EQUAL(uncles.size(), usCount); + + for (unsigned i = 0; i < usCount; i++) + { + Json::Value u = uncles[i]; + + // uncle (by hash) + BlockInfo uncle = _client.uncle(blockHash, i); + compareBlockInfos(u, uncle); + } + } + }); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/TestHelper.cpp b/TestHelper.cpp index b29c5dc3a..7dc001498 100644 --- a/TestHelper.cpp +++ b/TestHelper.cpp @@ -374,22 +374,6 @@ void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _e } } -std::string getTestPath() -{ - string testPath; - const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); - - if (ptestPath == NULL) - { - cnote << " could not find environment variable ETHEREUM_TEST_PATH \n"; - testPath = "../../../tests"; - } - else - testPath = ptestPath; - - return testPath; -} - void userDefinedTest(string testTypeFlag, std::function doTests) { for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) diff --git a/TestHelper.h b/TestHelper.h index ade20f5e4..022c715f8 100644 --- a/TestHelper.h +++ b/TestHelper.h @@ -28,6 +28,7 @@ #include "JsonSpiritHeaders.h" #include #include +#include namespace dev { @@ -138,7 +139,6 @@ void checkLog(eth::LogEntries _resultLogs, eth::LogEntries _expectedLogs); void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _expectedCallCreates); void executeTests(const std::string& _name, const std::string& _testPathAppendix, std::function doTests); -std::string getTestPath(); void userDefinedTest(std::string testTypeFlag, std::function doTests); RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj); eth::LastHashes lastHashes(u256 _currentBlockNumber); diff --git a/TestUtils.cpp b/TestUtils.cpp new file mode 100644 index 000000000..71eeadb3a --- /dev/null +++ b/TestUtils.cpp @@ -0,0 +1,130 @@ +/* + 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 TestUtils.cpp + * @author Marek Kotewicz + * @date 2015 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "TestUtils.h" + +// used methods from TestHelper: +// getTestPath +#include "TestHelper.h" + +using namespace std; +using namespace dev; +using namespace dev::eth; +using namespace dev::test; + +namespace dev +{ +namespace test +{ + +bool getCommandLineOption(std::string const& _name); +std::string getCommandLineArgument(std::string const& _name, bool _require = false); + +} +} + +bool dev::test::getCommandLineOption(string const& _name) +{ + auto argc = boost::unit_test::framework::master_test_suite().argc; + auto argv = boost::unit_test::framework::master_test_suite().argv; + bool result = false; + for (auto i = 0; !result && i < argc; ++i) + result = _name == argv[i]; + return result; +} + +std::string dev::test::getCommandLineArgument(string const& _name, bool _require) +{ + auto argc = boost::unit_test::framework::master_test_suite().argc; + auto argv = boost::unit_test::framework::master_test_suite().argv; + for (auto i = 1; i < argc; ++i) + { + string str = argv[i]; + if (_name == str.substr(0, _name.size())) + return str.substr(str.find("=") + 1); + } + if (_require) + BOOST_ERROR("Failed getting command line argument: " << _name << " from: " << argv); + return ""; +} + +bool LoadTestFileFixture::m_loaded = false; +Json::Value LoadTestFileFixture::m_json; + +LoadTestFileFixture::LoadTestFileFixture() +{ + if (!m_loaded) + { + m_json = loadJsonFromFile(toTestFilePath(getCommandLineArgument("--eth_testfile"))); + m_loaded = true; + } +} + +void ParallelFixture::enumerateThreads(std::function callback) +{ + size_t threadsCount = std::stoul(getCommandLineArgument("--eth_threads"), nullptr, 10); + + vector workers; + for (size_t i = 0; i < threadsCount; i++) + workers.emplace_back(callback); + + for_each(workers.begin(), workers.end(), [](thread &t) + { + t.join(); + }); +} + +void BlockChainFixture::enumerateBlockchains(std::function callback) +{ + for (string const& name: m_json.getMemberNames()) + { + BlockChainLoader bcl(m_json[name]); + callback(m_json[name], bcl.bc(), bcl.state()); + } +} + +void ClientBaseFixture::enumerateClients(std::function callback) +{ + enumerateBlockchains([&callback](Json::Value const& _json, BlockChain& _bc, State _state) -> void + { + FixedClient client(_bc, _state); + callback(_json, client); + }); +} + +void ParallelClientBaseFixture::enumerateClients(std::function callback) +{ + ClientBaseFixture::enumerateClients([this, &callback](Json::Value const& _json, dev::eth::ClientBase& _client) -> void + { + // json is being copied here + enumerateThreads([callback, _json, &_client]() -> void + { + callback(_json, _client); + }); + }); +} diff --git a/TestUtils.h b/TestUtils.h new file mode 100644 index 000000000..fef10e982 --- /dev/null +++ b/TestUtils.h @@ -0,0 +1,82 @@ +/* + 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 TestUtils.h + * @author Marek Kotewicz + * @date 2015 + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace dev +{ +namespace test +{ + +// should be used for multithread tests +static SharedMutex x_boostTest; +#define ETH_CHECK_EQUAL(x, y) { dev::WriteGuard(x_boostTest); BOOST_CHECK_EQUAL(x, y); } +#define ETH_CHECK_EQUAL_COLLECTIONS(xb, xe, yb, ye) { dev::WriteGuard(x_boostTest); BOOST_CHECK_EQUAL_COLLECTIONS(xb, xe, yb, ye); } +#define ETH_REQUIRE(x) { dev::WriteGuard(x_boostTest); BOOST_REQUIRE(x); } + +struct LoadTestFileFixture +{ + LoadTestFileFixture(); + + static bool m_loaded; + static Json::Value m_json; +}; + +struct ParallelFixture +{ + void enumerateThreads(std::function callback); +}; + +struct BlockChainFixture: public LoadTestFileFixture +{ + void enumerateBlockchains(std::function callback); +}; + +struct ClientBaseFixture: public BlockChainFixture +{ + void enumerateClients(std::function callback); +}; + +// important BOOST TEST do have problems with thread safety!!! +// BOOST_CHECK is not thread safe +// BOOST_MESSAGE is not thread safe +// http://boost.2283326.n4.nabble.com/Is-boost-test-thread-safe-td3471644.html +// http://lists.boost.org/boost-users/2010/03/57691.php +// worth reading +// https://codecrafter.wordpress.com/2012/11/01/c-unit-test-framework-adapter-part-3/ +struct ParallelClientBaseFixture: public ClientBaseFixture, public ParallelFixture +{ + void enumerateClients(std::function callback); +}; + +struct JsonRpcFixture: public ClientBaseFixture +{ + +}; + +} +} From 7e73fd3f45982ffcc4080c7df56a8f64d6cc91d1 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Mon, 23 Mar 2015 18:08:45 +0100 Subject: [PATCH 07/35] renamed getCanonicalSignature added externalTypes instead of types for interface functions added simple test todo testing --- SolidityNameAndTypeResolution.cpp | 36 ++++++++++++++++++++++++++++--- SolidityTypes.cpp | 1 + 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index 591cf053a..4e8166963 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -359,7 +359,7 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature) if (ContractDefinition* contract = dynamic_cast(node.get())) { auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_EQUAL("foo(uint256,uint64,bool)", functions[0]->getCanonicalSignature()); + BOOST_CHECK_EQUAL("foo(uint256,uint64,bool)", functions[0]->externalTypes()); } } @@ -376,10 +376,41 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases) if (ContractDefinition* contract = dynamic_cast(node.get())) { auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_EQUAL("boo(uint256,bytes32,address)", functions[0]->getCanonicalSignature()); + BOOST_CHECK_EQUAL("boo(uint256,bytes32,address)", functions[0]->externalTypes()); } } +BOOST_AUTO_TEST_CASE(function_external_types) +{ + ASTPointer sourceUnit; + char const* text = R"( + contract Test { + function boo(uint arg2, bool arg3, bytes8 arg4) returns (uint ret) { + ret = 5; + } + })"; + ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + { + auto functions = contract->getDefinedFunctions(); + BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8)", functions[0]->externalTypes()); + } +} + +//todo should check arrays and contract. also event +//BOOST_AUTO_TEST_CASE(function_external_types_throw) +//{ +// ASTPointer sourceUnit; +// char const* text = R"( +// contract Test { +// function boo(uint32[] arg5) returns (uint ret) { +// ret = 5; +// } +// })"; +// BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +//} + BOOST_AUTO_TEST_CASE(hash_collision_in_interface) { char const* text = "contract test {\n" @@ -635,7 +666,6 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) "mapping(uint=>bytes4) public map;\n" "mapping(uint=>mapping(uint=>bytes4)) public multiple_map;\n" "}\n"; - ASTPointer source; ContractDefinition const* contract; ETH_TEST_CHECK_NO_THROW(source = parseTextAndResolveNames(text), "Parsing and Resolving names failed"); diff --git a/SolidityTypes.cpp b/SolidityTypes.cpp index 6b6306479..4133ce7b7 100644 --- a/SolidityTypes.cpp +++ b/SolidityTypes.cpp @@ -86,6 +86,7 @@ BOOST_AUTO_TEST_CASE(storage_layout_arrays) BOOST_CHECK(ArrayType(ArrayType::Location::Storage, make_shared(32), 9).getStorageSize() == 9); } + BOOST_AUTO_TEST_SUITE_END() } From 54bb1abcfaf1eb0f4b77568004e529d94a076c4c Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Tue, 24 Mar 2015 11:11:27 +0100 Subject: [PATCH 08/35] renamed externalTypes to externalSignature --- SolidityNameAndTypeResolution.cpp | 27 +++++++++++++++++++++++---- SolidityTypes.cpp | 1 - 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index 4e8166963..a6d1920a1 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -359,7 +359,7 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature) if (ContractDefinition* contract = dynamic_cast(node.get())) { auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_EQUAL("foo(uint256,uint64,bool)", functions[0]->externalTypes()); + BOOST_CHECK_EQUAL("foo(uint256,uint64,bool)", functions[0]->externalSignature()); } } @@ -376,7 +376,7 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases) if (ContractDefinition* contract = dynamic_cast(node.get())) { auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_EQUAL("boo(uint256,bytes32,address)", functions[0]->externalTypes()); + BOOST_CHECK_EQUAL("boo(uint256,bytes32,address)", functions[0]->externalSignature()); } } @@ -385,7 +385,7 @@ BOOST_AUTO_TEST_CASE(function_external_types) ASTPointer sourceUnit; char const* text = R"( contract Test { - function boo(uint arg2, bool arg3, bytes8 arg4) returns (uint ret) { + function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs) public returns (uint ret) { ret = 5; } })"; @@ -394,10 +394,28 @@ BOOST_AUTO_TEST_CASE(function_external_types) if (ContractDefinition* contract = dynamic_cast(node.get())) { auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8)", functions[0]->externalTypes()); + BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8)", functions[0]->externalSignature()); } } +//BOOST_AUTO_TEST_CASE(function_external_types_throw) +//{ +// ASTPointer sourceUnit; +// char const* text = R"( +// contract ArrayContract { +// bool[2][] m_pairsOfFlags; +// function setAllFlagPairs(bool[2][] newPairs) { +// // assignment to array replaces the complete array +// m_pairsOfFlags = newPairs; +// } +// })"; +// ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); +// for (ASTPointer const& node: sourceUnit->getNodes()) +// if (ContractDefinition* contract = dynamic_cast(node.get())) +// { +// auto functions = contract->getDefinedFunctions(); +// BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8)", functions[0]->externalSigniture()); +// } //todo should check arrays and contract. also event //BOOST_AUTO_TEST_CASE(function_external_types_throw) //{ @@ -666,6 +684,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) "mapping(uint=>bytes4) public map;\n" "mapping(uint=>mapping(uint=>bytes4)) public multiple_map;\n" "}\n"; + ASTPointer source; ContractDefinition const* contract; ETH_TEST_CHECK_NO_THROW(source = parseTextAndResolveNames(text), "Parsing and Resolving names failed"); diff --git a/SolidityTypes.cpp b/SolidityTypes.cpp index 4133ce7b7..6b6306479 100644 --- a/SolidityTypes.cpp +++ b/SolidityTypes.cpp @@ -86,7 +86,6 @@ BOOST_AUTO_TEST_CASE(storage_layout_arrays) BOOST_CHECK(ArrayType(ArrayType::Location::Storage, make_shared(32), 9).getStorageSize() == 9); } - BOOST_AUTO_TEST_SUITE_END() } From ae0fa99123ba647c97f2f57d4590531b9f5f7364 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Wed, 25 Mar 2015 13:58:15 +0100 Subject: [PATCH 09/35] tests for external types --- SolidityNameAndTypeResolution.cpp | 83 +++++++++++++++++++------------ 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index a6d1920a1..75a912244 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "TestHelper.h" using namespace std; @@ -48,16 +49,28 @@ ASTPointer parseTextAndResolveNames(std::string const& _source) ASTPointer sourceUnit = parser.parse(std::make_shared(CharStream(_source))); NameAndTypeResolver resolver({}); resolver.registerDeclarations(*sourceUnit); + std::shared_ptr globalContext = make_shared(); + for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) + { + globalContext->setCurrentContract(*contract); + resolver.updateDeclaration(*globalContext->getCurrentThis()); + resolver.updateDeclaration(*globalContext->getCurrentSuper()); resolver.resolveNamesAndTypes(*contract); + } for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) + { + globalContext->setCurrentContract(*contract); + resolver.updateDeclaration(*globalContext->getCurrentThis()); resolver.checkTypeRequirements(*contract); + } return sourceUnit; } + static ContractDefinition const* retrieveContract(ASTPointer _source, unsigned index) { ContractDefinition* contract; @@ -376,6 +389,8 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases) if (ContractDefinition* contract = dynamic_cast(node.get())) { auto functions = contract->getDefinedFunctions(); + if (functions.empty()) + continue; BOOST_CHECK_EQUAL("boo(uint256,bytes32,address)", functions[0]->externalSignature()); } } @@ -384,8 +399,11 @@ BOOST_AUTO_TEST_CASE(function_external_types) { ASTPointer sourceUnit; char const* text = R"( + contract C { + uint a; + } contract Test { - function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs) public returns (uint ret) { + function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs, uint[] dynamic, C carg) external returns (uint ret) { ret = 5; } })"; @@ -394,40 +412,41 @@ BOOST_AUTO_TEST_CASE(function_external_types) if (ContractDefinition* contract = dynamic_cast(node.get())) { auto functions = contract->getDefinedFunctions(); - BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8)", functions[0]->externalSignature()); + if (functions.empty()) + continue; + BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8,bool[2],uint256[],address)", functions[0]->externalSignature(true)); } } -//BOOST_AUTO_TEST_CASE(function_external_types_throw) -//{ -// ASTPointer sourceUnit; -// char const* text = R"( -// contract ArrayContract { -// bool[2][] m_pairsOfFlags; -// function setAllFlagPairs(bool[2][] newPairs) { -// // assignment to array replaces the complete array -// m_pairsOfFlags = newPairs; -// } -// })"; -// ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); -// for (ASTPointer const& node: sourceUnit->getNodes()) -// if (ContractDefinition* contract = dynamic_cast(node.get())) -// { -// auto functions = contract->getDefinedFunctions(); -// BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8)", functions[0]->externalSigniture()); -// } -//todo should check arrays and contract. also event -//BOOST_AUTO_TEST_CASE(function_external_types_throw) -//{ -// ASTPointer sourceUnit; -// char const* text = R"( -// contract Test { -// function boo(uint32[] arg5) returns (uint ret) { -// ret = 5; -// } -// })"; -// BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); -//} +BOOST_AUTO_TEST_CASE(function_external_call_conversion) +{ + char const* sourceCode = R"( + contract C {} + contract Test { + function externalCall() { + address arg; + this.g(arg); + } + function g (C c) external {} + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + +BOOST_AUTO_TEST_CASE(function_internal_call_conversion) +{ + char const* text = R"( + contract C { + uint a; + } + contract Test { + address a; + function g (C c) {} + function internalCall() { + g(a); + } + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} BOOST_AUTO_TEST_CASE(hash_collision_in_interface) { From fc0b32f68394518894314682f95a7b45fc1a6ef0 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 20 Mar 2015 17:50:26 +0100 Subject: [PATCH 10/35] Parsing of not fully implemented functions - Adding the possibility of omitting a function body by simply ending a function definition with a semicolon - Such a function is marked as not fully implemented and any contract that contains such a function is considered a not fully implemented contract --- SolidityNameAndTypeResolution.cpp | 15 +++++++++++++++ SolidityParser.cpp | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index 591cf053a..3c088358c 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -346,6 +346,21 @@ BOOST_AUTO_TEST_CASE(comparison_bitop_precedence) ETH_TEST_CHECK_NO_THROW(parseTextAndResolveNames(text), "Parsing and Name Resolving Failed"); } +BOOST_AUTO_TEST_CASE(function_no_implementation) +{ + ASTPointer sourceUnit; + char const* text = "contract test {\n" + " function functionName(bytes32 input) returns (bytes32 out);\n" + "}\n"; + ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); + ContractDefinition* contract; + for (ASTPointer const& node: sourceUnit->getNodes()) + contract = dynamic_cast(node.get()); + BOOST_CHECK(contract); + BOOST_CHECK(!contract->isFullyImplemented()); + BOOST_CHECK(!contract->getDefinedFunctions()[0]->isFullyImplemented()); +} + BOOST_AUTO_TEST_CASE(function_canonical_signature) { ASTPointer sourceUnit; diff --git a/SolidityParser.cpp b/SolidityParser.cpp index 392d9ac47..7640f91ad 100644 --- a/SolidityParser.cpp +++ b/SolidityParser.cpp @@ -108,6 +108,14 @@ BOOST_AUTO_TEST_CASE(single_function_param) ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed."); } +BOOST_AUTO_TEST_CASE(function_no_body) +{ + char const* text = "contract test {\n" + " function functionName(bytes32 input) returns (bytes32 out);\n" + "}\n"; + ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed."); +} + BOOST_AUTO_TEST_CASE(missing_parameter_name_in_named_args) { char const* text = "contract test {\n" From b655a8b9aec3e97078c623fad8be56945949999b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 25 Mar 2015 18:33:20 +0100 Subject: [PATCH 11/35] Clean up some code redundancy. Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop --- transaction.cpp | 7 +++++++ ttTransactionTestFiller.json | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/transaction.cpp b/transaction.cpp index 77f6ecdaf..4c57326ba 100644 --- a/transaction.cpp +++ b/transaction.cpp @@ -48,6 +48,13 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) if (!txFromRlp.signature().isValid()) BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") ); } + catch(Exception const& _e) + { + cnote << i.first; + cnote << "Transaction Exception: " << diagnostic_information(_e); + BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!"); + continue; + } catch(...) { BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!"); diff --git a/ttTransactionTestFiller.json b/ttTransactionTestFiller.json index 0058feac1..c04b76848 100644 --- a/ttTransactionTestFiller.json +++ b/ttTransactionTestFiller.json @@ -571,6 +571,7 @@ "s" : "0x8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3" } }, + "unpadedRValue": { "transaction": { "nonce": "13", @@ -583,5 +584,19 @@ "v": "28", "value": "" } + }, + + "libsecp256k1test": { + "transaction": { + "nonce": "", + "gasPrice": "0x09184e72a000", + "gasLimit": "0x1388", + "to": "", + "data": "", + "r": "44", + "s": "4", + "v": "27", + "value": "" + } } } From 9a032ef39fba817c965f3850aacafecb8f89cf7a Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 25 Mar 2015 19:51:08 +0100 Subject: [PATCH 12/35] fixes for test/TestUtils.h --- TestUtils.cpp | 25 ++++++------------------- TestUtils.h | 14 +++++++------- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/TestUtils.cpp b/TestUtils.cpp index 71eeadb3a..6222955d5 100644 --- a/TestUtils.cpp +++ b/TestUtils.cpp @@ -19,8 +19,6 @@ * @date 2015 */ -#include -#include #include #include #include @@ -28,10 +26,6 @@ #include #include "TestUtils.h" -// used methods from TestHelper: -// getTestPath -#include "TestHelper.h" - using namespace std; using namespace dev; using namespace dev::eth; @@ -73,19 +67,12 @@ std::string dev::test::getCommandLineArgument(string const& _name, bool _require return ""; } -bool LoadTestFileFixture::m_loaded = false; -Json::Value LoadTestFileFixture::m_json; - LoadTestFileFixture::LoadTestFileFixture() { - if (!m_loaded) - { - m_json = loadJsonFromFile(toTestFilePath(getCommandLineArgument("--eth_testfile"))); - m_loaded = true; - } + m_json = loadJsonFromFile(toTestFilePath(getCommandLineArgument("--eth_testfile"))); } -void ParallelFixture::enumerateThreads(std::function callback) +void ParallelFixture::enumerateThreads(std::function callback) const { size_t threadsCount = std::stoul(getCommandLineArgument("--eth_threads"), nullptr, 10); @@ -99,7 +86,7 @@ void ParallelFixture::enumerateThreads(std::function callback) }); } -void BlockChainFixture::enumerateBlockchains(std::function callback) +void BlockChainFixture::enumerateBlockchains(std::function callback) const { for (string const& name: m_json.getMemberNames()) { @@ -108,16 +95,16 @@ void BlockChainFixture::enumerateBlockchains(std::function callback) +void ClientBaseFixture::enumerateClients(std::function callback) const { - enumerateBlockchains([&callback](Json::Value const& _json, BlockChain& _bc, State _state) -> void + enumerateBlockchains([&callback](Json::Value const& _json, BlockChain const& _bc, State _state) -> void { FixedClient client(_bc, _state); callback(_json, client); }); } -void ParallelClientBaseFixture::enumerateClients(std::function callback) +void ParallelClientBaseFixture::enumerateClients(std::function callback) const { ClientBaseFixture::enumerateClients([this, &callback](Json::Value const& _json, dev::eth::ClientBase& _client) -> void { diff --git a/TestUtils.h b/TestUtils.h index fef10e982..f9817c21d 100644 --- a/TestUtils.h +++ b/TestUtils.h @@ -41,24 +41,24 @@ static SharedMutex x_boostTest; struct LoadTestFileFixture { LoadTestFileFixture(); - - static bool m_loaded; - static Json::Value m_json; + +protected: + Json::Value m_json; }; struct ParallelFixture { - void enumerateThreads(std::function callback); + void enumerateThreads(std::function callback) const; }; struct BlockChainFixture: public LoadTestFileFixture { - void enumerateBlockchains(std::function callback); + void enumerateBlockchains(std::function callback) const; }; struct ClientBaseFixture: public BlockChainFixture { - void enumerateClients(std::function callback); + void enumerateClients(std::function callback) const; }; // important BOOST TEST do have problems with thread safety!!! @@ -70,7 +70,7 @@ struct ClientBaseFixture: public BlockChainFixture // https://codecrafter.wordpress.com/2012/11/01/c-unit-test-framework-adapter-part-3/ struct ParallelClientBaseFixture: public ClientBaseFixture, public ParallelFixture { - void enumerateClients(std::function callback); + void enumerateClients(std::function callback) const; }; struct JsonRpcFixture: public ClientBaseFixture From 70184ece429006ff824b6165b389a38491bc73fc Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 26 Mar 2015 06:06:34 +0100 Subject: [PATCH 13/35] correct net/test for ping packet --- net.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net.cpp b/net.cpp index 7ba2d8a12..a5f973450 100644 --- a/net.cpp +++ b/net.cpp @@ -145,7 +145,7 @@ public: bool success = false; }; -BOOST_AUTO_TEST_CASE(badPingNodePacket) +BOOST_AUTO_TEST_CASE(v2PingNodePacket) { // test old versino of pingNode packet w/new RLPStream s; @@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(badPingNodePacket) PingNode p((bi::udp::endpoint())); BOOST_REQUIRE_NO_THROW(p = PingNode::fromBytesConstRef(bi::udp::endpoint(), bytesConstRef(&s.out()))); - BOOST_REQUIRE(p.version == 0); + BOOST_REQUIRE(p.version == 2); } BOOST_AUTO_TEST_CASE(test_neighbours_packet) From 25e4cf071adc3bd54f5603b86e332efe06b2d371 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Thu, 26 Mar 2015 14:11:24 +0100 Subject: [PATCH 14/35] two more tests style fixes --- SolidityNameAndTypeResolution.cpp | 38 +++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index 75a912244..6b9916549 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -418,9 +418,23 @@ BOOST_AUTO_TEST_CASE(function_external_types) } } -BOOST_AUTO_TEST_CASE(function_external_call_conversion) +BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion) { - char const* sourceCode = R"( + char const* text = R"( + contract C {} + contract Test { + function externalCall() { + C arg; + this.g(arg); + } + function g (C c) external {} + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion) +{ + char const* text = R"( contract C {} contract Test { function externalCall() { @@ -429,10 +443,26 @@ BOOST_AUTO_TEST_CASE(function_external_call_conversion) } function g (C c) external {} })"; - BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } -BOOST_AUTO_TEST_CASE(function_internal_call_conversion) +BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion) +{ + char const* text = R"( + contract C { + uint a; + } + contract Test { + C a; + function g (C c) {} + function internalCall() { + g(a); + } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion) { char const* text = R"( contract C { From 708c55478c0df93995955bde989d26a25845b215 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 26 Mar 2015 16:21:25 +0100 Subject: [PATCH 15/35] adopt node IP address from udp header when ping.ipAddress isn't public --- net.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/net.cpp b/net.cpp index a5f973450..ec1efb360 100644 --- a/net.cpp +++ b/net.cpp @@ -145,6 +145,40 @@ public: bool success = false; }; +BOOST_AUTO_TEST_CASE(isIPAddressType) +{ + string wildcard = "0.0.0.0"; + BOOST_REQUIRE(bi::address::from_string(wildcard).is_unspecified()); + + string empty = ""; + BOOST_REQUIRE_THROW(bi::address::from_string(empty).is_unspecified(), std::exception); + + string publicAddress192 = "192.169.0.0"; + BOOST_REQUIRE(isPublicAddress(publicAddress192)); + BOOST_REQUIRE(!isPrivateAddress(publicAddress192)); + BOOST_REQUIRE(!isLocalHostAddress(publicAddress192)); + + string publicAddress172 = "172.32.0.0"; + BOOST_REQUIRE(isPublicAddress(publicAddress172)); + BOOST_REQUIRE(!isPrivateAddress(publicAddress172)); + BOOST_REQUIRE(!isLocalHostAddress(publicAddress172)); + + string privateAddress192 = "192.168.1.0"; + BOOST_REQUIRE(isPrivateAddress(privateAddress192)); + BOOST_REQUIRE(!isPublicAddress(privateAddress192)); + BOOST_REQUIRE(!isLocalHostAddress(privateAddress192)); + + string privateAddress172 = "172.16.0.0"; + BOOST_REQUIRE(isPrivateAddress(privateAddress172)); + BOOST_REQUIRE(!isPublicAddress(privateAddress172)); + BOOST_REQUIRE(!isLocalHostAddress(privateAddress172)); + + string privateAddress10 = "10.0.0.0"; + BOOST_REQUIRE(isPrivateAddress(privateAddress10)); + BOOST_REQUIRE(!isPublicAddress(privateAddress10)); + BOOST_REQUIRE(!isLocalHostAddress(privateAddress10)); +} + BOOST_AUTO_TEST_CASE(v2PingNodePacket) { // test old versino of pingNode packet w/new From 782e69fbe406de3b4924737b3a3120308a0e096a Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 20 Mar 2015 22:39:42 +0100 Subject: [PATCH 16/35] Optimizing various single operations. --- SolidityOptimizer.cpp | 80 +++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/SolidityOptimizer.cpp b/SolidityOptimizer.cpp index 9c6a4e361..2ced97430 100644 --- a/SolidityOptimizer.cpp +++ b/SolidityOptimizer.cpp @@ -74,6 +74,14 @@ public: "\nOptimized: " + toHex(optimizedOutput)); } + void checkCSE(AssemblyItems const& _input, AssemblyItems const& _expectation) + { + eth::CommonSubexpressionEliminator cse; + BOOST_REQUIRE(cse.feedItems(_input.begin(), _input.end()) == _input.end()); + AssemblyItems output = cse.getOptimizedItems(); + BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end()); + } + protected: Address m_optimizedContract; Address m_nonOptimizedContract; @@ -199,61 +207,59 @@ BOOST_AUTO_TEST_CASE(cse_intermediate_swap) BOOST_AUTO_TEST_CASE(cse_negative_stack_access) { - eth::CommonSubexpressionEliminator cse; - AssemblyItems input{AssemblyItem(Instruction::DUP2), AssemblyItem(u256(0))}; - BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); - AssemblyItems output = cse.getOptimizedItems(); - BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); + AssemblyItems input{Instruction::DUP2, u256(0)}; + checkCSE(input, input); } BOOST_AUTO_TEST_CASE(cse_negative_stack_end) { - eth::CommonSubexpressionEliminator cse; - AssemblyItems input{ - AssemblyItem(Instruction::ADD) - }; - BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); - AssemblyItems output = cse.getOptimizedItems(); - BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); + AssemblyItems input{Instruction::ADD}; + checkCSE(input, input); } BOOST_AUTO_TEST_CASE(cse_intermediate_negative_stack) { - eth::CommonSubexpressionEliminator cse; - AssemblyItems input{ - AssemblyItem(Instruction::ADD), - AssemblyItem(u256(1)), - AssemblyItem(Instruction::DUP2) - }; - BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); - AssemblyItems output = cse.getOptimizedItems(); - BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); + AssemblyItems input{Instruction::ADD, u256(1), Instruction::DUP1}; + checkCSE(input, input); } BOOST_AUTO_TEST_CASE(cse_pop) { - eth::CommonSubexpressionEliminator cse; - AssemblyItems input{ - AssemblyItem(Instruction::POP) - }; - BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); - AssemblyItems output = cse.getOptimizedItems(); - BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); + checkCSE({Instruction::POP}, {Instruction::POP}); } BOOST_AUTO_TEST_CASE(cse_unneeded_items) { - eth::CommonSubexpressionEliminator cse; AssemblyItems input{ - AssemblyItem(Instruction::ADD), - AssemblyItem(Instruction::SWAP1), - AssemblyItem(Instruction::POP), - AssemblyItem(u256(7)), - AssemblyItem(u256(8)), + Instruction::ADD, + Instruction::SWAP1, + Instruction::POP, + u256(7), + u256(8), }; - BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); - AssemblyItems output = cse.getOptimizedItems(); - BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); + checkCSE(input, input); +} + +BOOST_AUTO_TEST_CASE(cse_invariants) +{ + AssemblyItems input{ + Instruction::DUP1, + Instruction::DUP1, + u256(0), + Instruction::OR, + Instruction::OR + }; + checkCSE(input, {Instruction::DUP1}); +} + +BOOST_AUTO_TEST_CASE(cse_subself) +{ + checkCSE({Instruction::DUP1, Instruction::SUB}, {Instruction::POP, u256(0)}); +} + +BOOST_AUTO_TEST_CASE(cse_subother) +{ + checkCSE({Instruction::SUB}, {Instruction::SUB}); } BOOST_AUTO_TEST_SUITE_END() From 4e20d0fb6da983ce8716b7710a124e44226a16b0 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 23 Mar 2015 13:09:25 +0100 Subject: [PATCH 17/35] Pattern matching for expression simplification. --- SolidityOptimizer.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/SolidityOptimizer.cpp b/SolidityOptimizer.cpp index 2ced97430..2d5cff7ac 100644 --- a/SolidityOptimizer.cpp +++ b/SolidityOptimizer.cpp @@ -240,6 +240,12 @@ BOOST_AUTO_TEST_CASE(cse_unneeded_items) checkCSE(input, input); } +BOOST_AUTO_TEST_CASE(cse_constant_addition) +{ + AssemblyItems input{u256(7), u256(8), Instruction::ADD}; + checkCSE(input, {u256(7 + 8)}); +} + BOOST_AUTO_TEST_CASE(cse_invariants) { AssemblyItems input{ @@ -262,6 +268,41 @@ BOOST_AUTO_TEST_CASE(cse_subother) checkCSE({Instruction::SUB}, {Instruction::SUB}); } +BOOST_AUTO_TEST_CASE(cse_double_negation) +{ + checkCSE({Instruction::DUP5, Instruction::NOT, Instruction::NOT}, {Instruction::DUP5}); +} + +BOOST_AUTO_TEST_CASE(cse_associativity) +{ + AssemblyItems input{ + Instruction::DUP1, + Instruction::DUP1, + u256(0), + Instruction::OR, + Instruction::OR + }; + checkCSE(input, {Instruction::DUP1}); +} + +BOOST_AUTO_TEST_CASE(cse_associativity2) +{ + AssemblyItems input{ + u256(0), + Instruction::DUP2, + u256(2), + u256(1), + Instruction::DUP6, + Instruction::ADD, + u256(2), + Instruction::ADD, + Instruction::ADD, + Instruction::ADD, + Instruction::ADD + }; + checkCSE(input, {Instruction::DUP2, Instruction::DUP2, Instruction::ADD, u256(5), Instruction::ADD}); +} + BOOST_AUTO_TEST_SUITE_END() } From e82b8019ea7c44859a587caa640a76fed87acacb Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 27 Mar 2015 13:11:24 +0100 Subject: [PATCH 18/35] Parse test files and create ctest tests. --- CMakeLists.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef292c2bb..47dc611a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,21 @@ include_directories(${Boost_INCLUDE_DIRS}) include_directories(${CRYPTOPP_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +# search for test names and create ctest tests +enable_testing() +foreach(file ${SRC_LIST}) + file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/${file} test_list_raw REGEX "BOOST_.*TEST_(SUITE|CASE)") + set(TestSuite "DEFAULT") + foreach(test_raw ${test_list_raw}) + string(REGEX REPLACE ".*TEST_(SUITE|CASE)\\(([^ ,\\)]*).*" "\\1 \\2" test ${test_raw}) + if(test MATCHES "^SUITE .*") + string(SUBSTRING ${test} 6 -1 TestSuite) + elseif(test MATCHES "^CASE .*") + string(SUBSTRING ${test} 5 -1 TestCase) + add_test(NAME ${TestSuite}/${TestCase} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND testeth -t ${TestSuite}/${TestCase}) + endif(test MATCHES "^SUITE .*") + endforeach(test_raw) +endforeach(file) file(GLOB HEADERS "*.h") add_executable(testeth ${SRC_LIST} ${HEADERS}) From a427053d9927b74c6dd137dd978db8686a5a0cff Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Fri, 27 Mar 2015 13:28:32 +0100 Subject: [PATCH 19/35] added externalTypes function to functionType removed flag for externalSigniture --- SolidityNameAndTypeResolution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index 6b9916549..3bec70a2b 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -414,7 +414,7 @@ BOOST_AUTO_TEST_CASE(function_external_types) auto functions = contract->getDefinedFunctions(); if (functions.empty()) continue; - BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8,bool[2],uint256[],address)", functions[0]->externalSignature(true)); + BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8,bool[2],uint256[],address)", functions[0]->externalSignature()); } } From 621215918de0bb68c0db9369791672ec72f7bd1a Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 27 Mar 2015 15:15:34 +0100 Subject: [PATCH 20/35] Abstract contract and inheritance - Checking the linearized base contracts for abstract functions and handle their existence appropriately - If a contract is abstract it can't be created with new - An abstract contract is not compiled (no backend code is generated) - Of course tests --- SolidityNameAndTypeResolution.cpp | 48 +++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index 3c088358c..8eb83b117 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -353,14 +353,56 @@ BOOST_AUTO_TEST_CASE(function_no_implementation) " function functionName(bytes32 input) returns (bytes32 out);\n" "}\n"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); - ContractDefinition* contract; - for (ASTPointer const& node: sourceUnit->getNodes()) - contract = dynamic_cast(node.get()); + std::vector> nodes = sourceUnit->getNodes(); + ContractDefinition* contract = dynamic_cast(nodes[0].get()); BOOST_CHECK(contract); BOOST_CHECK(!contract->isFullyImplemented()); BOOST_CHECK(!contract->getDefinedFunctions()[0]->isFullyImplemented()); } +BOOST_AUTO_TEST_CASE(abstract_contract) +{ + ASTPointer sourceUnit; + char const* text = R"( + contract base { function foo(); } + contract derived is base { function foo() {} } + )"; + ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); + std::vector> nodes = sourceUnit->getNodes(); + ContractDefinition* base = dynamic_cast(nodes[0].get()); + ContractDefinition* derived = dynamic_cast(nodes[1].get()); + BOOST_CHECK(base); + BOOST_CHECK(!base->isFullyImplemented()); + BOOST_CHECK(!base->getDefinedFunctions()[0]->isFullyImplemented()); + BOOST_CHECK(derived); + BOOST_CHECK(derived->isFullyImplemented()); + BOOST_CHECK(derived->getDefinedFunctions()[0]->isFullyImplemented()); +} + +BOOST_AUTO_TEST_CASE(create_abstract_contract) +{ + ASTPointer sourceUnit; + char const* text = R"( + contract base { function foo(); } + contract derived { + base b; + function foo() { b = new base();} + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(redeclare_implemented_abstract_function_as_abstract) +{ + ASTPointer sourceUnit; + char const* text = R"( + contract base { function foo(); } + contract derived is base { function foo() {} } + contract wrong is derived { function foo(); } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_CASE(function_canonical_signature) { ASTPointer sourceUnit; From f9091e16777791aa70cad2c3ae6f62dcc1a8189b Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 27 Mar 2015 20:49:05 +0100 Subject: [PATCH 21/35] update CLI and AZ UI for replacing local-networking with explicit --listen-ip --- peer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/peer.cpp b/peer.cpp index bfb4680d3..b90fc7404 100644 --- a/peer.cpp +++ b/peer.cpp @@ -35,8 +35,8 @@ BOOST_AUTO_TEST_CASE(host) auto oldLogVerbosity = g_logVerbosity; g_logVerbosity = 10; - NetworkPreferences host1prefs(30301, "127.0.0.1", false, true); - NetworkPreferences host2prefs(30302, "127.0.0.1", false, true); + NetworkPreferences host1prefs("127.0.0.1", 30301, false); + NetworkPreferences host2prefs("127.0.0.1", 30302, false); Host host1("Test", host1prefs); host1.start(); @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(save_nodes) std::list hosts; for (auto i:{0,1,2,3,4,5}) { - Host* h = new Host("Test", NetworkPreferences(30300 + i, "127.0.0.1", false, true)); + Host* h = new Host("Test", NetworkPreferences("127.0.0.1", 30300 + i, false)); h->setIdealPeerCount(10); // starting host is required so listenport is available h->start(); From f6aaa7b12f64291a2ef8a723c5a1dd620751d0ac Mon Sep 17 00:00:00 2001 From: subtly Date: Sat, 28 Mar 2015 09:39:04 +0100 Subject: [PATCH 22/35] makePeer and support setting listen IP. --- peer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/peer.cpp b/peer.cpp index b90fc7404..48431504f 100644 --- a/peer.cpp +++ b/peer.cpp @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(host) auto node2 = host2.id(); host2.start(); - host1.addNode(node2, "127.0.0.1", host2prefs.listenPort, host2prefs.listenPort); + host1.addNode(node2, bi::address::from_string("127.0.0.1"), host2prefs.listenPort, host2prefs.listenPort); this_thread::sleep_for(chrono::seconds(3)); @@ -73,11 +73,11 @@ BOOST_AUTO_TEST_CASE(save_nodes) Host& host = *hosts.front(); for (auto const& h: hosts) - host.addNode(h->id(), "127.0.0.1", h->listenPort(), h->listenPort()); + host.addNode(h->id(), bi::address::from_string("127.0.0.1"), h->listenPort(), h->listenPort()); Host& host2 = *hosts.back(); for (auto const& h: hosts) - host2.addNode(h->id(), "127.0.0.1", h->listenPort(), h->listenPort()); + host2.addNode(h->id(), bi::address::from_string("127.0.0.1"), h->listenPort(), h->listenPort()); this_thread::sleep_for(chrono::milliseconds(2000)); bytes firstHostNetwork(host.saveNetwork()); @@ -122,7 +122,7 @@ int peerTest(int argc, char** argv) Host ph("Test", NetworkPreferences(listenPort)); if (!remoteHost.empty() && !remoteAlias) - ph.addNode(remoteAlias, remoteHost, remotePort, remotePort); + ph.addNode(remoteAlias, bi::address::from_string(remoteHost), remotePort, remotePort); this_thread::sleep_for(chrono::milliseconds(200)); From 5e28d981c729a929a37ba761e86a47de08ce9456 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 29 Mar 2015 19:13:39 +0200 Subject: [PATCH 23/35] Refactored much of transaction queue for tidiness and optimisation. --- blockchain.cpp | 21 ++++++++++----------- checkRandomStateTest.cpp | 3 +-- createRandomStateTest.cpp | 3 +-- solidityExecutionFramework.h | 3 ++- state.cpp | 3 +-- stateOriginal.cpp | 10 +++------- 6 files changed, 18 insertions(+), 25 deletions(-) diff --git a/blockchain.cpp b/blockchain.cpp index 50ca22c54..988859fe5 100644 --- a/blockchain.cpp +++ b/blockchain.cpp @@ -182,18 +182,17 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) Transactions txList; for (auto const& txi: txs.transactions()) { - Transaction tx(txi.second, CheckSignature::Sender); - txList.push_back(tx); + txList.push_back(txi.second); mObject txObject; - txObject["nonce"] = toString(tx.nonce()); - txObject["data"] = "0x" + toHex(tx.data()); - txObject["gasLimit"] = toString(tx.gas()); - txObject["gasPrice"] = toString(tx.gasPrice()); - txObject["r"] = "0x" + toString(tx.signature().r); - txObject["s"] = "0x" + toString(tx.signature().s); - txObject["v"] = to_string(tx.signature().v + 27); - txObject["to"] = tx.isCreation() ? "" : toString(tx.receiveAddress()); - txObject["value"] = toString(tx.value()); + txObject["nonce"] = toString(txi.second.nonce()); + txObject["data"] = "0x" + toHex(txi.second.data()); + txObject["gasLimit"] = toString(txi.second.gas()); + txObject["gasPrice"] = toString(txi.second.gasPrice()); + txObject["r"] = "0x" + toString(txi.second.signature().r); + txObject["s"] = "0x" + toString(txi.second.signature().s); + txObject["v"] = to_string(txi.second.signature().v + 27); + txObject["to"] = txi.second.isCreation() ? "" : toString(txi.second.receiveAddress()); + txObject["value"] = toString(txi.second.value()); txArray.push_back(txObject); } diff --git a/checkRandomStateTest.cpp b/checkRandomStateTest.cpp index a4d390b16..49aca852f 100644 --- a/checkRandomStateTest.cpp +++ b/checkRandomStateTest.cpp @@ -83,12 +83,11 @@ bool doStateTest(mValue& _v) ImportTest importer(o, false); eth::State theState = importer.m_statePre; - bytes tx = importer.m_transaction.rlp(); bytes output; try { - output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx).output; + output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output; } catch (Exception const& _e) { diff --git a/createRandomStateTest.cpp b/createRandomStateTest.cpp index f422d1717..5758598b9 100644 --- a/createRandomStateTest.cpp +++ b/createRandomStateTest.cpp @@ -183,12 +183,11 @@ void doStateTests(json_spirit::mValue& _v) test::ImportTest importer(o, true); eth::State theState = importer.m_statePre; - bytes tx = importer.m_transaction.rlp(); bytes output; try { - output = theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), tx).output; + output = theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output; } catch (Exception const& _e) { diff --git a/solidityExecutionFramework.h b/solidityExecutionFramework.h index 86062a90b..2451aa381 100644 --- a/solidityExecutionFramework.h +++ b/solidityExecutionFramework.h @@ -142,7 +142,8 @@ protected: try { // this will throw since the transaction is invalid, but it should nevertheless store the transaction - executive.setup(&transactionRLP); + executive.initialize(&transactionRLP); + executive.execute(); } catch (...) {} if (_isCreation) diff --git a/state.cpp b/state.cpp index 4ab59f7a1..7c586ec7d 100644 --- a/state.cpp +++ b/state.cpp @@ -57,13 +57,12 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) ImportTest importer(o, _fillin); State theState = importer.m_statePre; - bytes tx = importer.m_transaction.rlp(); bytes output; try { Listener::ExecTimeGuard guard{i.first}; - output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx).output; + output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output; } catch (Exception const& _e) { diff --git a/stateOriginal.cpp b/stateOriginal.cpp index 5b7b0415e..384d85344 100644 --- a/stateOriginal.cpp +++ b/stateOriginal.cpp @@ -79,13 +79,9 @@ BOOST_AUTO_TEST_CASE(Complex) cout << s; // Inject a transaction to transfer funds from miner to me. - bytes tx; - { - Transaction t(1000, 10000, 10000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret()); - assert(t.sender() == myMiner.address()); - tx = t.rlp(); - } - s.execute(bc, tx); + Transaction t(1000, 10000, 10000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret()); + assert(t.sender() == myMiner.address()); + s.execute(bc.lastHashes(), t); cout << s; From 25ccfe9ce4facdbf8fefaec26b79181cbac5d6fc Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 29 Mar 2015 22:23:59 +0200 Subject: [PATCH 24/35] Fix a load of horrible style that got through. Fix blockchain tests so they don't clobber the AZ blockchain DB! Make TransientDirectory use a temp path unless otherwise instructed. --- blockchain.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/blockchain.cpp b/blockchain.cpp index 988859fe5..e5bba607a 100644 --- a/blockchain.cpp +++ b/blockchain.cpp @@ -20,6 +20,7 @@ * block test functions. */ +#include #include #include #include "TestHelper.h" @@ -35,8 +36,8 @@ bytes createBlockRLPFromFields(mObject& _tObj); void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj); BlockInfo constructBlock(mObject& _o); void updatePoW(BlockInfo& _bi); -void writeBlockHeaderToJson(mObject& _o, const BlockInfo& _bi); -RLPStream createFullBlockFromHeader(const BlockInfo& _bi, const bytes& _txs = RLPEmptyList, const bytes& _uncles = RLPEmptyList); +void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi); +RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs = RLPEmptyList, bytes const& _uncles = RLPEmptyList); void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) { @@ -75,7 +76,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) o["genesisRLP"] = "0x" + toHex(rlpGenesisBlock.out()); // construct blockchain - BlockChain bc(rlpGenesisBlock.out(), string(), true); + BlockChain bc(rlpGenesisBlock.out(), (boost::filesystem::temp_directory_path() / ("eth_test_" + toString(rand()))).string(), true); if (_fillin) { @@ -241,6 +242,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) if (sha3(RLP(state.blockData())[2].data()) != sha3(RLP(block2.out())[2].data())) cnote << "uncle list mismatch\n" << RLP(state.blockData())[2].data() << "\n" << RLP(block2.out())[2].data(); + try { state.sync(bc); @@ -292,7 +294,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) BOOST_CHECK(blObj.count("uncleHeaders") == 0); continue; } - catch(...) + catch (...) { cnote << "state sync or block import did throw an exception\n"; BOOST_CHECK(blObj.count("blockHeader") == 0); @@ -388,7 +390,6 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) BOOST_CHECK_MESSAGE(txsFromField[i] == txsFromRlp[i], "transactions from rlp and transaction from field do not match"); BOOST_CHECK_MESSAGE(txsFromField[i].rlp() == txsFromRlp[i].rlp(), "transactions rlp do not match"); - } // check uncle list @@ -488,12 +489,12 @@ bytes createBlockRLPFromFields(mObject& _tObj) return rlpStream.out(); } -void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj) +void overwriteBlockHeader(BlockInfo& _currentBlockHeader, mObject& _blObj) { if (_blObj["blockHeader"].get_obj().size() != 14) { - BlockInfo tmp = _current_BlockHeader; + BlockInfo tmp = _currentBlockHeader; if (_blObj["blockHeader"].get_obj().count("parentHash")) tmp.parentHash = h256(_blObj["blockHeader"].get_obj()["parentHash"].get_str()); @@ -539,16 +540,16 @@ void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj) // find new valid nonce - if (tmp != _current_BlockHeader) + if (tmp != _currentBlockHeader) { - _current_BlockHeader = tmp; + _currentBlockHeader = tmp; ProofOfWork pow; std::pair ret; - while (!ProofOfWork::verify(_current_BlockHeader)) + while (!ProofOfWork::verify(_currentBlockHeader)) { - ret = pow.mine(_current_BlockHeader, 1000, true, true); - Ethash::assignResult(ret.second, _current_BlockHeader); + ret = pow.mine(_currentBlockHeader, 1000, true, true); + Ethash::assignResult(ret.second, _currentBlockHeader); } } } @@ -557,13 +558,12 @@ void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj) // take the blockheader as is const bytes c_blockRLP = createBlockRLPFromFields(_blObj["blockHeader"].get_obj()); const RLP c_bRLP(c_blockRLP); - _current_BlockHeader.populateFromHeader(c_bRLP, IgnoreNonce); + _currentBlockHeader.populateFromHeader(c_bRLP, IgnoreNonce); } } BlockInfo constructBlock(mObject& _o) { - BlockInfo ret; try { @@ -600,7 +600,7 @@ void updatePoW(BlockInfo& _bi) _bi.hash = _bi.headerHash(WithNonce); } -void writeBlockHeaderToJson(mObject& _o, const BlockInfo& _bi) +void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi) { _o["parentHash"] = toString(_bi.parentHash); _o["uncleHash"] = toString(_bi.sha3Uncles); @@ -620,7 +620,7 @@ void writeBlockHeaderToJson(mObject& _o, const BlockInfo& _bi) _o["hash"] = toString(_bi.hash); } -RLPStream createFullBlockFromHeader(const BlockInfo& _bi,const bytes& _txs, const bytes& _uncles ) +RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs, bytes const& _uncles) { RLPStream rlpStream; _bi.streamRLP(rlpStream, WithNonce); @@ -632,8 +632,8 @@ RLPStream createFullBlockFromHeader(const BlockInfo& _bi,const bytes& _txs, cons return ret; } -} }// Namespace Close +} }// Namespace Close BOOST_AUTO_TEST_SUITE(BlockChainTests) From 77589fce9b93ad9cafc93671cac80d46104bc248 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 29 Mar 2015 22:37:32 +0200 Subject: [PATCH 25/35] Use TransientDirectory. --- blockchain.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/blockchain.cpp b/blockchain.cpp index e5bba607a..17e6c3588 100644 --- a/blockchain.cpp +++ b/blockchain.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include "TestHelper.h" @@ -76,7 +77,8 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) o["genesisRLP"] = "0x" + toHex(rlpGenesisBlock.out()); // construct blockchain - BlockChain bc(rlpGenesisBlock.out(), (boost::filesystem::temp_directory_path() / ("eth_test_" + toString(rand()))).string(), true); + TransientDirectory td; + BlockChain bc(rlpGenesisBlock.out(), td.path(), true); if (_fillin) { From 1391b58e53cdc3f163b81a972f0e798b5f7a8980 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 24 Mar 2015 14:53:15 +0100 Subject: [PATCH 26/35] Storage access optimisation. --- SolidityOptimizer.cpp | 180 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) diff --git a/SolidityOptimizer.cpp b/SolidityOptimizer.cpp index 2d5cff7ac..de4cac8fd 100644 --- a/SolidityOptimizer.cpp +++ b/SolidityOptimizer.cpp @@ -303,6 +303,186 @@ BOOST_AUTO_TEST_CASE(cse_associativity2) checkCSE(input, {Instruction::DUP2, Instruction::DUP2, Instruction::ADD, u256(5), Instruction::ADD}); } +BOOST_AUTO_TEST_CASE(cse_storage) +{ + AssemblyItems input{ + u256(0), + Instruction::SLOAD, + u256(0), + Instruction::SLOAD, + Instruction::ADD, + u256(0), + Instruction::SSTORE + }; + checkCSE(input, { + u256(0), + Instruction::DUP1, + Instruction::SLOAD, + Instruction::DUP1, + Instruction::ADD, + Instruction::SWAP1, + Instruction::SSTORE + }); +} + +BOOST_AUTO_TEST_CASE(cse_noninterleaved_storage) +{ + // two stores to the same location should be replaced by only one store, even if we + // read in the meantime + AssemblyItems input{ + u256(7), + Instruction::DUP2, + Instruction::SSTORE, + Instruction::DUP1, + Instruction::SLOAD, + u256(8), + Instruction::DUP3, + Instruction::SSTORE + }; + checkCSE(input, { + u256(8), + Instruction::DUP2, + Instruction::SSTORE, + u256(7) + }); +} + +BOOST_AUTO_TEST_CASE(cse_interleaved_storage) +{ + // stores and reads to/from two unknown locations, should not optimize away the first store + AssemblyItems input{ + u256(7), + Instruction::DUP2, + Instruction::SSTORE, // store to "DUP1" + Instruction::DUP2, + Instruction::SLOAD, // read from "DUP2", might be equal to "DUP1" + u256(0), + Instruction::DUP3, + Instruction::SSTORE // store different value to "DUP1" + }; + checkCSE(input, input); +} + +BOOST_AUTO_TEST_CASE(cse_interleaved_storage_same_value) +{ + // stores and reads to/from two unknown locations, should not optimize away the first store + // but it should optimize away the second, since we already know the value will be the same + AssemblyItems input{ + u256(7), + Instruction::DUP2, + Instruction::SSTORE, // store to "DUP1" + Instruction::DUP2, + Instruction::SLOAD, // read from "DUP2", might be equal to "DUP1" + u256(6), + u256(1), + Instruction::ADD, + Instruction::DUP3, + Instruction::SSTORE // store same value to "DUP1" + }; + checkCSE(input, { + u256(7), + Instruction::DUP2, + Instruction::SSTORE, + Instruction::DUP2, + Instruction::SLOAD + }); +} + +BOOST_AUTO_TEST_CASE(cse_interleaved_storage_at_known_location) +{ + // stores and reads to/from two known locations, should optimize away the first store, + // because we know that the location is different + AssemblyItems input{ + u256(0x70), + u256(1), + Instruction::SSTORE, // store to 1 + u256(2), + Instruction::SLOAD, // read from 2, is different from 1 + u256(0x90), + u256(1), + Instruction::SSTORE // store different value at 1 + }; + checkCSE(input, { + u256(2), + Instruction::SLOAD, + u256(0x90), + u256(1), + Instruction::SSTORE + }); +} + +BOOST_AUTO_TEST_CASE(cse_interleaved_storage_at_known_location_offset) +{ + // stores and reads to/from two locations which are known to be different, + // should optimize away the first store, because we know that the location is different + AssemblyItems input{ + u256(0x70), + Instruction::DUP2, + u256(1), + Instruction::ADD, + Instruction::SSTORE, // store to "DUP1"+1 + Instruction::DUP1, + u256(2), + Instruction::ADD, + Instruction::SLOAD, // read from "DUP1"+2, is different from "DUP1"+1 + u256(0x90), + Instruction::DUP3, + u256(1), + Instruction::ADD, + Instruction::SSTORE // store different value at "DUP1"+1 + }; + checkCSE(input, { + u256(2), + Instruction::DUP2, + Instruction::ADD, + Instruction::SLOAD, + u256(0x90), + u256(1), + Instruction::DUP4, + Instruction::ADD, + Instruction::SSTORE + }); +} + +BOOST_AUTO_TEST_CASE(cse_deep_stack) +{ + AssemblyItems input{ + Instruction::ADD, + Instruction::SWAP1, + Instruction::POP, + Instruction::SWAP8, + Instruction::POP, + Instruction::SWAP8, + Instruction::POP, + Instruction::SWAP8, + Instruction::SWAP5, + Instruction::POP, + Instruction::POP, + Instruction::POP, + Instruction::POP, + Instruction::POP, + }; + checkCSE(input, { + Instruction::SWAP4, + Instruction::SWAP12, + Instruction::SWAP3, + Instruction::SWAP11, + Instruction::POP, + Instruction::SWAP1, + Instruction::SWAP3, + Instruction::ADD, + Instruction::SWAP8, + Instruction::POP, + Instruction::SWAP6, + Instruction::POP, + Instruction::POP, + Instruction::POP, + Instruction::POP, + Instruction::POP, + Instruction::POP, + }); +} + BOOST_AUTO_TEST_SUITE_END() } From b3fc122845c9f986d13b2a6b52df686ab5f1818e Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 26 Mar 2015 15:50:50 +0100 Subject: [PATCH 27/35] Optimizer for memory. --- SolidityOptimizer.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/SolidityOptimizer.cpp b/SolidityOptimizer.cpp index de4cac8fd..cf35536e6 100644 --- a/SolidityOptimizer.cpp +++ b/SolidityOptimizer.cpp @@ -444,6 +444,59 @@ BOOST_AUTO_TEST_CASE(cse_interleaved_storage_at_known_location_offset) }); } +BOOST_AUTO_TEST_CASE(cse_interleaved_memory_at_known_location_offset) +{ + // stores and reads to/from two locations which are known to be different, + // should not optimize away the first store, because the location overlaps with the load, + // but it should optimize away the second, because we know that the location is different by 32 + AssemblyItems input{ + u256(0x50), + Instruction::DUP2, + u256(2), + Instruction::ADD, + Instruction::MSTORE, // ["DUP1"+2] = 0x50 + u256(0x60), + Instruction::DUP2, + u256(32), + Instruction::ADD, + Instruction::MSTORE, // ["DUP1"+32] = 0x60 + Instruction::DUP1, + Instruction::MLOAD, // read from "DUP1" + u256(0x70), + Instruction::DUP3, + u256(32), + Instruction::ADD, + Instruction::MSTORE, // ["DUP1"+32] = 0x70 + u256(0x80), + Instruction::DUP3, + u256(2), + Instruction::ADD, + Instruction::MSTORE, // ["DUP1"+2] = 0x80 + }; + // If the actual code changes too much, we could also simply check that the output contains + // exactly 3 MSTORE and exactly 1 MLOAD instruction. + checkCSE(input, { + u256(0x50), + u256(2), + Instruction::DUP3, + Instruction::ADD, + Instruction::SWAP1, + Instruction::DUP2, + Instruction::MSTORE, // ["DUP1"+2] = 0x50 + Instruction::DUP2, + Instruction::MLOAD, // read from "DUP1" + u256(0x70), + u256(32), + Instruction::DUP5, + Instruction::ADD, + Instruction::MSTORE, // ["DUP1"+32] = 0x70 + u256(0x80), + Instruction::SWAP1, + Instruction::SWAP2, + Instruction::MSTORE // ["DUP1"+2] = 0x80 + }); +} + BOOST_AUTO_TEST_CASE(cse_deep_stack) { AssemblyItems input{ From 35274fb9b1a89589b60de7f54913d5f77712c6af Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 27 Mar 2015 00:24:31 +0100 Subject: [PATCH 28/35] Optimize breaking item. --- SolidityOptimizer.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/SolidityOptimizer.cpp b/SolidityOptimizer.cpp index cf35536e6..e69d5120e 100644 --- a/SolidityOptimizer.cpp +++ b/SolidityOptimizer.cpp @@ -536,6 +536,38 @@ BOOST_AUTO_TEST_CASE(cse_deep_stack) }); } +BOOST_AUTO_TEST_CASE(cse_jumpi_no_jump) +{ + AssemblyItems input{ + u256(0), + u256(1), + Instruction::DUP2, + AssemblyItem(PushTag, 1), + Instruction::JUMPI + }; + checkCSE(input, { + u256(0), + u256(1) + }); +} + +BOOST_AUTO_TEST_CASE(cse_jumpi_jump) +{ + AssemblyItems input{ + u256(1), + u256(1), + Instruction::DUP2, + AssemblyItem(PushTag, 1), + Instruction::JUMPI + }; + checkCSE(input, { + u256(1), + Instruction::DUP1, + AssemblyItem(PushTag, 1), + Instruction::JUMP + }); +} + BOOST_AUTO_TEST_SUITE_END() } From 0f416747ad3492aaab2b3a61d380579410753727 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 30 Mar 2015 14:02:27 +0200 Subject: [PATCH 29/35] failing tests for getting genesis block --- ClientBase.cpp | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/ClientBase.cpp b/ClientBase.cpp index 2197ac830..304182cfc 100644 --- a/ClientBase.cpp +++ b/ClientBase.cpp @@ -34,34 +34,45 @@ BOOST_AUTO_TEST_CASE(blocks) { enumerateClients([](Json::Value const& _json, dev::eth::ClientBase& _client) -> void { - for (string const& name: _json["postState"].getMemberNames()) + auto compareState = [&_client](Json::Value const& _o, string const& _name, BlockNumber _blockNumber) -> void { - Json::Value o = _json["postState"][name]; - Address address(name); + Address address(_name); // balanceAt - u256 expectedBalance = u256(o["balance"].asString()); - u256 balance = _client.balanceAt(address); + u256 expectedBalance = u256(_o["balance"].asString()); + u256 balance = _client.balanceAt(address, _blockNumber); ETH_CHECK_EQUAL(expectedBalance, balance); // countAt - u256 expectedCount = u256(o["nonce"].asString()); - u256 count = _client.countAt(address); + u256 expectedCount = u256(_o["nonce"].asString()); + u256 count = _client.countAt(address, _blockNumber); ETH_CHECK_EQUAL(expectedCount, count); // stateAt - for (string const& pos: o["storage"].getMemberNames()) + for (string const& pos: _o["storage"].getMemberNames()) { - u256 expectedState = u256(o["storage"][pos].asString()); - u256 state = _client.stateAt(address, u256(pos)); + u256 expectedState = u256(_o["storage"][pos].asString()); + u256 state = _client.stateAt(address, u256(pos), _blockNumber); ETH_CHECK_EQUAL(expectedState, state); } // codeAt - bytes expectedCode = fromHex(o["code"].asString()); - bytes code = _client.codeAt(address); + bytes expectedCode = fromHex(_o["code"].asString()); + bytes code = _client.codeAt(address, _blockNumber); ETH_CHECK_EQUAL_COLLECTIONS(expectedCode.begin(), expectedCode.end(), - code.begin(), code.end()); + code.begin(), code.end()); + }; + + for (string const& name: _json["postState"].getMemberNames()) + { + Json::Value o = _json["postState"][name]; + compareState(o, name, PendingBlock); + } + + for (string const& name: _json["pre"].getMemberNames()) + { + Json::Value o = _json["pre"][name]; + compareState(o, name, 0); } // number From d82a3ca956c0db1061df92c04220e935b6fa58d1 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 30 Mar 2015 15:14:59 +0200 Subject: [PATCH 30/35] Detect if non-existant parameter is documented with natspec --- SolidityNatspecJSON.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/SolidityNatspecJSON.cpp b/SolidityNatspecJSON.cpp index edfe89861..4e6c98556 100644 --- a/SolidityNatspecJSON.cpp +++ b/SolidityNatspecJSON.cpp @@ -176,7 +176,6 @@ BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) "}\n"; char const* devNatspec = "{\"methods\":{}}"; - char const* userNatspec = "{\"methods\":{}}"; checkNatspec(sourceCode, devNatspec, false); @@ -230,6 +229,18 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params) checkNatspec(sourceCode, natspec, false); } +BOOST_AUTO_TEST_CASE(dev_documenting_nonexistant_param) +{ + char const* sourceCode = "contract test {\n" + " /// @dev Multiplies a number by 7 and adds second parameter\n" + " /// @param a Documentation for the first parameter\n" + " /// @param not_existing Documentation for the second parameter\n" + " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + "}\n"; + + BOOST_CHECK_THROW(checkNatspec(sourceCode, natspec, false), DocstringParsingError); +} + BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) { char const* sourceCode = "contract test {\n" From 57432fe671110335b3779f4b03a76df133ee927d Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 30 Mar 2015 15:32:25 +0200 Subject: [PATCH 31/35] no need to have target json for failing tests --- SolidityNatspecJSON.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/SolidityNatspecJSON.cpp b/SolidityNatspecJSON.cpp index 4e6c98556..aeaad1966 100644 --- a/SolidityNatspecJSON.cpp +++ b/SolidityNatspecJSON.cpp @@ -238,7 +238,7 @@ BOOST_AUTO_TEST_CASE(dev_documenting_nonexistant_param) " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" "}\n"; - BOOST_CHECK_THROW(checkNatspec(sourceCode, natspec, false), DocstringParsingError); + BOOST_CHECK_THROW(checkNatspec(sourceCode, "", false), DocstringParsingError); } BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) @@ -498,17 +498,7 @@ BOOST_AUTO_TEST_CASE(dev_title_at_function_error) " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" "}\n"; - char const* natspec = "{" - " \"author\": \"Lefteris\"," - " \"title\": \"Just a test contract\"," - " \"methods\":{" - " \"mul(uint256,uint256)\":{ \n" - " \"details\": \"Mul function\"\n" - " }\n" - " }\n" - "}"; - - BOOST_CHECK_THROW(checkNatspec(sourceCode, natspec, false), DocstringParsingError); + BOOST_CHECK_THROW(checkNatspec(sourceCode, "", false), DocstringParsingError); } BOOST_AUTO_TEST_CASE(natspec_notice_without_tag) From de09be29ba80486b7fddafef4b740d5093d0c726 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 30 Mar 2015 17:18:38 +0200 Subject: [PATCH 32/35] Fix some styling issues and remove comments --- SolidityNameAndTypeResolution.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index 8eb83b117..a1f780134 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -384,10 +384,10 @@ BOOST_AUTO_TEST_CASE(create_abstract_contract) ASTPointer sourceUnit; char const* text = R"( contract base { function foo(); } - contract derived { + contract derived { base b; - function foo() { b = new base();} - } + function foo() { b = new base();} + } )"; BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } From b1a2292e77adcc2dab39fd76f15d7ca45ab64ae4 Mon Sep 17 00:00:00 2001 From: subtly Date: Tue, 31 Mar 2015 10:28:46 +0200 Subject: [PATCH 33/35] Fix #1475 --- peer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/peer.cpp b/peer.cpp index 48431504f..904de0e9d 100644 --- a/peer.cpp +++ b/peer.cpp @@ -57,6 +57,15 @@ BOOST_AUTO_TEST_CASE(host) g_logVerbosity = oldLogVerbosity; } +BOOST_AUTO_TEST_CASE(networkConfig) +{ + Host save("Test", NetworkPreferences(false)); + bytes store(save.saveNetwork()); + + Host restore("Test", NetworkPreferences(false), bytesConstRef(&store)); + BOOST_REQUIRE(save.id() == restore.id()); +} + BOOST_AUTO_TEST_CASE(save_nodes) { std::list hosts; From 8a94b58e4805598ad285866646711506d1681d1a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 31 Mar 2015 18:54:50 +0200 Subject: [PATCH 34/35] Upgrade to latest ethhash API. --- dagger.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dagger.cpp b/dagger.cpp index f7230f705..4dda9c4fc 100644 --- a/dagger.cpp +++ b/dagger.cpp @@ -63,8 +63,8 @@ BOOST_AUTO_TEST_CASE(basic_test) unsigned cacheSize(o["cache_size"].get_int()); h256 cacheHash(o["cache_hash"].get_str()); - BOOST_REQUIRE_EQUAL(Ethasher::get()->cache(header).size(), cacheSize); - BOOST_REQUIRE_EQUAL(sha3(Ethasher::get()->cache(header)), cacheHash); + BOOST_REQUIRE_EQUAL(Ethasher::get()->params(header).cache_size, cacheSize); + BOOST_REQUIRE_EQUAL(sha3(bytesConstRef((byte const*)Ethasher::get()->cache(header), cacheSize)), cacheHash); #if TEST_FULL unsigned fullSize(o["full_size"].get_int()); From 9d734e03fd085a3cbd1a403bd63e51da19e165b5 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Mon, 30 Mar 2015 14:34:38 +0200 Subject: [PATCH 35/35] changed checking for external type in VariableDeclaration::checkTypeRequirements() changed error msg --- SolidityNameAndTypeResolution.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index ddcf36140..531f3bc13 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -460,7 +460,7 @@ BOOST_AUTO_TEST_CASE(function_external_types) uint a; } contract Test { - function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs, uint[] dynamic, C carg) external returns (uint ret) { + function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs, uint[] dynamic, C carg, address[] addresses) external returns (uint ret) { ret = 5; } })"; @@ -471,7 +471,7 @@ BOOST_AUTO_TEST_CASE(function_external_types) auto functions = contract->getDefinedFunctions(); if (functions.empty()) continue; - BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8,bool[2],uint256[],address)", functions[0]->externalSignature()); + BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8,bool[2],uint256[],address,address[])", functions[0]->externalSignature()); } } @@ -503,6 +503,16 @@ BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +// todo delete when implemented +BOOST_AUTO_TEST_CASE(arrays_in_internal_functions) +{ + char const* text = R"( + contract Test { + function foo(address[] addresses) {} + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion) { char const* text = R"(