Merge pull request #3154 from poanetwork/vb-besu-support

Support of Hyperledger Besu client
pull/3157/head
Victor Baranov 5 years ago committed by GitHub
commit 88114f1224
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 4
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  3. 18
      apps/block_scout_web/priv/gettext/default.pot
  4. 18
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  5. 305
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/besu.ex
  6. 196
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/besu/fetched_beneficiaries.ex
  7. 2
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex
  8. 1
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/parity.ex
  9. 5
      apps/explorer/config/config.exs
  10. 25
      apps/explorer/config/dev/besu.exs
  11. 25
      apps/explorer/config/prod/besu.exs
  12. 14
      apps/explorer/config/test/besu.exs
  13. 3
      apps/indexer/config/config.exs
  14. 30
      apps/indexer/config/dev/besu.exs
  15. 29
      apps/indexer/config/prod/besu.exs
  16. 8
      apps/indexer/config/test/besu.exs
  17. 3
      apps/indexer/lib/indexer/fetcher/internal_transaction.ex

@ -1,6 +1,7 @@
## Current ## Current
### Features ### Features
- [#3154](https://github.com/poanetwork/blockscout/pull/3154) - Support of Hyperledger Besu client
- [#3153](https://github.com/poanetwork/blockscout/pull/3153) - Proxy contracts: logs decoding using implementation ABI - [#3153](https://github.com/poanetwork/blockscout/pull/3153) - Proxy contracts: logs decoding using implementation ABI
- [#3153](https://github.com/poanetwork/blockscout/pull/3153) - Proxy contracts: methods decoding using implementation ABI - [#3153](https://github.com/poanetwork/blockscout/pull/3153) - Proxy contracts: methods decoding using implementation ABI
- [#3149](https://github.com/poanetwork/blockscout/pull/3149) - Display and store revert reason of tx on demand at transaction details page and at gettxinfo API endpoint. - [#3149](https://github.com/poanetwork/blockscout/pull/3149) - Display and store revert reason of tx on demand at transaction details page and at gettxinfo API endpoint.

@ -55,12 +55,16 @@
class: "dropdown-item #{tab_status("txs", @conn.request_path)}", class: "dropdown-item #{tab_status("txs", @conn.request_path)}",
to: transaction_path(@conn, :index) to: transaction_path(@conn, :index)
) %> ) %>
<% json_rpc_named_arguments = Application.fetch_env!(:indexer, :json_rpc_named_arguments)%>
<% variant = Keyword.fetch!(json_rpc_named_arguments, :variant) %>
<%= if variant !== EthereumJSONRPC.Besu do %>
<%= link( <%= link(
gettext("Pending"), gettext("Pending"),
class: "dropdown-item #{tab_status("pending_transactions", @conn.request_path)}", class: "dropdown-item #{tab_status("pending_transactions", @conn.request_path)}",
"data-test": "pending_transactions_link", "data-test": "pending_transactions_link",
to: pending_transaction_path(@conn, :index) to: pending_transaction_path(@conn, :index)
) %> ) %>
<% end %>
</div> </div>
</li> </li>
<li class="nav-item"> <li class="nav-item">

@ -107,12 +107,12 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:81 #: lib/block_scout_web/templates/layout/_topnav.html.eex:85
msgid "APIs" msgid "APIs"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:71 #: lib/block_scout_web/templates/layout/_topnav.html.eex:75
msgid "Accounts" msgid "Accounts"
msgstr "" msgstr ""
@ -636,7 +636,7 @@ msgid "Error: Could not determine contract creator."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:95 #: lib/block_scout_web/templates/layout/_topnav.html.eex:99
msgid "Eth RPC" msgid "Eth RPC"
msgstr "" msgstr ""
@ -737,7 +737,7 @@ msgid "Github"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:85 #: lib/block_scout_web/templates/layout/_topnav.html.eex:89
msgid "GraphQL" msgid "GraphQL"
msgstr "" msgstr ""
@ -1158,7 +1158,7 @@ msgid "Parent Hash"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:59 #: lib/block_scout_web/templates/layout/_topnav.html.eex:62
#: lib/block_scout_web/views/transaction_view.ex:250 #: lib/block_scout_web/views/transaction_view.ex:250
#: lib/block_scout_web/views/transaction_view.ex:284 #: lib/block_scout_web/views/transaction_view.ex:284
msgid "Pending" msgid "Pending"
@ -1196,7 +1196,7 @@ msgid "Query"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:90 #: lib/block_scout_web/templates/layout/_topnav.html.eex:94
msgid "RPC" msgid "RPC"
msgstr "" msgstr ""
@ -1254,14 +1254,14 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:14 #: lib/block_scout_web/templates/address_logs/index.html.eex:14
#: lib/block_scout_web/templates/layout/_topnav.html.eex:141 #: lib/block_scout_web/templates/layout/_topnav.html.eex:145
#: lib/block_scout_web/templates/layout/_topnav.html.eex:158 #: lib/block_scout_web/templates/layout/_topnav.html.eex:162
msgid "Search" msgid "Search"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:135
#: lib/block_scout_web/templates/layout/_topnav.html.eex:139 #: lib/block_scout_web/templates/layout/_topnav.html.eex:139
#: lib/block_scout_web/templates/layout/_topnav.html.eex:143
msgid "Search by address, token symbol name, transaction hash, or block number" msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr "" msgstr ""

@ -107,12 +107,12 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:81 #: lib/block_scout_web/templates/layout/_topnav.html.eex:85
msgid "APIs" msgid "APIs"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:71 #: lib/block_scout_web/templates/layout/_topnav.html.eex:75
msgid "Accounts" msgid "Accounts"
msgstr "" msgstr ""
@ -636,7 +636,7 @@ msgid "Error: Could not determine contract creator."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:95 #: lib/block_scout_web/templates/layout/_topnav.html.eex:99
msgid "Eth RPC" msgid "Eth RPC"
msgstr "" msgstr ""
@ -737,7 +737,7 @@ msgid "Github"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:85 #: lib/block_scout_web/templates/layout/_topnav.html.eex:89
msgid "GraphQL" msgid "GraphQL"
msgstr "" msgstr ""
@ -1158,7 +1158,7 @@ msgid "Parent Hash"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:59 #: lib/block_scout_web/templates/layout/_topnav.html.eex:62
#: lib/block_scout_web/views/transaction_view.ex:250 #: lib/block_scout_web/views/transaction_view.ex:250
#: lib/block_scout_web/views/transaction_view.ex:284 #: lib/block_scout_web/views/transaction_view.ex:284
msgid "Pending" msgid "Pending"
@ -1196,7 +1196,7 @@ msgid "Query"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:90 #: lib/block_scout_web/templates/layout/_topnav.html.eex:94
msgid "RPC" msgid "RPC"
msgstr "" msgstr ""
@ -1254,14 +1254,14 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:14 #: lib/block_scout_web/templates/address_logs/index.html.eex:14
#: lib/block_scout_web/templates/layout/_topnav.html.eex:141 #: lib/block_scout_web/templates/layout/_topnav.html.eex:145
#: lib/block_scout_web/templates/layout/_topnav.html.eex:158 #: lib/block_scout_web/templates/layout/_topnav.html.eex:162
msgid "Search" msgid "Search"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:135
#: lib/block_scout_web/templates/layout/_topnav.html.eex:139 #: lib/block_scout_web/templates/layout/_topnav.html.eex:139
#: lib/block_scout_web/templates/layout/_topnav.html.eex:143
msgid "Search by address, token symbol name, transaction hash, or block number" msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr "" msgstr ""

@ -0,0 +1,305 @@
# credo:disable-for-this-file
defmodule EthereumJSONRPC.Besu do
@moduledoc """
Ethereum JSONRPC methods that are only supported by [Besu](https://besu.hyperledger.org/en/stable/Reference/API-Methods).
"""
require Logger
import EthereumJSONRPC, only: [id_to_params: 1, integer_to_quantity: 1, json_rpc: 2, request: 1]
alias EthereumJSONRPC.Parity.{FetchedBeneficiaries, Traces}
alias EthereumJSONRPC.{Transaction, Transactions}
@behaviour EthereumJSONRPC.Variant
@impl EthereumJSONRPC.Variant
def fetch_beneficiaries(block_numbers, json_rpc_named_arguments)
when is_list(block_numbers) and is_list(json_rpc_named_arguments) do
id_to_params =
block_numbers
|> block_numbers_to_params_list()
|> id_to_params()
with {:ok, responses} <-
id_to_params
|> FetchedBeneficiaries.requests()
|> json_rpc(json_rpc_named_arguments) do
{:ok, FetchedBeneficiaries.from_responses(responses, id_to_params)}
end
end
@impl EthereumJSONRPC.Variant
def fetch_internal_transactions(_transactions_params, _json_rpc_named_arguments), do: :ignore
@doc """
Fetches the `t:Explorer.Chain.InternalTransaction.changeset/2` params from the Besu trace URL.
"""
@impl EthereumJSONRPC.Variant
def fetch_block_internal_transactions(block_numbers, json_rpc_named_arguments) when is_list(block_numbers) do
id_to_params = id_to_params(block_numbers)
with {:ok, responses} <-
id_to_params
|> trace_replay_block_transactions_requests()
|> json_rpc(json_rpc_named_arguments) do
trace_replay_block_transactions_responses_to_internal_transactions_params(responses, id_to_params)
end
end
@impl EthereumJSONRPC.Variant
def fetch_first_trace(transactions_params, json_rpc_named_arguments) when is_list(transactions_params) do
id_to_params = id_to_params(transactions_params)
trace_replay_transaction_response =
id_to_params
|> trace_replay_transaction_requests()
|> json_rpc(json_rpc_named_arguments)
case trace_replay_transaction_response do
{:ok, responses} ->
case trace_replay_transaction_responses_to_first_trace_params(responses, id_to_params) do
{:ok, [first_trace]} ->
%{block_hash: block_hash} =
transactions_params
|> Enum.at(0)
{:ok,
[%{first_trace: first_trace, block_hash: block_hash, json_rpc_named_arguments: json_rpc_named_arguments}]}
{:error, error} ->
Logger.error(inspect(error))
{:error, error}
end
{:error, :econnrefused} ->
{:error, :econnrefused}
{:error, [error]} ->
Logger.error(inspect(error))
{:error, error}
end
end
@doc """
Fetches the pending transactions from the Besu node.
*NOTE*: The pending transactions are local to the node that is contacted and may not be consistent across nodes based
on the transactions that each node has seen and how each node prioritizes collating transactions into the next block.
"""
@impl EthereumJSONRPC.Variant
@spec fetch_pending_transactions(EthereumJSONRPC.json_rpc_named_arguments()) ::
{:ok, [Transaction.params()]} | {:error, reason :: term}
def fetch_pending_transactions(json_rpc_named_arguments) do
with {:ok, transactions} <-
%{id: 1, method: "txpool_besuTransactions", params: []}
|> request()
|> json_rpc(json_rpc_named_arguments) do
transactions_params =
transactions
|> Transactions.to_elixir()
|> Transactions.elixir_to_params()
{:ok, transactions_params}
end
end
defp block_numbers_to_params_list(block_numbers) when is_list(block_numbers) do
Enum.map(block_numbers, &%{block_quantity: integer_to_quantity(&1)})
end
defp trace_replay_block_transactions_responses_to_internal_transactions_params(responses, id_to_params)
when is_list(responses) and is_map(id_to_params) do
with {:ok, traces} <- trace_replay_block_transactions_responses_to_traces(responses, id_to_params) do
params =
traces
|> Traces.to_elixir()
|> Traces.elixir_to_params()
{:ok, params}
end
end
defp trace_replay_block_transactions_responses_to_traces(responses, id_to_params)
when is_list(responses) and is_map(id_to_params) do
responses
|> Enum.map(&trace_replay_block_transactions_response_to_traces(&1, id_to_params))
|> Enum.reduce(
{:ok, []},
fn
{:ok, traces}, {:ok, acc_traces_list} ->
{:ok, [traces | acc_traces_list]}
{:ok, _}, {:error, _} = acc_error ->
acc_error
{:error, reason}, {:ok, _} ->
{:error, [reason]}
{:error, reason}, {:error, acc_reason} ->
{:error, [reason | acc_reason]}
end
)
|> case do
{:ok, traces_list} ->
traces =
traces_list
|> Enum.reverse()
|> List.flatten()
{:ok, traces}
{:error, reverse_reasons} ->
reasons = Enum.reverse(reverse_reasons)
{:error, reasons}
end
end
defp trace_replay_block_transactions_response_to_traces(%{id: id, result: results}, id_to_params)
when is_list(results) and is_map(id_to_params) do
block_number = Map.fetch!(id_to_params, id)
annotated_traces =
results
|> Stream.with_index()
|> Enum.flat_map(fn {%{"trace" => traces, "transactionHash" => transaction_hash}, transaction_index} ->
traces
|> Stream.with_index()
|> Enum.map(fn {trace, index} ->
Map.merge(trace, %{
"blockNumber" => block_number,
"transactionHash" => transaction_hash,
"transactionIndex" => transaction_index,
"index" => index
})
end)
end)
{:ok, annotated_traces}
end
defp trace_replay_block_transactions_response_to_traces(%{id: id, error: error}, id_to_params)
when is_map(id_to_params) do
block_number = Map.fetch!(id_to_params, id)
annotated_error =
Map.put(error, :data, %{
"blockNumber" => block_number
})
{:error, annotated_error}
end
defp trace_replay_block_transactions_requests(id_to_params) when is_map(id_to_params) do
Enum.map(id_to_params, fn {id, block_number} ->
trace_replay_block_transactions_request(%{id: id, block_number: block_number})
end)
end
defp trace_replay_block_transactions_request(%{id: id, block_number: block_number}) do
request(%{id: id, method: "trace_replayBlockTransactions", params: [integer_to_quantity(block_number), ["trace"]]})
end
def trace_replay_transaction_responses_to_first_trace_params(responses, id_to_params)
when is_list(responses) and is_map(id_to_params) do
with {:ok, traces} <- trace_replay_transaction_responses_to_first_trace(responses, id_to_params) do
params =
traces
|> Traces.to_elixir()
|> Traces.elixir_to_params()
{:ok, params}
end
end
defp trace_replay_transaction_responses_to_first_trace(responses, id_to_params)
when is_list(responses) and is_map(id_to_params) do
responses
|> Enum.map(&trace_replay_transaction_response_to_first_trace(&1, id_to_params))
|> Enum.reduce(
{:ok, []},
fn
{:ok, traces}, {:ok, acc_traces_list} ->
{:ok, [traces | acc_traces_list]}
{:ok, _}, {:error, _} = acc_error ->
acc_error
{:error, reason}, {:ok, _} ->
{:error, [reason]}
{:error, reason}, {:error, acc_reason} ->
{:error, [reason | acc_reason]}
end
)
|> case do
{:ok, traces_list} ->
traces =
traces_list
|> Enum.reverse()
|> List.flatten()
{:ok, traces}
{:error, reverse_reasons} ->
reasons = Enum.reverse(reverse_reasons)
{:error, reasons}
end
end
defp trace_replay_transaction_response_to_first_trace(%{id: id, result: %{"trace" => traces}}, id_to_params)
when is_list(traces) and is_map(id_to_params) do
%{
block_hash: block_hash,
block_number: block_number,
hash_data: transaction_hash,
transaction_index: transaction_index
} = Map.fetch!(id_to_params, id)
first_trace =
traces
|> Stream.with_index()
|> Enum.map(fn {trace, index} ->
Map.merge(trace, %{
"blockHash" => block_hash,
"blockNumber" => block_number,
"index" => index,
"transactionIndex" => transaction_index,
"transactionHash" => transaction_hash
})
end)
|> Enum.filter(fn trace ->
Map.get(trace, "index") == 0
end)
{:ok, first_trace}
end
defp trace_replay_transaction_response_to_first_trace(%{id: id, error: error}, id_to_params)
when is_map(id_to_params) do
%{
block_hash: block_hash,
block_number: block_number,
hash_data: transaction_hash,
transaction_index: transaction_index
} = Map.fetch!(id_to_params, id)
annotated_error =
Map.put(error, :data, %{
"blockHash" => block_hash,
"blockNumber" => block_number,
"transactionIndex" => transaction_index,
"transactionHash" => transaction_hash
})
{:error, annotated_error}
end
defp trace_replay_transaction_requests(id_to_params) when is_map(id_to_params) do
Enum.map(id_to_params, fn {id, %{hash_data: hash_data}} ->
trace_replay_transaction_request(%{id: id, hash_data: hash_data})
end)
end
defp trace_replay_transaction_request(%{id: id, hash_data: hash_data}) do
request(%{id: id, method: "trace_replayTransaction", params: [hash_data, ["trace"]]})
end
end

@ -0,0 +1,196 @@
defmodule EthereumJSONRPC.Besu.FetchedBeneficiaries do
@moduledoc """
Beneficiaries and errors from batch requests to `trace_block`.
"""
import EthereumJSONRPC, only: [quantity_to_integer: 1]
@doc """
Converts `responses` to `EthereumJSONRPC.FetchedBeneficiaries.t()`.
responses - List with trace_block responses
id_to_params - Maps request id to query params
## Examples
iex> EthereumJSONRPC.Besu.FetchedBeneficiaries.from_responses(
...> [
...> %{
...> id: 0,
...> result: [
...> %{
...> "action" => %{"author" => "0x1", "rewardType" => "external", "value" => "0x0"},
...> "blockHash" => "0xFFF",
...> "blockNumber" => 12,
...> "result" => nil,
...> "subtraces" => 0,
...> "traceAddress" => [],
...> "transactionHash" => nil,
...> "transactionPosition" => nil,
...> "type" => "reward"
...> },
...> %{
...> "action" => %{"author" => "0x2", "rewardType" => "external", "value" => "0x0"},
...> "blockHash" => "0xFFF",
...> "blockNumber" => 12,
...> "result" => nil,
...> "subtraces" => 0,
...> "traceAddress" => [],
...> "transactionHash" => nil,
...> "transactionPosition" => nil,
...> "type" => "reward"
...> }
...> ]
...> }
...> ],
...> %{0 => %{block_quantity: "0xC"}}
...> )
%EthereumJSONRPC.FetchedBeneficiaries{
errors: [],
params_set: #MapSet<[
%{
address_hash: "0x1",
address_type: :validator,
block_hash: "0xFFF",
block_number: 12,
reward: "0x0"
},
%{
address_hash: "0x2",
address_type: :emission_funds,
block_hash: "0xFFF",
block_number: 12,
reward: "0x0"
}
]>
}
"""
def from_responses(responses, id_to_params) when is_list(responses) and is_map(id_to_params) do
responses
|> Enum.map(&response_to_params_set(&1, id_to_params))
|> Enum.reduce(
%EthereumJSONRPC.FetchedBeneficiaries{},
fn
{:ok, params_set}, %EthereumJSONRPC.FetchedBeneficiaries{params_set: acc_params_set} = acc ->
%EthereumJSONRPC.FetchedBeneficiaries{acc | params_set: MapSet.union(acc_params_set, params_set)}
{:error, reason}, %EthereumJSONRPC.FetchedBeneficiaries{errors: errors} = acc ->
%EthereumJSONRPC.FetchedBeneficiaries{acc | errors: [reason | errors]}
end
)
end
@doc """
`trace_block` requests for `id_to_params`.
"""
def requests(id_to_params) when is_map(id_to_params) do
Enum.map(id_to_params, fn {id, %{block_quantity: block_quantity}} ->
request(%{id: id, block_quantity: block_quantity})
end)
end
@spec response_to_params_set(%{id: id, result: nil}, %{id => %{block_quantity: block_quantity}}) ::
{:error, %{code: 404, message: String.t(), data: %{block_quantity: block_quantity}}}
when id: non_neg_integer(), block_quantity: String.t()
defp response_to_params_set(%{id: id, result: nil}, id_to_params) when is_map(id_to_params) do
%{block_quantity: block_quantity} = Map.fetch!(id_to_params, id)
{:error, %{code: 404, message: "Not Found", data: %{block_quantity: block_quantity}}}
end
@spec response_to_params_set(%{id: id, result: list(map())}, %{id => %{block_quantity: block_quantity}}) ::
{:ok, MapSet.t(EthereumJSONRPC.FetchedBeneficiary.params())}
when id: non_neg_integer(), block_quantity: String.t()
defp response_to_params_set(%{id: id, result: traces}, id_to_params) when is_list(traces) and is_map(id_to_params) do
%{block_quantity: block_quantity} = Map.fetch!(id_to_params, id)
block_number = quantity_to_integer(block_quantity)
params_set = traces_to_params_set(traces, block_number)
{:ok, params_set}
end
@spec response_to_params_set(%{id: id, error: %{code: code, message: message}}, %{
id => %{block_quantity: block_quantity}
}) :: {:error, %{code: code, message: message, data: %{block_quantity: block_quantity}}}
when id: non_neg_integer(), code: integer(), message: String.t(), block_quantity: String.t()
defp response_to_params_set(%{id: id, error: error}, id_to_params) when is_map(id_to_params) do
%{block_quantity: block_quantity} = Map.fetch!(id_to_params, id)
annotated_error = Map.put(error, :data, %{block_quantity: block_quantity})
{:error, annotated_error}
end
defp request(%{id: id, block_quantity: block_quantity}) when is_integer(id) and is_binary(block_quantity) do
EthereumJSONRPC.request(%{id: id, method: "trace_block", params: [block_quantity]})
end
defp traces_to_params_set(traces, block_number) when is_list(traces) and is_integer(block_number) do
traces
|> Stream.filter(&(&1["type"] == "reward"))
|> Stream.with_index()
|> Enum.reduce(MapSet.new(), fn {trace, index}, acc ->
MapSet.union(acc, trace_to_params_set(trace, block_number, index))
end)
end
defp trace_to_params_set(
%{
"action" => %{
"rewardType" => reward_type,
"author" => address_hash_data,
"value" => reward_value
},
"blockHash" => block_hash,
"blockNumber" => block_number
},
block_number,
index
)
when is_integer(block_number) and reward_type in ~w(block external uncle) do
MapSet.new([
%{
address_hash: address_hash_data,
block_hash: block_hash,
block_number: block_number,
reward: reward_value,
address_type: get_address_type(reward_type, index)
}
])
end
# Beneficiary's address type will depend on the responses' action.rewardType,
# which will vary depending on which network is being indexed
#
# On POA networks, rewardType will always be external and the type of the address being
# rewarded will depend on its position.
# First address will always be the validator's while the second will be the EmissionsFunds address
#
# On PoW networks, like Ethereum, the reward type will already specify the type for the
# address being rewarded
# The rewardType "block" will show the reward for the consensus block validator
# The rewardType "uncle" will show reward for validating an uncle block
defp get_address_type(reward_type, index) when reward_type == "external" and index == 0, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 1, do: :emission_funds
defp get_address_type(reward_type, index) when reward_type == "external" and index == 2, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 3, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 4, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 5, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 6, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 7, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 8, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 9, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 10, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 11, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 12, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 13, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 14, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 15, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 16, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 17, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 18, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 19, do: :validator
defp get_address_type(reward_type, index) when reward_type == "external" and index == 20, do: :validator
defp get_address_type(reward_type, _index) when reward_type == "block", do: :validator
defp get_address_type(reward_type, _index) when reward_type == "uncle", do: :uncle
defp get_address_type(reward_type, _index) when reward_type == "emptyStep", do: :validator
end

@ -38,7 +38,7 @@ defmodule EthereumJSONRPC.Geth do
end end
@doc """ @doc """
Fetches the first trace from the Parity trace URL. Fetches the first trace from the trace URL.
""" """
@impl EthereumJSONRPC.Variant @impl EthereumJSONRPC.Variant
def fetch_first_trace(_transactions_params, _json_rpc_named_arguments), do: :ignore def fetch_first_trace(_transactions_params, _json_rpc_named_arguments), do: :ignore

@ -1,3 +1,4 @@
# credo:disable-for-this-file
defmodule EthereumJSONRPC.Parity do defmodule EthereumJSONRPC.Parity do
@moduledoc """ @moduledoc """
Ethereum JSONRPC methods that are only supported by [Parity](https://wiki.parity.io/). Ethereum JSONRPC methods that are only supported by [Parity](https://wiki.parity.io/).

@ -207,6 +207,11 @@ config :explorer, Explorer.Chain.Cache.Accounts,
global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5)) global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5))
config :explorer, Explorer.Chain.Cache.PendingTransactions, config :explorer, Explorer.Chain.Cache.PendingTransactions,
enabled:
if(System.get_env("ETHEREUM_JSONRPC_VARIANT") == "besu",
do: false,
else: true
),
ttl_check_interval: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(1), else: false), ttl_check_interval: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(1), else: false),
global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5)) global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5))

