Merge pull request #3171 from poanetwork/vb-import-accounts-from-genesis-geth

Import accounts from Geth genesis
pull/3173/head
Victor Baranov 4 years ago committed by GitHub
commit 58358bb4f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 18
      apps/explorer/lib/explorer/chain_spec/genesis_data.ex
  3. 93
      apps/explorer/lib/explorer/chain_spec/geth/importer.ex
  4. 3
      apps/explorer/lib/explorer/chain_spec/parity/importer.ex
  5. 145
      apps/explorer/test/explorer/chain_spec/geth/importer_test.exs
  6. 53
      apps/explorer/test/support/fixture/chain_spec/qdai_genesis.json

@ -1,6 +1,7 @@
## Current ## Current
### Features ### Features
- [#3171](https://github.com/poanetwork/blockscout/pull/3171) - Import accounts/contracts/balances from Geth genesis.json
- [#3157](https://github.com/poanetwork/blockscout/pull/3157) - Read methods of implementation on proxy contract - [#3157](https://github.com/poanetwork/blockscout/pull/3157) - Read methods of implementation on proxy contract
### Fixes ### Fixes

@ -7,6 +7,7 @@ defmodule Explorer.ChainSpec.GenesisData do
require Logger require Logger
alias Explorer.ChainSpec.Geth.Importer, as: GethImporter
alias Explorer.ChainSpec.Parity.Importer alias Explorer.ChainSpec.Parity.Importer
alias HTTPoison.Response alias HTTPoison.Response
@ -58,11 +59,24 @@ defmodule Explorer.ChainSpec.GenesisData do
path = Application.get_env(:explorer, __MODULE__)[:chain_spec_path] path = Application.get_env(:explorer, __MODULE__)[:chain_spec_path]
if path do if path do
json_rpc_named_arguments = Application.fetch_env!(:indexer, :json_rpc_named_arguments)
variant = Keyword.fetch!(json_rpc_named_arguments, :variant)
Task.Supervisor.async_nolink(Explorer.GenesisDataTaskSupervisor, fn -> Task.Supervisor.async_nolink(Explorer.GenesisDataTaskSupervisor, fn ->
case fetch_spec(path) do case fetch_spec(path) do
{:ok, chain_spec} -> {:ok, chain_spec} ->
Importer.import_emission_rewards(chain_spec) case variant do
{:ok, _} = Importer.import_genesis_accounts(chain_spec) EthereumJSONRPC.Parity ->
Importer.import_emission_rewards(chain_spec)
{:ok, _} = Importer.import_genesis_accounts(chain_spec)
EthereumJSONRPC.Geth ->
{:ok, _} = GethImporter.import_genesis_accounts(chain_spec)
_ ->
Importer.import_emission_rewards(chain_spec)
{:ok, _} = Importer.import_genesis_accounts(chain_spec)
end
{:error, reason} -> {:error, reason} ->
Logger.warn(fn -> "Failed to fetch genesis data. #{inspect(reason)}" end) Logger.warn(fn -> "Failed to fetch genesis data. #{inspect(reason)}" end)

@ -0,0 +1,93 @@
# credo:disable-for-this-file
defmodule Explorer.ChainSpec.Geth.Importer do
@moduledoc """
Imports data from Geth genesis.json.
"""
require Logger
alias EthereumJSONRPC.Blocks
alias Explorer.Chain
alias Explorer.Chain.Hash.Address, as: AddressHash
def import_genesis_accounts(chain_spec) do
balance_params =
chain_spec
|> genesis_accounts()
|> Stream.map(fn balance_map ->
Map.put(balance_map, :block_number, 0)
end)
|> Enum.to_list()
json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
{:ok, %Blocks{blocks_params: [%{timestamp: timestamp}]}} =
EthereumJSONRPC.fetch_blocks_by_range(1..1, json_rpc_named_arguments)
day = DateTime.to_date(timestamp)
balance_daily_params =
chain_spec
|> genesis_accounts()
|> Stream.map(fn balance_map ->
Map.put(balance_map, :day, day)
end)
|> Enum.to_list()
address_params =
balance_params
|> Stream.map(fn %{address_hash: hash} = map ->
Map.put(map, :hash, hash)
end)
|> Enum.to_list()
params = %{
address_coin_balances: %{params: balance_params},
address_coin_balances_daily: %{params: balance_daily_params},
addresses: %{params: address_params}
}
Chain.import(params)
end
def genesis_accounts(chain_spec) do
accounts = chain_spec["alloc"]
if accounts do
parse_accounts(accounts)
else
Logger.warn(fn -> "No accounts are defined in genesis" end)
[]
end
end
defp parse_accounts(accounts) do
accounts
|> Stream.filter(fn {_address, map} ->
!is_nil(map["balance"])
end)
|> Stream.map(fn {address, %{"balance" => value} = params} ->
formatted_address = if String.starts_with?(address, "0x"), do: address, else: "0x" <> address
{:ok, address_hash} = AddressHash.cast(formatted_address)
balance = parse_number(value)
code = params["code"]
%{address_hash: address_hash, value: balance, contract_code: code}
end)
|> Enum.to_list()
end
defp parse_number("0x" <> hex_number) do
{number, ""} = Integer.parse(hex_number, 16)
number
end
defp parse_number(string_number) do
{number, ""} = Integer.parse(string_number, 10)
number
end
end

@ -1,6 +1,7 @@
# credo:disable-for-this-file
defmodule Explorer.ChainSpec.Parity.Importer do defmodule Explorer.ChainSpec.Parity.Importer do
@moduledoc """ @moduledoc """
Imports data from parity chain spec. Imports data from Parity/Open Ethereum chain spec.
""" """
require Logger require Logger

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save