diff --git a/CHANGELOG.md b/CHANGELOG.md index d3d0968625..60c0d36f9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - [#4931](https://github.com/blockscout/blockscout/pull/4931) - Web3 modal with Wallet Connect for Write contract page and Staking Dapp ### Fixes +- [#4979](https://github.com/blockscout/blockscout/pull/4979) - Store total gas_used in addresses table - [#4977](https://github.com/blockscout/blockscout/pull/4977) - Export token transfers on address: include transfers on contract itself - [#4976](https://github.com/blockscout/blockscout/pull/4976) - Handle :econnrefused in pending transactions fetcher - [#4965](https://github.com/blockscout/blockscout/pull/4965) - Fix search field appearance on medium size screens diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex index 7d917be3b1..7e7b146c01 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex @@ -84,15 +84,14 @@ defmodule BlockScoutWeb.AddressController do def address_counters(conn, %{"id" => address_hash_string}) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, address} <- Chain.hash_to_address(address_hash) do - {transaction_count, token_transfer_count, gas_usage_count, validation_count, crc_total_worth} = - address_counters(address) + {transaction_count, token_transfer_count, validation_count, crc_total_worth} = address_counters(address) - gas_usage_count_formatted = if gas_usage_count, do: gas_usage_count, else: 0 + address_gas_usage_from_db = address.gas_used || 0 json(conn, %{ transaction_count: transaction_count, token_transfer_count: token_transfer_count, - gas_usage_count: gas_usage_count_formatted, + gas_usage_count: address_gas_usage_from_db, validation_count: validation_count, crc_total_worth: crc_total_worth }) @@ -119,11 +118,6 @@ defmodule BlockScoutWeb.AddressController do token_transfers_count(address) end) - gas_usage_count_task = - Task.async(fn -> - gas_usage_count(address) - end) - validation_count_task = Task.async(fn -> validation_count(address) @@ -134,14 +128,17 @@ defmodule BlockScoutWeb.AddressController do crc_total_worth(address) end) + Task.start_link(fn -> + gas_usage_count(address) + end) + [ transaction_count_task, token_transfer_count_task, - gas_usage_count_task, validation_count_task, crc_total_worth_task ] - |> Task.yield_many(:timer.seconds(60)) + |> Task.yield_many(:infinity) |> Enum.map(fn {_task, res} -> case res do {:ok, result} -> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex index 84e4f6a784..0449eb1707 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/overview.html.eex @@ -242,7 +242,11 @@
- <%= render BlockScoutWeb.CommonComponentsView, "_loading_spinner.html", loading_text: gettext("Fetching gas used...") %> + <%= if @address.gas_used do %> + <%= Number.Delimit.number_to_delimited(@address.gas_used, precision: 0) %> + <% else %> + <%= render BlockScoutWeb.CommonComponentsView, "_loading_spinner.html", loading_text: gettext("Fetching gas used...") %> + <% end %>
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 9478570c66..39d8402344 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -398,7 +398,7 @@ msgid "Block number containing the transaction." msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/overview.html.eex:254 +#: lib/block_scout_web/templates/address/overview.html.eex:258 msgid "Block number in which the address was updated." msgstr "" @@ -420,7 +420,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/_tabs.html.eex:48 -#: lib/block_scout_web/templates/address/overview.html.eex:271 lib/block_scout_web/templates/address_validation/index.html.eex:15 +#: lib/block_scout_web/templates/address/overview.html.eex:275 lib/block_scout_web/templates/address_validation/index.html.eex:15 #: lib/block_scout_web/views/address_view.ex:356 msgid "Blocks Validated" msgstr "" @@ -1151,7 +1151,7 @@ msgid "Favorites" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/overview.html.eex:245 +#: lib/block_scout_web/templates/address/overview.html.eex:248 msgid "Fetching gas used..." msgstr "" @@ -1220,7 +1220,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/overview.html.eex:240 -#: lib/block_scout_web/templates/address/overview.html.eex:270 +#: lib/block_scout_web/templates/address/overview.html.eex:274 msgid "Gas used by the address." msgstr "" @@ -1377,7 +1377,7 @@ msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/overview.html.eex:255 +#: lib/block_scout_web/templates/address/overview.html.eex:259 msgid "Last Balance Update" msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 9478570c66..39d8402344 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -398,7 +398,7 @@ msgid "Block number containing the transaction." msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/overview.html.eex:254 +#: lib/block_scout_web/templates/address/overview.html.eex:258 msgid "Block number in which the address was updated." msgstr "" @@ -420,7 +420,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/_tabs.html.eex:48 -#: lib/block_scout_web/templates/address/overview.html.eex:271 lib/block_scout_web/templates/address_validation/index.html.eex:15 +#: lib/block_scout_web/templates/address/overview.html.eex:275 lib/block_scout_web/templates/address_validation/index.html.eex:15 #: lib/block_scout_web/views/address_view.ex:356 msgid "Blocks Validated" msgstr "" @@ -1151,7 +1151,7 @@ msgid "Favorites" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/overview.html.eex:245 +#: lib/block_scout_web/templates/address/overview.html.eex:248 msgid "Fetching gas used..." msgstr "" @@ -1220,7 +1220,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/overview.html.eex:240 -#: lib/block_scout_web/templates/address/overview.html.eex:270 +#: lib/block_scout_web/templates/address/overview.html.eex:274 msgid "Gas used by the address." msgstr "" @@ -1377,7 +1377,7 @@ msgid "JSON RPC error" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/overview.html.eex:255 +#: lib/block_scout_web/templates/address/overview.html.eex:259 msgid "Last Balance Update" msgstr "" diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 5a621035c1..e4e0040753 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -867,7 +867,7 @@ defmodule Explorer.Chain do Repo.aggregate(to_address_query, :count, :hash, timeout: :infinity) end - @spec address_to_incoming_transaction_gas_usage(Hash.Address.t()) :: non_neg_integer() + @spec address_to_incoming_transaction_gas_usage(Hash.Address.t()) :: Decimal.t() | nil def address_to_incoming_transaction_gas_usage(address_hash) do to_address_query = from( @@ -878,7 +878,7 @@ defmodule Explorer.Chain do Repo.aggregate(to_address_query, :sum, :gas_used, timeout: :infinity) end - @spec address_to_outcoming_transaction_gas_usage(Hash.Address.t()) :: non_neg_integer() + @spec address_to_outcoming_transaction_gas_usage(Hash.Address.t()) :: Decimal.t() | nil def address_to_outcoming_transaction_gas_usage(address_hash) do to_address_query = from( @@ -2527,12 +2527,12 @@ defmodule Explorer.Chain do Repo.aggregate(query, :count, timeout: :infinity) end - @spec address_to_gas_usage_count(Address.t()) :: non_neg_integer() + @spec address_to_gas_usage_count(Address.t()) :: Decimal.t() | nil def address_to_gas_usage_count(address) do if contract?(address) do incoming_transaction_gas_usage = address_to_incoming_transaction_gas_usage(address.hash) - if incoming_transaction_gas_usage == 0 do + if Decimal.cmp(incoming_transaction_gas_usage, 0) == :eq do address_to_outcoming_transaction_gas_usage(address.hash) else incoming_transaction_gas_usage diff --git a/apps/explorer/lib/explorer/chain/address.ex b/apps/explorer/lib/explorer/chain/address.ex index c310600789..7382cb7d07 100644 --- a/apps/explorer/lib/explorer/chain/address.ex +++ b/apps/explorer/lib/explorer/chain/address.ex @@ -25,7 +25,7 @@ defmodule Explorer.Chain.Address do alias Explorer.Chain.Cache.NetVersion - @optional_attrs ~w(contract_code fetched_coin_balance fetched_coin_balance_block_number nonce decompiled verified)a + @optional_attrs ~w(contract_code fetched_coin_balance fetched_coin_balance_block_number nonce decompiled verified gas_used)a @required_attrs ~w(hash)a @allowed_attrs @optional_attrs ++ @required_attrs @@ -58,7 +58,8 @@ defmodule Explorer.Chain.Address do contracts_creation_transaction: %Ecto.Association.NotLoaded{} | Transaction.t(), inserted_at: DateTime.t(), updated_at: DateTime.t(), - nonce: non_neg_integer() | nil + nonce: non_neg_integer() | nil, + gas_used: non_neg_integer() | nil } @derive {Poison.Encoder, @@ -95,6 +96,7 @@ defmodule Explorer.Chain.Address do field(:verified, :boolean, default: false) field(:has_decompiled_code?, :boolean, virtual: true) field(:stale?, :boolean, virtual: true) + field(:gas_used, :integer) has_one(:smart_contract, SmartContract) has_one(:token, Token, foreign_key: :contract_address_hash) diff --git a/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex b/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex index fbffbe1ccf..5dd1a825b1 100644 --- a/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex +++ b/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex @@ -4,7 +4,8 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do """ use GenServer - alias Explorer.Chain + alias Ecto.Changeset + alias Explorer.{Chain, Repo} @cache_name :address_transactions_gas_usage_counter @last_update_key "last_update" @@ -16,7 +17,7 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do read_concurrency: true ] - config = Application.get_env(:explorer, Explorer.Counters.AddressTransactionsGasUsageCounter) + config = Application.get_env(:explorer, __MODULE__) @enable_consolidation Keyword.get(config, :enable_consolidation) @spec start_link(term()) :: GenServer.on_start() @@ -51,7 +52,7 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do update_cache(address) end - address_hash_string = get_address_hash_string(address) + address_hash_string = to_string(address.hash) fetch_from_cache("hash_#{address_hash_string}") end @@ -59,7 +60,7 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do defp cache_expired?(address) do cache_period = address_transactions_gas_usage_counter_cache_period() - address_hash_string = get_address_hash_string(address) + address_hash_string = to_string(address.hash) updated_at = fetch_from_cache("hash_#{address_hash_string}_#{@last_update_key}") cond do @@ -70,10 +71,11 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do end defp update_cache(address) do - address_hash_string = get_address_hash_string(address) + address_hash_string = to_string(address.hash) put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", current_time()) new_data = Chain.address_to_gas_usage_count(address) put_into_cache("hash_#{address_hash_string}", new_data) + put_into_db(address, new_data) end defp fetch_from_cache(key) do @@ -90,8 +92,12 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do :ets.insert(@cache_name, {key, value}) end - defp get_address_hash_string(address) do - Base.encode16(address.hash.bytes, case: :lower) + defp put_into_db(_address, value) when is_nil(value), do: :ignore + + defp put_into_db(address, value) do + address + |> Changeset.change(%{gas_used: Decimal.to_integer(value)}) + |> Repo.update() end defp current_time do diff --git a/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex b/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex index c5488afd99..9df1ea7ebd 100644 --- a/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex +++ b/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex @@ -51,7 +51,7 @@ defmodule Explorer.Counters.AddressTokenTransfersCounter do update_cache(address) end - address_hash_string = get_address_hash_string(address) + address_hash_string = to_string(address.hash) fetch_from_cache("hash_#{address_hash_string}") end @@ -59,7 +59,7 @@ defmodule Explorer.Counters.AddressTokenTransfersCounter do defp cache_expired?(address) do cache_period = address_token_transfers_counter_cache_period() - address_hash_string = get_address_hash_string(address) + address_hash_string = to_string(address.hash) updated_at = fetch_from_cache("hash_#{address_hash_string}_#{@last_update_key}") cond do @@ -70,7 +70,7 @@ defmodule Explorer.Counters.AddressTokenTransfersCounter do end defp update_cache(address) do - address_hash_string = get_address_hash_string(address) + address_hash_string = to_string(address.hash) put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", current_time()) new_data = Chain.address_to_token_transfer_count(address) put_into_cache("hash_#{address_hash_string}", new_data) @@ -90,10 +90,6 @@ defmodule Explorer.Counters.AddressTokenTransfersCounter do :ets.insert(@cache_name, {key, value}) end - defp get_address_hash_string(address) do - Base.encode16(address.hash.bytes, case: :lower) - end - defp current_time do utc_now = DateTime.utc_now() diff --git a/apps/explorer/lib/explorer/counters/address_transactions_counter.ex b/apps/explorer/lib/explorer/counters/address_transactions_counter.ex index ac73176e45..487f04e7eb 100644 --- a/apps/explorer/lib/explorer/counters/address_transactions_counter.ex +++ b/apps/explorer/lib/explorer/counters/address_transactions_counter.ex @@ -51,7 +51,7 @@ defmodule Explorer.Counters.AddressTransactionsCounter do update_cache(address) end - address_hash_string = get_address_hash_string(address) + address_hash_string = to_string(address.hash) fetch_from_cache("hash_#{address_hash_string}") end @@ -59,7 +59,7 @@ defmodule Explorer.Counters.AddressTransactionsCounter do defp cache_expired?(address) do cache_period = address_transactions_counter_cache_period() - address_hash_string = get_address_hash_string(address) + address_hash_string = to_string(address.hash) updated_at = fetch_from_cache("hash_#{address_hash_string}_#{@last_update_key}") cond do @@ -70,7 +70,7 @@ defmodule Explorer.Counters.AddressTransactionsCounter do end defp update_cache(address) do - address_hash_string = get_address_hash_string(address) + address_hash_string = to_string(address.hash) put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", current_time()) new_data = Chain.address_to_transaction_count(address) put_into_cache("hash_#{address_hash_string}", new_data) @@ -90,10 +90,6 @@ defmodule Explorer.Counters.AddressTransactionsCounter do :ets.insert(@cache_name, {key, value}) end - defp get_address_hash_string(address) do - Base.encode16(address.hash.bytes, case: :lower) - end - defp current_time do utc_now = DateTime.utc_now() diff --git a/apps/explorer/lib/explorer/counters/token_holders_counter.ex b/apps/explorer/lib/explorer/counters/token_holders_counter.ex index 00681b985f..3b3380eea5 100644 --- a/apps/explorer/lib/explorer/counters/token_holders_counter.ex +++ b/apps/explorer/lib/explorer/counters/token_holders_counter.ex @@ -53,7 +53,7 @@ defmodule Explorer.Counters.TokenHoldersCounter do end) end - address_hash_string = get_address_hash_string(address_hash) + address_hash_string = to_string(address_hash) fetch_from_cache("hash_#{address_hash_string}") end @@ -61,7 +61,7 @@ defmodule Explorer.Counters.TokenHoldersCounter do defp cache_expired?(address_hash) do cache_period = token_holders_counter_cache_period() - address_hash_string = get_address_hash_string(address_hash) + address_hash_string = to_string(address_hash) updated_at = fetch_from_cache("hash_#{address_hash_string}_#{@last_update_key}") cond do @@ -72,7 +72,7 @@ defmodule Explorer.Counters.TokenHoldersCounter do end defp update_cache(address_hash) do - address_hash_string = get_address_hash_string(address_hash) + address_hash_string = to_string(address_hash) put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", current_time()) new_data = Chain.count_token_holders_from_token_hash(address_hash) put_into_cache("hash_#{address_hash_string}", new_data) @@ -92,10 +92,6 @@ defmodule Explorer.Counters.TokenHoldersCounter do :ets.insert(@cache_name, {key, value}) end - defp get_address_hash_string(address_hash) do - Base.encode16(address_hash.bytes, case: :lower) - end - defp current_time do utc_now = DateTime.utc_now() diff --git a/apps/explorer/lib/explorer/counters/token_transfers_counter.ex b/apps/explorer/lib/explorer/counters/token_transfers_counter.ex index 2026be6519..ce8eb7f854 100644 --- a/apps/explorer/lib/explorer/counters/token_transfers_counter.ex +++ b/apps/explorer/lib/explorer/counters/token_transfers_counter.ex @@ -53,7 +53,7 @@ defmodule Explorer.Counters.TokenTransfersCounter do end) end - address_hash_string = get_address_hash_string(address_hash) + address_hash_string = to_string(address_hash) fetch_from_cache("hash_#{address_hash_string}") end @@ -61,7 +61,7 @@ defmodule Explorer.Counters.TokenTransfersCounter do defp cache_expired?(address_hash) do cache_period = token_transfers_counter_cache_period() - address_hash_string = get_address_hash_string(address_hash) + address_hash_string = to_string(address_hash) updated_at = fetch_from_cache("hash_#{address_hash_string}_#{@last_update_key}") cond do @@ -72,7 +72,7 @@ defmodule Explorer.Counters.TokenTransfersCounter do end defp update_cache(address_hash) do - address_hash_string = get_address_hash_string(address_hash) + address_hash_string = to_string(address_hash) put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", current_time()) new_data = Chain.count_token_transfers_from_token_hash(address_hash) put_into_cache("hash_#{address_hash_string}", new_data) @@ -92,10 +92,6 @@ defmodule Explorer.Counters.TokenTransfersCounter do :ets.insert(@cache_name, {key, value}) end - defp get_address_hash_string(address_hash) do - Base.encode16(address_hash.bytes, case: :lower) - end - defp current_time do utc_now = DateTime.utc_now() diff --git a/apps/explorer/priv/repo/migrations/20211204184037_address_add_gas_used.exs b/apps/explorer/priv/repo/migrations/20211204184037_address_add_gas_used.exs new file mode 100644 index 0000000000..0494e0a9e6 --- /dev/null +++ b/apps/explorer/priv/repo/migrations/20211204184037_address_add_gas_used.exs @@ -0,0 +1,9 @@ +defmodule Explorer.Repo.Migrations.AddressAddGasUsed do + use Ecto.Migration + + def change do + alter table(:addresses) do + add(:gas_used, :integer, null: true) + end + end +end diff --git a/apps/explorer/priv/repo/migrations/20211206071033_modify_address_gas_used_bigint.exs b/apps/explorer/priv/repo/migrations/20211206071033_modify_address_gas_used_bigint.exs new file mode 100644 index 0000000000..5fecbe5c32 --- /dev/null +++ b/apps/explorer/priv/repo/migrations/20211206071033_modify_address_gas_used_bigint.exs @@ -0,0 +1,15 @@ +defmodule Explorer.Repo.Migrations.ModifyAddressGasUsedBignit do + use Ecto.Migration + + def up do + alter table(:addresses) do + modify(:gas_used, :bigint) + end + end + + def down do + alter table(:addresses) do + modify(:gas_used, :integer) + end + end +end