@ -0,0 +1,25 @@
use Mix.Config
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:8545",
method_to_url: [
eth_call: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:8545",
eth_getBalance: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:8545",
trace_replayTransaction: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:8545"
],
http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]]
],
variant: EthereumJSONRPC.Besu
],
subscribe_named_arguments: [
transport: EthereumJSONRPC.WebSocket,
transport_options: [
web_socket: EthereumJSONRPC.WebSocket.WebSocketClient,
url: System.get_env("ETHEREUM_JSONRPC_WS_URL")
],
variant: EthereumJSONRPC.Besu
]

@ -0,0 +1,25 @@
use Mix.Config
config :explorer,
json_rpc_named_arguments: [
transport: EthereumJSONRPC.HTTP,
transport_options: [
http: EthereumJSONRPC.HTTP.HTTPoison,
url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL"),
method_to_url: [
eth_call: System.get_env("ETHEREUM_JSONRPC_TRACE_URL"),
eth_getBalance: System.get_env("ETHEREUM_JSONRPC_TRACE_URL"),
trace_replayTransaction: System.get_env("ETHEREUM_JSONRPC_TRACE_URL")
],
http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]]
],
variant: EthereumJSONRPC.Besu
],
subscribe_named_arguments: [
transport: EthereumJSONRPC.WebSocket,
transport_options: [
web_socket: EthereumJSONRPC.WebSocket.WebSocketClient,
url: System.get_env("ETHEREUM_JSONRPC_WS_URL")
],
variant: EthereumJSONRPC.Besu
]

