From c22c16a2be374746db5c1665dc30f5f8783610ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 20 May 2021 16:48:21 +0200 Subject: [PATCH 1/4] Rename evm_stack -> Stack --- lib/evmone/baseline.cpp | 2 +- lib/evmone/execution_state.hpp | 6 +-- lib/evmone/instructions.cpp | 4 +- lib/evmone/instructions.hpp | 54 ++++++++++++------------- test/unittests/execution_state_test.cpp | 2 +- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/lib/evmone/baseline.cpp b/lib/evmone/baseline.cpp index d5aa1a62f2..e9b5f5dcc1 100644 --- a/lib/evmone/baseline.cpp +++ b/lib/evmone/baseline.cpp @@ -90,7 +90,7 @@ inline evmc_status_code check_requirements(const char* const* instruction_names, const auto stack_size = state.stack.size(); if (stack_size < metrics.stack_height_required) return EVMC_STACK_UNDERFLOW; - if (stack_size + metrics.stack_height_change > evm_stack::limit) + if (stack_size + metrics.stack_height_change > Stack::limit) return EVMC_STACK_OVERFLOW; return EVMC_SUCCESS; diff --git a/lib/evmone/execution_state.hpp b/lib/evmone/execution_state.hpp index d2c8ebb1bd..bb5ff19ea5 100644 --- a/lib/evmone/execution_state.hpp +++ b/lib/evmone/execution_state.hpp @@ -19,7 +19,7 @@ using bytes_view = std::basic_string_view; /// /// This implementation reserves memory inplace for all possible stack items (1024), /// so this type is big. Make sure it is allocated on heap. -struct evm_stack +struct Stack { /// The maximum number of stack items. static constexpr auto limit = 1024; @@ -33,7 +33,7 @@ struct evm_stack alignas(sizeof(intx::uint256)) intx::uint256 storage[limit]; /// Default constructor. Sets the top_item pointer to below the stack bottom. - evm_stack() noexcept { clear(); } + Stack() noexcept { clear(); } /// The current number of items on the stack. [[nodiscard]] int size() const noexcept { return static_cast(top_item + 1 - storage); } @@ -88,7 +88,7 @@ class evm_memory struct ExecutionState { int64_t gas_left = 0; - evm_stack stack; + Stack stack; evm_memory memory; const evmc_message* msg = nullptr; evmc::HostContext host; diff --git a/lib/evmone/instructions.cpp b/lib/evmone/instructions.cpp index fd69fa69fa..f44539614a 100644 --- a/lib/evmone/instructions.cpp +++ b/lib/evmone/instructions.cpp @@ -10,7 +10,7 @@ namespace evmone { namespace { -template +template const instruction* op(const instruction* instr, AdvancedExecutionState& state) noexcept { InstrFn(state.stack); @@ -189,7 +189,7 @@ const instruction* opx_beginblock(const instruction* instr, AdvancedExecutionSta if (static_cast(state.stack.size()) < block.stack_req) return state.exit(EVMC_STACK_UNDERFLOW); - if (static_cast(state.stack.size()) + block.stack_max_growth > evm_stack::limit) + if (static_cast(state.stack.size()) + block.stack_max_growth > Stack::limit) return state.exit(EVMC_STACK_OVERFLOW); state.current_block_cost = block.gas_cost; diff --git a/lib/evmone/instructions.hpp b/lib/evmone/instructions.hpp index 3372d22382..3003de1bec 100644 --- a/lib/evmone/instructions.hpp +++ b/lib/evmone/instructions.hpp @@ -56,51 +56,51 @@ inline bool check_memory(ExecutionState& state, const uint256& offset, const uin return check_memory(state, offset, static_cast(size)); } -inline void add(evm_stack& stack) noexcept +inline void add(Stack& stack) noexcept { stack.top() += stack.pop(); } -inline void mul(evm_stack& stack) noexcept +inline void mul(Stack& stack) noexcept { stack.top() *= stack.pop(); } -inline void sub(evm_stack& stack) noexcept +inline void sub(Stack& stack) noexcept { stack[1] = stack[0] - stack[1]; stack.pop(); } -inline void div(evm_stack& stack) noexcept +inline void div(Stack& stack) noexcept { auto& v = stack[1]; v = v != 0 ? stack[0] / v : 0; stack.pop(); } -inline void sdiv(evm_stack& stack) noexcept +inline void sdiv(Stack& stack) noexcept { auto& v = stack[1]; v = v != 0 ? intx::sdivrem(stack[0], v).quot : 0; stack.pop(); } -inline void mod(evm_stack& stack) noexcept +inline void mod(Stack& stack) noexcept { auto& v = stack[1]; v = v != 0 ? stack[0] % v : 0; stack.pop(); } -inline void smod(evm_stack& stack) noexcept +inline void smod(Stack& stack) noexcept { auto& v = stack[1]; v = v != 0 ? intx::sdivrem(stack[0], v).rem : 0; stack.pop(); } -inline void addmod(evm_stack& stack) noexcept +inline void addmod(Stack& stack) noexcept { const auto x = stack.pop(); const auto y = stack.pop(); @@ -108,7 +108,7 @@ inline void addmod(evm_stack& stack) noexcept m = m != 0 ? intx::addmod(x, y, m) : 0; } -inline void mulmod(evm_stack& stack) noexcept +inline void mulmod(Stack& stack) noexcept { const auto x = stack.pop(); const auto y = stack.pop(); @@ -132,7 +132,7 @@ inline evmc_status_code exp(ExecutionState& state) noexcept return EVMC_SUCCESS; } -inline void signextend(evm_stack& stack) noexcept +inline void signextend(Stack& stack) noexcept { const auto ext = stack.pop(); auto& x = stack.top(); @@ -147,19 +147,19 @@ inline void signextend(evm_stack& stack) noexcept } } -inline void lt(evm_stack& stack) noexcept +inline void lt(Stack& stack) noexcept { const auto x = stack.pop(); stack[0] = x < stack[0]; } -inline void gt(evm_stack& stack) noexcept +inline void gt(Stack& stack) noexcept { const auto x = stack.pop(); stack[0] = stack[0] < x; // TODO: Using < is faster than >. } -inline void slt(evm_stack& stack) noexcept +inline void slt(Stack& stack) noexcept { // TODO: Move this to intx. const auto x = stack.pop(); @@ -169,7 +169,7 @@ inline void slt(evm_stack& stack) noexcept y = ((x_neg ^ y_neg) != 0) ? x_neg : x < y; } -inline void sgt(evm_stack& stack) noexcept +inline void sgt(Stack& stack) noexcept { const auto x = stack.pop(); auto& y = stack[0]; @@ -178,38 +178,38 @@ inline void sgt(evm_stack& stack) noexcept y = ((x_neg ^ y_neg) != 0) ? y_neg : y < x; } -inline void eq(evm_stack& stack) noexcept +inline void eq(Stack& stack) noexcept { stack[1] = stack[0] == stack[1]; stack.pop(); } -inline void iszero(evm_stack& stack) noexcept +inline void iszero(Stack& stack) noexcept { stack.top() = stack.top() == 0; } -inline void and_(evm_stack& stack) noexcept +inline void and_(Stack& stack) noexcept { stack.top() &= stack.pop(); } -inline void or_(evm_stack& stack) noexcept +inline void or_(Stack& stack) noexcept { stack.top() |= stack.pop(); } -inline void xor_(evm_stack& stack) noexcept +inline void xor_(Stack& stack) noexcept { stack.top() ^= stack.pop(); } -inline void not_(evm_stack& stack) noexcept +inline void not_(Stack& stack) noexcept { stack.top() = ~stack.top(); } -inline void byte(evm_stack& stack) noexcept +inline void byte(Stack& stack) noexcept { const auto n = stack.pop(); auto& x = stack.top(); @@ -224,17 +224,17 @@ inline void byte(evm_stack& stack) noexcept } } -inline void shl(evm_stack& stack) noexcept +inline void shl(Stack& stack) noexcept { stack.top() <<= stack.pop(); } -inline void shr(evm_stack& stack) noexcept +inline void shr(Stack& stack) noexcept { stack.top() >>= stack.pop(); } -inline void sar(evm_stack& stack) noexcept +inline void sar(Stack& stack) noexcept { if ((stack[1] & (uint256{1} << 255)) == 0) return shr(stack); @@ -554,7 +554,7 @@ inline void selfbalance(ExecutionState& state) noexcept } -inline void pop(evm_stack& stack) noexcept +inline void pop(Stack& stack) noexcept { stack.pop(); } @@ -671,7 +671,7 @@ inline void msize(ExecutionState& state) noexcept /// DUP instruction implementation. /// @tparam N The number as in the instruction definition, e.g. DUP3 is dup<3>. template -inline void dup(evm_stack& stack) noexcept +inline void dup(Stack& stack) noexcept { static_assert(N >= 1 && N <= 16); stack.push(stack[N - 1]); @@ -680,7 +680,7 @@ inline void dup(evm_stack& stack) noexcept /// SWAP instruction implementation. /// @tparam N The number as in the instruction definition, e.g. SWAP3 is swap<3>. template -inline void swap(evm_stack& stack) noexcept +inline void swap(Stack& stack) noexcept { static_assert(N >= 1 && N <= 16); std::swap(stack.top(), stack[N]); diff --git a/test/unittests/execution_state_test.cpp b/test/unittests/execution_state_test.cpp index 10f4daedac..f758f4882b 100644 --- a/test/unittests/execution_state_test.cpp +++ b/test/unittests/execution_state_test.cpp @@ -140,7 +140,7 @@ TEST(execution_state, reset_advanced) TEST(execution_state, stack_clear) { - evmone::evm_stack stack; + evmone::Stack stack; stack.clear(); EXPECT_EQ(stack.size(), 0); From 77208cb69a6bb3c16a2de7268f98000c7c749408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 20 May 2021 16:54:27 +0200 Subject: [PATCH 2/4] Allow const access to Stack elements --- lib/evmone/execution_state.hpp | 6 ++++++ test/unittests/execution_state_test.cpp | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/lib/evmone/execution_state.hpp b/lib/evmone/execution_state.hpp index bb5ff19ea5..556f606373 100644 --- a/lib/evmone/execution_state.hpp +++ b/lib/evmone/execution_state.hpp @@ -44,6 +44,12 @@ struct Stack /// Returns the reference to the stack item on given position from the stack top. [[nodiscard]] intx::uint256& operator[](int index) noexcept { return *(top_item - index); } + /// Returns the const reference to the stack item on given position from the stack top. + [[nodiscard]] const intx::uint256& operator[](int index) const noexcept + { + return *(top_item - index); + } + /// Pushes an item on the stack. The stack limit is not checked. void push(const intx::uint256& item) noexcept { *++top_item = item; } diff --git a/test/unittests/execution_state_test.cpp b/test/unittests/execution_state_test.cpp index f758f4882b..055318eab2 100644 --- a/test/unittests/execution_state_test.cpp +++ b/test/unittests/execution_state_test.cpp @@ -158,3 +158,15 @@ TEST(execution_state, stack_clear) EXPECT_EQ(stack.size(), 0); EXPECT_EQ(stack.top_item + 1, stack.storage); } + +TEST(execution_state, const_stack) +{ + evmone::Stack stack; + stack.push(1); + stack.push(2); + + const auto& cstack = stack; + + EXPECT_EQ(cstack[0], 2); + EXPECT_EQ(cstack[1], 1); +} From 826c4d1a7760eba1a1fecc2775c9b12f71ed5553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 20 May 2021 16:54:59 +0200 Subject: [PATCH 3/4] Rename evm_memory -> Memory --- lib/evmone/execution_state.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/evmone/execution_state.hpp b/lib/evmone/execution_state.hpp index 556f606373..42a407d4f2 100644 --- a/lib/evmone/execution_state.hpp +++ b/lib/evmone/execution_state.hpp @@ -68,7 +68,7 @@ struct Stack /// Also std::basic_string has been tried but not faster and we don't want SSO /// if initial_capacity is used. /// In future, transition to std::realloc() + std::free() planned. -class evm_memory +class Memory { /// The initial memory allocation. static constexpr size_t initial_capacity = 4 * 1024; @@ -76,10 +76,10 @@ class evm_memory std::vector m_memory; public: - evm_memory() noexcept { m_memory.reserve(initial_capacity); } + Memory() noexcept { m_memory.reserve(initial_capacity); } - evm_memory(const evm_memory&) = delete; - evm_memory& operator=(const evm_memory&) = delete; + Memory(const Memory&) = delete; + Memory& operator=(const Memory&) = delete; uint8_t& operator[](size_t index) noexcept { return m_memory[index]; } @@ -95,7 +95,7 @@ struct ExecutionState { int64_t gas_left = 0; Stack stack; - evm_memory memory; + Memory memory; const evmc_message* msg = nullptr; evmc::HostContext host; evmc_revision rev = {}; From 59182d1f8c24d32120214af61af88748a9fdebb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 20 May 2021 17:00:57 +0200 Subject: [PATCH 4/4] Add Memory::data() const --- lib/evmone/execution_state.hpp | 1 + test/unittests/execution_state_test.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/evmone/execution_state.hpp b/lib/evmone/execution_state.hpp index 42a407d4f2..0dbb521be5 100644 --- a/lib/evmone/execution_state.hpp +++ b/lib/evmone/execution_state.hpp @@ -83,6 +83,7 @@ class Memory uint8_t& operator[](size_t index) noexcept { return m_memory[index]; } + [[nodiscard]] const uint8_t* data() const noexcept { return m_memory.data(); } [[nodiscard]] size_t size() const noexcept { return m_memory.size(); } void resize(size_t new_size) { m_memory.resize(new_size); } diff --git a/test/unittests/execution_state_test.cpp b/test/unittests/execution_state_test.cpp index 055318eab2..68a466dddf 100644 --- a/test/unittests/execution_state_test.cpp +++ b/test/unittests/execution_state_test.cpp @@ -170,3 +170,22 @@ TEST(execution_state, const_stack) EXPECT_EQ(cstack[0], 2); EXPECT_EQ(cstack[1], 1); } + +TEST(execution_state, memory_view) +{ + evmone::Memory memory; + memory.resize(3); + + evmone::bytes_view view{memory.data(), memory.size()}; + ASSERT_EQ(view.size(), 3); + EXPECT_EQ(view[0], 0x00); + EXPECT_EQ(view[1], 0x00); + EXPECT_EQ(view[2], 0x00); + + memory[0] = 0xc0; + memory[2] = 0xc2; + ASSERT_EQ(view.size(), 3); + EXPECT_EQ(view[0], 0xc0); + EXPECT_EQ(view[1], 0x00); + EXPECT_EQ(view[2], 0xc2); +}