diff --git a/.github/workflows/rpc-integration-tests.yml b/.github/workflows/rpc-integration-tests.yml index ee058fe8f5..a862daa34d 100644 --- a/.github/workflows/rpc-integration-tests.yml +++ b/.github/workflows/rpc-integration-tests.yml @@ -34,9 +34,9 @@ jobs: run: | rm -rf ${{runner.workspace}}/rpc-tests if [ ${{ matrix.backend }} == 'Erigon2' ]; then - git -c advice.detachedHead=false clone --depth 1 --branch v0.52.0 https://github.com/erigontech/rpc-tests ${{runner.workspace}}/rpc-tests + git -c advice.detachedHead=false clone --depth 1 --branch v0.54.0 https://github.com/erigontech/rpc-tests ${{runner.workspace}}/rpc-tests else - git -c advice.detachedHead=false clone --depth 1 --branch v0.52.0 https://github.com/erigontech/rpc-tests ${{runner.workspace}}/rpc-tests + git -c advice.detachedHead=false clone --depth 1 --branch v0.54.0 https://github.com/erigontech/rpc-tests ${{runner.workspace}}/rpc-tests fi cd ${{runner.workspace}}/rpc-tests pip3 install -r requirements.txt diff --git a/silkworm/rpc/common/util.cpp b/silkworm/rpc/common/util.cpp index 315700f7f1..41619d23e8 100644 --- a/silkworm/rpc/common/util.cpp +++ b/silkworm/rpc/common/util.cpp @@ -147,14 +147,15 @@ std::string get_opcode_hex(uint8_t opcode) { return {'0', 'x', kHexDigits[opcode >> 4], kHexDigits[opcode & 0xf]}; } -std::string get_opcode_name(const char* const* names, std::uint8_t opcode) { +std::optional get_opcode_name(const char* const* names, std::uint8_t opcode) { SILKWORM_ASSERT(names != nullptr); + std::optional op_name; const auto name = names[opcode]; if (name != nullptr) { - return name; + op_name = name; } - return "opcode " + get_opcode_hex(opcode) + " not defined"; + return op_name; } } // namespace silkworm diff --git a/silkworm/rpc/common/util.hpp b/silkworm/rpc/common/util.hpp index 22e427039d..a55ae51cf2 100644 --- a/silkworm/rpc/common/util.hpp +++ b/silkworm/rpc/common/util.hpp @@ -56,7 +56,7 @@ inline evmc::bytes32 bytes32_from_hex(const std::string& s) { std::ostream& operator<<(std::ostream& out, const Account& account); std::string get_opcode_hex(uint8_t opcode); -std::string get_opcode_name(const char* const* names, std::uint8_t opcode); +std::optional get_opcode_name(const char* const* names, std::uint8_t opcode); } // namespace silkworm inline auto hash_of(const silkworm::ByteView& bytes) { diff --git a/silkworm/rpc/common/util_test.cpp b/silkworm/rpc/common/util_test.cpp index 80496fec64..8cd393e03b 100644 --- a/silkworm/rpc/common/util_test.cpp +++ b/silkworm/rpc/common/util_test.cpp @@ -257,7 +257,7 @@ TEST_CASE("get_opcode_name") { } SECTION("not existent op_code") { auto op_code_name = get_opcode_name(names, 0x0d); - CHECK(op_code_name == "opcode 0xd not defined"); + CHECK(!op_code_name.has_value()); } } diff --git a/silkworm/rpc/core/evm_debug.cpp b/silkworm/rpc/core/evm_debug.cpp index 52e73480f4..9a649ca09b 100644 --- a/silkworm/rpc/core/evm_debug.cpp +++ b/silkworm/rpc/core/evm_debug.cpp @@ -21,7 +21,6 @@ #include #include -#include #include #include @@ -105,6 +104,7 @@ void insert_error(DebugLog& log, evmc_status_code status_code) { void DebugTracer::on_execution_start(evmc_revision rev, const evmc_message& msg, evmone::bytes_view code) noexcept { last_opcode_ = std::nullopt; if (opcode_names_ == nullptr) { + latest_opcode_names_ = evmc_get_instruction_names_table(EVMC_LATEST_STABLE_REVISION); opcode_names_ = evmc_get_instruction_names_table(rev); metrics_ = evmc_get_instruction_metrics_table(rev); } @@ -133,13 +133,16 @@ void DebugTracer::on_instruction_start(uint32_t pc, const intx::uint256* stack_t const evmc::address sender(execution_state.msg->sender); const auto opcode = execution_state.original_code[pc]; - const auto opcode_name = get_opcode_name(opcode_names_, opcode); + auto opcode_name = get_opcode_name(opcode_names_, opcode); + if (!opcode_name) { + opcode_name = get_opcode_name(latest_opcode_names_, opcode); + } last_opcode_ = opcode; SILK_DEBUG << "on_instruction_start:" << " pc: " << std::dec << pc << " opcode: 0x" << std::hex << evmc::hex(opcode) - << " opcode_name: " << opcode_name + << " opcode_name: " << opcode_name.value_or("UNDEFINED") << " recipient: " << recipient << " sender: " << sender << " execution_state: {" @@ -167,7 +170,7 @@ void DebugTracer::on_instruction_start(uint32_t pc, const intx::uint256* stack_t if (!logs_.empty()) { auto& log = logs_[logs_.size() - 1]; - if (log.opcode == OP_RETURN || log.opcode == OP_STOP || log.opcode == OP_REVERT) { + if (log.op_code == OP_RETURN || log.op_code == OP_STOP || log.op_code == OP_REVERT) { log.gas_cost = 0; } else if (log.depth == execution_state.msg->depth + 1) { log.gas_cost = execution_state.last_opcode_gas_cost; @@ -182,8 +185,8 @@ void DebugTracer::on_instruction_start(uint32_t pc, const intx::uint256* stack_t DebugLog log; log.pc = pc; - log.opcode = opcode; - log.op = opcode_name; + log.op_code = opcode; + log.op_name = opcode_name; log.gas = gas; log.gas_cost = metrics_[opcode].gas_cost; log.depth = execution_state.msg->depth + 1; @@ -226,17 +229,21 @@ void DebugTracer::on_execution_end(const evmc_result& result, const silkworm::In case evmc_status_code::EVMC_INVALID_INSTRUCTION: case evmc_status_code::EVMC_STACK_OVERFLOW: case evmc_status_code::EVMC_STACK_UNDERFLOW: - log.gas_cost = 0; + if (log.op_name) { + log.gas_cost = result.gas_cost; + } else { + log.gas_cost = 0; + } break; case evmc_status_code::EVMC_OUT_OF_GAS: - if (log.opcode != OP_CALLCODE) { + if (log.op_code != OP_CALLCODE) { log.gas_cost = result.gas_cost; } break; default: - if (log.opcode == OP_CALL || log.opcode == OP_CALLCODE || log.opcode == OP_STATICCALL || log.opcode == OP_DELEGATECALL || log.opcode == OP_CREATE || log.opcode == OP_CREATE2) { + if (log.op_code == OP_CALL || log.op_code == OP_CALLCODE || log.op_code == OP_STATICCALL || log.op_code == OP_DELEGATECALL || log.op_code == OP_CREATE || log.op_code == OP_CREATE2) { log.gas_cost += result.gas_cost; } else { log.gas_cost = log.gas_cost; @@ -248,8 +255,8 @@ void DebugTracer::on_execution_end(const evmc_result& result, const silkworm::In if (result.status_code == EVMC_SUCCESS && last_opcode_ && last_opcode_ != OP_SELFDESTRUCT && last_opcode_ != OP_RETURN && last_opcode_ != OP_STOP) { DebugLog newlog; newlog.pc = log.pc + 1; - newlog.op = get_opcode_name(opcode_names_, OP_STOP); - newlog.opcode = OP_STOP; + newlog.op_name = get_opcode_name(opcode_names_, OP_STOP); + newlog.op_code = OP_STOP; newlog.gas = log.gas - log.gas_cost; newlog.gas_cost = 0; newlog.depth = log.depth; @@ -287,7 +294,11 @@ void DebugTracer::write_log(const DebugLog& log) { stream_.write_field("depth", log.depth); stream_.write_field("gas", log.gas); stream_.write_field("gasCost", log.gas_cost); - stream_.write_field("op", log.op); + if (log.op_name) { + stream_.write_field("op", log.op_name.value()); + } else { + stream_.write_field("op", "opcode " + get_opcode_hex(log.op_code) + " not defined"); + } stream_.write_field("pc", log.pc); if (!config_.disable_stack) { diff --git a/silkworm/rpc/core/evm_debug.hpp b/silkworm/rpc/core/evm_debug.hpp index 72f8d3850d..eb5434b880 100644 --- a/silkworm/rpc/core/evm_debug.hpp +++ b/silkworm/rpc/core/evm_debug.hpp @@ -61,8 +61,8 @@ using Storage = std::map; struct DebugLog { std::uint32_t pc{0}; - unsigned char opcode{0}; - std::string op; + unsigned char op_code{0}; + std::optional op_name; std::int64_t gas{0}; std::int64_t gas_cost{0}; std::int32_t depth{0}; @@ -98,6 +98,7 @@ class DebugTracer : public EvmTracer { std::vector logs_; std::map storage_; const char* const* opcode_names_ = nullptr; + const char* const* latest_opcode_names_ = nullptr; const evmc_instruction_metrics* metrics_ = nullptr; std::optional last_opcode_; }; diff --git a/silkworm/rpc/core/evm_debug_test.cpp b/silkworm/rpc/core/evm_debug_test.cpp index da21fa257d..1c9f3e9fa9 100644 --- a/silkworm/rpc/core/evm_debug_test.cpp +++ b/silkworm/rpc/core/evm_debug_test.cpp @@ -270,10 +270,6 @@ TEST_CASE_METHOD(DebugExecutorTest, "DebugExecutor::execute call 1") { .WillRepeatedly(InvokeWithoutArgs([]() -> Task { co_return KeyValue{kAccountHistoryKey1, kAccountHistoryValue1}; })); - EXPECT_CALL(transaction, get(db::table::kAccountHistoryName, silkworm::ByteView{kAccountHistoryKey3})) - .WillOnce(InvokeWithoutArgs([]() -> Task { - co_return KeyValue{kAccountHistoryKey3, kAccountHistoryValue3}; - })); EXPECT_CALL(transaction, get(db::table::kAccountHistoryName, silkworm::ByteView{kAccountHistoryKey2})) .WillRepeatedly(InvokeWithoutArgs([]() -> Task { co_return KeyValue{kAccountHistoryKey2, kAccountHistoryValue2}; @@ -282,10 +278,6 @@ TEST_CASE_METHOD(DebugExecutorTest, "DebugExecutor::execute call 1") { .WillRepeatedly(InvokeWithoutArgs([]() -> Task { co_return Bytes{}; })); - EXPECT_CALL(transaction, get_both_range(db::table::kAccountChangeSetName, silkworm::ByteView{kAccountChangeSetKey1}, silkworm::ByteView{kAccountChangeSetSubkey1})) - .WillOnce(InvokeWithoutArgs([]() -> Task> { - co_return kAccountChangeSetValue1; - })); const auto block_number = 5'405'095; // 0x5279A7 Call call; diff --git a/silkworm/rpc/core/evm_trace.cpp b/silkworm/rpc/core/evm_trace.cpp index cf196894f6..2a9545408b 100644 --- a/silkworm/rpc/core/evm_trace.cpp +++ b/silkworm/rpc/core/evm_trace.cpp @@ -17,7 +17,6 @@ #include "evm_trace.hpp" #include -#include #include #include #include @@ -125,7 +124,11 @@ void to_json(nlohmann::json& json, const TraceOp& trace_op) { json["ex"] = *(trace_op.trace_ex); } json["idx"] = trace_op.idx; - json["op"] = trace_op.op_name; + if (trace_op.op_name) { + json["op"] = trace_op.op_name.value(); + } else { + json["op"] = "opcode " + get_opcode_hex(trace_op.op_code) + " not defined"; + } json["pc"] = trace_op.pc; if (trace_op.sub) { json["sub"] = *trace_op.sub; @@ -670,7 +673,7 @@ void VmTraceTracer::on_instruction_start(uint32_t pc, const intx::uint256* stack SILK_DEBUG << "VmTraceTracer::on_instruction_start:" << " pc: " << std::dec << pc << ", opcode: 0x" << std::hex << evmc::hex(op_code) - << ", opcode_name: " << op_name + << ", opcode_name: " << op_name.value_or("UNDEFINED") << ", index_prefix: " << index_prefix << ", execution_state: {" << " gas_left: " << std::dec << gas @@ -915,7 +918,7 @@ void TraceTracer::on_instruction_start(uint32_t pc, const intx::uint256* stack_t SILK_DEBUG << "TraceTracer::on_instruction_start:" << " pc: " << std::dec << pc << ", opcode: 0x" << std::hex << evmc::hex(opcode) - << ", opcode_name: " << opcode_name + << ", opcode_name: " << opcode_name.value_or("UNDEFINED") << ", recipient: " << evmc::address{execution_state.msg->recipient} << ", sender: " << evmc::address{execution_state.msg->sender} << ", execution_state: {" @@ -1138,7 +1141,7 @@ void StateDiffTracer::on_instruction_start(uint32_t pc, const intx::uint256* sta SILK_DEBUG << "StateDiffTracer::on_instruction_start:" << " pc: " << std::dec << pc - << ", opcode_name: " << opcode_name + << ", opcode_name: " << opcode_name.value_or("UNDEFINED") << ", recipient: " << evmc::address{execution_state.msg->recipient} << ", sender: " << evmc::address{execution_state.msg->sender} << ", execution_state: {" diff --git a/silkworm/rpc/core/evm_trace.hpp b/silkworm/rpc/core/evm_trace.hpp index 827faa937f..34db7fc739 100644 --- a/silkworm/rpc/core/evm_trace.hpp +++ b/silkworm/rpc/core/evm_trace.hpp @@ -105,7 +105,7 @@ struct TraceOp { std::string idx; int32_t depth{0}; uint8_t op_code{0}; - std::string op_name; + std::optional op_name; uint32_t pc{0}; std::shared_ptr sub; }; diff --git a/third_party/evmone/evmone b/third_party/evmone/evmone index b545b9a9b0..3298a6848f 160000 --- a/third_party/evmone/evmone +++ b/third_party/evmone/evmone @@ -1 +1 @@ -Subproject commit b545b9a9b0aa59546d78d5386fca0c89c4b07b3c +Subproject commit 3298a6848fc5e85122c67beac7a8a1c7ff4b0333