@ -0,0 +1,14 @@
use Mix.Config
config :explorer,
transport: EthereumJSONRPC.HTTP,
json_rpc_named_arguments: [
transport: EthereumJSONRPC.Mox,
transport_options: [],
variant: EthereumJSONRPC.Besu
],
subscribe_named_arguments: [
transport: EthereumJSONRPC.Mox,
transport_options: [],
variant: EthereumJSONRPC.Besu
]

@ -38,6 +38,9 @@ config :indexer,
first_block: System.get_env("FIRST_BLOCK") || "0", first_block: System.get_env("FIRST_BLOCK") || "0",
last_block: System.get_env("LAST_BLOCK") || "" last_block: System.get_env("LAST_BLOCK") || ""
config :indexer, Indexer.Fetcher.PendingTransaction.Supervisor,
disabled?: System.get_env("ETHEREUM_JSONRPC_VARIANT") == "besu"
# config :indexer, Indexer.Fetcher.ReplacedTransaction.Supervisor, disabled?: true # config :indexer, Indexer.Fetcher.ReplacedTransaction.Supervisor, disabled?: true
# config :indexer, Indexer.Fetcher.BlockReward.Supervisor, disabled?: true # config :indexer, Indexer.Fetcher.BlockReward.Supervisor, disabled?: true
config :indexer, Indexer.Fetcher.StakingPools.Supervisor, disabled?: true config :indexer, Indexer.Fetcher.StakingPools.Supervisor, disabled?: true

