diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/ExecutionFramework.h | 67 | ||||
-rw-r--r-- | test/RPCSession.cpp | 27 | ||||
-rw-r--r-- | test/RPCSession.h | 1 | ||||
-rw-r--r-- | test/contracts/AuctionRegistrar.cpp | 2 | ||||
-rw-r--r-- | test/contracts/ContractInterface.h | 99 | ||||
-rw-r--r-- | test/libevmasm/Optimiser.cpp | 14 | ||||
-rw-r--r-- | test/liblll/Compiler.cpp | 532 | ||||
-rw-r--r-- | test/libsolidity/AnalysisFramework.cpp | 2 | ||||
-rw-r--r-- | test/libsolidity/Assembly.cpp | 2 | ||||
-rw-r--r-- | test/libsolidity/GasMeter.cpp | 14 | ||||
-rw-r--r-- | test/libsolidity/SolidityABIJSON.cpp | 2 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 344 | ||||
-rw-r--r-- | test/libsolidity/SolidityExecutionFramework.h | 2 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 87 | ||||
-rw-r--r-- | test/libsolidity/SolidityNatspecJSON.cpp | 4 | ||||
-rw-r--r-- | test/libsolidity/ViewPureChecker.cpp | 7 |
16 files changed, 1112 insertions, 94 deletions
diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index cc25bea7..2c61c0a6 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -172,78 +172,13 @@ public: { return bytes(); } + //@todo might be extended in the future template <class Arg> static bytes encodeDyn(Arg const& _arg) { return encodeArgs(u256(0x20), u256(_arg.size()), _arg); } - class ContractInterface - { - public: - ContractInterface(ExecutionFramework& _framework): m_framework(_framework) {} - - void setNextValue(u256 const& _value) { m_nextValue = _value; } - - protected: - template <class... Args> - bytes const& call(std::string const& _sig, Args const&... _arguments) - { - auto const& ret = m_framework.callContractFunctionWithValue(_sig, m_nextValue, _arguments...); - m_nextValue = 0; - return ret; - } - - void callString(std::string const& _name, std::string const& _arg) - { - BOOST_CHECK(call(_name + "(string)", u256(0x20), _arg.length(), _arg).empty()); - } - - void callStringAddress(std::string const& _name, std::string const& _arg1, u160 const& _arg2) - { - BOOST_CHECK(call(_name + "(string,address)", u256(0x40), _arg2, _arg1.length(), _arg1).empty()); - } - - void callStringAddressBool(std::string const& _name, std::string const& _arg1, u160 const& _arg2, bool _arg3) - { - BOOST_CHECK(call(_name + "(string,address,bool)", u256(0x60), _arg2, _arg3, _arg1.length(), _arg1).empty()); - } - - void callStringBytes32(std::string const& _name, std::string const& _arg1, h256 const& _arg2) - { - BOOST_CHECK(call(_name + "(string,bytes32)", u256(0x40), _arg2, _arg1.length(), _arg1).empty()); - } - - u160 callStringReturnsAddress(std::string const& _name, std::string const& _arg) - { - bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg); - BOOST_REQUIRE(ret.size() == 0x20); - BOOST_CHECK(std::count(ret.begin(), ret.begin() + 12, 0) == 12); - return u160(u256(h256(ret))); - } - - std::string callAddressReturnsString(std::string const& _name, u160 const& _arg) - { - bytesConstRef const ret(&call(_name + "(address)", _arg)); - BOOST_REQUIRE(ret.size() >= 0x40); - u256 offset(h256(ret.cropped(0, 0x20))); - BOOST_REQUIRE_EQUAL(offset, 0x20); - u256 len(h256(ret.cropped(0x20, 0x20))); - BOOST_REQUIRE_EQUAL(ret.size(), 0x40 + ((len + 0x1f) / 0x20) * 0x20); - return ret.cropped(0x40, size_t(len)).toString(); - } - - h256 callStringReturnsBytes32(std::string const& _name, std::string const& _arg) - { - bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg); - BOOST_REQUIRE(ret.size() == 0x20); - return h256(ret); - } - - private: - u256 m_nextValue; - ExecutionFramework& m_framework; - }; private: template <class CppFunction, class... Args> diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index 768c8c4b..c06c3997 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -74,7 +74,10 @@ IPCSocket::IPCSocket(string const& _path): m_path(_path) BOOST_FAIL("Error creating IPC socket object"); if (connect(m_socket, reinterpret_cast<struct sockaddr const*>(&saun), sizeof(struct sockaddr_un)) < 0) + { + close(m_socket); BOOST_FAIL("Error connecting to IPC socket: " << _path); + } #endif } @@ -236,7 +239,10 @@ void RPCSession::test_setChainParams(vector<string> const& _accounts) "0000000000000000000000000000000000000001": { "wei": "1", "precompiled": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, "0000000000000000000000000000000000000002": { "wei": "1", "precompiled": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, "0000000000000000000000000000000000000003": { "wei": "1", "precompiled": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "wei": "1", "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } } + "0000000000000000000000000000000000000004": { "wei": "1", "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000006": { "wei": "1", "precompiled": { "name": "alt_bn128_G1_add", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000007": { "wei": "1", "precompiled": { "name": "alt_bn128_G1_mul", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000008": { "wei": "1", "precompiled": { "name": "alt_bn128_pairing_product", "linear": { "base": 15, "word": 3 } } } } } )"; @@ -333,22 +339,25 @@ Json::Value RPCSession::rpcCall(string const& _methodName, vector<string> const& return result["result"]; } +string const& RPCSession::accountCreate() +{ + m_accounts.push_back(personal_newAccount("")); + personal_unlockAccount(m_accounts.back(), "", 100000); + return m_accounts.back(); +} + string const& RPCSession::accountCreateIfNotExists(size_t _id) { - if (_id >= m_accounts.size()) - { - m_accounts.push_back(personal_newAccount("")); - personal_unlockAccount(m_accounts.back(), "", 100000); - } + while ((_id + 1) > m_accounts.size()) + accountCreate(); return m_accounts[_id]; } RPCSession::RPCSession(const string& _path): m_ipcSocket(_path) { - string account = personal_newAccount(""); - personal_unlockAccount(account, "", 100000); - m_accounts.push_back(account); + accountCreate(); + // This will pre-fund the accounts create prior. test_setChainParams(m_accounts); } diff --git a/test/RPCSession.h b/test/RPCSession.h index eae6a09c..63f1dd21 100644 --- a/test/RPCSession.h +++ b/test/RPCSession.h @@ -121,6 +121,7 @@ public: Json::Value rpcCall(std::string const& _methodName, std::vector<std::string> const& _args = std::vector<std::string>(), bool _canFail = false); std::string const& account(size_t _id) const { return m_accounts.at(_id); } + std::string const& accountCreate(); std::string const& accountCreateIfNotExists(size_t _id); private: diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index 73a5d1ed..c9c744af 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -24,6 +24,7 @@ #include <tuple> #include <boost/test/unit_test.hpp> #include <test/libsolidity/SolidityExecutionFramework.h> +#include <test/contracts/ContractInterface.h> using namespace std; using namespace dev::test; @@ -230,7 +231,6 @@ protected: BOOST_REQUIRE(!m_output.empty()); } - using ContractInterface = SolidityExecutionFramework::ContractInterface; class RegistrarInterface: public ContractInterface { public: diff --git a/test/contracts/ContractInterface.h b/test/contracts/ContractInterface.h new file mode 100644 index 00000000..052b0db2 --- /dev/null +++ b/test/contracts/ContractInterface.h @@ -0,0 +1,99 @@ +/* + This file is part of solidity. + + solidity 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. + + solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include <boost/test/unit_test.hpp> +#include <test/ExecutionFramework.h> + +#include <functional> + +namespace dev +{ +namespace test +{ + +class ContractInterface +{ +public: + ContractInterface(ExecutionFramework& _framework): m_framework(_framework) {} + + void setNextValue(u256 const& _value) { m_nextValue = _value; } + +protected: + template <class... Args> + bytes const& call(std::string const& _sig, Args const&... _arguments) + { + auto const& ret = m_framework.callContractFunctionWithValue(_sig, m_nextValue, _arguments...); + m_nextValue = 0; + return ret; + } + + void callString(std::string const& _name, std::string const& _arg) + { + BOOST_CHECK(call(_name + "(string)", u256(0x20), _arg.length(), _arg).empty()); + } + + void callStringAddress(std::string const& _name, std::string const& _arg1, u160 const& _arg2) + { + BOOST_CHECK(call(_name + "(string,address)", u256(0x40), _arg2, _arg1.length(), _arg1).empty()); + } + + void callStringAddressBool(std::string const& _name, std::string const& _arg1, u160 const& _arg2, bool _arg3) + { + BOOST_CHECK(call(_name + "(string,address,bool)", u256(0x60), _arg2, _arg3, _arg1.length(), _arg1).empty()); + } + + void callStringBytes32(std::string const& _name, std::string const& _arg1, h256 const& _arg2) + { + BOOST_CHECK(call(_name + "(string,bytes32)", u256(0x40), _arg2, _arg1.length(), _arg1).empty()); + } + + u160 callStringReturnsAddress(std::string const& _name, std::string const& _arg) + { + bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg); + BOOST_REQUIRE(ret.size() == 0x20); + BOOST_CHECK(std::count(ret.begin(), ret.begin() + 12, 0) == 12); + return u160(u256(h256(ret))); + } + + std::string callAddressReturnsString(std::string const& _name, u160 const& _arg) + { + bytesConstRef const ret(&call(_name + "(address)", _arg)); + BOOST_REQUIRE(ret.size() >= 0x40); + u256 offset(h256(ret.cropped(0, 0x20))); + BOOST_REQUIRE_EQUAL(offset, 0x20); + u256 len(h256(ret.cropped(0x20, 0x20))); + BOOST_REQUIRE_EQUAL(ret.size(), 0x40 + ((len + 0x1f) / 0x20) * 0x20); + return ret.cropped(0x40, size_t(len)).toString(); + } + + h256 callStringReturnsBytes32(std::string const& _name, std::string const& _arg) + { + bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg); + BOOST_REQUIRE(ret.size() == 0x20); + return h256(ret); + } + +private: + u256 m_nextValue; + ExecutionFramework& m_framework; +}; + +} +} // end namespaces + diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 9dc49581..0ab95b08 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -841,6 +841,20 @@ BOOST_AUTO_TEST_CASE(peephole_double_push) ); } +BOOST_AUTO_TEST_CASE(peephole_pop_calldatasize) +{ + AssemblyItems items{ + u256(4), + Instruction::CALLDATASIZE, + Instruction::LT, + Instruction::POP + }; + PeepholeOptimiser peepOpt(items); + for (size_t i = 0; i < 3; i++) + BOOST_CHECK(peepOpt.optimise()); + BOOST_CHECK(items.empty()); +} + BOOST_AUTO_TEST_CASE(jumpdest_removal) { AssemblyItems items{ diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp index 2d66bce1..ace97e15 100644 --- a/test/liblll/Compiler.cpp +++ b/test/liblll/Compiler.cpp @@ -24,6 +24,7 @@ #include <memory> #include <boost/test/unit_test.hpp> #include <liblll/Compiler.h> +#include <libdevcore/FixedHash.h> using namespace std; @@ -37,9 +38,9 @@ namespace test namespace { -bool successCompile(std::string const& _sourceCode) +bool successCompile(string const& _sourceCode) { - std::vector<std::string> errors; + vector<string> errors; bytes bytecode = eth::compileLLL(_sourceCode, false, &errors); if (!errors.empty()) return false; @@ -121,6 +122,533 @@ BOOST_AUTO_TEST_CASE(switch_inconsistent_return_count) BOOST_CHECK(!successCompile(sourceCode)); } +BOOST_AUTO_TEST_CASE(disallowed_asm_instructions) +{ + for (unsigned i = 1; i <= 32; i++) + BOOST_CHECK(!successCompile("(asm PUSH" + boost::lexical_cast<string>(i) + ")")); +} + +BOOST_AUTO_TEST_CASE(disallowed_functional_asm_instructions) +{ + for (unsigned i = 1; i <= 32; i++) + BOOST_CHECK(!successCompile("(PUSH" + boost::lexical_cast<string>(i) + ")")); + for (unsigned i = 1; i <= 16; i++) + BOOST_CHECK(!successCompile("(DUP" + boost::lexical_cast<string>(i) + ")")); + for (unsigned i = 1; i <= 16; i++) + BOOST_CHECK(!successCompile("(SWAP" + boost::lexical_cast<string>(i) + ")")); + BOOST_CHECK(!successCompile("(JUMPDEST)")); +} + +BOOST_AUTO_TEST_CASE(valid_opcodes_functional) +{ + vector<string> opcodes_bytecode { + "00", + "6000600001", + "6000600002", + "6000600003", + "6000600004", + "6000600005", + "6000600006", + "6000600007", + "60006000600008", + "60006000600009", + "600060000a", + "600060000b", + "6000600010", + "6000600011", + "6000600012", + "6000600013", + "6000600014", + "600015", + "6000600016", + "6000600017", + "6000600018", + "600019", + "600060001a", + "6000600020", + "30", + "600031", + "32", + "33", + "34", + "600035", + "36", + "60006000600037", + "38", + "60006000600039", + "3a", + "60003b", + "60006000600060003c", + "3d", + "6000600060003e", + "600040", + "41", + "42", + "43", + "44", + "45", + "600050", + "600051", + "6000600052", + "6000600053", + "600054", + "6000600055", + "600056", + "6000600057", + "58", + "59", + "5a", + "60ff", + "61ffff", + "62ffffff", + "63ffffffff", + "64ffffffffff", + "65ffffffffffff", + "66ffffffffffffff", + "67ffffffffffffffff", + "68ffffffffffffffffff", + "69ffffffffffffffffffff", + "6affffffffffffffffffffff", + "6bffffffffffffffffffffffff", + "6cffffffffffffffffffffffffff", + "6dffffffffffffffffffffffffffff", + "6effffffffffffffffffffffffffffff", + "6fffffffffffffffffffffffffffffffff", + "70ffffffffffffffffffffffffffffffffff", + "71ffffffffffffffffffffffffffffffffffff", + "72ffffffffffffffffffffffffffffffffffffff", + "73ffffffffffffffffffffffffffffffffffffffff", + "74ffffffffffffffffffffffffffffffffffffffffff", + "75ffffffffffffffffffffffffffffffffffffffffffff", + "76ffffffffffffffffffffffffffffffffffffffffffffff", + "77ffffffffffffffffffffffffffffffffffffffffffffffff", + "78ffffffffffffffffffffffffffffffffffffffffffffffffff", + "79ffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7affffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "60006000a0", + "600060006000a1", + "6000600060006000a2", + "60006000600060006000a3", + "600060006000600060006000a4", + "600060006000f0", + "6000600060006000600060006000f1", + "6000600060006000600060006000f2", + "60006000f3", + "600060006000600060006000f4", + "600060006000600060006000fa", + "60006000fd", + "fe", + "6000ff" + }; + + vector<string> opcodes_lll { + "{ (STOP) }", + "{ (ADD 0 0) }", + "{ (MUL 0 0) }", + "{ (SUB 0 0) }", + "{ (DIV 0 0) }", + "{ (SDIV 0 0) }", + "{ (MOD 0 0) }", + "{ (SMOD 0 0) }", + "{ (ADDMOD 0 0 0) }", + "{ (MULMOD 0 0 0) }", + "{ (EXP 0 0) }", + "{ (SIGNEXTEND 0 0) }", + "{ (LT 0 0) }", + "{ (GT 0 0) }", + "{ (SLT 0 0) }", + "{ (SGT 0 0) }", + "{ (EQ 0 0) }", + "{ (ISZERO 0) }", + "{ (AND 0 0) }", + "{ (OR 0 0) }", + "{ (XOR 0 0) }", + "{ (NOT 0) }", + "{ (BYTE 0 0) }", + "{ (KECCAK256 0 0) }", + "{ (ADDRESS) }", + "{ (BALANCE 0) }", + "{ (ORIGIN) }", + "{ (CALLER) }", + "{ (CALLVALUE) }", + "{ (CALLDATALOAD 0) }", + "{ (CALLDATASIZE) }", + "{ (CALLDATACOPY 0 0 0) }", + "{ (CODESIZE) }", + "{ (CODECOPY 0 0 0) }", + "{ (GASPRICE) }", + "{ (EXTCODESIZE 0) }", + "{ (EXTCODECOPY 0 0 0 0) }", + "{ (RETURNDATASIZE) }", + "{ (RETURNDATACOPY 0 0 0) }", + "{ (BLOCKHASH 0) }", + "{ (COINBASE) }", + "{ (TIMESTAMP) }", + "{ (NUMBER) }", + "{ (DIFFICULTY) }", + "{ (GASLIMIT) }", + "{ (POP 0) }", + "{ (MLOAD 0) }", + "{ (MSTORE 0 0) }", + "{ (MSTORE8 0 0) }", + "{ (SLOAD 0) }", + "{ (SSTORE 0 0) }", + "{ (JUMP 0) }", + "{ (JUMPI 0 0) }", + "{ (PC) }", + "{ (MSIZE) }", + "{ (GAS) }", + "{ 0xff }", + "{ 0xffff }", + "{ 0xffffff }", + "{ 0xffffffff }", + "{ 0xffffffffff }", + "{ 0xffffffffffff }", + "{ 0xffffffffffffff }", + "{ 0xffffffffffffffff }", + "{ 0xffffffffffffffffff }", + "{ 0xffffffffffffffffffff }", + "{ 0xffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff }", + "{ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff }", + "{ (LOG0 0 0) }", + "{ (LOG1 0 0 0) }", + "{ (LOG2 0 0 0 0) }", + "{ (LOG3 0 0 0 0 0) }", + "{ (LOG4 0 0 0 0 0 0) }", + "{ (CREATE 0 0 0) }", + "{ (CALL 0 0 0 0 0 0 0) }", + "{ (CALLCODE 0 0 0 0 0 0 0) }", + "{ (RETURN 0 0) }", + "{ (DELEGATECALL 0 0 0 0 0 0) }", + "{ (STATICCALL 0 0 0 0 0 0) }", + "{ (REVERT 0 0) }", + "{ (INVALID) }", + "{ (SELFDESTRUCT 0) }" + }; + + for (size_t i = 0; i < opcodes_bytecode.size(); i++) { + vector<string> errors; + bytes code = eth::compileLLL(opcodes_lll[i], false, &errors); + + BOOST_REQUIRE_MESSAGE(errors.empty(), opcodes_lll[i]); + + BOOST_CHECK_EQUAL(toHex(code), opcodes_bytecode[i]); + } +} + +BOOST_AUTO_TEST_CASE(valid_opcodes_asm) +{ + vector<string> opcodes_bytecode { + "00", + "01", + "02", + "03", + "04", + "05", + "06", + "07", + "08", + "09", + "0a", + "0b", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "1a", + "20", + "30", + "31", + "32", + "33", + "34", + "35", + "36", + "37", + "38", + "39", + "3a", + "3b", + "3c", + "3d", + "3e", + "40", + "41", + "42", + "43", + "44", + "45", + "50", + "51", + "52", + "53", + "54", + "55", + "56", + "57", + "58", + "59", + "5a", + "5b", + "60ff", + "61ffff", + "62ffffff", + "63ffffffff", + "64ffffffffff", + "65ffffffffffff", + "66ffffffffffffff", + "67ffffffffffffffff", + "68ffffffffffffffffff", + "69ffffffffffffffffffff", + "6affffffffffffffffffffff", + "6bffffffffffffffffffffffff", + "6cffffffffffffffffffffffffff", + "6dffffffffffffffffffffffffffff", + "6effffffffffffffffffffffffffffff", + "6fffffffffffffffffffffffffffffffff", + "70ffffffffffffffffffffffffffffffffff", + "71ffffffffffffffffffffffffffffffffffff", + "72ffffffffffffffffffffffffffffffffffffff", + "73ffffffffffffffffffffffffffffffffffffffff", + "74ffffffffffffffffffffffffffffffffffffffffff", + "75ffffffffffffffffffffffffffffffffffffffffffff", + "76ffffffffffffffffffffffffffffffffffffffffffffff", + "77ffffffffffffffffffffffffffffffffffffffffffffffff", + "78ffffffffffffffffffffffffffffffffffffffffffffffffff", + "79ffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7affffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "80", + "81", + "82", + "83", + "84", + "85", + "86", + "87", + "88", + "89", + "8a", + "8b", + "8c", + "8d", + "8e", + "8f", + "90", + "91", + "92", + "93", + "94", + "95", + "96", + "97", + "98", + "99", + "9a", + "9b", + "9c", + "9d", + "9e", + "9f", + "a0", + "a1", + "a2", + "a3", + "a4", + "f0", + "f1", + "f2", + "f3", + "f4", + "fa", + "fd", + "fe", + "ff" + }; + + vector<string> opcodes_lll { + "{ (asm STOP) }", + "{ (asm ADD) }", + "{ (asm MUL) }", + "{ (asm SUB) }", + "{ (asm DIV) }", + "{ (asm SDIV ) }", + "{ (asm MOD) }", + "{ (asm SMOD) }", + "{ (asm ADDMOD) }", + "{ (asm MULMOD) }", + "{ (asm EXP) }", + "{ (asm SIGNEXTEND) }", + "{ (asm LT) }", + "{ (asm GT) }", + "{ (asm SLT) }", + "{ (asm SGT) }", + "{ (asm EQ) }", + "{ (asm ISZERO) }", + "{ (asm AND) }", + "{ (asm OR) }", + "{ (asm XOR) }", + "{ (asm NOT) }", + "{ (asm BYTE) }", + "{ (asm KECCAK256) }", + "{ (asm ADDRESS) }", + "{ (asm BALANCE) }", + "{ (asm ORIGIN) }", + "{ (asm CALLER) }", + "{ (asm CALLVALUE) }", + "{ (asm CALLDATALOAD) }", + "{ (asm CALLDATASIZE) }", + "{ (asm CALLDATACOPY) }", + "{ (asm CODESIZE) }", + "{ (asm CODECOPY) }", + "{ (asm GASPRICE) }", + "{ (asm EXTCODESIZE)}", + "{ (asm EXTCODECOPY) }", + "{ (asm RETURNDATASIZE) }", + "{ (asm RETURNDATACOPY) }", + "{ (asm BLOCKHASH) }", + "{ (asm COINBASE) }", + "{ (asm TIMESTAMP) }", + "{ (asm NUMBER) }", + "{ (asm DIFFICULTY) }", + "{ (asm GASLIMIT) }", + "{ (asm POP) }", + "{ (asm MLOAD) }", + "{ (asm MSTORE) }", + "{ (asm MSTORE8) }", + "{ (asm SLOAD) }", + "{ (asm SSTORE) }", + "{ (asm JUMP ) }", + "{ (asm JUMPI ) }", + "{ (asm PC) }", + "{ (asm MSIZE) }", + "{ (asm GAS) }", + "{ (asm JUMPDEST) }", + "{ (asm 0xff) }", + "{ (asm 0xffff) }", + "{ (asm 0xffffff) }", + "{ (asm 0xffffffff) }", + "{ (asm 0xffffffffff) }", + "{ (asm 0xffffffffffff) }", + "{ (asm 0xffffffffffffff) }", + "{ (asm 0xffffffffffffffff) }", + "{ (asm 0xffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }", + "{ (asm DUP1) }", + "{ (asm DUP2) }", + "{ (asm DUP3) }", + "{ (asm DUP4) }", + "{ (asm DUP5) }", + "{ (asm DUP6) }", + "{ (asm DUP7) }", + "{ (asm DUP8) }", + "{ (asm DUP9) }", + "{ (asm DUP10) }", + "{ (asm DUP11) }", + "{ (asm DUP12) }", + "{ (asm DUP13) }", + "{ (asm DUP14) }", + "{ (asm DUP15) }", + "{ (asm DUP16) }", + "{ (asm SWAP1) }", + "{ (asm SWAP2) }", + "{ (asm SWAP3) }", + "{ (asm SWAP4) }", + "{ (asm SWAP5) }", + "{ (asm SWAP6) }", + "{ (asm SWAP7) }", + "{ (asm SWAP8) }", + "{ (asm SWAP9) }", + "{ (asm SWAP10) }", + "{ (asm SWAP11) }", + "{ (asm SWAP12) }", + "{ (asm SWAP13) }", + "{ (asm SWAP14) }", + "{ (asm SWAP15) }", + "{ (asm SWAP16) }", + "{ (asm LOG0) }", + "{ (asm LOG1) }", + "{ (asm LOG2) }", + "{ (asm LOG3) }", + "{ (asm LOG4) }", + "{ (asm CREATE) }", + "{ (asm CALL) }", + "{ (asm CALLCODE) }", + "{ (asm RETURN) }", + "{ (asm DELEGATECALL) }", + "{ (asm STATICCALL) }", + "{ (asm REVERT) }", + "{ (asm INVALID) }", + "{ (asm SELFDESTRUCT) }" + }; + + for (size_t i = 0; i < opcodes_bytecode.size(); i++) { + vector<string> errors; + bytes code = eth::compileLLL(opcodes_lll[i], false, &errors); + + BOOST_REQUIRE_MESSAGE(errors.empty(), opcodes_lll[i]); + + BOOST_CHECK_EQUAL(toHex(code), opcodes_bytecode[i]); + } +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 3bdc40a0..ea9703ea 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -81,7 +81,7 @@ AnalysisFramework::parseAnalyseAndReturnError( } } - return make_pair(&m_compiler.ast(), firstError); + return make_pair(&m_compiler.ast(""), firstError); } SourceUnit const* AnalysisFramework::parseAndAnalyse(string const& _source) diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 56ac8cf5..358d3c72 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(location_test) shared_ptr<string const> n = make_shared<string>(""); AssemblyItems items = compileContract(sourceCode); vector<SourceLocation> locations = - vector<SourceLocation>(18, SourceLocation(2, 75, n)) + + vector<SourceLocation>(24, SourceLocation(2, 75, n)) + vector<SourceLocation>(32, SourceLocation(20, 72, n)) + vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + vector<SourceLocation>(2, SourceLocation(58, 67, n)) + diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index c2886f5b..86e8201b 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -51,8 +51,8 @@ public: m_compiler.setOptimiserSettings(dev::test::Options::get().optimize); BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); - AssemblyItems const* items = m_compiler.runtimeAssemblyItems(""); - ASTNode const& sourceUnit = m_compiler.ast(); + AssemblyItems const* items = m_compiler.runtimeAssemblyItems(m_compiler.lastContractName()); + ASTNode const& sourceUnit = m_compiler.ast(""); BOOST_REQUIRE(items != nullptr); m_gasCosts = GasEstimator::breakToStatementLevel( GasEstimator::structuralEstimation(*items, vector<ASTNode const*>({&sourceUnit})), @@ -64,13 +64,13 @@ public: { compileAndRun(_sourceCode); auto state = make_shared<KnownState>(); - PathGasMeter meter(*m_compiler.assemblyItems()); + PathGasMeter meter(*m_compiler.assemblyItems(m_compiler.lastContractName())); GasMeter::GasConsumption gas = meter.estimateMax(0, state); - u256 bytecodeSize(m_compiler.runtimeObject().bytecode.size()); + u256 bytecodeSize(m_compiler.runtimeObject(m_compiler.lastContractName()).bytecode.size()); // costs for deployment gas += bytecodeSize * GasCosts::createDataGas; // costs for transaction - gas += gasForTransaction(m_compiler.object().bytecode, true); + gas += gasForTransaction(m_compiler.object(m_compiler.lastContractName()).bytecode, true); BOOST_REQUIRE(!gas.isInfinite); BOOST_CHECK(gas.value == m_gasUsed); @@ -91,7 +91,7 @@ public: } gas += GasEstimator::functionalEstimation( - *m_compiler.runtimeAssemblyItems(), + *m_compiler.runtimeAssemblyItems(m_compiler.lastContractName()), _sig ); BOOST_REQUIRE(!gas.isInfinite); @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(non_overlapping_filtered_costs) if (first->first->location().intersects(second->first->location())) { BOOST_CHECK_MESSAGE(false, "Source locations should not overlap!"); - auto scannerFromSource = [&](string const&) -> Scanner const& { return m_compiler.scanner(); }; + auto scannerFromSource = [&](string const& _sourceName) -> Scanner const& { return m_compiler.scanner(_sourceName); }; SourceReferenceFormatter::printSourceLocation(cout, &first->first->location(), scannerFromSource); SourceReferenceFormatter::printSourceLocation(cout, &second->first->location(), scannerFromSource); } diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 42f7525f..33962730 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -46,7 +46,7 @@ public: m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); - Json::Value generatedInterface = m_compilerStack.contractABI(""); + Json::Value generatedInterface = m_compilerStack.contractABI(m_compilerStack.lastContractName()); Json::Value expectedInterface; BOOST_REQUIRE(m_reader.parse(_expectedInterfaceString, expectedInterface)); BOOST_CHECK_MESSAGE( diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 35916ec7..9a837113 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -2899,6 +2899,25 @@ BOOST_AUTO_TEST_CASE(default_fallback_throws) ABI_CHECK(callContractFunction("f()"), encodeArgs(0)); } +BOOST_AUTO_TEST_CASE(short_data_calls_fallback) +{ + char const* sourceCode = R"( + contract A { + uint public x; + // Signature is d88e0b00 + function fow() { x = 3; } + function () { x = 2; } + } + )"; + compileAndRun(sourceCode); + // should call fallback + sendMessage(asBytes("\xd8\x8e\x0b"), false, 0); + ABI_CHECK(callContractFunction("x()"), encodeArgs(2)); + // should call function + sendMessage(asBytes(string("\xd8\x8e\x0b") + string(1, 0)), false, 0); + ABI_CHECK(callContractFunction("x()"), encodeArgs(3)); +} + BOOST_AUTO_TEST_CASE(event) { char const* sourceCode = R"( @@ -7309,6 +7328,30 @@ BOOST_AUTO_TEST_CASE(create_memory_array) ABI_CHECK(callContractFunction("f()"), encodeArgs(string("A"), u256(8), u256(4), string("B"))); } +BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size) +{ + // Check allocation size of byte array. Should be 32 plus length rounded up to next + // multiple of 32 + char const* sourceCode = R"( + contract C { + function f() pure returns (uint d1, uint d2, uint d3) { + bytes memory b1 = new bytes(31); + bytes memory b2 = new bytes(32); + bytes memory b3 = new bytes(256); + bytes memory b4 = new bytes(31); + assembly { + d1 := sub(b2, b1) + d2 := sub(b3, b2) + d3 := sub(b4, b3) + } + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256)); +} + + BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes) { // Computes binomial coefficients the chinese way @@ -10176,6 +10219,307 @@ BOOST_AUTO_TEST_CASE(address_overload_resolution) BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(5))); } +BOOST_AUTO_TEST_CASE(snark) +{ + char const* sourceCode = R"( + library Pairing { + struct G1Point { + uint X; + uint Y; + } + // Encoding of field elements is: X[0] * z + X[1] + struct G2Point { + uint[2] X; + uint[2] Y; + } + + /// @return the generator of G1 + function P1() internal returns (G1Point) { + return G1Point(1, 2); + } + + /// @return the generator of G2 + function P2() internal returns (G2Point) { + return G2Point( + [11559732032986387107991004021392285783925812861821192530917403151452391805634, + 10857046999023057135944570762232829481370756359578518086990519993285655852781], + [4082367875863433681332203403145435568316851327593401208105741076214120093531, + 8495653923123431417604973247489272438418190587263600148770280649306958101930] + ); + } + + /// @return the negation of p, i.e. p.add(p.negate()) should be zero. + function negate(G1Point p) internal returns (G1Point) { + // The prime q in the base field F_q for G1 + uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + if (p.X == 0 && p.Y == 0) + return G1Point(0, 0); + return G1Point(p.X, q - (p.Y % q)); + } + + /// @return the sum of two points of G1 + function add(G1Point p1, G1Point p2) internal returns (G1Point r) { + uint[4] memory input; + input[0] = p1.X; + input[1] = p1.Y; + input[2] = p2.X; + input[3] = p2.Y; + bool success; + assembly { + success := call(sub(gas, 2000), 6, 0, input, 0xc0, r, 0x60) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + } + + /// @return the product of a point on G1 and a scalar, i.e. + /// p == p.mul(1) and p.add(p) == p.mul(2) for all points p. + function mul(G1Point p, uint s) internal returns (G1Point r) { + uint[3] memory input; + input[0] = p.X; + input[1] = p.Y; + input[2] = s; + bool success; + assembly { + success := call(sub(gas, 2000), 7, 0, input, 0x80, r, 0x60) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + } + + /// @return the result of computing the pairing check + /// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 + /// For example pairing([P1(), P1().negate()], [P2(), P2()]) should + /// return true. + function pairing(G1Point[] p1, G2Point[] p2) internal returns (bool) { + require(p1.length == p2.length); + uint elements = p1.length; + uint inputSize = p1.length * 6; + uint[] memory input = new uint[](inputSize); + for (uint i = 0; i < elements; i++) + { + input[i * 6 + 0] = p1[i].X; + input[i * 6 + 1] = p1[i].Y; + input[i * 6 + 2] = p2[i].X[0]; + input[i * 6 + 3] = p2[i].X[1]; + input[i * 6 + 4] = p2[i].Y[0]; + input[i * 6 + 5] = p2[i].Y[1]; + } + uint[1] memory out; + bool success; + assembly { + success := call(sub(gas, 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + // Use "invalid" to make gas estimation work + switch success case 0 { invalid() } + } + require(success); + return out[0] != 0; + } + function pairingProd2(G1Point a1, G2Point a2, G1Point b1, G2Point b2) internal returns (bool) { + G1Point[] memory p1 = new G1Point[](2); + G2Point[] memory p2 = new G2Point[](2); + p1[0] = a1; + p1[1] = b1; + p2[0] = a2; + p2[1] = b2; + return pairing(p1, p2); + } + function pairingProd3( + G1Point a1, G2Point a2, + G1Point b1, G2Point b2, + G1Point c1, G2Point c2 + ) internal returns (bool) { + G1Point[] memory p1 = new G1Point[](3); + G2Point[] memory p2 = new G2Point[](3); + p1[0] = a1; + p1[1] = b1; + p1[2] = c1; + p2[0] = a2; + p2[1] = b2; + p2[2] = c2; + return pairing(p1, p2); + } + function pairingProd4( + G1Point a1, G2Point a2, + G1Point b1, G2Point b2, + G1Point c1, G2Point c2, + G1Point d1, G2Point d2 + ) internal returns (bool) { + G1Point[] memory p1 = new G1Point[](4); + G2Point[] memory p2 = new G2Point[](4); + p1[0] = a1; + p1[1] = b1; + p1[2] = c1; + p1[3] = d1; + p2[0] = a2; + p2[1] = b2; + p2[2] = c2; + p2[3] = d2; + return pairing(p1, p2); + } + } + + contract Test { + using Pairing for *; + struct VerifyingKey { + Pairing.G2Point A; + Pairing.G1Point B; + Pairing.G2Point C; + Pairing.G2Point gamma; + Pairing.G1Point gammaBeta1; + Pairing.G2Point gammaBeta2; + Pairing.G2Point Z; + Pairing.G1Point[] IC; + } + struct Proof { + Pairing.G1Point A; + Pairing.G1Point A_p; + Pairing.G2Point B; + Pairing.G1Point B_p; + Pairing.G1Point C; + Pairing.G1Point C_p; + Pairing.G1Point K; + Pairing.G1Point H; + } + function f() returns (bool) { + Pairing.G1Point memory p1; + Pairing.G1Point memory p2; + p1.X = 1; p1.Y = 2; + p2.X = 1; p2.Y = 2; + var explict_sum = Pairing.add(p1, p2); + var scalar_prod = Pairing.mul(p1, 2); + return (explict_sum.X == scalar_prod.X && + explict_sum.Y == scalar_prod.Y); + } + function g() returns (bool) { + Pairing.G1Point memory x = Pairing.add(Pairing.P1(), Pairing.negate(Pairing.P1())); + // should be zero + return (x.X == 0 && x.Y == 0); + } + function testMul() returns (bool) { + Pairing.G1Point memory p; + // @TODO The points here are reported to be not well-formed + p.X = 14125296762497065001182820090155008161146766663259912659363835465243039841726; + p.Y = 16229134936871442251132173501211935676986397196799085184804749187146857848057; + p = Pairing.mul(p, 13986731495506593864492662381614386532349950841221768152838255933892789078521); + return + p.X == 18256332256630856740336504687838346961237861778318632856900758565550522381207 && + p.Y == 6976682127058094634733239494758371323697222088503263230319702770853579280803; + } + function pair() returns (bool) { + Pairing.G2Point memory fiveTimesP2 = Pairing.G2Point( + [4540444681147253467785307942530223364530218361853237193970751657229138047649, 20954117799226682825035885491234530437475518021362091509513177301640194298072], + [11631839690097995216017572651900167465857396346217730511548857041925508482915, 21508930868448350162258892668132814424284302804699005394342512102884055673846] + ); + // The prime p in the base field F_p for G1 + uint p = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + Pairing.G1Point[] memory g1points = new Pairing.G1Point[](2); + Pairing.G2Point[] memory g2points = new Pairing.G2Point[](2); + // check e(5 P1, P2)e(-P1, 5 P2) == 1 + g1points[0] = Pairing.P1().mul(5); + g1points[1] = Pairing.P1().negate(); + g2points[0] = Pairing.P2(); + g2points[1] = fiveTimesP2; + if (!Pairing.pairing(g1points, g2points)) + return false; + // check e(P1, P2)e(-P1, P2) == 1 + g1points[0] = Pairing.P1(); + g1points[1] = Pairing.P1(); + g1points[1].Y = p - g1points[1].Y; + g2points[0] = Pairing.P2(); + g2points[1] = Pairing.P2(); + if (!Pairing.pairing(g1points, g2points)) + return false; + return true; + } + function verifyingKey() internal returns (VerifyingKey vk) { + vk.A = Pairing.G2Point([0x209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7, 0x04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678], [0x2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d, 0x120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550]); + vk.B = Pairing.G1Point(0x2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc02, 0x03d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db84); + vk.C = Pairing.G2Point([0x2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb, 0x01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb3], [0x14a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713, 0x178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590]); + vk.gamma = Pairing.G2Point([0x25f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb1, 0x22acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d], [0x065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf68, 0x06d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb]); + vk.gammaBeta1 = Pairing.G1Point(0x15794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f21, 0x14db745c6780e9df549864cec19c2daf4531f6ec0c89cc1c7436cc4d8d300c6d); + vk.gammaBeta2 = Pairing.G2Point([0x1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e, 0x283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39], [0x140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e, 0x0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd4]); + vk.Z = Pairing.G2Point([0x217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac29, 0x0a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c], [0x26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a9855, 0x2fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d7]); + vk.IC = new Pairing.G1Point[](10); + vk.IC[0] = Pairing.G1Point(0x0aee46a7ea6e80a3675026dfa84019deee2a2dedb1bbe11d7fe124cb3efb4b5a, 0x044747b6e9176e13ede3a4dfd0d33ccca6321b9acd23bf3683a60adc0366ebaf); + vk.IC[1] = Pairing.G1Point(0x1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc, 0x2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb); + vk.IC[2] = Pairing.G1Point(0x1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f, 0x042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db); + vk.IC[3] = Pairing.G1Point(0x17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc5, 0x02b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a1); + vk.IC[4] = Pairing.G1Point(0x0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d, 0x0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b); + vk.IC[5] = Pairing.G1Point(0x232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f8, 0x2ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda7); + vk.IC[6] = Pairing.G1Point(0x09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe, 0x18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4); + vk.IC[7] = Pairing.G1Point(0x0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a, 0x18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e); + vk.IC[8] = Pairing.G1Point(0x0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a, 0x04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e); + vk.IC[9] = Pairing.G1Point(0x111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f, 0x1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30); + } + function verify(uint[] input, Proof proof) internal returns (uint) { + VerifyingKey memory vk = verifyingKey(); + require(input.length + 1 == vk.IC.length); + // Compute the linear combination vk_x + Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); + for (uint i = 0; i < input.length; i++) + vk_x = Pairing.add(vk_x, Pairing.mul(vk.IC[i + 1], input[i])); + vk_x = Pairing.add(vk_x, vk.IC[0]); + if (!Pairing.pairingProd2(proof.A, vk.A, Pairing.negate(proof.A_p), Pairing.P2())) return 1; + if (!Pairing.pairingProd2(vk.B, proof.B, Pairing.negate(proof.B_p), Pairing.P2())) return 2; + if (!Pairing.pairingProd2(proof.C, vk.C, Pairing.negate(proof.C_p), Pairing.P2())) return 3; + if (!Pairing.pairingProd3( + proof.K, vk.gamma, + Pairing.negate(Pairing.add(vk_x, Pairing.add(proof.A, proof.C))), vk.gammaBeta2, + Pairing.negate(vk.gammaBeta1), proof.B + )) return 4; + if (!Pairing.pairingProd3( + Pairing.add(vk_x, proof.A), proof.B, + Pairing.negate(proof.H), vk.Z, + Pairing.negate(proof.C), Pairing.P2() + )) return 5; + return 0; + } + event Verified(string); + function verifyTx() returns (bool) { + uint[] memory input = new uint[](9); + Proof memory proof; + proof.A = Pairing.G1Point(12873740738727497448187997291915224677121726020054032516825496230827252793177, 21804419174137094775122804775419507726154084057848719988004616848382402162497); + proof.A_p = Pairing.G1Point(7742452358972543465462254569134860944739929848367563713587808717088650354556, 7324522103398787664095385319014038380128814213034709026832529060148225837366); + proof.B = Pairing.G2Point( + [8176651290984905087450403379100573157708110416512446269839297438960217797614, 15588556568726919713003060429893850972163943674590384915350025440408631945055], + [15347511022514187557142999444367533883366476794364262773195059233657571533367, 4265071979090628150845437155927259896060451682253086069461962693761322642015]); + proof.B_p = Pairing.G1Point(2979746655438963305714517285593753729335852012083057917022078236006592638393, 6470627481646078059765266161088786576504622012540639992486470834383274712950); + proof.C = Pairing.G1Point(6851077925310461602867742977619883934042581405263014789956638244065803308498, 10336382210592135525880811046708757754106524561907815205241508542912494488506); + proof.C_p = Pairing.G1Point(12491625890066296859584468664467427202390981822868257437245835716136010795448, 13818492518017455361318553880921248537817650587494176379915981090396574171686); + proof.H = Pairing.G1Point(12091046215835229523641173286701717671667447745509192321596954139357866668225, 14446807589950902476683545679847436767890904443411534435294953056557941441758); + proof.K = Pairing.G1Point(21341087976609916409401737322664290631992568431163400450267978471171152600502, 2942165230690572858696920423896381470344658299915828986338281196715687693170); + input[0] = 13986731495506593864492662381614386532349950841221768152838255933892789078521; + input[1] = 622860516154313070522697309645122400675542217310916019527100517240519630053; + input[2] = 11094488463398718754251685950409355128550342438297986977413505294941943071569; + input[3] = 6627643779954497813586310325594578844876646808666478625705401786271515864467; + input[4] = 2957286918163151606545409668133310005545945782087581890025685458369200827463; + input[5] = 1384290496819542862903939282897996566903332587607290986044945365745128311081; + input[6] = 5613571677741714971687805233468747950848449704454346829971683826953541367271; + input[7] = 9643208548031422463313148630985736896287522941726746581856185889848792022807; + input[8] = 18066496933330839731877828156604; + if (verify(input, proof) == 0) { + Verified("Transaction successfully verified."); + return true; + } else { + return false; + } + } + + } + )"; + compileAndRun(sourceCode, 0, "Pairing"); + compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Pairing", m_contractAddress}}); + // Disabled because the point seems to be not well-formed, we need to find another example. + //BOOST_CHECK(callContractFunction("testMul()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("pair()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("verifyTx()") == encodeArgs(true)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 342d0875..b0daaba9 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -69,7 +69,7 @@ public: ); BOOST_ERROR("Compiling contract failed"); } - eth::LinkerObject obj = m_compiler.object(_contractName); + eth::LinkerObject obj = m_compiler.object(_contractName.empty() ? m_compiler.lastContractName() : _contractName); BOOST_REQUIRE(obj.linkReferences.empty()); sendMessage(obj.bytecode + _arguments, true, _value); return m_output; diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 903e7308..e5990e9b 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -4783,6 +4783,16 @@ BOOST_AUTO_TEST_CASE(warn_about_callcode) } )"; CHECK_WARNING(text, "\"callcode\" has been deprecated in favour of \"delegatecall\""); + text = R"( + pragma experimental "v0.5.0"; + contract test { + function f() pure public { + var x = address(0x12).callcode; + x; + } + } + )"; + CHECK_ERROR(text, TypeError, "\"callcode\" has been deprecated in favour of \"delegatecall\""); } BOOST_AUTO_TEST_CASE(no_warn_about_callcode_as_function) @@ -5537,7 +5547,7 @@ BOOST_AUTO_TEST_CASE(invalid_mobile_type) } } )"; - CHECK_ERROR(text, TypeError, "Invalid mobile type."); + CHECK_ERROR(text, TypeError, "Invalid rational number."); } BOOST_AUTO_TEST_CASE(warns_msg_value_in_non_payable_public_function) @@ -5879,6 +5889,28 @@ BOOST_AUTO_TEST_CASE(interface_function_bodies) CHECK_ERROR(text, TypeError, "Functions in interfaces cannot have an implementation"); } +BOOST_AUTO_TEST_CASE(interface_function_external) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + interface I { + function f() external; + } + )"; + success(text); +} + +BOOST_AUTO_TEST_CASE(interface_function_public) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + interface I { + function f() public; + } + )"; + CHECK_ERROR(text, TypeError, "Functions in interfaces must be declared external."); +} + BOOST_AUTO_TEST_CASE(interface_function_internal) { char const* text = R"( @@ -7074,6 +7106,53 @@ BOOST_AUTO_TEST_CASE(non_external_fallback) CHECK_ERROR(text, TypeError, "Fallback function must be defined as \"external\"."); } +BOOST_AUTO_TEST_CASE(invalid_literal_in_tuple) +{ + char const* text = R"( + contract C { + function f() pure public { + uint x; + (x, ) = (1E111); + } + } + )"; + CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type"); + text = R"( + contract C { + function f() pure public { + uint x; + (x, ) = (1, 1E111); + } + } + )"; + CHECK_ERROR(text, TypeError, "Invalid rational number."); + text = R"( + contract C { + function f() pure public { + uint x; + (x, ) = (1E111, 1); + } + } + )"; + CHECK_ERROR(text, TypeError, "Invalid rational number."); + text = R"( + contract C { + function f() pure public { + (2**270, 1); + } + } + )"; + CHECK_ERROR(text, TypeError, "Invalid rational number."); + text = R"( + contract C { + function f() pure public { + ((2**270) / 2**100, 1); + } + } + )"; + CHECK_SUCCESS(text); +} + BOOST_AUTO_TEST_CASE(warn_about_sha3) { char const* text = R"( @@ -7168,6 +7247,12 @@ BOOST_AUTO_TEST_CASE(array_length_invalid_expression) } )"; CHECK_ERROR(text, TypeError, "Invalid literal value."); + text = R"( + contract C { + uint[3/0] ids; + } + )"; + CHECK_ERROR(text, TypeError, "Operator / not compatible with types int_const 3 and int_const 0"); } BOOST_AUTO_TEST_CASE(no_address_members_on_contract) diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index d83773bc..fb09451f 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -51,9 +51,9 @@ public: Json::Value generatedDocumentation; if (_userDocumentation) - generatedDocumentation = m_compilerStack.natspecUser(""); + generatedDocumentation = m_compilerStack.natspecUser(m_compilerStack.lastContractName()); else - generatedDocumentation = m_compilerStack.natspecDev(""); + generatedDocumentation = m_compilerStack.natspecDev(m_compilerStack.lastContractName()); Json::Value expectedDocumentation; m_reader.parse(_expectedDocumentationString, expectedDocumentation); BOOST_CHECK_MESSAGE( diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index 80241519..6353ae8a 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -349,7 +349,7 @@ BOOST_AUTO_TEST_CASE(assembly) assembly { x := 7 } } function g() view public { - assembly { for {} 1 { pop(sload(0)) } { } } + assembly { for {} 1 { pop(sload(0)) } { } pop(gas) } } function h() view public { assembly { function g() { pop(blockhash(20)) } } @@ -357,6 +357,9 @@ BOOST_AUTO_TEST_CASE(assembly) function j() public { assembly { pop(call(0, 1, 2, 3, 4, 5, 6)) } } + function k() public { + assembly { pop(call(gas, 1, 2, 3, 4, 5, 6)) } + } } )"; CHECK_SUCCESS_NO_WARNINGS(text); @@ -367,7 +370,7 @@ BOOST_AUTO_TEST_CASE(assembly_staticcall) string text = R"( contract C { function i() view public { - assembly { pop(staticcall(0, 1, 2, 3, 4, 5)) } + assembly { pop(staticcall(gas, 1, 2, 3, 4, 5)) } } } )"; |