aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt39
-rw-r--r--ClientBase.cpp202
-rw-r--r--SolidityNameAndTypeResolution.cpp159
-rw-r--r--SolidityNatspecJSON.cpp25
-rw-r--r--SolidityOptimizer.cpp210
-rw-r--r--SolidityParser.cpp8
-rw-r--r--TestHelper.cpp16
-rw-r--r--TestHelper.h2
-rw-r--r--TestUtils.cpp117
-rw-r--r--TestUtils.h82
-rw-r--r--blockchain.cpp57
-rw-r--r--checkRandomStateTest.cpp3
-rw-r--r--createRandomStateTest.cpp3
-rw-r--r--net.cpp38
-rw-r--r--peer.cpp14
-rw-r--r--solidityExecutionFramework.h3
-rw-r--r--state.cpp3
-rw-r--r--stateOriginal.cpp10
-rw-r--r--transaction.cpp7
-rw-r--r--ttTransactionTestFiller.json15
20 files changed, 908 insertions, 105 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ef292c2b..01681dbe 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})
@@ -30,6 +45,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 +58,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 00000000..2197ac83
--- /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 <http://www.gnu.org/licenses/>.
+ */
+/** @file ClientBase.cpp
+ * @author Marek Kotewicz <marek@ethdev.com>
+ * @date 2015
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <libdevcore/CommonJS.h>
+#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/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp
index 591cf053..ddcf3614 100644
--- a/SolidityNameAndTypeResolution.cpp
+++ b/SolidityNameAndTypeResolution.cpp
@@ -28,6 +28,7 @@
#include <libsolidity/Parser.h>
#include <libsolidity/NameAndTypeResolver.h>
#include <libsolidity/Exceptions.h>
+#include <libsolidity/GlobalContext.h>
#include "TestHelper.h"
using namespace std;
@@ -48,16 +49,28 @@ ASTPointer<SourceUnit> parseTextAndResolveNames(std::string const& _source)
ASTPointer<SourceUnit> sourceUnit = parser.parse(std::make_shared<Scanner>(CharStream(_source)));
NameAndTypeResolver resolver({});
resolver.registerDeclarations(*sourceUnit);
+ std::shared_ptr<GlobalContext> globalContext = make_shared<GlobalContext>();
+
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
+ {
+ globalContext->setCurrentContract(*contract);
+ resolver.updateDeclaration(*globalContext->getCurrentThis());
+ resolver.updateDeclaration(*globalContext->getCurrentSuper());
resolver.resolveNamesAndTypes(*contract);
+ }
for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
+ {
+ globalContext->setCurrentContract(*contract);
+ resolver.updateDeclaration(*globalContext->getCurrentThis());
resolver.checkTypeRequirements(*contract);
+ }
return sourceUnit;
}
+
static ContractDefinition const* retrieveContract(ASTPointer<SourceUnit> _source, unsigned index)
{
ContractDefinition* contract;
@@ -346,6 +359,63 @@ 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> 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");
+ std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->getNodes();
+ ContractDefinition* contract = dynamic_cast<ContractDefinition*>(nodes[0].get());
+ BOOST_CHECK(contract);
+ BOOST_CHECK(!contract->isFullyImplemented());
+ BOOST_CHECK(!contract->getDefinedFunctions()[0]->isFullyImplemented());
+}
+
+BOOST_AUTO_TEST_CASE(abstract_contract)
+{
+ ASTPointer<SourceUnit> 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<ASTPointer<ASTNode>> nodes = sourceUnit->getNodes();
+ ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[0].get());
+ ContractDefinition* derived = dynamic_cast<ContractDefinition*>(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> 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> 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> sourceUnit;
@@ -359,7 +429,7 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature)
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(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]->externalSignature());
}
}
@@ -376,10 +446,95 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases)
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
{
auto functions = contract->getDefinedFunctions();
- BOOST_CHECK_EQUAL("boo(uint256,bytes32,address)", functions[0]->getCanonicalSignature());
+ if (functions.empty())
+ continue;
+ BOOST_CHECK_EQUAL("boo(uint256,bytes32,address)", functions[0]->externalSignature());
+ }
+}
+
+BOOST_AUTO_TEST_CASE(function_external_types)
+{
+ ASTPointer<SourceUnit> sourceUnit;
+ char const* text = R"(
+ contract C {
+ uint a;
+ }
+ contract Test {
+ function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs, uint[] dynamic, C carg) external returns (uint ret) {
+ ret = 5;
+ }
+ })";
+ ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed");
+ for (ASTPointer<ASTNode> const& node: sourceUnit->getNodes())
+ if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
+ {
+ auto functions = contract->getDefinedFunctions();
+ if (functions.empty())
+ continue;
+ BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8,bool[2],uint256[],address)", functions[0]->externalSignature());
}
}
+BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion)
+{
+ 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() {
+ address arg;
+ this.g(arg);
+ }
+ function g (C c) external {}
+ })";
+ BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
+}
+
+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 {
+ 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)
{
char const* text = "contract test {\n"
diff --git a/SolidityNatspecJSON.cpp b/SolidityNatspecJSON.cpp
index edfe8986..aeaad196 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, "", false), DocstringParsingError);
+}
+
BOOST_AUTO_TEST_CASE(dev_mutiline_param_description)
{
char const* sourceCode = "contract test {\n"
@@ -487,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)
diff --git a/SolidityOptimizer.cpp b/SolidityOptimizer.cpp
index 85b77d21..2d5cff7a 100644
--- a/SolidityOptimizer.cpp
+++ b/SolidityOptimizer.cpp
@@ -26,8 +26,11 @@
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <test/solidityExecutionFramework.h>
+#include <libevmcore/CommonSubexpressionEliminator.h>
+#include <libevmcore/Assembly.h>
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<string>(sizeDiff) + " bytes, expected: "
- + boost::lexical_cast<string>(_expectedSizeDecrease));
+ BOOST_CHECK_MESSAGE(
+ nonOptimizedBytecode.size() > optimizedBytecode.size(),
+ "Optimizer did not reduce bytecode size."
+ );
m_optimizedContract = m_contractAddress;
}
@@ -66,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;
@@ -81,24 +97,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 +109,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 +123,7 @@ BOOST_AUTO_TEST_CASE(unused_expressions)
data;
}
})";
- compileBothVersions(36, sourceCode);
+ compileBothVersions(sourceCode);
compareVersions("f()");
}
@@ -135,10 +138,171 @@ 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)
+{
+ AssemblyItems input{Instruction::DUP2, u256(0)};
+ checkCSE(input, input);
+}
+
+BOOST_AUTO_TEST_CASE(cse_negative_stack_end)
+{
+ AssemblyItems input{Instruction::ADD};
+ checkCSE(input, input);
+}
+
+BOOST_AUTO_TEST_CASE(cse_intermediate_negative_stack)
+{
+ AssemblyItems input{Instruction::ADD, u256(1), Instruction::DUP1};
+ checkCSE(input, input);
+}
+
+BOOST_AUTO_TEST_CASE(cse_pop)
+{
+ checkCSE({Instruction::POP}, {Instruction::POP});
+}
+
+BOOST_AUTO_TEST_CASE(cse_unneeded_items)
+{
+ AssemblyItems input{
+ Instruction::ADD,
+ Instruction::SWAP1,
+ Instruction::POP,
+ u256(7),
+ u256(8),
+ };
+ 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{
+ 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_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()
}
diff --git a/SolidityParser.cpp b/SolidityParser.cpp
index 392d9ac4..7640f91a 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"
diff --git a/TestHelper.cpp b/TestHelper.cpp
index b3e64f47..295b759f 100644
--- a/TestHelper.cpp
+++ b/TestHelper.cpp
@@ -375,22 +375,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<void(json_spirit::mValue&, bool)> doTests)
{
for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
diff --git a/TestHelper.h b/TestHelper.h
index 05e01792..e5f96f51 100644
--- a/TestHelper.h
+++ b/TestHelper.h
@@ -28,6 +28,7 @@
#include "JsonSpiritHeaders.h"
#include <libethereum/State.h>
#include <libevm/ExtVMFace.h>
+#include <libtestutils/Common.h>
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<void(json_spirit::mValue&, bool)> doTests);
-std::string getTestPath();
void userDefinedTest(std::string testTypeFlag, std::function<void(json_spirit::mValue&, bool)> 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 00000000..6222955d
--- /dev/null
+++ b/TestUtils.cpp
@@ -0,0 +1,117 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+ */
+/** @file TestUtils.cpp
+ * @author Marek Kotewicz <marek@ethdev.com>
+ * @date 2015
+ */
+
+#include <thread>
+#include <boost/test/unit_test.hpp>
+#include <boost/filesystem.hpp>
+#include <libtestutils/BlockChainLoader.h>
+#include <libtestutils/FixedClient.h>
+#include "TestUtils.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 "";
+}
+
+LoadTestFileFixture::LoadTestFileFixture()
+{
+ m_json = loadJsonFromFile(toTestFilePath(getCommandLineArgument("--eth_testfile")));
+}
+
+void ParallelFixture::enumerateThreads(std::function<void()> callback) const
+{
+ size_t threadsCount = std::stoul(getCommandLineArgument("--eth_threads"), nullptr, 10);
+
+ vector<thread> 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<void(Json::Value const&, dev::eth::BlockChain const&, State state)> callback) const
+{
+ 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<void(Json::Value const&, dev::eth::ClientBase&)> callback) const
+{
+ enumerateBlockchains([&callback](Json::Value const& _json, BlockChain const& _bc, State _state) -> void
+ {
+ FixedClient client(_bc, _state);
+ callback(_json, client);
+ });
+}
+
+void ParallelClientBaseFixture::enumerateClients(std::function<void(Json::Value const&, dev::eth::ClientBase&)> callback) const
+{
+ 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 00000000..f9817c21
--- /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 <http://www.gnu.org/licenses/>.
+ */
+/** @file TestUtils.h
+ * @author Marek Kotewicz <marek@ethdev.com>
+ * @date 2015
+ */
+
+#pragma once
+
+#include <functional>
+#include <string>
+#include <json/json.h>
+#include <libethereum/BlockChain.h>
+#include <libethereum/ClientBase.h>
+
+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();
+
+protected:
+ Json::Value m_json;
+};
+
+struct ParallelFixture
+{
+ void enumerateThreads(std::function<void()> callback) const;
+};
+
+struct BlockChainFixture: public LoadTestFileFixture
+{
+ void enumerateBlockchains(std::function<void(Json::Value const&, dev::eth::BlockChain const&, dev::eth::State state)> callback) const;
+};
+
+struct ClientBaseFixture: public BlockChainFixture
+{
+ void enumerateClients(std::function<void(Json::Value const&, dev::eth::ClientBase&)> callback) const;
+};
+
+// 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<void(Json::Value const&, dev::eth::ClientBase&)> callback) const;
+};
+
+struct JsonRpcFixture: public ClientBaseFixture
+{
+
+};
+
+}
+}
diff --git a/blockchain.cpp b/blockchain.cpp
index 50ca22c5..17e6c358 100644
--- a/blockchain.cpp
+++ b/blockchain.cpp
@@ -20,7 +20,9 @@
* block test functions.
*/
+#include <boost/filesystem.hpp>
#include <libdevcrypto/FileSystem.h>
+#include <libtestutils/TransientDirectory.h>
#include <libethereum/CanonBlockChain.h>
#include "TestHelper.h"
@@ -35,8 +37,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 +77,8 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
o["genesisRLP"] = "0x" + toHex(rlpGenesisBlock.out());
// construct blockchain
- BlockChain bc(rlpGenesisBlock.out(), string(), true);
+ TransientDirectory td;
+ BlockChain bc(rlpGenesisBlock.out(), td.path(), true);
if (_fillin)
{
@@ -182,18 +185,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);
}
@@ -242,6 +244,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);
@@ -293,7 +296,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);
@@ -389,7 +392,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
@@ -489,12 +491,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());
@@ -540,16 +542,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<MineInfo, Ethash::Proof> 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);
}
}
}
@@ -558,13 +560,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
{
@@ -601,7 +602,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);
@@ -621,7 +622,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);
@@ -633,8 +634,8 @@ RLPStream createFullBlockFromHeader(const BlockInfo& _bi,const bytes& _txs, cons
return ret;
}
-} }// Namespace Close
+} }// Namespace Close
BOOST_AUTO_TEST_SUITE(BlockChainTests)
diff --git a/checkRandomStateTest.cpp b/checkRandomStateTest.cpp
index a4d390b1..49aca852 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 f422d171..5758598b 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/net.cpp b/net.cpp
index 7ba2d8a1..ec1efb36 100644
--- a/net.cpp
+++ b/net.cpp
@@ -145,7 +145,41 @@ public:
bool success = false;
};
-BOOST_AUTO_TEST_CASE(badPingNodePacket)
+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
RLPStream s;
@@ -153,7 +187,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)
diff --git a/peer.cpp b/peer.cpp
index bfb4680d..48431504 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();
@@ -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));
@@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(save_nodes)
std::list<Host*> 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();
@@ -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));
diff --git a/solidityExecutionFramework.h b/solidityExecutionFramework.h
index 86062a90..2451aa38 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 8168693b..e4bf06bd 100644
--- a/state.cpp
+++ b/state.cpp
@@ -53,13 +53,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 5b7b0415..384d8534 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;
diff --git a/transaction.cpp b/transaction.cpp
index 77f6ecda..4c57326b 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 0058feac..c04b7684 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": ""
+ }
}
}