@ -0,0 +1,30 @@
use Mix.Config
config :indexer,
block_interval: :timer.seconds(5),
json_rpc_named_arguments: [
transport:
if(System.get_env("ETHEREUM_JSONRPC_TRANSPORT", "http") == "http",
do: EthereumJSONRPC.HTTP,
else: EthereumJSONRPC.IPC
),
else: EthereumJSONRPC.IPC,
transport_options: [
http: EthereumJSONRPC.HTTP.HTTPoison,
url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "http://localhost:8545",
method_to_url: [
eth_getBalance: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:8545",
trace_block: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:8545",
trace_replayBlockTransactions: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:8545"
],
http_options: [recv_timeout: :timer.minutes(10), timeout: :timer.minutes(10), hackney: [pool: :ethereum_jsonrpc]]
],
variant: EthereumJSONRPC.Besu
],
subscribe_named_arguments: [
transport: 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,29 @@
use Mix.Config
config :indexer,
block_interval: :timer.seconds(5),
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"),
method_to_url: [
eth_getBalance: System.get_env("ETHEREUM_JSONRPC_TRACE_URL"),
trace_block: System.get_env("ETHEREUM_JSONRPC_TRACE_URL"),
trace_replayTransaction: System.get_env("ETHEREUM_JSONRPC_TRACE_URL")
],
http_options: [recv_timeout: :timer.minutes(10), timeout: :timer.minutes(10), hackney: [pool: :ethereum_jsonrpc]]
],
variant: EthereumJSONRPC.Besu
],
subscribe_named_arguments: [
transport: 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 @@
use Mix.Config
config :indexer,
json_rpc_named_arguments: [
transport: EthereumJSONRPC.Mox,
transport_options: [],
variant: EthereumJSONRPC.Besu
]

@ -105,6 +105,9 @@ defmodule Indexer.Fetcher.InternalTransaction do
EthereumJSONRPC.Parity -> EthereumJSONRPC.Parity ->
EthereumJSONRPC.fetch_block_internal_transactions(unique_numbers, json_rpc_named_arguments) EthereumJSONRPC.fetch_block_internal_transactions(unique_numbers, json_rpc_named_arguments)
EthereumJSONRPC.Besu ->
EthereumJSONRPC.fetch_block_internal_transactions(unique_numbers, json_rpc_named_arguments)
_ -> _ ->
fetch_block_internal_transactions_by_transactions(unique_numbers, json_rpc_named_arguments) fetch_block_internal_transactions_by_transactions(unique_numbers, json_rpc_named_arguments)
end end

Loading…
Cancel
Save