From 3c2f23c5f26cbd728b22df7164cfbdb766cd7b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 7 Apr 2021 10:50:56 +0200 Subject: [PATCH 1/7] Update EVMC to version with EIP-2929 --- evmc | 2 +- test/utils/utils.hpp | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/evmc b/evmc index 649c66176e..7a772a6856 160000 --- a/evmc +++ b/evmc @@ -1 +1 @@ -Subproject commit 649c66176ef5aa886441447c4bfee11600d8a512 +Subproject commit 7a772a6856b8b2d2b19ebf462d34dca5f7699476 diff --git a/test/utils/utils.hpp b/test/utils/utils.hpp index 8cfb3d65e4..62016fb05b 100644 --- a/test/utils/utils.hpp +++ b/test/utils/utils.hpp @@ -6,21 +6,10 @@ #include using evmc::bytes; +using evmc::from_hex; using evmc::hex; using bytes_view = std::basic_string_view; -/// Decodes hex encoded string to bytes. -inline bytes from_hex(std::string_view hex) -{ - return evmc::from_hex(std::string{hex}); -} - -/// Encodes bytes as hex string. -inline std::string hex(bytes_view bs) -{ - return evmc::hex(bs.data(), bs.size()); -} - /// Decodes the hexx encoded string. /// /// The hexx encoding format is the hex format (base 16) with the extension From 09bcf241f6ac8d30b3ebe00e2189f40f2108344a Mon Sep 17 00:00:00 2001 From: yperbasis Date: Fri, 12 Feb 2021 16:06:18 +0100 Subject: [PATCH 2/7] Implement EIP-2929 changes to SLOAD and SSTORE --- .gitmodules | 3 +- lib/evmone/baseline.cpp | 9 +++++- lib/evmone/instruction_traits.hpp | 6 +++- lib/evmone/instructions.hpp | 50 +++++++++++++++++++++---------- 4 files changed, 49 insertions(+), 19 deletions(-) diff --git a/.gitmodules b/.gitmodules index c55742f157..f8057f74ca 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "evmc"] path = evmc - url = https://github.com/ethereum/evmc + url = https://github.com/torquem-ch/evmc + branch = eip-2929 diff --git a/lib/evmone/baseline.cpp b/lib/evmone/baseline.cpp index d17396f6a4..e1b7150ea9 100644 --- a/lib/evmone/baseline.cpp +++ b/lib/evmone/baseline.cpp @@ -381,8 +381,15 @@ evmc_result baseline_execute(ExecutionState& state) noexcept msize(state); break; case OP_SLOAD: - sload(state); + { + const auto status_code = sload(state); + if (status_code != EVMC_SUCCESS) + { + state.status = status_code; + goto exit; + } break; + } case OP_SSTORE: { const auto status_code = sstore(state); diff --git a/lib/evmone/instruction_traits.hpp b/lib/evmone/instruction_traits.hpp index fced3e7f2a..18befb116b 100644 --- a/lib/evmone/instruction_traits.hpp +++ b/lib/evmone/instruction_traits.hpp @@ -333,5 +333,9 @@ constexpr inline std::array gas_costs = []() noexce }(); template <> -constexpr inline auto gas_costs = gas_costs; +constexpr inline std::array gas_costs = []() noexcept { + auto table = gas_costs; + table[OP_SLOAD] = 100; // EIP-2929 WARM_STORAGE_READ_COST + return table; +}(); } // namespace evmone::instr diff --git a/lib/evmone/instructions.hpp b/lib/evmone/instructions.hpp index f09ebfb826..d428c3134e 100644 --- a/lib/evmone/instructions.hpp +++ b/lib/evmone/instructions.hpp @@ -561,11 +561,22 @@ inline evmc_status_code mstore8(ExecutionState& state) noexcept return EVMC_SUCCESS; } -inline void sload(ExecutionState& state) noexcept +inline evmc_status_code sload(ExecutionState& state) noexcept { auto& x = state.stack.top(); - x = intx::be::load( - state.host.get_storage(state.msg->destination, intx::be::store(x))); + const auto key = intx::be::store(x); + + if (state.rev >= EVMC_BERLIN && + state.host.access_storage(state.msg->destination, key) == EVMC_ACCESS_COLD) + { + // EIP-2929: COLD_SLOAD_COST - WARM_STORAGE_READ_COST = 2000 + if ((state.gas_left -= 2000) < 0) + return EVMC_OUT_OF_GAS; + } + + x = intx::be::load(state.host.get_storage(state.msg->destination, key)); + + return EVMC_SUCCESS; } inline evmc_status_code sstore(ExecutionState& state) noexcept @@ -578,12 +589,26 @@ inline evmc_status_code sstore(ExecutionState& state) noexcept const auto key = intx::be::store(state.stack.pop()); const auto value = intx::be::store(state.stack.pop()); - const auto status = state.host.set_storage(state.msg->destination, key, value); + + // EIP-2929 + static constexpr int COLD_SLOAD_COST = 2100; + static constexpr int WARM_STORAGE_READ_COST = 100; int cost = 0; + if (state.rev >= EVMC_BERLIN && + state.host.access_storage(state.msg->destination, key) == EVMC_ACCESS_COLD) + { + cost = COLD_SLOAD_COST; + } + + const auto status = state.host.set_storage(state.msg->destination, key, value); + switch (status) { case EVMC_STORAGE_UNCHANGED: - if (state.rev >= EVMC_ISTANBUL) + case EVMC_STORAGE_MODIFIED_AGAIN: + if (state.rev >= EVMC_BERLIN) + cost += WARM_STORAGE_READ_COST; + else if (state.rev == EVMC_ISTANBUL) cost = 800; else if (state.rev == EVMC_CONSTANTINOPLE) cost = 200; @@ -591,21 +616,14 @@ inline evmc_status_code sstore(ExecutionState& state) noexcept cost = 5000; break; case EVMC_STORAGE_MODIFIED: - cost = 5000; - break; - case EVMC_STORAGE_MODIFIED_AGAIN: - if (state.rev >= EVMC_ISTANBUL) - cost = 800; - else if (state.rev == EVMC_CONSTANTINOPLE) - cost = 200; + case EVMC_STORAGE_DELETED: + if (state.rev >= EVMC_BERLIN) + cost += 5000 - COLD_SLOAD_COST; else cost = 5000; break; case EVMC_STORAGE_ADDED: - cost = 20000; - break; - case EVMC_STORAGE_DELETED: - cost = 5000; + cost += 20000; break; } if ((state.gas_left -= cost) < 0) From b931546bc3381d0e459b12af500bc38d12eef709 Mon Sep 17 00:00:00 2001 From: yperbasis Date: Sat, 13 Feb 2021 16:27:53 +0100 Subject: [PATCH 3/7] Set instruction costs for Berlin / EIP-2929 --- lib/evmone/instruction_traits.hpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/evmone/instruction_traits.hpp b/lib/evmone/instruction_traits.hpp index 18befb116b..c3114ebfe2 100644 --- a/lib/evmone/instruction_traits.hpp +++ b/lib/evmone/instruction_traits.hpp @@ -335,7 +335,19 @@ constexpr inline std::array gas_costs = []() noexce template <> constexpr inline std::array gas_costs = []() noexcept { auto table = gas_costs; - table[OP_SLOAD] = 100; // EIP-2929 WARM_STORAGE_READ_COST + + // EIP-2929 WARM_STORAGE_READ_COST + table[OP_EXTCODESIZE] = 100; + table[OP_EXTCODECOPY] = 100; + table[OP_EXTCODEHASH] = 100; + table[OP_BALANCE] = 100; + table[OP_CALL] = 100; + table[OP_CALLCODE] = 100; + table[OP_DELEGATECALL] = 100; + table[OP_STATICCALL] = 100; + table[OP_SLOAD] = 100; + return table; }(); + } // namespace evmone::instr From defdf04db49d589ce129e210abec7baf2859f1bd Mon Sep 17 00:00:00 2001 From: yperbasis Date: Sun, 14 Feb 2021 16:39:35 +0100 Subject: [PATCH 4/7] EIP-2929 for EXT* & BALANCE instructions --- lib/evmone/baseline.cpp | 28 ++++++++++++++++++--- lib/evmone/instructions.cpp | 2 +- lib/evmone/instructions.hpp | 50 ++++++++++++++++++++++++++++++++----- 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/lib/evmone/baseline.cpp b/lib/evmone/baseline.cpp index e1b7150ea9..db8a72cdbb 100644 --- a/lib/evmone/baseline.cpp +++ b/lib/evmone/baseline.cpp @@ -226,8 +226,15 @@ evmc_result baseline_execute(ExecutionState& state) noexcept address(state); break; case OP_BALANCE: - balance(state); + { + const auto status_code = balance(state); + if (status_code != EVMC_SUCCESS) + { + state.status = status_code; + goto exit; + } break; + } case OP_ORIGIN: origin(state); break; @@ -270,8 +277,15 @@ evmc_result baseline_execute(ExecutionState& state) noexcept gasprice(state); break; case OP_EXTCODESIZE: - extcodesize(state); + { + const auto status_code = extcodesize(state); + if (status_code != EVMC_SUCCESS) + { + state.status = status_code; + goto exit; + } break; + } case OP_EXTCODECOPY: { const auto status_code = extcodecopy(state); @@ -296,9 +310,15 @@ evmc_result baseline_execute(ExecutionState& state) noexcept break; } case OP_EXTCODEHASH: - extcodehash(state); + { + const auto status_code = extcodehash(state); + if (status_code != EVMC_SUCCESS) + { + state.status = status_code; + goto exit; + } break; - + } case OP_BLOCKHASH: blockhash(state); break; diff --git a/lib/evmone/instructions.cpp b/lib/evmone/instructions.cpp index eb32d70904..4ef41e0d03 100644 --- a/lib/evmone/instructions.cpp +++ b/lib/evmone/instructions.cpp @@ -316,7 +316,7 @@ constexpr std::array instruction_implementations = []( table[OP_SHL] = op; table[OP_SHR] = op; table[OP_SAR] = op; - table[OP_EXTCODEHASH] = op; + table[OP_CREATE2] = op_create; table[OP_CHAINID] = op; diff --git a/lib/evmone/instructions.hpp b/lib/evmone/instructions.hpp index d428c3134e..cf2d301799 100644 --- a/lib/evmone/instructions.hpp +++ b/lib/evmone/instructions.hpp @@ -279,10 +279,20 @@ inline void address(ExecutionState& state) noexcept state.stack.push(intx::be::load(state.msg->destination)); } -inline void balance(ExecutionState& state) noexcept +inline evmc_status_code balance(ExecutionState& state) noexcept { auto& x = state.stack.top(); - x = intx::be::load(state.host.get_balance(intx::be::trunc(x))); + const auto addr = intx::be::trunc(x); + + if (state.rev >= EVMC_BERLIN && state.host.access_account(addr) == EVMC_ACCESS_COLD) + { + // EIP-2929: COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST = 2500 + if ((state.gas_left -= 2500) < 0) + return EVMC_OUT_OF_GAS; + } + + x = intx::be::load(state.host.get_balance(addr)); + return EVMC_SUCCESS; } inline void origin(ExecutionState& state) noexcept @@ -394,10 +404,21 @@ inline void gasprice(ExecutionState& state) noexcept state.stack.push(intx::be::load(state.host.get_tx_context().tx_gas_price)); } -inline void extcodesize(ExecutionState& state) noexcept +inline evmc_status_code extcodesize(ExecutionState& state) noexcept { auto& x = state.stack.top(); - x = state.host.get_code_size(intx::be::trunc(x)); + const auto addr = intx::be::trunc(x); + + if (state.rev >= EVMC_BERLIN && state.host.access_account(addr) == EVMC_ACCESS_COLD) + { + // EIP-2929: COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST = 2500 + if ((state.gas_left -= 2500) < 0) + return EVMC_OUT_OF_GAS; + } + + x = state.host.get_code_size(addr); + + return EVMC_SUCCESS; } inline evmc_status_code extcodecopy(ExecutionState& state) noexcept @@ -418,6 +439,13 @@ inline evmc_status_code extcodecopy(ExecutionState& state) noexcept if ((state.gas_left -= copy_cost) < 0) return EVMC_OUT_OF_GAS; + if (state.rev >= EVMC_BERLIN && state.host.access_account(addr) == EVMC_ACCESS_COLD) + { + // EIP-2929: COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST = 2500 + if ((state.gas_left -= 2500) < 0) + return EVMC_OUT_OF_GAS; + } + auto data = s != 0 ? &state.memory[dst] : nullptr; auto num_bytes_copied = state.host.copy_code(addr, src, data, s); if (s - num_bytes_copied > 0) @@ -460,10 +488,20 @@ inline evmc_status_code returndatacopy(ExecutionState& state) noexcept return EVMC_SUCCESS; } -inline void extcodehash(ExecutionState& state) noexcept +inline evmc_status_code extcodehash(ExecutionState& state) noexcept { auto& x = state.stack.top(); - x = intx::be::load(state.host.get_code_hash(intx::be::trunc(x))); + const auto addr = intx::be::trunc(x); + + if (state.rev >= EVMC_BERLIN && state.host.access_account(addr) == EVMC_ACCESS_COLD) + { + // EIP-2929: COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST = 2500 + if ((state.gas_left -= 2500) < 0) + return EVMC_OUT_OF_GAS; + } + + x = intx::be::load(state.host.get_code_hash(addr)); + return EVMC_SUCCESS; } From 6e22dd6dd0a8dcce7a0e07b31b0646059636d4aa Mon Sep 17 00:00:00 2001 From: yperbasis Date: Sun, 14 Feb 2021 16:52:43 +0100 Subject: [PATCH 5/7] EIP-2929 for CALL* instructions --- lib/evmone/instructions_calls.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/evmone/instructions_calls.cpp b/lib/evmone/instructions_calls.cpp index fb9ac49e4e..5f90d95370 100644 --- a/lib/evmone/instructions_calls.cpp +++ b/lib/evmone/instructions_calls.cpp @@ -20,6 +20,13 @@ evmc_status_code call(ExecutionState& state) noexcept state.stack.push(0); // Assume failure. + if (state.rev >= EVMC_BERLIN && state.host.access_account(dst) == EVMC_ACCESS_COLD) + { + // EIP-2929: COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST = 2500 + if ((state.gas_left -= 2500) < 0) + return EVMC_OUT_OF_GAS; + } + if (!check_memory(state, input_offset, input_size)) return EVMC_OUT_OF_GAS; From 81ee11c2a274b296989242cd34fe9da6a60b2bee Mon Sep 17 00:00:00 2001 From: yperbasis Date: Mon, 15 Feb 2021 11:44:13 +0100 Subject: [PATCH 6/7] EIP-2929 SELFDESTRUCT --- lib/evmone/instructions.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/evmone/instructions.hpp b/lib/evmone/instructions.hpp index cf2d301799..94cc2f7f86 100644 --- a/lib/evmone/instructions.hpp +++ b/lib/evmone/instructions.hpp @@ -736,6 +736,13 @@ inline evmc_status_code selfdestruct(ExecutionState& state) noexcept const auto beneficiary = intx::be::trunc(state.stack[0]); + if (state.rev >= EVMC_BERLIN && state.host.access_account(beneficiary) == EVMC_ACCESS_COLD) + { + // EIP-2929: COLD_ACCOUNT_ACCESS_COST = 2600 + if ((state.gas_left -= 2600) < 0) + return EVMC_OUT_OF_GAS; + } + if (state.rev >= EVMC_TANGERINE_WHISTLE) { if (state.rev == EVMC_TANGERINE_WHISTLE || state.host.get_balance(state.msg->destination)) From fbe900e8e7e035b3238b3e27df17585a181a409b Mon Sep 17 00:00:00 2001 From: yperbasis Date: Thu, 11 Mar 2021 10:46:35 +0100 Subject: [PATCH 7/7] ci: Upgrade Silkworm and Ethereum tests (8.0.2) --- circle.yml | 38 +++++--------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/circle.yml b/circle.yml index 75a0936899..7a799027f2 100644 --- a/circle.yml +++ b/circle.yml @@ -19,7 +19,7 @@ commands: steps: - restore_cache: name: "Restore Silkworm cache" - key: &silkworm-cache-key silkworm-v1 + key: &silkworm-cache-key silkworm-20210407 - run: name: "Check Silkworm cache" command: | @@ -38,11 +38,11 @@ commands: working_directory: ~/silkworm/src command: | [ "$SILKWORM_BUILD" = true ] || exit 0 - git clone --no-checkout --single-branch https://github.com/torquem-ch/silkworm.git . - git checkout 614fabfcf19b8e06f0dcbe3e9af2345dcf748f3e + git clone --no-checkout --single-branch --branch eip2929_update https://github.com/torquem-ch/silkworm.git . + git checkout b083086cd4692b2a7f54af06644324a833fb4d3e git submodule init git submodule deinit tests - git submodule update --recursive --depth=1 --progress + git submodule update --init --recursive --depth=1 --progress - run: name: "Configure Silkworm" working_directory: ~/silkworm @@ -239,41 +239,16 @@ jobs: ghr -u $CIRCLE_PROJECT_USERNAME -r $CIRCLE_PROJECT_REPONAME -n "$name" $prerelease_flag $CIRCLE_TAG ~/package consensus-tests: - environment: - TESTS_REV: v7.0.0 executor: linux-gcc-latest steps: - build_silkworm - unpack_package - download_consensus_tests: - rev: v7.0.0 + rev: 8.0.2 - run: name: "Silkworm-driven consensus tests" command: ~/silkworm/consensus --evm ~/package/lib/libevmone.so --tests ~/tests - state-tests: - environment: - TESTS_REV: ac8cf2cd8ba326d67101183060272e7f7b1eaa92 - ALETH_REV: 1.8.0 - docker: - - image: cimg/base:stable - steps: - - unpack_package - - run: - name: "Download Aleth" - background: true - command: curl -L https://github.com/ethereum/aleth/releases/download/v$ALETH_REV/aleth-$ALETH_REV-linux-x86_64.tar.gz | tar xz - - download_consensus_tests: - rev: ac8cf2cd8ba326d67101183060272e7f7b1eaa92 - - run: - name: "Fixup consensus tests" - command: | - mkdir -p ~/tests/GeneralStateTests/stEWASMTests - mkdir -p ~/tests/src/GeneralStateTestsFiller/stEWASMTests - - run: - name: "Run State Tests" - command: bin/testeth -t GeneralStateTests -- --testpath ~/tests --vm ~/package/lib/libevmone.so - gcc-min: executor: linux-gcc-7 @@ -382,9 +357,6 @@ workflows: - consensus-tests: requires: - release-linux - - state-tests: - requires: - - release-linux - gcc-min - gcc-latest-coverage - clang-latest-ubsan