Merge pull request #9386 from blockscout/vb-filecon-jsonrpc

Filecoin JSON RPC variant
kf-arm-build-test2
Victor Baranov 8 months ago committed by GitHub
commit 7bb28d5f8c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 5679
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/filecoin.ex
  3. 6
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex
  4. 18
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/variant.ex
  5. 200
      apps/ethereum_jsonrpc/test/ethereum_jsonrpc/filecoin_test.exs
  6. 17
      apps/ethereum_jsonrpc/test/support/ethereum_jsonrpc/case/filecoin/mox.ex
  7. 33
      apps/explorer/config/dev/filecoin.exs
  8. 33
      apps/explorer/config/prod/filecoin.exs
  9. 13
      apps/explorer/config/test/filecoin.exs
  10. 4
      apps/explorer/lib/explorer/chain/import/runner/internal_transactions.ex
  11. 56
      apps/explorer/test/explorer/chain/import/runner/internal_transactions_test.exs
  12. 17
      apps/explorer/test/explorer/chain/import_test.exs
  13. 44
      apps/explorer/test/explorer/chain_test.exs
  14. 39
      apps/indexer/config/dev/filecoin.exs
  15. 39
      apps/indexer/config/prod/filecoin.exs
  16. 8
      apps/indexer/config/test/filecoin.exs
  17. 3
      apps/indexer/lib/indexer/fetcher/internal_transaction.ex
  18. 3
      cspell.json

