From 4071304fb69cadc1e1f2b72eda8f5f76fbac332a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 22 Feb 2024 18:04:07 +0100 Subject: [PATCH] evm: apply state diff from evmone APIv2 if enabled Implement handling of evmone's StateDiff and apply it to the IntraBlockState after each transaction if evmone APIv2 is abled in ExecutionProcessor. Also enable evmone APIv2 in direct unit tests for ExecutionProcessor. --- silkworm/core/execution/execution_test.cpp | 2 +- silkworm/core/execution/processor.cpp | 25 ++++++++++++++++++++++ silkworm/core/execution/processor_test.cpp | 10 ++++----- silkworm/core/state/intra_block_state.hpp | 1 + 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/silkworm/core/execution/execution_test.cpp b/silkworm/core/execution/execution_test.cpp index 5d8abda898..638f7a5559 100644 --- a/silkworm/core/execution/execution_test.cpp +++ b/silkworm/core/execution/execution_test.cpp @@ -165,7 +165,7 @@ TEST_CASE("Execute block with tracing") { std::vector receipts; const auto rule_set{protocol::rule_set_factory(chain_config)}; REQUIRE(rule_set); - ExecutionProcessor processor{block, *rule_set, state, chain_config, false}; + ExecutionProcessor processor{block, *rule_set, state, chain_config, true}; BlockTracer block_tracer{}; processor.evm().add_tracer(block_tracer); diff --git a/silkworm/core/execution/processor.cpp b/silkworm/core/execution/processor.cpp index 4b69d45d89..168c5c5445 100644 --- a/silkworm/core/execution/processor.cpp +++ b/silkworm/core/execution/processor.cpp @@ -180,6 +180,31 @@ void ExecutionProcessor::execute_transaction(const Transaction& txn, Receipt& re receipt.logs.emplace_back(Log{addr, std::move(topics), std::move(data)}); receipt.bloom = logs_bloom(receipt.logs); + if (evm1_v2_) { + // Apply the state diff produced by evmone APIv2 to the state and skip the Silkworm execution. + const auto& state_diff = evm1_receipt.state_diff; + for (const auto& m : state_diff.modified_accounts) { + if (!m.code.empty()) { + state_.create_contract(m.addr); + state_.set_code(m.addr, m.code); + } + + auto& acc = state_.get_or_create_object(m.addr); + acc.current->nonce = m.nonce; + acc.current->balance = m.balance; + + auto& storage = state_.storage_[m.addr]; + for (const auto& [k, v] : m.modified_storage) { + storage.committed[k].original = v; + } + } + + for (const auto& a : state_diff.deleted_accounts) { + state_.destruct(a); + } + return; + } + state_.clear_journal_and_substate(); const std::optional sender{txn.sender()}; diff --git a/silkworm/core/execution/processor_test.cpp b/silkworm/core/execution/processor_test.cpp index dee0a19ae2..6d7929adb1 100644 --- a/silkworm/core/execution/processor_test.cpp +++ b/silkworm/core/execution/processor_test.cpp @@ -45,7 +45,7 @@ TEST_CASE("Zero gas price") { InMemoryState state; auto rule_set{protocol::rule_set_factory(kMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, false}; + ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, true}; Receipt receipt; processor.execute_transaction(txn, receipt); @@ -85,7 +85,7 @@ TEST_CASE("No refund on error") { InMemoryState state; auto rule_set{protocol::rule_set_factory(kMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, false}; + ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, true}; Transaction txn{}; txn.nonce = nonce; @@ -179,7 +179,7 @@ TEST_CASE("Self-destruct") { InMemoryState state; auto rule_set{protocol::rule_set_factory(kMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, false}; + ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, true}; processor.evm().state().add_to_balance(originator, kEther); processor.evm().state().set_code(caller_address, caller_code); @@ -327,7 +327,7 @@ TEST_CASE("Out of Gas during account re-creation") { txn.set_sender(caller); auto rule_set{protocol::rule_set_factory(kMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, false}; + ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, true}; processor.evm().state().add_to_balance(caller, kEther); Receipt receipt; @@ -370,7 +370,7 @@ TEST_CASE("Empty suicide beneficiary") { InMemoryState state; auto rule_set{protocol::rule_set_factory(kMainnetConfig)}; - ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, false}; + ExecutionProcessor processor{block, *rule_set, state, kMainnetConfig, true}; processor.evm().state().add_to_balance(caller, kEther); Receipt receipt; diff --git a/silkworm/core/state/intra_block_state.hpp b/silkworm/core/state/intra_block_state.hpp index 8d4fd80cec..c413fba86a 100644 --- a/silkworm/core/state/intra_block_state.hpp +++ b/silkworm/core/state/intra_block_state.hpp @@ -133,6 +133,7 @@ class IntraBlockState { friend class state::AccountAccessDelta; friend class state::TransientStorageChangeDelta; friend class StateView; + friend class ExecutionProcessor; evmc::bytes32 get_storage(const evmc::address& address, const evmc::bytes32& key, bool original) const noexcept;