-
Notifications
You must be signed in to change notification settings - Fork 331
EIP-7873: EOF - TXCREATE and InitcodeTransaction type #1139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -172,6 +172,7 @@ class ExecutionState | |
|
|
||
| private: | ||
| evmc_tx_context m_tx = {}; | ||
| std::optional<std::unordered_map<evmc::bytes32, bytes_view>> m_initcodes; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will it fly if we omit
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is optimization to avoid calling So it will work without optional, but for no initcodes it will check |
||
|
|
||
| public: | ||
| /// Pointer to code analysis. | ||
|
|
@@ -214,6 +215,7 @@ class ExecutionState | |
| output_size = 0; | ||
| deploy_container = {}; | ||
| m_tx = {}; | ||
| m_initcodes.reset(); | ||
| call_stack = {}; | ||
| } | ||
|
|
||
|
|
@@ -225,5 +227,25 @@ class ExecutionState | |
| m_tx = host.get_tx_context(); | ||
| return m_tx; | ||
| } | ||
|
|
||
| /// Get initcode by its hash from transaction initcodes. | ||
| /// | ||
| /// Returns empty bytes_view if no such initcode was found. | ||
| [[nodiscard]] bytes_view get_tx_initcode_by_hash(const evmc_bytes32& hash) noexcept | ||
| { | ||
| if (!m_initcodes.has_value()) | ||
| { | ||
| m_initcodes.emplace(); | ||
| const auto& tx_context = get_tx_context(); | ||
| for (size_t i = 0; i < tx_context.initcodes_count; ++i) | ||
| { | ||
| const auto& initcode = tx_context.initcodes[i]; | ||
| m_initcodes->insert({initcode.hash, {initcode.code, initcode.code_size}}); | ||
| } | ||
| } | ||
|
|
||
| const auto it = m_initcodes->find(hash); | ||
| return it != m_initcodes->end() ? it->second : bytes_view{}; | ||
| } | ||
| }; | ||
| } // namespace evmone | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,6 +66,7 @@ consteval evmc_call_kind to_call_kind(Opcode op) noexcept | |
| case OP_CREATE2: | ||
| return EVMC_CREATE2; | ||
| case OP_EOFCREATE: | ||
| case OP_TXCREATE: | ||
| return EVMC_EOFCREATE; | ||
| default: | ||
| intx::unreachable(); | ||
|
|
@@ -381,12 +382,17 @@ Result create_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noex | |
| return {EVMC_SUCCESS, gas_left}; | ||
| } | ||
|
|
||
| Result eofcreate( | ||
| template <Opcode Op> | ||
| Result create_eof_impl( | ||
| StackTop stack, int64_t gas_left, ExecutionState& state, code_iterator& pos) noexcept | ||
| { | ||
| static_assert(Op == OP_EOFCREATE || Op == OP_TXCREATE); | ||
|
|
||
| if (state.in_static_mode()) | ||
| return {EVMC_STATIC_MODE_VIOLATION, gas_left}; | ||
|
|
||
| const auto initcode_hash = | ||
| (Op == OP_TXCREATE) ? intx::be::store<evmc::bytes32>(stack.pop()) : evmc::bytes32{}; | ||
| const auto salt = stack.pop(); | ||
| const auto input_offset_u256 = stack.pop(); | ||
| const auto input_size_u256 = stack.pop(); | ||
|
|
@@ -398,11 +404,24 @@ Result eofcreate( | |
| if (!check_memory(gas_left, state.memory, input_offset_u256, input_size_u256)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is weird that memory check happens after we push 0 to the stack. Please check this.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's the same as what CREATE* is doing (stack is not observable after OOG) |
||
| return {EVMC_OUT_OF_GAS, gas_left}; | ||
|
|
||
| const auto initcontainer_index = pos[1]; | ||
| pos += 2; | ||
| const auto& container = state.original_code; | ||
| const auto& eof_header = state.analysis.baseline->eof_header(); | ||
| const auto initcontainer = eof_header.get_container(container, initcontainer_index); | ||
| bytes_view initcontainer; | ||
| if constexpr (Op == OP_EOFCREATE) | ||
| { | ||
| const auto initcontainer_index = pos[1]; | ||
| pos += 2; | ||
| const auto& container = state.original_code; | ||
| const auto& eof_header = state.analysis.baseline->eof_header(); | ||
| initcontainer = eof_header.get_container(container, initcontainer_index); | ||
| } | ||
| else | ||
| { | ||
| pos += 1; | ||
| initcontainer = state.get_tx_initcode_by_hash(initcode_hash); | ||
| // In case initcode was not found, empty bytes_view was returned. | ||
| // Transaction initcodes are not allowed to be empty. | ||
| if (initcontainer.empty()) | ||
| return {EVMC_SUCCESS, gas_left}; // "Light" failure | ||
| } | ||
|
|
||
| const auto input_offset = static_cast<size_t>(input_offset_u256); | ||
| const auto input_size = static_cast<size_t>(input_size_u256); | ||
|
|
@@ -414,7 +433,14 @@ Result eofcreate( | |
| intx::be::load<uint256>(state.host.get_balance(state.msg->recipient)) < endowment) | ||
| return {EVMC_SUCCESS, gas_left}; // "Light" failure. | ||
|
|
||
| evmc_message msg{.kind = EVMC_EOFCREATE}; | ||
| if constexpr (Op == OP_TXCREATE) | ||
| { | ||
| const auto error_subcont = validate_eof(state.rev, ContainerKind::initcode, initcontainer); | ||
| if (error_subcont != EOFValidationError::success) | ||
| return {EVMC_SUCCESS, gas_left}; // "Light" failure. | ||
| } | ||
|
|
||
| evmc_message msg{.kind = to_call_kind(Op)}; | ||
| msg.gas = gas_left - gas_left / 64; | ||
| if (input_size > 0) | ||
| { | ||
|
|
@@ -446,4 +472,8 @@ template Result create_impl<OP_CREATE>( | |
| StackTop stack, int64_t gas_left, ExecutionState& state) noexcept; | ||
| template Result create_impl<OP_CREATE2>( | ||
| StackTop stack, int64_t gas_left, ExecutionState& state) noexcept; | ||
| template Result create_eof_impl<OP_EOFCREATE>( | ||
| StackTop stack, int64_t gas_left, ExecutionState& state, code_iterator& pos) noexcept; | ||
| template Result create_eof_impl<OP_TXCREATE>( | ||
| StackTop stack, int64_t gas_left, ExecutionState& state, code_iterator& pos) noexcept; | ||
| } // namespace evmone::instr::core | ||
Uh oh!
There was an error while loading. Please reload this page.