From a1f32a0b26dd2fe1fa8f3a2e35bd981223181bf8 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 6 Oct 2014 17:13:52 +0200 Subject: [PATCH 01/48] Solidity scanner and some unit tests. The scanner is a modified version of the v8 javascript scanner. --- CMakeLists.txt | 1 + solidityScanner.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 solidityScanner.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6936addb3..b4d0e46bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ target_link_libraries(testeth ethereum) target_link_libraries(testeth ethcore) target_link_libraries(testeth secp256k1) target_link_libraries(testeth gmp) +target_link_libraries(testeth solidity) target_link_libraries(testeth ${CRYPTOPP_LS}) if ("${TARGET_PLATFORM}" STREQUAL "w64") diff --git a/solidityScanner.cpp b/solidityScanner.cpp new file mode 100644 index 000000000..afbcdffae --- /dev/null +++ b/solidityScanner.cpp @@ -0,0 +1,139 @@ +/* + 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 . +*/ +/** + * @author Christian + * @date 2014 + * Unit tests for the solidity scanner. + */ + +#include +#include + +namespace dev { +namespace solidity { +namespace test { + +BOOST_AUTO_TEST_SUITE(solidity) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::FUNCTION); + BOOST_CHECK_EQUAL(scanner.next(), Token::BREAK); + BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765"); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1"); + BOOST_CHECK_EQUAL(scanner.next(), Token::COMMA); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2"); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1"); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(string_escapes) +{ + Scanner scanner(CharStream(" { \"a\\x61\"")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa"); +} + +BOOST_AUTO_TEST_CASE(string_escapes_with_zero) +{ + Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6)); +} + +BOOST_AUTO_TEST_CASE(string_escape_illegal) +{ + Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ""); + // TODO recovery from illegal tokens should be improved + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(hex_numbers) +{ + Scanner scanner(CharStream("var x = 0x765432536763762734623472346;")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::VAR); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "0x765432536763762734623472346"); + BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(locations) +{ + Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 0); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 19); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 20); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 23); + BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 24); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 25); + BOOST_CHECK_EQUAL(scanner.next(), Token::SUB); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 26); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 27); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 27); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 32); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 45); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 50); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(ambiguities) +{ + // test scanning of some operators which need look-ahead + Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::LTE); + BOOST_CHECK_EQUAL(scanner.next(), Token::LT); + BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN_ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::INC); + BOOST_CHECK_EQUAL(scanner.next(), Token::ARROW); + BOOST_CHECK_EQUAL(scanner.next(), Token::SHL); +} + + +BOOST_AUTO_TEST_SUITE_END() + +} } } // end namespaces From 762817f8383b5ddbf4de7f0c3595681e7c89f69a Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 7 Oct 2014 18:25:04 +0200 Subject: [PATCH 02/48] Solidity parser, can not parse much yet. --- solidityParser.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++ solidityScanner.cpp | 37 ++++++++++++++++---------------- 2 files changed, 70 insertions(+), 19 deletions(-) create mode 100644 solidityParser.cpp diff --git a/solidityParser.cpp b/solidityParser.cpp new file mode 100644 index 000000000..f42506767 --- /dev/null +++ b/solidityParser.cpp @@ -0,0 +1,52 @@ +/* + 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 . +*/ +/** + * @author Christian + * @date 2014 + * Unit tests for the solidity parser. + */ + +#include + +#include +#include +#include + +namespace dev { +namespace solidity { +namespace test { + +BOOST_AUTO_TEST_SUITE(SolidityParser) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + std::string text = "contract test123 {\n" + "\tuint256 stateVariable1;\n" + "}\n"; + Parser parser; + CharStream str(text); + // @todo: figure out why this does not compile + //Scanner scanner(CharStream(text)); + Scanner scanner(str); + BOOST_CHECK_NO_THROW(parser.parse(scanner)); +} + + +BOOST_AUTO_TEST_SUITE_END() + +} } } // end namespaces + diff --git a/solidityScanner.cpp b/solidityScanner.cpp index afbcdffae..7f84146a3 100644 --- a/solidityScanner.cpp +++ b/solidityScanner.cpp @@ -27,21 +27,26 @@ namespace dev { namespace solidity { namespace test { -BOOST_AUTO_TEST_SUITE(solidity) +BOOST_AUTO_TEST_SUITE(SolidityScanner) + +BOOST_AUTO_TEST_CASE(test_empty) +{ + Scanner scanner(CharStream("")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS); +} BOOST_AUTO_TEST_CASE(smoke_test) { Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::FUNCTION); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::FUNCTION); BOOST_CHECK_EQUAL(scanner.next(), Token::BREAK); BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765"); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1"); BOOST_CHECK_EQUAL(scanner.next(), Token::COMMA); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2"); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1"); @@ -51,26 +56,23 @@ BOOST_AUTO_TEST_CASE(smoke_test) BOOST_AUTO_TEST_CASE(string_escapes) { Scanner scanner(CharStream(" { \"a\\x61\"")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::LBRACE); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa"); } BOOST_AUTO_TEST_CASE(string_escapes_with_zero) { Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::LBRACE); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6)); } BOOST_AUTO_TEST_CASE(string_escape_illegal) { Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ""); // TODO recovery from illegal tokens should be improved @@ -83,8 +85,7 @@ BOOST_AUTO_TEST_CASE(string_escape_illegal) BOOST_AUTO_TEST_CASE(hex_numbers) { Scanner scanner(CharStream("var x = 0x765432536763762734623472346;")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::VAR); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::VAR); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN); BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); @@ -96,8 +97,7 @@ BOOST_AUTO_TEST_CASE(hex_numbers) BOOST_AUTO_TEST_CASE(locations) { Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 0); BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 19); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); @@ -122,8 +122,7 @@ BOOST_AUTO_TEST_CASE(ambiguities) { // test scanning of some operators which need look-ahead Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::LTE); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LTE); BOOST_CHECK_EQUAL(scanner.next(), Token::LT); BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN_ADD); From 9766467f50a5a34776d80744238687fea3fbbec0 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 8 Oct 2014 20:53:50 +0200 Subject: [PATCH 03/48] Parse everything up to function bodies and report parser errors with location. --- solidityParser.cpp | 103 ++++++++++++++++++++++++++++++++++++++++---- solidityScanner.cpp | 24 +++++------ 2 files changed, 106 insertions(+), 21 deletions(-) diff --git a/solidityParser.cpp b/solidityParser.cpp index f42506767..91247a3b7 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -30,19 +31,103 @@ namespace dev { namespace solidity { namespace test { +namespace { + ptr parseText(const std::string& _source) + { + Parser parser; + return parser.parse(std::make_shared(CharStream(_source))); + } +} + BOOST_AUTO_TEST_SUITE(SolidityParser) BOOST_AUTO_TEST_CASE(smoke_test) { - std::string text = "contract test123 {\n" - "\tuint256 stateVariable1;\n" - "}\n"; - Parser parser; - CharStream str(text); - // @todo: figure out why this does not compile - //Scanner scanner(CharStream(text)); - Scanner scanner(str); - BOOST_CHECK_NO_THROW(parser.parse(scanner)); + char const* text = "contract test {\n" + " uint256 stateVariable1;\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration) +{ + char const* text = "contract test {\n" + " uint256 ;\n" + "}\n"; + cwarn << "The next error is expected."; + BOOST_CHECK_THROW(parseText(text), std::exception); +} + +BOOST_AUTO_TEST_CASE(empty_function) +{ + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " function functionName(hash160 arg1, address addr) const\n" + " returns (int id)\n" + " { }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(no_function_params) +{ + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " function functionName() {}\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(single_function_param) +{ + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " function functionName(hash hashin) returns (hash hashout) {}\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(struct_definition) +{ + char const* text = "contract test {\n" + " uint256 stateVar;\n" + " struct MyStructName {\n" + " address addr;\n" + " uint256 count;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(mapping) +{ + char const* text = "contract test {\n" + " mapping(address => string) names;\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(mapping_in_struct) +{ + char const* text = "contract test {\n" + " struct test_struct {\n" + " address addr;\n" + " uint256 count;\n" + " mapping(hash => test_struct) self_reference;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(mapping_to_mapping_in_struct) +{ + char const* text = "contract test {\n" + " struct test_struct {\n" + " address addr;\n" + " mapping (uint64 => mapping (hash => uint)) complex_mapping;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); } diff --git a/solidityScanner.cpp b/solidityScanner.cpp index 7f84146a3..759d2f101 100644 --- a/solidityScanner.cpp +++ b/solidityScanner.cpp @@ -98,23 +98,23 @@ BOOST_AUTO_TEST_CASE(locations) { Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 0); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 19); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 0); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 19); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 20); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 23); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 20); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 23); BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 24); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 25); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 25); BOOST_CHECK_EQUAL(scanner.next(), Token::SUB); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 26); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 27); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 26); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 27); BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 27); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 32); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 27); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32); BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().beg_pos, 45); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end_pos, 50); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 50); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } From 51f335838c4d882e71fe8e09f744f9ed40391e02 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 9 Oct 2014 15:57:49 +0200 Subject: [PATCH 04/48] Initial implementation of Solidity parser finished, not yet tested much. --- solidityParser.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/solidityParser.cpp b/solidityParser.cpp index 91247a3b7..86d09f170 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -130,6 +130,84 @@ BOOST_AUTO_TEST_CASE(mapping_to_mapping_in_struct) BOOST_CHECK_NO_THROW(parseText(text)); } +BOOST_AUTO_TEST_CASE(variable_definition) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " var b;\n" + " uint256 c;\n" + " mapping(address=>hash) d;\n" + " customtype varname;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(variable_definition_with_initialization) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " var b = 2;\n" + " uint256 c = 0x87;\n" + " mapping(address=>hash) d;\n" + " string name = \"Solidity\";" + " customtype varname;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(operator_expression) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " uint256 x = (1 + 4) || false && (1 - 12) + -9;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(complex_expression) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " uint256 x = (1 + 4).member(++67)[a/=9] || true;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(while_loop) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " uint256 x = (1 + 4).member(++67) || true;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(if_statement) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) {\n" + " if (a >= 8) return 2; else { var b = 7; }\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(else_if_statement) +{ + char const* text = "contract test {\n" + " function fun(uint256 a) returns (address b) {\n" + " if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + + BOOST_AUTO_TEST_SUITE_END() From 9c9a529b9d08e28a000ba537488aad136bfe9789 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 13 Oct 2014 15:07:21 +0200 Subject: [PATCH 05/48] Name resolution. --- solidityNameAndTypeResolution.cpp | 113 ++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 solidityNameAndTypeResolution.cpp diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp new file mode 100644 index 000000000..568025e5a --- /dev/null +++ b/solidityNameAndTypeResolution.cpp @@ -0,0 +1,113 @@ +/* + 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 . +*/ +/** + * @author Christian + * @date 2014 + * Unit tests for the name and type resolution of the solidity parser. + */ + +#include + +#include +#include +#include +#include +#include + +namespace dev { +namespace solidity { +namespace test { + +namespace { + void parseTextAndResolveNames(const std::string& _source) + { + Parser parser; + ptr contract = parser.parse( + std::make_shared(CharStream(_source))); + NameAndTypeResolver resolver; + resolver.resolveNamesAndTypes(*contract); + } +} + +BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + char const* text = "contract test {\n" + " uint256 stateVariable1;\n" + " function fun(uint256 arg1) { var x = 2; uint256 y = 3; x = 1; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) +{ + char const* text = "contract test {\n" + " uint256 variable;\n" + " uint128 variable;\n" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); +} + +BOOST_AUTO_TEST_CASE(double_function_declaration) +{ + char const* text = "contract test {\n" + " function fun() { var x = 2; }\n" + " function fun() { var y = 9; }\n" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); +} + +BOOST_AUTO_TEST_CASE(double_variable_declaration) +{ + char const* text = "contract test {\n" + " function f() { uint256 x = 9; if (true) { uint256 x = 2;} x = 3; }\n" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); +} + +BOOST_AUTO_TEST_CASE(name_shadowing) +{ + char const* text = "contract test {\n" + " uint256 variable;\n" + " function f() { uint8 variable = 2; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(name_references) +{ + char const* text = "contract test {\n" + " uint256 variable;\n" + " function f() { variable = 2; f(); test; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(undeclared_name) +{ + char const* text = "contract test {\n" + " uint256 variable;\n" + " function f() { notfound = 2; }" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); +} + +BOOST_AUTO_TEST_SUITE_END() + +} } } // end namespaces + From 0abb8e9b1d9d3549068c5c3432444292b713cbc6 Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 15 Oct 2014 11:58:27 +0200 Subject: [PATCH 06/48] cryptopp aes128-cbc --- TestHelperCrypto.h | 10 ++++++---- crypto.cpp | 43 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/TestHelperCrypto.h b/TestHelperCrypto.h index 6feeeb97f..7e38c438a 100644 --- a/TestHelperCrypto.h +++ b/TestHelperCrypto.h @@ -22,11 +22,13 @@ #pragma once //#include -#include -#include -#include #include -#include +#include // secp256r1 +#include // ec domain +#include // ec prime field +#include // also for buffer +#include +#include // aes modes using namespace std; using namespace CryptoPP; diff --git a/crypto.cpp b/crypto.cpp index 25106a77f..0f0a5f607 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdh_prime) cnote << "Testing cryptopp_ecdh_prime..."; using namespace CryptoPP; - OID curve = ASN1::secp256r1(); + OID curve = ASN1::secp256k1(); ECDH::Domain dhLocal(curve); SecByteBlock privLocal(dhLocal.PrivateKeyLength()); @@ -136,14 +136,51 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdh_prime) assert(ssLocal == ssRemote); } +BOOST_AUTO_TEST_CASE(cryptopp_aes128_cbc) +{ + const int aesKeyLen = 16; + assert(sizeof(char) == sizeof(byte)); + + AutoSeededRandomPool rng; + SecByteBlock key(0x00, aesKeyLen); + rng.GenerateBlock(key, key.size()); + + // Generate random IV + byte iv[AES::BLOCKSIZE]; + rng.GenerateBlock(iv, AES::BLOCKSIZE); + + string string128("AAAAAAAAAAAAAAAA"); + string plainOriginal = string128; + + CryptoPP::CBC_Mode::Encryption cbcEncryption(key, key.size(), iv); + cbcEncryption.ProcessData((byte*)&string128[0], (byte*)&string128[0], string128.size()); + assert(string128 != plainOriginal); + + CBC_Mode::Decryption cbcDecryption(key, key.size(), iv); + cbcDecryption.ProcessData((byte*)&string128[0], (byte*)&string128[0], string128.size()); + assert(plainOriginal == string128); + + + // plaintext whose size isn't divisible by block size must use stream filter for padding + string string192("AAAAAAAAAAAAAAAABBBBBBBB"); + plainOriginal = string192; + + string cipher; + StreamTransformationFilter* aesStream = new StreamTransformationFilter(cbcEncryption, new StringSink(cipher)); + StringSource source(string192, true, aesStream); + assert(cipher.size() == 32); + + cbcDecryption.ProcessData((byte*)&cipher[0], (byte*)&string192[0], cipher.size()); + assert(string192 == plainOriginal); +} + BOOST_AUTO_TEST_CASE(cryptopp_ecdh_aes128_cbc_noauth) { // ECDH gives 256-bit shared while aes uses 128-bits // Use first 128-bits of shared secret as symmetric key // IV is 0 // New connections require new ECDH keypairs - - + } BOOST_AUTO_TEST_CASE(cryptopp_eth_fbba) From de155c13efcfa0b88b17fd8eb297b660d99ffcc0 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 13 Oct 2014 18:22:15 +0200 Subject: [PATCH 07/48] Type system, not yet complete. --- solidityNameAndTypeResolution.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index 568025e5a..5a938e461 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) { char const* text = "contract test {\n" " uint256 stateVariable1;\n" - " function fun(uint256 arg1) { var x = 2; uint256 y = 3; x = 1; }" + " function fun(uint256 arg1) { var x; uint256 y; }" "}\n"; BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } @@ -66,8 +66,8 @@ BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) BOOST_AUTO_TEST_CASE(double_function_declaration) { char const* text = "contract test {\n" - " function fun() { var x = 2; }\n" - " function fun() { var y = 9; }\n" + " function fun() { var x; }\n" + " function fun() { var x; }\n" "}\n"; BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); } @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(double_function_declaration) BOOST_AUTO_TEST_CASE(double_variable_declaration) { char const* text = "contract test {\n" - " function f() { uint256 x = 9; if (true) { uint256 x = 2;} x = 3; }\n" + " function f() { uint256 x; if (true) { uint256 x; } }\n" "}\n"; BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); } @@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(name_shadowing) { char const* text = "contract test {\n" " uint256 variable;\n" - " function f() { uint8 variable = 2; }" + " function f() { uint32 variable ; }" "}\n"; BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } @@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE(name_references) { char const* text = "contract test {\n" " uint256 variable;\n" - " function f() { variable = 2; f(); test; }" + " function f(uint256 arg) returns (uint out) { f(variable); test; out; }" "}\n"; BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } @@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(undeclared_name) { char const* text = "contract test {\n" " uint256 variable;\n" - " function f() { notfound = 2; }" + " function f(uint256 arg) { f(notfound); }" "}\n"; BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); } From 35383f9b882bdbadb79f5729aca9cf32f7fce17a Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 15 Oct 2014 14:45:51 +0200 Subject: [PATCH 08/48] Added meaningful exception types. --- solidityNameAndTypeResolution.cpp | 9 +++++---- solidityParser.cpp | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index 5a938e461..c9817eb46 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace dev { @@ -60,7 +61,7 @@ BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) " uint256 variable;\n" " uint128 variable;\n" "}\n"; - BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); + BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } BOOST_AUTO_TEST_CASE(double_function_declaration) @@ -69,7 +70,7 @@ BOOST_AUTO_TEST_CASE(double_function_declaration) " function fun() { var x; }\n" " function fun() { var x; }\n" "}\n"; - BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); + BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } BOOST_AUTO_TEST_CASE(double_variable_declaration) @@ -77,7 +78,7 @@ BOOST_AUTO_TEST_CASE(double_variable_declaration) char const* text = "contract test {\n" " function f() { uint256 x; if (true) { uint256 x; } }\n" "}\n"; - BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); + BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } BOOST_AUTO_TEST_CASE(name_shadowing) @@ -104,7 +105,7 @@ BOOST_AUTO_TEST_CASE(undeclared_name) " uint256 variable;\n" " function f(uint256 arg) { f(notfound); }" "}\n"; - BOOST_CHECK_THROW(parseTextAndResolveNames(text), std::exception); + BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } BOOST_AUTO_TEST_SUITE_END() diff --git a/solidityParser.cpp b/solidityParser.cpp index 86d09f170..b1f27bcb6 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace dev { @@ -54,8 +55,7 @@ BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration) char const* text = "contract test {\n" " uint256 ;\n" "}\n"; - cwarn << "The next error is expected."; - BOOST_CHECK_THROW(parseText(text), std::exception); + BOOST_CHECK_THROW(parseText(text), ParserError); } BOOST_AUTO_TEST_CASE(empty_function) From c2f3d27940cb36d1991d2464f36f320d9d656577 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 15 Oct 2014 15:54:41 +0200 Subject: [PATCH 09/48] Some fixes for the type system, should be quite usable now. --- solidityNameAndTypeResolution.cpp | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index c9817eb46..d2f99e83e 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -108,6 +108,64 @@ BOOST_AUTO_TEST_CASE(undeclared_name) BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } +BOOST_AUTO_TEST_CASE(reference_to_later_declaration) +{ + char const* text = "contract test {\n" + " function g() { f(); }" + " function f() { }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(type_inference_smoke_test) +{ + char const* text = "contract test {\n" + " function f(uint256 arg1, uint32 arg2) returns (bool ret) { var x = arg1 + arg2 == 8; ret = x; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(type_checking_return) +{ + char const* text = "contract test {\n" + " function f() returns (bool r) { return 1 >= 2; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(type_checking_return_wrong_number) +{ + char const* text = "contract test {\n" + " function f() returns (bool r1, bool r2) { return 1 >= 2; }" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type) +{ + char const* text = "contract test {\n" + " function f() returns (uint256 r) { return 1 >= 2; }" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(type_checking_function_call) +{ + char const* text = "contract test {\n" + " function f() returns (bool r) { return g(12, true) == 3; }\n" + " function g(uint256 a, bool b) returns (uint256 r) { }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) +{ + char const* text = "contract test {\n" + " function f() returns (int256 r) { var x = int256(uint32(2)); return x; }" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + BOOST_AUTO_TEST_SUITE_END() } } } // end namespaces From ee06ed2ff8fab08bc31662c298796c50009c2a11 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 16 Oct 2014 14:08:54 +0200 Subject: [PATCH 10/48] Corrected coding style. --- solidityNameAndTypeResolution.cpp | 32 +++--- solidityParser.cpp | 26 +++-- solidityScanner.cpp | 155 +++++++++++++++--------------- 3 files changed, 115 insertions(+), 98 deletions(-) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index d2f99e83e..ed2cb7b53 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -29,19 +29,23 @@ #include #include -namespace dev { -namespace solidity { -namespace test { +namespace dev +{ +namespace solidity +{ +namespace test +{ -namespace { - void parseTextAndResolveNames(const std::string& _source) - { - Parser parser; - ptr contract = parser.parse( - std::make_shared(CharStream(_source))); - NameAndTypeResolver resolver; - resolver.resolveNamesAndTypes(*contract); - } +namespace +{ +void parseTextAndResolveNames(const std::string& _source) +{ + Parser parser; + ptr contract = parser.parse( + std::make_shared(CharStream(_source))); + NameAndTypeResolver resolver; + resolver.resolveNamesAndTypes(*contract); +} } BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution) @@ -168,5 +172,7 @@ BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) BOOST_AUTO_TEST_SUITE_END() -} } } // end namespaces +} +} +} // end namespaces diff --git a/solidityParser.cpp b/solidityParser.cpp index b1f27bcb6..ef434cc35 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -28,16 +28,20 @@ #include #include -namespace dev { -namespace solidity { -namespace test { +namespace dev +{ +namespace solidity +{ +namespace test +{ -namespace { - ptr parseText(const std::string& _source) - { - Parser parser; - return parser.parse(std::make_shared(CharStream(_source))); - } +namespace +{ +ptr parseText(const std::string& _source) +{ + Parser parser; + return parser.parse(std::make_shared(CharStream(_source))); +} } BOOST_AUTO_TEST_SUITE(SolidityParser) @@ -211,5 +215,7 @@ BOOST_AUTO_TEST_CASE(else_if_statement) BOOST_AUTO_TEST_SUITE_END() -} } } // end namespaces +} +} +} // end namespaces diff --git a/solidityScanner.cpp b/solidityScanner.cpp index 759d2f101..d2a960cfb 100644 --- a/solidityScanner.cpp +++ b/solidityScanner.cpp @@ -23,116 +23,121 @@ #include #include -namespace dev { -namespace solidity { -namespace test { +namespace dev +{ +namespace solidity +{ +namespace test +{ BOOST_AUTO_TEST_SUITE(SolidityScanner) BOOST_AUTO_TEST_CASE(test_empty) { - Scanner scanner(CharStream("")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS); + Scanner scanner(CharStream("")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS); } BOOST_AUTO_TEST_CASE(smoke_test) { - Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::FUNCTION); - BOOST_CHECK_EQUAL(scanner.next(), Token::BREAK); - BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); - BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765"); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1"); - BOOST_CHECK_EQUAL(scanner.next(), Token::COMMA); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2"); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1"); - BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::FUNCTION); + BOOST_CHECK_EQUAL(scanner.next(), Token::BREAK); + BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765"); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1"); + BOOST_CHECK_EQUAL(scanner.next(), Token::COMMA); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2"); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1"); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } BOOST_AUTO_TEST_CASE(string_escapes) { - Scanner scanner(CharStream(" { \"a\\x61\"")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa"); + Scanner scanner(CharStream(" { \"a\\x61\"")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa"); } BOOST_AUTO_TEST_CASE(string_escapes_with_zero) { - Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); - BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6)); + Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE); + BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6)); } BOOST_AUTO_TEST_CASE(string_escape_illegal) { - Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ""); - // TODO recovery from illegal tokens should be improved - BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); - BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), ""); + // TODO recovery from illegal tokens should be improved + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } BOOST_AUTO_TEST_CASE(hex_numbers) { - Scanner scanner(CharStream("var x = 0x765432536763762734623472346;")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::VAR); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN); - BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); - BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "0x765432536763762734623472346"); - BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); - BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + Scanner scanner(CharStream("var x = 0x765432536763762734623472346;")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::VAR); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "0x765432536763762734623472346"); + BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } BOOST_AUTO_TEST_CASE(locations) { - Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 0); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 19); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 20); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 23); - BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 25); - BOOST_CHECK_EQUAL(scanner.next(), Token::SUB); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 26); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 27); - BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 27); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); - BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 50); - BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 0); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 19); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 20); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 23); + BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 25); + BOOST_CHECK_EQUAL(scanner.next(), Token::SUB); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 26); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 27); + BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 27); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); + BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 50); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } BOOST_AUTO_TEST_CASE(ambiguities) { - // test scanning of some operators which need look-ahead - Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<")); - BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LTE); - BOOST_CHECK_EQUAL(scanner.next(), Token::LT); - BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); - BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN_ADD); - BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); - BOOST_CHECK_EQUAL(scanner.next(), Token::INC); - BOOST_CHECK_EQUAL(scanner.next(), Token::ARROW); - BOOST_CHECK_EQUAL(scanner.next(), Token::SHL); + // test scanning of some operators which need look-ahead + Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LTE); + BOOST_CHECK_EQUAL(scanner.next(), Token::LT); + BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN_ADD); + BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); + BOOST_CHECK_EQUAL(scanner.next(), Token::INC); + BOOST_CHECK_EQUAL(scanner.next(), Token::ARROW); + BOOST_CHECK_EQUAL(scanner.next(), Token::SHL); } BOOST_AUTO_TEST_SUITE_END() -} } } // end namespaces +} +} +} // end namespaces From 224f43bf81b5cf7e54b0bdf95cd87e2d46bdb081 Mon Sep 17 00:00:00 2001 From: subtly Date: Sat, 18 Oct 2014 05:11:36 +0200 Subject: [PATCH 11/48] basic ecies class --- TestHelperCrypto.h | 2 - crypto.cpp | 114 ++++++++++++++------------------------------- 2 files changed, 35 insertions(+), 81 deletions(-) diff --git a/TestHelperCrypto.h b/TestHelperCrypto.h index 57e4e4201..24104f118 100644 --- a/TestHelperCrypto.h +++ b/TestHelperCrypto.h @@ -21,8 +21,6 @@ #pragma once -//#include - #pragma warning(push) #pragma warning(disable:4100 4244) #pragma GCC diagnostic push diff --git a/crypto.cpp b/crypto.cpp index 1c5b9a308..428fcb270 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -27,27 +27,38 @@ #include #include #include +#include +#include #include "TestHelperCrypto.h" using namespace std; using namespace dev; - -namespace dev -{ -namespace crypto -{ - -inline CryptoPP::AutoSeededRandomPool& PRNG() { - static CryptoPP::AutoSeededRandomPool prng; - return prng; -} - -} -} - +using namespace dev::crypto; using namespace CryptoPP; -BOOST_AUTO_TEST_SUITE(crypto) +BOOST_AUTO_TEST_SUITE(devcrypto) + +BOOST_AUTO_TEST_CASE(ecies) +{ + ECKeyPair k = ECKeyPair::create(); + + string message("Now is the time for all good men to come to the aide of humanity."); + bytes b = bytesConstRef(message).toBytes(); + ECIESEncryptor(&k).encrypt(b); + + bytesConstRef br(&b); + bytes plain = ECIESDecryptor(&k).decrypt(br); + + assert(plain == bytesConstRef(message).toBytes()); +} + +BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) +{ + // New connections require new ECDH keypairs + // Every new connection requires a new EC keypair + // Every new trust requires a new EC keypair + // All connections should share seed for PRF (or PRNG) for nonces +} BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) { @@ -55,9 +66,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) string const message("Now is the time for all good men to come to the aide of humanity."); - AutoSeededRandomPool prng; - - ECIES::Decryptor localDecryptor(prng, ASN1::secp256r1()); + ECIES::Decryptor localDecryptor(crypto::PRNG(), crypto::secp256k1()); SavePrivateKey(localDecryptor.GetPrivateKey()); ECIES::Encryptor localEncryptor(localDecryptor); @@ -65,31 +74,31 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) ECIES::Decryptor futureDecryptor; LoadPrivateKey(futureDecryptor.AccessPrivateKey()); - futureDecryptor.GetPrivateKey().ThrowIfInvalid(prng, 3); + futureDecryptor.GetPrivateKey().ThrowIfInvalid(crypto::PRNG(), 3); ECIES::Encryptor futureEncryptor; LoadPublicKey(futureEncryptor.AccessPublicKey()); - futureEncryptor.GetPublicKey().ThrowIfInvalid(prng, 3); + futureEncryptor.GetPublicKey().ThrowIfInvalid(crypto::PRNG(), 3); // encrypt/decrypt with local string cipherLocal; - StringSource ss1 (message, true, new PK_EncryptorFilter(prng, localEncryptor, new StringSink(cipherLocal) ) ); + StringSource ss1 (message, true, new PK_EncryptorFilter(crypto::PRNG(), localEncryptor, new StringSink(cipherLocal) ) ); string plainLocal; - StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(prng, localDecryptor, new StringSink(plainLocal) ) ); + StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(crypto::PRNG(), localDecryptor, new StringSink(plainLocal) ) ); // encrypt/decrypt with future string cipherFuture; - StringSource ss3 (message, true, new PK_EncryptorFilter(prng, futureEncryptor, new StringSink(cipherFuture) ) ); + StringSource ss3 (message, true, new PK_EncryptorFilter(crypto::PRNG(), futureEncryptor, new StringSink(cipherFuture) ) ); string plainFuture; - StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(prng, futureDecryptor, new StringSink(plainFuture) ) ); + StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(crypto::PRNG(), futureDecryptor, new StringSink(plainFuture) ) ); // decrypt local w/future string plainFutureFromLocal; - StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(prng, futureDecryptor, new StringSink(plainFutureFromLocal) ) ); + StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(crypto::PRNG(), futureDecryptor, new StringSink(plainFutureFromLocal) ) ); // decrypt future w/local string plainLocalFromFuture; - StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(prng, localDecryptor, new StringSink(plainLocalFromFuture) ) ); + StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(crypto::PRNG(), localDecryptor, new StringSink(plainLocalFromFuture) ) ); assert(plainLocal == message); @@ -173,60 +182,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_cbc) cbcDecryption.ProcessData((byte*)&cipher[0], (byte*)&string192[0], cipher.size()); assert(string192 == plainOriginal); } - -BOOST_AUTO_TEST_CASE(cryptopp_ecdh_aes128_cbc_noauth) -{ - // ECDH gives 256-bit shared while aes uses 128-bits - // Use first 128-bits of shared secret as symmetric key - // IV is 0 - // New connections require new ECDH keypairs -} - -BOOST_AUTO_TEST_CASE(cryptopp_eth_fbba) -{ - // Initial Authentication: - // - // New/Known Peer: - // pubkeyL = knownR? ? myKnown : myECDH - // pubkeyR = knownR? ? theirKnown : theirECDH - // - // Initial message = hmac(k=sha3(shared-secret[128..255]), address(pubkeyL)) || ECIES encrypt(pubkeyR, pubkeyL) - // - // Key Exchange (this could occur after handshake messages): - // If peers do not know each other they will need to exchange public keys. - // - // Drop ECDH (this could occur after handshake messages): - // After authentication and/or key exchange, both sides generate shared key - // from their 'known' keys and use this to encrypt all future messages. - // - // v2: If one side doesn't trust the other then a single-use key maybe sent. - // This will need to be tracked for future connections; when non-trusting peer - // wants to trust the other, it can request that it's old, 'new', public key be - // accepted. And, if the peer *really* doesn't trust the other side, it can request - // that a new, 'new', public key be accepted. - // - // Handshake (all or nothing, padded): - // All Peers (except blacklisted): - // - // - // New Peer: - // - // - // Known Untrusted Peer: - // - // - // Known Trusted Peer: - // - // - // Blacklisted Peeer: - // Already dropped by now. - // - // - // MAC: - // ... -} - BOOST_AUTO_TEST_CASE(eth_keypairs) { cnote << "Testing Crypto..."; From 8669468cbc18dfe0a7dd2049ff7e9662fc914fc3 Mon Sep 17 00:00:00 2001 From: subtly Date: Sat, 18 Oct 2014 23:01:42 +0200 Subject: [PATCH 12/48] cleanup headers --- crypto.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crypto.cpp b/crypto.cpp index 428fcb270..484b8714d 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -41,14 +41,18 @@ BOOST_AUTO_TEST_SUITE(devcrypto) BOOST_AUTO_TEST_CASE(ecies) { ECKeyPair k = ECKeyPair::create(); - + string message("Now is the time for all good men to come to the aide of humanity."); - bytes b = bytesConstRef(message).toBytes(); + bytes b = bytesRef(message).toBytes(); ECIESEncryptor(&k).encrypt(b); bytesConstRef br(&b); bytes plain = ECIESDecryptor(&k).decrypt(br); + + // ideally, decryptor will go a step further, accept a bytesRef and zero input. + assert(plain != b); + // plaintext is same as output assert(plain == bytesConstRef(message).toBytes()); } From c24fa78b21080c254719904c4eaccea24e79a446 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 20 Oct 2014 14:00:37 +0200 Subject: [PATCH 13/48] Pointer type cleanup: Use ASTPointer only for AST nodes and shared_ptr for type pointer. --- solidityNameAndTypeResolution.cpp | 2 +- solidityParser.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solidityNameAndTypeResolution.cpp b/solidityNameAndTypeResolution.cpp index ed2cb7b53..833ae6d4b 100644 --- a/solidityNameAndTypeResolution.cpp +++ b/solidityNameAndTypeResolution.cpp @@ -41,7 +41,7 @@ namespace void parseTextAndResolveNames(const std::string& _source) { Parser parser; - ptr contract = parser.parse( + ASTPointer contract = parser.parse( std::make_shared(CharStream(_source))); NameAndTypeResolver resolver; resolver.resolveNamesAndTypes(*contract); diff --git a/solidityParser.cpp b/solidityParser.cpp index ef434cc35..025cd74d1 100644 --- a/solidityParser.cpp +++ b/solidityParser.cpp @@ -37,7 +37,7 @@ namespace test namespace { -ptr parseText(const std::string& _source) +ASTPointer parseText(const std::string& _source) { Parser parser; return parser.parse(std::make_shared(CharStream(_source))); From ed827c771950fb1bd0cea69ff09525962c6837f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 11:54:54 +0200 Subject: [PATCH 14/48] Enhance VM tests reports, resolves ethereum/cpp-ethereum#399 --- vm.cpp | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/vm.cpp b/vm.cpp index d77906731..01ecc0d01 100644 --- a/vm.cpp +++ b/vm.cpp @@ -574,8 +574,44 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); - BOOST_CHECK(test.toInt(o["gas"]) == gas); - BOOST_CHECK(test.addresses == fev.addresses); + BOOST_CHECK_EQUAL(test.toInt(o["gas"]), gas); + + auto& expectedAddrs = test.addresses; + auto& resultAddrs = fev.addresses; + for (auto&& expectedPair : expectedAddrs) + { + auto& expectedAddr = expectedPair.first; + auto resultAddrIt = resultAddrs.find(expectedAddr); + if (resultAddrIt == resultAddrs.end()) + BOOST_ERROR("Missing expected address " << expectedAddr); + else + { + auto& expectedState = expectedPair.second; + auto& resultState = resultAddrIt->second; + BOOST_CHECK_MESSAGE(std::get<0>(expectedState) == std::get<0>(resultState), expectedAddr << ": incorrect balance " << std::get<0>(resultState) << ", expected " << std::get<0>(expectedState)); + BOOST_CHECK_MESSAGE(std::get<1>(expectedState) == std::get<1>(resultState), expectedAddr << ": incorrect txCount " << std::get<1>(resultState) << ", expected " << std::get<1>(expectedState)); + BOOST_CHECK_MESSAGE(std::get<3>(expectedState) == std::get<3>(resultState), expectedAddr << ": incorrect code"); + + auto&& expectedStore = std::get<2>(expectedState); + auto&& resultStore = std::get<2>(resultState); + + for (auto&& expectedStorePair : expectedStore) + { + auto& expectedStoreKey = expectedStorePair.first; + auto resultStoreIt = resultStore.find(expectedStoreKey); + if (resultStoreIt == resultStore.end()) + BOOST_ERROR(expectedAddr << ": missing store key " << expectedStoreKey); + else + { + auto& expectedStoreValue = expectedStorePair.second; + auto& resultStoreValue = resultStoreIt->second; + BOOST_CHECK_MESSAGE(expectedStoreValue == resultStoreValue, expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue); + } + } + } + } + + BOOST_CHECK(test.addresses == fev.addresses); // Just to make sure nothing missed BOOST_CHECK(test.callcreates == fev.callcreates); } } From 6c0b16bc032b89520d737f313e31c03856783f9f Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Tue, 21 Oct 2014 14:20:16 +0200 Subject: [PATCH 15/48] Random test optimizations --- createRandomTest.cpp | 67 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/createRandomTest.cpp b/createRandomTest.cpp index 874869a5c..2508d89f2 100644 --- a/createRandomTest.cpp +++ b/createRandomTest.cpp @@ -42,11 +42,11 @@ void doMyTests(json_spirit::mValue& v); int main(int argc, char *argv[]) { - if (argc != 2) - { - cout << "usage: createRandomTest \n"; - return 0; - } +// if (argc != 2) +// { +// cout << "usage: createRandomTest \n"; +// return 0; +// } // create random code @@ -64,14 +64,48 @@ int main(int argc, char *argv[]) string randomCode; for (int i = 0; i < lengthOfCode; ++i) - randomCode += toHex(toCompactBigEndian(randGen())); + { + uint8_t opcode = randGen(); - // read template test file + // disregard all invalid commands, except of one (0x10) + if (dev::eth::isValidInstruction(dev::eth::Instruction(opcode)) || opcode == 0x10) + randomCode += toHex(toCompactBigEndian(opcode)); + else + i--; + } + + const string s =\ +"{\n\ + \"randomVMtest\": {\n\ + \"env\" : {\n\ + \"previousHash\" : \"5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6\",\n\ + \"currentNumber\" : \"0\",\n\ + \"currentGasLimit\" : \"1000000\",\n\ + \"currentDifficulty\" : \"256\",\n\ + \"currentTimestamp\" : 1,\n\ + \"currentCoinbase\" : \"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba\"\n\ + },\n\ + \"pre\" : {\n\ + \"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6\" : {\n\ + \"balance\" : \"1000000000000000000\",\n\ + \"nonce\" : 0,\n\ + \"code\" : \"random\",\n\ + \"storage\": {}\n\ + }\n\ + },\n\ + \"exec\" : {\n\ + \"address\" : \"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6\",\n\ + \"origin\" : \"cd1722f3947def4cf144679da39c4c32bdc35681\",\n\ + \"caller\" : \"cd1722f3947def4cf144679da39c4c32bdc35681\",\n\ + \"value\" : \"1000000000000000000\",\n\ + \"data\" : \"\",\n\ + \"gasPrice\" : \"100000000000000\",\n\ + \"gas\" : \"10000\"\n\ + }\n\ + }\n\ +}"; mValue v; - boost::filesystem::path p(__FILE__); - boost::filesystem::path dir = p.parent_path(); - string s = asString(contents(dir.string() + "/randomTestFiller.json")); read_string(s, v); // insert new random code @@ -80,9 +114,16 @@ int main(int argc, char *argv[]) // execute code in vm doMyTests(v); - // write new test - string filename = argv[1]; - writeFile(filename, asBytes(json_spirit::write_string(v, true))); +// // write new test +// string filename = argv[1]; +// writeFile(filename, asBytes(json_spirit::write_string(v, true))); + + // write resultsing test to envirnoment variable + string str = "ETHEREUM_RANDOM_TEST=" + json_spirit::write_string(v, true); + char *cstr = new char[str.length() + 1]; + strcpy(cstr, str.c_str()); + putenv(cstr); + delete [] cstr; return 0; } From 60a7ff58a1c6061a838b5d50b7f24d1ac05193b9 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Tue, 21 Oct 2014 17:02:49 +0200 Subject: [PATCH 16/48] Change output of random test to std::out instead of file --- createRandomTest.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/createRandomTest.cpp b/createRandomTest.cpp index 2508d89f2..28e4342d7 100644 --- a/createRandomTest.cpp +++ b/createRandomTest.cpp @@ -42,11 +42,7 @@ void doMyTests(json_spirit::mValue& v); int main(int argc, char *argv[]) { -// if (argc != 2) -// { -// cout << "usage: createRandomTest \n"; -// return 0; -// } + g_logVerbosity = 0; // create random code @@ -114,16 +110,8 @@ int main(int argc, char *argv[]) // execute code in vm doMyTests(v); -// // write new test -// string filename = argv[1]; -// writeFile(filename, asBytes(json_spirit::write_string(v, true))); - - // write resultsing test to envirnoment variable - string str = "ETHEREUM_RANDOM_TEST=" + json_spirit::write_string(v, true); - char *cstr = new char[str.length() + 1]; - strcpy(cstr, str.c_str()); - putenv(cstr); - delete [] cstr; + // stream to output for further handling by the bash script + cout << json_spirit::write_string(v, true); return 0; } From 05a8e41d5d5bf58de008bbd77dab702a4d5b7e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 Oct 2014 17:36:26 +0200 Subject: [PATCH 17/48] Another round of fixing ExtVM interface --- vm.cpp | 19 +++++++++++++++---- vm.h | 18 +++++++++--------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/vm.cpp b/vm.cpp index 7306ef32d..582c3c410 100644 --- a/vm.cpp +++ b/vm.cpp @@ -35,7 +35,7 @@ using namespace dev::test; FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth): /// TODO: XXX: remove the default argument & fix. ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytesConstRef(), _previousBlock, _currentBlock, _depth) {} -h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc) +h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc const&) { Transaction t; t.value = _endowment; @@ -45,7 +45,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun m_s.noteSending(myAddress); m_ms.internal.resize(m_ms.internal.size() + 1); - auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); + auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); @@ -61,7 +61,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun return ret; } -bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc, Address _myAddressOverride = Address(), Address _codeAddressOverride = Address()) +bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride = Address(), Address _codeAddressOverride = Address()) { u256 contractgas = 0xffff; @@ -91,7 +91,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, if (!m_s.addresses().count(myAddress)) { m_ms.internal.resize(m_ms.internal.size() + 1); - auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); + auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); if (na != myAddress) @@ -578,6 +578,17 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); + //auto a = fev.addresses.at(fev.myAddress); + //auto b = test.addresses.at(fev.myAddress); + + //auto t = a == b; + //auto t0 = get<0>(a) == get<0>(b); + //auto t1 = get<1>(a) == get<1>(b); + //auto t2 = get<2>(a) == get<2>(b); + //auto t3 = get<3>(a) == get<3>(b); + + //BOOST_CHECK_EQUAL(get<0>(a), get<0>(b)); + BOOST_CHECK(test.toInt(o["gas"]) == gas); BOOST_CHECK(test.addresses == fev.addresses); BOOST_CHECK(test.callcreates == fev.callcreates); diff --git a/vm.h b/vm.h index 34e0e855a..a9897bee3 100644 --- a/vm.h +++ b/vm.h @@ -53,15 +53,15 @@ public: FakeExtVM() {} FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth = 0); - u256 store(u256 _n) { return std::get<2>(addresses[myAddress])[_n]; } - void setStore(u256 _n, u256 _v) { std::get<2>(addresses[myAddress])[_n] = _v; } - u256 balance(Address _a) { return std::get<0>(addresses[_a]); } - void subBalance(u256 _a) { std::get<0>(addresses[myAddress]) -= _a; } - u256 txCount(Address _a) { return std::get<1>(addresses[_a]); } - void suicide(Address _a) { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); } - bytes const& codeAt(Address _a) { return std::get<3>(addresses[_a]); } - h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc); - bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc, Address, Address); + u256 store(u256 _n) override { return std::get<2>(addresses[myAddress])[_n]; } + void setStore(u256 _n, u256 _v) override { std::get<2>(addresses[myAddress])[_n] = _v; } + u256 balance(Address _a) override { return std::get<0>(addresses[_a]); } + void subBalance(u256 _a) override { std::get<0>(addresses[myAddress]) -= _a; } + u256 txCount(Address _a) override { return std::get<1>(addresses[_a]); } + void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); } + bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); } + h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc const&) override; + bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override; void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data); void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); void set(Address _a, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); From d5c09e6450ed8182c3e6e680e6094c1e81b4af0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 21 Oct 2014 11:51:45 +0200 Subject: [PATCH 18/48] Remove dead code --- vm.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/vm.cpp b/vm.cpp index 582c3c410..8aa186473 100644 --- a/vm.cpp +++ b/vm.cpp @@ -578,17 +578,6 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); - //auto a = fev.addresses.at(fev.myAddress); - //auto b = test.addresses.at(fev.myAddress); - - //auto t = a == b; - //auto t0 = get<0>(a) == get<0>(b); - //auto t1 = get<1>(a) == get<1>(b); - //auto t2 = get<2>(a) == get<2>(b); - //auto t3 = get<3>(a) == get<3>(b); - - //BOOST_CHECK_EQUAL(get<0>(a), get<0>(b)); - BOOST_CHECK(test.toInt(o["gas"]) == gas); BOOST_CHECK(test.addresses == fev.addresses); BOOST_CHECK(test.callcreates == fev.callcreates); From 95e7e44c0895c76f1bb8b105c6c76658e401a34b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 12:45:26 +0200 Subject: [PATCH 19/48] Add virtual specifier to overridden methods in FakeVM --- vm.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/vm.h b/vm.h index a9897bee3..3a0091a06 100644 --- a/vm.h +++ b/vm.h @@ -50,18 +50,18 @@ public: class FakeExtVM: public eth::ExtVMFace { public: - FakeExtVM() {} + FakeExtVM() = default; FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth = 0); - u256 store(u256 _n) override { return std::get<2>(addresses[myAddress])[_n]; } - void setStore(u256 _n, u256 _v) override { std::get<2>(addresses[myAddress])[_n] = _v; } - u256 balance(Address _a) override { return std::get<0>(addresses[_a]); } - void subBalance(u256 _a) override { std::get<0>(addresses[myAddress]) -= _a; } - u256 txCount(Address _a) override { return std::get<1>(addresses[_a]); } - void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); } - bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); } - h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc const&) override; - bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override; + virtual u256 store(u256 _n) override { return std::get<2>(addresses[myAddress])[_n]; } + virtual void setStore(u256 _n, u256 _v) override { std::get<2>(addresses[myAddress])[_n] = _v; } + virtual u256 balance(Address _a) override { return std::get<0>(addresses[_a]); } + virtual void subBalance(u256 _a) override { std::get<0>(addresses[myAddress]) -= _a; } + virtual u256 txCount(Address _a) override { return std::get<1>(addresses[_a]); } + virtual void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); } + virtual bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); } + virtual h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc const&) override; + virtual bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override; void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data); void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); void set(Address _a, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); From e987e1a69289fcf05abb25a3d087681b8347b021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 22 Oct 2014 12:54:31 +0200 Subject: [PATCH 20/48] Drop universal initializer in some places --- vm.cpp | 2 +- vm.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vm.cpp b/vm.cpp index 8aa186473..ffa99dc01 100644 --- a/vm.cpp +++ b/vm.cpp @@ -61,7 +61,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun return ret; } -bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride = Address(), Address _codeAddressOverride = Address()) +bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride) { u256 contractgas = 0xffff; diff --git a/vm.h b/vm.h index 3a0091a06..d9dca1d7a 100644 --- a/vm.h +++ b/vm.h @@ -44,7 +44,7 @@ class FakeState: public eth::State { public: /// Execute a contract-creation transaction. - h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = Address(), std::set
* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = eth::OnOpFunc(), unsigned _level = 0); + h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = {}, std::set
* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = {}, unsigned _level = 0); }; class FakeExtVM: public eth::ExtVMFace From 9a5a6db634eba31bc1e009ef54b71c82dbc33dfb Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 22 Oct 2014 15:57:52 +0200 Subject: [PATCH 21/48] aes ctr mode test --- crypto.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/crypto.cpp b/crypto.cpp index 484b8714d..ba5bbfa4b 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -62,6 +62,11 @@ BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) // Every new connection requires a new EC keypair // Every new trust requires a new EC keypair // All connections should share seed for PRF (or PRNG) for nonces + + + + + } BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) @@ -149,6 +154,74 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdh_prime) assert(ssLocal == ssRemote); } +BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) +{ + const int aesKeyLen = 16; + assert(sizeof(char) == sizeof(byte)); + + // generate test key + AutoSeededRandomPool rng; + SecByteBlock key(0x00, aesKeyLen); + rng.GenerateBlock(key, key.size()); + + // cryptopp uses IV as nonce/counter which is same as using nonce w/0 ctr + byte ctr[ AES::BLOCKSIZE ]; + rng.GenerateBlock( ctr, sizeof(ctr) ); + + string text = "Now is the time for all good men to come to the aide of humanity."; + // c++11 ftw + unsigned char const* in = (unsigned char*)&text[0]; + unsigned char* out = (unsigned char*)&text[0]; + string original = text; + + string cipherCopy; + try + { + CTR_Mode< AES >::Encryption e; + e.SetKeyWithIV( key, key.size(), ctr ); + e.ProcessData(out, in, text.size()); + assert(text!=original); + cipherCopy = text; + } + catch( CryptoPP::Exception& e ) + { + cerr << e.what() << endl; + } + + try + { + CTR_Mode< AES >::Decryption d; + d.SetKeyWithIV( key, key.size(), ctr ); + d.ProcessData(out, in, text.size()); + assert(text==original); + } + catch( CryptoPP::Exception& e ) + { + cerr << e.what() << endl; + } + + + // reencrypt ciphertext... + try + { + assert(cipherCopy!=text); + in = (unsigned char*)&cipherCopy[0]; + out = (unsigned char*)&cipherCopy[0]; + + CTR_Mode< AES >::Encryption e; + e.SetKeyWithIV( key, key.size(), ctr ); + e.ProcessData(out, in, text.size()); + + // yep, ctr mode. + assert(cipherCopy==original); + } + catch( CryptoPP::Exception& e ) + { + cerr << e.what() << endl; + } + +} + BOOST_AUTO_TEST_CASE(cryptopp_aes128_cbc) { const int aesKeyLen = 16; From 76c29fc08addfd4cffa1773def96833f3616b4c0 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Wed, 22 Oct 2014 16:26:10 +0200 Subject: [PATCH 22/48] Bugfix, get correct gas after exception --- vm.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/vm.cpp b/vm.cpp index 7306ef32d..0ac211568 100644 --- a/vm.cpp +++ b/vm.cpp @@ -24,7 +24,7 @@ #include #include -#define FILL_TESTS +//#define FILL_TESTS using namespace std; using namespace json_spirit; @@ -512,12 +512,10 @@ void doTests(json_spirit::mValue& v, bool _fillin) } bytes output; - u256 gas; + VM vm(fev.gas); try { - VM vm(fev.gas); output = vm.go(fev).toVector(); - gas = vm.gas(); // Get the remaining gas } catch (Exception const& _e) { @@ -554,7 +552,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) o["post"] = mValue(fev.exportState()); o["callcreates"] = fev.exportCallCreates(); o["out"] = "0x" + toHex(output); - fev.push(o, "gas", gas); + fev.push(o, "gas", vm.gas()); } else { @@ -578,7 +576,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); - BOOST_CHECK(test.toInt(o["gas"]) == gas); + BOOST_CHECK(test.toInt(o["gas"]) == vm.gas()); BOOST_CHECK(test.addresses == fev.addresses); BOOST_CHECK(test.callcreates == fev.callcreates); } @@ -621,11 +619,13 @@ void executeTests(const string& _name) if (ptestPath == NULL) { cnote << " could not find environment variable ETHEREUM_TEST_PATH \n"; - testPath = "../../../tests/vmtests"; + testPath = "../../../tests"; } else testPath = ptestPath; + testPath += "/vmtests"; + #ifdef FILL_TESTS try { @@ -654,7 +654,7 @@ void executeTests(const string& _name) cnote << "Testing VM..." << _name; json_spirit::mValue v; string s = asString(contents(testPath + "/" + _name + ".json")); - BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); json_spirit::read_string(s, v); dev::test::doTests(v, false); } @@ -715,4 +715,3 @@ BOOST_AUTO_TEST_CASE(vmSystemOperationsTest) { dev::test::executeTests("vmSystemOperationsTest"); } - From 52e3b15735a71ed527d538b82ba135bd9c29d18e Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Wed, 22 Oct 2014 21:21:18 +0200 Subject: [PATCH 23/48] Added call depth tests --- vm.cpp | 2 +- vmIOandFlowOperationsTestFiller.json | 28 +++++++++++ vmSystemOperationsTestFiller.json | 71 ++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/vm.cpp b/vm.cpp index 0ac211568..fd23829fa 100644 --- a/vm.cpp +++ b/vm.cpp @@ -24,7 +24,7 @@ #include #include -//#define FILL_TESTS +#define FILL_TESTS using namespace std; using namespace json_spirit; diff --git a/vmIOandFlowOperationsTestFiller.json b/vmIOandFlowOperationsTestFiller.json index 79d162c8d..a470b9c8d 100644 --- a/vmIOandFlowOperationsTestFiller.json +++ b/vmIOandFlowOperationsTestFiller.json @@ -670,6 +670,34 @@ } }, + "jumpi2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "0x60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff596002600357", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + "pc0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", diff --git a/vmSystemOperationsTestFiller.json b/vmSystemOperationsTestFiller.json index c948f0436..c0dae74d3 100644 --- a/vmSystemOperationsTestFiller.json +++ b/vmSystemOperationsTestFiller.json @@ -949,6 +949,77 @@ } }, + "ABAcalls2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x945304eb96065b2a98b57a48a06ae28d285a71b5 1 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "0", + "code" : " { [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 0 0 0 0 0) } ", + "nonce" : "0", + "storage" : { + } + } + + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "100000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000000000000" + } + }, + + "ABAcalls3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1025000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x945304eb96065b2a98b57a48a06ae28d285a71b5 1 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "0", + "code" : " { [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 0 0 0 0 0) } ", + "nonce" : "0", + "storage" : { + } + } + + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "100000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "1000000" + } + }, "ABAcallsSuicide0": { "env" : { From c7a101dec321d5bd6fb0c0875b772527cd69a8b4 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Wed, 22 Oct 2014 22:13:08 +0200 Subject: [PATCH 24/48] bug fix --- vm.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vm.cpp b/vm.cpp index f74076399..36837eea4 100644 --- a/vm.cpp +++ b/vm.cpp @@ -512,12 +512,10 @@ void doTests(json_spirit::mValue& v, bool _fillin) } bytes output; - u256 gas; + VM vm(fev.gas); try { - VM vm(fev.gas); output = vm.go(fev).toVector(); - gas = vm.gas(); // Get the remaining gas } catch (Exception const& _e) { @@ -554,7 +552,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) o["post"] = mValue(fev.exportState()); o["callcreates"] = fev.exportCallCreates(); o["out"] = "0x" + toHex(output); - fev.push(o, "gas", gas); + fev.push(o, "gas", vm.gas()); } else { @@ -578,7 +576,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); - BOOST_CHECK_EQUAL(test.toInt(o["gas"]), gas); + BOOST_CHECK_EQUAL(test.toInt(o["gas"]), vm.gas()); auto& expectedAddrs = test.addresses; auto& resultAddrs = fev.addresses; @@ -657,11 +655,13 @@ void executeTests(const string& _name) if (ptestPath == NULL) { cnote << " could not find environment variable ETHEREUM_TEST_PATH \n"; - testPath = "../../../tests/vmtests"; + testPath = "../../../tests"; } else testPath = ptestPath; + testPath += "/vmtests"; + #ifdef FILL_TESTS try { @@ -690,7 +690,7 @@ void executeTests(const string& _name) cnote << "Testing VM..." << _name; json_spirit::mValue v; string s = asString(contents(testPath + "/" + _name + ".json")); - BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); json_spirit::read_string(s, v); dev::test::doTests(v, false); } From 29450c0fab3b093962e32c36fa0b1c5c237b3998 Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 22 Oct 2014 22:57:41 +0200 Subject: [PATCH 25/48] abstract cryptopp. add/test encrypt/decrypt for key. --- crypto.cpp | 66 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/crypto.cpp b/crypto.cpp index ba5bbfa4b..48c6fc70c 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -38,22 +38,36 @@ using namespace CryptoPP; BOOST_AUTO_TEST_SUITE(devcrypto) -BOOST_AUTO_TEST_CASE(ecies) +BOOST_AUTO_TEST_CASE(eckeypair_encrypt) { ECKeyPair k = ECKeyPair::create(); - - string message("Now is the time for all good men to come to the aide of humanity."); - bytes b = bytesRef(message).toBytes(); - ECIESEncryptor(&k).encrypt(b); - - bytesConstRef br(&b); - bytes plain = ECIESDecryptor(&k).decrypt(br); - - // ideally, decryptor will go a step further, accept a bytesRef and zero input. - assert(plain != b); + string message("Now is the time for all good persons to come to the aide of humanity."); + string original = message; - // plaintext is same as output - assert(plain == bytesConstRef(message).toBytes()); + bytes b = asBytes(message); + k.encrypt(b); + assert(b != asBytes(original)); + + bytes p = k.decrypt(&b); + assert(p == asBytes(original)); +} + +BOOST_AUTO_TEST_CASE(ecies) +{ +// ECKeyPair k = ECKeyPair::create(); +// +// string message("Now is the time for all good persons to come to the aide of humanity."); +// bytes b = bytesRef(message).toBytes(); +// ECIESEncryptor(&k).encrypt(b); +// +// bytesConstRef br(&b); +// bytes plain = ECIESDecryptor(&k).decrypt(br); +// +// // ideally, decryptor will go a step further, accept a bytesRef and zero input. +// assert(plain != b); +// +// // plaintext is same as output +// assert(plain == bytesConstRef(message).toBytes()); } BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) @@ -73,9 +87,9 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) { cnote << "Testing cryptopp_ecies_message..."; - string const message("Now is the time for all good men to come to the aide of humanity."); + string const message("Now is the time for all good persons to come to the aide of humanity."); - ECIES::Decryptor localDecryptor(crypto::PRNG(), crypto::secp256k1()); + ECIES::Decryptor localDecryptor(pp::PRNG(), pp::secp256k1()); SavePrivateKey(localDecryptor.GetPrivateKey()); ECIES::Encryptor localEncryptor(localDecryptor); @@ -83,31 +97,31 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) ECIES::Decryptor futureDecryptor; LoadPrivateKey(futureDecryptor.AccessPrivateKey()); - futureDecryptor.GetPrivateKey().ThrowIfInvalid(crypto::PRNG(), 3); + futureDecryptor.GetPrivateKey().ThrowIfInvalid(pp::PRNG(), 3); ECIES::Encryptor futureEncryptor; LoadPublicKey(futureEncryptor.AccessPublicKey()); - futureEncryptor.GetPublicKey().ThrowIfInvalid(crypto::PRNG(), 3); + futureEncryptor.GetPublicKey().ThrowIfInvalid(pp::PRNG(), 3); // encrypt/decrypt with local string cipherLocal; - StringSource ss1 (message, true, new PK_EncryptorFilter(crypto::PRNG(), localEncryptor, new StringSink(cipherLocal) ) ); + StringSource ss1 (message, true, new PK_EncryptorFilter(pp::PRNG(), localEncryptor, new StringSink(cipherLocal) ) ); string plainLocal; - StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(crypto::PRNG(), localDecryptor, new StringSink(plainLocal) ) ); + StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG(), localDecryptor, new StringSink(plainLocal) ) ); // encrypt/decrypt with future string cipherFuture; - StringSource ss3 (message, true, new PK_EncryptorFilter(crypto::PRNG(), futureEncryptor, new StringSink(cipherFuture) ) ); + StringSource ss3 (message, true, new PK_EncryptorFilter(pp::PRNG(), futureEncryptor, new StringSink(cipherFuture) ) ); string plainFuture; - StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(crypto::PRNG(), futureDecryptor, new StringSink(plainFuture) ) ); + StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG(), futureDecryptor, new StringSink(plainFuture) ) ); // decrypt local w/future string plainFutureFromLocal; - StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(crypto::PRNG(), futureDecryptor, new StringSink(plainFutureFromLocal) ) ); + StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG(), futureDecryptor, new StringSink(plainFutureFromLocal) ) ); // decrypt future w/local string plainLocalFromFuture; - StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(crypto::PRNG(), localDecryptor, new StringSink(plainLocalFromFuture) ) ); + StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG(), localDecryptor, new StringSink(plainLocalFromFuture) ) ); assert(plainLocal == message); @@ -126,12 +140,12 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdh_prime) ECDH::Domain dhLocal(curve); SecByteBlock privLocal(dhLocal.PrivateKeyLength()); SecByteBlock pubLocal(dhLocal.PublicKeyLength()); - dhLocal.GenerateKeyPair(dev::crypto::PRNG(), privLocal, pubLocal); + dhLocal.GenerateKeyPair(pp::PRNG(), privLocal, pubLocal); ECDH::Domain dhRemote(curve); SecByteBlock privRemote(dhRemote.PrivateKeyLength()); SecByteBlock pubRemote(dhRemote.PublicKeyLength()); - dhRemote.GenerateKeyPair(dev::crypto::PRNG(), privRemote, pubRemote); + dhRemote.GenerateKeyPair(pp::PRNG(), privRemote, pubRemote); assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength()); @@ -168,7 +182,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) byte ctr[ AES::BLOCKSIZE ]; rng.GenerateBlock( ctr, sizeof(ctr) ); - string text = "Now is the time for all good men to come to the aide of humanity."; + string text = "Now is the time for all good persons to come to the aide of humanity."; // c++11 ftw unsigned char const* in = (unsigned char*)&text[0]; unsigned char* out = (unsigned char*)&text[0]; From 9308d04a4cc1b93a879f542aa9c3e3e8297410e4 Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 22 Oct 2014 23:59:00 +0200 Subject: [PATCH 26/48] Export and encrypt via dev::Public. more cryptopp abstraction. --- crypto.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/crypto.cpp b/crypto.cpp index 48c6fc70c..7e3ce81ab 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +//#include #include "TestHelperCrypto.h" using namespace std; @@ -38,6 +38,21 @@ using namespace CryptoPP; BOOST_AUTO_TEST_SUITE(devcrypto) +BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) +{ + ECIES::Decryptor d(pp::PRNG(), pp::secp256k1()); + ECIES::Encryptor e(d.GetKey()); + + Public p = pp::exportPublicKey(e.GetKey()); + Integer x(&p[0], 32); + Integer y(&p[32], 32); + + DL_PublicKey_EC pub; + pub.Initialize(pp::secp256k1(), ECP::Point(x,y)); + + assert(pub == e.GetKey()); +} + BOOST_AUTO_TEST_CASE(eckeypair_encrypt) { ECKeyPair k = ECKeyPair::create(); @@ -50,6 +65,11 @@ BOOST_AUTO_TEST_CASE(eckeypair_encrypt) bytes p = k.decrypt(&b); assert(p == asBytes(original)); + + encrypt(p, k.publicKey()); + assert(p != asBytes(original)); + + // todo: test decrypt w/Secret } BOOST_AUTO_TEST_CASE(ecies) From 6513d4312962f7d99d52572f02b5ff4277272496 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 23 Oct 2014 02:40:02 +0200 Subject: [PATCH 27/48] import/export cryptopp keys. begin to separate operations and public/secret. --- crypto.cpp | 49 +++++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/crypto.cpp b/crypto.cpp index 7e3ce81ab..a9b9904cc 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -28,7 +28,6 @@ #include #include #include -//#include #include "TestHelperCrypto.h" using namespace std; @@ -38,22 +37,32 @@ using namespace CryptoPP; BOOST_AUTO_TEST_SUITE(devcrypto) +BOOST_AUTO_TEST_CASE(cryptopp_private_secret_import) +{ + ECKeyPair k = ECKeyPair::create(); + Integer e = k.m_decryptor.AccessKey().GetPrivateExponent(); + assert(pp::ExponentFromSecret(k.secret()) == e); +} + BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) { ECIES::Decryptor d(pp::PRNG(), pp::secp256k1()); ECIES::Encryptor e(d.GetKey()); - Public p = pp::exportPublicKey(e.GetKey()); + Public p; + pp::exportDL_PublicKey_EC(e.GetKey(), p); Integer x(&p[0], 32); Integer y(&p[32], 32); DL_PublicKey_EC pub; pub.Initialize(pp::secp256k1(), ECP::Point(x,y)); - assert(pub == e.GetKey()); + + DL_PublicKey_EC pub2; + pub.Initialize(pp::secp256k1(), ECP::Point(x,y)); } -BOOST_AUTO_TEST_CASE(eckeypair_encrypt) +BOOST_AUTO_TEST_CASE(ecies_eckeypair) { ECKeyPair k = ECKeyPair::create(); string message("Now is the time for all good persons to come to the aide of humanity."); @@ -62,32 +71,16 @@ BOOST_AUTO_TEST_CASE(eckeypair_encrypt) bytes b = asBytes(message); k.encrypt(b); assert(b != asBytes(original)); - - bytes p = k.decrypt(&b); - assert(p == asBytes(original)); - encrypt(p, k.publicKey()); - assert(p != asBytes(original)); - - // todo: test decrypt w/Secret -} + Secret s = k.secret(); + decrypt(s, b); + assert(b == asBytes(original)); -BOOST_AUTO_TEST_CASE(ecies) -{ -// ECKeyPair k = ECKeyPair::create(); -// -// string message("Now is the time for all good persons to come to the aide of humanity."); -// bytes b = bytesRef(message).toBytes(); -// ECIESEncryptor(&k).encrypt(b); -// -// bytesConstRef br(&b); -// bytes plain = ECIESDecryptor(&k).decrypt(br); -// -// // ideally, decryptor will go a step further, accept a bytesRef and zero input. -// assert(plain != b); -// -// // plaintext is same as output -// assert(plain == bytesConstRef(message).toBytes()); + // Fix Me! +// encrypt(k.publicKey(), b); +// assert(b != asBytes(original)); +// bytes plain = k.decrypt(&b); +// assert(plain == asBytes(original)); } BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) From 19e169694c7ae60acc8eb923fe71c4a971dc32fd Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 23 Oct 2014 04:50:04 +0200 Subject: [PATCH 28/48] fix public import/export --- crypto.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/crypto.cpp b/crypto.cpp index a9b9904cc..bb8db2b65 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -51,15 +51,10 @@ BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) Public p; pp::exportDL_PublicKey_EC(e.GetKey(), p); - Integer x(&p[0], 32); - Integer y(&p[32], 32); - + DL_PublicKey_EC pub; - pub.Initialize(pp::secp256k1(), ECP::Point(x,y)); - assert(pub == e.GetKey()); - - DL_PublicKey_EC pub2; - pub.Initialize(pp::secp256k1(), ECP::Point(x,y)); + pub.Initialize(pp::secp256k1(), pp::PointFromPublic(p)); + assert(pub.GetPublicElement() == e.GetKey().GetPublicElement()); } BOOST_AUTO_TEST_CASE(ecies_eckeypair) @@ -78,9 +73,10 @@ BOOST_AUTO_TEST_CASE(ecies_eckeypair) // Fix Me! // encrypt(k.publicKey(), b); -// assert(b != asBytes(original)); -// bytes plain = k.decrypt(&b); -// assert(plain == asBytes(original)); + k.encrypt(b); + assert(b != asBytes(original)); + k.decrypt(b); + assert(b == asBytes(original)); } BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) From 4dcfbd05c6218e8cd38a36eacdc09b0dabf5e9f0 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 23 Oct 2014 05:04:25 +0200 Subject: [PATCH 29/48] cryptopp_vs_secp256k1 --- crypto.cpp | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/crypto.cpp b/crypto.cpp index bb8db2b65..55ee1e176 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -37,6 +37,37 @@ using namespace CryptoPP; BOOST_AUTO_TEST_SUITE(devcrypto) +BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1) +{ + ECIES::Decryptor d(pp::PRNG(), pp::secp256k1()); + ECIES::Encryptor e(d.GetKey()); + + Secret s; + pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s); + + Public p; + pp::PublicFromDL_PublicKey_EC(e.GetKey(), p); + + assert(dev::toAddress(s) == right160(dev::sha3(p.ref()))); + + Secret previous = s; + for (auto i = 0; i < 30; i++) + { + ECIES::Decryptor d(pp::PRNG(), pp::secp256k1()); + ECIES::Encryptor e(d.GetKey()); + + Secret s; + pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s); + assert(s!=previous); + + Public p; + pp::PublicFromDL_PublicKey_EC(e.GetKey(), p); + + /// wow, this worked. the first time. + assert(dev::toAddress(s) == right160(dev::sha3(p.ref()))); + } +} + BOOST_AUTO_TEST_CASE(cryptopp_private_secret_import) { ECKeyPair k = ECKeyPair::create(); @@ -50,7 +81,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) ECIES::Encryptor e(d.GetKey()); Public p; - pp::exportDL_PublicKey_EC(e.GetKey(), p); + pp::PublicFromDL_PublicKey_EC(e.GetKey(), p); DL_PublicKey_EC pub; pub.Initialize(pp::secp256k1(), pp::PointFromPublic(p)); From d865275202fbd141c55056c6f525f9ecf9b2e507 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Thu, 23 Oct 2014 11:25:34 +0200 Subject: [PATCH 30/48] Changing gas cost to zero at stackunderflow --- vm.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vm.cpp b/vm.cpp index 36837eea4..2e4571be5 100644 --- a/vm.cpp +++ b/vm.cpp @@ -24,7 +24,7 @@ #include #include -#define FILL_TESTS +//#define FILL_TESTS using namespace std; using namespace json_spirit; @@ -751,4 +751,3 @@ BOOST_AUTO_TEST_CASE(vmSystemOperationsTest) { dev::test::executeTests("vmSystemOperationsTest"); } - From 9e28ef7cf013205dbd59be66bcd93d8fa2eb5cff Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Thu, 23 Oct 2014 16:07:13 +0200 Subject: [PATCH 31/48] Added new recursive bombs to vm tests --- vmPushDupSwapTestFiller.json | 28 ++++++++++ vmSystemOperationsTestFiller.json | 86 ++++++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/vmPushDupSwapTestFiller.json b/vmPushDupSwapTestFiller.json index 1bb3e6630..52c704d42 100644 --- a/vmPushDupSwapTestFiller.json +++ b/vmPushDupSwapTestFiller.json @@ -27,6 +27,34 @@ } }, + "push1_missingStack": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "0x60", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, + "push2": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", diff --git a/vmSystemOperationsTestFiller.json b/vmSystemOperationsTestFiller.json index c0dae74d3..1df2697e0 100644 --- a/vmSystemOperationsTestFiller.json +++ b/vmSystemOperationsTestFiller.json @@ -509,7 +509,7 @@ } }, - "CallRecursiveBomb": { + "CallRecursiveBomb0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", "currentNumber" : "0", @@ -543,6 +543,90 @@ } }, + "CallRecursiveBomb1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ (SLOAD 0) 1) [[ 1 ]] (CALL (- (GAS) 224) (ADDRESS) 0 0 0 0 0) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "100000", + "data" : "", + "gasPrice" : "1", + "gas" : "364723" + } + }, + + "CallRecursiveBomb2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ (SLOAD 0) 1) [[ 1 ]] (CALL (- (GAS) 224) (ADDRESS) 0 0 0 0 0) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "100000", + "data" : "", + "gasPrice" : "1", + "gas" : "364724" + } + }, + + "CallRecursiveBomb3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ (SLOAD 0) 1) [[ 1 ]] (CALL (- (GAS) 224) (ADDRESS) 0 0 0 0 0) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "100000", + "data" : "", + "gasPrice" : "1", + "gas" : "1000000" + } + }, + "suicide0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", From 9604a5a4d9cb48d01538f9199988a901f56c9b1d Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 23 Oct 2014 16:38:50 +0200 Subject: [PATCH 32/48] commit before narrowing down import-public key issue w/cryptopp --- crypto.cpp | 64 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/crypto.cpp b/crypto.cpp index 55ee1e176..ccfa1003a 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -62,52 +62,80 @@ BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1) Public p; pp::PublicFromDL_PublicKey_EC(e.GetKey(), p); - - /// wow, this worked. the first time. + assert(dev::toAddress(s) == right160(dev::sha3(p.ref()))); } } -BOOST_AUTO_TEST_CASE(cryptopp_private_secret_import) +BOOST_AUTO_TEST_CASE(cryptopp_is_bad) { - ECKeyPair k = ECKeyPair::create(); - Integer e = k.m_decryptor.AccessKey().GetPrivateExponent(); - assert(pp::ExponentFromSecret(k.secret()) == e); + SecretKeyRef k; + Secret s = k.sec(); + + /// Convert secret to exponent used by pp + Integer e = pp::ExponentFromSecret(k.sec()); + + ECIES::Decryptor d; +// k.AccessGroupParameters().Initialize(ASN1::secp256r1()); +// k.SetPrivateExponent(_e); + + pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s); + } BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) { ECIES::Decryptor d(pp::PRNG(), pp::secp256k1()); ECIES::Encryptor e(d.GetKey()); - + + Secret s; + pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s); Public p; pp::PublicFromDL_PublicKey_EC(e.GetKey(), p); - + Address addr = right160(dev::sha3(p.ref())); + assert(toAddress(s) == addr); + + KeyPair l(s); + assert(l.address() == addr); + DL_PublicKey_EC pub; pub.Initialize(pp::secp256k1(), pp::PointFromPublic(p)); assert(pub.GetPublicElement() == e.GetKey().GetPublicElement()); + + + //// + SecretKeyRef k; + Public p2; + pp::PublicFromExponent(pp::ExponentFromSecret(k.sec()), p2); + assert(k.pub() == p2); + + // Fix me: + Address a = k.address(); + Address a2 = toAddress(k.sec()); + assert(a2 == a); } BOOST_AUTO_TEST_CASE(ecies_eckeypair) { - ECKeyPair k = ECKeyPair::create(); + KeyPair l = KeyPair::create(); + SecretKeyRef k(l.sec()); + string message("Now is the time for all good persons to come to the aide of humanity."); string original = message; bytes b = asBytes(message); - k.encrypt(b); + encrypt(k.pub(), b); assert(b != asBytes(original)); - Secret s = k.secret(); - decrypt(s, b); + decrypt(k.sec(), b); assert(b == asBytes(original)); - // Fix Me! -// encrypt(k.publicKey(), b); - k.encrypt(b); - assert(b != asBytes(original)); - k.decrypt(b); - assert(b == asBytes(original)); +// // Fix Me! +//// encrypt(k.publicKey(), b); +// k.encrypt(b); +// assert(b != asBytes(original)); +// k.decrypt(b); +// assert(b == asBytes(original)); } BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) From 3726c120e9ede1a5cd835ee4beb516a9aca6e669 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 23 Oct 2014 16:59:01 +0200 Subject: [PATCH 33/48] two ec curves walked into a bar... --- crypto.cpp | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/crypto.cpp b/crypto.cpp index ccfa1003a..40e0a6a41 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -67,20 +67,39 @@ BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1) } } -BOOST_AUTO_TEST_CASE(cryptopp_is_bad) +BOOST_AUTO_TEST_CASE(cryptopp_keys_cryptor_sipaseckp256k1) { SecretKeyRef k; Secret s = k.sec(); - /// Convert secret to exponent used by pp - Integer e = pp::ExponentFromSecret(k.sec()); + // Convert secret to exponent used by pp + Integer e = pp::ExponentFromSecret(s); + // Test that exported DL_EC private is same as exponent from Secret + CryptoPP::DL_PrivateKey_EC privatek; + privatek.AccessGroupParameters().Initialize(pp::secp256k1()); + privatek.SetPrivateExponent(e); + assert(e == privatek.GetPrivateExponent()); + + // Test that exported secret is same as decryptor(privatek) secret ECIES::Decryptor d; -// k.AccessGroupParameters().Initialize(ASN1::secp256r1()); -// k.SetPrivateExponent(_e); + d.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1()); + d.AccessKey().SetPrivateExponent(e); + assert(d.AccessKey().GetPrivateExponent() == e); - pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s); + // Test that decryptor->encryptor->public == private->makepublic->public + CryptoPP::DL_PublicKey_EC pubk; + pubk.AccessGroupParameters().Initialize(pp::secp256k1()); + privatek.MakePublicKey(pubk); + ECIES::Encryptor enc(d); + assert(pubk.GetPublicElement() == enc.AccessKey().GetPublicElement()); + + // Test against sipa/seckp256k1 + Public p; + pp::PublicFromExponent(pp::ExponentFromSecret(s), p); + assert(toAddress(s) == dev::right160(dev::sha3(p.ref()))); + assert(k.pub() == p); } BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) @@ -101,9 +120,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) DL_PublicKey_EC pub; pub.Initialize(pp::secp256k1(), pp::PointFromPublic(p)); assert(pub.GetPublicElement() == e.GetKey().GetPublicElement()); - - - //// + SecretKeyRef k; Public p2; pp::PublicFromExponent(pp::ExponentFromSecret(k.sec()), p2); From a203fb7ae8fd84d576ef530c83e1fe5b09ad364e Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Thu, 23 Oct 2014 18:58:59 +0200 Subject: [PATCH 34/48] merge --- vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm.cpp b/vm.cpp index 54f3b8ced..2e4571be5 100644 --- a/vm.cpp +++ b/vm.cpp @@ -91,7 +91,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, if (!m_s.addresses().count(myAddress)) { m_ms.internal.resize(m_ms.internal.size() + 1); - auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); + auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); if (na != myAddress) From ee062e564b4cac38a14d755abcde1c68b3ad8b53 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 23 Oct 2014 19:06:31 +0200 Subject: [PATCH 35/48] add ecies encrypt/decrypt support to common crypto --- TestHelperCrypto.h | 18 +----------------- crypto.cpp | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/TestHelperCrypto.h b/TestHelperCrypto.h index 24104f118..01e97c21f 100644 --- a/TestHelperCrypto.h +++ b/TestHelperCrypto.h @@ -21,23 +21,7 @@ #pragma once -#pragma warning(push) -#pragma warning(disable:4100 4244) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" -#pragma GCC diagnostic ignored "-Wextra" -#include -#include // secp256k1 -#include // ec domain -#include // ec prime field -#include // cryptopp buffer -#include -#include // aes modes -#pragma warning(pop) -#pragma GCC diagnostic pop +#include using namespace std; using namespace CryptoPP; diff --git a/crypto.cpp b/crypto.cpp index 40e0a6a41..3662bb83d 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -37,6 +37,24 @@ using namespace CryptoPP; BOOST_AUTO_TEST_SUITE(devcrypto) +BOOST_AUTO_TEST_CASE(common_crypt) +{ + string message("Now is the time for all good persons to come to the aide of humanity."); + bytes m = asBytes(message); + bytesConstRef bcr(&m); + + SecretKeyRef k; + bytes cipher; + encrypt(k.pub(), bcr, cipher); + assert(cipher != asBytes(message) && cipher.size() > 0); + + bytes plain; + decrypt(k.sec(), bytesConstRef(&cipher), plain); + + assert(asString(plain) == message); + assert(plain == asBytes(message)); +} + BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1) { ECIES::Decryptor d(pp::PRNG(), pp::secp256k1()); From 2b66efb72d2b58c9f165766cb427928525601a47 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 23 Oct 2014 19:19:02 +0200 Subject: [PATCH 36/48] cleanup more headers --- crypto.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto.cpp b/crypto.cpp index 3662bb83d..ba17b9fee 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -37,7 +37,7 @@ using namespace CryptoPP; BOOST_AUTO_TEST_SUITE(devcrypto) -BOOST_AUTO_TEST_CASE(common_crypt) +BOOST_AUTO_TEST_CASE(common_encrypt_decrypt) { string message("Now is the time for all good persons to come to the aide of humanity."); bytes m = asBytes(message); From f02987e2199de3b6296c24cc5746c7857fbed60e Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 23 Oct 2014 19:25:12 +0200 Subject: [PATCH 37/48] remove irrelevant test code --- crypto.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/crypto.cpp b/crypto.cpp index ba17b9fee..8e56d6076 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -144,7 +144,6 @@ BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) pp::PublicFromExponent(pp::ExponentFromSecret(k.sec()), p2); assert(k.pub() == p2); - // Fix me: Address a = k.address(); Address a2 = toAddress(k.sec()); assert(a2 == a); @@ -164,13 +163,6 @@ BOOST_AUTO_TEST_CASE(ecies_eckeypair) decrypt(k.sec(), b); assert(b == asBytes(original)); - -// // Fix Me! -//// encrypt(k.publicKey(), b); -// k.encrypt(b); -// assert(b != asBytes(original)); -// k.decrypt(b); -// assert(b == asBytes(original)); } BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) From 1c8ef381247ae249a4dd9f7567a3aa5aaa0e4417 Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 23 Oct 2014 21:59:05 +0200 Subject: [PATCH 38/48] coding standards --- crypto.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/crypto.cpp b/crypto.cpp index 8e56d6076..57c992e50 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1) Secret s; pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s); - assert(s!=previous); + assert(s != previous); Public p; pp::PublicFromDL_PublicKey_EC(e.GetKey(), p); @@ -274,8 +274,8 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) rng.GenerateBlock(key, key.size()); // cryptopp uses IV as nonce/counter which is same as using nonce w/0 ctr - byte ctr[ AES::BLOCKSIZE ]; - rng.GenerateBlock( ctr, sizeof(ctr) ); + byte ctr[AES::BLOCKSIZE]; + rng.GenerateBlock(ctr, sizeof(ctr)); string text = "Now is the time for all good persons to come to the aide of humanity."; // c++11 ftw @@ -286,13 +286,13 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) string cipherCopy; try { - CTR_Mode< AES >::Encryption e; - e.SetKeyWithIV( key, key.size(), ctr ); + CTR_Mode::Encryption e; + e.SetKeyWithIV(key, key.size(), ctr); e.ProcessData(out, in, text.size()); - assert(text!=original); + assert(text != original); cipherCopy = text; } - catch( CryptoPP::Exception& e ) + catch(CryptoPP::Exception& e) { cerr << e.what() << endl; } @@ -300,11 +300,11 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) try { CTR_Mode< AES >::Decryption d; - d.SetKeyWithIV( key, key.size(), ctr ); + d.SetKeyWithIV(key, key.size(), ctr); d.ProcessData(out, in, text.size()); - assert(text==original); + assert(text == original); } - catch( CryptoPP::Exception& e ) + catch(CryptoPP::Exception& e) { cerr << e.what() << endl; } @@ -313,18 +313,18 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) // reencrypt ciphertext... try { - assert(cipherCopy!=text); + assert(cipherCopy != text); in = (unsigned char*)&cipherCopy[0]; out = (unsigned char*)&cipherCopy[0]; - CTR_Mode< AES >::Encryption e; - e.SetKeyWithIV( key, key.size(), ctr ); + CTR_Mode::Encryption e; + e.SetKeyWithIV(key, key.size(), ctr); e.ProcessData(out, in, text.size()); // yep, ctr mode. - assert(cipherCopy==original); + assert(cipherCopy == original); } - catch( CryptoPP::Exception& e ) + catch(CryptoPP::Exception& e) { cerr << e.what() << endl; } From 9a6b5fd613b8fbe208ee9e8eecf7571371ce8beb Mon Sep 17 00:00:00 2001 From: subtly Date: Thu, 23 Oct 2014 22:12:47 +0200 Subject: [PATCH 39/48] style. remove unused code. --- crypto.cpp | 47 ++++------------------------------------------- 1 file changed, 4 insertions(+), 43 deletions(-) diff --git a/crypto.cpp b/crypto.cpp index 57c992e50..0d3b6202f 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -43,7 +43,7 @@ BOOST_AUTO_TEST_CASE(common_encrypt_decrypt) bytes m = asBytes(message); bytesConstRef bcr(&m); - SecretKeyRef k; + KeyPair k = KeyPair::create(); bytes cipher; encrypt(k.pub(), bcr, cipher); assert(cipher != asBytes(message) && cipher.size() > 0); @@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1) BOOST_AUTO_TEST_CASE(cryptopp_keys_cryptor_sipaseckp256k1) { - SecretKeyRef k; + KeyPair k = KeyPair::create(); Secret s = k.sec(); // Convert secret to exponent used by pp @@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) pub.Initialize(pp::secp256k1(), pp::PointFromPublic(p)); assert(pub.GetPublicElement() == e.GetKey().GetPublicElement()); - SecretKeyRef k; + KeyPair k = KeyPair::create(); Public p2; pp::PublicFromExponent(pp::ExponentFromSecret(k.sec()), p2); assert(k.pub() == p2); @@ -151,8 +151,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_public_export_import) BOOST_AUTO_TEST_CASE(ecies_eckeypair) { - KeyPair l = KeyPair::create(); - SecretKeyRef k(l.sec()); + KeyPair k = KeyPair::create(); string message("Now is the time for all good persons to come to the aide of humanity."); string original = message; @@ -225,44 +224,6 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) assert(plainLocalFromFuture == plainLocal); } -BOOST_AUTO_TEST_CASE(cryptopp_ecdh_prime) -{ - cnote << "Testing cryptopp_ecdh_prime..."; - - using namespace CryptoPP; - OID curve = ASN1::secp256k1(); - - ECDH::Domain dhLocal(curve); - SecByteBlock privLocal(dhLocal.PrivateKeyLength()); - SecByteBlock pubLocal(dhLocal.PublicKeyLength()); - dhLocal.GenerateKeyPair(pp::PRNG(), privLocal, pubLocal); - - ECDH::Domain dhRemote(curve); - SecByteBlock privRemote(dhRemote.PrivateKeyLength()); - SecByteBlock pubRemote(dhRemote.PublicKeyLength()); - dhRemote.GenerateKeyPair(pp::PRNG(), privRemote, pubRemote); - - assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength()); - - // local: send public to remote; remote: send public to local - - // Local - SecByteBlock sharedLocal(dhLocal.AgreedValueLength()); - assert(dhLocal.Agree(sharedLocal, privLocal, pubRemote)); - - // Remote - SecByteBlock sharedRemote(dhRemote.AgreedValueLength()); - assert(dhRemote.Agree(sharedRemote, privRemote, pubLocal)); - - // Test - Integer ssLocal, ssRemote; - ssLocal.Decode(sharedLocal.BytePtr(), sharedLocal.SizeInBytes()); - ssRemote.Decode(sharedRemote.BytePtr(), sharedRemote.SizeInBytes()); - - assert(ssLocal != 0); - assert(ssLocal == ssRemote); -} - BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) { const int aesKeyLen = 16; From ed7a56cc16ad28601d2d6546615a1d1feb5ce527 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Oct 2014 14:13:16 +0100 Subject: [PATCH 40/48] PoC-7: Reversion of 0-hashes, empty-list hashes and sha3('') -> '' --- MemTrie.cpp | 4 ++-- TrieHash.cpp | 6 +++--- crypto.cpp | 3 +++ state.cpp | 1 + vm.cpp | 7 ++++--- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/MemTrie.cpp b/MemTrie.cpp index 4879f2674..c3a44e1e5 100644 --- a/MemTrie.cpp +++ b/MemTrie.cpp @@ -437,12 +437,12 @@ MemTrie::~MemTrie() h256 MemTrie::hash256() const { - return m_root ? m_root->hash256() : h256(); + return m_root ? m_root->hash256() : sha3(dev::rlp(bytesConstRef())); } bytes MemTrie::rlp() const { - return m_root ? m_root->rlp() : bytes(); + return m_root ? m_root->rlp() : dev::rlp(bytesConstRef()); } void MemTrie::debugPrint() diff --git a/TrieHash.cpp b/TrieHash.cpp index af32e870d..ee4f2e87d 100644 --- a/TrieHash.cpp +++ b/TrieHash.cpp @@ -162,7 +162,7 @@ h256 hash256(StringMap const& _s) { // build patricia tree. if (_s.empty()) - return h256(); + return sha3(rlp("")); HexMap hexMap; for (auto i = _s.rbegin(); i != _s.rend(); ++i) hexMap[asNibbles(i->first)] = i->second; @@ -175,7 +175,7 @@ bytes rlp256(StringMap const& _s) { // build patricia tree. if (_s.empty()) - return bytes(); + return rlp(""); HexMap hexMap; for (auto i = _s.rbegin(); i != _s.rend(); ++i) hexMap[asNibbles(i->first)] = i->second; @@ -188,7 +188,7 @@ h256 hash256(u256Map const& _s) { // build patricia tree. if (_s.empty()) - return h256(); + return sha3(rlp("")); HexMap hexMap; for (auto i = _s.rbegin(); i != _s.rend(); ++i) hexMap[asNibbles(toBigEndianString(i->first))] = asString(rlp(i->second)); diff --git a/crypto.cpp b/crypto.cpp index 0d3b6202f..67286bfca 100644 --- a/crypto.cpp +++ b/crypto.cpp @@ -341,6 +341,7 @@ BOOST_AUTO_TEST_CASE(eth_keypairs) { eth::Transaction t; t.nonce = 0; + t.type = eth::Transaction::MessageCall; t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")); t.value = 1000; auto rlp = t.rlp(false); @@ -369,6 +370,7 @@ int cryptoTest() { eth::Transaction t; t.nonce = 0; + t.type = eth::Transaction::MessageCall; t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")); t.value = 1000; auto rlp = t.rlp(false); @@ -397,6 +399,7 @@ int cryptoTest() Transaction t; t.nonce = 0; t.value = 1; // 1 wei. + t.type = eth::Transaction::MessageCall; t.receiveAddress = toAddress(sha3("123")); bytes sig64 = toBigEndian(t.vrs.r) + toBigEndian(t.vrs.s); diff --git a/state.cpp b/state.cpp index 99ce30957..b0f279bac 100644 --- a/state.cpp +++ b/state.cpp @@ -68,6 +68,7 @@ int stateTest() Transaction t; t.nonce = s.transactionsFrom(myMiner.address()); t.value = 1000; // 1e3 wei. + t.type = eth::Transaction::MessageCall; t.receiveAddress = me.address(); t.sign(myMiner.secret()); assert(t.sender() == myMiner.address()); diff --git a/vm.cpp b/vm.cpp index 2e4571be5..b49c5cd27 100644 --- a/vm.cpp +++ b/vm.cpp @@ -56,14 +56,13 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun get<3>(addresses[ret]) = m_s.code(ret); } - t.receiveAddress = ret; + t.type = eth::Transaction::ContractCreation; callcreates.push_back(t); return ret; } bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride) { - u256 contractgas = 0xffff; Transaction t; @@ -71,6 +70,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, t.gasPrice = gasPrice; t.gas = *_gas; t.data = _data.toVector(); + t.type = eth::Transaction::MessageCall; t.receiveAddress = _receiveAddress; callcreates.push_back(t); @@ -384,7 +384,7 @@ mArray FakeExtVM::exportCallCreates() for (Transaction const& tx: callcreates) { mObject o; - o["destination"] = toString(tx.receiveAddress); + o["destination"] = tx.type == Transaction::ContractCreation ? "" : toString(tx.receiveAddress); push(o, "gasLimit", tx.gas); push(o, "value", tx.value); o["data"] = "0x" + toHex(tx.data); @@ -403,6 +403,7 @@ void FakeExtVM::importCallCreates(mArray& _callcreates) BOOST_REQUIRE(tx.count("destination") > 0); BOOST_REQUIRE(tx.count("gasLimit") > 0); Transaction t; + t.type = tx["destination"].get_str().empty() ? Transaction::ContractCreation : Transaction::MessageCall; t.receiveAddress = Address(tx["destination"].get_str()); t.value = toInt(tx["value"]); t.gas = toInt(tx["gasLimit"]); From dba99342ba185c264b5b04ca36b9ac7e5ecd0a56 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Oct 2014 16:32:53 +0100 Subject: [PATCH 41/48] Move suicides into SubState and include logs and refunds. Refund gas from zero-resetting SSTOREs. --- vm.cpp | 24 ++++++++++++++---------- vm.h | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/vm.cpp b/vm.cpp index b49c5cd27..fe4863041 100644 --- a/vm.cpp +++ b/vm.cpp @@ -45,7 +45,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun m_s.noteSending(myAddress); m_ms.internal.resize(m_ms.internal.size() + 1); - auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); + auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &sub, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); @@ -91,7 +91,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, if (!m_s.addresses().count(myAddress)) { m_ms.internal.resize(m_ms.internal.size() + 1); - auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); + auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &sub, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); if (na != myAddress) @@ -116,7 +116,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, { m_s.noteSending(myAddress); m_ms.internal.resize(m_ms.internal.size() + 1); - auto na = m_s.createNewAddress(_codeAddressOverride ? _codeAddressOverride : _receiveAddress, myAddress, balance(_codeAddressOverride ? _codeAddressOverride : _receiveAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); + auto na = m_s.createNewAddress(_codeAddressOverride ? _codeAddressOverride : _receiveAddress, myAddress, balance(_codeAddressOverride ? _codeAddressOverride : _receiveAddress), gasPrice, &contractgas, init, origin, &sub, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); @@ -131,7 +131,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, m_ms.internal.resize(m_ms.internal.size() + 1); - auto ret = m_s.call(_receiveAddress,_codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _value, gasPrice, _data, _gas, _out, origin, &suicides, &(m_ms.internal.back()), OnOpFunc(), 1); + auto ret = m_s.call(_receiveAddress,_codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _value, gasPrice, _data, _gas, _out, origin, &sub, &(m_ms.internal.back()), OnOpFunc(), 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); @@ -146,12 +146,15 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, if (!ret) return false; + // TODO: @CJentzsch refund SSTORE stuff. + // TODO: @CJentzsch test logs. + // do suicides - for (auto const& f: suicides) + for (auto const& f: sub.suicides) addresses.erase(f); // get storage - if ((get<0>(addresses[myAddress]) >= _value) && (suicides.find(_receiveAddress) == suicides.end())) + if ((get<0>(addresses[myAddress]) >= _value) && (sub.suicides.find(_receiveAddress) == sub.suicides.end())) { for (auto const& j: m_s.storage(_receiveAddress)) { @@ -419,8 +422,11 @@ void FakeExtVM::importCallCreates(mArray& _callcreates) } } -h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, std::set
* o_suicides, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level) +// THIS IS BROKEN AND NEEDS TO BE REMOVED. +h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, SubState* o_sub, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level) { + (void)o_sub; + if (!_origin) _origin = _sender; @@ -446,9 +452,7 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end out = vm.go(evm, _onOp); if (o_ms) o_ms->output = out.toBytes(); - if (o_suicides) - for (auto i: evm.suicides) - o_suicides->insert(i); + // TODO: deal with evm.sub } catch (OutOfGas const& /*_e*/) { diff --git a/vm.h b/vm.h index d9dca1d7a..58ff58cd9 100644 --- a/vm.h +++ b/vm.h @@ -44,7 +44,7 @@ class FakeState: public eth::State { public: /// Execute a contract-creation transaction. - h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = {}, std::set
* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = {}, unsigned _level = 0); + h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = {}, eth::SubState* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = {}, unsigned _level = 0); }; class FakeExtVM: public eth::ExtVMFace From 0a3b337be5174d6c6749b5a548690cdd84706b3a Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Mon, 27 Oct 2014 17:04:18 +0100 Subject: [PATCH 42/48] use ETHEREUM_TEST_PATH in all tests --- genesis.cpp | 13 ++++++++++++- hexPrefix.cpp | 13 ++++++++++++- rlp.cpp | 13 ++++++++++++- trie.cpp | 13 ++++++++++++- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/genesis.cpp b/genesis.cpp index 5f17d2762..16ffb1859 100644 --- a/genesis.cpp +++ b/genesis.cpp @@ -35,9 +35,20 @@ namespace js = json_spirit; BOOST_AUTO_TEST_CASE(genesis_tests) { + const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); + string testPath; + + if (ptestPath == NULL) + { + cnote << " could not find environment variable ETHEREUM_TEST_PATH \n"; + testPath = "../../../tests"; + } + else + testPath = ptestPath; + cnote << "Testing Genesis block..."; js::mValue v; - string s = asString(contents("../../../tests/genesishashestest.json")); + string s = asString(contents(testPath + "/genesishashestest.json")); BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'genesishashestest.json' is empty. Have you cloned the 'tests' repo branch develop?"); js::read_string(s, v); diff --git a/hexPrefix.cpp b/hexPrefix.cpp index fb2fbc826..99207ab97 100644 --- a/hexPrefix.cpp +++ b/hexPrefix.cpp @@ -33,9 +33,20 @@ namespace js = json_spirit; BOOST_AUTO_TEST_CASE(hexPrefix_test) { + const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); + string testPath; + + if (ptestPath == NULL) + { + cnote << " could not find environment variable ETHEREUM_TEST_PATH \n"; + testPath = "../../../tests"; + } + else + testPath = ptestPath; + cnote << "Testing Hex-Prefix-Encode..."; js::mValue v; - string s = asString(contents("../../../tests/hexencodetest.json")); + string s = asString(contents(testPath + "/hexencodetest.json")); BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content from 'hexencodetest.json' is empty. Have you cloned the 'tests' repo branch develop?"); js::read_string(s, v); for (auto& i: v.get_obj()) diff --git a/rlp.cpp b/rlp.cpp index 69360ad66..608a8499e 100644 --- a/rlp.cpp +++ b/rlp.cpp @@ -61,7 +61,18 @@ namespace dev static void getRLPTestCases(js::mValue& v) { - string s = asString(contents("../../../tests/rlptest.json")); + const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); + string testPath; + + if (ptestPath == NULL) + { + cnote << " could not find environment variable ETHEREUM_TEST_PATH \n"; + testPath = "../../../tests"; + } + else + testPath = ptestPath; + + string s = asString(contents(testPath + "/rlptest.json")); BOOST_REQUIRE_MESSAGE( s.length() > 0, "Contents of 'rlptest.json' is empty. Have you cloned the 'tests' repo branch develop?"); js::read_string(s, v); diff --git a/trie.cpp b/trie.cpp index 899eb1f60..f8ebd10c8 100644 --- a/trie.cpp +++ b/trie.cpp @@ -49,9 +49,20 @@ static unsigned fac(unsigned _i) BOOST_AUTO_TEST_CASE(trie_tests) { + const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); + string testPath; + + if (ptestPath == NULL) + { + cnote << " could not find environment variable ETHEREUM_TEST_PATH \n"; + testPath = "../../../tests"; + } + else + testPath = ptestPath; + cnote << "Testing Trie..."; js::mValue v; - string s = asString(contents("../../../tests/trietest.json")); + string s = asString(contents(testPath + "/trietest.json")); BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'trietest.json' is empty. Have you cloned the 'tests' repo branch develop?"); js::read_string(s, v); for (auto& i: v.get_obj()) From 1905208649843cbd52d5ff8be5be6c8206755038 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Mon, 27 Oct 2014 18:59:42 +0100 Subject: [PATCH 43/48] Add VMTRACE to user defined vm test Conflicts: test/vm.cpp --- vm.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- vm.h | 3 +++ 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/vm.cpp b/vm.cpp index fe4863041..c0452ef78 100644 --- a/vm.cpp +++ b/vm.cpp @@ -20,9 +20,9 @@ * vm test functions. */ -#include "vm.h" -#include #include +#include +#include "vm.h" //#define FILL_TESTS @@ -63,6 +63,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride) { + u256 contractgas = 0xffff; Transaction t; @@ -422,8 +423,27 @@ void FakeExtVM::importCallCreates(mArray& _callcreates) } } -// THIS IS BROKEN AND NEEDS TO BE REMOVED. -h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, SubState* o_sub, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level) +OnOpFunc FakeExtVM::simpleTrace() +{ + return [](uint64_t steps, Instruction inst, bigint newMemSize, bigint gasCost, void* voidVM, void const* voidExt) + { + FakeExtVM const& ext = *(FakeExtVM const*)voidExt; + VM& vm = *(VM*)voidVM; + + ostringstream o; + o << endl << " STACK" << endl; + for (auto i: vm.stack()) + o << (h256)i << endl; + o << " MEMORY" << endl << memDump(vm.memory()); + o << " STORAGE" << endl; + for (auto const& i: ext.state().storage(ext.myAddress)) + o << showbase << hex << i.first << ": " << i.second << endl; + dev::LogOutputStream(true) << o.str(); + dev::LogOutputStream(false) << " | " << dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << dec << vm.gas() << " | -" << dec << gasCost << " | " << newMemSize << "x32" << " ]"; + }; +} + +h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, std::set
* o_suicides, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level) { (void)o_sub; @@ -520,7 +540,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) VM vm(fev.gas); try { - output = vm.go(fev).toVector(); + output = vm.go(fev, fev.simpleTrace()).toVector(); } catch (Exception const& _e) { @@ -756,3 +776,30 @@ BOOST_AUTO_TEST_CASE(vmSystemOperationsTest) { dev::test::executeTests("vmSystemOperationsTest"); } + +BOOST_AUTO_TEST_CASE(userDefinedFile) +{ + + if (boost::unit_test::framework::master_test_suite().argc == 2) + { + string filename = boost::unit_test::framework::master_test_suite().argv[1]; + g_logVerbosity = 12; + try + { + cnote << "Testing VM..." << "user defined test"; + json_spirit::mValue v; + string s = asString(contents(filename)); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. "); + json_spirit::read_string(s, v); + dev::test::doTests(v, false); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed VM Test with Exception: " << diagnostic_information(_e)); + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed VM Test with Exception: " << _e.what()); + } + } +} diff --git a/vm.h b/vm.h index 58ff58cd9..bf44c4b42 100644 --- a/vm.h +++ b/vm.h @@ -80,6 +80,9 @@ public: json_spirit::mArray exportCallCreates(); void importCallCreates(json_spirit::mArray& _callcreates); + static eth::OnOpFunc simpleTrace(); + FakeState state() const { return m_s; } + std::map, bytes>> addresses; eth::Transactions callcreates; bytes thisTxData; From 6d1c06a7194209f5a33643198a3734b3be744e49 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Mon, 27 Oct 2014 19:01:10 +0100 Subject: [PATCH 44/48] VMTRACE for internal calls Conflicts: test/vm.cpp --- vm.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/vm.cpp b/vm.cpp index c0452ef78..fe2aff8cd 100644 --- a/vm.cpp +++ b/vm.cpp @@ -509,6 +509,7 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end + namespace dev { namespace test { void doTests(json_spirit::mValue& v, bool _fillin) From 0006d8fefa29af93a80455d32b50cdf08f30d5cb Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Oct 2014 20:26:34 +0100 Subject: [PATCH 45/48] Draft of new LOG/bloom/headers/block format. --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index ef009e299..3f8860d7a 100644 --- a/main.cpp +++ b/main.cpp @@ -44,7 +44,7 @@ using namespace dev::eth; BOOST_AUTO_TEST_CASE(basic_tests) { /* RLPStream s; - BlockInfo::genesis().fillStream(s, false); + BlockInfo::genesis().streamRLP(s, false); std::cout << RLP(s.out()) << std::endl; std::cout << toHex(s.out()) << std::endl; std::cout << sha3(s.out()) << std::endl;*/ From 7a3517ed3af5525de8af979baa229f9fdb94b2b6 Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Mon, 27 Oct 2014 22:21:30 +0100 Subject: [PATCH 46/48] log VMTRACE in file for user defined test --- vm.cpp | 31 ++++++------------------------- vm.h | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/vm.cpp b/vm.cpp index fe2aff8cd..feb2bbaaa 100644 --- a/vm.cpp +++ b/vm.cpp @@ -21,7 +21,6 @@ */ #include -#include #include "vm.h" //#define FILL_TESTS @@ -63,7 +62,6 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride) { - u256 contractgas = 0xffff; Transaction t; @@ -132,7 +130,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, m_ms.internal.resize(m_ms.internal.size() + 1); - auto ret = m_s.call(_receiveAddress,_codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _value, gasPrice, _data, _gas, _out, origin, &sub, &(m_ms.internal.back()), OnOpFunc(), 1); + auto ret = m_s.call(_receiveAddress,_codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _value, gasPrice, _data, _gas, _out, origin, &sub, &(m_ms.internal.back()), simpleTrace(), 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); @@ -423,27 +421,8 @@ void FakeExtVM::importCallCreates(mArray& _callcreates) } } -OnOpFunc FakeExtVM::simpleTrace() -{ - return [](uint64_t steps, Instruction inst, bigint newMemSize, bigint gasCost, void* voidVM, void const* voidExt) - { - FakeExtVM const& ext = *(FakeExtVM const*)voidExt; - VM& vm = *(VM*)voidVM; - - ostringstream o; - o << endl << " STACK" << endl; - for (auto i: vm.stack()) - o << (h256)i << endl; - o << " MEMORY" << endl << memDump(vm.memory()); - o << " STORAGE" << endl; - for (auto const& i: ext.state().storage(ext.myAddress)) - o << showbase << hex << i.first << ": " << i.second << endl; - dev::LogOutputStream(true) << o.str(); - dev::LogOutputStream(false) << " | " << dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << dec << vm.gas() << " | -" << dec << gasCost << " | " << newMemSize << "x32" << " ]"; - }; -} - -h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, std::set
* o_suicides, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level) +// THIS IS BROKEN AND NEEDS TO BE REMOVED. +h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, SubState* o_sub, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level) { (void)o_sub; @@ -541,7 +520,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) VM vm(fev.gas); try { - output = vm.go(fev, fev.simpleTrace()).toVector(); + output = vm.go(fev, fev.simpleTrace()).toVector(); } catch (Exception const& _e) { @@ -784,6 +763,7 @@ BOOST_AUTO_TEST_CASE(userDefinedFile) if (boost::unit_test::framework::master_test_suite().argc == 2) { string filename = boost::unit_test::framework::master_test_suite().argv[1]; + int currentVerbosity = g_logVerbosity; g_logVerbosity = 12; try { @@ -802,5 +782,6 @@ BOOST_AUTO_TEST_CASE(userDefinedFile) { BOOST_ERROR("Failed VM Test with Exception: " << _e.what()); } + g_logVerbosity = currentVerbosity; } } diff --git a/vm.h b/vm.h index bf44c4b42..1718cd6f0 100644 --- a/vm.h +++ b/vm.h @@ -28,6 +28,7 @@ along with cpp-ethereum. If not, see . #include #include "JsonSpiritHeaders.h" #include +#include #include #include #include @@ -36,6 +37,7 @@ along with cpp-ethereum. If not, see . #include #include + namespace dev { namespace test { struct FakeExtVMFailure : virtual Exception {}; @@ -44,7 +46,7 @@ class FakeState: public eth::State { public: /// Execute a contract-creation transaction. - h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = {}, eth::SubState* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = {}, unsigned _level = 0); + h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = {}, eth::SubState* o_sub = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = {}, unsigned _level = 0); }; class FakeExtVM: public eth::ExtVMFace @@ -80,7 +82,9 @@ public: json_spirit::mArray exportCallCreates(); void importCallCreates(json_spirit::mArray& _callcreates); - static eth::OnOpFunc simpleTrace(); + template + eth::OnOpFunc simpleTrace(); + FakeState state() const { return m_s; } std::map, bytes>> addresses; @@ -94,4 +98,32 @@ private: eth::Manifest m_ms; }; +template +eth::OnOpFunc FakeExtVM::simpleTrace() +{ + return [](uint64_t steps, eth::Instruction inst, bigint newMemSize, bigint gasCost, void* voidVM, void const* voidExt) + { + ExtVMType const& ext = *(ExtVMType const*)voidExt; + eth::VM& vm = *(eth::VM*)voidVM; + + std::ostringstream o; + o << std::endl << " STACK" << std::endl; + for (auto i: vm.stack()) + o << (h256)i << std::endl; + o << " MEMORY" << std::endl << memDump(vm.memory()); + o << " STORAGE" << std::endl; + for (auto const& i: ext.state().storage(ext.myAddress)) + o << std::showbase << std::hex << i.first << ": " << i.second << std::endl; + dev::LogOutputStream(true) << o.str(); + dev::LogOutputStream(false) << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32" << " ]"; + + if (eth::VMTraceChannel::verbosity <= g_logVerbosity) + { + std::ofstream f; + f.open("./vmtrace.log", std::ofstream::app); + f << o.str(); + f << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32"; + } + }; +} } } // Namespace Close From a0cfe7aeef1fd18b4cc7e8a62f3f788c0619d80c Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Mon, 27 Oct 2014 22:33:23 +0100 Subject: [PATCH 47/48] Update vm.cpp --- vm.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/vm.cpp b/vm.cpp index feb2bbaaa..40a0a862b 100644 --- a/vm.cpp +++ b/vm.cpp @@ -486,9 +486,6 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end return _newAddress; } - - - namespace dev { namespace test { void doTests(json_spirit::mValue& v, bool _fillin) From f1f8e2632da9866832e8e41d1b7383444a5d042e Mon Sep 17 00:00:00 2001 From: Christoph Jentzsch Date: Mon, 27 Oct 2014 22:33:50 +0100 Subject: [PATCH 48/48] Update vm.h --- vm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/vm.h b/vm.h index 1718cd6f0..f3aae694a 100644 --- a/vm.h +++ b/vm.h @@ -37,7 +37,6 @@ along with cpp-ethereum. If not, see . #include #include - namespace dev { namespace test { struct FakeExtVMFailure : virtual Exception {};