@ -9,6 +9,7 @@
- [#9403](https://github.com/blockscout/blockscout/pull/9403) - Null round handling
- [#9401](https://github.com/blockscout/blockscout/pull/9401) - Eliminate incorrect token transfers with empty token_ids
- [#9396](https://github.com/blockscout/blockscout/pull/9396) - More-Minimal Proxy support
- [#9386](https://github.com/blockscout/blockscout/pull/9386) - Filecoin JSON RPC variant
- [#9379](https://github.com/blockscout/blockscout/pull/9379) - Filter non-traceable transactions for zetachain
- [#9364](https://github.com/blockscout/blockscout/pull/9364) - Fix using of startblock/endblock in API v1 list endpoints: txlist, txlistinternal, tokentx
- [#9360](https://github.com/blockscout/blockscout/pull/9360) - Move missing ranges sanitize to a separate background migration

File diff suppressed because one or more lines are too long

@ -89,7 +89,8 @@ defmodule EthereumJSONRPC.Geth do
end
end
defp check_errors_exist(blocks_responses, id_to_params) do
@spec check_errors_exist(list(), %{non_neg_integer() => any()}) :: :ok | {:error, list()}
def check_errors_exist(blocks_responses, id_to_params) do
blocks_responses
|> EthereumJSONRPC.sanitize_responses(id_to_params)
|> Enum.reduce([], fn
@ -400,7 +401,8 @@ defmodule EthereumJSONRPC.Geth do
|> 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
@spec reduce_internal_transactions_params(list()) :: {:ok, list()} | {:error, list()}
def 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)
|> finalize_internal_transactions_params()

@ -96,7 +96,9 @@ defmodule EthereumJSONRPC.Variant do
) :: {:ok, [raw_trace_params]} | {:error, reason :: term} | :ignore
def get do
variant = System.get_env("ETHEREUM_JSONRPC_VARIANT", "nethermind")
default_variant = get_default_variant()
variant = System.get_env("ETHEREUM_JSONRPC_VARIANT", default_variant)
cond do
is_nil(variant) ->
@ -112,4 +114,18 @@ defmodule EthereumJSONRPC.Variant do
|> String.downcase()
end
end
# credo:disable-for-next-line
defp get_default_variant do
case Application.get_env(:explorer, :chain_type) do
"polygon_zkevm" -> "geth"
"zetachain" -> "geth"
"shibarium" -> "geth"
"stability" -> "geth"
"zksync" -> "geth"
"rsk" -> "rsk"
"filecoin" -> "filecoin"
_ -> "nethermind"
end
end
end

@ -0,0 +1,200 @@
defmodule EthereumJSONRPC.FilecoinTest do
use EthereumJSONRPC.Case, async: false
import Mox
alias EthereumJSONRPC.Filecoin
setup :verify_on_exit!
describe "fetch_block_internal_transactions/2" do
setup do
initial_env = Application.get_all_env(:ethereum_jsonrpc)
old_env = Application.get_env(:explorer, :chain_type)
Application.put_env(:explorer, :chain_type, "filecoin")
on_exit(fn ->
Application.put_all_env([{:ethereum_jsonrpc, initial_env}])
Application.put_env(:explorer, :chain_type, old_env)
end)
EthereumJSONRPC.Case.Filecoin.Mox.setup()
end
setup :verify_on_exit!
test "is supported", %{json_rpc_named_arguments: json_rpc_named_arguments} do
block_number = 3_663_376
block_quantity = EthereumJSONRPC.integer_to_quantity(block_number)
expect(EthereumJSONRPC.Mox, :json_rpc, fn [%{id: id, params: [^block_quantity]}], _ ->
{:ok,
[
%{
id: id,
result: [
%{
"type" => "call",
"subtraces" => 0,
"traceAddress" => [],
"action" => %{
"callType" => "call",
"from" => "0xff0000000000000000000000000000000021cc23",
"to" => "0xff000000000000000000000000000000001a34e5",
"gas" => "0x1891a7d",
"value" => "0x0",
"input" =>
"0x868e10c400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000f2850d8182004081820d58c0960ee115a7a4b6f2fd36a83da26c608d49e4160a3737655d0f637b81be81b018539809d35519b0b75ca06304b3b4d40c810e50b954e82c5119a8b4a64c3e762a7ae8a2d465d1cd5bf096c87c56ab0da879568378e5a2368c902eea9898cf1e2a1974ddb479ec6257b69aca7734d3b3e1e70428c77f9e528ffcb3dc3f050f0193c2cc005927a765c39a4931d67fb29aaba6e99f2c7d2566b98fdbf30d6e15a2bbd63b8fa059cfad231ccba1d8964542b50419eaad4bc442d3a1dc1f41941944c11a0037e5f45820d41114bb6abbf966c2528f5705447a53ee37b7055cd4478503ea5eaf1fe165c60000000000000000000000000000"
},
"result" => %{
"gasUsed" => "0x14696c1",
"output" =>
"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
},
"blockHash" => "0xbeef70ac3db42f10dd1eb03f5f0640557acd72db61357cf3c4f47945d8beab79",
"blockNumber" => 3_663_376,
"transactionHash" => "0xf37d8b8bf67df3ddaa264e22322d2b092e390ed33f1ab14c8a136b2767979254",
"transactionPosition" => 1
},
%{
"type" => "call",
"subtraces" => 0,
"traceAddress" => [
1
],
"action" => %{
"callType" => "call",
"from" => "0xff000000000000000000000000000000002c2c61",
"to" => "0xff00000000000000000000000000000000000004",
"gas" => "0x2c6aae6",
"value" => "0x0",
"input" =>
"0x868e10c40000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
},
"result" => %{
"gasUsed" => "0x105fb2",
"output" =>
"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000578449007d2903b8000000004a000190f76c1adff180004c00907e2dd41a18e7c7a7f2bd82581a0001916cb98a2c3dfb67a389a588fb0e593f762dd6c9195851235601fba7e16707ee65746d4671e80aa2bb15bc7d6ebe3b000000000000000000"
},
"blockHash" => "0xbeef70ac3db42f10dd1eb03f5f0640557acd72db61357cf3c4f47945d8beab79",
"blockNumber" => 3_663_376,
"transactionHash" => "0xbc62a61e0be0e8f6ae09e21ad10f6d79c9a8b8ebc46f8ce076dc0dbe1d6ed4a9",
"transactionPosition" => 21
}
]
}
]}
end)
assert {:ok,
[
%{
block_number: ^block_number,
transaction_index: 21,
transaction_hash: "0xbc62a61e0be0e8f6ae09e21ad10f6d79c9a8b8ebc46f8ce076dc0dbe1d6ed4a9",
index: 0,
trace_address: [1],
type: "call",
call_type: "call",
from_address_hash: "0xff000000000000000000000000000000002c2c61",
to_address_hash: "0xff00000000000000000000000000000000000004",
gas: 46_574_310,
gas_used: 1_073_074,
input:
"0x868e10c40000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
output:
"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000578449007d2903b8000000004a000190f76c1adff180004c00907e2dd41a18e7c7a7f2bd82581a0001916cb98a2c3dfb67a389a588fb0e593f762dd6c9195851235601fba7e16707ee65746d4671e80aa2bb15bc7d6ebe3b000000000000000000",
value: 0
},
%{
block_number: ^block_number,
transaction_index: 1,
transaction_hash: "0xf37d8b8bf67df3ddaa264e22322d2b092e390ed33f1ab14c8a136b2767979254",
index: 0,
trace_address: [],
type: "call",
call_type: "call",
from_address_hash: "0xff0000000000000000000000000000000021cc23",
to_address_hash: "0xff000000000000000000000000000000001a34e5",
gas: 25_762_429,
gas_used: 21_403_329,
input:
"0x868e10c400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000f2850d8182004081820d58c0960ee115a7a4b6f2fd36a83da26c608d49e4160a3737655d0f637b81be81b018539809d35519b0b75ca06304b3b4d40c810e50b954e82c5119a8b4a64c3e762a7ae8a2d465d1cd5bf096c87c56ab0da879568378e5a2368c902eea9898cf1e2a1974ddb479ec6257b69aca7734d3b3e1e70428c77f9e528ffcb3dc3f050f0193c2cc005927a765c39a4931d67fb29aaba6e99f2c7d2566b98fdbf30d6e15a2bbd63b8fa059cfad231ccba1d8964542b50419eaad4bc442d3a1dc1f41941944c11a0037e5f45820d41114bb6abbf966c2528f5705447a53ee37b7055cd4478503ea5eaf1fe165c60000000000000000000000000000",
output:
"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
value: 0
}
]} =
Filecoin.fetch_block_internal_transactions(
[
block_number
],
json_rpc_named_arguments
)
end
test "parses smart-contract creation", %{json_rpc_named_arguments: json_rpc_named_arguments} do
block_number = 3_663_377
block_quantity = EthereumJSONRPC.integer_to_quantity(block_number)
expect(EthereumJSONRPC.Mox, :json_rpc, fn [%{id: id, params: [^block_quantity]}], _ ->
{:ok,
[
%{
id: id,
result: [
%{
"type" => "create",
"subtraces" => 0,
"traceAddress" => [
0
],
"action" => %{
"from" => "0xff00000000000000000000000000000000000004",
"gas" => "0x53cf101",
"value" => "0x0",
"init" => "0xfe"
},
"result" => %{
"address" => "0xff000000000000000000000000000000002d44e6",
"gasUsed" => "0x1be32fc",
"code" => "0xfe"
},
"blockHash" => "0xbeef70ac3db42f10dd1eb03f5f0640557acd72db61357cf3c4f47945d8beab79",
"blockNumber" => 3_663_377,
"transactionHash" => "0x86ccda9dc76bd37c7201a6da1e10260bf984590efc6b221635c8dd33cc520067",
"transactionPosition" => 18
}
]
}
]}
end)
assert {:ok,
[
%{
block_number: ^block_number,
transaction_index: 18,
transaction_hash: "0x86ccda9dc76bd37c7201a6da1e10260bf984590efc6b221635c8dd33cc520067",
index: 0,
trace_address: [0],
type: "create",
from_address_hash: "0xff00000000000000000000000000000000000004",
created_contract_address_hash: "0xff000000000000000000000000000000002d44e6",
gas: 87_879_937,
gas_used: 29_242_108,
init: "0xfe",
created_contract_code: "0xfe",
value: 0
}
]} =
Filecoin.fetch_block_internal_transactions(
[
block_number
],
json_rpc_named_arguments
)
end
end
end

@ -0,0 +1,17 @@
defmodule EthereumJSONRPC.Case.Filecoin.Mox do
@moduledoc """
`EthereumJSONRPC.Case` for mocking connecting to Filecoin using `Mox`
"""
def setup do
%{
block_interval: 500,
json_rpc_named_arguments: [
transport: EthereumJSONRPC.Mox,
transport_options: [http_options: [timeout: 60000, recv_timeout: 60000]],
variant: EthereumJSONRPC.Filecoin
],
subscribe_named_arguments: [transport: EthereumJSONRPC.Mox, transport_options: []]
}
end
end

@ -0,0 +1,33 @@
import Config
~w(config config_helper.exs)
|> Path.join()
|> Code.eval_file()
hackney_opts = ConfigHelper.hackney_options()
timeout = ConfigHelper.timeout(1)
config :explorer,
json_rpc_named_arguments: [
transport: EthereumJSONRPC.HTTP,
transport_options: [
http: EthereumJSONRPC.HTTP.HTTPoison,
url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "http://localhost:1234/rpc/v1",
fallback_url: System.get_env("ETHEREUM_JSONRPC_FALLBACK_HTTP_URL"),
fallback_trace_url: System.get_env("ETHEREUM_JSONRPC_FALLBACK_TRACE_URL"),
method_to_url: [
eth_call: ConfigHelper.eth_call_url("http://localhost:1234/rpc/v1"),
trace_block: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:1234/rpc/v1"
],
http_options: [recv_timeout: timeout, timeout: timeout, hackney: hackney_opts]
],
variant: EthereumJSONRPC.Filecoin
],
subscribe_named_arguments: [
transport: EthereumJSONRPC.WebSocket,
transport_options: [
web_socket: EthereumJSONRPC.WebSocket.WebSocketClient,
url: System.get_env("ETHEREUM_JSONRPC_WS_URL")
],
variant: EthereumJSONRPC.Filecoin
]

@ -0,0 +1,33 @@
import Config
~w(config config_helper.exs)
|> Path.join()
|> Code.eval_file()
hackney_opts = ConfigHelper.hackney_options()
timeout = ConfigHelper.timeout(1)
config :explorer,
json_rpc_named_arguments: [
transport: EthereumJSONRPC.HTTP,
transport_options: [
http: EthereumJSONRPC.HTTP.HTTPoison,
url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL"),
fallback_url: System.get_env("ETHEREUM_JSONRPC_FALLBACK_HTTP_URL"),
fallback_trace_url: System.get_env("ETHEREUM_JSONRPC_FALLBACK_TRACE_URL"),
method_to_url: [
eth_call: ConfigHelper.eth_call_url(),
trace_block: System.get_env("ETHEREUM_JSONRPC_TRACE_URL")
],
http_options: [recv_timeout: timeout, timeout: timeout, hackney: hackney_opts]
],
variant: EthereumJSONRPC.Filecoin
],
subscribe_named_arguments: [
transport: EthereumJSONRPC.WebSocket,
transport_options: [
web_socket: EthereumJSONRPC.WebSocket.WebSocketClient,
url: System.get_env("ETHEREUM_JSONRPC_WS_URL")
],
variant: EthereumJSONRPC.Filecoin
]

@ -0,0 +1,13 @@
import Config
config :explorer,
json_rpc_named_arguments: [
transport: EthereumJSONRPC.Mox,
transport_options: [],
variant: EthereumJSONRPC.Filecoin
],
subscribe_named_arguments: [
transport: EthereumJSONRPC.Mox,
transport_options: [],
variant: EthereumJSONRPC.Filecoin
]

@ -395,7 +395,9 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactions do
block_hash = Map.fetch!(blocks_map, block_number)
entries
|> Enum.sort_by(&{&1.transaction_hash, &1.index})
|> Enum.sort_by(
&{(Map.has_key?(&1, :transaction_index) && &1.transaction_index) || &1.transaction_hash, &1.index}
)
|> Enum.with_index()
|> Enum.map(fn {entry, index} ->
entry

@ -163,35 +163,38 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do
internal_transaction_changes_2_1
])
assert from(i in InternalTransaction, where: i.transaction_hash == ^transaction0.hash, where: i.index == 0)
|> Repo.one()
|> is_nil()
# transaction with index 0 is ignored in Nethermind JSON RPC Variant and not ignored in case of Geth
# assert from(i in InternalTransaction, where: i.transaction_hash == ^transaction0.hash, where: i.index == 0)
# |> Repo.one()
# |> is_nil()
assert 1 == Repo.get_by!(InternalTransaction, transaction_hash: transaction0.hash, index: 1).block_index
assert from(i in InternalTransaction, where: i.transaction_hash == ^transaction1.hash) |> Repo.one() |> is_nil()
# assert from(i in InternalTransaction, where: i.transaction_hash == ^transaction1.hash) |> Repo.one() |> is_nil()
assert from(i in InternalTransaction, where: i.transaction_hash == ^transaction2.hash, where: i.index == 0)
|> Repo.one()
|> is_nil()
# assert from(i in InternalTransaction, where: i.transaction_hash == ^transaction2.hash, where: i.index == 0)
# |> Repo.one()
# |> is_nil()
assert 4 == Repo.get_by!(InternalTransaction, transaction_hash: transaction2.hash, index: 1).block_index
end
test "simple coin transfer has no internal transaction inserted" do
transaction = insert(:transaction) |> with_block(status: :ok)
insert(:pending_block_operation, block_hash: transaction.block_hash, block_number: transaction.block_number)
# test "simple coin transfer has no internal transaction inserted for Nethermind" do
# transaction = insert(:transaction) |> with_block(status: :ok)
# insert(:pending_block_operation, block_hash: transaction.block_hash, block_number: transaction.block_number)
assert :ok == transaction.status
# assert :ok == transaction.status
index = 0
# # transaction with index 0 is ignored in Nethermind JSON RPC Variant and not ignored in case of Geth
# index = 0
internal_transaction_changes =
make_internal_transaction_changes_for_simple_coin_transfers(transaction, index, nil)
# internal_transaction_changes =
# make_internal_transaction_changes_for_simple_coin_transfers(transaction, index, nil)
assert {:ok, _} = run_internal_transactions([internal_transaction_changes])
# assert {:ok, _} = run_internal_transactions([internal_transaction_changes])
assert !Repo.exists?(from(i in InternalTransaction, where: i.transaction_hash == ^transaction.hash))
end
# assert !Repo.exists?(from(i in InternalTransaction, where: i.transaction_hash == ^transaction.hash))
# end
test "pending transactions don't get updated not its internal_transactions inserted" do
transaction = insert(:transaction) |> with_block(status: :ok)
@ -283,8 +286,10 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do
assert full_block.hash == inserted.block_hash
transaction_changes = make_internal_transaction_changes(inserted, 0, nil)
transaction_changes_2 = make_internal_transaction_changes(inserted, 1, nil)
# transaction with index 0 is ignored in Nethermind JSON RPC Variant and not ignored in case of Geth
_transaction_changes_0 = make_internal_transaction_changes(inserted, 0, nil)
transaction_changes = make_internal_transaction_changes(inserted, 1, nil)
transaction_changes_2 = make_internal_transaction_changes(inserted, 2, nil)
empty_changes = make_empty_block_changes(empty_block.number)
assert {:ok, _} = run_internal_transactions([empty_changes, transaction_changes, transaction_changes_2])
@ -292,12 +297,12 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do
assert %{consensus: true} = Repo.get(Block, empty_block.hash)
assert PendingBlockOperation |> Repo.get(empty_block.hash) |> is_nil()
assert from(i in InternalTransaction, where: i.transaction_hash == ^inserted.hash, where: i.index == 0)
assert from(i in InternalTransaction, where: i.transaction_hash == ^inserted.hash, where: i.index == 1)
|> Repo.one()
|> is_nil() ==
true
false
assert from(i in InternalTransaction, where: i.transaction_hash == ^inserted.hash, where: i.index == 1)
assert from(i in InternalTransaction, where: i.transaction_hash == ^inserted.hash, where: i.index == 2)
|> Repo.one()
|> is_nil() ==
false
@ -404,7 +409,12 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do
to_address_hash: insert(:address).hash,
call_type: :call,
gas: 0,
gas_used: nil,
gas_used:
if is_nil(error) do
100_500
else
nil
end,
input: %Data{bytes: <<>>},
output:
if is_nil(error) do

@ -60,7 +60,8 @@ defmodule Explorer.Chain.ImportTest do
block_number: 37,
transaction_index: 0,
transaction_hash: "0x53bd884872de3e488692881baeec262e7b95234d3965248c39fe992fffd433e5",
index: 0,
# transaction with index 0 is ignored in Nethermind JSON RPC Variant and not ignored in case of Geth
index: 1,
trace_address: [],
type: "call",
call_type: "call",
@ -76,7 +77,7 @@ defmodule Explorer.Chain.ImportTest do
block_number: 37,
transaction_index: 1,
transaction_hash: "0x53bd884872de3e488692881baeec262e7b95234d3965248c39fe992fffd433e5",
index: 1,
index: 2,
trace_address: [0],
type: "call",
call_type: "call",
@ -270,6 +271,15 @@ defmodule Explorer.Chain.ImportTest do
<<83, 189, 136, 72, 114, 222, 62, 72, 134, 146, 136, 27, 174, 236, 38, 46, 123, 149, 35, 77, 57,
101, 36, 140, 57, 254, 153, 47, 255, 212, 51, 229>>
}
},
%{
index: 2,
transaction_hash: %Hash{
byte_count: 32,
bytes:
<<83, 189, 136, 72, 114, 222, 62, 72, 134, 146, 136, 27, 174, 236, 38, 46, 123, 149, 35, 77, 57,
101, 36, 140, 57, 254, 153, 47, 255, 212, 51, 229>>
}
}
],
logs: [
@ -504,7 +514,8 @@ defmodule Explorer.Chain.ImportTest do
Subscriber.to(:internal_transactions, :realtime)
Import.all(@import_data)
assert_receive {:chain_event, :internal_transactions, :realtime, [%{transaction_hash: _, index: _}]}
assert_receive {:chain_event, :internal_transactions, :realtime,
[%{transaction_hash: _, index: _}, %{transaction_hash: _, index: _}]}
end
test "publishes transactions data to subscribers on insert" do

@ -1294,7 +1294,8 @@ defmodule Explorer.ChainTest do
%{
block_number: 37,
transaction_hash: "0x53bd884872de3e488692881baeec262e7b95234d3965248c39fe992fffd433e5",
index: 0,
# transaction with index 0 is ignored in Nethermind JSON RPC Variant and not ignored in case of Geth
index: 1,
trace_address: [],
type: "call",
call_type: "call",
@ -1383,7 +1384,7 @@ defmodule Explorer.ChainTest do
}
}
test "with valid data" do
test "with valid data", %{json_rpc_named_arguments: json_rpc_named_arguments} do
{:ok, first_topic} = Explorer.Chain.Hash.Full.cast(@first_topic_hex_string)
{:ok, second_topic} = Explorer.Chain.Hash.Full.cast(@second_topic_hex_string)
{:ok, third_topic} = Explorer.Chain.Hash.Full.cast(@third_topic_hex_string)
@ -1393,6 +1394,9 @@ defmodule Explorer.ChainTest do
gas_limit = Decimal.new(6_946_336)
gas_used = Decimal.new(50450)
gas_int = Decimal.new("4677320")
gas_used_int = Decimal.new("27770")
assert {:ok,
%{
addresses: [
@ -1474,7 +1478,41 @@ defmodule Explorer.ChainTest do
updated_at: %{}
}
],
internal_transactions: [],
internal_transactions: [
%InternalTransaction{
call_type: :call,
created_contract_code: nil,
error: nil,
gas: ^gas_int,
gas_used: ^gas_used_int,
index: 1,
init: nil,
input: %Explorer.Chain.Data{
bytes:
<<16, 133, 82, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 45, 103, 203, 7, 115, 238, 63, 140,
231, 234, 137, 179, 40, 255, 234, 134, 26, 179, 239>>
},
output: %Explorer.Chain.Data{bytes: ""},
trace_address: [],
type: :call,
block_number: 37,
transaction_index: nil,
block_index: 0,
created_contract_address_hash: nil,
from_address_hash: %Explorer.Chain.Hash{
byte_count: 20,
bytes:
<<232, 221, 197, 199, 162, 210, 240, 215, 169, 121, 132, 89, 192, 16, 79, 223, 94, 152, 122,
202>>
},
to_address_hash: %Explorer.Chain.Hash{
byte_count: 20,
bytes:
<<139, 243, 141, 71, 100, 146, 144, 100, 242, 212, 211, 165, 101, 32, 167, 106, 179, 223, 65,
91>>
}
}
],
logs: [
%Log{
address_hash: %Hash{

@ -0,0 +1,39 @@
import Config
~w(config config_helper.exs)
|> Path.join()
|> Code.eval_file()
hackney_opts = ConfigHelper.hackney_options()
timeout = ConfigHelper.timeout(1)
config :indexer,
block_interval: ConfigHelper.parse_time_env_var("INDEXER_CATCHUP_BLOCK_INTERVAL", "5s"),
json_rpc_named_arguments: [
transport:
if(System.get_env("ETHEREUM_JSONRPC_TRANSPORT", "http") == "http",
do: EthereumJSONRPC.HTTP,
else: EthereumJSONRPC.IPC
),
transport_options: [
http: EthereumJSONRPC.HTTP.HTTPoison,
url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "http://localhost:1234/rpc/v1",
fallback_url: System.get_env("ETHEREUM_JSONRPC_FALLBACK_HTTP_URL"),
fallback_trace_url: System.get_env("ETHEREUM_JSONRPC_FALLBACK_TRACE_URL"),
method_to_url: [
eth_call: ConfigHelper.eth_call_url("http://localhost:1234/rpc/v1"),
trace_block: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:1234/rpc/v1"
],
http_options: [recv_timeout: timeout, timeout: timeout, hackney: hackney_opts]
],
variant: EthereumJSONRPC.Filecoin
],
subscribe_named_arguments: [
transport:
System.get_env("ETHEREUM_JSONRPC_WS_URL") && System.get_env("ETHEREUM_JSONRPC_WS_URL") !== "" &&
EthereumJSONRPC.WebSocket,
transport_options: [
web_socket: EthereumJSONRPC.WebSocket.WebSocketClient,
url: System.get_env("ETHEREUM_JSONRPC_WS_URL")
]
]

@ -0,0 +1,39 @@
import Config
~w(config config_helper.exs)
|> Path.join()
|> Code.eval_file()
hackney_opts = ConfigHelper.hackney_options()
timeout = ConfigHelper.timeout(10)
config :indexer,
block_interval: ConfigHelper.parse_time_env_var("INDEXER_CATCHUP_BLOCK_INTERVAL", "5s"),
json_rpc_named_arguments: [
transport:
if(System.get_env("ETHEREUM_JSONRPC_TRANSPORT", "http") == "http",
do: EthereumJSONRPC.HTTP,
else: EthereumJSONRPC.IPC
),
transport_options: [
http: EthereumJSONRPC.HTTP.HTTPoison,
url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL"),
fallback_url: System.get_env("ETHEREUM_JSONRPC_FALLBACK_HTTP_URL"),
fallback_trace_url: System.get_env("ETHEREUM_JSONRPC_FALLBACK_TRACE_URL"),
method_to_url: [
eth_call: ConfigHelper.eth_call_url(),
trace_block: System.get_env("ETHEREUM_JSONRPC_TRACE_URL")
],
http_options: [recv_timeout: timeout, timeout: timeout, hackney: hackney_opts]
],
variant: EthereumJSONRPC.Filecoin
],
subscribe_named_arguments: [
transport:
System.get_env("ETHEREUM_JSONRPC_WS_URL") && System.get_env("ETHEREUM_JSONRPC_WS_URL") !== "" &&
EthereumJSONRPC.WebSocket,
transport_options: [
web_socket: EthereumJSONRPC.WebSocket.WebSocketClient,
url: System.get_env("ETHEREUM_JSONRPC_WS_URL")
]
]

@ -0,0 +1,8 @@
import Config
config :indexer,
json_rpc_named_arguments: [
transport: EthereumJSONRPC.Mox,
transport_options: [],
variant: EthereumJSONRPC.Filecoin
]

@ -164,7 +164,8 @@ defmodule Indexer.Fetcher.InternalTransaction do
EthereumJSONRPC.Nethermind,
EthereumJSONRPC.Erigon,
EthereumJSONRPC.Besu,
EthereumJSONRPC.RSK
EthereumJSONRPC.RSK,
EthereumJSONRPC.Filecoin
]
defp block_traceable_variants do
if Application.get_env(:ethereum_jsonrpc, EthereumJSONRPC.Geth)[:block_traceable?] do

@ -170,7 +170,9 @@
"exvcr",
"Faileddi",
"falala",
"FEVM",
"Filesize",
"Filecoin",
"fkey",
"Floki",
"fontawesome",
@ -574,6 +576,7 @@
"NOTOK",
"sushiswap",
"zetachain",
"zksync",
"filecoin",
"Filecoin"
],

Loading…
Cancel
Save