From 8d004c4539daf09b78cf54b9af5678c8b62c945d Mon Sep 17 00:00:00 2001 From: sl1depengwyn Date: Mon, 16 Jan 2023 21:47:32 +0500 Subject: [PATCH 01/10] Add callTracer support for geth --- .../lib/ethereum_jsonrpc/geth.ex | 68 ++++++++++++++++++- config/runtime.exs | 3 + docker-compose/envs/common-blockscout.env | 1 + docker/Makefile | 3 + 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex index 7b754a51f86b..e8c20ceb4001 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex @@ -78,12 +78,18 @@ defmodule EthereumJSONRPC.Geth do defp debug_trace_transaction_request(%{id: id, hash_data: hash_data}) do timeout = Application.get_env(:ethereum_jsonrpc, :internal_transaction_timeout) + tracer = + case Application.get_env(:ethereum_jsonrpc, __MODULE__)[:tracer] do + "js" -> @tracer + "call_tracer" -> "callTracer" + end + request(%{ id: id, method: "debug_traceTransaction", params: [ hash_data, - %{tracer: @tracer, disableStack: true, disableMemory: true, disableStorage: true, timeout: timeout} + %{tracer: tracer, disableStack: true, disableMemory: true, disableStorage: true, timeout: timeout} ] }) end @@ -177,6 +183,7 @@ defmodule EthereumJSONRPC.Geth do internal_transaction_params = calls + |> prepare_calls() |> Stream.with_index() |> Enum.map(fn {trace, index} -> Map.merge(trace, %{ @@ -223,6 +230,65 @@ defmodule EthereumJSONRPC.Geth do {:error, annotated_error} end + defp prepare_calls(calls) do + case Application.get_env(:ethereum_jsonrpc, __MODULE__)[:tracer] do + "call_tracer" -> {calls, 0} |> parse_call_tracer_calls([], [], false) |> Enum.reverse() + "js" -> calls + end + end + + defp parse_call_tracer_calls(calls, acc, trace_address, inner? \\ true) + defp parse_call_tracer_calls([], acc, _trace_address, _inner?), do: acc + defp parse_call_tracer_calls({%{"type" => 0}, _}, acc, _trace_address, _inner?), do: acc + + defp parse_call_tracer_calls( + {%{"type" => type, "from" => from} = call, index}, + acc, + trace_address, + inner? + ) do + new_trace_address = [index | trace_address] + + formatted_call = + %{ + "type" => if(type in ~w(CALL CALLCODE DELEGATECALL STATICCALL), do: "call", else: String.downcase(type)), + "callType" => String.downcase(type), + "from" => from, + "to" => Map.get(call, "to", "0x"), + "createdContractAddressHash" => Map.get(call, "to", "0x"), + "value" => Map.get(call, "value", "0x0"), + "gas" => Map.get(call, "gas", "0x0"), + "gasUsed" => Map.get(call, "gasUsed", "0x0"), + "input" => Map.get(call, "input", "0x"), + "init" => Map.get(call, "input", "0x"), + "createdContractCode" => Map.get(call, "output", "0x"), + "traceAddress" => if(inner?, do: Enum.reverse(new_trace_address), else: []), + "error" => call["error"] + } + |> case do + %{"error" => nil} = ok_call -> + ok_call + |> Map.delete("error") + # to handle staticcall, all other cases handled by EthereumJSONRPC.Geth.Call.elixir_to_internal_transaction_params/1 + |> Map.put("output", Map.get(call, "output", "0x")) + + error_call -> + error_call + end + + parse_call_tracer_calls( + Map.get(call, "calls", []), + [formatted_call | acc], + if(inner?, do: new_trace_address, else: []) + ) + end + + defp parse_call_tracer_calls(calls, acc, trace_address, _inner) when is_list(calls) do + calls + |> Stream.with_index() + |> Enum.reduce(acc, &parse_call_tracer_calls(&1, &2, trace_address)) + end + defp reduce_internal_transactions_params(internal_transactions_params) when is_list(internal_transactions_params) do internal_transactions_params |> Enum.reduce({:ok, []}, &internal_transactions_params_reducer/2) diff --git a/config/runtime.exs b/config/runtime.exs index 35ab189fd103..76d8a7394c35 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -193,6 +193,9 @@ config :ethereum_jsonrpc, debug_trace_transaction_timeout = System.get_env("ETHEREUM_JSONRPC_DEBUG_TRACE_TRANSACTION_TIMEOUT", "900s") config :ethereum_jsonrpc, :internal_transaction_timeout, debug_trace_transaction_timeout +config :ethereum_jsonrpc, EthereumJSONRPC.Geth, + tracer: System.get_env("INDEXER_INTERNAL_TRANSACTIONS_TRACER_TYPE", "call_tracer") + config :ethereum_jsonrpc, EthereumJSONRPC.PendingTransaction, type: System.get_env("ETHEREUM_JSONRPC_PENDING_TRANSACTIONS_TYPE", "default") diff --git a/docker-compose/envs/common-blockscout.env b/docker-compose/envs/common-blockscout.env index 73c936dbfa47..7f496a61b154 100644 --- a/docker-compose/envs/common-blockscout.env +++ b/docker-compose/envs/common-blockscout.env @@ -84,6 +84,7 @@ INDEXER_DISABLE_PENDING_TRANSACTIONS_FETCHER=false INDEXER_DISABLE_INTERNAL_TRANSACTIONS_FETCHER=false # INDEXER_CATCHUP_BLOCKS_BATCH_SIZE= # INDEXER_CATCHUP_BLOCKS_CONCURRENCY= +# INDEXER_INTERNAL_TRANSACTIONS_TRACER_TYPE= # INDEXER_INTERNAL_TRANSACTIONS_BATCH_SIZE= # INDEXER_INTERNAL_TRANSACTIONS_CONCURRENCY= # INDEXER_COIN_BALANCES_BATCH_SIZE= diff --git a/docker/Makefile b/docker/Makefile index 6423dd549b2e..d2d5a638dbe3 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -482,6 +482,9 @@ endif ifdef INDEXER_EMPTY_BLOCKS_SANITIZER_BATCH_SIZE BLOCKSCOUT_CONTAINER_PARAMS += -e 'INDEXER_EMPTY_BLOCKS_SANITIZER_BATCH_SIZE=$(INDEXER_EMPTY_BLOCKS_SANITIZER_BATCH_SIZE)' endif +ifdef INDEXER_INTERNAL_TRANSACTIONS_TRACER_TYPE + BLOCKSCOUT_CONTAINER_PARAMS += -e 'INDEXER_INTERNAL_TRANSACTIONS_TRACER_TYPE=$(INDEXER_INTERNAL_TRANSACTIONS_TRACER_TYPE)' +endif ifdef TOKEN_ID_MIGRATION_FIRST_BLOCK BLOCKSCOUT_CONTAINER_PARAMS += -e 'INDEXER_EMPTY_BLOCKS_SANITIZER_BATCH_SIZE=$(INDEXER_EMPTY_BLOCKS_SANITIZER_BATCH_SIZE)' endif From 9b7704768e614fa005eebd235ddf708f8813a28e Mon Sep 17 00:00:00 2001 From: sl1depengwyn Date: Mon, 16 Jan 2023 21:48:01 +0500 Subject: [PATCH 02/10] Add test for geth callTracer support --- .../test/ethereum_jsonrpc/geth_test.exs | 359 ++++++++++++++++++ 1 file changed, 359 insertions(+) diff --git a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/geth_test.exs b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/geth_test.exs index 0e38447731b0..214ed1bd6a1b 100644 --- a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/geth_test.exs +++ b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/geth_test.exs @@ -11,6 +11,8 @@ defmodule EthereumJSONRPC.GethTest do # Infura Mainnet does not support debug_traceTransaction, so this cannot be tested expect in Mox setup do EthereumJSONRPC.Case.Geth.Mox.setup() + initial_env = Application.get_all_env(:ethereum_jsonrpc) + on_exit(fn -> Application.put_all_env([{:ethereum_jsonrpc, initial_env}]) end) end setup :verify_on_exit! @@ -45,6 +47,8 @@ defmodule EthereumJSONRPC.GethTest do ]} end) + Application.put_env(:ethereum_jsonrpc, Geth, tracer: "js") + assert {:ok, [ %{ @@ -75,6 +79,361 @@ defmodule EthereumJSONRPC.GethTest do json_rpc_named_arguments ) end + + test "call_tracer contract calls results are the same as js tracer", %{ + json_rpc_named_arguments: json_rpc_named_arguments + } do + transaction_hash = "0xb342cafc6ac552c3be2090561453204c8784caf025ac8267320834e4cd163d96" + block_number = 3_287_375 + transaction_index = 13 + + transaction_params = %{ + block_number: block_number, + transaction_index: transaction_index, + hash_data: transaction_hash + } + + tracer = File.read!("priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js") + + expect(EthereumJSONRPC.Mox, :json_rpc, 1, fn + [%{id: id, params: [^transaction_hash, %{tracer: "callTracer"}]}], _ -> + {:ok, + [ + %{ + id: id, + result: %{ + "calls" => [ + %{ + "calls" => [ + %{ + "from" => "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "gas" => "0x12816", + "gasUsed" => "0x229e", + "input" => + "0xa9059cbb0000000000000000000000009507c04b10486547584c37bcbd931b2a4fee9a4100000000000000000000000000000000000000000000000322a0aedb1fe2c7e6", + "output" => "0x", + "to" => "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + "type" => "CALL", + "value" => "0x0" + }, + %{ + "calls" => [ + %{ + "from" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "gas" => "0xfbb8", + "gasUsed" => "0x211", + "input" => "0x70a0823100000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "output" => "0x", + "to" => "0xa2327a938febf5fec13bacfb16ae10ecbc4cbdcf", + "type" => "DELEGATECALL" + } + ], + "from" => "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "gas" => "0x1029c", + "gasUsed" => "0x523", + "input" => "0x70a0823100000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "output" => "0x", + "to" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "type" => "STATICCALL" + }, + %{ + "calls" => [ + %{ + "calls" => [ + %{ + "from" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "gas" => "0xe3e3", + "gasUsed" => "0x259c", + "input" => + "0xa9059cbb00000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f564000000000000000000000000000000000000000000000000000000014e53ad37c", + "output" => "0x", + "to" => "0xa2327a938febf5fec13bacfb16ae10ecbc4cbdcf", + "type" => "DELEGATECALL" + } + ], + "from" => "0x9507c04b10486547584c37bcbd931b2a4fee9a41", + "gas" => "0xea6a", + "gasUsed" => "0x28b1", + "input" => + "0xa9059cbb00000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f564000000000000000000000000000000000000000000000000000000014e53ad37c", + "output" => "0x", + "to" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "type" => "CALL", + "value" => "0x0" + } + ], + "from" => "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "gas" => "0xfa71", + "gasUsed" => "0x3627", + "input" => + "0xfa461e3300000000000000000000000000000000000000000000000000000014e53ad37cfffffffffffffffffffffffffffffffffffffffffffffffcdd5f5124e01d381a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000014e53ad37c00000000000000000000000000000000000000000000000322a0aedb1fe2c7e600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000", + "output" => "0x", + "to" => "0x9507c04b10486547584c37bcbd931b2a4fee9a41", + "type" => "CALL", + "value" => "0x0" + }, + %{ + "calls" => [ + %{ + "from" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "gas" => "0xbcc4", + "gasUsed" => "0x211", + "input" => "0x70a0823100000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "output" => "0x", + "to" => "0xa2327a938febf5fec13bacfb16ae10ecbc4cbdcf", + "type" => "DELEGATECALL" + } + ], + "from" => "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "gas" => "0xc2a9", + "gasUsed" => "0x523", + "input" => "0x70a0823100000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "output" => "0x", + "to" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "type" => "STATICCALL" + } + ], + "from" => "0x9507c04b10486547584c37bcbd931b2a4fee9a41", + "gas" => "0x185b2", + "gasUsed" => "0xd38e", + "input" => + "0x128acb080000000000000000000000009507c04b10486547584c37bcbd931b2a4fee9a410000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffcdd5f5124e01d381a00000000000000000000000000000000000000000000000000000001000276a400000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000014e53ad37c00000000000000000000000000000000000000000000000322a0aedb1fe2c7e600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000", + "output" => "0x", + "to" => "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "type" => "CALL", + "value" => "0x0" + } + ], + "from" => "0x56d0c33e5e8cb6390cebd7369d2fe7e7870a04e0", + "gas" => "0x1a8c6", + "gasUsed" => "0xf1f6", + "input" => + "0x33000000000000000014e53ad37c0000000322a0aedb1fe2c7e6010201f4ff010088e6a0c2ddd26feeb64f039a2c41296fcb3f5640a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc203", + "output" => "0x", + "time" => "48.391824ms", + "to" => "0x9507c04b10486547584c37bcbd931b2a4fee9a41", + "type" => "CALL", + "value" => "0xfa72c6" + } + } + ]} + end) + + expect(EthereumJSONRPC.Mox, :json_rpc, 1, fn + [%{id: id, params: [^transaction_hash, %{tracer: ^tracer}]}], _ -> + {:ok, + [ + %{ + id: id, + result: [ + %{ + "callType" => "call", + "from" => "0x56d0c33e5e8cb6390cebd7369d2fe7e7870a04e0", + "gas" => "0x1a8c6", + "gasUsed" => "0xf1f6", + "input" => + "0x33000000000000000014e53ad37c0000000322a0aedb1fe2c7e6010201f4ff010088e6a0c2ddd26feeb64f039a2c41296fcb3f5640a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc203", + "output" => "0x", + "to" => "0x9507c04b10486547584c37bcbd931b2a4fee9a41", + "traceAddress" => [], + "type" => "call", + "value" => "0xfa72c6" + }, + %{ + "callType" => "call", + "from" => "0x9507c04b10486547584c37bcbd931b2a4fee9a41", + "gas" => "0x185b2", + "gasUsed" => "0xd38e", + "input" => + "0x128acb080000000000000000000000009507c04b10486547584c37bcbd931b2a4fee9a410000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffcdd5f5124e01d381a00000000000000000000000000000000000000000000000000000001000276a400000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000014e53ad37c00000000000000000000000000000000000000000000000322a0aedb1fe2c7e600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000", + "output" => "0x", + "to" => "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "traceAddress" => [0], + "type" => "call", + "value" => "0x0" + }, + %{ + "callType" => "call", + "from" => "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "gas" => "0x12816", + "gasUsed" => "0x229e", + "input" => + "0xa9059cbb0000000000000000000000009507c04b10486547584c37bcbd931b2a4fee9a4100000000000000000000000000000000000000000000000322a0aedb1fe2c7e6", + "output" => "0x", + "to" => "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + "traceAddress" => [0, 0], + "type" => "call", + "value" => "0x0" + }, + %{ + "callType" => "staticcall", + "from" => "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "gas" => "0x1029c", + "gasUsed" => "0x523", + "input" => "0x70a0823100000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "output" => "0x", + "to" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "traceAddress" => [0, 1], + "type" => "call", + "value" => "0x0" + }, + %{ + "callType" => "delegatecall", + "from" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "gas" => "0xfbb8", + "gasUsed" => "0x211", + "input" => "0x70a0823100000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "output" => "0x", + "to" => "0xa2327a938febf5fec13bacfb16ae10ecbc4cbdcf", + "traceAddress" => [0, 1, 0], + "type" => "call", + "value" => "0x0" + }, + %{ + "callType" => "call", + "from" => "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "gas" => "0xfa71", + "gasUsed" => "0x3627", + "input" => + "0xfa461e3300000000000000000000000000000000000000000000000000000014e53ad37cfffffffffffffffffffffffffffffffffffffffffffffffcdd5f5124e01d381a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000014e53ad37c00000000000000000000000000000000000000000000000322a0aedb1fe2c7e600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000", + "output" => "0x", + "to" => "0x9507c04b10486547584c37bcbd931b2a4fee9a41", + "traceAddress" => [0, 2], + "type" => "call", + "value" => "0x0" + }, + %{ + "callType" => "call", + "from" => "0x9507c04b10486547584c37bcbd931b2a4fee9a41", + "gas" => "0xea6a", + "gasUsed" => "0x28b1", + "input" => + "0xa9059cbb00000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f564000000000000000000000000000000000000000000000000000000014e53ad37c", + "output" => "0x", + "to" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "traceAddress" => [0, 2, 0], + "type" => "call", + "value" => "0x0" + }, + %{ + "callType" => "delegatecall", + "from" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "gas" => "0xe3e3", + "gasUsed" => "0x259c", + "input" => + "0xa9059cbb00000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f564000000000000000000000000000000000000000000000000000000014e53ad37c", + "output" => "0x", + "to" => "0xa2327a938febf5fec13bacfb16ae10ecbc4cbdcf", + "traceAddress" => [0, 2, 0, 0], + "type" => "call", + "value" => "0x0" + }, + %{ + "callType" => "staticcall", + "from" => "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "gas" => "0xc2a9", + "gasUsed" => "0x523", + "input" => "0x70a0823100000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "output" => "0x", + "to" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "traceAddress" => [0, 3], + "type" => "call", + "value" => "0x0" + }, + %{ + "callType" => "delegatecall", + "from" => "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "gas" => "0xbcc4", + "gasUsed" => "0x211", + "input" => "0x70a0823100000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640", + "output" => "0x", + "to" => "0xa2327a938febf5fec13bacfb16ae10ecbc4cbdcf", + "traceAddress" => [0, 3, 0], + "type" => "call", + "value" => "0x0" + } + ] + } + ]} + end) + + call_tracer_internal_txs = Geth.fetch_internal_transactions([transaction_params], json_rpc_named_arguments) + + Application.put_env(:ethereum_jsonrpc, Geth, tracer: "js") + + assert call_tracer_internal_txs == + Geth.fetch_internal_transactions([transaction_params], json_rpc_named_arguments) + end + + test "call_tracer contract creation results are the same as js tracer", %{ + json_rpc_named_arguments: json_rpc_named_arguments + } do + transaction_hash = "0xb342cafc6ac552c3be2090561453204c8784caf025ac8267320834e4cd163d96" + block_number = 3_287_375 + transaction_index = 13 + + transaction_params = %{ + block_number: block_number, + transaction_index: transaction_index, + hash_data: transaction_hash + } + + tracer = File.read!("priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js") + + expect(EthereumJSONRPC.Mox, :json_rpc, 1, fn + [%{id: id, params: [^transaction_hash, %{tracer: "callTracer"}]}], _ -> + {:ok, + [ + %{ + id: id, + result: %{ + "type" => "CREATE", + "from" => "0x117b358218da5a4f647072ddb50ded038ed63d17", + "to" => "0x205a6b72ce16736c9d87172568a9c0cb9304de0d", + "value" => "0x0", + "gas" => "0x106f5", + "gasUsed" => "0x106f5", + "input" => + "0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100d9565b60405180910390f35b610073600480360381019061006e919061009d565b61007e565b005b60008054905090565b8060008190555050565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea26469706673582212209a159a4f3847890f10bfb87871a61eba91c5dbf5ee3cf6398207e292eee22a1664736f6c63430008070033", + "output" => + "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100d9565b60405180910390f35b610073600480360381019061006e919061009d565b61007e565b005b60008054905090565b8060008190555050565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea26469706673582212209a159a4f3847890f10bfb87871a61eba91c5dbf5ee3cf6398207e292eee22a1664736f6c63430008070033" + } + } + ]} + end) + + expect(EthereumJSONRPC.Mox, :json_rpc, 1, fn + [%{id: id, params: [^transaction_hash, %{tracer: ^tracer}]}], _ -> + {:ok, + [ + %{ + id: id, + result: [ + %{ + "type" => "create", + "from" => "0x117b358218da5a4f647072ddb50ded038ed63d17", + "init" => + "0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100d9565b60405180910390f35b610073600480360381019061006e919061009d565b61007e565b005b60008054905090565b8060008190555050565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea26469706673582212209a159a4f3847890f10bfb87871a61eba91c5dbf5ee3cf6398207e292eee22a1664736f6c63430008070033", + "createdContractAddressHash" => "0x205a6b72ce16736c9d87172568a9c0cb9304de0d", + "createdContractCode" => + "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100d9565b60405180910390f35b610073600480360381019061006e919061009d565b61007e565b005b60008054905090565b8060008190555050565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea26469706673582212209a159a4f3847890f10bfb87871a61eba91c5dbf5ee3cf6398207e292eee22a1664736f6c63430008070033", + "traceAddress" => [], + "value" => "0x0", + "gas" => "0x106f5", + "gasUsed" => "0x106f5" + } + ] + } + ]} + end) + + call_tracer_internal_txs = Geth.fetch_internal_transactions([transaction_params], json_rpc_named_arguments) + + Application.put_env(:ethereum_jsonrpc, Geth, tracer: "js") + + assert call_tracer_internal_txs == + Geth.fetch_internal_transactions([transaction_params], json_rpc_named_arguments) + end end describe "fetch_block_internal_transactions/1" do From 8788f74b53cbfb8f21d71cc219671c6dea75ad31 Mon Sep 17 00:00:00 2001 From: sl1depengwyn Date: Mon, 16 Jan 2023 21:57:58 +0500 Subject: [PATCH 03/10] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdb701443d4b..f379d6cbac6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## Current ### Features - +- [#6721](https://github.com/blockscout/blockscout/pull/6721) - Implement fetching internal transactions from callTracer - [#5561](https://github.com/blockscout/blockscout/pull/5561), [#6523](https://github.com/blockscout/blockscout/pull/6523) - Improve working with contracts implementations - [#6401](https://github.com/blockscout/blockscout/pull/6401) - Add Sol2Uml contract visualization - [#6481](https://github.com/blockscout/blockscout/pull/6481) - Smart contract verification improvements From f238302c2d54661dbff36d7172b6dd47fdea3d3f Mon Sep 17 00:00:00 2001 From: sl1depengwyn Date: Mon, 6 Feb 2023 20:59:46 +0300 Subject: [PATCH 04/10] Fix handling unknown calls from callTracer --- CHANGELOG.md | 2 ++ apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f379d6cbac6e..0b590f8e884a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Current ### Features + - [#6721](https://github.com/blockscout/blockscout/pull/6721) - Implement fetching internal transactions from callTracer - [#5561](https://github.com/blockscout/blockscout/pull/5561), [#6523](https://github.com/blockscout/blockscout/pull/6523) - Improve working with contracts implementations - [#6401](https://github.com/blockscout/blockscout/pull/6401) - Add Sol2Uml contract visualization @@ -29,6 +30,7 @@ ### Fixes +- [#6827](https://github.com/blockscout/blockscout/pull/6827) - Fix handling unknown calls from `callTracer` - [#6532](https://github.com/blockscout/blockscout/pull/6532) - Fix index creation migration - [#6473](https://github.com/blockscout/blockscout/pull/6473) - Fix state changes for contract creation transactions - [#6475](https://github.com/blockscout/blockscout/pull/6475) - Fix token name with unicode graphemes shortening diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex index e8c20ceb4001..599dbb32e262 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex @@ -3,6 +3,8 @@ defmodule EthereumJSONRPC.Geth do Ethereum JSONRPC methods that are only supported by [Geth](https://github.com/ethereum/go-ethereum/wiki/geth). """ + require Logger + import EthereumJSONRPC, only: [id_to_params: 1, integer_to_quantity: 1, json_rpc: 2, request: 1] alias EthereumJSONRPC.{FetchedBalance, FetchedCode, PendingTransaction} @@ -246,7 +248,8 @@ defmodule EthereumJSONRPC.Geth do acc, trace_address, inner? - ) do + ) + when type in ~w(CALL CALLCODE DELEGATECALL STATICCALL CREATE CREATE2 SELFDESTRUCT REWARD) do new_trace_address = [index | trace_address] formatted_call = @@ -283,6 +286,11 @@ defmodule EthereumJSONRPC.Geth do ) end + defp parse_call_tracer_calls({call, _}, acc, _trace_address, _inner?) do + Logger.warning("Call from a callTracer with an unknown type: #{inspect(call)}") + acc + end + defp parse_call_tracer_calls(calls, acc, trace_address, _inner) when is_list(calls) do calls |> Stream.with_index() From c8225037267038c5f9c93def5f6a628facfc628d Mon Sep 17 00:00:00 2001 From: Valentin Rodygin Date: Wed, 15 Mar 2023 13:10:54 +0100 Subject: [PATCH 05/10] Updated internal TX test to use js tracer --- .../indexer/fetcher/internal_transaction_test.exs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/indexer/test/indexer/fetcher/internal_transaction_test.exs b/apps/indexer/test/indexer/fetcher/internal_transaction_test.exs index 74c49c84c84c..2a9ab106ab72 100644 --- a/apps/indexer/test/indexer/fetcher/internal_transaction_test.exs +++ b/apps/indexer/test/indexer/fetcher/internal_transaction_test.exs @@ -9,9 +9,16 @@ defmodule Indexer.Fetcher.InternalTransactionTest do alias Explorer.Chain.{PendingBlockOperation, TokenTransfer} alias Indexer.Fetcher.{CoinBalance, InternalTransaction, PendingTransaction, TokenBalance} - # MUST use global mode because we aren't guaranteed to get PendingTransactionFetcher's pid back fast enough to `allow` - # it to use expectations and stubs from test's pid. - setup :set_mox_global + setup do + # MUST use global mode because we aren't guaranteed to get PendingTransactionFetcher's pid back fast enough to `allow` + # it to use expectations and stubs from test's pid. + set_mox_global() + + initial_env = Application.get_all_env(:ethereum_jsonrpc) + Application.put_env(:ethereum_jsonrpc, EthereumJSONRPC.Geth, tracer: "js") + + on_exit(fn -> Application.put_all_env([{:ethereum_jsonrpc, initial_env}]) end) + end setup :verify_on_exit! From 3ffbcdd9883b4a5fbb37b99d31f2957edd6f983a Mon Sep 17 00:00:00 2001 From: Donald Hutchison Date: Thu, 6 Jul 2023 11:17:20 +0200 Subject: [PATCH 06/10] Set coin balance fetcher concurrency 1. --- apps/indexer/config/prod.exs | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/indexer/config/prod.exs b/apps/indexer/config/prod.exs index f87975711d08..f646275fe4d4 100644 --- a/apps/indexer/config/prod.exs +++ b/apps/indexer/config/prod.exs @@ -1,6 +1,7 @@ import Config config :indexer, Indexer.Tracer, env: "production", disabled?: true +config :indexer, Indexer.Fetcher.CoinBalance, concurrency: 1 config :indexer, :environment, :prod From 422893ee6838bf2fa4f2f05d7df478519a4b62a0 Mon Sep 17 00:00:00 2001 From: Donald Hutchison Date: Thu, 6 Jul 2023 14:48:55 +0200 Subject: [PATCH 07/10] Tweak itx concurrency settings. --- config/runtime.exs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/runtime.exs b/config/runtime.exs index 76d8a7394c35..1ff1247096c1 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -523,10 +523,10 @@ config :indexer, Indexer.Block.Catchup.Fetcher, concurrency: blocks_catchup_fetcher_concurrency {internal_transaction_fetcher_batch_size, _} = - Integer.parse(System.get_env("INDEXER_INTERNAL_TRANSACTIONS_BATCH_SIZE", "8")) + Integer.parse(System.get_env("INDEXER_INTERNAL_TRANSACTIONS_BATCH_SIZE", "4")) {internal_transaction_fetcher_concurrency, _} = - Integer.parse(System.get_env("INDEXER_INTERNAL_TRANSACTIONS_CONCURRENCY", "8")) + Integer.parse(System.get_env("INDEXER_INTERNAL_TRANSACTIONS_CONCURRENCY", "5")) config :indexer, Indexer.Fetcher.InternalTransaction, batch_size: internal_transaction_fetcher_batch_size, @@ -534,7 +534,7 @@ config :indexer, Indexer.Fetcher.InternalTransaction, {coin_balance_fetcher_batch_size, _} = Integer.parse(System.get_env("INDEXER_COIN_BALANCES_BATCH_SIZE", "500")) -{coin_balance_fetcher_concurrency, _} = Integer.parse(System.get_env("INDEXER_COIN_BALANCES_CONCURRENCY", "4")) +{coin_balance_fetcher_concurrency, _} = Integer.parse(System.get_env("INDEXER_COIN_BALANCES_CONCURRENCY", "1")) config :indexer, Indexer.Fetcher.CoinBalance, batch_size: coin_balance_fetcher_batch_size, From de76216870869674c9eb74d101b510ed1af7e600 Mon Sep 17 00:00:00 2001 From: Donald Hutchison Date: Thu, 6 Jul 2023 14:57:24 +0200 Subject: [PATCH 08/10] ITX concurrency 4. --- config/runtime.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/runtime.exs b/config/runtime.exs index 1ff1247096c1..4a2c276ada92 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -526,7 +526,7 @@ config :indexer, Indexer.Block.Catchup.Fetcher, Integer.parse(System.get_env("INDEXER_INTERNAL_TRANSACTIONS_BATCH_SIZE", "4")) {internal_transaction_fetcher_concurrency, _} = - Integer.parse(System.get_env("INDEXER_INTERNAL_TRANSACTIONS_CONCURRENCY", "5")) + Integer.parse(System.get_env("INDEXER_INTERNAL_TRANSACTIONS_CONCURRENCY", "4")) config :indexer, Indexer.Fetcher.InternalTransaction, batch_size: internal_transaction_fetcher_batch_size, From 6b36059dae47821a3e672193fb045c0f663518ab Mon Sep 17 00:00:00 2001 From: Donald Hutchison Date: Mon, 17 Jul 2023 16:55:18 +0200 Subject: [PATCH 09/10] Set default tracer to 'js' --- config/runtime.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/runtime.exs b/config/runtime.exs index 4a2c276ada92..1a9e32c5e2f6 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -194,7 +194,7 @@ debug_trace_transaction_timeout = System.get_env("ETHEREUM_JSONRPC_DEBUG_TRACE_T config :ethereum_jsonrpc, :internal_transaction_timeout, debug_trace_transaction_timeout config :ethereum_jsonrpc, EthereumJSONRPC.Geth, - tracer: System.get_env("INDEXER_INTERNAL_TRANSACTIONS_TRACER_TYPE", "call_tracer") + tracer: System.get_env("INDEXER_INTERNAL_TRANSACTIONS_TRACER_TYPE", "js") config :ethereum_jsonrpc, EthereumJSONRPC.PendingTransaction, type: System.get_env("ETHEREUM_JSONRPC_PENDING_TRANSACTIONS_TYPE", "default") From 0e6a7247805b92fa281a98089b4dfd87ff822543 Mon Sep 17 00:00:00 2001 From: Donald Hutchison Date: Mon, 17 Jul 2023 17:41:13 +0200 Subject: [PATCH 10/10] Fix test. --- apps/indexer/test/indexer/block/fetcher_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/indexer/test/indexer/block/fetcher_test.exs b/apps/indexer/test/indexer/block/fetcher_test.exs index 74520a1eab4a..9ed106ccf6ae 100644 --- a/apps/indexer/test/indexer/block/fetcher_test.exs +++ b/apps/indexer/test/indexer/block/fetcher_test.exs @@ -353,7 +353,7 @@ defmodule Indexer.Block.FetcherTest do unprefixed_celo_token_address_hash, event_first_topic, event_data, - 18 + 17 ) variant ->