diff --git a/CHANGELOG.md b/CHANGELOG.md index cd6b87c7c0..43c47348b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,16 @@ ## Current ### Features +- [#2499](https://github.com/poanetwork/blockscout/pull/2499) - import emission reward ranges +- [#2497](https://github.com/poanetwork/blockscout/pull/2497) - Add generic Ordered Cache behaviour and implementation ### Fixes +- [#2570](https://github.com/poanetwork/blockscout/pull/2570) - Network icons preload +- [#2569](https://github.com/poanetwork/blockscout/pull/2569) - do not fetch emission rewards for transactions csv exporter - [#2568](https://github.com/poanetwork/blockscout/pull/2568) - filter pending token transfers - [#2564](https://github.com/poanetwork/blockscout/pull/2564) - fix first page button for uncles and reorgs - [#2563](https://github.com/poanetwork/blockscout/pull/2563) - Fix view less transfers button +- [#2538](https://github.com/poanetwork/blockscout/pull/2538) - fetch the last not empty coin balance records ### Chore - [#2566](https://github.com/poanetwork/blockscout/pull/2566) - upgrade absinthe phoenix diff --git a/apps/block_scout_web/assets/css/_images-preload.scss b/apps/block_scout_web/assets/css/_images-preload.scss new file mode 100644 index 0000000000..ee25dbd966 --- /dev/null +++ b/apps/block_scout_web/assets/css/_images-preload.scss @@ -0,0 +1,14 @@ +body:after { + position:absolute; width:0; height:0; overflow:hidden; z-index:-1; + content: + url(/images/network-selector-icons/callisto-mainnet.png) + url(/images/network-selector-icons/ethereum-classic.png) + url(/images/network-selector-icons/goerli-testnet.png) + url(/images/network-selector-icons/kovan-testnet.png) + url(/images/network-selector-icons/poa-core.png) + url(/images/network-selector-icons/poa-sokol.png) + url(/images/network-selector-icons/rinkeby-testnet.png) + url(/images/network-selector-icons/rsk-mainnet.png) + url(/images/network-selector-icons/ropsten-testnet.png) + url(/images/network-selector-icons/xdai-chain.png) +}; \ No newline at end of file diff --git a/apps/block_scout_web/assets/css/app.scss b/apps/block_scout_web/assets/css/app.scss index 4bc13bd0bc..508bb5335b 100644 --- a/apps/block_scout_web/assets/css/app.scss +++ b/apps/block_scout_web/assets/css/app.scss @@ -60,6 +60,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts"; // Custom SCSS @import "layout"; @import "typography"; +@import "images-preload"; @import "code"; @import "helpers"; @import "elements"; diff --git a/apps/block_scout_web/assets/css/components/_network-selector.scss b/apps/block_scout_web/assets/css/components/_network-selector.scss index e8b5f72e78..65e5437641 100644 --- a/apps/block_scout_web/assets/css/components/_network-selector.scss +++ b/apps/block_scout_web/assets/css/components/_network-selector.scss @@ -243,6 +243,37 @@ $network-selector-item-icon-dimensions: 30px !default; height: $network-selector-item-icon-dimensions; margin: 0 15px 0 0; width: $network-selector-item-icon-dimensions; + + &-callisto-mainnet { + background-image: url(/images/network-selector-icons/callisto-mainnet.png) + } + &-ethereum-classic { + background-image: url(/images/network-selector-icons/ethereum-classic.png) + } + &-goerli-testnet { + background-image: url(/images/network-selector-icons/goerli-testnet.png) + } + &-kovan-testnet { + background-image: url(/images/network-selector-icons/kovan-testnet.png) + } + &-poa-core { + background-image: url(/images/network-selector-icons/poa-core.png) + } + &-poa-sokol { + background-image: url(/images/network-selector-icons/poa-sokol.png) + } + &-rinkeby-testnet { + background-image: url(/images/network-selector-icons/rinkeby-testnet.png) + } + &-rsk-mainnet { + background-image: url(/images/network-selector-icons/rsk-mainnet.png) + } + &-ropsten-testnet { + background-image: url(/images/network-selector-icons/ropsten-testnet.png) + } + &-xdai-chain { + background-image: url(/images/network-selector-icons/xdai-chain.png) + } } .network-selector-item-title { diff --git a/apps/block_scout_web/assets/js/lib/coin_balance_history_chart.js b/apps/block_scout_web/assets/js/lib/coin_balance_history_chart.js index ec41d57a4e..db84586c6b 100644 --- a/apps/block_scout_web/assets/js/lib/coin_balance_history_chart.js +++ b/apps/block_scout_web/assets/js/lib/coin_balance_history_chart.js @@ -18,6 +18,14 @@ export function createCoinBalanceHistoryChart (el) { y: balance.value })) + var stepSize = 3 + + if (data.length > 1) { + var diff = Math.abs(new Date(data[data.length - 1].date) - new Date(data[data.length - 2].date)) + var periodInDays = diff / (1000 * 60 * 60 * 24) + + stepSize = periodInDays + } return new Chart(el, { type: 'line', data: { @@ -36,7 +44,7 @@ export function createCoinBalanceHistoryChart (el) { type: 'time', time: { unit: 'day', - stepSize: 3 + stepSize: stepSize } }], yAxes: [{ diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_network_selector_item.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_network_selector_item.html.eex index 55ea7a6023..74ab4ed7ba 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_network_selector_item.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_network_selector_item.html.eex @@ -5,7 +5,7 @@ - .png');"> + <%= @title %> diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs index 19099b8db5..54197c5866 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs @@ -4,8 +4,8 @@ defmodule BlockScoutWeb.API.V1.HealthControllerTest do alias Explorer.{Chain, PagingOptions} setup do - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) :ok end diff --git a/apps/block_scout_web/test/support/conn_case.ex b/apps/block_scout_web/test/support/conn_case.ex index 3c7aef4e82..4ab8f3bcd9 100644 --- a/apps/block_scout_web/test/support/conn_case.ex +++ b/apps/block_scout_web/test/support/conn_case.ex @@ -40,8 +40,8 @@ defmodule BlockScoutWeb.ConnCase do Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()}) end - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) {:ok, conn: Phoenix.ConnTest.build_conn()} end diff --git a/apps/block_scout_web/test/support/feature_case.ex b/apps/block_scout_web/test/support/feature_case.ex index a9476a7b85..cdacd547bf 100644 --- a/apps/block_scout_web/test/support/feature_case.ex +++ b/apps/block_scout_web/test/support/feature_case.ex @@ -27,8 +27,8 @@ defmodule BlockScoutWeb.FeatureCase do Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()}) end - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) metadata = Phoenix.Ecto.SQL.Sandbox.metadata_for(Explorer.Repo, self()) {:ok, session} = Wallaby.start_session(metadata: metadata) diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index 1ceed7c387..95c80ba445 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -27,6 +27,8 @@ config :explorer, Explorer.Counters.AverageBlockTime, enabled: true, period: average_block_period +config :explorer, Explorer.ChainSpec.GenesisData, enabled: true, chain_spec_path: System.get_env("CHAIN_SPEC_PATH") + config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: true config :explorer, Explorer.ExchangeRates.Source.CoinMarketCap, diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index c1fb19f600..c28469c340 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -37,17 +37,18 @@ defmodule Explorer.Application do Explorer.Repo, Supervisor.Spec.worker(SpandexDatadog.ApiServer, [datadog_opts()]), Supervisor.child_spec({Task.Supervisor, name: Explorer.MarketTaskSupervisor}, id: Explorer.MarketTaskSupervisor), + Supervisor.child_spec({Task.Supervisor, name: Explorer.GenesisDataTaskSupervisor}, id: GenesisDataTaskSupervisor), Supervisor.child_spec({Task.Supervisor, name: Explorer.TaskSupervisor}, id: Explorer.TaskSupervisor), Explorer.SmartContract.SolcDownloader, {Registry, keys: :duplicate, name: Registry.ChainEvents, id: Registry.ChainEvents}, {Admin.Recovery, [[], [name: Admin.Recovery]]}, {TransactionCount, [[], []]}, {BlockCount, []}, - con_cache_child_spec(Blocks.cache_name()), + Blocks, con_cache_child_spec(NetVersion.cache_name()), con_cache_child_spec(MarketHistoryCache.cache_name()), con_cache_child_spec(RSK.cache_name(), ttl_check_interval: :timer.minutes(1), global_ttl: :timer.minutes(30)), - con_cache_child_spec(Transactions.cache_name()) + Transactions ] children = base_children ++ configurable_children() @@ -64,6 +65,7 @@ defmodule Explorer.Application do defp configurable_children do [ configure(Explorer.ExchangeRates), + configure(Explorer.ChainSpec.GenesisData), configure(Explorer.KnownTokens), configure(Explorer.Market.History.Cataloger), configure(Explorer.Counters.AddressesWithBalanceCounter), diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index e6ffcbd9c5..58253c0f27 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -248,7 +248,7 @@ defmodule Explorer.Chain do end end - defp address_to_transactions_without_rewards(address_hash, paging_options, options) do + def address_to_transactions_without_rewards(address_hash, paging_options, options) do direction = Keyword.get(options, :direction) necessity_by_association = Keyword.get(options, :necessity_by_association, %{}) @@ -1258,14 +1258,16 @@ defmodule Explorer.Chain do block_type = Keyword.get(options, :block_type, "Block") if block_type == "Block" && !paging_options.key do - if Blocks.enough_elements?(paging_options.page_size) do - Blocks.blocks(paging_options.page_size) - else - elements = fetch_blocks(block_type, paging_options, necessity_by_association) + case Blocks.take_enough(paging_options.page_size) do + nil -> + elements = fetch_blocks(block_type, paging_options, necessity_by_association) + + Blocks.update(elements) - Blocks.rewrite_cache(elements) + elements - elements + blocks -> + blocks end else fetch_blocks(block_type, paging_options, necessity_by_association) @@ -2975,8 +2977,13 @@ defmodule Explorer.Chain do @spec address_to_balances_by_day(Hash.Address.t()) :: [balance_by_day] def address_to_balances_by_day(address_hash) do + latest_block_timestamp = + address_hash + |> CoinBalance.last_coin_balance_timestamp() + |> Repo.one() + address_hash - |> CoinBalance.balances_by_day() + |> CoinBalance.balances_by_day(latest_block_timestamp) |> Repo.all() |> normalize_balances_by_day() end @@ -2992,7 +2999,7 @@ defmodule Explorer.Chain do today = Date.to_string(NaiveDateTime.utc_now()) if Enum.count(result) > 0 && !Enum.any?(result, fn map -> map[:date] == today end) do - [%{date: today, value: List.last(result)[:value]} | result] + List.flatten([result | [%{date: today, value: List.last(result)[:value]}]]) else result end diff --git a/apps/explorer/lib/explorer/chain/address/coin_balance.ex b/apps/explorer/lib/explorer/chain/address/coin_balance.ex index af12491247..537f6a0483 100644 --- a/apps/explorer/lib/explorer/chain/address/coin_balance.ex +++ b/apps/explorer/lib/explorer/chain/address/coin_balance.ex @@ -75,7 +75,7 @@ defmodule Explorer.Chain.Address.CoinBalance do from( cb in CoinBalance, where: cb.address_hash == ^address_hash, - where: cb.value > ^0, + where: not is_nil(cb.value), inner_join: b in Block, on: cb.block_number == b.number, order_by: [desc: :block_number], @@ -89,16 +89,32 @@ defmodule Explorer.Chain.Address.CoinBalance do Builds an `Ecto.Query` to fetch a series of balances by day for the given account. Each element in the series corresponds to the maximum balance in that day. Only the last 90 days of data are used. """ - def balances_by_day(address_hash) do + def balances_by_day(address_hash, block_timestamp \\ nil) do CoinBalance |> join(:inner, [cb], b in Block, on: cb.block_number == b.number) |> where([cb], cb.address_hash == ^address_hash) - |> where([cb, b], b.timestamp >= fragment("date_trunc('day', now()) - interval '90 days'")) + |> limit_time_interval(block_timestamp) |> group_by([cb, b], fragment("date_trunc('day', ?)", b.timestamp)) |> order_by([cb, b], fragment("date_trunc('day', ?)", b.timestamp)) |> select([cb, b], %{date: type(fragment("date_trunc('day', ?)", b.timestamp), :date), value: max(cb.value)}) end + def limit_time_interval(query, nil) do + query |> where([cb, b], b.timestamp >= fragment("date_trunc('day', now()) - interval '90 days'")) + end + + def limit_time_interval(query, %{timestamp: timestamp}) do + query |> where([cb, b], b.timestamp >= fragment("(? AT TIME ZONE ?) - interval '90 days'", ^timestamp, ^"Etc/UTC")) + end + + def last_coin_balance_timestamp(address_hash) do + CoinBalance + |> join(:inner, [cb], b in Block, on: cb.block_number == b.number) + |> where([cb], cb.address_hash == ^address_hash) + |> last(:block_number) + |> select([cb, b], %{timestamp: b.timestamp}) + end + def changeset(%__MODULE__{} = balance, params) do balance |> cast(params, @allowed_fields) diff --git a/apps/explorer/lib/explorer/chain/address_transaction_csv_exporter.ex b/apps/explorer/lib/explorer/chain/address_transaction_csv_exporter.ex index 64df1c7e59..0196de3bc0 100644 --- a/apps/explorer/lib/explorer/chain/address_transaction_csv_exporter.ex +++ b/apps/explorer/lib/explorer/chain/address_transaction_csv_exporter.ex @@ -42,9 +42,8 @@ defmodule Explorer.Chain.AddressTransactionCsvExporter do end defp fetch_all_transactions(address_hash, paging_options, acc \\ []) do - options = Keyword.merge(@necessity_by_association, paging_options: paging_options) - - transactions = Chain.address_to_transactions_with_rewards(address_hash, options) + transactions = + Chain.address_to_transactions_without_rewards(address_hash, paging_options, @necessity_by_association) new_acc = transactions ++ acc diff --git a/apps/explorer/lib/explorer/chain/block/emission_reward.ex b/apps/explorer/lib/explorer/chain/block/emission_reward.ex index 82ab015ac9..a6c3713fcc 100644 --- a/apps/explorer/lib/explorer/chain/block/emission_reward.ex +++ b/apps/explorer/lib/explorer/chain/block/emission_reward.ex @@ -3,7 +3,7 @@ defmodule Explorer.Chain.Block.EmissionReward do Represents the static reward given to the miner of a block in a range of block numbers. """ - use Ecto.Schema + use Explorer.Schema alias Explorer.Chain.Block.{EmissionReward, Range} alias Explorer.Chain.Wei @@ -24,4 +24,10 @@ defmodule Explorer.Chain.Block.EmissionReward do field(:block_range, Range) field(:reward, Wei) end + + def changeset(%__MODULE__{} = emission_reward, attrs) do + emission_reward + |> cast(attrs, [:block_range, :reward]) + |> validate_required([:block_range, :reward]) + end end diff --git a/apps/explorer/lib/explorer/chain/block/range.ex b/apps/explorer/lib/explorer/chain/block/range.ex index 26bf902142..c60cd2039d 100644 --- a/apps/explorer/lib/explorer/chain/block/range.ex +++ b/apps/explorer/lib/explorer/chain/block/range.ex @@ -136,10 +136,12 @@ defmodule Explorer.Chain.Block.Range do def load(_), do: :error + defp parse_upper(%PGRange{upper: :unbound}), do: :infinity defp parse_upper(%PGRange{upper: nil}), do: :infinity defp parse_upper(%PGRange{upper: upper, upper_inclusive: true}), do: upper defp parse_upper(%PGRange{upper: upper, upper_inclusive: false}), do: upper - 1 + defp parse_upper(%PGRange{lower: :unbound}), do: :negative_infinity defp parse_lower(%PGRange{lower: nil}), do: :negative_infinity defp parse_lower(%PGRange{lower: lower, lower_inclusive: true}), do: lower defp parse_lower(%PGRange{lower: lower, lower_inclusive: false}), do: lower + 1 diff --git a/apps/explorer/lib/explorer/chain/cache/blocks.ex b/apps/explorer/lib/explorer/chain/cache/blocks.ex index 76fc2473a6..4a18646d37 100644 --- a/apps/explorer/lib/explorer/chain/cache/blocks.ex +++ b/apps/explorer/lib/explorer/chain/cache/blocks.ex @@ -3,87 +3,19 @@ defmodule Explorer.Chain.Cache.Blocks do Caches the last imported blocks """ - alias Explorer.Repo + alias Explorer.Chain.Block - @block_numbers_key "block_numbers" - @cache_name :blocks - @number_of_elements 60 + use Explorer.Chain.OrderedCache, + name: :blocks, + max_size: 60, + ids_list_key: "block_numbers", + preload: :transactions, + preload: [miner: :names], + preload: :rewards - def update(block) do - numbers = block_numbers() + @type element :: Block.t() - max_number = if numbers == [], do: -1, else: Enum.max(numbers) - min_number = if numbers == [], do: -1, else: Enum.min(numbers) + @type id :: non_neg_integer() - in_range? = block.number > min_number && Enum.all?(numbers, fn number -> number != block.number end) - not_too_far_away? = block.number > max_number - @number_of_elements - 1 - - if (block.number > max_number || Enum.count(numbers) == 1 || in_range?) && not_too_far_away? do - if Enum.count(numbers) >= @number_of_elements do - remove_block(numbers) - put_block(block, List.delete(numbers, Enum.min(numbers))) - else - put_block(block, numbers) - end - end - end - - def rewrite_cache(elements) do - numbers = block_numbers() - - ConCache.delete(@cache_name, @block_numbers_key) - - numbers - |> Enum.each(fn number -> - ConCache.delete(@cache_name, number) - end) - - elements - |> Enum.reduce([], fn element, acc -> - put_block(element, acc) - - [element.number | acc] - end) - end - - def enough_elements?(number) do - ConCache.size(@cache_name) > number - end - - def update_blocks(blocks) do - Enum.each(blocks, fn block -> - update(block) - end) - end - - def blocks(number \\ nil) do - numbers = block_numbers() - - number = if is_nil(number), do: Enum.count(numbers), else: number - - numbers - |> Enum.sort() - |> Enum.reverse() - |> Enum.slice(0, number) - |> Enum.map(fn number -> - ConCache.get(@cache_name, number) - end) - end - - def cache_name, do: @cache_name - - def block_numbers do - ConCache.get(@cache_name, @block_numbers_key) || [] - end - - defp remove_block(numbers) do - min_number = Enum.min(numbers) - ConCache.delete(@cache_name, min_number) - end - - defp put_block(block, numbers) do - block_with_preloads = Repo.preload(block, [:transactions, [miner: :names], :rewards]) - ConCache.put(@cache_name, block.number, block_with_preloads) - ConCache.put(@cache_name, @block_numbers_key, [block.number | numbers]) - end + def element_to_id(%Block{number: number}), do: number end diff --git a/apps/explorer/lib/explorer/chain/cache/transactions.ex b/apps/explorer/lib/explorer/chain/cache/transactions.ex index 54748258cf..7dee7ec87d 100644 --- a/apps/explorer/lib/explorer/chain/cache/transactions.ex +++ b/apps/explorer/lib/explorer/chain/cache/transactions.ex @@ -4,140 +4,25 @@ defmodule Explorer.Chain.Cache.Transactions do """ alias Explorer.Chain.Transaction - alias Explorer.Repo - @transactions_ids_key "transactions_ids" - @cache_name :transactions - @max_size 51 - @preloads [ - :block, - created_contract_address: :names, - from_address: :names, - to_address: :names, - token_transfers: :token, - token_transfers: :from_address, - token_transfers: :to_address - ] - - @spec cache_name :: atom() - def cache_name, do: @cache_name - - @doc """ - Fetches a transaction from its id ({block_number, index}), returns nil if not found - """ - @spec get({non_neg_integer(), non_neg_integer()}) :: Transaction.t() | nil - def get(id), do: ConCache.get(@cache_name, id) - - @doc """ - Return the current number of transactions stored - """ - @spec size :: non_neg_integer() - def size, do: Enum.count(transactions_ids()) - - @doc """ - Checks if there are enough transactions stored - """ - @spec enough?(non_neg_integer()) :: boolean() - def enough?(amount) do - amount <= size() - end - - @doc """ - Checks if the number of transactions stored is already the max allowed - """ - @spec full? :: boolean() - def full? do - @max_size <= size() - end - - @doc "Returns the list ids of the transactions currently stored" - @spec transactions_ids :: [{non_neg_integer(), non_neg_integer()}] - def transactions_ids do - ConCache.get(@cache_name, @transactions_ids_key) || [] - end - - @doc "Returns all the stored transactions" - @spec all :: [Transaction.t()] - def all, do: Enum.map(transactions_ids(), &get(&1)) - - @doc "Returns the `n` most recent transactions stored" - @spec take(integer()) :: [Transaction.t()] - def take(amount) do - transactions_ids() - |> Enum.take(amount) - |> Enum.map(&get(&1)) - end - - @doc """ - Returns the `n` most recent transactions, unless there are not as many stored, - in which case returns `nil` - """ - @spec take_enough(integer()) :: [Transaction.t()] | nil - def take_enough(amount) do - if enough?(amount), do: take(amount) - end - - @doc """ - Adds a transaction (or a list of transactions). - If the cache is already full, the transaction will be only stored if it can take - the place of a less recent one. - NOTE: each transaction is inserted atomically - """ - @spec update([Transaction.t()] | Transaction.t() | nil) :: :ok - def update(transactions) when is_nil(transactions), do: :ok - - def update(transactions) when is_list(transactions) do - Enum.map(transactions, &update(&1)) - end - - def update(transaction) do - ConCache.isolated(@cache_name, @transactions_ids_key, fn -> - transaction_id = {transaction.block_number, transaction.index} - ids = transactions_ids() - - if full?() do - {init, [min]} = Enum.split(ids, -1) - - cond do - transaction_id < min -> - :ok - - transaction_id > min -> - insert_transaction(transaction_id, transaction, init) - ConCache.delete(@cache_name, min) - - transaction_id == min -> - put_transaction(transaction_id, transaction) - end - else - insert_transaction(transaction_id, transaction, ids) - end - end) - end - - defp insert_transaction(transaction_id, transaction, ids) do - put_transaction(transaction_id, transaction) - - ConCache.put(@cache_name, @transactions_ids_key, insert_sorted(transaction_id, ids)) - end - - defp put_transaction(transaction_id, transaction) do - full_transaction = Repo.preload(transaction, @preloads) - - ConCache.put(@cache_name, transaction_id, full_transaction) - end - - defp insert_sorted(id, ids) do - case ids do - [] -> - [id] - - [head | tail] -> - cond do - head > id -> [head | insert_sorted(id, tail)] - head < id -> [id | ids] - head == id -> ids - end - end + use Explorer.Chain.OrderedCache, + name: :transactions, + max_size: 51, + preloads: [ + :block, + created_contract_address: :names, + from_address: :names, + to_address: :names, + token_transfers: :token, + token_transfers: :from_address, + token_transfers: :to_address + ] + + @type element :: Transaction.t() + + @type id :: {non_neg_integer(), non_neg_integer()} + + def element_to_id(%Transaction{block_number: block_number, index: index}) do + {block_number, index} end end diff --git a/apps/explorer/lib/explorer/chain/ordered_cache.ex b/apps/explorer/lib/explorer/chain/ordered_cache.ex new file mode 100644 index 0000000000..2a1c0fc689 --- /dev/null +++ b/apps/explorer/lib/explorer/chain/ordered_cache.ex @@ -0,0 +1,326 @@ +defmodule Explorer.Chain.OrderedCache do + @moduledoc """ + Behaviour for a cache of ordered elements. + + A macro based on `ConCache` is provided as well, at its minimum it can be used as; + ``` + use Explorer.Chain.OrderedCache, name + ``` + where `name is an `t:atom/0` identifying the cache. + + All default values can be modified by overriding their respective function or + by setting an option. For example (showing all of them): + ``` + use Explorer.Chain.OrderedCache, + name: :name, # need to be set + max_size: 51, # defaults to 100 + ids_list_key: :ids_key, # defaults to `name` + preloads: [] # defaults to [] + ``` + Note: `preloads` can also be set singularly with the option `preload`, e.g.: + ``` + use Explorer.Chain.OrderedCache, + name: :cache + preload: :block + preload: :address + preload: [transaction: :hash] + ``` + Additionally all of the options accepted by `ConCache.start_link/1` can be + provided as well. By default only `ttl_check_interval:` is set (to `false`). + + It's also possible, and advised, to override the implementation of the `c:prevails?/2` + and `c:element_to_id/1` callbacks. + For typechecking purposes it's also recommended to override the `t:element/0` + and `t:id/0` type definitions. + """ + + @type element :: struct() + + @type id :: term() + + @doc """ + An atom that identifies this cache + """ + @callback cache_name :: atom() + + @doc """ + The key used to store the (ordered) list of elements. + Because this list is stored in the cache itself, one needs to make sure it is + cannot be equal to any element id. + """ + @callback ids_list_key :: term() + + @doc """ + The size that this cache cannot exceed. + """ + @callback max_size :: non_neg_integer() + + @doc """ + Fields of the stored elements that need to be preloaded. + For entities that are not stored in `Explorer.Repo` this should be empty. + """ + @callback preloads :: [term()] + + @doc """ + The function that orders the elements and decides the ones that are stored. + `prevails?(id_a, id_b)` should return `true` if (in case there is no space for both) + the element with `id_a` should be stored instead of the element with `id_b`, + `false` otherwise. + """ + @callback prevails?(id, id) :: boolean() + + @doc """ + The function that obtains an unique `t:id/0` from an `t:element/0` + """ + @callback element_to_id(element()) :: id() + + @doc "Returns the list ids of the elements currently stored" + @callback ids_list :: [id] + + @doc """ + Fetches a element from its id, returns nil if not found + """ + @callback get(id) :: element | nil + + @doc """ + Return the current number of elements stored + """ + @callback size() :: non_neg_integer() + + @doc """ + Checks if there are enough elements stored + """ + @callback enough?(non_neg_integer()) :: boolean() + + @doc """ + Checks if the number of elements stored is already the max allowed + """ + @callback full? :: boolean() + + @doc "Returns all the stored elements" + @callback all :: [element] + + @doc "Returns the `n` most prevailing elements stored, based on `c:prevails?/2`" + @callback take(integer()) :: [element] + + @doc """ + Returns the `n` most prevailing elements, based on `c:prevails?/2`, unless there + are not as many stored, in which case it returns `nil` + """ + @callback take_enough(integer()) :: [element] | nil + + @doc """ + Adds an element, or a list of elements, to the cache. + When the cache is full, only the most prevailing elements will be stored, based + on `c:prevails?/2`. + NOTE: every update is isolated from another one. + """ + @callback update([element] | element | nil) :: :ok + + defmacro __using__(name) when is_atom(name), do: do_using(name, []) + + defmacro __using__(opts) when is_list(opts) do + # name is necessary + name = Keyword.fetch!(opts, :name) + do_using(name, opts) + end + + # credo:disable-for-next-line /Complexity/ + defp do_using(name, opts) when is_atom(name) and is_list(opts) do + ids_list_key = Keyword.get(opts, :ids_list_key, name) + max_size = Keyword.get(opts, :max_size, 100) + preloads = Keyword.get(opts, :preloads) || Keyword.get_values(opts, :preload) + + concache_params = + opts + |> Keyword.drop([:ids_list_key, :max_size, :preloads, :preload]) + |> Keyword.put_new(:ttl_check_interval, false) + + # credo:disable-for-next-line Credo.Check.Refactor.LongQuoteBlocks + quote do + alias Explorer.Chain.OrderedCache + + @behaviour OrderedCache + + ### Automatically set functions + + @impl OrderedCache + def cache_name, do: unquote(name) + + @impl OrderedCache + def ids_list_key, do: unquote(ids_list_key) + + @impl OrderedCache + def max_size, do: unquote(max_size) + + @impl OrderedCache + def preloads, do: unquote(preloads) + + ### Settable functions + + @impl OrderedCache + def prevails?(id_a, id_b), do: id_a > id_b + + @impl OrderedCache + def element_to_id(element), do: element + + ### Straightforward fetching functions + + @impl OrderedCache + def ids_list, do: ConCache.get(cache_name(), ids_list_key()) || [] + + @impl OrderedCache + def get(id), do: ConCache.get(cache_name(), id) + + @impl OrderedCache + def size, do: ids_list() |> Enum.count() + + @impl OrderedCache + def enough?(amount), do: amount <= size() + + @impl OrderedCache + def full?, do: max_size() <= size() + + @impl OrderedCache + def all, do: Enum.map(ids_list(), &get(&1)) + + @impl OrderedCache + def take(amount) do + ids_list() + |> Enum.take(amount) + |> Enum.map(&get(&1)) + end + + @impl OrderedCache + def take_enough(amount) do + # behaves just like `if enough?(amount), do: take(amount)` but fetching + # the list only once + ids = ids_list() + + if amount <= Enum.count(ids) do + ids + |> Enum.take(amount) + |> Enum.map(&get(&1)) + end + end + + ### Updating function + + @impl OrderedCache + def update(elements) when is_nil(elements), do: :ok + + def update(elements) when is_list(elements) do + ConCache.update(cache_name(), ids_list_key(), fn ids -> + updated_list = + elements + |> Enum.map(&{element_to_id(&1), &1}) + |> Enum.sort(&prevails?(&1, &2)) + |> merge_and_update(ids || [], max_size()) + + {:ok, updated_list} + end) + end + + def update(element), do: update([element]) + + defp merge_and_update(_candidates, existing, 0) do + # if there is no more space in the list remove the remaining existing + # elements and return an empty list + remove(existing) + [] + end + + defp merge_and_update([], existing, size) do + # if there are no more candidates to be inserted keep as many of the + # exsisting elements and remove the rest + {remaining, to_remove} = Enum.split(existing, size) + remove(to_remove) + remaining + end + + defp merge_and_update(candidates, [], size) do + # if there are still candidates and no more existing value insert as many + # candidates as possible and ignore the rest + candidates + |> Enum.take(size) + |> Enum.map(fn {element_id, element} -> + put_element(element_id, element) + element_id + end) + end + + defp merge_and_update(candidates, existing, size) do + [{candidate_id, candidate} | to_check] = candidates + [head | tail] = existing + + cond do + head == candidate_id -> + # if a candidate has the id of and existing element, update its value + put_element(candidate_id, candidate) + [head | merge_and_update(to_check, tail, size - 1)] + + prevails?(head, candidate_id) -> + # keep the prevaling existing value and compare all candidates against the rest + [head | merge_and_update(candidates, tail, size - 1)] + + true -> + # insert new prevailing candidate and compare the remaining ones with the rest + put_element(candidate_id, candidate) + [candidate_id | merge_and_update(to_check, existing, size - 1)] + end + end + + defp remove(key) do + # Always performs async removal so it can wait 1/10 of a second and + # others have the time to get elements that were in the cache's list. + # Different updates cannot interfere with the removed element because + # if this was scheduled for removal it means it is too old, so following + # updates cannot insert it in the future. + Task.start(fn -> + Process.sleep(100) + + if is_list(key) do + Enum.map(key, &ConCache.delete(cache_name(), &1)) + else + ConCache.delete(cache_name(), key) + end + end) + end + + defp put_element(element_id, element) do + full_element = + if Enum.empty?(preloads()) do + element + else + Explorer.Repo.preload(element, preloads()) + end + + # dirty puts are a little faster than puts with locks. + # this is not a problem because this is the only function modifying rows + # and it only gets called inside `update`, which works isolated + ConCache.dirty_put(cache_name(), element_id, full_element) + end + + ### Supervisor's child specification + + @doc """ + The child specification for a Supervisor. Note that all the `params` + provided to this function will override the ones set by using the macro + """ + def child_spec(params) do + params = Keyword.merge(unquote(concache_params), params) + + Supervisor.child_spec({ConCache, params}, id: child_id()) + end + + def child_id, do: {ConCache, cache_name()} + + defoverridable cache_name: 0, + ids_list_key: 0, + max_size: 0, + preloads: 0, + prevails?: 2, + element_to_id: 1 + end + end +end diff --git a/apps/explorer/lib/explorer/chain_spec/genesis_data.ex b/apps/explorer/lib/explorer/chain_spec/genesis_data.ex new file mode 100644 index 0000000000..a156aae6d7 --- /dev/null +++ b/apps/explorer/lib/explorer/chain_spec/genesis_data.ex @@ -0,0 +1,108 @@ +defmodule Explorer.ChainSpec.GenesisData do + @moduledoc """ + Fetches genesis data. + """ + + use GenServer + + require Logger + + alias Explorer.ChainSpec.Parity.Importer + alias HTTPoison.Response + + @interval :timer.minutes(2) + + def start_link(opts) do + GenServer.start_link(__MODULE__, opts, name: __MODULE__) + end + + @impl GenServer + def init(_) do + :timer.send_interval(@interval, :import) + Process.send_after(self(), :import, @interval) + + {:ok, %{}} + end + + # Callback for errored fetch + @impl GenServer + def handle_info({_ref, {:error, reason}}, state) do + Logger.warn(fn -> "Failed to fetch genesis data '#{reason}'." end) + + fetch_genesis_data() + + {:noreply, state} + end + + @impl GenServer + def handle_info(:import, state) do + Logger.debug(fn -> "Importing genesis data" end) + + fetch_genesis_data() + + {:noreply, state} + end + + # Callback that a monitored process has shutdown + @impl GenServer + def handle_info({:DOWN, _, :process, _, _}, state) do + {:noreply, state} + end + + # Callback for successful fetch + @impl GenServer + def handle_info({_ref, _}, state) do + {:noreply, state} + end + + def fetch_genesis_data do + path = Application.get_env(:explorer, __MODULE__)[:chain_spec_path] + + if path do + Task.Supervisor.async_nolink(Explorer.GenesisDataTaskSupervisor, fn -> + case fetch_spec(path) do + {:ok, chain_spec} -> + Importer.import_emission_rewards(chain_spec) + {:ok, _} = Importer.import_genesis_coin_balances(chain_spec) + + {:error, reason} -> + Logger.warn(fn -> "Failed to fetch genesis data. #{inspect(reason)}" end) + end + end) + else + Logger.warn(fn -> "Failed to fetch genesis data. Chain spec path is not set." end) + end + end + + defp fetch_spec(path) do + if valid_url?(path) do + fetch_from_url(path) + else + fetch_from_file(path) + end + end + + # sobelow_skip ["Traversal"] + defp fetch_from_file(path) do + with {:ok, data} <- File.read(path), + {:ok, json} <- Jason.decode(data) do + {:ok, json} + end + end + + defp fetch_from_url(url) do + case HTTPoison.get(url) do + {:ok, %Response{body: body, status_code: 200}} -> + {:ok, Jason.decode!(body)} + + reason -> + {:error, reason} + end + end + + defp valid_url?(string) do + uri = URI.parse(string) + + uri.scheme != nil && uri.host =~ "." + end +end diff --git a/apps/explorer/lib/explorer/chain_spec/parity/importer.ex b/apps/explorer/lib/explorer/chain_spec/parity/importer.ex new file mode 100644 index 0000000000..6b560bf530 --- /dev/null +++ b/apps/explorer/lib/explorer/chain_spec/parity/importer.ex @@ -0,0 +1,107 @@ +defmodule Explorer.ChainSpec.Parity.Importer do + @moduledoc """ + Imports data from parity chain spec. + """ + + alias Explorer.{Chain, Repo} + alias Explorer.Chain.Block.{EmissionReward, Range} + alias Explorer.Chain.Hash.Address, as: AddressHash + alias Explorer.Chain.Wei + + @max_block_number :infinity + + def import_emission_rewards(chain_spec) do + rewards = emission_rewards(chain_spec) + + {_, nil} = Repo.delete_all(EmissionReward) + {_, nil} = Repo.insert_all(EmissionReward, rewards) + end + + def import_genesis_coin_balances(chain_spec) do + balance_params = + chain_spec + |> genesis_coin_balances() + |> Stream.map(fn balance_map -> + Map.put(balance_map, :block_number, 0) + end) + |> Enum.to_list() + + address_params = + balance_params + |> Stream.map(fn %{address_hash: hash} -> + %{hash: hash} + end) + |> Enum.to_list() + + params = %{address_coin_balances: %{params: balance_params}, addresses: %{params: address_params}} + + Chain.import(params) + end + + def genesis_coin_balances(chain_spec) do + accounts = chain_spec["accounts"] + + parse_accounts(accounts) + end + + def emission_rewards(chain_spec) do + rewards = chain_spec["engine"]["Ethash"]["params"]["blockReward"] + + rewards + |> parse_hex_numbers() + |> format_ranges() + end + + defp parse_accounts(accounts) do + accounts + |> Stream.filter(fn {_address, map} -> + !is_nil(map["balance"]) + end) + |> Stream.map(fn {address, %{"balance" => value}} -> + {:ok, address_hash} = AddressHash.cast(address) + balance = parse_hex_number(value) + + %{address_hash: address_hash, value: balance} + end) + |> Enum.to_list() + end + + defp format_ranges(block_number_reward_pairs) do + block_number_reward_pairs + |> Enum.chunk_every(2, 1) + |> Enum.map(fn values -> + create_range(values) + end) + end + + defp create_range([{block_number1, reward}, {block_number2, _}]) do + block_number1 = if block_number1 != 0, do: block_number1 + 1, else: 0 + + %{ + block_range: %Range{from: block_number1, to: block_number2}, + reward: reward + } + end + + defp create_range([{block_number, reward}]) do + %{ + block_range: %Range{from: block_number + 1, to: @max_block_number}, + reward: reward + } + end + + defp parse_hex_numbers(rewards) do + Enum.map(rewards, fn {hex_block_number, hex_reward} -> + block_number = parse_hex_number(hex_block_number) + {:ok, reward} = hex_reward |> parse_hex_number() |> Wei.cast() + + {block_number, reward} + end) + end + + defp parse_hex_number("0x" <> hex_number) do + {number, ""} = Integer.parse(hex_number, 16) + + number + end +end diff --git a/apps/explorer/test/explorer/chain/address/coin_balance_test.exs b/apps/explorer/test/explorer/chain/address/coin_balance_test.exs index 87ed80a94c..171a2764c0 100644 --- a/apps/explorer/test/explorer/chain/address/coin_balance_test.exs +++ b/apps/explorer/test/explorer/chain/address/coin_balance_test.exs @@ -2,8 +2,8 @@ defmodule Explorer.Chain.Address.CoinBalanceTest do use Explorer.DataCase alias Ecto.Changeset - alias Explorer.Chain.{Block, Wei} alias Explorer.Chain.Address.CoinBalance + alias Explorer.Chain.{Block, Wei} alias Explorer.PagingOptions describe "changeset/2" do @@ -225,7 +225,7 @@ defmodule Explorer.Chain.Address.CoinBalanceTest do assert(length(result) == 1) - value = List.first(result) |> Map.get(:value) + value = result |> List.first() |> Map.get(:value) assert(value == Wei.from(Decimal.new(3000), :wei)) end @@ -247,7 +247,7 @@ defmodule Explorer.Chain.Address.CoinBalanceTest do assert(length(result) == 1) - value = List.first(result) |> Map.get(:value) + value = result |> List.first() |> Map.get(:value) assert(value == Wei.from(Decimal.new(3000), :wei)) end @@ -269,9 +269,33 @@ defmodule Explorer.Chain.Address.CoinBalanceTest do assert(length(result) == 1) - value = List.first(result) |> Map.get(:value) + value = result |> List.first() |> Map.get(:value) assert(value == Wei.from(Decimal.new(3000), :wei)) end + + test "fetches old records" do + address = insert(:address) + noon = Timex.now() |> Timex.beginning_of_day() |> Timex.set(hour: 12) + + old_block = insert(:block, timestamp: Timex.shift(noon, days: -700)) + insert(:fetched_balance, address_hash: address.hash, value: 2000, block_number: old_block.number) + + latest_block_timestamp = + address.hash + |> CoinBalance.last_coin_balance_timestamp() + |> Repo.one() + + result = + address.hash + |> CoinBalance.balances_by_day(latest_block_timestamp) + |> Repo.all() + + assert(length(result) == 1) + + value = result |> List.first() |> Map.get(:value) + + assert(value == Wei.from(Decimal.new(2000), :wei)) + end end end diff --git a/apps/explorer/test/explorer/chain/cache/blocks_test.exs b/apps/explorer/test/explorer/chain/cache/blocks_test.exs index 52ac4eabb4..87f887ae26 100644 --- a/apps/explorer/test/explorer/chain/cache/blocks_test.exs +++ b/apps/explorer/test/explorer/chain/cache/blocks_test.exs @@ -16,7 +16,7 @@ defmodule Explorer.Chain.Cache.BlocksTest do Blocks.update(block) - assert Blocks.blocks() == [block] + assert Blocks.all() == [block] end test "adds a new elements removing the oldest one" do @@ -30,22 +30,16 @@ defmodule Explorer.Chain.Cache.BlocksTest do block.number end) + assert Blocks.size() == 60 + new_block = insert(:block, number: 70) Blocks.update(new_block) new_blocks = blocks |> List.replace_at(0, new_block.number) |> Enum.sort() |> Enum.reverse() - assert Enum.map(Blocks.blocks(), & &1.number) == new_blocks - end - - test "does not add too old blocks" do - block = insert(:block, number: 100_000) |> Repo.preload([:transactions, [miner: :names], :rewards]) - old_block = insert(:block, number: 1_000) + assert Blocks.full?() - Blocks.update(block) - Blocks.update(old_block) - - assert Blocks.blocks() == [block] + assert Enum.map(Blocks.all(), & &1.number) == new_blocks end test "adds missing element" do @@ -55,30 +49,13 @@ defmodule Explorer.Chain.Cache.BlocksTest do Blocks.update(block1) Blocks.update(block2) - assert Enum.count(Blocks.blocks()) == 2 + assert Blocks.size() == 2 block3 = insert(:block, number: 6) Blocks.update(block3) - assert Enum.map(Blocks.blocks(), & &1.number) == [10, 6, 4] - end - end - - describe "rewrite_cache/1" do - test "updates cache" do - block = insert(:block) - - Blocks.update(block) - - block1 = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards]) - block2 = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards]) - - new_blocks = [block1, block2] - - Blocks.rewrite_cache(new_blocks) - - assert Blocks.blocks() == [block2, block1] + assert Enum.map(Blocks.all(), & &1.number) == [10, 6, 4] end end end diff --git a/apps/explorer/test/explorer/chain_spec/parity/importer_test.exs b/apps/explorer/test/explorer/chain_spec/parity/importer_test.exs new file mode 100644 index 0000000000..06b993f144 --- /dev/null +++ b/apps/explorer/test/explorer/chain_spec/parity/importer_test.exs @@ -0,0 +1,108 @@ +defmodule Explorer.ChainSpec.Parity.ImporterTest do + use Explorer.DataCase + + alias Explorer.Chain.Address.CoinBalance + alias Explorer.Chain.Block.{EmissionReward, Range} + alias Explorer.Chain.{Address, Hash, Wei} + alias Explorer.ChainSpec.Parity.Importer + alias Explorer.Repo + + @chain_spec "#{File.cwd!()}/test/support/fixture/chain_spec/foundation.json" + |> File.read!() + |> Jason.decode!() + + describe "emission_rewards/1" do + test "fetches and formats reward ranges" do + assert Importer.emission_rewards(@chain_spec) == [ + %{ + block_range: %Range{from: 0, to: 4_370_000}, + reward: %Wei{value: Decimal.new(5_000_000_000_000_000_000)} + }, + %{ + block_range: %Range{from: 4_370_001, to: 7_280_000}, + reward: %Wei{value: Decimal.new(3_000_000_000_000_000_000)} + }, + %{ + block_range: %Range{from: 7_280_001, to: :infinity}, + reward: %Wei{value: Decimal.new(2_000_000_000_000_000_000)} + } + ] + end + end + + describe "import_emission_rewards/1" do + test "inserts emission rewards from chain spec" do + assert {3, nil} = Importer.import_emission_rewards(@chain_spec) + end + + test "rewrites all recored" do + old_block_rewards = %{ + "0x0" => "0x1bc16d674ec80000", + "0x42ae50" => "0x29a2241af62c0000", + "0x6f1580" => "0x4563918244f40000" + } + + chain_spec = %{ + @chain_spec + | "engine" => %{ + @chain_spec["engine"] + | "Ethash" => %{ + @chain_spec["engine"]["Ethash"] + | "params" => %{@chain_spec["engine"]["Ethash"]["params"] | "blockReward" => old_block_rewards} + } + } + } + + assert {3, nil} = Importer.import_emission_rewards(chain_spec) + [first, second, third] = Repo.all(EmissionReward) + + assert first.reward == %Wei{value: Decimal.new(2_000_000_000_000_000_000)} + assert first.block_range == %Range{from: 0, to: 4_370_000} + + assert second.reward == %Wei{value: Decimal.new(3_000_000_000_000_000_000)} + assert second.block_range == %Range{from: 4_370_001, to: 7_280_000} + + assert third.reward == %Wei{value: Decimal.new(5_000_000_000_000_000_000)} + assert third.block_range == %Range{from: 7_280_001, to: :infinity} + + assert {3, nil} = Importer.import_emission_rewards(@chain_spec) + [new_first, new_second, new_third] = Repo.all(EmissionReward) + + assert new_first.reward == %Wei{value: Decimal.new(5_000_000_000_000_000_000)} + assert new_first.block_range == %Range{from: 0, to: 4_370_000} + + assert new_second.reward == %Wei{value: Decimal.new(3_000_000_000_000_000_000)} + assert new_second.block_range == %Range{from: 4_370_001, to: 7_280_000} + + assert new_third.reward == %Wei{value: Decimal.new(2_000_000_000_000_000_000)} + assert new_third.block_range == %Range{from: 7_280_001, to: :infinity} + end + end + + describe "genesis_coin_balances/1" do + test "parses coin balance" do + coin_balances = Importer.genesis_coin_balances(@chain_spec) + + assert Enum.count(coin_balances) == 403 + + assert %{ + address_hash: %Hash{ + byte_count: 20, + bytes: <<121, 174, 179, 69, 102, 185, 116, 195, 90, 88, 129, 222, 192, 32, 146, 125, 167, 223, 93, 37>> + }, + value: 2_000_000_000_000_000_000_000 + } == + List.first(coin_balances) + end + end + + describe "import_genesis_coin_balances/1" do + test "imports coin balances" do + {:ok, %{address_coin_balances: address_coin_balances}} = Importer.import_genesis_coin_balances(@chain_spec) + + assert Enum.count(address_coin_balances) == 403 + assert CoinBalance |> Repo.all() |> Enum.count() == 403 + assert Address |> Repo.all() |> Enum.count() == 403 + end + end +end diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index 234252dbe4..f49be6da4e 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -3896,8 +3896,8 @@ defmodule Explorer.ChainTest do balances = Chain.address_to_balances_by_day(address.hash) assert balances == [ - %{date: today |> NaiveDateTime.to_date() |> Date.to_string(), value: Decimal.new("1E-15")}, - %{date: yesterday |> NaiveDateTime.to_date() |> Date.to_string(), value: Decimal.new("1E-15")} + %{date: yesterday |> NaiveDateTime.to_date() |> Date.to_string(), value: Decimal.new("1E-15")}, + %{date: today |> NaiveDateTime.to_date() |> Date.to_string(), value: Decimal.new("1E-15")} ] end end diff --git a/apps/explorer/test/explorer/market/market_history_cache_test.exs b/apps/explorer/test/explorer/market/market_history_cache_test.exs index 6dbd15fe7f..1ce5ba16f1 100644 --- a/apps/explorer/test/explorer/market/market_history_cache_test.exs +++ b/apps/explorer/test/explorer/market/market_history_cache_test.exs @@ -9,8 +9,8 @@ defmodule Explorer.Market.MarketHistoryCacheTest do Supervisor.restart_child(Explorer.Supervisor, {ConCache, MarketHistoryCache.cache_name()}) on_exit(fn -> - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) end) :ok diff --git a/apps/explorer/test/explorer/market/market_test.exs b/apps/explorer/test/explorer/market/market_test.exs index 881e1dccc8..44342b3996 100644 --- a/apps/explorer/test/explorer/market/market_test.exs +++ b/apps/explorer/test/explorer/market/market_test.exs @@ -6,12 +6,12 @@ defmodule Explorer.MarketTest do alias Explorer.Repo setup do - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) on_exit(fn -> - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) end) :ok diff --git a/apps/explorer/test/support/data_case.ex b/apps/explorer/test/support/data_case.ex index e159891987..fa87839725 100644 --- a/apps/explorer/test/support/data_case.ex +++ b/apps/explorer/test/support/data_case.ex @@ -40,10 +40,10 @@ defmodule Explorer.DataCase do end Explorer.Chain.Cache.BlockNumber.setup() - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) :ok end diff --git a/apps/explorer/test/support/fixture/chain_spec/foundation.json b/apps/explorer/test/support/fixture/chain_spec/foundation.json new file mode 100644 index 0000000000..68c8414220 --- /dev/null +++ b/apps/explorer/test/support/fixture/chain_spec/foundation.json @@ -0,0 +1,1533 @@ +{ + "name": "Ethereum", + "dataDir": "ethereum", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x20000", + "difficultyBoundDivisor": "0x800", + "durationLimit": "0xd", + "blockReward": { + "0x0": "0x4563918244f40000", + "0x42ae50": "0x29a2241af62c0000", + "0x6f1580": "0x1bc16d674ec80000" + }, + "homesteadTransition": "0x118c30", + "daoHardforkTransition": "0x1d4c00", + "daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754", + "daoHardforkAccounts": [ + "0xd4fe7bc31cedb7bfb8a345f31e668033056b2728", + "0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425", + "0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f", + "0xecd135fa4f61a655311e86238c92adcd779555d2", + "0x1975bd06d486162d5dc297798dfc41edd5d160a7", + "0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6", + "0x319f70bab6845585f412ec7724b744fec6095c85", + "0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936", + "0x5c8536898fbb74fc7445814902fd08422eac56d0", + "0x6966ab0d485353095148a2155858910e0965b6f9", + "0x779543a0491a837ca36ce8c635d6154e3c4911a6", + "0x2a5ed960395e2a49b1c758cef4aa15213cfd874c", + "0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5", + "0x9c50426be05db97f5d64fc54bf89eff947f0a321", + "0x200450f06520bdd6c527622a273333384d870efb", + "0xbe8539bfe837b67d1282b2b1d61c3f723966f049", + "0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb", + "0xf1385fb24aad0cd7432824085e42aff90886fef5", + "0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091", + "0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd", + "0x51e0ddd9998364a2eb38588679f0d2c42653e4a6", + "0x627a0a960c079c21c34f7612d5d230e01b4ad4c7", + "0xf0b1aa0eb660754448a7937c022e30aa692fe0c5", + "0x24c4d950dfd4dd1902bbed3508144a54542bba94", + "0x9f27daea7aca0aa0446220b98d028715e3bc803d", + "0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90", + "0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b", + "0x63ed5a272de2f6d968408b4acb9024f4cc208ebf", + "0x6f6704e5a10332af6672e50b3d9754dc460dfa4d", + "0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6", + "0x492ea3bb0f3315521c31f273e565b868fc090f17", + "0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00", + "0x9ea779f907f0b315b364b0cfc39a0fde5b02a416", + "0xceaeb481747ca6c540a000c1f3641f8cef161fa7", + "0xcc34673c6c40e791051898567a1222daf90be287", + "0x579a80d909f346fbfb1189493f521d7f48d52238", + "0xe308bd1ac5fda103967359b2712dd89deffb7973", + "0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c", + "0xac1ecab32727358dba8962a0f3b261731aad9723", + "0x4fd6ace747f06ece9c49699c7cabc62d02211f75", + "0x440c59b325d2997a134c2c7c60a8c61611212bad", + "0x4486a3d68fac6967006d7a517b889fd3f98c102b", + "0x9c15b54878ba618f494b38f0ae7443db6af648ba", + "0x27b137a85656544b1ccb5a0f2e561a5703c6a68f", + "0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241", + "0x23b75c2f6791eef49c69684db4c6c1f93bf49a50", + "0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b", + "0xb9637156d330c0d605a791f1c31ba5890582fe1c", + "0x6131c42fa982e56929107413a9d526fd99405560", + "0x1591fc0f688c81fbeb17f5426a162a7024d430c2", + "0x542a9515200d14b68e934e9830d91645a980dd7a", + "0xc4bbd073882dd2add2424cf47d35213405b01324", + "0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4", + "0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb", + "0x3ba4d81db016dc2890c81f3acec2454bff5aada5", + "0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab", + "0xe4ae1efdfc53b73893af49113d8694a057b9c0d1", + "0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5", + "0x0737a6b837f97f46ebade41b9bc3e1c509c85c53", + "0x97f43a37f595ab5dd318fb46e7a155eae057317a", + "0x52c5317c848ba20c7504cb2c8052abd1fde29d03", + "0x4863226780fe7c0356454236d3b1c8792785748d", + "0x5d2b2e6fcbe3b11d26b525e085ff818dae332479", + "0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c", + "0x057b56736d32b86616a10f619859c6cd6f59092a", + "0x9aa008f65de0b923a2a4f02012ad034a5e2e2192", + "0x304a554a310c7e546dfe434669c62820b7d83490", + "0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79", + "0x4deb0033bb26bc534b197e61d19e0733e5679784", + "0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a", + "0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b", + "0x4fa802324e929786dbda3b8820dc7834e9134a2a", + "0x9da397b9e80755301a3b32173283a91c0ef6c87e", + "0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6", + "0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9", + "0x5dc28b15dffed94048d73806ce4b7a4612a1d48f", + "0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76", + "0x12e626b0eebfe86a56d633b9864e389b45dcb260", + "0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7", + "0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5", + "0xd164b088bd9108b60d0ca3751da4bceb207b0782", + "0x6231b6d0d5e77fe001c2a460bd9584fee60d409b", + "0x1cba23d343a983e9b5cfd19496b9a9701ada385f", + "0xa82f360a8d3455c5c41366975bde739c37bfeb8a", + "0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339", + "0x005f5cee7a43331d5a3d3eec71305925a62f34b6", + "0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d", + "0xd131637d5275fd1a68a3200f4ad25c71a2a9522e", + "0xbc07118b9ac290e4622f5e77a0853539789effbe", + "0x47e7aa56d6bdf3f36be34619660de61275420af8", + "0xacd87e28b0c9d1254e868b81cba4cc20d9a32225", + "0xadf80daec7ba8dcf15392f1ac611fff65d94f880", + "0x5524c55fb03cf21f549444ccbecb664d0acad706", + "0x40b803a9abce16f50f36a77ba41180eb90023925", + "0xfe24cdd8648121a43a7c86d289be4dd2951ed49f", + "0x17802f43a0137c506ba92291391a8a8f207f487d", + "0x253488078a4edf4d6f42f113d1e62836a942cf1a", + "0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915", + "0xb136707642a4ea12fb4bae820f03d2562ebff487", + "0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940", + "0xf14c14075d6c4ed84b86798af0956deef67365b5", + "0xca544e5c4687d109611d0f8f928b53a25af72448", + "0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c", + "0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7", + "0x6d87578288b6cb5549d5076a207456a1f6a63dc0", + "0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e", + "0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6", + "0x2b3455ec7fedf16e646268bf88846bd7a2319bb2", + "0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a", + "0xd343b217de44030afaa275f54d31a9317c7f441e", + "0x84ef4b2357079cd7a7c69fd7a37cd0609a679106", + "0xda2fef9e4a3230988ff17df2165440f37e8b1708", + "0xf4c64518ea10f995918a454158c6b61407ea345c", + "0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97", + "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", + "0x807640a13483f8ac783c557fcdf27be11ea4ac7a" + ], + "eip100bTransition": "0x42ae50", + "difficultyBombDelays": { + "0x42ae50": "0x2dc6c0", + "0x6f1580": "0x1e8480" + } + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x400", + "registrar": "0xe3389675d0338462dC76C6f9A3e432550c36A142", + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID": "0x1", + "forkBlock": "0x1d4c00", + "forkCanonHash": "0x4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb", + "eip150Transition": "0x259518", + "eip160Transition": "0x28d138", + "eip161abcTransition": "0x28d138", + "eip161dTransition": "0x28d138", + "eip155Transition": "0x28d138", + "maxCodeSize": "0x6000", + "maxCodeSizeTransition": "0x28d138", + "eip140Transition": "0x42ae50", + "eip211Transition": "0x42ae50", + "eip214Transition": "0x42ae50", + "eip658Transition": "0x42ae50", + "eip145Transition": "0x6f1580", + "eip1014Transition": "0x6f1580", + "eip1052Transition": "0x6f1580" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388", + "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" + }, + "hardcodedSync": { + "header": "f90212a0113ba3b1153987fc483b01ccfe9ecadbdc36a7b264be75d6486cb6b694cc38a1a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452bc44d5378309ee2abf1539bf71de1b7d7be3b5a0d91db5900e312a1ba8d39505406a95dc0ea20393b723c4bf488ade4e3c4ee4c3a05e63ab076852043b1c2fe010e2f14ab13dcc8e1c546ac497a24ce88c4abf3056a0b72e4a776f895459b6bf0937040990d868b1f45889aeaa26684e07472263fc31b90100b00200000063664554889124822ce2001022840543085d5810042382888542ca3816801780384384cd6851081cdc4d4b2b205a814b049198110a6869d60f4009a79c3854c9000581044889080000611c09142200106552000044027024004038092102814ed6c48040a8715851088a20108e80165f8c0c514019037a0000121304b2343416800b029000024404248238a06818414cb8690244879491855405026bc8250220520992c2380099d10024411c6048424083d1307822442d8444700405147883c4c041300aaa2408bb61084012983825a22830040a180106b5e27182088060b111515832902903a8f1d432a48004d0250437106a503491000048a91587067a897789f4d78371d801837a309c8379ffd7845c9d879e9150505945206e616e6f706f6f6c2e6f7267a0db22736cb3f06f9c86804902731fa6841eaaa1cd6326ea2a30e9c304d48bdd04880323b06837344cb8", + "totalDifficulty": "9633968582330911261986", + "CHTs": [ + "0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc", + "0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11", + "0x816e7463af7b5d2fcb804ba55f09e8452182b0ba6c995a34e144245d76333d55", + "0x3793af64c1ddc07ab61b2ba120034d91c02183ff788f07d3120fd4e6a48305b5", + "0x14c6106a17e041032210bfa0ca80d11860a1c6d95175d55eff39f97b8d8acded", + "0x396f832bfa3a9c494e9245471f0e65552613d87b6fe62128103590d95de72c2d", + "0xb060979f095c170a776b2b50a1e2ab0ffea80f6e522753fa36ad6f106ee32e9f", + "0x8f452e7cbd8a333ed04d819a143a8d3a75fe8c58418e7fc420bb2a717c0d4d2f", + "0xbae1427beab8c3e71cea57e5f9cdd55bc278c6d6073ae2628f0d3efbf9894a42", + "0x389bbd1b3fa390e8d3339cf5b018ec64d9cfc02bbcb801acad0857fe377ed83b" + ] + }, + "nodes": [ + "enode://81863f47e9bd652585d3f78b4b2ee07b93dad603fd9bc3c293e1244250725998adc88da0cef48f1de89b15ab92b15db8f43dc2b6fb8fbd86a6f217a1dd886701@193.70.55.37:30303", + "enode://4afb3a9137a88267c02651052cf6fb217931b8c78ee058bb86643542a4e2e0a8d24d47d871654e1b78a276c363f3c1bc89254a973b00adc359c9e9a48f140686@144.217.139.5:30303", + "enode://c16d390b32e6eb1c312849fe12601412313165df1a705757d671296f1ac8783c5cff09eab0118ac1f981d7148c85072f0f26407e5c68598f3ad49209fade404d@139.99.51.203:30303", + "enode://4faf867a2e5e740f9b874e7c7355afee58a2d1ace79f7b692f1d553a1134eddbeb5f9210dd14dc1b774a46fd5f063a8bc1fa90579e13d9d18d1f59bac4a4b16b@139.99.160.213:30303", + "enode://6a868ced2dec399c53f730261173638a93a40214cf299ccf4d42a76e3fa54701db410669e8006347a4b3a74fa090bb35af0320e4bc8d04cf5b7f582b1db285f5@163.172.131.191:30303", + "enode://66a483383882a518fcc59db6c017f9cd13c71261f13c8d7e67ed43adbbc82a932d88d2291f59be577e9425181fc08828dc916fdd053af935a9491edf9d6006ba@212.47.247.103:30303", + "enode://cd6611461840543d5b9c56fbf088736154c699c43973b3a1a32390cf27106f87e58a818a606ccb05f3866de95a4fe860786fea71bf891ea95f234480d3022aa3@163.172.157.114:30303", + "enode://1d1f7bcb159d308eb2f3d5e32dc5f8786d714ec696bb2f7e3d982f9bcd04c938c139432f13aadcaf5128304a8005e8606aebf5eebd9ec192a1471c13b5e31d49@138.201.223.35:30303", + "enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303", + "enode://3f1d12044546b76342d59d4a05532c14b85aa669704bfe1f864fe079415aa2c02d743e03218e57a33fb94523adb54032871a6c51b2cc5514cb7c7e35b3ed0a99@13.93.211.84:30303", + "enode://78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d@191.235.84.50:30303", + "enode://158f8aab45f6d19c6cbf4a089c2670541a8da11978a2f90dbf6a502a4a3bab80d288afdbeb7ec0ef6d92de563767f3b1ea9e8e334ca711e9f8e2df5a0385e8e6@13.75.154.138:30303", + "enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303", + "enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303", + "enode://0cc5f5ffb5d9098c8b8c62325f3797f56509bff942704687b6530992ac706e2cb946b90a34f1f19548cd3c7baccbcaea354531e5983c7d1bc0dee16ce4b6440b@40.118.3.223:30305", + "enode://1c7a64d76c0334b0418c004af2f67c50e36a3be60b5e4790bdac0439d21603469a85fad36f2473c9a80eb043ae60936df905fa28f1ff614c3e5dc34f15dcd2dc@40.118.3.223:30308", + "enode://85c85d7143ae8bb96924f2b54f1b3e70d8c4d367af305325d30a61385a432f247d2c75c45c6b4a60335060d072d7f5b35dd1d4c45f76941f62a4f83b6e75daaf@40.118.3.223:30309", + "enode://de471bccee3d042261d52e9bff31458daecc406142b401d4cd848f677479f73104b9fdeb090af9583d3391b7f10cb2ba9e26865dd5fca4fcdc0fb1e3b723c786@54.94.239.50:30303", + "enode://4cd540b2c3292e17cff39922e864094bf8b0741fcc8c5dcea14957e389d7944c70278d872902e3d0345927f621547efa659013c400865485ab4bfa0c6596936f@138.201.144.135:30303", + "enode://01f76fa0561eca2b9a7e224378dd854278735f1449793c46ad0c4e79e8775d080c21dcc455be391e90a98153c3b05dcc8935c8440de7b56fe6d67251e33f4e3c@51.15.42.252:30303", + "enode://2c9059f05c352b29d559192fe6bca272d965c9f2290632a2cfda7f83da7d2634f3ec45ae3a72c54dd4204926fb8082dcf9686e0d7504257541c86fc8569bcf4b@163.172.171.38:30303", + "enode://efe4f2493f4aff2d641b1db8366b96ddacfe13e7a6e9c8f8f8cf49f9cdba0fdf3258d8c8f8d0c5db529f8123c8f1d95f36d54d590ca1bb366a5818b9a4ba521c@163.172.187.252:30303", + "enode://bcc7240543fe2cf86f5e9093d05753dd83343f8fda7bf0e833f65985c73afccf8f981301e13ef49c4804491eab043647374df1c4adf85766af88a624ecc3330e@136.243.154.244:30303", + "enode://ed4227681ca8c70beb2277b9e870353a9693f12e7c548c35df6bca6a956934d6f659999c2decb31f75ce217822eefca149ace914f1cbe461ed5a2ebaf9501455@88.212.206.70:30303", + "enode://cadc6e573b6bc2a9128f2f635ac0db3353e360b56deef239e9be7e7fce039502e0ec670b595f6288c0d2116812516ad6b6ff8d5728ff45eba176989e40dead1e@37.128.191.230:30303", + "enode://595a9a06f8b9bc9835c8723b6a82105aea5d55c66b029b6d44f229d6d135ac3ecdd3e9309360a961ea39d7bee7bac5d03564077a4e08823acc723370aace65ec@46.20.235.22:30303", + "enode://029178d6d6f9f8026fc0bc17d5d1401aac76ec9d86633bba2320b5eed7b312980c0a210b74b20c4f9a8b0b2bf884b111fa9ea5c5f916bb9bbc0e0c8640a0f56c@216.158.85.185:30303", + "enode://fdd1b9bb613cfbc200bba17ce199a9490edc752a833f88d4134bf52bb0d858aa5524cb3ec9366c7a4ef4637754b8b15b5dc913e4ed9fdb6022f7512d7b63f181@212.47.247.103:30303", + "enode://cc26c9671dffd3ee8388a7c8c5b601ae9fe75fc0a85cedb72d2dd733d5916fad1d4f0dcbebad5f9518b39cc1f96ba214ab36a7fa5103aaf17294af92a89f227b@52.79.241.155:30303", + "enode://140872ce4eee37177fbb7a3c3aa4aaebe3f30bdbf814dd112f6c364fc2e325ba2b6a942f7296677adcdf753c33170cb4999d2573b5ff7197b4c1868f25727e45@52.78.149.82:30303" + ], + "accounts": { + "0x0000000000000000000000000000000000000001": { + "builtin": { + "name": "ecrecover", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000002": { + "builtin": { + "name": "sha256", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0x0000000000000000000000000000000000000003": { + "builtin": { + "name": "ripemd160", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0x0000000000000000000000000000000000000004": { + "builtin": { + "name": "identity", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0x0000000000000000000000000000000000000005": { + "builtin": { + "name": "modexp", + "activate_at": "0x42ae50", + "pricing": { + "modexp": { + "divisor": 20 + } + } + } + }, + "0x0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x42ae50", + "pricing": { + "linear": { + "base": 500, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x42ae50", + "pricing": { + "linear": { + "base": 40000, + "word": 0 + } + } + } + }, + "0x0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x42ae50", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000 + } + } + } + }, + "0x3282791d6fd713f1e94f4bfd565eaa78b3a0599d": { + "balance": "0x487a9a304539440000" + }, + "0x17961d633bcf20a7b029a7d94b7df4da2ec5427f": { + "balance": "0xc6ff070f1938b8000" + }, + "0x493a67fe23decc63b10dda75f3287695a81bd5ab": { + "balance": "0x2fb474098f67c00000" + }, + "0x01fb8ec12425a04f813e46c54c05748ca6b29aa9": { + "balance": "0xe15730385467c0000" + }, + "0xd2a030ac8952325f9e1db378a71485a24e1b07b2": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x77a34907f305a54c85db09c363fde3c47e6ae21f": { + "balance": "0x35659ef93f0fc40000" + }, + "0x391a77405c09a72b5e8436237aaaf95d68da1709": { + "balance": "0x2a9264af3d1b90000" + }, + "0x00aada25ea2286709abb422d41923fd380cd04c7": { + "balance": "0x233df3299f61720000" + }, + "0xacc46a2a555c74ded4a2bd094e821b97843b40c0": { + "balance": "0x692ae8897081d00000" + }, + "0xde07fb5b7a464e3ba7fbe09e9acb271af5338c58": { + "balance": "0x2b5e3af16b1880000" + }, + "0x4c696be99f3a690440c3436a59a7d7e937d6ba0d": { + "balance": "0xbb9125542263900000" + }, + "0xfa33553285a973719a0d5f956ff861b2d89ed304": { + "balance": "0x1158e460913d00000" + }, + "0x67cfda6e70bf7657d39059b59790e5145afdbe61": { + "balance": "0x23050d095866580000" + }, + "0xa321091d3018064279db399d2b2a88a6f440ae24": { + "balance": "0xad78ebc5ac62000000" + }, + "0xfb3fa1ac08aba9cc3bf0fe9d483820688f65b410": { + "balance": "0x65a4da25d3016c00000" + }, + "0x6715c14035fb57bb3d667f7b707498c41074b855": { + "balance": "0x25f273933db5700000" + }, + "0xd4344f7d5cad65d17e5c2d0e7323943d6f62fe92": { + "balance": "0xe7eeba3410b740000" + }, + "0xa3294626ec2984c43b43da4d5d8e4669b11d4b59": { + "balance": "0x36a4cf636319c00000" + }, + "0x656018584130db83ab0591a8128d9381666a8d0e": { + "balance": "0x3779f912019fc0000" + }, + "0x0fa010ce0c731d3b628e36b91f571300e49dbeab": { + "balance": "0x36330322d5238c0000" + }, + "0x3098b65db93ecacaf7353c48808390a223d57684": { + "balance": "0x186484cf7bb6a48000" + }, + "0xae635bf73831119d2d29c0d04ff8f8d8d0a57a46": { + "balance": "0x487a9a304539440000" + }, + "0x0f7515ff0e808f695e0c20485ff96ed2f7b79310": { + "balance": "0x3638221660a5aa8000" + }, + "0x8b30c04098d7a7e6420c357ea7bfa49bac9a8a18": { + "balance": "0x1b1b113f91fb0140000" + }, + "0x64dba2d6615b8bd7571836dc75bc79d314f5ecee": { + "balance": "0x21e19e0c9bab2400000" + }, + "0xe7912d4cf4562c573ddc5b71e37310e378ef86c9": { + "balance": "0x155bd9307f9fe80000" + }, + "0xa4da34450d22ec0ffcede0004b02f7872ee0b73a": { + "balance": "0x50f616673f0830000" + }, + "0x34437d1465640b136cb5841c3f934f9ba0b7097d": { + "balance": "0x960db77681e940000" + }, + "0xc652871d192422c6bc235fa063b44a7e1d43e385": { + "balance": "0x8670e9ec6598c0000" + }, + "0xa8a708e84f82db86a35502193b4c6ee9a76ebe8f": { + "balance": "0x3708baed3d68900000" + }, + "0x5c3f567faff7bad1b5120022e8cbcaa82b4917b3": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xdbc1d0ee2bab531140de137722cd36bdb4e47194": { + "balance": "0xad78ebc5ac6200000" + }, + "0xf59dab1bf8df11327e61f9b7a14b563a96ec3554": { + "balance": "0x14542ba12a337c00000" + }, + "0x456f8d746682b224679349064d1b368c7c05b176": { + "balance": "0xc893d09c8f51500000" + }, + "0x5f13154631466dcb1353c890932a7c97e0878e90": { + "balance": "0x14542ba12a337c00000" + }, + "0xf4b1626e24f30bcad9273c527fcc714b5d007b8f": { + "balance": "0xad78ebc5ac6200000" + }, + "0xa8db0b9b201453333c757f6ad9bcb555c02da93b": { + "balance": "0x7742b7830f341d0000" + }, + "0xa0fc7e53c5ebd27a2abdac45261f84ab3b51aefb": { + "balance": "0xa313daec9bc0d90000" + }, + "0x1b636b7a496f044d7359596e353a104616436f6b": { + "balance": "0x1388ea95c33f1d0000" + }, + "0x74bce9ec38362d6c94ccac26d5c0e13a8b3b1d40": { + "balance": "0x363526410442f50000" + }, + "0x9834682180b982d166badb9d9d1d9bbf016d87ee": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x1e6e0153fc161bc05e656bbb144c7187bf4fe84d": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x989c0ccff654da03aeb11af701054561d6297e1d": { + "balance": "0xd8d726b7177a800000" + }, + "0x78a1e254409fb1b55a7cb4dd8eba3b30c8bad9ef": { + "balance": "0x56bc75e2d63100000" + }, + "0x9ef1896b007c32a15114fb89d73dbd47f9122b69": { + "balance": "0xd8d726b7177a800000" + }, + "0x33320dd90f2baa110dd334872a998f148426453c": { + "balance": "0x36356633ebd8ea0000" + }, + "0xe72e1d335cc29a96b9b1c02f003a16d971e90b9d": { + "balance": "0x55a6e79ccd1d300000" + }, + "0x0921605f99164e3bcc28f31caece78973182561d": { + "balance": "0x2b07692a9065a80000" + }, + "0xfc00a420a36107dfd5f495128a5fe5abb2db0f34": { + "balance": "0x143179d869110200000" + }, + "0xdfcbdf09454e1a5e4a40d3eef7c5cf1cd3de9486": { + "balance": "0xd8d726b7177a800000" + }, + "0x646e043d0597a664948fbb0dc15475a3a4f3a6ed": { + "balance": "0x1158e460913d00000" + }, + "0x79aeb34566b974c35a5881dec020927da7df5d25": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xdbadc61ed5f0460a7f18e51b2fb2614d9264a0e0": { + "balance": "0x22b1c8c1227a00000" + }, + "0x97b91efe7350c2d57e7e406bab18f3617bcde14a": { + "balance": "0x21e1999bbd5d2be0000" + }, + "0x8398e07ebcb4f75ff2116de77c1c2a99f303a4cf": { + "balance": "0x1b1ae4d6e2ef500000" + }, + "0xf02796295101674288c1d93467053d042219b794": { + "balance": "0x281d901f4fdd100000" + }, + "0xf4ed848ec961739c2c7e352f435ba70a7cd5db38": { + "balance": "0x6acb3df27e1f880000" + }, + "0x82485728d0e281563758c75ab27ed9e882a0002d": { + "balance": "0x7f808e9291e6c0000" + }, + "0x427ec668ac9404e895cc861511d1620a4912be98": { + "balance": "0x878678326eac9000000" + }, + "0x1bbc199e586790be87afedc849c04726745c5d7b": { + "balance": "0xd8d726b7177a800000" + }, + "0x10d945334ecde47beb9ca3816c173dfbbd0b5333": { + "balance": "0x4be4e7267b6ae00000" + }, + "0x1dcebcb7656df5dcaa3368a055d22f9ed6cdd940": { + "balance": "0x1b181e4bf2343c0000" + }, + "0x2ac1f8d7bf721f3cfe74d20fea9b87a28aaa982c": { + "balance": "0x8ba52e6fc45e40000" + }, + "0x0a47ad9059a249fc936b2662353da6905f75c2b9": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x768498934e37e905f1d0e77b44b574bcf3ec4ae8": { + "balance": "0x43c33c1937564800000" + }, + "0xf46b6b9c7cb552829c1d3dfd8ffb11aabae782f6": { + "balance": "0x1236efcbcbb340000" + }, + "0x7aea25d42b2612286e99c53697c6bc4100e2dbbf": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xaf3615c789d0b1152ad4db25fe5dcf222804cf62": { + "balance": "0x3635c9adc5dea00000" + }, + "0x92e6581e1da1f9b846e09347333dc818e2d2ac66": { + "balance": "0xc55325ca7415e00000" + }, + "0x240305727313d01e73542c775ff59d11cd35f819": { + "balance": "0x141885666807f5c8000" + }, + "0xb95cfda8465ba9c2661b249fc3ab661bdfa35ff0": { + "balance": "0x114a4e79a2c2108000" + }, + "0x1b0d076817e8d68ee2df4e1da1c1142d198c4435": { + "balance": "0x54069233bf7f780000" + }, + "0x93c2e64e5de5589ed25006e843196ee9b1cf0b3e": { + "balance": "0x5a87e7d7f5f6580000" + }, + "0x0e2e504a2d1122b5a9feee5cb1451bf4c2ace87b": { + "balance": "0xd5967be4fc3f100000" + }, + "0x22b96ab2cad55db100b53001f9e4db378104c807": { + "balance": "0x21e19e0c9bab2400000" + }, + "0xa927d48bb6cb814bc609cbcaa9151f5d459a27e1": { + "balance": "0xeb935090064180000" + }, + "0x5cbd8daf27ddf704cdd0d909a789ba36ed4f37b2": { + "balance": "0xb9f65d00f63c0000" + }, + "0x9adbd3bc7b0afc05d1d2eda49ff863939c48db46": { + "balance": "0xad6eedd17cf3b8000" + }, + "0xac7e03702723cb16ee27e22dd0b815dc2d5cae9f": { + "balance": "0x3635c9adc5dea000000" + }, + "0x1e210e7047886daa52aaf70f4b991dac68e3025e": { + "balance": "0xad78ebc5ac6200000" + }, + "0xc98048687f2bfcc9bd90ed18736c57edd352b65d": { + "balance": "0x3635c9adc5dea00000" + }, + "0x81c18c2a238ddc4cba230a072dd7dc101e620273": { + "balance": "0x487a9a304539440000" + }, + "0xcb3d766c983f192bcecac70f4ee03dd9ff714d51": { + "balance": "0x56bc75e2d63100000" + }, + "0x44a63d18424587b9b307bfc3c364ae10cd04c713": { + "balance": "0x1158e460913d00000" + }, + "0x4ab2d34f04834fbf7479649cab923d2c4725c553": { + "balance": "0xbed1d0263d9f000000" + }, + "0xb834acf3015322c58382eeb2b79638906e88b6de": { + "balance": "0x5150ae84a8cdf000000" + }, + "0x7d551397f79a2988b064afd0efebee802c7721bc": { + "balance": "0x857e0d6f1da76a00000" + }, + "0xb537d36a70eeb8d3e5c80de815225c1158cb92c4": { + "balance": "0x5150ae84a8cdf00000" + }, + "0x805ce51297a0793b812067f017b3e7b2df9bb1f9": { + "balance": "0x56bc75e2d63100000" + }, + "0x085ba65febe23eefc2c802666ab1262382cfc494": { + "balance": "0x15af1d78b58c400000" + }, + "0xb1c0d08b36e184f9952a4037e3e53a667d070a4e": { + "balance": "0x3635c9adc5dea00000" + }, + "0x83fe5a1b328bae440711beaf6aad6026eda6d220": { + "balance": "0x43c33c1937564800000" + }, + "0x7fd679e5fb0da2a5d116194dcb508318edc580f3": { + "balance": "0x1639e49bba162800000" + }, + "0x41ad369f758fef38a19aa3149379832c818ef2a0": { + "balance": "0x36369ed7747d260000" + }, + "0x6d846dc12657e91af25008519c3e857f51707dd6": { + "balance": "0xf8d30bc92342f80000" + }, + "0xc02d6eadeacf1b78b3ca85035c637bb1ce01f490": { + "balance": "0xd8d726b7177a800000" + }, + "0x826eb7cd7319b82dd07a1f3b409071d96e39677f": { + "balance": "0x3635c9adc5dea00000" + }, + "0x4ac9905a4cb6ab1cfd62546ee5917300b87c4fde": { + "balance": "0x3708baed3d68900000" + }, + "0xcf6e52e6b77480b1867efec6446d9fc3cc3577e8": { + "balance": "0xc0901f6bd98790000" + }, + "0x2476b2bb751ce748e1a4c4ff7b230be0c15d2245": { + "balance": "0xd8d726b7177a800000" + }, + "0x1a505e62a74e87e577473e4f3afa16bedd3cfa52": { + "balance": "0x1b1ae4d6e2ef500000" + }, + "0x21d02705f3f64905d80ed9147913ea8c7307d695": { + "balance": "0x49edb1c09887360000" + }, + "0x7b1daf14891b8a1e1bd429d8b36b9a4aa1d9afbf": { + "balance": "0x1b1ae4d6e2ef500000" + }, + "0x5338ef70eac9dd9af5a0503b5efad1039e67e725": { + "balance": "0x90f534608a72880000" + }, + "0x50ca86b5eb1d01874df8e5f34945d49c6c1ab848": { + "balance": "0x3635c9adc5dea00000" + }, + "0xf3cc8bcb559465f81bfe583bd7ab0a2306453b9e": { + "balance": "0x43c33c1937564800000" + }, + "0x5c323457e187761a8276e359b7b7af3f3b6e3df6": { + "balance": "0x21e19e0c9bab2400000" + }, + "0x4d82d7700c123bb919419bbaf046799c6b0e2c66": { + "balance": "0x43c33c1937564800000" + }, + "0x8a66abbc2d30ce21a833b0db8e561d5105e0a72c": { + "balance": "0x25f1de5c76acdf0000" + }, + "0x2ae53866fc2d14d572ab73b4a065a1188267f527": { + "balance": "0x1b1ae4d6e2ef5000000" + }, + "0x9af5c9894c33e42c2c518e3ac670ea9505d1b53e": { + "balance": "0xfc936392801c0000" + }, + "0xcba25c7a503cc8e0d04971ca05c762f9b762b48b": { + "balance": "0x1b1ae4d6e2ef500000" + }, + "0xfda3042819af3e662900e1b92b4358eda6e92590": { + "balance": "0x1907a284d58f63e00000" + }, + "0x9bd7c38a4210304a4d653edeff1b3ce45fce7843": { + "balance": "0xf498941e664280000" + }, + "0xedc22fb92c638e1e21ff5cf039daa6e734dafb29": { + "balance": "0x102794ad20da680000" + }, + "0xa1f193a0592f1feb9fdfc90aa813784eb80471c9": { + "balance": "0x4be4e7267b6ae00000" + }, + "0xe97fde0b67716325cf0ecce8a191a3761b2c791d": { + "balance": "0x3677036edf0af60000" + }, + "0x110237cf9117e767922fc4a1b78d7964da82df20": { + "balance": "0xd5967be4fc3f100000" + }, + "0xe32f95766d57b5cd4b173289d6876f9e64558194": { + "balance": "0x56bc75e2d63100000" + }, + "0xf2d59c8923759073d6f415aaf8eb065ff2f3b685": { + "balance": "0x1ab2cf7c9f87e200000" + }, + "0xc53d79f7cb9b70952fd30fce58d54b9f0b59f647": { + "balance": "0x113e2d6744345f80000" + }, + "0x9eb281c32719c40fdb3e216db0f37fbc73a026b7": { + "balance": "0x1158e460913d00000" + }, + "0x2d6511fd7a3800b26854c7ec39c0dcb5f4c4e8e8": { + "balance": "0x15adddba2f9e770000" + }, + "0x61ba87c77e9b596de7ba0e326fddfeec2163ef66": { + "balance": "0xad78ebc5ac6200000" + }, + "0xde1121829c9a08284087a43fbd2fc1142a3233b4": { + "balance": "0x3635c9adc5dea00000" + }, + "0x22a25812ab56dcc423175ed1d8adacce33cd1810": { + "balance": "0x6449e84e47a8a80000" + }, + "0x518cef27b10582b6d14f69483ddaa0dd3c87bb5c": { + "balance": "0x2086ac351052600000" + }, + "0x59161749fedcf1c721f2202d13ade2abcf460b3d": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x3e36c17253c11cf38974ed0db1b759160da63783": { + "balance": "0x17b7883c06916600000" + }, + "0xcbfa76db04ce38fb205d37b8d377cf1380da0317": { + "balance": "0x4d853c8f8908980000" + }, + "0xa7e83772bc200f9006aa2a260dbaa8483dc52b30": { + "balance": "0xb42d5366637e50000" + }, + "0xe87eac6d602b4109c9671bf57b950c2cfdb99d55": { + "balance": "0x2b4f21972ecce0000" + }, + "0x9b06ad841dffbe4ccf46f1039fc386f3c321446e": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xe0f903c1e48ac421ab48528f3d4a2648080fe043": { + "balance": "0x3708baed3d68900000" + }, + "0x5d872b122e994ef27c71d7deb457bf65429eca6c": { + "balance": "0x1b1aded81d394108000" + }, + "0xf34083ecea385017aa40bdd35ef7effb4ce7762d": { + "balance": "0x15af1d78b58c400000" + }, + "0x7f3709391f3fbeba3592d175c740e87a09541d02": { + "balance": "0x1a055690d9db800000" + }, + "0x888e94917083d152202b53163939869d271175b4": { + "balance": "0xd8d726b7177a800000" + }, + "0xbed4c8f006a27c1e5f7ce205de75f516bfb9f764": { + "balance": "0x3635c9adc5dea000000" + }, + "0xb3a6bd41f9d9c3201e050b87198fbda399342210": { + "balance": "0xc461e1dd1029b58000" + }, + "0x550aadae1221b07afea39fba2ed62e05e5b7b5f9": { + "balance": "0x1158e460913d00000" + }, + "0xbcedc4267ccb89b31bb764d7211171008d94d44d": { + "balance": "0xad78ebc5ac6200000" + }, + "0x6229dcc203b1edccfdf06e87910c452a1f4d7a72": { + "balance": "0x6e1d41a8f9ec3500000" + }, + "0x94be3ae54f62d663b0d4cc9e1ea8fe9556ea9ebf": { + "balance": "0x143132ca843180000" + }, + "0x0e0c9d005ea016c295cd795cc9213e87febc33eb": { + "balance": "0xabbcd4ef377580000" + }, + "0x55d057bcc04bd0f4af9642513aa5090bb3ff93fe": { + "balance": "0x3bfe452c8edd4c0000" + }, + "0xed9e030ca75cb1d29ea01d0d4cdfdccd3844b6e4": { + "balance": "0x1acc116cfafb18000" + }, + "0x86c4ce06d9ac185bb148d96f7b7abe73f441006d": { + "balance": "0x21e19e0c9bab2400000" + }, + "0x2c04115c3e52961b0dc0b0bf31fba4546f5966fd": { + "balance": "0xad78ebc5ac6200000" + }, + "0xb959dce02e91d9db02b1bd8b7d17a9c41a97af09": { + "balance": "0x1b1ae4d6e2ef5000000" + }, + "0xe01547ba42fcafaf93938becf7699f74290af74f": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xc593d6e37d14b566643ac4135f243caa0787c182": { + "balance": "0x28a857425466f800000" + }, + "0x2c0ee134d8b36145b47beee7af8d2738dbda08e8": { + "balance": "0xae56f730e6d840000" + }, + "0x0ef54ac7264d2254abbb5f8b41adde875157db7c": { + "balance": "0x22b1c8c1227a00000" + }, + "0x0349634dc2a9e80c3f7721ee2b5046aeaaedfbb5": { + "balance": "0xd8d726b7177a800000" + }, + "0x873e49135c3391991060290aa7f6ccb8f85a78db": { + "balance": "0x1158e460913d00000" + }, + "0x05236d4c90d065f9e3938358aaffd777b86aec49": { + "balance": "0x1b1ae4d6e2ef500000" + }, + "0xd2abd84a181093e5e229136f42d835e8235de109": { + "balance": "0x56be03ca3e47d8000" + }, + "0xb56a780028039c81caf37b6775c620e786954764": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x86df73bd377f2c09de63c45d67f283eaefa0f4ab": { + "balance": "0x3635c9adc5dea00000" + }, + "0x7670b02f2c3cf8fd4f4730f3381a71ea431c33c7": { + "balance": "0xe7eeba3410b740000" + }, + "0x24aa1151bb765fa3a89ca50eb6e1b1c706417fd4": { + "balance": "0xa80d24677efef00000" + }, + "0x43227d65334e691cf231b4a4e1d339b95d598afb": { + "balance": "0x21e19e0c9bab2400000" + }, + "0x695550656cbf90b75d92ad9122d90d23ca68ca4d": { + "balance": "0x3635c9adc5dea00000" + }, + "0x5281733473e00d87f11e9955e589b59f4ac28e7a": { + "balance": "0x8bd62ff4eec559200000" + }, + "0x99a96bf2242ea1b39ece6fcc0d18aed00c0179f3": { + "balance": "0x1043561a8829300000" + }, + "0xb1cf94f8091505055f010ab4bac696e0ca0f67a1": { + "balance": "0x55a6e79ccd1d300000" + }, + "0x54391b4d176d476cea164e5fb535c69700cb2535": { + "balance": "0x56cd55fc64dfe0000" + }, + "0x152f2bd229ddf3cb0fdaf455c183209c0e1e39a2": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xaffc99d5ebb4a84fe7788d97dce274b038240438": { + "balance": "0x10f0cf064dd59200000" + }, + "0x23df8f48ee009256ea797e1fa369beebcf6bc663": { + "balance": "0x7cd3fac26d19818000" + }, + "0x3a72d635aadeee4382349db98a1813a4cfeb3df1": { + "balance": "0x2a5a058fc295ed000000" + }, + "0xce26f9a5305f8381094354dbfc92664e84f902b5": { + "balance": "0xc7aaab0591eec0000" + }, + "0xd283b8edb10a25528a4404de1c65e7410dbcaa67": { + "balance": "0x28a857425466f800000" + }, + "0xa7859fc07f756ea7dcebbccd42f05817582d973f": { + "balance": "0x21e19e0c9bab2400000" + }, + "0xb28181a458a440f1c6bb1de8400281a3148f4c35": { + "balance": "0x14620c57dddae00000" + }, + "0x27b1694eafa165ebd7cc7bc99e74814a951419dc": { + "balance": "0x2b5e3af16b18800000" + }, + "0x66cc8ab23c00d1b82acd7d73f38c99e0d05a4fa6": { + "balance": "0x56bc75e2d63100000" + }, + "0x926082cb7eed4b1993ad245a477267e1c33cd568": { + "balance": "0x144a74badfa4b60000" + }, + "0x4a47fc3e177f567a1e3893e000e36bba23520ab8": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x594a76f06935388dde5e234696a0668bc20d2ddc": { + "balance": "0x97c9ce4cf6d5c00000" + }, + "0xe91fa0badaddb9a97e88d3f4db7c55d6bb7430fe": { + "balance": "0x14620c57dddae00000" + }, + "0x574de1b3f38d915846ae3718564a5ada20c2f3ed": { + "balance": "0xd8d726b7177a800000" + }, + "0x5816c2687777b6d7d2a2432d59a41fa059e3a406": { + "balance": "0x1c4fe43adb0a5e900000" + }, + "0xb50955aa6e341571986608bdc891c2139f540cdf": { + "balance": "0x6acb3df27e1f880000" + }, + "0x6d44974a31d187eda16ddd47b9c7ec5002d61fbe": { + "balance": "0x32f51edbaaa3300000" + }, + "0x80abec5aa36e5c9d098f1b942881bd5acac6963d": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x294f494b3f2e143c2ffc9738cbfd9501850b874e": { + "balance": "0x796e3ea3f8ab000000" + }, + "0xbca3ffd4683fba0ad3bbc90734b611da9cfb457e": { + "balance": "0xad78ebc5ac6200000" + }, + "0x5992624c54cdec60a5ae938033af8be0c50cbb0a": { + "balance": "0xc454e0f8870f2b0000" + }, + "0x6560941328ff587cbc56c38c78238a7bb5f442f6": { + "balance": "0x2861906b59c47a0000" + }, + "0x74b7e0228baed65957aebb4d916d333aae164f0e": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x8516fcaf77c893970fcd1a958ba9a00e49044019": { + "balance": "0xaa3eb1691bce58000" + }, + "0xb992a967308c02b98af91ee760fd3b6b4824ab0e": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x30bb4357cd6910c86d2238bf727cbe8156680e62": { + "balance": "0x56bf91b1a65eb0000" + }, + "0xb8cc0f060aad92d4eb8b36b3b95ce9e90eb383d7": { + "balance": "0x1fc3842bd1f071c00000" + }, + "0x28d4ebf41e3d3c451e943bdd7e1f175fae932a3d": { + "balance": "0x14542ba12a337c00000" + }, + "0x8c83d424a3cf24d51f01923dd54a18d6b6fede7b": { + "balance": "0xd8d726b7177a800000" + }, + "0x7efc90766a00bc52372cac97fabd8a3c831f8ecd": { + "balance": "0x890b0c2e14fb80000" + }, + "0x7c2b9603884a4f2e464eceb97d17938d828bc02c": { + "balance": "0xa2a15d09519be00000" + }, + "0x9d250ae4f110d71cafc7b0adb52e8d9acb6679b8": { + "balance": "0x2156d6e997213c00000" + }, + "0x61b3df2e9e9fd968131f1e88f0a0eb5bd765464d": { + "balance": "0xd8d726b7177a800000" + }, + "0x9ae13bd882f2576575921a94974cbea861ba0d35": { + "balance": "0xab4dcf399a3a600000" + }, + "0x3d09688d93ad07f3abe68c722723cd680990435e": { + "balance": "0x65a4ce99f769e6e0000" + }, + "0x5e58e255fc19870a04305ff2a04631f2ff294bb1": { + "balance": "0xf43fc2c04ee00000" + }, + "0xbcaed0acb6a76f113f7c613555a2c3b0f5bf34a5": { + "balance": "0xa7ebd5e4363a00000" + }, + "0x159adce27aa10b47236429a34a5ac42cad5b6416": { + "balance": "0x6bf90a96edbfa718000" + }, + "0xe834c64318205ca7dd4a21abcb08266cb21ff02c": { + "balance": "0x3635c6204739d98000" + }, + "0x7b6a84718dd86e63338429ac811d7c8a860f21f1": { + "balance": "0x61093d7c2c6d380000" + }, + "0x2118c116ab0cdf6fd11d54a4309307b477c3fc0f": { + "balance": "0x21e19e0c9bab2400000" + }, + "0x34a901a69f036bcf9f7843c0ba01b426e8c3dc2b": { + "balance": "0xd8d726b7177a800000" + }, + "0xc7d44fe32c7f8cd5f1a97427b6cd3afc9e45023e": { + "balance": "0x55a6e79ccd1d300000" + }, + "0xc6045b3c350b4ce9ca0c6b754fb41a69b97e9900": { + "balance": "0x3224f42723d4540000" + }, + "0xcf5a6f9df75579c644f794711215b30d77a0ce40": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xe2904b1aefa056398b6234cb35811288d736db67": { + "balance": "0x22b1c8c1227a00000" + }, + "0x7101bd799e411cde14bdfac25b067ac890eab8e8": { + "balance": "0x4e9b8aae48de470000" + }, + "0xcc45fb3a555bad807b388a0357c855205f7c75e8": { + "balance": "0x2ee449550898e40000" + }, + "0xff0c3c7798e8733dd2668152891bab80a8be955c": { + "balance": "0x45946b0f9e9d60000" + }, + "0x3536453322c1466cb905af5c335ca8db74bff1e6": { + "balance": "0x183b5f03b1479c0000" + }, + "0x08cac8952641d8fc526ec1ab4f2df826a5e7710f": { + "balance": "0x1043561a8829300000" + }, + "0x0d8aab8f74ea862cdf766805009d3f3e42d8d00b": { + "balance": "0x13b80b99c5185700000" + }, + "0x8908760cd39b9c1e8184e6a752ee888e3f0b7045": { + "balance": "0x14542ba12a337c00000" + }, + "0x8156360bbd370961ceca6b6691d75006ad204cf2": { + "balance": "0x878678326eac9000000" + }, + "0xa304588f0d850cd8d38f76e9e83c1bf63e333ede": { + "balance": "0x2285601216c8c0000" + }, + "0x14c63ba2dcb1dd4df33ddab11c4f0007fa96a62d": { + "balance": "0x34841b6057afab00000" + }, + "0xa009bf076f1ba3fa57d2a7217218bed5565a7a7a": { + "balance": "0x3635c9adc5dea00000" + }, + "0x1c89060f987c518fa079ec2c0a5ebfa30f5d20f7": { + "balance": "0x80bfbefcb5f0bc00000" + }, + "0x8895eb726226edc3f78cc6a515077b3296fdb95e": { + "balance": "0xd5967be4fc3f100000" + }, + "0x7919e7627f9b7d54ea3b14bb4dd4649f4f39dee0": { + "balance": "0x5a87e7d7f5f6580000" + }, + "0xb3c65b845aba6cd816fbaae983e0e46c82aa8622": { + "balance": "0x3635c9adc5dea00000" + }, + "0xeff51d72adfae143edf3a42b1aec55a2ccdd0b90": { + "balance": "0x1043561a8829300000" + }, + "0x05bb64a916be66f460f5e3b64332110d209e19ae": { + "balance": "0xe3aeb5737240a00000" + }, + "0xd5b117ec116eb846418961eb7edb629cd0dd697f": { + "balance": "0xa2a15d09519be00000" + }, + "0x05e97b09492cd68f63b12b892ed1d11d152c0eca": { + "balance": "0x3708baed3d68900000" + }, + "0x84cc7878da605fdb019fab9b4ccfc157709cdda5": { + "balance": "0x48798513af04c90000" + }, + "0x79cac6494f11ef2798748cb53285bd8e22f97cda": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xbd5a8c94bd8be6470644f70c8f8a33a8a55c6341": { + "balance": "0xad78ebc5ac6200000" + }, + "0xb119e79aa9b916526581cbf521ef474ae84dcff4": { + "balance": "0x4fba1001e5befe0000" + }, + "0xaff1045adf27a1aa329461b24de1bae9948a698b": { + "balance": "0x1cf84a30a0a0c0000" + }, + "0x4398628ea6632d393e929cbd928464c568aa4a0c": { + "balance": "0x4be4e7267b6ae00000" + }, + "0x99997668f7c1a4ff9e31f9977ae3224bcb887a85": { + "balance": "0xfc936392801c00000" + }, + "0xbc0e8745c3a549445c2be900f52300804ab56289": { + "balance": "0x7029bf5dd4c53b28000" + }, + "0xe5bab4f0afd8a9d1a381b45761aa18f3d3cce105": { + "balance": "0x51bfd7c13878d10000" + }, + "0xbe60037e90714a4b917e61f193d834906703b13a": { + "balance": "0x5c283d410394100000" + }, + "0x8ed4284c0f47449c15b8d9b3245de8beb6ce80bf": { + "balance": "0x2b5e3af16b18800000" + }, + "0x333ad1596401e05aea2d36ca47318ef4cd2cb3df": { + "balance": "0x9dc05cce28c2b80000" + }, + "0x22db559f2c3c1475a2e6ffe83a5979599196a7fa": { + "balance": "0x3635c9adc5dea00000" + }, + "0xfdf449f108c6fb4f5a2b081eed7e45e6919e4d25": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x0be1bcb90343fae5303173f461bd914a4839056c": { + "balance": "0x14542ba12a337c00000" + }, + "0xb981ad5e6b7793a23fc6c1e8692eb2965d18d0da": { + "balance": "0x21e18d2c821c7520000" + }, + "0xc75d2259306aec7df022768c69899a652185dbc4": { + "balance": "0xd8d726b7177a800000" + }, + "0x6c2e9be6d4ab450fd12531f33f028c614674f197": { + "balance": "0xc2127af858da700000" + }, + "0x6dcc7e64fcafcbc2dc6c0e5e662cb347bffcd702": { + "balance": "0x43c33c1937564800000" + }, + "0xaabdb35c1514984a039213793f3345a168e81ff1": { + "balance": "0x10cac896d239000000" + }, + "0xd315deea1d8c1271f9d1311263ab47c007afb6f5": { + "balance": "0x3c81d4e654b400000" + }, + "0x4faf90b76ecfb9631bf9022176032d8b2c207009": { + "balance": "0x36363b5d9a77700000" + }, + "0x3e7a966b5dc357ffb07e9fe067c45791fd8e3049": { + "balance": "0x3342d60dff1960000" + }, + "0x2e64a8d71111a22f4c5de1e039b336f68d398a7c": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x181fbba852a7f50178b1c7f03ed9e58d54162929": { + "balance": "0x241a9b4f617a280000" + }, + "0x4f7330096f79ed264ee0127f5d30d2f73c52b3d8": { + "balance": "0x1b1a7a420ba00d0000" + }, + "0xa8a8dbdd1a85d1beee2569e91ccc4d09ae7f6ea1": { + "balance": "0x13a6b2b564871a00000" + }, + "0x1f9c3268458da301a2be5ab08257f77bb5a98aa4": { + "balance": "0xad78ebc5ac6200000" + }, + "0xfc372ff6927cb396d9cf29803500110da632bc52": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x4fa554ab955c249217386a4d3263bbf72895434e": { + "balance": "0x1154e53217ddb0000" + }, + "0x2a59e47ea5d8f0e7c028a3e8e093a49c1b50b9a3": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x5e32c72191b8392c55f510d8e3326e3a60501d62": { + "balance": "0x9513ea9de0243800000" + }, + "0x1dfaee077212f1beaf0e6f2f1840537ae154ad86": { + "balance": "0x3635c9adc5dea00000" + }, + "0x7eaba035e2af3793fd74674b102540cf190addb9": { + "balance": "0x45026c835b60440000" + }, + "0xd62edb96fce2969aaf6c545e967cf1c0bc805205": { + "balance": "0x4a565536a5ada8000" + }, + "0x220dc68df019b6b0ccbffb784b5a5ab4b15d4060": { + "balance": "0xd5967be4fc3f100000" + }, + "0x45bb829652d8bfb58b8527f0ecb621c29e212ec3": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x79b120eb8806732321288f675a27a9225f1cd2eb": { + "balance": "0x85a0bf37dec9e40000" + }, + "0x740af1eefd3365d78ba7b12cb1a673e06a077246": { + "balance": "0x42bf06b78ed3b500000" + }, + "0x0f042c9c2fb18766f836bb59f735f27dc329fe3c": { + "balance": "0x21e19e0c9bab2400000" + }, + "0x6dda5f788a6c688ddf921fa3852eb6d6c6c62966": { + "balance": "0x22b1c8c1227a00000" + }, + "0x96ad579bbfa8db8ebec9d286a72e4661eed8e356": { + "balance": "0x3a0ba42bec61830000" + }, + "0x0c2073ba44d3ddbdb639c04e191039a71716237f": { + "balance": "0x4d853c8f8908980000" + }, + "0x1a3520453582c718a21c42375bc50773255253e1": { + "balance": "0x2ad373ce668e980000" + }, + "0xefcaae9ff64d2cd95b5249dcffe7faa0a0c0e44d": { + "balance": "0x15be6174e1912e0000" + }, + "0x0a3de155d5ecd8e81c1ff9bbf0378301f8d4c623": { + "balance": "0xd8d726b7177a800000" + }, + "0x80f07ac09e7b2c3c0a3d1e9413a544c73a41becb": { + "balance": "0x1158e460913d00000" + }, + "0xc3631c7698b6c5111989bf452727b3f9395a6dea": { + "balance": "0x243275896641dbe0000" + }, + "0x4cc22c9bc9ad05d875a397dbe847ed221c920c67": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x1a987e3f83de75a42f1bde7c997c19217b4a5f24": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x5b2b64e9c058e382a8b299224eecaa16e09c8d92": { + "balance": "0x8ba52e6fc45e40000" + }, + "0x86caafacf32aa0317c032ac36babed974791dc03": { + "balance": "0x878678326eac9000000" + }, + "0x1cd1f0a314cbb200de0a0cb1ef97e920709d97c2": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x7d980f4b566bb045517e4c14c87750de9346744b": { + "balance": "0x487a9a304539440000" + }, + "0x8b5f29cc2faa262cdef30ef554f50eb488146eac": { + "balance": "0x13b68705c9720810000" + }, + "0x5153a0c3c8912881bf1c3501bf64b45649e48222": { + "balance": "0xd8d726b7177a800000" + }, + "0xd21a7341eb84fd151054e5e387bb25d36e499c09": { + "balance": "0x2f6f10780d22cc00000" + }, + "0x9560e8ac6718a6a1cdcff189d603c9063e413da6": { + "balance": "0xd8d726b7177a800000" + }, + "0xe49ba0cd96816c4607773cf8a5970bb5bc16a1e6": { + "balance": "0x5a87e7d7f5f6580000" + }, + "0xb8ac117d9f0dba80901445823c4c9d4fa3fedc6e": { + "balance": "0x3564c4427a8fc7d8000" + }, + "0xaf67fd3e127fd9dc36eb3fcd6a80c7be4f7532b2": { + "balance": "0x5a87e7d7f5f6580000" + }, + "0xb43c27f7a0a122084b98f483922541c8836cee2c": { + "balance": "0x26c29e47c4844c0000" + }, + "0x4d9279962029a8bd45639737e98b511eff074c21": { + "balance": "0x487a9a304539440000" + }, + "0xc667441e7f29799aba616451d53b3f489f9e0f48": { + "balance": "0x2f29ace68addd800000" + }, + "0x275875ff4fbb0cf3a430213127487f7608d04cba": { + "balance": "0x1b1c010e766d580000" + }, + "0x9a953b5bcc709379fcb559d7b916afdaa50cadcc": { + "balance": "0x56bc75e2d63100000" + }, + "0x7ea791ebab0445a00efdfc4e4a8e9a7e7565136d": { + "balance": "0xfc936392801c0000" + }, + "0x6ffe5cf82cc9ea5e36cad7c2974ce7249f3749e6": { + "balance": "0x692ae8897081d00000" + }, + "0xf1b4ecc63525f7432c3d834ffe2b970fbeb87212": { + "balance": "0xa2a24068facd800000" + }, + "0x6b72a8f061cfe6996ad447d3c72c28c0c08ab3a7": { + "balance": "0xe78c6ac79912620000" + }, + "0xbba3c68004248e489573abb2743677066b24c8a7": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xb7c0d0cc0b4d342d4062bac624ccc3c70cc6da3f": { + "balance": "0xd8d726b7177a800000" + }, + "0xfe98c664c3e447a95e69bd582171b7176ea2a685": { + "balance": "0xd8d726b7177a800000" + }, + "0xce71086d4c602554b82dcbfce88d20634d53cc4d": { + "balance": "0x92896529baddc880000" + }, + "0x1c601993789207f965bb865cbb4cd657cce76fc0": { + "balance": "0x5541a7037503f0000" + }, + "0x476b5599089a3fb6f29c6c72e49b2e4740ea808d": { + "balance": "0x97c9ce4cf6d5c00000" + }, + "0x3439998b247cb4bf8bc80a6d2b3527f1dfe9a6d2": { + "balance": "0x796e3ea3f8ab00000" + }, + "0xc4f7d2e2e22084c44f70feaab6c32105f3da376f": { + "balance": "0x6acb3df27e1f880000" + }, + "0xc1eba5684aa1b24cba63150263b7a9131aeec28d": { + "balance": "0x1158e460913d00000" + }, + "0x94ad4bad824bd0eb9ea49c58cebcc0ff5e08346b": { + "balance": "0x692ae8897081d00000" + }, + "0xded877378407b94e781c4ef4af7cfc5bc220b516": { + "balance": "0x143179d86911020000" + }, + "0x699c9ee47195511f35f862ca4c22fd35ae8ffbf4": { + "balance": "0x4563918244f400000" + }, + "0xe3a89a1927cc4e2d43fbcda1e414d324a7d9e057": { + "balance": "0xb23e2a936dec60000" + }, + "0x4d93696fa24859f5d2939aebfa54b4b51ae1dccc": { + "balance": "0x10910d4cdc9f60000" + }, + "0x0af65f14784e55a6f95667fd73252a1c94072d2a": { + "balance": "0xa763b8e02d44f8000" + }, + "0x5b70c49cc98b3df3fbe2b1597f5c1b6347a388b7": { + "balance": "0x34957444b840e80000" + }, + "0x426f78f70db259ac8534145b2934f4ef1098b5d8": { + "balance": "0x138400eca364a00000" + }, + "0x58b8ae8f63ef35ed0762f0b6233d4ac14e64b64d": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x8eae29435598ba8f1c93428cdb3e2b4d31078e00": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x17fd9b551a98cb61c2e07fbf41d3e8c9a530cba5": { + "balance": "0x1768c308193048000" + }, + "0xab3e78294ba886a0cfd5d3487fb3a3078d338d6e": { + "balance": "0x6acb3df27e1f880000" + }, + "0xbdf6e68c0cd7584080e847d72cbb23aad46aeb1d": { + "balance": "0x6acb3df27e1f880000" + }, + "0xf989346772995ec1906faffeba2a7fe7de9c6bab": { + "balance": "0x16a6502f15a1e540000" + }, + "0xdc5f5ad663a6f263327d64cac9cb133d2c960597": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x68fe1357218d095849cd579842c4aa02ff888d93": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xe09c68e61998d9c81b14e4ee802ba7adf6d74cdb": { + "balance": "0xd8d726b7177a800000" + }, + "0x890fe11f3c24db8732d6c2e772e2297c7e65f139": { + "balance": "0xd5627137da8b5900000" + }, + "0xa76929890a7b47fb859196016c6fdd8289ceb755": { + "balance": "0x10f0cf064dd59200000" + }, + "0x2dc79d6e7f55bce2e2d0c02ad07ceca8bb529354": { + "balance": "0x55a6e79ccd1d300000" + }, + "0x19687daa39c368139b6e7be60dc1753a9f0cbea3": { + "balance": "0x1b1ae4d6e2ef5000000" + }, + "0xc69be440134d6280980144a9f64d84748a37f349": { + "balance": "0x26c29e47c4844c0000" + }, + "0x3d8d0723721e73a6c0d860aa0557abd14c1ee362": { + "balance": "0x10f0cf064dd59200000" + }, + "0x2b241f037337eb4acc61849bd272ac133f7cdf4b": { + "balance": "0x500b6bca962ab8400000" + }, + "0x24b95ebef79500baa0eda72e77f877415df75c33": { + "balance": "0x3154c9729d05780000" + }, + "0x106ed5c719b5261477890425ae7551dc59bd255c": { + "balance": "0x2896a58c95be5880000" + }, + "0x5b2e2f1618552eab0db98add55637c2951f1fb19": { + "balance": "0x28a857425466f800000" + }, + "0x403145cb4ae7489fcc90cd985c6dc782b3cc4e44": { + "balance": "0x1453ff387b27cac0000" + }, + "0xe8be24f289443ee473bc76822f55098d89b91cc5": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xf6bc37b1d2a3788d589b6de212dc1713b2f6e78e": { + "balance": "0x10f0cf064dd59200000" + }, + "0x67fc527dce1785f0fb8bc7e518b1c669f7ecdfb5": { + "balance": "0xd02ab486cedc00000" + }, + "0x6580b1bc94390f04b397bd73e95d96ef11eaf3a8": { + "balance": "0x1158e460913d00000" + }, + "0x98bf4af3810b842387db70c14d46099626003d10": { + "balance": "0xd8d726b7177a800000" + }, + "0x17993d312aa1106957868f6a55a5e8f12f77c843": { + "balance": "0x1865e814f4142e8000" + }, + "0x0729b4b47c09eb16158464c8aa7fd9690b438839": { + "balance": "0x6c68ccd09b022c0000" + }, + "0xae70e69d2c4a0af818807b1a2705f79fd0b5dbc4": { + "balance": "0x35659ef93f0fc40000" + }, + "0x38b50146e71916a5448de12a4d742135dcf39833": { + "balance": "0x6d190c475169a200000" + }, + "0x38439aaa24e3636f3a18e020ea1da7e145160d86": { + "balance": "0x8cf23f909c0fa00000" + }, + "0x54b4429b182f0377be7e626939c5db6440f75d7a": { + "balance": "0x6acb3df27e1f880000" + }, + "0x7179726f5c71ae1b6d16a68428174e6b34b23646": { + "balance": "0x18ea250097cbaf60000" + }, + "0xc2ee91d3ef58c9d1a589844ea1ae3125d6c5ba69": { + "balance": "0x34957444b840e80000" + }, + "0x912304118b80473d9e9fe3ee458fbe610ffda2bb": { + "balance": "0xad78ebc5ac6200000" + }, + "0x3308b03466c27a17dfe1aafceb81e16d2934566f": { + "balance": "0x39992648a23c8a00000" + }, + "0x10346414bec6d3dcc44e50e54d54c2b8c3734e3e": { + "balance": "0xd8d726b7177a800000" + }, + "0x4fee50c5f988206b09a573469fb1d0b42ebb6dce": { + "balance": "0x6cee06ddbe15ec0000" + }, + "0x9ece1400800936c7c6485fcdd3626017d09afbf6": { + "balance": "0x10ce1d3d8cb3180000" + }, + "0xddf3ad76353810be6a89d731b787f6f17188612b": { + "balance": "0x43c33c1937564800000" + }, + "0x72402300e81d146c2e644e2bbda1da163ca3fb56": { + "balance": "0x17b7883c06916600000" + }, + "0xbb4b4a4b548070ff41432c9e08a0ca6fa7bc9f76": { + "balance": "0x2e141ea081ca080000" + }, + "0xc3dd58903886303b928625257ae1a013d71ae216": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xca6c818befd251361e02744068be99d8aa60b84a": { + "balance": "0x14542ba12a337c00000" + }, + "0xb8d2ddc66f308c0158ae3ccb7b869f7d199d7b32": { + "balance": "0x2dcbf4840eca000000" + }, + "0x8e486a0442d171c8605be348fee57eb5085eff0d": { + "balance": "0xd8d726b7177a800000" + }, + "0xa807104f2703d679f8deafc442befe849e42950b": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xbb61a04bffd57c10470d45c39103f64650347616": { + "balance": "0x3635c9adc5dea00000" + }, + "0xd1c45954a62b911ad701ff2e90131e8ceb89c95c": { + "balance": "0x4b91a2de457e880000" + }, + "0x5e65458be964ae449f71773704979766f8898761": { + "balance": "0x1ca7cc735b6f7c0000" + }, + "0xf9b37825f03073d31e249378c30c795c33f83af2": { + "balance": "0xad9aabf8c9bfc0000" + }, + "0xe309974ce39d60aadf2e69673251bf0e04760a10": { + "balance": "0xdc55fdb17647b0000" + }, + "0xd541ac187ad7e090522de6da3213e9a7f4439673": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xf33efc6397aa65fb53a8f07a0f893aae30e8bcee": { + "balance": "0x7cf2381f619f150000" + }, + "0xd2f1998e1cb1580cec4f6c047dcd3dcec54cf73c": { + "balance": "0xad78ebc5ac6200000" + }, + "0x0ed76c2c3b5d50ff8fb50b3eeacd681590be1c2d": { + "balance": "0x56bc75e2d63100000" + }, + "0x637d67d87f586f0a5a479e20ee13ea310a10b647": { + "balance": "0xa3a5926afa1e7300000" + }, + "0x1a5ee533acbfb3a2d76d5b685277b796c56a052b": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x323fca5ed77f699f9d9930f5ceeff8e56f59f03c": { + "balance": "0x487a9a304539440000" + }, + "0xa5fe2ce97f0e8c3856be0de5f4dcb2ce5d389a16": { + "balance": "0x13db0b8b6863e0000" + }, + "0x93258255b37c7f58f4b10673a932dd3afd90f4f2": { + "balance": "0x3635c9adc5dea00000" + }, + "0x950fe9c6cad50c18f11a9ed9c45740a6180612d0": { + "balance": "0x1b1ae4d6e2ef5000000" + }, + "0xee31167f9cc93b3c6465609d79db0cde90e8484c": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x6ebb5e6957aa821ef659b6018a393a504cae4450": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xbe305a796e33bbf7f9aeae6512959066efda1010": { + "balance": "0x24dce54d34a1a000000" + }, + "0x537f9d4d31ef70839d84b0d9cdb72b9afedbdf35": { + "balance": "0xed2b525841adfc00000" + }, + "0xfe9e1197d7974a7648dcc7a03112a88edbc9045d": { + "balance": "0x10afc1ade3b4ed40000" + }, + "0x99f77f998b20e0bcdcd9fc838641526cf25918ef": { + "balance": "0x61093d7c2c6d380000" + }, + "0x76ffc157ad6bf8d56d9a1a7fddbc0fea010aabf4": { + "balance": "0x3635c9adc5dea00000" + }, + "0xdefe9141f4704599159d7b223de42bffd80496b3": { + "balance": "0x56bc75e2d63100000" + }, + "0x7b1bf53a9cbe83a7dea434579fe72aac8d2a0cd0": { + "balance": "0xad4c8316a0b0c0000" + }, + "0x23ccc3c6acd85c2e460c4ffdd82bc75dc849ea14": { + "balance": "0xd8d726b7177a800000" + }, + "0x9f86a066edb61fcb5856de93b75c8c791864b97b": { + "balance": "0x6c6b935b8bbd400000" + }, + "0x871b8a8b51dea1989a5921f13ec1a955a515ad47": { + "balance": "0x1b1ae4d6e2ef5000000" + }, + "0x4efcd9c79fb4334ca6247b0a33bd9cc33208e272": { + "balance": "0x487a9a304539440000" + }, + "0x35ac1d3ed7464fa3db14e7729213ceaa378c095e": { + "balance": "0x52663ccab1e1c00000" + }, + "0xc69d663c8d60908391c8d236191533fdf7775613": { + "balance": "0x1a4aba225c20740000" + }, + "0xc2ed5ffdd1add855a2692fe062b5d618742360d4": { + "balance": "0x410d586a20a4c00000" + }, + "0x454f0141d721d33cbdc41018bd01119aa4784818": { + "balance": "0x14542ba12a337c00000" + }, + "0x6c8687e3417710bb8a93559021a1469e6a86bc77": { + "balance": "0x25b2da278d96b7b8000" + }, + "0xec5b198a00cfb55a97b5d53644cffa8a04d2ab45": { + "balance": "0x6c6b935b8bbd400000" + }, + "0xcd59f3dde77e09940befb6ee58031965cae7a336": { + "balance": "0x21e19e0c9bab2400000" + }, + "0x8eebec1a62c08b05a7d1d59180af9ff0d18e3f36": { + "balance": "0x1b1ae4d6e2ef500000" + } + } +} diff --git a/apps/indexer/lib/indexer/block/fetcher.ex b/apps/indexer/lib/indexer/block/fetcher.ex index 4155538e76..6a4eb3661b 100644 --- a/apps/indexer/lib/indexer/block/fetcher.ex +++ b/apps/indexer/lib/indexer/block/fetcher.ex @@ -189,7 +189,7 @@ defmodule Indexer.Block.Fetcher do BlockNumber.update(max_block.number) BlockNumber.update(min_block.number) - BlocksCache.update_blocks(blocks) + BlocksCache.update(blocks) end defp update_transactions_cache(transactions) do diff --git a/docs/env-variables.md b/docs/env-variables.md index 6a9cd6fee3..60c9eee442 100644 --- a/docs/env-variables.md +++ b/docs/env-variables.md @@ -6,7 +6,7 @@ Below is a table outlining the environment variables utilized by BlockScout. - This table is horizontally scrollable, version information is located in the last column. - Settings related to the `ETHEREUM_JSONRPC_VARIANT` variable and client related settings for running a full archive node with geth or parity are located in [this forum post](https://forum.poa.network/t/faq-what-settings-are-required-on-a-parity-or-geth-client/1805). - Additional information related to certain variables is available on the [ansible deployment](ansible-deployment.md) page. -- To set variables using the CLI, use the export command. For example: +- To set variables using the CLI, use the export command. For example: ```bash $ export ETHEREUM_JSONRPC_VARIANT=parity $ export COIN=POA @@ -53,6 +53,7 @@ $ export NETWORK=POA | `ADDRESS_WITH_BALANCES`
`_UPDATE_INTERVAL`| | Interval in seconds to restart the task, which calculates addresses with balances. | 30 * 60 | v1.3.9+ | | `LINK_TO_OTHER_EXPLORERS` | | true/false. If true, links to other explorers are added in the footer | (empty) | v1.3.0+ | | `COINMARKETCAP_PAGES` | | the number of pages on coinmarketcap to list in order to find token's price | 10 | v1.3.10+ | +| `CHAIN_SPEC_PATH` | | Chain specification path (absolute file system path or url) to import block emission reward ranges and genesis account balances from | (empty) | master | | `SUPPORTED_CHAINS` | | Array of supported chains that displays in the footer and in the chains dropdown. This var was introduced in this PR [#1900](https://github.com/poanetwork/blockscout/pull/1900) and looks like an array of JSON objects. | (empty) | v2.0.0+ | | `BLOCK_COUNT_CACHE_PERIOD ` | | time to live of cache in seconds. This var was introduced in [#1876](https://github.com/poanetwork/blockscout/pull/1876) | 600 | v2.0.0+ | | `ALLOWED_EVM_VERSIONS ` | | the comma-separated list of allowed EVM versions for contracts verification. This var was introduced in [#1964](https://github.com/poanetwork/blockscout/pull/1964) | "homestead, tangerineWhistle, spuriousDragon, byzantium, constantinople, petersburg" | v2.0.0+ |