From 4167f7c860be3b42c425cfd6998ce015e21f4e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Apr 2017 17:06:35 +0200 Subject: [PATCH 01/26] Improve ccache usage On Travis CI limit cache to 1 GB and cleanup after the build. Print better CMake logs and stats. --- .travis.yml | 8 ++------ cmake/EthCompilerSettings.cmake | 11 ++++++----- scripts/cleanup_ccache.sh | 6 ++++++ scripts/install_deps.sh | 7 ++++++- scripts/prepare_ccache.sh | 15 +++++++++++++++ 5 files changed, 35 insertions(+), 12 deletions(-) create mode 100755 scripts/cleanup_ccache.sh create mode 100755 scripts/prepare_ccache.sh diff --git a/.travis.yml b/.travis.yml index 7343992f5f9..e8416fda4e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -106,17 +106,13 @@ cache: # Cache whole deps dir hoping you will not need to download and # build external dependencies next build. - $TRAVIS_BUILD_DIR/deps -before_install: - # Install ccache on osx - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ccache; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi install: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./scripts/install_cmake.sh; fi - ./scripts/install_deps.sh before_script: - - ccache -s + - ./scripts/prepare_ccache.sh - ./scripts/build.sh $TRAVIS_BUILD_TYPE $TRAVIS_TESTS - - ccache -s + - ./scripts/cleanup_ccache.sh script: - cd $TRAVIS_BUILD_DIR/build && ../scripts/tests.sh $TRAVIS_TESTS after_success: diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 53a2648a6fd..d6c0347bc04 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -14,13 +14,14 @@ # # These settings then end up spanning all POSIX platforms (Linux, OS X, BSD, etc) -# Use ccache if available -find_program(CCACHE_FOUND ccache) -if(CCACHE_FOUND) +# Setup ccache. +# ccache is auto-enabled if the tool is found. To disable set -DCCACHE=Off option. +find_program(CCACHE ccache) +if(CCACHE) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) - message("Using ccache") -endif(CCACHE_FOUND) + message(STATUS "ccache enabled (${CCACHE})") +endif() if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) # Enables all the warnings about constructions that some users consider questionable, diff --git a/scripts/cleanup_ccache.sh b/scripts/cleanup_ccache.sh new file mode 100755 index 00000000000..a8488f04710 --- /dev/null +++ b/scripts/cleanup_ccache.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +set -e + +ccache --cleanup +ccache --show-stats diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 3372471961e..0adbfbee1b1 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -88,6 +88,10 @@ Darwin) ;; esac + if [ "$TRAVIS" ]; then + TRAVIS_PACKAGES="ccache" + fi + # Check for Homebrew install and abort if it is not installed. brew -v > /dev/null 2>&1 || { echo >&2 "ERROR - cpp-ethereum requires a Homebrew install. See http://brew.sh."; exit 1; } @@ -95,7 +99,8 @@ Darwin) brew install \ leveldb \ libmicrohttpd \ - miniupnpc + miniupnpc \ + $TRAVIS_PACKAGES ;; diff --git a/scripts/prepare_ccache.sh b/scripts/prepare_ccache.sh new file mode 100755 index 00000000000..fbe37325bfb --- /dev/null +++ b/scripts/prepare_ccache.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env sh + +set -e + +if [ "$TRAVIS_OS_NAME" = "linux" ]; then + # In Travis Ubuntu 14.04 ccache is too old and does not support some of + # the compiler flags and does not work. Upgrade it to version 3.2. + curl -O http://de.archive.ubuntu.com/ubuntu/pool/main/c/ccache/ccache_3.2.4-1_amd64.deb + sudo dpkg -i ccache_3.2.4-1_amd64.deb +fi + +ccache --version +ccache --show-stats +ccache --zero-stats +ccache --max-size=1G From f2b1b1a4fdb1c5044d8418564889bbe56c58b602 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 18 Apr 2017 17:26:08 +0200 Subject: [PATCH 02/26] change create tx --- libethereum/Executive.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index dbff81d3b4b..59216a55850 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -336,7 +336,11 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g // We can allow for the reverted state (i.e. that with which m_ext is constructed) to contain the m_orig.address, since // we delete it explicitly if we decide we need to revert. - m_newAddress = right160(sha3(rlpList(_sender, nonce))); + if (m_envInfo.number() < m_sealEngine.chainParams().u256Param("Metropolis")) + m_newAddress = right160(sha3(rlpList(_sender, nonce))); + else + m_newAddress = right160(sha3(MaxAddress.asBytes() + sha3(_init).asBytes())); + m_gas = _gas; // Transfer ether before deploying the code. This will also create new From 26b2f33082aff29008c3e150938692658f496f01 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 13:36:43 +0200 Subject: [PATCH 03/26] eip86_create --- ethvm/main.cpp | 2 +- libethereum/Executive.cpp | 15 ++++++++++----- libethereum/Executive.h | 2 +- libethereum/ExtVM.cpp | 4 ++-- libethereum/ExtVM.h | 2 +- libevm/ExtVMFace.h | 2 +- libevm/VM.cpp | 6 ++++++ libevm/VM.h | 2 +- libevm/VMCalls.cpp | 3 ++- libevmcore/Instruction.h | 3 ++- test/tools/jsontests/vm.cpp | 3 ++- test/tools/jsontests/vm.h | 2 +- 12 files changed, 30 insertions(+), 16 deletions(-) diff --git a/ethvm/main.cpp b/ethvm/main.cpp index 2086262bc56..b2d0087030b 100755 --- a/ethvm/main.cpp +++ b/ethvm/main.cpp @@ -299,7 +299,7 @@ int main(int argc, char** argv) if (!code.empty()) executive.call(contractDestination, sender, value, gasPrice, &data, gas); else - executive.create(sender, value, gasPrice, gas, &data, origin); + executive.create(sender, value, gasPrice, gas, &data, origin, Instruction::CREATE); Timer timer; if ((mode == Mode::Statistics || mode == Mode::Trace) && vmKind == VMKind::Interpreter) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 59216a55850..fa9413b94a5 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -251,7 +251,7 @@ bool Executive::execute() m_s.subBalance(m_t.sender(), m_gasCost); if (m_t.isCreation()) - return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)m_baseGasRequired, &m_t.data(), m_t.sender()); + return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)m_baseGasRequired, &m_t.data(), m_t.sender(), Instruction::CREATE); else return call(m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)m_baseGasRequired); } @@ -324,7 +324,7 @@ bool Executive::call(CallParameters const& _p, u256 const& _gasPrice, Address co return !m_ext; } -bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin) +bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin, Instruction _creationType) { u256 nonce = m_s.getNonce(_sender); if (_sender != MaxAddress) // EIP86 @@ -336,10 +336,15 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g // We can allow for the reverted state (i.e. that with which m_ext is constructed) to contain the m_orig.address, since // we delete it explicitly if we decide we need to revert. - if (m_envInfo.number() < m_sealEngine.chainParams().u256Param("Metropolis")) - m_newAddress = right160(sha3(rlpList(_sender, nonce))); + if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("Metropolis")) + { + Address pushedAddress = MaxAddress; + if (_creationType == Instruction::CREATE_PSH) + pushedAddress = _sender; + m_newAddress = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes())); + } else - m_newAddress = right160(sha3(MaxAddress.asBytes() + sha3(_init).asBytes())); + m_newAddress = right160(sha3(rlpList(_sender, nonce))); m_gas = _gas; diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 64c946d81a2..9b756b0938b 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -150,7 +150,7 @@ class Executive /// Set up the executive for evaluating a bare CREATE (contract-creation) operation. /// @returns false iff go() must be called (and thus a VM execution in required). - bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress); + bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress, Instruction _creationType); /// Set up the executive for evaluating a bare CALL (message call) operation. /// @returns false iff go() must be called (and thus a VM execution in required). bool call(Address _receiveAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas); diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index df10f350c98..88a1a80572c 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -115,10 +115,10 @@ void ExtVM::setStore(u256 _n, u256 _v) m_s.setStorage(myAddress, _n, _v); } -h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp) +h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp, Instruction _creationType) { Executive e{m_s, envInfo(), m_sealEngine, depth + 1}; - if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin)) + if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin, _creationType)) { go(depth, e, _onOp); e.accrueSubState(sub); diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index dadcf453607..a94c3d193ff 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -65,7 +65,7 @@ class ExtVM: public ExtVMFace virtual size_t codeSizeAt(Address _a) override final; /// Create a new contract. - virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp = {}) override final; + virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp = {}, Instruction _creationType = Instruction::CREATE) override final; /// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller. /// @returns success flag and output data, if any. diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 272aa6af5ec..2ba9393a7a0 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -298,7 +298,7 @@ class ExtVMFace virtual void suicide(Address) { sub.suicides.insert(myAddress); } /// Create a new (contract) account. - virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&) { return h160(); } + virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&, Instruction) { return h160(); } /// Make a new message call. /// @returns success flag and output data, if any. diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 856b8ec7162..75be2c06d8e 100755 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -211,6 +211,12 @@ void VM::interpretCases() // // Call-related instructions // + + CASE(CREATE_PSH) + { + m_bounce = &VM::caseCreate; + } + BREAK CASE(CREATE) { diff --git a/libevm/VM.h b/libevm/VM.h index 3adb958d06d..ddf76f77489 100755 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -88,7 +88,7 @@ class VM: public VMFace void copyCode(int); const void* const* c_jumpTable = 0; bool m_caseInit = false; - + typedef void (VM::*MemFnPtr)(); MemFnPtr m_bounce = 0; MemFnPtr m_onFail = 0; diff --git a/libevm/VMCalls.cpp b/libevm/VMCalls.cpp index ae4578ca835..96327e318f5 100755 --- a/libevm/VMCalls.cpp +++ b/libevm/VMCalls.cpp @@ -127,7 +127,8 @@ void VM::caseCreate() if (!m_schedule->staticCallDepthLimit()) createGas -= createGas / 64; u256 gas = createGas; - m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_onOp); + m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_onOp, m_OP); + *m_io_gas_p -= (createGas - gas); m_io_gas = uint64_t(*m_io_gas_p); } diff --git a/libevmcore/Instruction.h b/libevmcore/Instruction.h index 34660beab17..c93f4cfb42b 100755 --- a/libevmcore/Instruction.h +++ b/libevmcore/Instruction.h @@ -183,11 +183,12 @@ enum class Instruction: uint8_t JUMPCI, ///< conditionally alter the program counter - pre-verified BAD, ///< placed to force invalid instruction exception - CREATE = 0xf0, ///< create a new account with associated code + CREATE = 0xf0, ///< create a new account with associated code. (since EIP86: sha3((MaxAddress + sha3(code)) CALL, ///< message-call into an account CALLCODE, ///< message-call with another account's code only RETURN, ///< halt execution returning output data DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender + CREATE_PSH = 0xfb, ///< create a new account with associated code. sha3((sender + sha3(code)) REVERT = 0xfd, ///< stop execution and revert state changes, without consuming all provided gas SUICIDE = 0xff ///< halt execution and register account for later deletion }; diff --git a/test/tools/jsontests/vm.cpp b/test/tools/jsontests/vm.cpp index 62bf43bb43c..d61bae32b89 100644 --- a/test/tools/jsontests/vm.cpp +++ b/test/tools/jsontests/vm.cpp @@ -37,8 +37,9 @@ FakeExtVM::FakeExtVM(EnvInfo const& _envInfo, unsigned _depth): /// TODO: XXX: ExtVMFace(_envInfo, Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), EmptySHA3, _depth) {} -h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&) +h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&, Instruction _creationType) { + (void)_creationType; Address na = right160(sha3(rlpList(myAddress, get<1>(addresses[myAddress])))); Transaction t(_endowment, gasPrice, io_gas, _init.toBytes()); diff --git a/test/tools/jsontests/vm.h b/test/tools/jsontests/vm.h index f1a2a60112f..6e38cf98375 100644 --- a/test/tools/jsontests/vm.h +++ b/test/tools/jsontests/vm.h @@ -54,7 +54,7 @@ class FakeExtVM: public eth::ExtVMFace 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 size_t codeSizeAt(Address _a) override { return std::get<3>(addresses[_a]).size(); } - virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&) override; + virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&, eth::Instruction) override; virtual std::pair call(eth::CallParameters&) 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); From 52422f5528d5be6a90f8fc020d339ab7cb9a77dd Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 14:21:52 +0200 Subject: [PATCH 04/26] thrown if address already used --- libethcore/Exceptions.h | 1 + libethereum/Executive.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h index 060731b8cb8..0f6ec6e538d 100644 --- a/libethcore/Exceptions.h +++ b/libethcore/Exceptions.h @@ -77,6 +77,7 @@ DEV_SIMPLE_EXCEPTION(InvalidNumber); DEV_SIMPLE_EXCEPTION(InvalidZeroSignatureTransaction); DEV_SIMPLE_EXCEPTION(BlockNotFound); DEV_SIMPLE_EXCEPTION(UnknownParent); +DEV_SIMPLE_EXCEPTION(AddressAlreadyUsed); DEV_SIMPLE_EXCEPTION(DatabaseAlreadyOpen); DEV_SIMPLE_EXCEPTION(DAGCreationFailure); diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index fa9413b94a5..ee87a8f73aa 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -400,6 +400,8 @@ bool Executive::go(OnOpFunc const& _onOp) auto vm = _onOp ? VMFactory::create(VMKind::Interpreter) : VMFactory::create(); if (m_isCreation) { + if (m_s.addressHasCode(m_newAddress)) + BOOST_THROW_EXCEPTION(AddressAlreadyUsed()); auto out = vm->exec(m_gas, *m_ext, _onOp); if (m_res) { From 88df55150af15456fbde8027884e5e5a896adf27 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Tue, 11 Apr 2017 20:13:34 +0400 Subject: [PATCH 05/26] move transaction verification checks to sealEngine --- libethashseal/Ethash.cpp | 16 ++++++++++++++++ libethereum/Executive.cpp | 26 ++++---------------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/libethashseal/Ethash.cpp b/libethashseal/Ethash.cpp index 4b885cbf4f6..2bc06c1a3fb 100644 --- a/libethashseal/Ethash.cpp +++ b/libethashseal/Ethash.cpp @@ -160,6 +160,22 @@ void Ethash::verifyTransaction(ImportRequirements::value _ir, TransactionBase co } if (_ir & ImportRequirements::TransactionBasic && _t.baseGasRequired(evmSchedule(_env)) > _t.gas()) BOOST_THROW_EXCEPTION(OutOfGasIntrinsic()); + + // Avoid transactions that would take us beyond the block gas limit. + u256 startGasUsed = _env.gasUsed(); + if (startGasUsed + (bigint)_t.gas() > _env.gasLimit()) + { + //clog(ExecutiveWarnChannel) << "Cannot fit tx in block" << _env.number() << ": Require <" << (_env.gasLimit() - startGasUsed) << " Got" << _t.gas(); + BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(_env.gasLimit() - startGasUsed), (bigint)_t.gas())); + } + + // Check gas cost is enough. + int64_t baseGasRequired = _t.baseGasRequired(evmSchedule(_env)); + if (baseGasRequired > _t.gas()) + { + //clog(ExecutiveWarnChannel) << "Not enough gas to pay for the transaction: Require >" << m_baseGasRequired << " Got" << _t.gas(); + BOOST_THROW_EXCEPTION(OutOfGasBase() << RequirementError((bigint)baseGasRequired, (bigint)_t.gas())); + } } u256 Ethash::childGasLimit(BlockHeader const& _bi, u256 const& _gasFloorTarget) const diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index dbff81d3b4b..36704863776 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -178,34 +178,16 @@ void Executive::accrueSubState(SubState& _parentContext) void Executive::initialize(Transaction const& _transaction) { - m_t = _transaction; - try { - m_sealEngine.verifyTransaction(ImportRequirements::Everything, _transaction, m_envInfo); + m_t = _transaction; + m_sealEngine.verifyTransaction(ImportRequirements::Everything, m_t, m_envInfo); + m_baseGasRequired = m_t.baseGasRequired(m_sealEngine.evmSchedule(m_envInfo)); } catch (Exception const& ex) { m_excepted = toTransactionException(ex); - throw; - } - - // Avoid transactions that would take us beyond the block gas limit. - u256 startGasUsed = m_envInfo.gasUsed(); - if (startGasUsed + (bigint)m_t.gas() > m_envInfo.gasLimit()) - { - clog(ExecutiveWarnChannel) << "Cannot fit tx in block" << m_envInfo.number() << ": Require <" << (m_envInfo.gasLimit() - startGasUsed) << " Got" << m_t.gas(); - m_excepted = TransactionException::BlockGasLimitReached; - BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(m_envInfo.gasLimit() - startGasUsed), (bigint)m_t.gas())); - } - - // Check gas cost is enough. - m_baseGasRequired = m_t.baseGasRequired(m_sealEngine.evmSchedule(m_envInfo)); - if (m_baseGasRequired > m_t.gas()) - { - clog(ExecutiveWarnChannel) << "Not enough gas to pay for the transaction: Require >" << m_baseGasRequired << " Got" << m_t.gas(); - m_excepted = TransactionException::OutOfGasBase; - BOOST_THROW_EXCEPTION(OutOfGasBase() << RequirementError((bigint)m_baseGasRequired, (bigint)m_t.gas())); + BOOST_THROW_EXCEPTION(ex); } if (!m_t.hasZeroSignature()) From 8201381ed36e669fdb29cae1fcaea7736f2b33ce Mon Sep 17 00:00:00 2001 From: Dimitry Date: Tue, 18 Apr 2017 20:16:45 +0300 Subject: [PATCH 06/26] use BlockHeader in EnvInfo --- libethashseal/Ethash.cpp | 8 ---- libethereum/Executive.cpp | 2 +- libevm/ExtVMFace.h | 48 ++++++----------------- test/tools/jsontests/TransactionTests.cpp | 1 + 4 files changed, 14 insertions(+), 45 deletions(-) diff --git a/libethashseal/Ethash.cpp b/libethashseal/Ethash.cpp index 2bc06c1a3fb..13b8402caac 100644 --- a/libethashseal/Ethash.cpp +++ b/libethashseal/Ethash.cpp @@ -168,14 +168,6 @@ void Ethash::verifyTransaction(ImportRequirements::value _ir, TransactionBase co //clog(ExecutiveWarnChannel) << "Cannot fit tx in block" << _env.number() << ": Require <" << (_env.gasLimit() - startGasUsed) << " Got" << _t.gas(); BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(_env.gasLimit() - startGasUsed), (bigint)_t.gas())); } - - // Check gas cost is enough. - int64_t baseGasRequired = _t.baseGasRequired(evmSchedule(_env)); - if (baseGasRequired > _t.gas()) - { - //clog(ExecutiveWarnChannel) << "Not enough gas to pay for the transaction: Require >" << m_baseGasRequired << " Got" << _t.gas(); - BOOST_THROW_EXCEPTION(OutOfGasBase() << RequirementError((bigint)baseGasRequired, (bigint)_t.gas())); - } } u256 Ethash::childGasLimit(BlockHeader const& _bi, u256 const& _gasFloorTarget) const diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 36704863776..e6a309dcc27 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -187,7 +187,7 @@ void Executive::initialize(Transaction const& _transaction) catch (Exception const& ex) { m_excepted = toTransactionException(ex); - BOOST_THROW_EXCEPTION(ex); + throw; } if (!m_t.hasZeroSignature()) diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 272aa6af5ec..2f993fc6a02 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -209,52 +209,28 @@ class EnvInfo public: EnvInfo() {} EnvInfo(BlockHeader const& _current, LastHashes const& _lh = LastHashes(), u256 const& _gasUsed = u256()): - m_number(_current.number()), - m_author(_current.author()), - m_timestamp(_current.timestamp()), - m_difficulty(_current.difficulty()), - // Trim gas limit to int64. convert_to used explicitly instead of - // static_cast to be noticed when BlockHeader::gasLimit() will be - // changed to int64 too. - m_gasLimit(_current.gasLimit().convert_to()), + m_headerInfo(_current), m_lastHashes(_lh), m_gasUsed(_gasUsed) {} - EnvInfo(BlockHeader const& _current, LastHashes&& _lh, u256 const& _gasUsed = u256()): - m_number(_current.number()), - m_author(_current.author()), - m_timestamp(_current.timestamp()), - m_difficulty(_current.difficulty()), - // Trim gas limit to int64. convert_to used explicitly instead of - // static_cast to be noticed when BlockHeader::gasLimit() will be - // changed to int64 too. - m_gasLimit(_current.gasLimit().convert_to()), - m_lastHashes(_lh), - m_gasUsed(_gasUsed) - {} - - u256 const& number() const { return m_number; } - Address const& author() const { return m_author; } - u256 const& timestamp() const { return m_timestamp; } - u256 const& difficulty() const { return m_difficulty; } - int64_t gasLimit() const { return m_gasLimit; } + u256 const& number() const { return m_headerInfo.number(); } + Address const& author() const { return m_headerInfo.author(); } + u256 const& timestamp() const { return m_headerInfo.timestamp(); } + u256 const& difficulty() const { return m_headerInfo.difficulty(); } + u256 gasLimit() const { return m_headerInfo.gasLimit(); } LastHashes const& lastHashes() const { return m_lastHashes; } u256 const& gasUsed() const { return m_gasUsed; } - void setNumber(u256 const& _v) { m_number = _v; } - void setAuthor(Address const& _v) { m_author = _v; } - void setTimestamp(u256 const& _v) { m_timestamp = _v; } - void setDifficulty(u256 const& _v) { m_difficulty = _v; } - void setGasLimit(int64_t _v) { m_gasLimit = _v; } + void setNumber(u256 const& _v) { m_headerInfo.setNumber(_v); } + void setAuthor(Address const& _v) { m_headerInfo.setAuthor(_v); } + void setTimestamp(u256 const& _v) { m_headerInfo.setTimestamp(_v); } + void setDifficulty(u256 const& _v) { m_headerInfo.setDifficulty(_v); } + void setGasLimit(u256 _v) { m_headerInfo.setGasLimit(_v); } void setLastHashes(LastHashes&& _lh) { m_lastHashes = _lh; } private: - u256 m_number; - Address m_author; - u256 m_timestamp; - u256 m_difficulty; - int64_t m_gasLimit; + BlockHeader m_headerInfo; LastHashes m_lastHashes; u256 m_gasUsed; }; diff --git a/test/tools/jsontests/TransactionTests.cpp b/test/tools/jsontests/TransactionTests.cpp index 7fc8fbd453e..5a19b905c02 100644 --- a/test/tools/jsontests/TransactionTests.cpp +++ b/test/tools/jsontests/TransactionTests.cpp @@ -50,6 +50,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) u256 transactionBlock = toInt(o["blocknumber"].get_str()); BlockHeader bh; bh.setNumber(transactionBlock); + bh.setGasLimit(u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); bool onMetropolis = (transactionBlock >= se->chainParams().u256Param("metropolisForkBlock")); if (_fillin) From d4b41c005f013a3e7ca3d6fe97f1493d4c719f3f Mon Sep 17 00:00:00 2001 From: Dimitry Date: Wed, 19 Apr 2017 15:42:03 +0300 Subject: [PATCH 07/26] fixes --- libethashseal/Ethash.cpp | 3 --- libethereum/Executive.cpp | 4 ++-- libevm/ExtVMFace.h | 4 ++-- libevm/JitVM.cpp | 3 ++- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/libethashseal/Ethash.cpp b/libethashseal/Ethash.cpp index 13b8402caac..c5a3d90d6f6 100644 --- a/libethashseal/Ethash.cpp +++ b/libethashseal/Ethash.cpp @@ -164,10 +164,7 @@ void Ethash::verifyTransaction(ImportRequirements::value _ir, TransactionBase co // Avoid transactions that would take us beyond the block gas limit. u256 startGasUsed = _env.gasUsed(); if (startGasUsed + (bigint)_t.gas() > _env.gasLimit()) - { - //clog(ExecutiveWarnChannel) << "Cannot fit tx in block" << _env.number() << ": Require <" << (_env.gasLimit() - startGasUsed) << " Got" << _t.gas(); BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(_env.gasLimit() - startGasUsed), (bigint)_t.gas())); - } } u256 Ethash::childGasLimit(BlockHeader const& _bi, u256 const& _gasFloorTarget) const diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index e6a309dcc27..fa37a4bce5b 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -178,11 +178,11 @@ void Executive::accrueSubState(SubState& _parentContext) void Executive::initialize(Transaction const& _transaction) { + m_t = _transaction; + m_baseGasRequired = m_t.baseGasRequired(m_sealEngine.evmSchedule(m_envInfo)); try { - m_t = _transaction; m_sealEngine.verifyTransaction(ImportRequirements::Everything, m_t, m_envInfo); - m_baseGasRequired = m_t.baseGasRequired(m_sealEngine.evmSchedule(m_envInfo)); } catch (Exception const& ex) { diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 2f993fc6a02..57c06467997 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -218,7 +218,7 @@ class EnvInfo Address const& author() const { return m_headerInfo.author(); } u256 const& timestamp() const { return m_headerInfo.timestamp(); } u256 const& difficulty() const { return m_headerInfo.difficulty(); } - u256 gasLimit() const { return m_headerInfo.gasLimit(); } + u256 const& gasLimit() const { return m_headerInfo.gasLimit(); } LastHashes const& lastHashes() const { return m_lastHashes; } u256 const& gasUsed() const { return m_gasUsed; } @@ -226,7 +226,7 @@ class EnvInfo void setAuthor(Address const& _v) { m_headerInfo.setAuthor(_v); } void setTimestamp(u256 const& _v) { m_headerInfo.setTimestamp(_v); } void setDifficulty(u256 const& _v) { m_headerInfo.setDifficulty(_v); } - void setGasLimit(u256 _v) { m_headerInfo.setGasLimit(_v); } + void setGasLimit(u256 const& _v) { m_headerInfo.setGasLimit(_v); } void setLastHashes(LastHashes&& _lh) { m_lastHashes = _lh; } private: diff --git a/libevm/JitVM.cpp b/libevm/JitVM.cpp index 1c3c1abd437..48de9fdce57 100644 --- a/libevm/JitVM.cpp +++ b/libevm/JitVM.cpp @@ -73,7 +73,8 @@ void evm_query( o_result->uint256be = toEvmC(env.envInfo().difficulty()); break; case EVM_GAS_LIMIT: - o_result->int64 = env.envInfo().gasLimit(); + // TODO: Handle overflow / exception + o_result->int64 = static_cast(env.envInfo().gasLimit()); break; case EVM_NUMBER: // TODO: Handle overflow / exception From e4db84287cd2bffb1144f1fa62211c3e6e841270 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Wed, 19 Apr 2017 15:42:08 +0300 Subject: [PATCH 08/26] json tests --- test/jsontests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jsontests b/test/jsontests index 613bb864dc2..789c43bdbb4 160000 --- a/test/jsontests +++ b/test/jsontests @@ -1 +1 @@ -Subproject commit 613bb864dc25045169e7fc58b3d138ff13eb66bf +Subproject commit 789c43bdbb4cb5913e28f855df35703ac87a40c9 From d0d8fc3eb90aa61909a4b62d36f78b8229b7daff Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 15:22:57 +0200 Subject: [PATCH 09/26] MetropolisFakeExtVM --- test/tools/jsontests/vm.cpp | 17 +++++++++++++++++ test/tools/jsontests/vm.h | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/test/tools/jsontests/vm.cpp b/test/tools/jsontests/vm.cpp index d61bae32b89..09a917c6b93 100644 --- a/test/tools/jsontests/vm.cpp +++ b/test/tools/jsontests/vm.cpp @@ -282,6 +282,23 @@ eth::OnOpFunc FakeExtVM::simpleTrace() const }; } +MetropolisFakeExtVM::MetropolisFakeExtVM(EnvInfo const& _envInfo, unsigned _depth): + FakeExtVM(_envInfo, _depth) +{} + +h160 MetropolisFakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&, Instruction _creationType) +{ + (void)_creationType; + Address pushedAddress = MaxAddress; + if (_creationType == Instruction::CREATE_PSH) + pushedAddress = myAddress; + Address na = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes())); + + Transaction t(_endowment, gasPrice, io_gas, _init.toBytes()); + callcreates.push_back(t); + return na; +} + namespace dev { namespace test { void doVMTests(json_spirit::mValue& _v, bool _fillin) diff --git a/test/tools/jsontests/vm.h b/test/tools/jsontests/vm.h index 6e38cf98375..87eb6850293 100644 --- a/test/tools/jsontests/vm.h +++ b/test/tools/jsontests/vm.h @@ -80,5 +80,12 @@ class FakeExtVM: public eth::ExtVMFace u256 execGas; }; +class MetropolisFakeExtVM: public FakeExtVM +{ +public: + MetropolisFakeExtVM(eth::EnvInfo const& _envInfo, unsigned _depth = 0); + virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&, eth::Instruction) override; +}; + } } // Namespace Close From de767cad08214b11d21adfac98bfbea9d7e62a9a Mon Sep 17 00:00:00 2001 From: Dimitry Date: Wed, 19 Apr 2017 15:55:51 +0300 Subject: [PATCH 10/26] remove blockHash tests from stateTests --- test/tools/jsontests/StateTests.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/tools/jsontests/StateTests.cpp b/test/tools/jsontests/StateTests.cpp index 1f1eb991319..403d962b775 100644 --- a/test/tools/jsontests/StateTests.cpp +++ b/test/tools/jsontests/StateTests.cpp @@ -137,7 +137,6 @@ class generaltestfixture BOOST_FIXTURE_TEST_SUITE(StateTestsGeneral, generaltestfixture) //Frontier Tests -BOOST_AUTO_TEST_CASE(stBlockHashTest){} BOOST_AUTO_TEST_CASE(stBoundsTest){} BOOST_AUTO_TEST_CASE(stCallCodes){} BOOST_AUTO_TEST_CASE(stCallCreateCallCodeTest){} From 09f8b940073b0c6badbd9cce9560b933ace87732 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Wed, 19 Apr 2017 16:28:50 +0300 Subject: [PATCH 11/26] jsontests --- test/jsontests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jsontests b/test/jsontests index 789c43bdbb4..4e8b9be3fba 160000 --- a/test/jsontests +++ b/test/jsontests @@ -1 +1 @@ -Subproject commit 789c43bdbb4cb5913e28f855df35703ac87a40c9 +Subproject commit 4e8b9be3fba16ec32e0cdf50b8f9329826283aaa From 995dbdbe1a544c8c2ae73d96b73db1e288f24233 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 15:54:14 +0200 Subject: [PATCH 12/26] remove (void)var --- test/tools/jsontests/vm.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/tools/jsontests/vm.cpp b/test/tools/jsontests/vm.cpp index 09a917c6b93..94148a9bb1e 100644 --- a/test/tools/jsontests/vm.cpp +++ b/test/tools/jsontests/vm.cpp @@ -288,7 +288,6 @@ MetropolisFakeExtVM::MetropolisFakeExtVM(EnvInfo const& _envInfo, unsigned _dept h160 MetropolisFakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&, Instruction _creationType) { - (void)_creationType; Address pushedAddress = MaxAddress; if (_creationType == Instruction::CREATE_PSH) pushedAddress = myAddress; From e95fdbb75906ad02c931fc5b67a096eb7639c353 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 15:56:53 +0200 Subject: [PATCH 13/26] check already used address only if after metropolis --- libethereum/Executive.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index ee87a8f73aa..4d69f9da8de 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -338,6 +338,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g // we delete it explicitly if we decide we need to revert. if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("Metropolis")) { + // EIP86 Address pushedAddress = MaxAddress; if (_creationType == Instruction::CREATE_PSH) pushedAddress = _sender; @@ -400,8 +401,9 @@ bool Executive::go(OnOpFunc const& _onOp) auto vm = _onOp ? VMFactory::create(VMKind::Interpreter) : VMFactory::create(); if (m_isCreation) { - if (m_s.addressHasCode(m_newAddress)) - BOOST_THROW_EXCEPTION(AddressAlreadyUsed()); + if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("Metropolis") && m_s.addressHasCode(m_newAddress)) + BOOST_THROW_EXCEPTION(AddressAlreadyUsed()); // EIP86 + auto out = vm->exec(m_gas, *m_ext, _onOp); if (m_res) { From 6c30f3cc38b96a22b81b2c76af997ba69c73bd8a Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 16:40:00 +0200 Subject: [PATCH 14/26] properly implement CREATE_PSH --- libevm/VM.cpp | 2 ++ libevmcore/EVMSchedule.h | 2 ++ libevmcore/Instruction.cpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 75be2c06d8e..7cfebbda069 100755 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -214,6 +214,8 @@ void VM::interpretCases() CASE(CREATE_PSH) { + if (!m_schedule->haveCreatePsh) + throwBadInstruction(); m_bounce = &VM::caseCreate; } BREAK diff --git a/libevmcore/EVMSchedule.h b/libevmcore/EVMSchedule.h index 308cea4dbc3..de6cd54e8e8 100644 --- a/libevmcore/EVMSchedule.h +++ b/libevmcore/EVMSchedule.h @@ -39,6 +39,7 @@ struct EVMSchedule bool eip150Mode = false; bool eip158Mode = false; bool haveRevert = false; + bool haveCreatePsh = false; std::array tierStepGas; unsigned expGas = 10; unsigned expByteGas = 10; @@ -109,6 +110,7 @@ static const EVMSchedule MetropolisSchedule = [] { EVMSchedule schedule = EIP158Schedule; schedule.haveRevert = true; + schedule.haveCreatePsh = true; return schedule; }(); diff --git a/libevmcore/Instruction.cpp b/libevmcore/Instruction.cpp index 49d18798343..f411ef24a5d 100755 --- a/libevmcore/Instruction.cpp +++ b/libevmcore/Instruction.cpp @@ -165,6 +165,7 @@ const std::map dev::eth::c_instructions = { "LOG3", Instruction::LOG3 }, { "LOG4", Instruction::LOG4 }, { "CREATE", Instruction::CREATE }, + { "CREATE_PSH", Instruction::CREATE_PSH }, { "CALL", Instruction::CALL }, { "CALLCODE", Instruction::CALLCODE }, { "RETURN", Instruction::RETURN }, @@ -313,6 +314,7 @@ static const std::map c_instructionInfo = { Instruction::LOG3, { "LOG3", 0, 5, 0, true, Tier::Special } }, { Instruction::LOG4, { "LOG4", 0, 6, 0, true, Tier::Special } }, { Instruction::CREATE, { "CREATE", 0, 3, 1, true, Tier::Special } }, + { Instruction::CREATE_PSH, { "CREATE_PSH", 0, 3, 1, true, Tier::Special } }, { Instruction::CALL, { "CALL", 0, 7, 1, true, Tier::Special } }, { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, Tier::Special } }, { Instruction::RETURN, { "RETURN", 0, 2, 0, true, Tier::Zero } }, From ca3f062740fb16e793858fbb2afe9278a587b0d7 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 17:52:09 +0200 Subject: [PATCH 15/26] remove MetropolisFakeExtVM --- libethereum/Executive.cpp | 4 ++-- libethereum/ExtVM.cpp | 2 +- libethereum/ExtVM.h | 2 +- libevm/ExtVMFace.h | 2 +- libevm/VMCalls.cpp | 2 +- test/tools/jsontests/vm.cpp | 32 +++++++++++++------------------- test/tools/jsontests/vm.h | 10 +--------- 7 files changed, 20 insertions(+), 34 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 4d69f9da8de..970b2203117 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -336,7 +336,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g // We can allow for the reverted state (i.e. that with which m_ext is constructed) to contain the m_orig.address, since // we delete it explicitly if we decide we need to revert. - if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("Metropolis")) + if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("metropolisForkBlock")) { // EIP86 Address pushedAddress = MaxAddress; @@ -401,7 +401,7 @@ bool Executive::go(OnOpFunc const& _onOp) auto vm = _onOp ? VMFactory::create(VMKind::Interpreter) : VMFactory::create(); if (m_isCreation) { - if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("Metropolis") && m_s.addressHasCode(m_newAddress)) + if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("metropolisForkBlock") && m_s.addressHasCode(m_newAddress)) BOOST_THROW_EXCEPTION(AddressAlreadyUsed()); // EIP86 auto out = vm->exec(m_gas, *m_ext, _onOp); diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index 88a1a80572c..0d8261ead65 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -115,7 +115,7 @@ void ExtVM::setStore(u256 _n, u256 _v) m_s.setStorage(myAddress, _n, _v); } -h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp, Instruction _creationType) +h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, Instruction _creationType, OnOpFunc const& _onOp) { Executive e{m_s, envInfo(), m_sealEngine, depth + 1}; if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin, _creationType)) diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index a94c3d193ff..ebf2d03fe9c 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -65,7 +65,7 @@ class ExtVM: public ExtVMFace virtual size_t codeSizeAt(Address _a) override final; /// Create a new contract. - virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp = {}, Instruction _creationType = Instruction::CREATE) override final; + virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, Instruction _creationType, OnOpFunc const& _onOp = {}) override final; /// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller. /// @returns success flag and output data, if any. diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 2ba9393a7a0..be7cda3f76f 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -298,7 +298,7 @@ class ExtVMFace virtual void suicide(Address) { sub.suicides.insert(myAddress); } /// Create a new (contract) account. - virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&, Instruction) { return h160(); } + virtual h160 create(u256, u256&, bytesConstRef, Instruction, OnOpFunc const&) { return h160(); } /// Make a new message call. /// @returns success flag and output data, if any. diff --git a/libevm/VMCalls.cpp b/libevm/VMCalls.cpp index 96327e318f5..b05f75aab93 100755 --- a/libevm/VMCalls.cpp +++ b/libevm/VMCalls.cpp @@ -127,7 +127,7 @@ void VM::caseCreate() if (!m_schedule->staticCallDepthLimit()) createGas -= createGas / 64; u256 gas = createGas; - m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_onOp, m_OP); + m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_OP, m_onOp); *m_io_gas_p -= (createGas - gas); m_io_gas = uint64_t(*m_io_gas_p); diff --git a/test/tools/jsontests/vm.cpp b/test/tools/jsontests/vm.cpp index 94148a9bb1e..4212e6683ce 100644 --- a/test/tools/jsontests/vm.cpp +++ b/test/tools/jsontests/vm.cpp @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -37,10 +38,19 @@ FakeExtVM::FakeExtVM(EnvInfo const& _envInfo, unsigned _depth): /// TODO: XXX: ExtVMFace(_envInfo, Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), EmptySHA3, _depth) {} -h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&, Instruction _creationType) +h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, Instruction _creationType, OnOpFunc const&) { - (void)_creationType; - Address na = right160(sha3(rlpList(myAddress, get<1>(addresses[myAddress])))); + unique_ptr se(ChainParams(genesisInfo(eth::Network::MainNetworkTest)).createSealEngine()); + Address na; + if (envInfo().number() >= se->chainParams().u256Param("metropolisForkBlock")) + { + Address pushedAddress = MaxAddress; + if (_creationType == Instruction::CREATE_PSH) + pushedAddress = myAddress; + na = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes())); + } + else + na = right160(sha3(rlpList(myAddress, get<1>(addresses[myAddress])))); Transaction t(_endowment, gasPrice, io_gas, _init.toBytes()); callcreates.push_back(t); @@ -282,22 +292,6 @@ eth::OnOpFunc FakeExtVM::simpleTrace() const }; } -MetropolisFakeExtVM::MetropolisFakeExtVM(EnvInfo const& _envInfo, unsigned _depth): - FakeExtVM(_envInfo, _depth) -{} - -h160 MetropolisFakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&, Instruction _creationType) -{ - Address pushedAddress = MaxAddress; - if (_creationType == Instruction::CREATE_PSH) - pushedAddress = myAddress; - Address na = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes())); - - Transaction t(_endowment, gasPrice, io_gas, _init.toBytes()); - callcreates.push_back(t); - return na; -} - namespace dev { namespace test { void doVMTests(json_spirit::mValue& _v, bool _fillin) diff --git a/test/tools/jsontests/vm.h b/test/tools/jsontests/vm.h index 87eb6850293..ed3b254a1f9 100644 --- a/test/tools/jsontests/vm.h +++ b/test/tools/jsontests/vm.h @@ -54,7 +54,7 @@ class FakeExtVM: public eth::ExtVMFace 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 size_t codeSizeAt(Address _a) override { return std::get<3>(addresses[_a]).size(); } - virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&, eth::Instruction) override; + virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::Instruction, eth::OnOpFunc const&) override; virtual std::pair call(eth::CallParameters&) 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); @@ -80,12 +80,4 @@ class FakeExtVM: public eth::ExtVMFace u256 execGas; }; -class MetropolisFakeExtVM: public FakeExtVM -{ -public: - MetropolisFakeExtVM(eth::EnvInfo const& _envInfo, unsigned _depth = 0); - virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&, eth::Instruction) override; -}; - - } } // Namespace Close From cf0bb9016ca2c74f78cbe45cc2a67e5a06989f24 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 20 Apr 2017 10:38:05 +0200 Subject: [PATCH 16/26] fix build (evmjit) --- libevm/JitVM.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libevm/JitVM.cpp b/libevm/JitVM.cpp index 1c3c1abd437..136152ce3d3 100644 --- a/libevm/JitVM.cpp +++ b/libevm/JitVM.cpp @@ -1,6 +1,7 @@ #include "JitVM.h" #include +#include #include #include @@ -179,7 +180,7 @@ int64_t evm_call( { assert(_outputSize == 20); u256 gas = _gas; - auto addr = env.create(value, gas, input, {}); + auto addr = env.create(value, gas, input, Instruction::CREATE, {}); auto gasLeft = static_cast(gas); if (addr) std::memcpy(_outputData, addr.data(), 20); From 98b2371d162d178b11e3fd464b7d9e78222a5fa3 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 18 Apr 2017 17:26:08 +0200 Subject: [PATCH 17/26] change create tx --- libethereum/Executive.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index fa37a4bce5b..9084213e772 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -318,7 +318,11 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g // We can allow for the reverted state (i.e. that with which m_ext is constructed) to contain the m_orig.address, since // we delete it explicitly if we decide we need to revert. - m_newAddress = right160(sha3(rlpList(_sender, nonce))); + if (m_envInfo.number() < m_sealEngine.chainParams().u256Param("Metropolis")) + m_newAddress = right160(sha3(rlpList(_sender, nonce))); + else + m_newAddress = right160(sha3(MaxAddress.asBytes() + sha3(_init).asBytes())); + m_gas = _gas; // Transfer ether before deploying the code. This will also create new From 9931b85d2e6eaa444aeb6c6d7880d4e32ff59229 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 13:36:43 +0200 Subject: [PATCH 18/26] eip86_create --- ethvm/main.cpp | 2 +- libethereum/Executive.cpp | 15 ++++++++++----- libethereum/Executive.h | 2 +- libethereum/ExtVM.cpp | 4 ++-- libethereum/ExtVM.h | 2 +- libevm/ExtVMFace.h | 2 +- libevm/VM.cpp | 6 ++++++ libevm/VM.h | 2 +- libevm/VMCalls.cpp | 3 ++- libevmcore/Instruction.h | 3 ++- test/tools/jsontests/vm.cpp | 3 ++- test/tools/jsontests/vm.h | 2 +- 12 files changed, 30 insertions(+), 16 deletions(-) diff --git a/ethvm/main.cpp b/ethvm/main.cpp index 2086262bc56..b2d0087030b 100755 --- a/ethvm/main.cpp +++ b/ethvm/main.cpp @@ -299,7 +299,7 @@ int main(int argc, char** argv) if (!code.empty()) executive.call(contractDestination, sender, value, gasPrice, &data, gas); else - executive.create(sender, value, gasPrice, gas, &data, origin); + executive.create(sender, value, gasPrice, gas, &data, origin, Instruction::CREATE); Timer timer; if ((mode == Mode::Statistics || mode == Mode::Trace) && vmKind == VMKind::Interpreter) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 9084213e772..62ea0aad6fb 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -233,7 +233,7 @@ bool Executive::execute() m_s.subBalance(m_t.sender(), m_gasCost); if (m_t.isCreation()) - return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)m_baseGasRequired, &m_t.data(), m_t.sender()); + return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)m_baseGasRequired, &m_t.data(), m_t.sender(), Instruction::CREATE); else return call(m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)m_baseGasRequired); } @@ -306,7 +306,7 @@ bool Executive::call(CallParameters const& _p, u256 const& _gasPrice, Address co return !m_ext; } -bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin) +bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin, Instruction _creationType) { u256 nonce = m_s.getNonce(_sender); if (_sender != MaxAddress) // EIP86 @@ -318,10 +318,15 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g // We can allow for the reverted state (i.e. that with which m_ext is constructed) to contain the m_orig.address, since // we delete it explicitly if we decide we need to revert. - if (m_envInfo.number() < m_sealEngine.chainParams().u256Param("Metropolis")) - m_newAddress = right160(sha3(rlpList(_sender, nonce))); + if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("Metropolis")) + { + Address pushedAddress = MaxAddress; + if (_creationType == Instruction::CREATE_PSH) + pushedAddress = _sender; + m_newAddress = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes())); + } else - m_newAddress = right160(sha3(MaxAddress.asBytes() + sha3(_init).asBytes())); + m_newAddress = right160(sha3(rlpList(_sender, nonce))); m_gas = _gas; diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 64c946d81a2..9b756b0938b 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -150,7 +150,7 @@ class Executive /// Set up the executive for evaluating a bare CREATE (contract-creation) operation. /// @returns false iff go() must be called (and thus a VM execution in required). - bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress); + bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress, Instruction _creationType); /// Set up the executive for evaluating a bare CALL (message call) operation. /// @returns false iff go() must be called (and thus a VM execution in required). bool call(Address _receiveAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas); diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index df10f350c98..88a1a80572c 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -115,10 +115,10 @@ void ExtVM::setStore(u256 _n, u256 _v) m_s.setStorage(myAddress, _n, _v); } -h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp) +h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp, Instruction _creationType) { Executive e{m_s, envInfo(), m_sealEngine, depth + 1}; - if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin)) + if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin, _creationType)) { go(depth, e, _onOp); e.accrueSubState(sub); diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index dadcf453607..a94c3d193ff 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -65,7 +65,7 @@ class ExtVM: public ExtVMFace virtual size_t codeSizeAt(Address _a) override final; /// Create a new contract. - virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp = {}) override final; + virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp = {}, Instruction _creationType = Instruction::CREATE) override final; /// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller. /// @returns success flag and output data, if any. diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 57c06467997..5f98786b259 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -274,7 +274,7 @@ class ExtVMFace virtual void suicide(Address) { sub.suicides.insert(myAddress); } /// Create a new (contract) account. - virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&) { return h160(); } + virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&, Instruction) { return h160(); } /// Make a new message call. /// @returns success flag and output data, if any. diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 856b8ec7162..75be2c06d8e 100755 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -211,6 +211,12 @@ void VM::interpretCases() // // Call-related instructions // + + CASE(CREATE_PSH) + { + m_bounce = &VM::caseCreate; + } + BREAK CASE(CREATE) { diff --git a/libevm/VM.h b/libevm/VM.h index 3adb958d06d..ddf76f77489 100755 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -88,7 +88,7 @@ class VM: public VMFace void copyCode(int); const void* const* c_jumpTable = 0; bool m_caseInit = false; - + typedef void (VM::*MemFnPtr)(); MemFnPtr m_bounce = 0; MemFnPtr m_onFail = 0; diff --git a/libevm/VMCalls.cpp b/libevm/VMCalls.cpp index ae4578ca835..96327e318f5 100755 --- a/libevm/VMCalls.cpp +++ b/libevm/VMCalls.cpp @@ -127,7 +127,8 @@ void VM::caseCreate() if (!m_schedule->staticCallDepthLimit()) createGas -= createGas / 64; u256 gas = createGas; - m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_onOp); + m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_onOp, m_OP); + *m_io_gas_p -= (createGas - gas); m_io_gas = uint64_t(*m_io_gas_p); } diff --git a/libevmcore/Instruction.h b/libevmcore/Instruction.h index 34660beab17..c93f4cfb42b 100755 --- a/libevmcore/Instruction.h +++ b/libevmcore/Instruction.h @@ -183,11 +183,12 @@ enum class Instruction: uint8_t JUMPCI, ///< conditionally alter the program counter - pre-verified BAD, ///< placed to force invalid instruction exception - CREATE = 0xf0, ///< create a new account with associated code + CREATE = 0xf0, ///< create a new account with associated code. (since EIP86: sha3((MaxAddress + sha3(code)) CALL, ///< message-call into an account CALLCODE, ///< message-call with another account's code only RETURN, ///< halt execution returning output data DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender + CREATE_PSH = 0xfb, ///< create a new account with associated code. sha3((sender + sha3(code)) REVERT = 0xfd, ///< stop execution and revert state changes, without consuming all provided gas SUICIDE = 0xff ///< halt execution and register account for later deletion }; diff --git a/test/tools/jsontests/vm.cpp b/test/tools/jsontests/vm.cpp index 2702d8db57e..aa5023ea940 100644 --- a/test/tools/jsontests/vm.cpp +++ b/test/tools/jsontests/vm.cpp @@ -37,8 +37,9 @@ FakeExtVM::FakeExtVM(EnvInfo const& _envInfo, unsigned _depth): /// TODO: XXX: ExtVMFace(_envInfo, Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), EmptySHA3, _depth) {} -h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&) +h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&, Instruction _creationType) { + (void)_creationType; Address na = right160(sha3(rlpList(myAddress, get<1>(addresses[myAddress])))); Transaction t(_endowment, gasPrice, io_gas, _init.toBytes()); diff --git a/test/tools/jsontests/vm.h b/test/tools/jsontests/vm.h index f1a2a60112f..6e38cf98375 100644 --- a/test/tools/jsontests/vm.h +++ b/test/tools/jsontests/vm.h @@ -54,7 +54,7 @@ class FakeExtVM: public eth::ExtVMFace 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 size_t codeSizeAt(Address _a) override { return std::get<3>(addresses[_a]).size(); } - virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&) override; + virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&, eth::Instruction) override; virtual std::pair call(eth::CallParameters&) 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); From 8eeeaced63df38500dbfb5407ac516cfa3309a44 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 14:21:52 +0200 Subject: [PATCH 19/26] thrown if address already used --- libethcore/Exceptions.h | 1 + libethereum/Executive.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h index 060731b8cb8..0f6ec6e538d 100644 --- a/libethcore/Exceptions.h +++ b/libethcore/Exceptions.h @@ -77,6 +77,7 @@ DEV_SIMPLE_EXCEPTION(InvalidNumber); DEV_SIMPLE_EXCEPTION(InvalidZeroSignatureTransaction); DEV_SIMPLE_EXCEPTION(BlockNotFound); DEV_SIMPLE_EXCEPTION(UnknownParent); +DEV_SIMPLE_EXCEPTION(AddressAlreadyUsed); DEV_SIMPLE_EXCEPTION(DatabaseAlreadyOpen); DEV_SIMPLE_EXCEPTION(DAGCreationFailure); diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 62ea0aad6fb..8b3ea6e6ace 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -382,6 +382,8 @@ bool Executive::go(OnOpFunc const& _onOp) auto vm = _onOp ? VMFactory::create(VMKind::Interpreter) : VMFactory::create(); if (m_isCreation) { + if (m_s.addressHasCode(m_newAddress)) + BOOST_THROW_EXCEPTION(AddressAlreadyUsed()); auto out = vm->exec(m_gas, *m_ext, _onOp); if (m_res) { From 22bae65868c09060474539cad1aa6b19f2ffba40 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 15:22:57 +0200 Subject: [PATCH 20/26] MetropolisFakeExtVM --- test/tools/jsontests/vm.cpp | 17 +++++++++++++++++ test/tools/jsontests/vm.h | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/test/tools/jsontests/vm.cpp b/test/tools/jsontests/vm.cpp index aa5023ea940..53e218f6403 100644 --- a/test/tools/jsontests/vm.cpp +++ b/test/tools/jsontests/vm.cpp @@ -282,6 +282,23 @@ eth::OnOpFunc FakeExtVM::simpleTrace() const }; } +MetropolisFakeExtVM::MetropolisFakeExtVM(EnvInfo const& _envInfo, unsigned _depth): + FakeExtVM(_envInfo, _depth) +{} + +h160 MetropolisFakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&, Instruction _creationType) +{ + (void)_creationType; + Address pushedAddress = MaxAddress; + if (_creationType == Instruction::CREATE_PSH) + pushedAddress = myAddress; + Address na = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes())); + + Transaction t(_endowment, gasPrice, io_gas, _init.toBytes()); + callcreates.push_back(t); + return na; +} + namespace dev { namespace test { void doVMTests(json_spirit::mValue& _v, bool _fillin) diff --git a/test/tools/jsontests/vm.h b/test/tools/jsontests/vm.h index 6e38cf98375..87eb6850293 100644 --- a/test/tools/jsontests/vm.h +++ b/test/tools/jsontests/vm.h @@ -80,5 +80,12 @@ class FakeExtVM: public eth::ExtVMFace u256 execGas; }; +class MetropolisFakeExtVM: public FakeExtVM +{ +public: + MetropolisFakeExtVM(eth::EnvInfo const& _envInfo, unsigned _depth = 0); + virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&, eth::Instruction) override; +}; + } } // Namespace Close From 406e4fdaf2766771dcb0c808050f88aafe7724a6 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 15:54:14 +0200 Subject: [PATCH 21/26] remove (void)var --- test/tools/jsontests/vm.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/tools/jsontests/vm.cpp b/test/tools/jsontests/vm.cpp index 53e218f6403..828392528d5 100644 --- a/test/tools/jsontests/vm.cpp +++ b/test/tools/jsontests/vm.cpp @@ -288,7 +288,6 @@ MetropolisFakeExtVM::MetropolisFakeExtVM(EnvInfo const& _envInfo, unsigned _dept h160 MetropolisFakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&, Instruction _creationType) { - (void)_creationType; Address pushedAddress = MaxAddress; if (_creationType == Instruction::CREATE_PSH) pushedAddress = myAddress; From 1fa7213140ae5eb14c47d6d8df9ec163d4ff444a Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 15:56:53 +0200 Subject: [PATCH 22/26] check already used address only if after metropolis --- libethereum/Executive.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 8b3ea6e6ace..380c5af9b65 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -320,6 +320,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g // we delete it explicitly if we decide we need to revert. if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("Metropolis")) { + // EIP86 Address pushedAddress = MaxAddress; if (_creationType == Instruction::CREATE_PSH) pushedAddress = _sender; @@ -382,8 +383,9 @@ bool Executive::go(OnOpFunc const& _onOp) auto vm = _onOp ? VMFactory::create(VMKind::Interpreter) : VMFactory::create(); if (m_isCreation) { - if (m_s.addressHasCode(m_newAddress)) - BOOST_THROW_EXCEPTION(AddressAlreadyUsed()); + if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("Metropolis") && m_s.addressHasCode(m_newAddress)) + BOOST_THROW_EXCEPTION(AddressAlreadyUsed()); // EIP86 + auto out = vm->exec(m_gas, *m_ext, _onOp); if (m_res) { From ffc5996c7c109e371b25203afdec4c451d533ec2 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 16:40:00 +0200 Subject: [PATCH 23/26] properly implement CREATE_PSH --- libevm/VM.cpp | 2 ++ libevmcore/EVMSchedule.h | 2 ++ libevmcore/Instruction.cpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 75be2c06d8e..7cfebbda069 100755 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -214,6 +214,8 @@ void VM::interpretCases() CASE(CREATE_PSH) { + if (!m_schedule->haveCreatePsh) + throwBadInstruction(); m_bounce = &VM::caseCreate; } BREAK diff --git a/libevmcore/EVMSchedule.h b/libevmcore/EVMSchedule.h index 308cea4dbc3..de6cd54e8e8 100644 --- a/libevmcore/EVMSchedule.h +++ b/libevmcore/EVMSchedule.h @@ -39,6 +39,7 @@ struct EVMSchedule bool eip150Mode = false; bool eip158Mode = false; bool haveRevert = false; + bool haveCreatePsh = false; std::array tierStepGas; unsigned expGas = 10; unsigned expByteGas = 10; @@ -109,6 +110,7 @@ static const EVMSchedule MetropolisSchedule = [] { EVMSchedule schedule = EIP158Schedule; schedule.haveRevert = true; + schedule.haveCreatePsh = true; return schedule; }(); diff --git a/libevmcore/Instruction.cpp b/libevmcore/Instruction.cpp index 49d18798343..f411ef24a5d 100755 --- a/libevmcore/Instruction.cpp +++ b/libevmcore/Instruction.cpp @@ -165,6 +165,7 @@ const std::map dev::eth::c_instructions = { "LOG3", Instruction::LOG3 }, { "LOG4", Instruction::LOG4 }, { "CREATE", Instruction::CREATE }, + { "CREATE_PSH", Instruction::CREATE_PSH }, { "CALL", Instruction::CALL }, { "CALLCODE", Instruction::CALLCODE }, { "RETURN", Instruction::RETURN }, @@ -313,6 +314,7 @@ static const std::map c_instructionInfo = { Instruction::LOG3, { "LOG3", 0, 5, 0, true, Tier::Special } }, { Instruction::LOG4, { "LOG4", 0, 6, 0, true, Tier::Special } }, { Instruction::CREATE, { "CREATE", 0, 3, 1, true, Tier::Special } }, + { Instruction::CREATE_PSH, { "CREATE_PSH", 0, 3, 1, true, Tier::Special } }, { Instruction::CALL, { "CALL", 0, 7, 1, true, Tier::Special } }, { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, Tier::Special } }, { Instruction::RETURN, { "RETURN", 0, 2, 0, true, Tier::Zero } }, From 4b2f69ac4f6935241fc097f2b600e0f65006714c Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 19 Apr 2017 17:52:09 +0200 Subject: [PATCH 24/26] remove MetropolisFakeExtVM --- libethereum/Executive.cpp | 4 ++-- libethereum/ExtVM.cpp | 2 +- libethereum/ExtVM.h | 2 +- libevm/ExtVMFace.h | 2 +- libevm/VMCalls.cpp | 2 +- test/tools/jsontests/vm.cpp | 32 +++++++++++++------------------- test/tools/jsontests/vm.h | 10 +--------- 7 files changed, 20 insertions(+), 34 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 380c5af9b65..691ec6919d2 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -318,7 +318,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g // We can allow for the reverted state (i.e. that with which m_ext is constructed) to contain the m_orig.address, since // we delete it explicitly if we decide we need to revert. - if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("Metropolis")) + if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("metropolisForkBlock")) { // EIP86 Address pushedAddress = MaxAddress; @@ -383,7 +383,7 @@ bool Executive::go(OnOpFunc const& _onOp) auto vm = _onOp ? VMFactory::create(VMKind::Interpreter) : VMFactory::create(); if (m_isCreation) { - if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("Metropolis") && m_s.addressHasCode(m_newAddress)) + if (m_envInfo.number() >= m_sealEngine.chainParams().u256Param("metropolisForkBlock") && m_s.addressHasCode(m_newAddress)) BOOST_THROW_EXCEPTION(AddressAlreadyUsed()); // EIP86 auto out = vm->exec(m_gas, *m_ext, _onOp); diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index 88a1a80572c..0d8261ead65 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -115,7 +115,7 @@ void ExtVM::setStore(u256 _n, u256 _v) m_s.setStorage(myAddress, _n, _v); } -h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp, Instruction _creationType) +h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, Instruction _creationType, OnOpFunc const& _onOp) { Executive e{m_s, envInfo(), m_sealEngine, depth + 1}; if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin, _creationType)) diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index a94c3d193ff..ebf2d03fe9c 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -65,7 +65,7 @@ class ExtVM: public ExtVMFace virtual size_t codeSizeAt(Address _a) override final; /// Create a new contract. - virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp = {}, Instruction _creationType = Instruction::CREATE) override final; + virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, Instruction _creationType, OnOpFunc const& _onOp = {}) override final; /// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller. /// @returns success flag and output data, if any. diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 5f98786b259..0340f51a65f 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -274,7 +274,7 @@ class ExtVMFace virtual void suicide(Address) { sub.suicides.insert(myAddress); } /// Create a new (contract) account. - virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&, Instruction) { return h160(); } + virtual h160 create(u256, u256&, bytesConstRef, Instruction, OnOpFunc const&) { return h160(); } /// Make a new message call. /// @returns success flag and output data, if any. diff --git a/libevm/VMCalls.cpp b/libevm/VMCalls.cpp index 96327e318f5..b05f75aab93 100755 --- a/libevm/VMCalls.cpp +++ b/libevm/VMCalls.cpp @@ -127,7 +127,7 @@ void VM::caseCreate() if (!m_schedule->staticCallDepthLimit()) createGas -= createGas / 64; u256 gas = createGas; - m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_onOp, m_OP); + m_SPP[0] = (u160)m_ext->create(endowment, gas, bytesConstRef(m_mem.data() + initOff, initSize), m_OP, m_onOp); *m_io_gas_p -= (createGas - gas); m_io_gas = uint64_t(*m_io_gas_p); diff --git a/test/tools/jsontests/vm.cpp b/test/tools/jsontests/vm.cpp index 828392528d5..f8eaaae44be 100644 --- a/test/tools/jsontests/vm.cpp +++ b/test/tools/jsontests/vm.cpp @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -37,10 +38,19 @@ FakeExtVM::FakeExtVM(EnvInfo const& _envInfo, unsigned _depth): /// TODO: XXX: ExtVMFace(_envInfo, Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), EmptySHA3, _depth) {} -h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&, Instruction _creationType) +h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, Instruction _creationType, OnOpFunc const&) { - (void)_creationType; - Address na = right160(sha3(rlpList(myAddress, get<1>(addresses[myAddress])))); + unique_ptr se(ChainParams(genesisInfo(eth::Network::MainNetworkTest)).createSealEngine()); + Address na; + if (envInfo().number() >= se->chainParams().u256Param("metropolisForkBlock")) + { + Address pushedAddress = MaxAddress; + if (_creationType == Instruction::CREATE_PSH) + pushedAddress = myAddress; + na = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes())); + } + else + na = right160(sha3(rlpList(myAddress, get<1>(addresses[myAddress])))); Transaction t(_endowment, gasPrice, io_gas, _init.toBytes()); callcreates.push_back(t); @@ -282,22 +292,6 @@ eth::OnOpFunc FakeExtVM::simpleTrace() const }; } -MetropolisFakeExtVM::MetropolisFakeExtVM(EnvInfo const& _envInfo, unsigned _depth): - FakeExtVM(_envInfo, _depth) -{} - -h160 MetropolisFakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpFunc const&, Instruction _creationType) -{ - Address pushedAddress = MaxAddress; - if (_creationType == Instruction::CREATE_PSH) - pushedAddress = myAddress; - Address na = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes())); - - Transaction t(_endowment, gasPrice, io_gas, _init.toBytes()); - callcreates.push_back(t); - return na; -} - namespace dev { namespace test { void doVMTests(json_spirit::mValue& _v, bool _fillin) diff --git a/test/tools/jsontests/vm.h b/test/tools/jsontests/vm.h index 87eb6850293..ed3b254a1f9 100644 --- a/test/tools/jsontests/vm.h +++ b/test/tools/jsontests/vm.h @@ -54,7 +54,7 @@ class FakeExtVM: public eth::ExtVMFace 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 size_t codeSizeAt(Address _a) override { return std::get<3>(addresses[_a]).size(); } - virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&, eth::Instruction) override; + virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::Instruction, eth::OnOpFunc const&) override; virtual std::pair call(eth::CallParameters&) 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); @@ -80,12 +80,4 @@ class FakeExtVM: public eth::ExtVMFace u256 execGas; }; -class MetropolisFakeExtVM: public FakeExtVM -{ -public: - MetropolisFakeExtVM(eth::EnvInfo const& _envInfo, unsigned _depth = 0); - virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&, eth::Instruction) override; -}; - - } } // Namespace Close From 99768e29ac711bf9a4f6fdadb0e8dcfe0479b680 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 20 Apr 2017 10:38:05 +0200 Subject: [PATCH 25/26] fix build (evmjit) --- libevm/JitVM.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libevm/JitVM.cpp b/libevm/JitVM.cpp index 48de9fdce57..1010bf6c9ae 100644 --- a/libevm/JitVM.cpp +++ b/libevm/JitVM.cpp @@ -1,6 +1,7 @@ #include "JitVM.h" #include +#include #include #include @@ -180,7 +181,7 @@ int64_t evm_call( { assert(_outputSize == 20); u256 gas = _gas; - auto addr = env.create(value, gas, input, {}); + auto addr = env.create(value, gas, input, Instruction::CREATE, {}); auto gasLeft = static_cast(gas); if (addr) std::memcpy(_outputData, addr.data(), 20); From a0b8dbe41fc5b749a23d187fe4a53534c0338490 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 21 Apr 2017 10:34:31 +0200 Subject: [PATCH 26/26] rename CREATE_PSH => CREATE_P2SH --- libethereum/Executive.cpp | 2 +- libevm/VM.cpp | 2 +- libevmcore/Instruction.cpp | 4 ++-- libevmcore/Instruction.h | 2 +- test/tools/jsontests/vm.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 691ec6919d2..510f512d3f0 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -322,7 +322,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g { // EIP86 Address pushedAddress = MaxAddress; - if (_creationType == Instruction::CREATE_PSH) + if (_creationType == Instruction::CREATE_P2SH) pushedAddress = _sender; m_newAddress = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes())); } diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 7cfebbda069..a5d22b07a9b 100755 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -212,7 +212,7 @@ void VM::interpretCases() // Call-related instructions // - CASE(CREATE_PSH) + CASE(CREATE_P2SH) { if (!m_schedule->haveCreatePsh) throwBadInstruction(); diff --git a/libevmcore/Instruction.cpp b/libevmcore/Instruction.cpp index f411ef24a5d..0d7ebce2ecc 100755 --- a/libevmcore/Instruction.cpp +++ b/libevmcore/Instruction.cpp @@ -165,7 +165,7 @@ const std::map dev::eth::c_instructions = { "LOG3", Instruction::LOG3 }, { "LOG4", Instruction::LOG4 }, { "CREATE", Instruction::CREATE }, - { "CREATE_PSH", Instruction::CREATE_PSH }, + { "CREATE_P2SH", Instruction::CREATE_P2SH }, { "CALL", Instruction::CALL }, { "CALLCODE", Instruction::CALLCODE }, { "RETURN", Instruction::RETURN }, @@ -314,7 +314,7 @@ static const std::map c_instructionInfo = { Instruction::LOG3, { "LOG3", 0, 5, 0, true, Tier::Special } }, { Instruction::LOG4, { "LOG4", 0, 6, 0, true, Tier::Special } }, { Instruction::CREATE, { "CREATE", 0, 3, 1, true, Tier::Special } }, - { Instruction::CREATE_PSH, { "CREATE_PSH", 0, 3, 1, true, Tier::Special } }, + { Instruction::CREATE_P2SH, { "CREATE_P2SH", 0, 3, 1, true, Tier::Special } }, { Instruction::CALL, { "CALL", 0, 7, 1, true, Tier::Special } }, { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, Tier::Special } }, { Instruction::RETURN, { "RETURN", 0, 2, 0, true, Tier::Zero } }, diff --git a/libevmcore/Instruction.h b/libevmcore/Instruction.h index c93f4cfb42b..509fc214163 100755 --- a/libevmcore/Instruction.h +++ b/libevmcore/Instruction.h @@ -188,7 +188,7 @@ enum class Instruction: uint8_t CALLCODE, ///< message-call with another account's code only RETURN, ///< halt execution returning output data DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender - CREATE_PSH = 0xfb, ///< create a new account with associated code. sha3((sender + sha3(code)) + CREATE_P2SH = 0xfb, ///< create a new account with associated code. sha3((sender + sha3(code)) REVERT = 0xfd, ///< stop execution and revert state changes, without consuming all provided gas SUICIDE = 0xff ///< halt execution and register account for later deletion }; diff --git a/test/tools/jsontests/vm.cpp b/test/tools/jsontests/vm.cpp index f8eaaae44be..f3a2a8c08cd 100644 --- a/test/tools/jsontests/vm.cpp +++ b/test/tools/jsontests/vm.cpp @@ -45,7 +45,7 @@ h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, Instr if (envInfo().number() >= se->chainParams().u256Param("metropolisForkBlock")) { Address pushedAddress = MaxAddress; - if (_creationType == Instruction::CREATE_PSH) + if (_creationType == Instruction::CREATE_P2SH) pushedAddress = myAddress; na = right160(sha3(pushedAddress.asBytes() + sha3(_init).asBytes())); }