From 1e4b5c25175abdc188b571600b387061cbe651dd Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 23 Apr 2019 11:18:05 +0300 Subject: [PATCH 001/191] add pagination to addresses query --- .../lib/block_scout_web/chain.ex | 4 +++ apps/explorer/lib/explorer/chain.ex | 20 ++++++++++---- apps/explorer/test/explorer/chain_test.exs | 27 +++++++++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/chain.ex b/apps/block_scout_web/lib/block_scout_web/chain.ex index ebe196739c..b2fd0a188d 100644 --- a/apps/block_scout_web/lib/block_scout_web/chain.ex +++ b/apps/block_scout_web/lib/block_scout_web/chain.ex @@ -81,6 +81,10 @@ defmodule BlockScoutWeb.Chain do Map.merge(params, paging_params(List.last(list))) end + def paging_options(%{"hash" => hash, "fetched_coin_balance" => fetched_coin_balance}) do + [paging_options: %{@default_paging_options | key: {fetched_coin_balance, hash}}] + end + def paging_options(%{ "block_number" => block_number_string, "transaction_index" => transaction_index_string, diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index b45e0d13e4..e2a68ccbe9 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1121,17 +1121,21 @@ defmodule Explorer.Chain do """ @spec list_top_addresses :: [{Address.t(), non_neg_integer()}] - def list_top_addresses do - query = + def list_top_addresses(options \\ []) do + paging_options = Keyword.get(options, :paging_options, @default_paging_options) + + base_query = from(a in Address, where: a.fetched_coin_balance > ^0, order_by: [desc: a.fetched_coin_balance, asc: a.hash], preload: [:names], - select: {a, fragment("coalesce(1 + ?, 0)", a.nonce)}, - limit: 250 + select: {a, fragment("coalesce(1 + ?, 0)", a.nonce)} ) - Repo.all(query) + base_query + |> page_addresses(paging_options) + |> limit(^paging_options.page_size) + |> Repo.all() end @doc """ @@ -2267,6 +2271,12 @@ defmodule Explorer.Chain do end) end + defp page_addresses(query, %PagingOptions{key: nil}), do: query + + defp page_addresses(query, %PagingOptions{key: {coin_balance, hash}}) do + where(query, [address], address.fetched_coin_balance <= ^coin_balance and address.hash > ^hash) + end + defp page_blocks(query, %PagingOptions{key: nil}), do: query defp page_blocks(query, %PagingOptions{key: {block_number}}) do diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index 36edace635..a9b479c3bd 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -1415,6 +1415,33 @@ defmodule Explorer.ChainTest do |> Enum.map(fn {address, _transaction_count} -> address end) |> Enum.map(& &1.hash) end + + test "paginates addresses" do + test_hashes = + 4..0 + |> Enum.map(&Explorer.Chain.Hash.cast(Explorer.Chain.Hash.Address, &1)) + |> Enum.map(&elem(&1, 1)) + + result = + 4..1 + |> Enum.map(&insert(:address, fetched_coin_balance: &1, hash: Enum.fetch!(test_hashes, &1 - 1))) + |> Enum.map(& &1.hash) + + options = [paging_options: %PagingOptions{page_size: 1}] + + [{top_address, _}] = Chain.list_top_addresses(options) + assert top_address.hash == List.first(result) + + tail_options = [ + paging_options: %PagingOptions{key: {top_address.fetched_coin_balance.value, top_address.hash}, page_size: 3} + ] + + tail_result = tail_options |> Chain.list_top_addresses() |> Enum.map(fn {address, _} -> address.hash end) + + [_ | expected_tail] = result + + assert tail_result == expected_tail + end end describe "stream_blocks_without_rewards/2" do From 75cf4c9f271fcc424eb0684387f4e8269cd00334 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 23 Apr 2019 13:27:59 +0300 Subject: [PATCH 002/191] add addresses pagination to view --- .../lib/block_scout_web/chain.ex | 15 ++++++++-- .../controllers/address_controller.ex | 30 +++++++++++++++++-- .../templates/address/index.html.eex | 9 +++++- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/chain.ex b/apps/block_scout_web/lib/block_scout_web/chain.ex index b2fd0a188d..5903db1144 100644 --- a/apps/block_scout_web/lib/block_scout_web/chain.ex +++ b/apps/block_scout_web/lib/block_scout_web/chain.ex @@ -25,7 +25,8 @@ defmodule BlockScoutWeb.Chain do InternalTransaction, Log, TokenTransfer, - Transaction + Transaction, + Wei } alias Explorer.PagingOptions @@ -82,7 +83,13 @@ defmodule BlockScoutWeb.Chain do end def paging_options(%{"hash" => hash, "fetched_coin_balance" => fetched_coin_balance}) do - [paging_options: %{@default_paging_options | key: {fetched_coin_balance, hash}}] + with {coin_balance, ""} <- Integer.parse(fetched_coin_balance), + {:ok, address_hash} <- string_to_address_hash(hash) do + [paging_options: %{@default_paging_options | key: {%Wei{value: Decimal.new(coin_balance)}, address_hash}}] + else + _ -> + [paging_options: @default_paging_options] + end end def paging_options(%{ @@ -175,6 +182,10 @@ defmodule BlockScoutWeb.Chain do end end + defp paging_params({%Address{hash: hash, fetched_coin_balance: fetched_coin_balance}, _}) do + %{"hash" => hash, "fetched_coin_balance" => Decimal.to_string(fetched_coin_balance.value)} + end + defp paging_params({%Reward{block: %{number: number}}, _}) do %{"block_number" => number, "index" => 0} end 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 a0c443aee6..730b09eb8f 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 @@ -1,16 +1,40 @@ defmodule BlockScoutWeb.AddressController do use BlockScoutWeb, :controller + import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] + alias Explorer.{Chain, Market} alias Explorer.Chain.Address alias Explorer.ExchangeRates.Token - def index(conn, _params) do + def index(conn, params) do + addresses = + params + |> paging_options() + |> Chain.list_top_addresses() + + {addresses_page, next_page} = split_list_by_page(addresses) + + next_page_path = + case next_page_params(next_page, addresses_page, params) do + nil -> + nil + + next_page_params -> + address_path( + conn, + :index, + next_page_params + ) + end + render(conn, "index.html", - address_tx_count_pairs: Chain.list_top_addresses(), + address_tx_count_pairs: addresses_page, + page_address_count: Enum.count(addresses_page), address_count: Chain.count_addresses_with_balance_from_cache(), exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), - total_supply: Chain.total_supply() + total_supply: Chain.total_supply(), + next_page_path: next_page_path ) end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex index e0a10a8e65..cf4e0efb95 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex @@ -3,7 +3,9 @@

<%= gettext "Addresses" %>

- <%= gettext "Showing 250 addresses of" %> + <%= gettext "Showing " %> + <%= Cldr.Number.to_string!(@page_address_count, format: "#,###") %> + <%= gettext " addresses of" %> <%= Cldr.Number.to_string!(@address_count, format: "#,###") %> <%= gettext "total addresses with a balance" %>

@@ -15,6 +17,11 @@ total_supply: @total_supply, tx_count: tx_count, validation_count: validation_count(address) %> <% end %> + <%= if @next_page_path do %> + " class="button button-secondary button-small float-right mt-4"> + <%= gettext("Next") %> + + <% end %>
From 78036abeb58af5706d1ecbc0b495cbaa629f9d3b Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 23 Apr 2019 13:30:47 +0300 Subject: [PATCH 003/191] add CHANGELOG entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f88ff0a14..4a03165c3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features + - [#1812](https://github.com/poanetwork/blockscout/pull/1812) - add pagination to addresses page + ### Fixes ### Chore From d5356c47841f46ad70f36fc415151dc2b6dd7c88 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 23 Apr 2019 13:31:53 +0300 Subject: [PATCH 004/191] fix gettext --- apps/block_scout_web/priv/gettext/default.pot | 18 ++++++++++++------ .../priv/gettext/en/LC_MESSAGES/default.po | 18 ++++++++++++------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index c4d03d82ec..d38e4fadfc 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -592,6 +592,7 @@ msgid "Newer" msgstr "" #, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:22 #: lib/block_scout_web/templates/address_token/index.html.eex:25 msgid "Next" msgstr "" @@ -755,11 +756,6 @@ msgstr "" msgid "Showing" msgstr "" -#, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:6 -msgid "Showing 250 addresses of" -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8 #: lib/block_scout_web/views/transaction_view.ex:210 @@ -1114,7 +1110,7 @@ msgid "string" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:8 +#: lib/block_scout_web/templates/address/index.html.eex:10 msgid "total addresses with a balance" msgstr "" @@ -1744,3 +1740,13 @@ msgstr "" #: lib/block_scout_web/templates/transaction/overview.html.eex:165 msgid "ERC-721" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:8 +msgid " addresses of" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:6 +msgid "Showing " +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 26503607c4..fd1b565304 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 @@ -592,6 +592,7 @@ msgid "Newer" msgstr "" #, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:22 #: lib/block_scout_web/templates/address_token/index.html.eex:25 msgid "Next" msgstr "" @@ -755,11 +756,6 @@ msgstr "" msgid "Showing" msgstr "" -#, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:6 -msgid "Showing 250 addresses of" -msgstr "" - #, elixir-format #: lib/block_scout_web/templates/transaction/_emission_reward_tile.html.eex:8 #: lib/block_scout_web/views/transaction_view.ex:210 @@ -1114,7 +1110,7 @@ msgid "string" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:8 +#: lib/block_scout_web/templates/address/index.html.eex:10 msgid "total addresses with a balance" msgstr "" @@ -1744,3 +1740,13 @@ msgstr "" #: lib/block_scout_web/templates/transaction/overview.html.eex:165 msgid "ERC-721" msgstr "" + +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/address/index.html.eex:8 +msgid " addresses of" +msgstr "" + +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/address/index.html.eex:6 +msgid "Showing " +msgstr "" From 4404645e0f73dbe79a54e923ac5c97c0e33998cc Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 23 Apr 2019 19:20:52 +0300 Subject: [PATCH 005/191] add style to every line of decompiled contract --- .../views/address_decompiled_contract_view.ex | 58 +++++++++++++++++-- .../address_decompiled_contract_view_test.exs | 16 ++++- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex index 148d82b818..3382f681a6 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex @@ -18,13 +18,59 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do } def highlight_decompiled_code(code) do - @colors - |> Enum.reduce(code, fn {symbol, rgb}, acc -> - String.replace(acc, symbol, "") + {_, result} = + @colors + |> Enum.reduce(code, fn {symbol, rgb}, acc -> + String.replace(acc, symbol, "") + end) + |> String.replace("\e[1m", "") + |> String.replace("»", "»") + |> String.replace("\e[0m", "") + |> String.split(~r/\|\<\/span\>/, include_captures: true, trim: true) + |> Enum.reduce({"", []}, fn part, {style, acc} -> + new_style = + cond do + String.contains?(part, " part + part == "" -> "" + true -> style + end + + new_part = + cond do + part == "" -> + "" + + part == "" -> + "" + + part == new_style -> + "" + + new_style == "" -> + part + + true -> + result = + part + |> String.split("\n") + |> Enum.reduce("", fn p, a -> + a <> new_style <> p <> "\n" + end) + + if String.ends_with?(part, "\n") do + result + else + String.slice(result, 0..-2) + end + end + + {new_style, [new_part | acc]} + end) + + result + |> Enum.reduce("", fn part, acc -> + part <> acc end) - |> String.replace("\e[1m", "") - |> String.replace("»", "»") - |> String.replace("\e[0m", "") |> add_line_numbers() end diff --git a/apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs index 9e12503c3a..c3ff123584 100644 --- a/apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs +++ b/apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs @@ -56,7 +56,21 @@ defmodule BlockScoutWeb.AddressDecompiledContractViewTest do result = AddressDecompiledContractView.highlight_decompiled_code(code) assert result == - " #\n # eveem.org 6 Feb 2019\n # Decompiled source of 0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875\n #\n # Let's make the world open source\n # \n #\n # I failed with these:\n # - unknowne77c646d(?)\n # - transferFromWithData(address _from, address _to, uint256 _value, bytes _data)\n # All the rest is below.\n #\n\n\n # Storage definitions and getters\n\n def storage:\n allowance is uint256 => uint256 # mask(256, 0) at storage #2\n stor4 is uint256 => uint8 # mask(8, 0) at storage #4\n\n def allowance(address _owner, address _spender) payable: \n require (calldata.size - 4) >= 64\n return allowance[sha3(((320 - 1) and (320 - 1) and _owner), 1), ((320 - 1) and _spender and (320 - 1))]\n\n\n #\n # Regular functions - see Tutorial for understanding quirks of the code\n #\n\n\n # folder failed in this function - may be terribly long, sorry\n def unknownc47d033b(?) payable: \n if (calldata.size - 4) < 32:\n revert\n else:\n if not (320 - 1) or not cd[4]:\n revert\n else:\n mem[0] = (320 - 1) and (320 - 1) and cd[4]\n mem[32] = 4\n mem[96] = bool(stor4[((320 - 1) and (320 - 1) and cd[4])])\n return bool(stor4[((320 - 1) and (320 - 1) and cd[4])])\n\n def _fallback() payable: # default function\n revert\n\n" + " #\n # eveem.org 6 Feb 2019\n # Decompiled source of 0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875\n #\n # Let's make the world open source\n # \n #\n # I failed with these:\n # - unknowne77c646d(?)\n # - transferFromWithData(address _from, address _to, uint256 _value, bytes _data)\n # All the rest is below.\n #\n\n\n # Storage definitions and getters\n\n def storage:\n allowance is uint256 => uint256 # mask(256, 0) at storage #2\n stor4 is uint256 => uint8 # mask(8, 0) at storage #4\n\n def allowance(address _owner, address _spender) payable: 64\n return allowance[sha3(((320 - 1) and (320 - 1) and _owner), 1), ((320 - 1) and _spender and (320 - 1))]\n\n\n #\n # Regular functions - see Tutorial for understanding quirks of the code\n #\n\n\n # folder failed in this function - may be terribly long, sorry\n def unknownc47d033b(?) payable: not cd[4]:\n revert\n else:\n mem[0]cd[4]\n mem[32] = 4\n mem[96] = bool(stor4[((320 - 1) and (320 - 1) and cd[4])])\n return bool(stor4[((320 - 1) and (320 - 1) and cd[4])])\n\n def _fallback() payable: # default function\n revert\n\n" + end + + test "adds style span to every line" do + code = """ + # + # eveem.org 6 Feb 2019 + # Decompiled source of 0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875 + # + # Let's make the world open source + #  + """ + + assert AddressDecompiledContractView.highlight_decompiled_code(code) == + " #\n # eveem.org 6 Feb 2019\n # Decompiled source of 0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875\n #\n # Let's make the world open source\n # \n\n" end end From 326ea32a775173af054aa5f5571c8ddb810a8f7c Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 23 Apr 2019 19:26:08 +0300 Subject: [PATCH 006/191] fix credo --- .../views/address_decompiled_contract_view.ex | 59 ++++++++++--------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex index 3382f681a6..1418255594 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex @@ -35,34 +35,7 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do true -> style end - new_part = - cond do - part == "" -> - "" - - part == "" -> - "" - - part == new_style -> - "" - - new_style == "" -> - part - - true -> - result = - part - |> String.split("\n") - |> Enum.reduce("", fn p, a -> - a <> new_style <> p <> "\n" - end) - - if String.ends_with?(part, "\n") do - result - else - String.slice(result, 0..-2) - end - end + new_part = new_part(part, new_style) {new_style, [new_part | acc]} end) @@ -87,4 +60,34 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do acc <> "#{line}\n" end) end + + defp new_part(part, new_style) do + cond do + part == "" -> + "" + + part == "" -> + "" + + part == new_style -> + "" + + new_style == "" -> + part + + true -> + result = + part + |> String.split("\n") + |> Enum.reduce("", fn p, a -> + a <> new_style <> p <> "\n" + end) + + if String.ends_with?(part, "\n") do + result + else + String.slice(result, 0..-2) + end + end + end end From 718c1411848374ebe5e9d8ceb459c8f5294eb17e Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 24 Apr 2019 10:42:03 +0300 Subject: [PATCH 007/191] fix line numbers --- apps/block_scout_web/assets/css/_code.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/block_scout_web/assets/css/_code.scss b/apps/block_scout_web/assets/css/_code.scss index a3c4f5823c..510352ad6f 100644 --- a/apps/block_scout_web/assets/css/_code.scss +++ b/apps/block_scout_web/assets/css/_code.scss @@ -14,7 +14,7 @@ pre { .pre-decompiled code::before { content: counter(line); display: inline-block; - width: flex; + width: 3em; border-right: 1px solid #ddd; padding: 0 .5em; margin-right: .5em; From d733a5d0f2a9eea957654ad2ceccd05b2224aec0 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 24 Apr 2019 15:13:33 +0300 Subject: [PATCH 008/191] add Back button --- .../controllers/address_controller.ex | 17 +++++++++++++++-- .../templates/address/index.html.eex | 18 ++++++++++++------ 2 files changed, 27 insertions(+), 8 deletions(-) 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 730b09eb8f..6f834034cf 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 @@ -21,10 +21,12 @@ defmodule BlockScoutWeb.AddressController do nil next_page_params -> + next_params = Map.put(next_page_params, "prev_page_path", cur_page_path(conn, params)) + address_path( conn, :index, - next_page_params + next_params ) end @@ -34,7 +36,8 @@ defmodule BlockScoutWeb.AddressController do address_count: Chain.count_addresses_with_balance_from_cache(), exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), total_supply: Chain.total_supply(), - next_page_path: next_page_path + next_page_path: next_page_path, + prev_page_path: params["prev_page_path"] ) end @@ -49,4 +52,14 @@ defmodule BlockScoutWeb.AddressController do def validation_count(%Address{} = address) do Chain.address_to_validation_count(address) end + + defp cur_page_path(conn, %{"hash" => _hash, "fetched_coin_balance" => _balance} = params) do + address_path( + conn, + :index, + params + ) + end + + defp cur_page_path(conn, _), do: address_path(conn, :index) end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex index cf4e0efb95..535b732f44 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex @@ -8,8 +8,19 @@ <%= gettext " addresses of" %> <%= Cldr.Number.to_string!(@address_count, format: "#,###") %> <%= gettext "total addresses with a balance" %> -

+ <%= if @next_page_path do %> + " class="button button-secondary button-small float-right mt-0 ml-1"> + <%= gettext("Next") %> + + <% end %> + <%= if @prev_page_path do %> + " class="button button-secondary button-small float-right mt-0"> + <%= gettext("Back") %> + + <% end %> +

+
<%= for {{address, tx_count}, index} <- Enum.with_index(@address_tx_count_pairs, 1) do %> <%= render "_tile.html", @@ -17,11 +28,6 @@ total_supply: @total_supply, tx_count: tx_count, validation_count: validation_count(address) %> <% end %> - <%= if @next_page_path do %> - " class="button button-secondary button-small float-right mt-4"> - <%= gettext("Next") %> - - <% end %> From e22ef81457d908ccc2ae35d4bac201e9ec19c881 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 24 Apr 2019 15:42:43 +0300 Subject: [PATCH 009/191] add page number --- .../controllers/address_controller.ex | 20 ++++++++++++++++--- .../templates/address/index.html.eex | 2 ++ 2 files changed, 19 insertions(+), 3 deletions(-) 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 6f834034cf..3d43ed7054 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 @@ -15,13 +15,24 @@ defmodule BlockScoutWeb.AddressController do {addresses_page, next_page} = split_list_by_page(addresses) + cur_page_number = + cond do + !params["prev_page_number"] -> 1 + params["next_page"] -> String.to_integer(params["prev_page_number"]) + 1 + params["prev_page"] -> String.to_integer(params["prev_page_number"]) - 1 + end + next_page_path = case next_page_params(next_page, addresses_page, params) do nil -> nil next_page_params -> - next_params = Map.put(next_page_params, "prev_page_path", cur_page_path(conn, params)) + next_params = + next_page_params + |> Map.put("prev_page_path", cur_page_path(conn, params)) + |> Map.put("next_page", true) + |> Map.put("prev_page_number", cur_page_number) address_path( conn, @@ -37,7 +48,8 @@ defmodule BlockScoutWeb.AddressController do exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), total_supply: Chain.total_supply(), next_page_path: next_page_path, - prev_page_path: params["prev_page_path"] + prev_page_path: params["prev_page_path"], + cur_page_number: cur_page_number ) end @@ -54,10 +66,12 @@ defmodule BlockScoutWeb.AddressController do end defp cur_page_path(conn, %{"hash" => _hash, "fetched_coin_balance" => _balance} = params) do + new_params = Map.put(params, "next_page", false) + address_path( conn, :index, - params + new_params ) end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex index 535b732f44..ff84c71c05 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex @@ -8,6 +8,8 @@ <%= gettext " addresses of" %> <%= Cldr.Number.to_string!(@address_count, format: "#,###") %> <%= gettext "total addresses with a balance" %> + <%= gettext " (page" %> + <%= Cldr.Number.to_string!(@cur_page_number, format: "#,###)") %> <%= if @next_page_path do %> " class="button button-secondary button-small float-right mt-0 ml-1"> From 760b94d68fb95409b515f2e194be054fe5b04f1b Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 24 Apr 2019 15:46:10 +0300 Subject: [PATCH 010/191] fix gettext --- apps/block_scout_web/priv/gettext/default.pot | 27 ++++++++++++++++++- .../priv/gettext/en/LC_MESSAGES/default.po | 27 ++++++++++++++++++- apps/explorer/lib/explorer/chain.ex | 2 +- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 410a821df2..16d92c38bf 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -592,7 +592,7 @@ msgid "Newer" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:22 +#: lib/block_scout_web/templates/address/index.html.eex:16 #: lib/block_scout_web/templates/address_token/index.html.eex:25 msgid "Next" msgstr "" @@ -1740,3 +1740,28 @@ msgstr "" #: lib/block_scout_web/templates/transaction/overview.html.eex:165 msgid "ERC-721" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:11 +msgid " (page" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:8 +msgid " addresses of" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:21 +msgid "Back" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:6 +msgid "Showing " +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/chain/show.html.eex:58 +msgid "Total blocks" +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 547f288ae4..f8ad214ea1 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 @@ -592,7 +592,7 @@ msgid "Newer" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:22 +#: lib/block_scout_web/templates/address/index.html.eex:16 #: lib/block_scout_web/templates/address_token/index.html.eex:25 msgid "Next" msgstr "" @@ -1740,3 +1740,28 @@ msgstr "" #: lib/block_scout_web/templates/transaction/overview.html.eex:165 msgid "ERC-721" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:11 +msgid " (page" +msgstr "" + +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/address/index.html.eex:8 +msgid " addresses of" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:21 +msgid "Back" +msgstr "" + +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/address/index.html.eex:6 +msgid "Showing " +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/chain/show.html.eex:58 +msgid "Total blocks" +msgstr "" diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index e2a68ccbe9..e26c229d9c 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1117,7 +1117,7 @@ defmodule Explorer.Chain do end @doc """ - Lists the top 250 `t:Explorer.Chain.Address.t/0`'s' in descending order based on coin balance. + Lists the top `t:Explorer.Chain.Address.t/0`'s' in descending order based on coin balance and address hash. """ @spec list_top_addresses :: [{Address.t(), non_neg_integer()}] From 01e79319f58abedc888ec2a7f18134ef9d798e60 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Wed, 1 May 2019 16:51:49 +0300 Subject: [PATCH 011/191] eth theme --- .../assets/css/theme/_ethereum_variables.scss | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss b/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss index 98d2da802c..7437274bf6 100644 --- a/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss +++ b/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss @@ -1,3 +1,50 @@ -$primary: #16465b; -$secondary: #5ab3ff; -$tertiary: #77a4c5; +// general +$primary: #153550; +$secondary: #49a2ee; +$tertiary: #4ad7a7; +$additional-font: #89cae6; + +// footer +$footer-background-color: $primary; +$footer-title-color: #fff; +$footer-text-color: #89cae6; +$footer-item-disc-color: $secondary; +.footer-logo { filter: brightness(0) invert(1); } + +// dashboard +$dashboard-line-color-price: $tertiary; // price left border + +$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels + +$dashboard-stats-item-value-color: $additional-font; // stat values + +$dashboard-stats-item-border-color: $secondary; // stat border + +$dashboard-banner-gradient-start: $primary; // gradient begin + +$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end + +$dashboard-banner-network-plain-container-background-color: #1c476c; // stats bg + + +// navigation +.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow +$header-icon-border-color-hover: $secondary; // top border on hover +$header-icon-color-hover: $secondary; // nav icon on hover +.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover + +// buttons +$btn-line-bg: #fff; // button bg +$btn-line-color: $secondary; // button border and font color && hover bg color +$btn-copy-color: $secondary; // btn copy +$btn-qr-color: $secondary; // btn qr-code + +//links & tile +.tile a { color: $secondary !important; } // links color for badges +.tile-type-block { + border-left: 4px solid $secondary; +} // tab active bg + +// card +$card-background-1: $secondary; +$card-tab-active: $secondary; From 9b16de335686481dc5c4ac6d04e046818610b616 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Wed, 1 May 2019 16:52:38 +0300 Subject: [PATCH 012/191] eth logo --- .../assets/static/images/ethereum_logo.svg | 41 +------------------ 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/apps/block_scout_web/assets/static/images/ethereum_logo.svg b/apps/block_scout_web/assets/static/images/ethereum_logo.svg index 3f47dc7fe2..b2ebb795f8 100644 --- a/apps/block_scout_web/assets/static/images/ethereum_logo.svg +++ b/apps/block_scout_web/assets/static/images/ethereum_logo.svg @@ -1,40 +1 @@ - - - - -ethereum-logo - - - - - - - - - - - - - + From 7e5e3536d074948540f9581570753dc3e4fd0bfc Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 1 May 2019 17:43:50 +0300 Subject: [PATCH 013/191] update cache if cache is nil --- .../lib/explorer/chain/block_count_cache.ex | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/block_count_cache.ex b/apps/explorer/lib/explorer/chain/block_count_cache.ex index 7c900bfedd..11fcddd98d 100644 --- a/apps/explorer/lib/explorer/chain/block_count_cache.ex +++ b/apps/explorer/lib/explorer/chain/block_count_cache.ex @@ -29,15 +29,17 @@ defmodule Explorer.Chain.BlockCountCache do end def count do - initial_cache = {_count, old_current_time} = cached_values() + initial_cache = cached_values() {count, _current_time} = - if current_time() - old_current_time > cache_period() do + with {_count, old_current_time} <- initial_cache, + true <- current_time() - old_current_time > cache_period() do update_cache() cached_values() else - initial_cache + _ -> + initial_cache end count @@ -58,9 +60,13 @@ defmodule Explorer.Chain.BlockCountCache do end defp cached_values do - [{_, cached_values}] = :ets.lookup(@tab, @key) + case :ets.lookup(@tab, @key) do + [{_, cached_values}] -> + cached_values - cached_values + [] -> + nil + end end defp cache_period do From 234c02d7cac627f0bb330c5d1c67cdd2176cb8be Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 3 May 2019 09:10:33 +0300 Subject: [PATCH 014/191] fix gettext --- apps/block_scout_web/priv/gettext/default.pot | 27 +++++++++++++++- .../priv/gettext/en/LC_MESSAGES/default.po | 31 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 5b078d2ffe..92c3b244a6 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -579,7 +579,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/address/index.html.eex:16 -#: lib/block_scout_web/templates/address_token/index.html.eex:25 +#: lib/block_scout_web/templates/address_token/index.html.eex:22 msgid "Next" msgstr "" @@ -1730,3 +1730,28 @@ msgstr "" #: lib/block_scout_web/views/transaction_view.ex:341 msgid "Raw Trace" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:11 +msgid " (page" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:8 +msgid " addresses of" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:21 +msgid "Back" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:6 +msgid "Showing " +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/chain/show.html.eex:64 +msgid "Total blocks" +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 a723d5b1f0..f59f67d08b 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 @@ -577,6 +577,12 @@ msgstr "" msgid "Newer" msgstr "" +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/address/index.html.eex:16 +#: lib/block_scout_web/templates/address_token/index.html.eex:22 +msgid "Next" +msgstr "" + #, elixir-format #: lib/block_scout_web/templates/tokens/holder/index.html.eex:37 #: lib/block_scout_web/templates/tokens/inventory/index.html.eex:32 @@ -1724,3 +1730,28 @@ msgstr "" #: lib/block_scout_web/views/transaction_view.ex:341 msgid "Raw Trace" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:11 +msgid " (page" +msgstr "" + +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/address/index.html.eex:8 +msgid " addresses of" +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:21 +msgid "Back" +msgstr "" + +#, elixir-format, fuzzy +#: lib/block_scout_web/templates/address/index.html.eex:6 +msgid "Showing " +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/chain/show.html.eex:64 +msgid "Total blocks" +msgstr "" From 9a480f8db69c0429c8044cd425d3938e4d75334e Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 3 May 2019 11:13:58 +0300 Subject: [PATCH 015/191] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cd047fd5c..de28200d6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - [#1849](https://github.com/poanetwork/blockscout/pull/1849) - Improve chains menu - [#1869](https://github.com/poanetwork/blockscout/pull/1869) - Fix output and gas extraction in JS tracer for Geth - [#1868](https://github.com/poanetwork/blockscout/pull/1868) - fix: logs list endpoint performance +- [#1822](https://github.com/poanetwork/blockscout/pull/1822) - Fix style breaks in decompiled contract code view ### Chore From 2bdab7372b2b5d1f76ad60eb9cbb971abc66cd2d Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 3 May 2019 12:15:53 +0300 Subject: [PATCH 016/191] address CR issues --- .../templates/address/index.html.eex | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex index 5f45651724..fca5d5b50d 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex @@ -1,6 +1,17 @@
+ <%= if @next_page_path do %> + " class="button button-secondary button-small float-right ml-1"> + <%= gettext("Next") %> + + <% end %> + <%= if @prev_page_path do %> + " class="button button-secondary button-small float-right"> + <%= gettext("Back") %> + + <% end %> +

<%= gettext "Addresses" %>

<%= gettext "Showing " %> @@ -10,26 +21,26 @@ <%= gettext "total addresses with a balance" %> <%= gettext " (page" %> <%= Cldr.Number.to_string!(@cur_page_number, format: "#,###)") %> +

+ + <%= for {{address, tx_count}, index} <- Enum.with_index(@address_tx_count_pairs, 1) do %> + <%= render "_tile.html", + address: address, index: index, exchange_rate: @exchange_rate, + total_supply: @total_supply, tx_count: tx_count, + validation_count: validation_count(address) %> + <% end %> +
<%= if @next_page_path do %> - " class="button button-secondary button-small float-right mt-0 ml-1"> + " class="button button-secondary button-small float-right mt-0 mb-0 ml-1"> <%= gettext("Next") %> <% end %> <%= if @prev_page_path do %> - " class="button button-secondary button-small float-right mt-0"> + " class="button button-secondary button-small float-right mt-0 mb-0"> <%= gettext("Back") %> <% end %> -

-
- - <%= for {{address, tx_count}, index} <- Enum.with_index(@address_tx_count_pairs, 1) do %> - <%= render "_tile.html", - address: address, index: index, exchange_rate: @exchange_rate, - total_supply: @total_supply, tx_count: tx_count, - validation_count: validation_count(address) %> - <% end %>
From 266f3f02ec59e519777035b667af8e63693bb2a9 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 3 May 2019 12:19:37 +0300 Subject: [PATCH 017/191] fix gettext --- apps/block_scout_web/priv/gettext/default.pot | 16 ++++++++------ .../priv/gettext/en/LC_MESSAGES/default.po | 22 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 92c3b244a6..8ee6c84113 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -104,7 +104,7 @@ msgid "Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:4 +#: lib/block_scout_web/templates/address/index.html.eex:15 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:59 msgid "Addresses" msgstr "" @@ -578,7 +578,8 @@ msgid "Newer" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:16 +#: lib/block_scout_web/templates/address/index.html.eex:6 +#: lib/block_scout_web/templates/address/index.html.eex:36 #: lib/block_scout_web/templates/address_token/index.html.eex:22 msgid "Next" msgstr "" @@ -1074,7 +1075,7 @@ msgid "string" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:10 +#: lib/block_scout_web/templates/address/index.html.eex:21 msgid "total addresses with a balance" msgstr "" @@ -1732,22 +1733,23 @@ msgid "Raw Trace" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:11 +#: lib/block_scout_web/templates/address/index.html.eex:22 msgid " (page" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:8 +#: lib/block_scout_web/templates/address/index.html.eex:19 msgid " addresses of" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:21 +#: lib/block_scout_web/templates/address/index.html.eex:11 +#: lib/block_scout_web/templates/address/index.html.eex:41 msgid "Back" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:6 +#: lib/block_scout_web/templates/address/index.html.eex:17 msgid "Showing " 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 f59f67d08b..4612b16a72 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 @@ -104,7 +104,7 @@ msgid "Address" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:4 +#: lib/block_scout_web/templates/address/index.html.eex:15 #: lib/block_scout_web/templates/tokens/overview/_details.html.eex:59 msgid "Addresses" msgstr "" @@ -577,8 +577,9 @@ msgstr "" msgid "Newer" msgstr "" -#, elixir-format, fuzzy -#: lib/block_scout_web/templates/address/index.html.eex:16 +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:6 +#: lib/block_scout_web/templates/address/index.html.eex:36 #: lib/block_scout_web/templates/address_token/index.html.eex:22 msgid "Next" msgstr "" @@ -1074,7 +1075,7 @@ msgid "string" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:10 +#: lib/block_scout_web/templates/address/index.html.eex:21 msgid "total addresses with a balance" msgstr "" @@ -1732,22 +1733,23 @@ msgid "Raw Trace" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:11 +#: lib/block_scout_web/templates/address/index.html.eex:22 msgid " (page" msgstr "" -#, elixir-format, fuzzy -#: lib/block_scout_web/templates/address/index.html.eex:8 +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:19 msgid " addresses of" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/address/index.html.eex:21 +#: lib/block_scout_web/templates/address/index.html.eex:11 +#: lib/block_scout_web/templates/address/index.html.eex:41 msgid "Back" msgstr "" -#, elixir-format, fuzzy -#: lib/block_scout_web/templates/address/index.html.eex:6 +#, elixir-format +#: lib/block_scout_web/templates/address/index.html.eex:17 msgid "Showing " msgstr "" From 29815b2fc02f02514f46a02cc5b938296b58e87d Mon Sep 17 00:00:00 2001 From: saneery Date: Fri, 3 May 2019 13:22:34 +0300 Subject: [PATCH 018/191] update count of blocks cache --- .../controllers/chain_controller.ex | 4 +- apps/explorer/lib/explorer/application.ex | 4 +- apps/explorer/lib/explorer/chain.ex | 20 +++++ .../lib/explorer/chain/block_count_cache.ex | 79 ++++++++----------- ...2094552_create_estimate_count_function.exs | 24 ++++++ .../explorer/chain/block_count_cache_test.exs | 37 ++++++--- 6 files changed, 108 insertions(+), 60 deletions(-) create mode 100644 apps/explorer/priv/repo/migrations/20190502094552_create_estimate_count_function.exs diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex index 6849f0f94c..48d84dd5d1 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex @@ -3,7 +3,7 @@ defmodule BlockScoutWeb.ChainController do alias BlockScoutWeb.ChainView alias Explorer.{Chain, PagingOptions, Repo} - alias Explorer.Chain.{Address, Block, BlockCountCache, Transaction} + alias Explorer.Chain.{Address, Block, Transaction} alias Explorer.Counters.AverageBlockTime alias Explorer.ExchangeRates.Token alias Explorer.Market @@ -11,7 +11,7 @@ defmodule BlockScoutWeb.ChainController do def show(conn, _params) do transaction_estimated_count = Chain.transaction_estimated_count() - block_count = BlockCountCache.count() + block_count = Chain.block_estimated_count() exchange_rate = Market.get_exchange_rate(Explorer.coin()) || Token.null() diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index 080b880211..1e82d58527 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -28,7 +28,8 @@ defmodule Explorer.Application do Supervisor.child_spec({Task.Supervisor, name: Explorer.TaskSupervisor}, id: Explorer.TaskSupervisor), {Registry, keys: :duplicate, name: Registry.ChainEvents, id: Registry.ChainEvents}, {Admin.Recovery, [[], [name: Admin.Recovery]]}, - {TransactionCountCache, [[], []]} + {TransactionCountCache, [[], []]}, + {BlockCountCache, []} ] children = base_children ++ configurable_children() @@ -38,7 +39,6 @@ defmodule Explorer.Application do res = Supervisor.start_link(children, opts) BlockNumberCache.setup() - BlockCountCache.setup() res end diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index beee541ebf..f28e5e4763 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -29,6 +29,7 @@ defmodule Explorer.Chain do Address.CurrentTokenBalance, Address.TokenBalance, Block, + BlockCountCache, BlockNumberCache, Data, DecompiledSmartContract, @@ -1949,6 +1950,25 @@ defmodule Explorer.Chain do end end + @doc """ + Estimated count of `t:Explorer.Chain.Block.t/0`. + + Estimated count of consensus blocks. + """ + @spec block_estimated_count() :: non_neg_integer() + def block_estimated_count do + cached_value = BlockCountCache.count() + + if is_nil(cached_value) do + %Postgrex.Result{rows: [[rows]]} = + SQL.query!(Repo, "SELECT count_estimate('SELECT 1 FROM blocks WHERE consensus = true');") |> IO.inspect() + + rows + else + cached_value + end + end + @doc """ `t:Explorer.Chain.InternalTransaction/0`s in `t:Explorer.Chain.Transaction.t/0` with `hash`. diff --git a/apps/explorer/lib/explorer/chain/block_count_cache.ex b/apps/explorer/lib/explorer/chain/block_count_cache.ex index 11fcddd98d..75b8b9f6db 100644 --- a/apps/explorer/lib/explorer/chain/block_count_cache.ex +++ b/apps/explorer/lib/explorer/chain/block_count_cache.ex @@ -4,15 +4,20 @@ defmodule Explorer.Chain.BlockCountCache do """ alias Explorer.Chain + use GenServer @tab :block_count_cache # 1 minutes @cache_period 1_000 * 60 @key "count" - @opts_key "opts" + @opts "ttl" - @spec setup() :: :ok - def setup do + def start_link(params) do + name = Keyword.get(params, :name, __MODULE__) + GenServer.start_link(__MODULE__, params, name: name) + end + + def init(_) do if :ets.whereis(@tab) == :undefined do :ets.new(@tab, [ :set, @@ -22,64 +27,45 @@ defmodule Explorer.Chain.BlockCountCache do ]) end - setup_opts() - update_cache() - - :ok - end - - def count do - initial_cache = cached_values() - - {count, _current_time} = - with {_count, old_current_time} <- initial_cache, - true <- current_time() - old_current_time > cache_period() do - update_cache() - - cached_values() - else - _ -> - initial_cache - end - - count - end - - defp update_cache do - current_time = current_time() - count = count_from_db() - tuple = {count, current_time} - - :ets.insert(@tab, {@key, tuple}) - end - - defp setup_opts do cache_period = Application.get_env(:explorer, __MODULE__)[:ttl] || @cache_period + :ets.insert(@tab, {@opts, cache_period}) - :ets.insert(@tab, {@opts_key, cache_period}) + {:ok, nil} end - defp cached_values do + def count(name \\ __MODULE__) do case :ets.lookup(@tab, @key) do - [{_, cached_values}] -> + [{_, {cached_values, timestamp}}] -> + if timeout?(timestamp), do: send(name, :update_cache) + cached_values [] -> + send(name, :update_cache) nil end end - defp cache_period do - [{_, cache_period}] = :ets.lookup(@tab, @opts_key) + def handle_info(:set_timer, nil) do + [{_, cache_period}] = :ets.lookup(@tab, @opts) + timer = Process.send_after(self(), :update_cache, cache_period) + {:noreply, timer} + end + + def handle_info(:update_cache, timer) do + if timer, do: Process.cancel_timer(timer) - cache_period + count = count_from_db() + + :ets.insert(@tab, {@key, {count, current_time()}}) + + send(self(), :set_timer) + + {:noreply, nil} end defp count_from_db do Chain.fetch_count_consensus_block() - rescue - _e -> - 0 end defp current_time do @@ -87,4 +73,9 @@ defmodule Explorer.Chain.BlockCountCache do DateTime.to_unix(utc_now, :millisecond) end + + defp timeout?(timestamp) do + [{_, cache_period}] = :ets.lookup(@tab, @opts) + current_time() - timestamp > cache_period + end end diff --git a/apps/explorer/priv/repo/migrations/20190502094552_create_estimate_count_function.exs b/apps/explorer/priv/repo/migrations/20190502094552_create_estimate_count_function.exs new file mode 100644 index 0000000000..718a2aa3a6 --- /dev/null +++ b/apps/explorer/priv/repo/migrations/20190502094552_create_estimate_count_function.exs @@ -0,0 +1,24 @@ +defmodule Explorer.Repo.Migrations.CreateEstimateCountFunction do + use Ecto.Migration + + def up do + execute(""" + CREATE FUNCTION count_estimate(query text) RETURNS integer AS $$ + DECLARE + rec record; + rows integer; + BEGIN + FOR rec IN EXECUTE 'EXPLAIN ' || query LOOP + rows := substring(rec."QUERY PLAN" FROM ' rows=([[:digit:]]+)'); + EXIT WHEN rows IS NOT NULL; + END LOOP; + RETURN rows; + END; + $$ LANGUAGE plpgsql VOLATILE STRICT; + """) + end + + def down do + execute("DROP FUNCTION count_estimate") + end +end diff --git a/apps/explorer/test/explorer/chain/block_count_cache_test.exs b/apps/explorer/test/explorer/chain/block_count_cache_test.exs index 9b3795d15e..89e3ddcb7c 100644 --- a/apps/explorer/test/explorer/chain/block_count_cache_test.exs +++ b/apps/explorer/test/explorer/chain/block_count_cache_test.exs @@ -5,41 +5,54 @@ defmodule Explorer.Chain.BlockCountCacheTest do describe "count/0" do test "return count" do + Application.put_env(:explorer, BlockCountCache, ttl: 200) + BlockCountCache.start_link(name: BlockTest) + Process.sleep(300) + insert(:block, number: 1, consensus: true) insert(:block, number: 2, consensus: true) insert(:block, number: 3, consensus: false) - BlockCountCache.setup() + _result = BlockCountCache.count(BlockTest) + + Process.sleep(300) - assert BlockCountCache.count() == 2 + assert BlockCountCache.count(BlockTest) == 2 end test "invalidates cache if period did pass" do + Application.put_env(:explorer, BlockCountCache, ttl: 200) + BlockCountCache.start_link(name: BlockTest) + Process.sleep(300) + insert(:block, number: 1, consensus: true) - Application.put_env(:explorer, BlockCountCache, ttl: 2_00) - BlockCountCache.setup() + _result = BlockCountCache.count(BlockTest) - assert BlockCountCache.count() == 1 + Process.sleep(300) + assert BlockCountCache.count(BlockTest) == 1 insert(:block, number: 2, consensus: true) + Process.sleep(300) - Process.sleep(2_000) - - assert BlockCountCache.count() == 2 + assert BlockCountCache.count(BlockTest) == 2 end test "does not invalidate cache if period time did not pass" do + Application.put_env(:explorer, BlockCountCache, ttl: 200) + BlockCountCache.start_link(name: BlockTest) + Process.sleep(300) + insert(:block, number: 1, consensus: true) - Application.put_env(:explorer, BlockCountCache, ttl: 2_00) - BlockCountCache.setup() + _result = BlockCountCache.count(BlockTest) + Process.sleep(300) - assert BlockCountCache.count() == 1 + assert BlockCountCache.count(BlockTest) == 1 insert(:block, number: 2, consensus: true) - assert BlockCountCache.count() == 1 + assert BlockCountCache.count(BlockTest) == 1 end end end From 7ce2a8fb74c891600de83513edc766dfb8930eef Mon Sep 17 00:00:00 2001 From: saneery Date: Fri, 3 May 2019 13:44:03 +0300 Subject: [PATCH 019/191] credo fix --- apps/explorer/lib/explorer/chain.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index f28e5e4763..cb82fd1fac 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1961,7 +1961,7 @@ defmodule Explorer.Chain do if is_nil(cached_value) do %Postgrex.Result{rows: [[rows]]} = - SQL.query!(Repo, "SELECT count_estimate('SELECT 1 FROM blocks WHERE consensus = true');") |> IO.inspect() + SQL.query!(Repo, "SELECT count_estimate('SELECT 1 FROM blocks WHERE consensus = true');") rows else From eeb22049768eb92162e86427fd2f46c3295e5e1f Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 3 May 2019 14:02:01 +0300 Subject: [PATCH 020/191] remove extra new line --- .../views/address_decompiled_contract_view.ex | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex index 1418255594..bcfd2a5638 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex @@ -76,18 +76,12 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do part true -> - result = - part - |> String.split("\n") - |> Enum.reduce("", fn p, a -> - a <> new_style <> p <> "\n" - end) - - if String.ends_with?(part, "\n") do - result - else - String.slice(result, 0..-2) - end + part + |> String.split("\n") + |> Enum.reduce("", fn p, a -> + a <> new_style <> p <> "\n" + end) + |> String.slice(0..-2) end end end From fa2b21d1d9f82d64d959e82938e9c0ade5c53884 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Fri, 3 May 2019 14:11:38 +0300 Subject: [PATCH 021/191] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66676df93b..625c2485fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -195,3 +195,6 @@ - [https://github.com/poanetwork/blockscout/pull/1532](https://github.com/poanetwork/blockscout/pull/1532) - Upgrade elixir to 1.8.1 - [https://github.com/poanetwork/blockscout/pull/1553](https://github.com/poanetwork/blockscout/pull/1553) - Dockerfile: remove 1.7.1 version pin FROM bitwalker/alpine-elixir-phoenix - [https://github.com/poanetwork/blockscout/pull/1465](https://github.com/poanetwork/blockscout/pull/1465) - Resolve lodash security alert + +### Improvements +-[#1874] - add changes to ethereum theme and ethereum logo From d47db7a06daad7bea29d72c771714203d39a1c4b Mon Sep 17 00:00:00 2001 From: saneery Date: Fri, 3 May 2019 15:21:20 +0300 Subject: [PATCH 022/191] fetch blocks count with task --- .../lib/explorer/chain/block_count_cache.ex | 150 +++++++++++++----- .../explorer/chain/block_count_cache_test.exs | 68 ++++---- 2 files changed, 141 insertions(+), 77 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/block_count_cache.ex b/apps/explorer/lib/explorer/chain/block_count_cache.ex index 75b8b9f6db..494de296a4 100644 --- a/apps/explorer/lib/explorer/chain/block_count_cache.ex +++ b/apps/explorer/lib/explorer/chain/block_count_cache.ex @@ -1,71 +1,129 @@ defmodule Explorer.Chain.BlockCountCache do @moduledoc """ - Cache for count consensus blocks. + Cache for block count. """ - alias Explorer.Chain + require Logger + use GenServer - @tab :block_count_cache + alias Explorer.Chain + # 1 minutes @cache_period 1_000 * 60 @key "count" - @opts "ttl" + @default_value nil + @name __MODULE__ def start_link(params) do - name = Keyword.get(params, :name, __MODULE__) - GenServer.start_link(__MODULE__, params, name: name) + name = params[:name] || @name + params_with_name = Keyword.put(params, :name, name) + + GenServer.start_link(__MODULE__, params_with_name, name: name) end - def init(_) do - if :ets.whereis(@tab) == :undefined do - :ets.new(@tab, [ - :set, - :named_table, - :public, - write_concurrency: true - ]) - end + def init(params) do + cache_period = period_from_env_var() || params[:cache_period] || @cache_period + current_value = params[:default_value] || @default_value + name = params[:name] - cache_period = Application.get_env(:explorer, __MODULE__)[:ttl] || @cache_period - :ets.insert(@tab, {@opts, cache_period}) + init_ets_table(name) - {:ok, nil} + {:ok, {{cache_period, current_value, name}, nil}} end - def count(name \\ __MODULE__) do - case :ets.lookup(@tab, @key) do - [{_, {cached_values, timestamp}}] -> - if timeout?(timestamp), do: send(name, :update_cache) + def count(process_name \\ __MODULE__) do + GenServer.call(process_name, :count) + end - cached_values + def handle_call(:count, _, {{cache_period, default_value, name}, task}) do + {count, task} = + case cached_values(name) do + nil -> + {default_value, update_cache(task, name)} - [] -> - send(name, :update_cache) - nil - end + {cached_value, timestamp} -> + task = + if current_time() - timestamp > cache_period do + update_cache(task, name) + end + + {cached_value, task} + end + + {:reply, count, {{cache_period, default_value, name}, task}} end - def handle_info(:set_timer, nil) do - [{_, cache_period}] = :ets.lookup(@tab, @opts) - timer = Process.send_after(self(), :update_cache, cache_period) - {:noreply, timer} + def update_cache(nil, name) do + async_update_cache(name) end - def handle_info(:update_cache, timer) do - if timer, do: Process.cancel_timer(timer) + def update_cache(task, _) do + task + end - count = count_from_db() + def handle_cast({:update_cache, value}, {{cache_period, default_value, name}, _}) do + current_time = current_time() + tuple = {value, current_time} - :ets.insert(@tab, {@key, {count, current_time()}}) + table_name = table_name(name) - send(self(), :set_timer) + :ets.insert(table_name, {@key, tuple}) - {:noreply, nil} + {:noreply, {{cache_period, default_value, name}, nil}} end - defp count_from_db do - Chain.fetch_count_consensus_block() + def handle_info({:DOWN, _, _, _, _}, {{cache_period, default_value, name}, _}) do + {:noreply, {{cache_period, default_value, name}, nil}} + end + + def handle_info(_, {{cache_period, default_value, name}, _}) do + {:noreply, {{cache_period, default_value, name}, nil}} + end + + # sobelow_skip ["DOS"] + defp table_name(name) do + name + |> Atom.to_string() + |> Macro.underscore() + |> String.to_atom() + end + + def async_update_cache(name) do + Task.async(fn -> + try do + result = Chain.fetch_count_consensus_block() + + GenServer.cast(name, {:update_cache, result}) + rescue + e -> + Logger.debug([ + "Coudn't update block count test #{inspect(e)}" + ]) + end + end) + end + + defp init_ets_table(name) do + table_name = table_name(name) + + if :ets.whereis(table_name) == :undefined do + :ets.new(table_name, [ + :set, + :named_table, + :public, + write_concurrency: true + ]) + end + end + + defp cached_values(name) do + table_name = table_name(name) + + case :ets.lookup(table_name, @key) do + [{_, cached_values}] -> cached_values + _ -> nil + end end defp current_time do @@ -74,8 +132,16 @@ defmodule Explorer.Chain.BlockCountCache do DateTime.to_unix(utc_now, :millisecond) end - defp timeout?(timestamp) do - [{_, cache_period}] = :ets.lookup(@tab, @opts) - current_time() - timestamp > cache_period + defp period_from_env_var do + case System.get_env("BLOCK_COUNT_CACHE_PERIOD") do + value when is_binary(value) -> + case Integer.parse(value) do + {integer, ""} -> integer * 1_000 + _ -> nil + end + + _ -> + nil + end end end diff --git a/apps/explorer/test/explorer/chain/block_count_cache_test.exs b/apps/explorer/test/explorer/chain/block_count_cache_test.exs index 89e3ddcb7c..afc75e9d32 100644 --- a/apps/explorer/test/explorer/chain/block_count_cache_test.exs +++ b/apps/explorer/test/explorer/chain/block_count_cache_test.exs @@ -3,56 +3,54 @@ defmodule Explorer.Chain.BlockCountCacheTest do alias Explorer.Chain.BlockCountCache - describe "count/0" do - test "return count" do - Application.put_env(:explorer, BlockCountCache, ttl: 200) - BlockCountCache.start_link(name: BlockTest) - Process.sleep(300) + test "returns default transaction count" do + BlockCountCache.start_link([[], [name: TestCache]]) - insert(:block, number: 1, consensus: true) - insert(:block, number: 2, consensus: true) - insert(:block, number: 3, consensus: false) + result = BlockCountCache.value(TestCache) - _result = BlockCountCache.count(BlockTest) + assert is_nil(result) + end + + test "updates cache if initial value is zero" do + BlockCountCache.start_link([[], [name: TestCache]]) + + insert(:block, consensus: true) + insert(:block, consensus: true) + insert(:block, consensus: false) - Process.sleep(300) + _result = BlockCountCache.value(TestCache) - assert BlockCountCache.count(BlockTest) == 2 - end + Process.sleep(1000) - test "invalidates cache if period did pass" do - Application.put_env(:explorer, BlockCountCache, ttl: 200) - BlockCountCache.start_link(name: BlockTest) - Process.sleep(300) + updated_value = BlockCountCache.value(TestCache) + + assert updated_value == 2 + end - insert(:block, number: 1, consensus: true) + test "does not update cache if cache period did not pass" do + BlockCountCache.start_link([[], [name: TestCache]]) - _result = BlockCountCache.count(BlockTest) + insert(:block, consensus: true) + insert(:block, consensus: true) + insert(:block, consensus: false) - Process.sleep(300) - assert BlockCountCache.count(BlockTest) == 1 + _result = BlockCountCache.value(TestCache) - insert(:block, number: 2, consensus: true) - Process.sleep(300) + Process.sleep(1000) - assert BlockCountCache.count(BlockTest) == 2 - end + updated_value = BlockCountCache.value(TestCache) - test "does not invalidate cache if period time did not pass" do - Application.put_env(:explorer, BlockCountCache, ttl: 200) - BlockCountCache.start_link(name: BlockTest) - Process.sleep(300) + assert updated_value == 2 - insert(:block, number: 1, consensus: true) + insert(:block, consensus: true) + insert(:block, consensus: true) - _result = BlockCountCache.count(BlockTest) - Process.sleep(300) + _updated_value = BlockCountCache.value(TestCache) - assert BlockCountCache.count(BlockTest) == 1 + Process.sleep(1000) - insert(:block, number: 2, consensus: true) + updated_value = BlockCountCache.value(TestCache) - assert BlockCountCache.count(BlockTest) == 1 - end + assert updated_value == 2 end end From 49615e04ef0793f2bb11289f1da1febde6e99cf5 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 3 May 2019 15:22:33 +0300 Subject: [PATCH 023/191] add custom colors to reserved words --- .../views/address_decompiled_contract_view.ex | 91 +++++++++++++++---- 1 file changed, 71 insertions(+), 20 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex index bcfd2a5638..6964c3dede 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex @@ -2,51 +2,102 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do use BlockScoutWeb, :view @colors %{ - "\e[95m" => "136, 0, 0", + "\e[95m" => "", # red - "\e[91m" => "236, 89, 58", + "\e[91m" => "", # gray - "\e[38;5;8m" => "111, 110, 111", + "\e[38;5;8m" => "", # green - "\e[32m" => "57, 115, 0", + "\e[32m" => "", # yellowgreen - "\e[93m" => "57, 115, 0", + "\e[93m" => "", # yellow - "\e[92m" => "119, 232, 81", + "\e[92m" => "", # red - "\e[94m" => "136, 0, 0" + "\e[94m" => "" } + @reserved_words [ + "def", + "require", + "revert", + "return", + "assembly", + "memory", + "payable", + "public", + "view", + "pure", + "returns", + "internal" + ] + def highlight_decompiled_code(code) do {_, result} = @colors |> Enum.reduce(code, fn {symbol, rgb}, acc -> - String.replace(acc, symbol, "") + String.replace(acc, symbol, rgb) end) |> String.replace("\e[1m", "") |> String.replace("»", "»") |> String.replace("\e[0m", "") |> String.split(~r/\|\<\/span\>/, include_captures: true, trim: true) - |> Enum.reduce({"", []}, fn part, {style, acc} -> - new_style = - cond do - String.contains?(part, " part - part == "" -> "" - true -> style - end - - new_part = new_part(part, new_style) - - {new_style, [new_part | acc]} - end) + |> add_styles_to_every_line() result |> Enum.reduce("", fn part, acc -> part <> acc end) + |> add_styles_to_reserved_words() |> add_line_numbers() end + defp add_styles_to_every_line(lines) do + lines + |> Enum.reduce({"", []}, fn part, {style, acc} -> + new_style = + cond do + String.contains?(part, " part + part == "" -> "" + true -> style + end + + new_part = new_part(part, new_style) + + {new_style, [new_part | acc]} + end) + end + + defp add_styles_to_reserved_words(code) do + code + |> String.split("\n") + |> Enum.map(fn line -> + parts = + line + |> String.split(~r/def|require|revert|return|assembly|memory|payable|public|view|pure|returns|internal|#/, + include_captures: true + ) + + comment_position = Enum.find_index(parts, fn part -> part == "#" end) + + parts + |> Enum.with_index() + |> Enum.map(fn {el, index} -> + if (is_nil(comment_position) || comment_position > index) && el in @reserved_words do + "" <> el <> "" + else + el + end + end) + |> Enum.reduce("", fn el, acc -> + acc <> el + end) + end) + |> Enum.reduce("", fn el, acc -> + acc <> el <> "\n" + end) + end + def sort_contracts_by_version(decompiled_contracts) do decompiled_contracts |> Enum.sort_by(& &1.decompiler_version) From 7aafc8914f535629a22519184d6c731d8455bc73 Mon Sep 17 00:00:00 2001 From: saneery Date: Fri, 3 May 2019 15:36:33 +0300 Subject: [PATCH 024/191] fix test --- apps/explorer/config/config.exs | 2 -- .../explorer/chain/block_count_cache_test.exs | 20 +++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index ace69884ea..e6eb5c4813 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -82,8 +82,6 @@ config :spandex_ecto, SpandexEcto.EctoLogger, tracer: Explorer.Tracer, otp_app: :explorer -config :explorer, Explorer.Chain.BlockCountCache, ttl: System.get_env("BLOCK_COUNT_CACHE_TTL") - # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" diff --git a/apps/explorer/test/explorer/chain/block_count_cache_test.exs b/apps/explorer/test/explorer/chain/block_count_cache_test.exs index afc75e9d32..dcf7299278 100644 --- a/apps/explorer/test/explorer/chain/block_count_cache_test.exs +++ b/apps/explorer/test/explorer/chain/block_count_cache_test.exs @@ -4,52 +4,52 @@ defmodule Explorer.Chain.BlockCountCacheTest do alias Explorer.Chain.BlockCountCache test "returns default transaction count" do - BlockCountCache.start_link([[], [name: TestCache]]) + BlockCountCache.start_link([name: BlockTestCache]) - result = BlockCountCache.value(TestCache) + result = BlockCountCache.count(BlockTestCache) assert is_nil(result) end test "updates cache if initial value is zero" do - BlockCountCache.start_link([[], [name: TestCache]]) + BlockCountCache.start_link([name: BlockTestCache]) insert(:block, consensus: true) insert(:block, consensus: true) insert(:block, consensus: false) - _result = BlockCountCache.value(TestCache) + _result = BlockCountCache.count(BlockTestCache) Process.sleep(1000) - updated_value = BlockCountCache.value(TestCache) + updated_value = BlockCountCache.count(BlockTestCache) assert updated_value == 2 end test "does not update cache if cache period did not pass" do - BlockCountCache.start_link([[], [name: TestCache]]) + BlockCountCache.start_link([name: BlockTestCache]) insert(:block, consensus: true) insert(:block, consensus: true) insert(:block, consensus: false) - _result = BlockCountCache.value(TestCache) + _result = BlockCountCache.count(BlockTestCache) Process.sleep(1000) - updated_value = BlockCountCache.value(TestCache) + updated_value = BlockCountCache.count(BlockTestCache) assert updated_value == 2 insert(:block, consensus: true) insert(:block, consensus: true) - _updated_value = BlockCountCache.value(TestCache) + _updated_value = BlockCountCache.count(BlockTestCache) Process.sleep(1000) - updated_value = BlockCountCache.value(TestCache) + updated_value = BlockCountCache.count(BlockTestCache) assert updated_value == 2 end From 8b49f4c7390650ec22c627627947bb7a730e3c86 Mon Sep 17 00:00:00 2001 From: saneery Date: Fri, 3 May 2019 15:41:03 +0300 Subject: [PATCH 025/191] mix format --- .../explorer/test/explorer/chain/block_count_cache_test.exs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/explorer/test/explorer/chain/block_count_cache_test.exs b/apps/explorer/test/explorer/chain/block_count_cache_test.exs index dcf7299278..d1bbd5eb53 100644 --- a/apps/explorer/test/explorer/chain/block_count_cache_test.exs +++ b/apps/explorer/test/explorer/chain/block_count_cache_test.exs @@ -4,7 +4,7 @@ defmodule Explorer.Chain.BlockCountCacheTest do alias Explorer.Chain.BlockCountCache test "returns default transaction count" do - BlockCountCache.start_link([name: BlockTestCache]) + BlockCountCache.start_link(name: BlockTestCache) result = BlockCountCache.count(BlockTestCache) @@ -12,7 +12,7 @@ defmodule Explorer.Chain.BlockCountCacheTest do end test "updates cache if initial value is zero" do - BlockCountCache.start_link([name: BlockTestCache]) + BlockCountCache.start_link(name: BlockTestCache) insert(:block, consensus: true) insert(:block, consensus: true) @@ -28,7 +28,7 @@ defmodule Explorer.Chain.BlockCountCacheTest do end test "does not update cache if cache period did not pass" do - BlockCountCache.start_link([name: BlockTestCache]) + BlockCountCache.start_link(name: BlockTestCache) insert(:block, consensus: true) insert(:block, consensus: true) From 05febe61586baca59522c42da246ce8fdca8c89d Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Fri, 3 May 2019 16:07:19 +0300 Subject: [PATCH 026/191] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 625c2485fd..295875742f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -197,4 +197,4 @@ - [https://github.com/poanetwork/blockscout/pull/1465](https://github.com/poanetwork/blockscout/pull/1465) - Resolve lodash security alert ### Improvements --[#1874] - add changes to ethereum theme and ethereum logo +- [#1874](https://github.com/poanetwork/blockscout/pull/1874) - add changes to ethereum theme and ethereum logo From 5afc5319704c4dcc68c8211ea0f5b13df66028ae Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 3 May 2019 17:20:06 +0300 Subject: [PATCH 027/191] highlight reserved words --- .../views/address_decompiled_contract_view.ex | 171 +++++++++++++++--- .../address_decompiled_contract_view_test.exs | 4 +- 2 files changed, 152 insertions(+), 23 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex index 6964c3dede..f80a0ded99 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/address_decompiled_contract_view.ex @@ -17,13 +17,131 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do "\e[94m" => "" } - @reserved_words [ + @comment_start "#" + + @reserved_words_types [ + "var", + "bool", + "string", + "int", + "uint", + "int8", + "uint8", + "int16", + "uint16", + "int24", + "uint24", + "int32", + "uint32", + "int40", + "uint40", + "int48", + "uint48", + "int56", + "uint56", + "int64", + "uint64", + "int72", + "uint72", + "int80", + "uint80", + "int88", + "uint88", + "int96", + "uint96", + "int104", + "uint104", + "int112", + "uint112", + "int120", + "uint120", + "int128", + "uint128", + "int136", + "uint136", + "int144", + "uint144", + "int152", + "uint152", + "int160", + "uint160", + "int168", + "uint168", + "int176", + "uint176", + "int184", + "uint184", + "int192", + "uint192", + "int200", + "uint200", + "int208", + "uint208", + "int216", + "uint216", + "int224", + "uint224", + "int232", + "uint232", + "int240", + "uint240", + "int248", + "uint248", + "int256", + "uint256", + "byte", + "bytes", + "bytes1", + "bytes2", + "bytes3", + "bytes4", + "bytes5", + "bytes6", + "bytes7", + "bytes8", + "bytes9", + "bytes10", + "bytes11", + "bytes12", + "bytes13", + "bytes14", + "bytes15", + "bytes16", + "bytes17", + "bytes18", + "bytes19", + "bytes20", + "bytes21", + "bytes22", + "bytes23", + "bytes24", + "bytes25", + "bytes26", + "bytes27", + "bytes28", + "bytes29", + "bytes30", + "bytes31", + "bytes32", + "true", + "false", + "enum", + "struct", + "mapping", + "address" + ] + + @reserved_words_keywords [ "def", "require", "revert", "return", "assembly", "memory", + "mem" + ] + + @modifiers [ "payable", "public", "view", @@ -32,6 +150,12 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do "internal" ] + @reserved_words @reserved_words_keywords ++ @reserved_words_types + + @reserved_words_regexp ([@comment_start | @reserved_words] ++ @modifiers) + |> Enum.reduce("", fn el, acc -> acc <> "|" <> el end) + |> Regex.compile!() + def highlight_decompiled_code(code) do {_, result} = @colors @@ -72,32 +196,37 @@ defmodule BlockScoutWeb.AddressDecompiledContractView do code |> String.split("\n") |> Enum.map(fn line -> - parts = - line - |> String.split(~r/def|require|revert|return|assembly|memory|payable|public|view|pure|returns|internal|#/, - include_captures: true - ) - - comment_position = Enum.find_index(parts, fn part -> part == "#" end) - - parts - |> Enum.with_index() - |> Enum.map(fn {el, index} -> - if (is_nil(comment_position) || comment_position > index) && el in @reserved_words do - "" <> el <> "" - else - el - end - end) - |> Enum.reduce("", fn el, acc -> - acc <> el - end) + add_styles_to_line(line) end) |> Enum.reduce("", fn el, acc -> acc <> el <> "\n" end) end + defp add_styles_to_line(line) do + parts = + line + |> String.split(@reserved_words_regexp, + include_captures: true + ) + + comment_position = Enum.find_index(parts, fn part -> part == "#" end) + + parts + |> Enum.with_index() + |> Enum.map(fn {el, index} -> + cond do + !(is_nil(comment_position) || comment_position > index) -> el + el in @reserved_words -> "" <> el <> "" + el in @modifiers -> "" <> el <> "" + true -> el + end + end) + |> Enum.reduce("", fn el, acc -> + acc <> el + end) + end + def sort_contracts_by_version(decompiled_contracts) do decompiled_contracts |> Enum.sort_by(& &1.decompiler_version) diff --git a/apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs index c3ff123584..8f1636ba06 100644 --- a/apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs +++ b/apps/block_scout_web/test/block_scout_web/views/address_decompiled_contract_view_test.exs @@ -56,7 +56,7 @@ defmodule BlockScoutWeb.AddressDecompiledContractViewTest do result = AddressDecompiledContractView.highlight_decompiled_code(code) assert result == - " #\n # eveem.org 6 Feb 2019\n # Decompiled source of 0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875\n #\n # Let's make the world open source\n # \n #\n # I failed with these:\n # - unknowne77c646d(?)\n # - transferFromWithData(address _from, address _to, uint256 _value, bytes _data)\n # All the rest is below.\n #\n\n\n # Storage definitions and getters\n\n def storage:\n allowance is uint256 => uint256 # mask(256, 0) at storage #2\n stor4 is uint256 => uint8 # mask(8, 0) at storage #4\n\n def allowance(address _owner, address _spender) payable: 64\n return allowance[sha3(((320 - 1) and (320 - 1) and _owner), 1), ((320 - 1) and _spender and (320 - 1))]\n\n\n #\n # Regular functions - see Tutorial for understanding quirks of the code\n #\n\n\n # folder failed in this function - may be terribly long, sorry\n def unknownc47d033b(?) payable: not cd[4]:\n revert\n else:\n mem[0]cd[4]\n mem[32] = 4\n mem[96] = bool(stor4[((320 - 1) and (320 - 1) and cd[4])])\n return bool(stor4[((320 - 1) and (320 - 1) and cd[4])])\n\n def _fallback() payable: # default function\n revert\n\n" + " #\n # eveem.org 6 Feb 2019\n # Decompiled source of 0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875\n #\n # Let's make the world open source\n # \n #\n # I failed with these:\n # - unknowne77c646d(?)\n # - transferFromWithData(address _from, address _to, uint256 _value, bytes _data)\n # All the rest is below.\n #\n\n\n # Storage definitions and getters\n\n def storage:\n allowance is uint256 => uint256 # mask(256, 0) at storage #2\n stor4 is uint256 => uint8 # mask(8, 0) at storage #4\n\n def allowance(address _owner, address _spender) payable: 64\n return allowance[_owner_spender(320 - 1))]\n\n\n #\n # Regular functions - see Tutorial for understanding quirks of the code\n #\n\n\n # folder failed in this function - may be terribly long, sorry\n def unknownc47d033b(?) payable: not cd[4]:\n revert\n else:\n mem[0]cd[4]\n mem[32] = 4\n mem[96] = bool(stor4[cd[4])])\n return bool(stor4[cd[4])])\n\n def _fallback() payable: # default function\n revert\n\n\n" end test "adds style span to every line" do @@ -70,7 +70,7 @@ defmodule BlockScoutWeb.AddressDecompiledContractViewTest do """ assert AddressDecompiledContractView.highlight_decompiled_code(code) == - " #\n # eveem.org 6 Feb 2019\n # Decompiled source of 0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875\n #\n # Let's make the world open source\n # \n\n" + " #\n # eveem.org 6 Feb 2019\n # Decompiled source of 0x00Bd9e214FAb74d6fC21bf1aF34261765f57e875\n #\n # Let's make the world open source\n # \n\n\n" end end From e49412f38934a981b48e41fe8cc36a58229ee898 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 6 May 2019 10:23:07 +0300 Subject: [PATCH 028/191] remove temporary worker modules --- apps/indexer/lib/indexer/supervisor.ex | 4 - .../temporary/addresses_without_code.ex | 147 ------- .../temporary/failed_created_addresses.ex | 132 ------ .../temporary/addresses_without_code_test.exs | 389 ------------------ .../failed_created_addresses_test.exs | 78 ---- 5 files changed, 750 deletions(-) delete mode 100644 apps/indexer/lib/indexer/temporary/addresses_without_code.ex delete mode 100644 apps/indexer/lib/indexer/temporary/failed_created_addresses.ex delete mode 100644 apps/indexer/test/indexer/temporary/addresses_without_code_test.exs delete mode 100644 apps/indexer/test/indexer/temporary/failed_created_addresses_test.exs diff --git a/apps/indexer/lib/indexer/supervisor.ex b/apps/indexer/lib/indexer/supervisor.ex index 375a17e669..4e04b53092 100644 --- a/apps/indexer/lib/indexer/supervisor.ex +++ b/apps/indexer/lib/indexer/supervisor.ex @@ -24,8 +24,6 @@ defmodule Indexer.Supervisor do } alias Indexer.Temporary.{ - AddressesWithoutCode, - FailedCreatedAddresses, UncatalogedTokenTransfers, UnclesWithoutIndex } @@ -130,8 +128,6 @@ defmodule Indexer.Supervisor do {TokenUpdater.Supervisor, [%{update_interval: metadata_updater_inverval}]}, # Temporary workers - {AddressesWithoutCode.Supervisor, [fixing_realtime_fetcher]}, - {FailedCreatedAddresses.Supervisor, [json_rpc_named_arguments]}, {UncatalogedTokenTransfers.Supervisor, [[]]}, {UnclesWithoutIndex.Supervisor, [[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor]]} diff --git a/apps/indexer/lib/indexer/temporary/addresses_without_code.ex b/apps/indexer/lib/indexer/temporary/addresses_without_code.ex deleted file mode 100644 index 4aa36ce0b6..0000000000 --- a/apps/indexer/lib/indexer/temporary/addresses_without_code.ex +++ /dev/null @@ -1,147 +0,0 @@ -defmodule Indexer.Temporary.AddressesWithoutCode do - @moduledoc """ - Temporary module to fetch contract code for addresses without it. - """ - - use GenServer - use Indexer.Fetcher - - require Logger - - import Ecto.Query - - alias Explorer.Chain.{Address, Block, Transaction} - alias Explorer.Repo - alias Indexer.Block.Realtime.Fetcher - alias Indexer.Temporary.AddressesWithoutCode.TaskSupervisor - - @task_options [max_concurrency: 3, timeout: :infinity] - @batch_size 500 - @query_timeout :infinity - - def start_link([fetcher, gen_server_options]) do - GenServer.start_link(__MODULE__, fetcher, gen_server_options) - end - - @impl GenServer - def init(fetcher) do - schedule_work() - - {:ok, fetcher} - end - - def schedule_work do - Process.send_after(self(), :run, 1_000) - end - - @impl GenServer - def handle_info(:run, fetcher) do - run(fetcher) - - {:noreply, fetcher} - end - - def run(fetcher) do - fix_transaction_without_to_address_and_created_contract_address(fetcher) - fix_addresses_with_creation_transaction_but_without_code(fetcher) - end - - def fix_transaction_without_to_address_and_created_contract_address(fetcher) do - Logger.debug( - [ - "Started fix_transaction_without_to_address_and_created_contract_address" - ], - fetcher: :addresses_without_code - ) - - query = - from(block in Block, - left_join: transaction in Transaction, - on: block.hash == transaction.block_hash, - where: - is_nil(transaction.to_address_hash) and is_nil(transaction.created_contract_address_hash) and - block.consensus == true and is_nil(transaction.error) and not is_nil(transaction.hash), - distinct: block.hash - ) - - process_query(query, fetcher) - - Logger.debug( - [ - "Started fix_transaction_without_to_address_and_created_contract_address" - ], - fetcher: :addresses_without_code - ) - end - - def fix_addresses_with_creation_transaction_but_without_code(fetcher) do - Logger.debug( - [ - "Started fix_addresses_with_creation_transaction_but_without_code" - ], - fetcher: :addresses_without_code - ) - - second_query = - from(block in Block, - left_join: transaction in Transaction, - on: transaction.block_hash == block.hash, - left_join: address in Address, - on: address.hash == transaction.created_contract_address_hash, - where: - not is_nil(transaction.block_hash) and not is_nil(transaction.created_contract_address_hash) and - is_nil(address.contract_code) and - block.consensus == true and is_nil(transaction.error) and not is_nil(transaction.hash), - distinct: block.hash - ) - - process_query(second_query, fetcher) - - Logger.debug( - [ - "Finished fix_addresses_with_creation_transaction_but_without_code" - ], - fetcher: :addresses_without_code - ) - end - - defp process_query(query, fetcher) do - query_stream = Repo.stream(query, max_rows: @batch_size, timeout: @query_timeout) - - stream = - TaskSupervisor - |> Task.Supervisor.async_stream_nolink( - query_stream, - fn block -> refetch_block(block, fetcher) end, - @task_options - ) - - Repo.transaction(fn -> Stream.run(stream) end, timeout: @query_timeout) - end - - def refetch_block(block, fetcher) do - Logger.debug( - [ - "Processing block #{to_string(block.hash)} #{block.number}" - ], - fetcher: :addresses_without_code - ) - - Fetcher.fetch_and_import_block(block.number, fetcher, false) - - Logger.debug( - [ - "Finished processing block #{to_string(block.hash)} #{block.number}" - ], - fetcher: :addresses_without_code - ) - rescue - e -> - Logger.debug( - [ - "Failed to fetch block #{to_string(block.hash)} #{block.number} because of #{inspect(e)}" - ], - fetcher: :addresses_without_code - ) - end -end diff --git a/apps/indexer/lib/indexer/temporary/failed_created_addresses.ex b/apps/indexer/lib/indexer/temporary/failed_created_addresses.ex deleted file mode 100644 index a80cf657cd..0000000000 --- a/apps/indexer/lib/indexer/temporary/failed_created_addresses.ex +++ /dev/null @@ -1,132 +0,0 @@ -defmodule Indexer.Temporary.FailedCreatedAddresses do - @moduledoc """ - Temporary module to fix internal transactions and their created transactions if a parent transaction has failed. - """ - use GenServer - use Indexer.Fetcher - - require Logger - - import Ecto.Query - - alias Explorer.Chain.{Address, Data, InternalTransaction, Transaction} - alias Explorer.Repo - alias Indexer.Fetcher.ContractCode - alias Indexer.Temporary.FailedCreatedAddresses.TaskSupervisor - - @task_options [max_concurrency: 3, timeout: :infinity] - @query_timeout :infinity - - def start_link([json_rpc_named_arguments, gen_server_options]) do - GenServer.start_link(__MODULE__, json_rpc_named_arguments, gen_server_options) - end - - @impl GenServer - def init(json_rpc_named_arguments) do - schedule_work() - - {:ok, json_rpc_named_arguments} - end - - def schedule_work do - Process.send_after(self(), :run, 1_000) - end - - @impl GenServer - def handle_info(:run, json_rpc_named_arguments) do - run(json_rpc_named_arguments) - - {:noreply, json_rpc_named_arguments} - end - - def run(json_rpc_named_arguments) do - Logger.debug( - [ - "Started query to fetch internal transactions that need to be fixed" - ], - fetcher: :failed_created_addresses - ) - - data = %Data{bytes: ""} - - query = - from(t in Transaction, - left_join: it in InternalTransaction, - on: it.transaction_hash == t.hash, - left_join: address in Address, - on: address.hash == it.created_contract_address_hash, - where: t.status == ^0 and not is_nil(it.created_contract_address_hash) and address.contract_code != ^data, - distinct: t.hash - ) - - found_transactions = Repo.all(query, timeout: @query_timeout) - - Logger.debug( - [ - "Finished query to fetch internal transactions that need to be fixed. Number of records is #{ - Enum.count(found_transactions) - }" - ], - fetcher: :failed_created_addresses - ) - - TaskSupervisor - |> Task.Supervisor.async_stream_nolink( - found_transactions, - fn transaction -> fix_internal_transaction(transaction, json_rpc_named_arguments) end, - @task_options - ) - |> Enum.to_list() - end - - def fix_internal_transaction(transaction, json_rpc_named_arguments) do - # credo:disable-for-next-line - try do - Logger.debug( - [ - "Started fixing transaction #{to_string(transaction.hash)}" - ], - fetcher: :failed_created_addresses - ) - - transaction_with_internal_transactions = Repo.preload(transaction, [:internal_transactions]) - - transaction_with_internal_transactions.internal_transactions - |> Enum.filter(fn internal_transaction -> - internal_transaction.created_contract_address_hash - end) - |> Enum.each(fn internal_transaction -> - :ok = - internal_transaction - |> code_entry() - |> ContractCode.run(json_rpc_named_arguments) - end) - - Logger.debug( - [ - "Finished fixing transaction #{to_string(transaction.hash)}" - ], - fetcher: :failed_created_addresses - ) - rescue - e -> - Logger.debug( - [ - "Failed fixing transaction #{to_string(transaction.hash)} because of #{inspect(e)}" - ], - fetcher: :failed_created_addresses - ) - end - end - - def code_entry(%InternalTransaction{ - block_number: block_number, - created_contract_address_hash: %{bytes: created_contract_bytes} - }) do - [{block_number, created_contract_bytes, <<>>}] - end - - def transaction_entry(%Transaction{hash: %{bytes: bytes}, index: index, block_number: block_number}) do - [{block_number, bytes, index}] - end -end diff --git a/apps/indexer/test/indexer/temporary/addresses_without_code_test.exs b/apps/indexer/test/indexer/temporary/addresses_without_code_test.exs deleted file mode 100644 index 18efd3b557..0000000000 --- a/apps/indexer/test/indexer/temporary/addresses_without_code_test.exs +++ /dev/null @@ -1,389 +0,0 @@ -defmodule Indexer.Temporary.AddressesWithoutCodeTest do - use Explorer.DataCase, async: false - use EthereumJSONRPC.Case, async: false - - import Mox - - import Ecto.Query - - alias Explorer.Repo - alias Explorer.Chain.{Address, Transaction} - alias Indexer.Block.Fetcher - alias Indexer.Block.Realtime.Fetcher, as: RealtimeFetcher - alias Indexer.Fetcher.{CoinBalance, ContractCode, InternalTransaction, ReplacedTransaction, Token, TokenBalance} - alias Indexer.Temporary.AddressesWithoutCode.Supervisor - - @moduletag capture_log: true - - setup :set_mox_global - - setup :verify_on_exit! - - describe "run/1" do - setup %{json_rpc_named_arguments: json_rpc_named_arguments} do - CoinBalance.Supervisor.Case.start_supervised!(json_rpc_named_arguments: json_rpc_named_arguments) - ContractCode.Supervisor.Case.start_supervised!(json_rpc_named_arguments: json_rpc_named_arguments) - InternalTransaction.Supervisor.Case.start_supervised!(json_rpc_named_arguments: json_rpc_named_arguments) - Token.Supervisor.Case.start_supervised!(json_rpc_named_arguments: json_rpc_named_arguments) - TokenBalance.Supervisor.Case.start_supervised!(json_rpc_named_arguments: json_rpc_named_arguments) - ReplacedTransaction.Supervisor.Case.start_supervised!() - - [name: Indexer.Block.Realtime.TaskSupervisor] - |> Task.Supervisor.child_spec() - |> ExUnit.Callbacks.start_supervised!() - - fetcher = %Fetcher{ - broadcast: false, - callback_module: RealtimeFetcher, - json_rpc_named_arguments: json_rpc_named_arguments - } - - {:ok, %{fetcher: fetcher}} - end - - @tag :no_parity - @tag :no_geth - test "refetches blocks setting created address and code", %{ - fetcher: %{json_rpc_named_arguments: json_rpc_named_arguments} = fetcher - } do - block = insert(:block, consensus: true) - - transaction = - :transaction - |> insert( - status: 0, - to_address: nil, - created_contract_address_hash: nil, - block: block, - block_number: block.number, - block_hash: block.hash, - cumulative_gas_used: 200, - gas_used: 100, - index: 0 - ) - - address = insert(:address, contract_code: nil) - - if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do - EthereumJSONRPC.Mox - |> expect(:json_rpc, fn [%{id: id, method: "eth_getBlockByNumber", params: [_block_quantity, true]}], - _options -> - {:ok, - [ - %{ - id: id, - jsonrpc: "2.0", - result: %{ - "author" => "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", - "difficulty" => "0xfffffffffffffffffffffffffffffffe", - "extraData" => "0xd5830108048650617269747986312e32322e31826c69", - "gasLimit" => "0x69fe20", - "gasUsed" => "0xc512", - "hash" => "0xf6b4b8c88df3ebd252ec476328334dc026cf66606a84fb769b3d3cbccc8471bd", - "logsBloom" => - "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000200000000000000000000020000000000000000200000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner" => "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", - "number" => "0x25", - "parentHash" => "0xc37bbad7057945d1bf128c1ff009fb1ad632110bf6a000aac025a80f7766b66e", - "receiptsRoot" => "0xd300311aab7dcc98c05ac3f1893629b2c9082c189a0a0c76f4f63e292ac419d5", - "sealFields" => [ - "0x84120a71de", - "0xb841fcdb570511ec61edda93849bb7c6b3232af60feb2ea74e4035f0143ab66dfdd00f67eb3eda1adddbb6b572db1e0abd39ce00f9b3ccacb9f47973279ff306fe5401" - ], - "sha3Uncles" => "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "signature" => - "fcdb570511ec61edda93849bb7c6b3232af60feb2ea74e4035f0143ab66dfdd00f67eb3eda1adddbb6b572db1e0abd39ce00f9b3ccacb9f47973279ff306fe5401", - "size" => "0x2cf", - "stateRoot" => "0x2cd84079b0d0c267ed387e3895fd1c1dc21ff82717beb1132adac64276886e19", - "step" => "302674398", - "timestamp" => "0x5a343956", - "totalDifficulty" => "0x24ffffffffffffffffffffffffedf78dfd", - "transactions" => [ - %{ - "blockHash" => "0xf6b4b8c88df3ebd252ec476328334dc026cf66606a84fb769b3d3cbccc8471bd", - "blockNumber" => "0x25", - "chainId" => "0x4d", - "condition" => "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", - "creates" => to_string(address.hash), - "from" => "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", - "to" => nil, - "gas" => "0x47b760", - "gasPrice" => "0x174876e800", - "hash" => to_string(transaction.hash), - "input" => "0x10855269000000000000000000000000862d67cb0773ee3f8ce7ea89b328ffea861ab3ef", - "nonce" => "0x4", - "publicKey" => - "0xe5d196ad4ceada719d9e592f7166d0c75700f6eab2e3c3de34ba751ea786527cb3f6eb96ad9fdfdb9989ff572df50f1c42ef800af9c5207a38b929aff969b5c9", - "r" => "0xa7f8f45cce375bb7af8750416e1b03e0473f93c256da2285d1134fc97a700e01", - "raw" => - "0xf88a0485174876e8008347b760948bf38d4764929064f2d4d3a56520a76ab3df415b80a410855269000000000000000000000000862d67cb0773ee3f8ce7ea89b328ffea861ab3ef81bea0a7f8f45cce375bb7af8750416e1b03e0473f93c256da2285d1134fc97a700e01a01f87a076f13824f4be8963e3dffd7300dae64d5f23c9a062af0c6ead347c135f", - "s" => "0x1f87a076f13824f4be8963e3dffd7300dae64d5f23c9a062af0c6ead347c135f", - "standardV" => "0x1", - "transactionIndex" => "0x0", - "v" => "0xbe", - "value" => "0x0" - } - ], - "transactionsRoot" => "0x68e314a05495f390f9cd0c36267159522e5450d2adf254a74567b452e767bf34", - "uncles" => [] - } - } - ]} - end) - |> expect(:json_rpc, fn [ - %{ - id: id, - method: "eth_getTransactionReceipt", - params: _ - } - ], - _options -> - {:ok, - [ - %{ - id: id, - jsonrpc: "2.0", - result: %{ - "blockHash" => "0xf6b4b8c88df3ebd252ec476328334dc026cf66606a84fb769b3d3cbccc8471bd", - "blockNumber" => "0x25", - "contractAddress" => to_string(address.hash), - "cumulativeGasUsed" => "0xc512", - "gasUsed" => "0xc512", - "logs" => [ - %{ - "address" => "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", - "blockHash" => "0xf6b4b8c88df3ebd252ec476328334dc026cf66606a84fb769b3d3cbccc8471bd", - "blockNumber" => "0x25", - "data" => "0x000000000000000000000000862d67cb0773ee3f8ce7ea89b328ffea861ab3ef", - "logIndex" => "0x0", - "topics" => ["0x600bcf04a13e752d1e3670a5a9f1c21177ca2a93c6f5391d4f1298d098097c22"], - "transactionHash" => to_string(transaction.hash), - "transactionIndex" => "0x0", - "transactionLogIndex" => "0x0", - "type" => "mined" - } - ], - "logsBloom" => - "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000200000000000000000000020000000000000000200000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "root" => nil, - "status" => "0x1", - "transactionHash" => to_string(transaction.hash), - "transactionIndex" => "0x0" - } - } - ]} - end) - |> expect(:json_rpc, fn [%{id: id, method: "trace_block", params: _}], _options -> - {:ok, [%{id: id, result: []}]} - end) - |> expect(:json_rpc, fn [%{id: id, method: "trace_replayBlockTransactions", params: _}], _options -> - {:ok, [%{id: id, result: []}]} - end) - |> expect(:json_rpc, fn [ - %{ - id: 0, - jsonrpc: "2.0", - method: "eth_getBalance", - params: ["0x0000000000000000000000000000000000000003", "0x25"] - }, - %{ - id: 1, - jsonrpc: "2.0", - method: "eth_getBalance", - params: ["0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", "0x25"] - } - ], - _options -> - {:ok, [%{id: 0, jsonrpc: "2.0", result: "0x0"}, %{id: 1, jsonrpc: "2.0", result: "0x0"}]} - end) - end - - [fetcher, [name: AddressesWithoutCodeTest]] - |> Supervisor.child_spec() - |> ExUnit.Callbacks.start_supervised!() - - Process.sleep(5_000) - - updated_address = - from(a in Address, where: a.hash == ^address.hash, preload: :contracts_creation_transaction) |> Repo.one() - - assert updated_address.contracts_creation_transaction.hash == transaction.hash - - updated_transaction = - from(t in Transaction, where: t.hash == ^transaction.hash, preload: :created_contract_address) |> Repo.one() - - assert updated_transaction.created_contract_address.hash == address.hash - - assert updated_address.contract_code == updated_transaction.input - end - - @tag :no_parity - @tag :no_geth - test "doesn't set contract code if contract wasn't create", %{ - fetcher: %{json_rpc_named_arguments: json_rpc_named_arguments} = fetcher - } do - block = insert(:block, consensus: true) - - transaction = - :transaction - |> insert( - status: 0, - to_address: nil, - created_contract_address_hash: nil, - block: block, - block_number: block.number, - block_hash: block.hash, - cumulative_gas_used: 200, - gas_used: 100, - index: 0 - ) - - address = insert(:address, contract_code: nil) - - if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do - EthereumJSONRPC.Mox - |> expect(:json_rpc, fn [%{id: id, method: "eth_getBlockByNumber", params: [_block_quantity, true]}], - _options -> - {:ok, - [ - %{ - id: id, - jsonrpc: "2.0", - result: %{ - "author" => "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", - "difficulty" => "0xfffffffffffffffffffffffffffffffe", - "extraData" => "0xd5830108048650617269747986312e32322e31826c69", - "gasLimit" => "0x69fe20", - "gasUsed" => "0xc512", - "hash" => "0xf6b4b8c88df3ebd252ec476328334dc026cf66606a84fb769b3d3cbccc8471bd", - "logsBloom" => - "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000200000000000000000000020000000000000000200000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner" => "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", - "number" => "0x25", - "parentHash" => "0xc37bbad7057945d1bf128c1ff009fb1ad632110bf6a000aac025a80f7766b66e", - "receiptsRoot" => "0xd300311aab7dcc98c05ac3f1893629b2c9082c189a0a0c76f4f63e292ac419d5", - "sealFields" => [ - "0x84120a71de", - "0xb841fcdb570511ec61edda93849bb7c6b3232af60feb2ea74e4035f0143ab66dfdd00f67eb3eda1adddbb6b572db1e0abd39ce00f9b3ccacb9f47973279ff306fe5401" - ], - "sha3Uncles" => "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "signature" => - "fcdb570511ec61edda93849bb7c6b3232af60feb2ea74e4035f0143ab66dfdd00f67eb3eda1adddbb6b572db1e0abd39ce00f9b3ccacb9f47973279ff306fe5401", - "size" => "0x2cf", - "stateRoot" => "0x2cd84079b0d0c267ed387e3895fd1c1dc21ff82717beb1132adac64276886e19", - "step" => "302674398", - "timestamp" => "0x5a343956", - "totalDifficulty" => "0x24ffffffffffffffffffffffffedf78dfd", - "transactions" => [ - %{ - "blockHash" => "0xf6b4b8c88df3ebd252ec476328334dc026cf66606a84fb769b3d3cbccc8471bd", - "blockNumber" => "0x25", - "chainId" => "0x4d", - "condition" => "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", - "from" => "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", - "to" => nil, - "gas" => "0x47b760", - "gasPrice" => "0x174876e800", - "hash" => to_string(transaction.hash), - "input" => "0x10855269000000000000000000000000862d67cb0773ee3f8ce7ea89b328ffea861ab3ef", - "nonce" => "0x4", - "publicKey" => - "0xe5d196ad4ceada719d9e592f7166d0c75700f6eab2e3c3de34ba751ea786527cb3f6eb96ad9fdfdb9989ff572df50f1c42ef800af9c5207a38b929aff969b5c9", - "r" => "0xa7f8f45cce375bb7af8750416e1b03e0473f93c256da2285d1134fc97a700e01", - "raw" => - "0xf88a0485174876e8008347b760948bf38d4764929064f2d4d3a56520a76ab3df415b80a410855269000000000000000000000000862d67cb0773ee3f8ce7ea89b328ffea861ab3ef81bea0a7f8f45cce375bb7af8750416e1b03e0473f93c256da2285d1134fc97a700e01a01f87a076f13824f4be8963e3dffd7300dae64d5f23c9a062af0c6ead347c135f", - "s" => "0x1f87a076f13824f4be8963e3dffd7300dae64d5f23c9a062af0c6ead347c135f", - "standardV" => "0x1", - "transactionIndex" => "0x0", - "v" => "0xbe", - "value" => "0x0" - } - ], - "transactionsRoot" => "0x68e314a05495f390f9cd0c36267159522e5450d2adf254a74567b452e767bf34", - "uncles" => [] - } - } - ]} - end) - |> expect(:json_rpc, fn [ - %{ - id: id, - method: "eth_getTransactionReceipt", - params: _ - } - ], - _options -> - {:ok, - [ - %{ - id: id, - jsonrpc: "2.0", - result: %{ - "blockHash" => "0xf6b4b8c88df3ebd252ec476328334dc026cf66606a84fb769b3d3cbccc8471bd", - "blockNumber" => "0x25", - "contractAddress" => nil, - "cumulativeGasUsed" => "0xc512", - "gasUsed" => "0xc512", - "logs" => [ - %{ - "address" => "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", - "blockHash" => "0xf6b4b8c88df3ebd252ec476328334dc026cf66606a84fb769b3d3cbccc8471bd", - "blockNumber" => "0x25", - "data" => "0x000000000000000000000000862d67cb0773ee3f8ce7ea89b328ffea861ab3ef", - "logIndex" => "0x0", - "topics" => ["0x600bcf04a13e752d1e3670a5a9f1c21177ca2a93c6f5391d4f1298d098097c22"], - "transactionHash" => to_string(transaction.hash), - "transactionIndex" => "0x0", - "transactionLogIndex" => "0x0", - "type" => "mined" - } - ], - "logsBloom" => - "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000200000000000000000000020000000000000000200000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "root" => nil, - "status" => "0x1", - "transactionHash" => to_string(transaction.hash), - "transactionIndex" => "0x0" - } - } - ]} - end) - |> expect(:json_rpc, fn [%{id: id, method: "trace_block", params: _}], _options -> - {:ok, [%{id: id, result: []}]} - end) - |> expect(:json_rpc, fn [%{id: id, method: "trace_replayBlockTransactions", params: _}], _options -> - {:ok, [%{id: id, result: []}]} - end) - |> expect(:json_rpc, fn [ - %{ - id: 1, - jsonrpc: "2.0", - method: "eth_getBalance", - params: ["0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca", "0x25"] - } - ], - _options -> - {:ok, [%{id: 1, jsonrpc: "2.0", result: "0x0"}]} - end) - end - - [fetcher, [name: AddressesWithoutCodeTest1]] - |> Supervisor.child_spec() - |> ExUnit.Callbacks.start_supervised!() - - Process.sleep(2_000) - - updated_address = - from(a in Address, where: a.hash == ^address.hash, preload: :contracts_creation_transaction) |> Repo.one() - - assert is_nil(updated_address.contracts_creation_transaction) - - updated_transaction = - from(t in Transaction, where: t.hash == ^transaction.hash, preload: :created_contract_address) |> Repo.one() - - assert is_nil(updated_transaction.created_contract_address) - - assert is_nil(updated_address.contract_code) - end - end -end diff --git a/apps/indexer/test/indexer/temporary/failed_created_addresses_test.exs b/apps/indexer/test/indexer/temporary/failed_created_addresses_test.exs deleted file mode 100644 index ef03376161..0000000000 --- a/apps/indexer/test/indexer/temporary/failed_created_addresses_test.exs +++ /dev/null @@ -1,78 +0,0 @@ -defmodule Indexer.Temporary.FailedCreatedAddressesTest do - use Explorer.DataCase, async: false - use EthereumJSONRPC.Case, async: false - - import Mox - - import Ecto.Query - - alias Explorer.Repo - alias Explorer.Chain.Address - alias Indexer.Fetcher.CoinBalance - alias Indexer.Temporary.FailedCreatedAddresses.Supervisor - - @moduletag capture_log: true - - setup :set_mox_global - - setup :verify_on_exit! - - describe "run/1" do - @tag :no_parity - @tag :no_geth - test "updates failed replaced transactions", %{json_rpc_named_arguments: json_rpc_named_arguments} do - CoinBalance.Supervisor.Case.start_supervised!(json_rpc_named_arguments: json_rpc_named_arguments) - - block = insert(:block) - - transaction = - :transaction - |> insert( - status: 0, - error: "Reverted", - internal_transactions_indexed_at: DateTime.utc_now(), - block: block, - block_number: block.number, - cumulative_gas_used: 200, - gas_used: 100, - index: 0 - ) - - address = insert(:address, contract_code: "0x0102030405") - - insert(:internal_transaction, - block_number: transaction.block_number, - transaction: transaction, - index: 0, - created_contract_address_hash: address.hash - ) - - if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do - EthereumJSONRPC.Mox - |> expect(:json_rpc, fn _json, _options -> - {:ok, [%{id: 0, jsonrpc: "2.0", result: "0x"}]} - end) - |> expect(:json_rpc, fn [%{id: id, method: "eth_getBalance", params: [_address, _block_quantity]}], _options -> - {:ok, [%{id: id, result: "0x0"}]} - end) - end - - params = [json_rpc_named_arguments, [name: TestFailedCreatedAddresses]] - - params - |> Supervisor.child_spec() - |> ExUnit.Callbacks.start_supervised!() - - Process.sleep(3_000) - - fetched_address = - Repo.one( - from(a in Address, - where: a.hash == ^address.hash - ) - ) - - assert fetched_address.contract_code == %Explorer.Chain.Data{bytes: ""} - end - end -end From 88a2a528f7c3711b5092294060301416da7cbaab Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 6 May 2019 10:30:34 +0300 Subject: [PATCH 029/191] fix build --- apps/indexer/lib/indexer/supervisor.ex | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/indexer/lib/indexer/supervisor.ex b/apps/indexer/lib/indexer/supervisor.ex index 4e04b53092..21dc3637ec 100644 --- a/apps/indexer/lib/indexer/supervisor.ex +++ b/apps/indexer/lib/indexer/supervisor.ex @@ -78,12 +78,6 @@ defmodule Indexer.Supervisor do |> Map.drop(~w(block_interval blocks_concurrency memory_monitor subscribe_named_arguments realtime_overrides)a) |> Block.Fetcher.new() - fixing_realtime_fetcher = %Block.Fetcher{ - broadcast: false, - callback_module: Realtime.Fetcher, - json_rpc_named_arguments: json_rpc_named_arguments - } - realtime_block_fetcher = named_arguments |> Map.drop(~w(block_interval blocks_concurrency memory_monitor subscribe_named_arguments realtime_overrides)a) From baecd9462d9393a2b54ef181928f323a880fcfe6 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 6 May 2019 10:36:31 +0300 Subject: [PATCH 030/191] add CHANGELOG entry --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7901172443..40aa891851 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ - [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x" - [#1813](https://github.com/poanetwork/blockscout/pull/1813) - add total blocks counter to the main page - [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request -- [#1857](https://github.com/poanetwork/blockscout/pull/1857) - Re-implement Geth JS internal transaction tracer in Elixir +- [#1857](https://github.com/poanetwork/blockscout/pull/1857) - Re-implement Geth JS internal transaction tracer in Elixir - [#1859](https://github.com/poanetwork/blockscout/pull/1859) - feat: show raw transaction traces ### Fixes @@ -23,6 +23,7 @@ - [#1814](https://github.com/poanetwork/blockscout/pull/1814) - Clear build artefacts script - [#1837](https://github.com/poanetwork/blockscout/pull/1837) - Add -f flag to clear_build.sh script delete static folder +- [#1892](https://github.com/poanetwork/blockscout/pull/1892) - Remove temporary worker modules ## 1.3.10-beta From 42b56fb62ba581e1f2a4c89eb63ead3afe237e4e Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Mon, 6 May 2019 11:06:45 +0300 Subject: [PATCH 031/191] Update CHANGELOG.md --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f80c101ff..132cad2fa7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- [#1874](https://github.com/poanetwork/blockscout/pull/1874) - add changes to ethereum theme and ethereum logo - [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x" - [#1813](https://github.com/poanetwork/blockscout/pull/1813) - add total blocks counter to the main page - [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request @@ -201,5 +202,3 @@ - [https://github.com/poanetwork/blockscout/pull/1553](https://github.com/poanetwork/blockscout/pull/1553) - Dockerfile: remove 1.7.1 version pin FROM bitwalker/alpine-elixir-phoenix - [https://github.com/poanetwork/blockscout/pull/1465](https://github.com/poanetwork/blockscout/pull/1465) - Resolve lodash security alert -### Improvements -- [#1874](https://github.com/poanetwork/blockscout/pull/1874) - add changes to ethereum theme and ethereum logo From 7dadb446bed862e8818d521ca20da89882be2817 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 6 May 2019 14:17:51 +0300 Subject: [PATCH 032/191] add CHANGELOG entry --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7901172443..7e566541cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ - [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x" - [#1813](https://github.com/poanetwork/blockscout/pull/1813) - add total blocks counter to the main page - [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request -- [#1857](https://github.com/poanetwork/blockscout/pull/1857) - Re-implement Geth JS internal transaction tracer in Elixir +- [#1857](https://github.com/poanetwork/blockscout/pull/1857) - Re-implement Geth JS internal transaction tracer in Elixir - [#1859](https://github.com/poanetwork/blockscout/pull/1859) - feat: show raw transaction traces ### Fixes @@ -18,6 +18,7 @@ - [#1869](https://github.com/poanetwork/blockscout/pull/1869) - Fix output and gas extraction in JS tracer for Geth - [#1868](https://github.com/poanetwork/blockscout/pull/1868) - fix: logs list endpoint performance - [#1822](https://github.com/poanetwork/blockscout/pull/1822) - Fix style breaks in decompiled contract code view +- [#1885](https://github.com/poanetwork/blockscout/pull/1885) - highlight reserved words in decompiled code ### Chore From f6905d4e3355b6696891c4b61490cbde040b20e0 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Mon, 6 May 2019 14:58:44 +0300 Subject: [PATCH 033/191] Update _poa_variables.scss --- .../assets/css/theme/_poa_variables.scss | 55 ++++++++++++++++--- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/apps/block_scout_web/assets/css/theme/_poa_variables.scss b/apps/block_scout_web/assets/css/theme/_poa_variables.scss index da2fe0de74..198c89ba5a 100644 --- a/apps/block_scout_web/assets/css/theme/_poa_variables.scss +++ b/apps/block_scout_web/assets/css/theme/_poa_variables.scss @@ -1,11 +1,50 @@ -$primary: #5b389f; -$secondary: #7dd79f; -$tertiary: #997fdc; +// general +$primary: #5c34a2; +$secondary: #87e1a9; +$tertiary: #bf9cff; +$additional-font: #fff; -$header-links-color-active: #333; -$button-secondary-color: $primary; - -$footer-background-color: $primary; +// footer +$footer-background-color: #3c226a; $footer-title-color: #fff; -$footer-text-color: #fff; +$footer-text-color: #bda6e7; $footer-item-disc-color: $secondary; +.footer-logo { filter: brightness(0) invert(1); } + +// dashboard +$dashboard-line-color-price: $tertiary; // price left border + +$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels + +$dashboard-stats-item-value-color: $additional-font; // stat values + +$dashboard-stats-item-border-color: $secondary; // stat border + +$dashboard-banner-gradient-start: $primary; // gradient begin + +$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end + +$dashboard-banner-network-plain-container-background-color: #865bd4; // stats bg + + +// navigation +.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow +$header-icon-border-color-hover: $primary; // top border on hover +$header-icon-color-hover: $primary; // nav icon on hover +.dropdown-item:hover, .dropdown-item:focus { background-color: $primary !important; } // dropdown item on hover + +// buttons +$btn-line-bg: #fff; // button bg +$btn-line-color: $primary; // button border and font color && hover bg color +$btn-copy-color: $primary; // btn copy +$btn-qr-color: $primary; // btn qr-code + +//links & tile +.tile a { color: $primary !important; } // links color for badges +.tile-type-block { + border-left: 4px solid $primary; +} // tab active bg + +// card +$card-background-1: $primary; +$card-tab-active: $primary; From 4af728ea8dc8ba584c76cbc5de473283a7829dd5 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Mon, 6 May 2019 14:59:44 +0300 Subject: [PATCH 034/191] Update poa_logo.svg --- apps/block_scout_web/assets/static/images/poa_logo.svg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/block_scout_web/assets/static/images/poa_logo.svg b/apps/block_scout_web/assets/static/images/poa_logo.svg index 551871a7e1..321033174f 100644 --- a/apps/block_scout_web/assets/static/images/poa_logo.svg +++ b/apps/block_scout_web/assets/static/images/poa_logo.svg @@ -1 +1,3 @@ -poa_logo \ No newline at end of file + + + From f0cb59c26b6c1c5b0cc351494f2e2f0cdff9d9b4 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Mon, 6 May 2019 15:08:29 +0300 Subject: [PATCH 035/191] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 132cad2fa7..9bf1a98a5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## Current ### Features - +- [#1895](https://github.com/poanetwork/blockscout/pull/1874) - add changes to poa theme and poa logo - [#1874](https://github.com/poanetwork/blockscout/pull/1874) - add changes to ethereum theme and ethereum logo - [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x" - [#1813](https://github.com/poanetwork/blockscout/pull/1813) - add total blocks counter to the main page From fd64a6eb270f7cfd5de74a57cc0f81cbbb9b911c Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 6 May 2019 15:38:07 +0300 Subject: [PATCH 036/191] requery tokens in top nav automplete --- .../lib/block_scout_web/templates/layout/_topnav.html.eex | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex index 032ab22930..f7392a6b39 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex @@ -112,9 +112,8 @@ "data-test": "search_input" ], [ url: "#{chain_path(@conn, :token_autocomplete)}?q=", - prepop: true, - minChars: 3, - maxItems: 8, + limit: 0, + minChars: 2, value: "contract_address_hash", label: "contract_address_hash", descrSearch: true, From cbc701b789e498ef39ccc25ab2fcc5b6f974511e Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 6 May 2019 15:40:53 +0300 Subject: [PATCH 037/191] add CHANGELOG entry --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b951086721..b7f41344db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x" - [#1813](https://github.com/poanetwork/blockscout/pull/1813) - add total blocks counter to the main page - [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request -- [#1857](https://github.com/poanetwork/blockscout/pull/1857) - Re-implement Geth JS internal transaction tracer in Elixir +- [#1857](https://github.com/poanetwork/blockscout/pull/1857) - Re-implement Geth JS internal transaction tracer in Elixir - [#1859](https://github.com/poanetwork/blockscout/pull/1859) - feat: show raw transaction traces ### Fixes @@ -20,6 +20,7 @@ - [#1869](https://github.com/poanetwork/blockscout/pull/1869) - Fix output and gas extraction in JS tracer for Geth - [#1868](https://github.com/poanetwork/blockscout/pull/1868) - fix: logs list endpoint performance - [#1822](https://github.com/poanetwork/blockscout/pull/1822) - Fix style breaks in decompiled contract code view +- [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete ### Chore @@ -202,4 +203,3 @@ - [https://github.com/poanetwork/blockscout/pull/1532](https://github.com/poanetwork/blockscout/pull/1532) - Upgrade elixir to 1.8.1 - [https://github.com/poanetwork/blockscout/pull/1553](https://github.com/poanetwork/blockscout/pull/1553) - Dockerfile: remove 1.7.1 version pin FROM bitwalker/alpine-elixir-phoenix - [https://github.com/poanetwork/blockscout/pull/1465](https://github.com/poanetwork/blockscout/pull/1465) - Resolve lodash security alert - From e8b53ac8edc67a061bfebbeae1d8c371dfe4fa7a Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 6 May 2019 15:43:25 +0300 Subject: [PATCH 038/191] fix gettext --- apps/block_scout_web/priv/gettext/default.pot | 2 +- apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 8ee6c84113..d38ebaced2 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -714,7 +714,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/layout/_topnav.html.eex:111 -#: lib/block_scout_web/templates/layout/_topnav.html.eex:129 +#: lib/block_scout_web/templates/layout/_topnav.html.eex:128 msgid "Search" 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 4612b16a72..067af0cd66 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 @@ -714,7 +714,7 @@ msgstr "" #, elixir-format #: lib/block_scout_web/templates/layout/_topnav.html.eex:111 -#: lib/block_scout_web/templates/layout/_topnav.html.eex:129 +#: lib/block_scout_web/templates/layout/_topnav.html.eex:128 msgid "Search" msgstr "" From 2e0bab6cab343a4b2250a7b0c56447640be71deb Mon Sep 17 00:00:00 2001 From: zachdaniel Date: Thu, 2 May 2019 13:48:05 -0400 Subject: [PATCH 039/191] fix: store solc versions locally for performance --- CHANGELOG.md | 1 + apps/explorer/.gitignore | 3 +- apps/explorer/lib/explorer/application.ex | 1 + .../smart_contract/solc_downloader.ex | 92 +++++++++++++++++++ .../smart_contract/solidity/code_compiler.ex | 57 +++++++----- apps/explorer/priv/compile_solc.js | 64 +++++++------ 6 files changed, 159 insertions(+), 59 deletions(-) create mode 100644 apps/explorer/lib/explorer/smart_contract/solc_downloader.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index eeb0f377f6..1460a1af7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - [#1868](https://github.com/poanetwork/blockscout/pull/1868) - fix: logs list endpoint performance - [#1822](https://github.com/poanetwork/blockscout/pull/1822) - Fix style breaks in decompiled contract code view - [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete +- [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance ### Chore diff --git a/apps/explorer/.gitignore b/apps/explorer/.gitignore index f4cd5728cc..bf75b19355 100644 --- a/apps/explorer/.gitignore +++ b/apps/explorer/.gitignore @@ -1 +1,2 @@ -priv/.recovery \ No newline at end of file +priv/.recovery +priv/solc_compilers/ diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index 47b30cfa2b..b4f8589a57 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -26,6 +26,7 @@ defmodule Explorer.Application do 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.TaskSupervisor}, id: Explorer.TaskSupervisor), + Explorer.SmartContract.SolcDownloader, {Registry, keys: :duplicate, name: Registry.ChainEvents, id: Registry.ChainEvents}, {Admin.Recovery, [[], [name: Admin.Recovery]]}, {TransactionCountCache, [[], []]} diff --git a/apps/explorer/lib/explorer/smart_contract/solc_downloader.ex b/apps/explorer/lib/explorer/smart_contract/solc_downloader.ex new file mode 100644 index 0000000000..1aa81d2488 --- /dev/null +++ b/apps/explorer/lib/explorer/smart_contract/solc_downloader.ex @@ -0,0 +1,92 @@ +defmodule Explorer.SmartContract.SolcDownloader do + @moduledoc """ + Checks to see if the requested solc compiler version exists, and if not it + downloads and stores the file. + """ + use GenServer + + alias Explorer.SmartContract.Solidity.CompilerVersion + + @latest_compiler_refetch_time :timer.minutes(30) + + def ensure_exists(version) do + path = file_path(version) + + if File.exists?(path) do + path + else + {:ok, compiler_versions} = CompilerVersion.fetch_versions() + + if version in compiler_versions do + GenServer.call(__MODULE__, {:ensure_exists, version}, 60_000) + else + false + end + end + end + + def start_link(_) do + GenServer.start_link(__MODULE__, [], name: __MODULE__) + end + + # sobelow_skip ["Traversal"] + @impl true + def init([]) do + File.mkdir(compiler_dir()) + + {:ok, []} + end + + # sobelow_skip ["Traversal"] + @impl true + def handle_call({:ensure_exists, version}, _from, state) do + path = file_path(version) + + if fetch?(version, path) do + temp_path = file_path("#{version}-tmp") + + contents = download(version) + + file = File.open!(temp_path, [:write, :exclusive]) + + IO.binwrite(file, contents) + + File.rename(temp_path, path) + end + + {:reply, path, state} + end + + defp fetch?("latest", path) do + case File.stat(path) do + {:error, :enoent} -> + true + + {:ok, %{mtime: mtime}} -> + last_modified = NaiveDateTime.from_erl!(mtime) + diff = Timex.diff(NaiveDateTime.utc_now(), last_modified, :milliseconds) + + diff > @latest_compiler_refetch_time + end + end + + defp fetch?(_, path) do + not File.exists?(path) + end + + defp file_path(version) do + Path.join(compiler_dir(), "#{version}.js") + end + + defp compiler_dir do + Application.app_dir(:explorer, "priv/solc_compilers/") + end + + defp download(version) do + download_path = "https://ethereum.github.io/solc-bin/bin/soljson-#{version}.js" + + download_path + |> HTTPoison.get!([], timeout: 60_000) + |> Map.get(:body) + end +end diff --git a/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex b/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex index e7f6090707..72c5bae186 100644 --- a/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex +++ b/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex @@ -3,6 +3,8 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do Module responsible to compile the Solidity code of a given Smart Contract. """ + alias Explorer.SmartContract.SolcDownloader + @new_contract_name "New.sol" @allowed_evm_versions ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg"] @@ -79,31 +81,36 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do "byzantium" end - {response, _status} = - System.cmd( - "node", - [ - Application.app_dir(:explorer, "priv/compile_solc.js"), - code, - compiler_version, - optimize_value(optimize), - optimization_runs, - @new_contract_name, - external_libs_string, - checked_evm_version - ] - ) - - with {:ok, contracts} <- Jason.decode(response), - %{"abi" => abi, "evm" => %{"deployedBytecode" => %{"object" => bytecode}}} <- - get_contract_info(contracts, name) do - {:ok, %{"abi" => abi, "bytecode" => bytecode, "name" => name}} - else - {:error, %Jason.DecodeError{}} -> - {:error, :compilation} - - error -> - parse_error(error) + path = SolcDownloader.ensure_exists(compiler_version) + + if path do + {response, _status} = + System.cmd( + "node", + [ + Application.app_dir(:explorer, "priv/compile_solc.js"), + code, + compiler_version, + optimize_value(optimize), + optimization_runs, + @new_contract_name, + external_libs_string, + checked_evm_version, + path + ] + ) + + with {:ok, contracts} <- Jason.decode(response), + %{"abi" => abi, "evm" => %{"deployedBytecode" => %{"object" => bytecode}}} <- + get_contract_info(contracts, name) do + {:ok, %{"abi" => abi, "bytecode" => bytecode, "name" => name}} + else + {:error, %Jason.DecodeError{}} -> + {:error, :compilation} + + error -> + parse_error(error) + end end end diff --git a/apps/explorer/priv/compile_solc.js b/apps/explorer/priv/compile_solc.js index 7179ebda56..5aaf3f54d7 100755 --- a/apps/explorer/priv/compile_solc.js +++ b/apps/explorer/priv/compile_solc.js @@ -1,7 +1,5 @@ #!/usr/bin/env node -const solc = require('solc'); - var sourceCode = process.argv[2]; var version = process.argv[3]; var optimize = process.argv[4]; @@ -9,38 +7,38 @@ var optimizationRuns = parseInt(process.argv[5], 10); var newContractName = process.argv[6]; var externalLibraries = JSON.parse(process.argv[7]) var evmVersion = process.argv[8]; +var compilerVersionPath = process.argv[9]; + +var solc = require('solc') +var compilerSnapshot = require(compilerVersionPath); +var solc = solc.setupMethods(compilerSnapshot); -var compiled_code = solc.loadRemoteVersion(version, function (err, solcSnapshot) { - if (err) { - console.log(JSON.stringify(err.message)); - } else { - const input = { - language: 'Solidity', - sources: { - [newContractName]: { - content: sourceCode - } - }, - settings: { - evmVersion: evmVersion, - optimizer: { - enabled: optimize == '1', - runs: optimizationRuns - }, - libraries: { - [newContractName]: externalLibraries - }, - outputSelection: { - '*': { - '*': ['*'] - } - } +const input = { + language: 'Solidity', + sources: { + [newContractName]: { + content: sourceCode + } + }, + settings: { + evmVersion: evmVersion, + optimizer: { + enabled: optimize == '1', + runs: optimizationRuns + }, + libraries: { + [newContractName]: externalLibraries + }, + outputSelection: { + '*': { + '*': ['*'] } } - - const output = JSON.parse(solcSnapshot.compile(JSON.stringify(input))) - /** Older solc-bin versions don't use filename as contract key */ - const response = output.contracts[newContractName] || output.contracts[''] - console.log(JSON.stringify(response)); } -}); +} + + +const output = JSON.parse(solc.compile(JSON.stringify(input))) +/** Older solc-bin versions don't use filename as contract key */ +const response = output.contracts[newContractName] || output.contracts[''] +console.log(JSON.stringify(response)); From 98eb50cc03a5db9f76c36e89ff8e5e9242bcc497 Mon Sep 17 00:00:00 2001 From: Andrew Gross Date: Mon, 6 May 2019 16:13:31 -0600 Subject: [PATCH 040/191] add location clarification for mix phx.server command --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a2df24f85c..289a3d35ed 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ The [development stack page](https://github.com/poanetwork/blockscout/wiki/Devel ``` * If using Chrome, Enable `chrome://flags/#allow-insecure-localhost`. - 9. Start Phoenix Server. + 9. Run the Phoenix Server from the root directory of your application. `mix phx.server` Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. From ab758d008aa1709d662f107de1bc7e6c220dd508 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 7 May 2019 11:26:09 +0300 Subject: [PATCH 041/191] check if construct has arguments --- .../lib/explorer/smart_contract/verifier.ex | 6 +- .../solidity/code_compiler_test.exs | 95 +++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/apps/explorer/lib/explorer/smart_contract/verifier.ex b/apps/explorer/lib/explorer/smart_contract/verifier.ex index 0fc9f6b21b..4b521fba35 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier.ex @@ -74,7 +74,7 @@ defmodule Explorer.SmartContract.Verifier do generated_bytecode != blockchain_bytecode_without_whisper -> {:error, :generated_bytecode} - !ConstructorArguments.verify(address_hash, arguments_data) -> + has_constructor_with_params?(abi) && !ConstructorArguments.verify(address_hash, arguments_data) -> {:error, :constructor_arguments} true -> @@ -111,4 +111,8 @@ defmodule Explorer.SmartContract.Verifier do prev_version end end + + defp has_constructor_with_params?(abi) do + Enum.any?(abi, fn el -> el["type"] == "constructor" && el["inputs"] != [] end) + end end diff --git a/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs b/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs index 79bbb62f70..57f15577ac 100644 --- a/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs +++ b/apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs @@ -173,6 +173,101 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do assert {:error, :compilation} = response end + + test "returns constructor in abi" do + code = """ + pragma solidity ^0.4.22; + + contract OwnedToken { + // TokenCreator is a contract type that is defined below. + // It is fine to reference it as long as it is not used + // to create a new contract. + TokenCreator creator; + address owner; + bytes32 name; + + // This is the constructor which registers the + // creator and the assigned name. + constructor(bytes32 _name) public { + // State variables are accessed via their name + // and not via e.g. this.owner. This also applies + // to functions and especially in the constructors, + // you can only call them like that ("internally"), + // because the contract itself does not exist yet. + owner = msg.sender; + // We do an explicit type conversion from `address` + // to `TokenCreator` and assume that the type of + // the calling contract is TokenCreator, there is + // no real way to check that. + creator = TokenCreator(msg.sender); + name = _name; + } + + function changeName(bytes32 newName) public { + // Only the creator can alter the name -- + // the comparison is possible since contracts + // are implicitly convertible to addresses. + if (msg.sender == address(creator)) + name = newName; + } + + function transfer(address newOwner) public { + // Only the current owner can transfer the token. + if (msg.sender != owner) return; + // We also want to ask the creator if the transfer + // is fine. Note that this calls a function of the + // contract defined below. If the call fails (e.g. + // due to out-of-gas), the execution here stops + // immediately. + if (creator.isTokenTransferOK(owner, newOwner)) + owner = newOwner; + } + } + + contract TokenCreator { + function createToken(bytes32 name) + public + returns (OwnedToken tokenAddress) + { + // Create a new Token contract and return its address. + // From the JavaScript side, the return type is simply + // `address`, as this is the closest type available in + // the ABI. + return new OwnedToken(name); + } + + function changeName(OwnedToken tokenAddress, bytes32 name) public { + // Again, the external type of `tokenAddress` is + // simply `address`. + tokenAddress.changeName(name); + } + + function isTokenTransferOK(address currentOwner, address newOwner) + public + view + returns (bool ok) + { + // Check some arbitrary condition. + address tokenAddress = msg.sender; + return (keccak256(newOwner) & 0xff) == (bytes20(tokenAddress) & 0xff); + } + } + """ + + name = "OwnedToken" + compiler_version = "v0.4.22+commit.4cb486ee" + + {:ok, %{"abi" => abi}} = + CodeCompiler.run( + name: name, + compiler_version: compiler_version, + code: code, + evm_version: "byzantium", + optimize: true + ) + + assert Enum.any?(abi, fn el -> el["type"] == "constructor" end) + end end describe "get_contract_info/1" do From e8bc0e6b6bcadb16ffacc5753401cf3755d50209 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 7 May 2019 11:41:51 +0300 Subject: [PATCH 042/191] remove expired test --- .../explorer/smart_contract/verifier_test.exs | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/apps/explorer/test/explorer/smart_contract/verifier_test.exs b/apps/explorer/test/explorer/smart_contract/verifier_test.exs index 631c15695e..1e8301a90c 100644 --- a/apps/explorer/test/explorer/smart_contract/verifier_test.exs +++ b/apps/explorer/test/explorer/smart_contract/verifier_test.exs @@ -117,31 +117,6 @@ defmodule Explorer.SmartContract.VerifierTest do assert abi != nil end - test "returns error when constructor arguments do not match", %{ - contract_code_info: contract_code_info - } do - contract_address = insert(:contract_address, contract_code: contract_code_info.bytecode) - - constructor_arguments = "0102030405" - - params = %{ - "contract_source_code" => contract_code_info.source_code, - "compiler_version" => contract_code_info.version, - "name" => contract_code_info.name, - "optimization" => contract_code_info.optimized, - "constructor_arguments" => constructor_arguments - } - - :transaction - |> insert( - created_contract_address_hash: contract_address.hash, - input: Verifier.extract_bytecode(contract_code_info.bytecode) <> "010203" - ) - |> with_block() - - assert {:error, :constructor_arguments} = Verifier.evaluate_authenticity(contract_address.hash, params) - end - test "returns error when bytecode doesn't match", %{contract_code_info: contract_code_info} do contract_address = insert(:contract_address, contract_code: contract_code_info.bytecode) From 7acf983c9bf6020f723c165e9faa368961a3cac2 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 7 May 2019 11:44:40 +0300 Subject: [PATCH 043/191] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1460a1af7d..a546f01a95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - [#1822](https://github.com/poanetwork/blockscout/pull/1822) - Fix style breaks in decompiled contract code view - [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete - [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance +- [#1898](https://github.com/poanetwork/blockscout/pull/1898) - check if the constructor has arguments before verifying constructor arguments ### Chore From a71526b4c5c76e36b4cad8af08894f76919943cc Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Tue, 7 May 2019 13:03:20 +0300 Subject: [PATCH 044/191] Supported chains env var --- apps/block_scout_web/config/config.exs | 60 +------------------ .../lib/block_scout_web/views/layout_view.ex | 6 +- 2 files changed, 6 insertions(+), 60 deletions(-) diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs index 78b887b122..f38ed779b5 100644 --- a/apps/block_scout_web/config/config.exs +++ b/apps/block_scout_web/config/config.exs @@ -28,65 +28,7 @@ config :block_scout_web, "EtherChain" => "https://www.etherchain.org/", "Bloxy" => "https://bloxy.info/" }, - other_networks: [ - %{ - title: "POA Core", - url: "https://blockscout.com/poa/core" - }, - %{ - title: "POA Sokol", - url: "https://blockscout.com/poa/sokol", - test_net?: true - }, - %{ - title: "xDai Chain", - url: "https://blockscout.com/poa/dai" - }, - %{ - title: "Ethereum Mainnet", - url: "https://blockscout.com/eth/mainnet" - }, - %{ - title: "Kovan Testnet", - url: "https://blockscout.com/eth/kovan", - test_net?: true - }, - %{ - title: "Ropsten Testnet", - url: "https://blockscout.com/eth/ropsten", - test_net?: true - }, - %{ - title: "Goerli Testnet", - url: "https://blockscout.com/eth/goerli", - test_net?: true - }, - %{ - title: "Rinkeby Testnet", - url: "https://blockscout.com/eth/rinkeby", - test_net?: true - }, - %{ - title: "Ethereum Classic", - url: "https://blockscout.com/etc/mainnet", - other?: true - }, - %{ - title: "Aerum Mainnet", - url: "https://blockscout.com/aerum/mainnet", - other?: true - }, - %{ - title: "Callisto Mainnet", - url: "https://blockscout.com/callisto/mainnet", - other?: true - }, - %{ - title: "RSK Mainnet", - url: "https://blockscout.com/rsk/mainnet", - other?: true - } - ] + other_networks: System.get_env("SUPPORTED_CHAINS") config :block_scout_web, BlockScoutWeb.Counters.BlocksIndexedCounter, enabled: true diff --git a/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex b/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex index c4e17bc2f1..92c39f7b84 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex @@ -96,7 +96,11 @@ defmodule BlockScoutWeb.LayoutView do def other_networks do :block_scout_web - |> Application.get_env(:other_networks, []) + |> Application.get_env(:other_networks) + |> Poison.decode!() + |> Enum.map(fn chain -> + chain = for {key, val} <- chain, into: %{}, do: {String.to_atom(key), val} + end) |> Enum.reject(fn %{title: title} -> title == subnetwork_title() end) From 3c4d63149c4816a6ddc1b285a2a04f7670340aef Mon Sep 17 00:00:00 2001 From: saneery Date: Tue, 7 May 2019 13:06:44 +0300 Subject: [PATCH 045/191] mark pools as deleted if they don't exist in the list --- .../chain/import/runner/staking_pools.ex | 29 +++++++++++++++++++ .../lib/indexer/fetcher/staking_pools.ex | 1 + 2 files changed, 30 insertions(+) diff --git a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex index aaf5d7242e..f0e62b7e89 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/staking_pools.ex @@ -41,6 +41,9 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do |> Map.put(:timestamps, timestamps) multi + |> Multi.run(:mark_as_deleted, fn repo, _ -> + mark_as_deleted(repo, changes_list, insert_options) + end) |> Multi.run(:insert_staking_pools, fn repo, _ -> insert(repo, changes_list, insert_options) end) @@ -49,6 +52,32 @@ defmodule Explorer.Chain.Import.Runner.StakingPools do @impl Import.Runner def timeout, do: @timeout + defp mark_as_deleted(repo, changes_list, %{timeout: timeout}) when is_list(changes_list) do + addresses = Enum.map(changes_list, & &1.address_hash) + + query = + from( + address_name in Address.Name, + where: + address_name.address_hash not in ^addresses and + fragment("(metadata->>'is_pool')::boolean = true"), + update: [ + set: [ + metadata: fragment("metadata || '{\"deleted\": true}'::jsonb") + ] + ] + ) + + try do + {_, result} = repo.update_all(query, [], timeout: timeout) + + {:ok, result} + rescue + postgrex_error in Postgrex.Error -> + {:error, %{exception: postgrex_error}} + end + end + @spec insert(Repo.t(), [map()], %{ optional(:on_conflict) => Import.Runner.on_conflict(), required(:timeout) => timeout, diff --git a/apps/indexer/lib/indexer/fetcher/staking_pools.ex b/apps/indexer/lib/indexer/fetcher/staking_pools.ex index 68794d9ee4..fe4ab84c28 100644 --- a/apps/indexer/lib/indexer/fetcher/staking_pools.ex +++ b/apps/indexer/lib/indexer/fetcher/staking_pools.ex @@ -125,6 +125,7 @@ defmodule Indexer.Fetcher.StakingPools do pool |> Map.delete(:staking_address) |> Map.put(:mining_address, mining_address) + |> Map.put(:is_pool, true) %{ name: "anonymous", From 3705ba2d1e1b6e4acd9384206c60fdcc9c12d6a2 Mon Sep 17 00:00:00 2001 From: saneery Date: Tue, 7 May 2019 13:09:44 +0300 Subject: [PATCH 046/191] get pool's stake amount that been made by the pool --- .../lib/explorer/staking/pools_reader.ex | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/pools_reader.ex b/apps/explorer/lib/explorer/staking/pools_reader.ex index de03ff10b5..e3bb27084f 100644 --- a/apps/explorer/lib/explorer/staking/pools_reader.ex +++ b/apps/explorer/lib/explorer/staking/pools_reader.ex @@ -29,6 +29,7 @@ defmodule Explorer.Staking.PoolsReader do {:ok, [delegator_addresses]} <- data["poolDelegators"], delegators_count = Enum.count(delegator_addresses), {:ok, [staked_amount]} <- data["stakeAmountTotalMinusOrderedWithdraw"], + {:ok, [self_staked_amount]} <- data["stakeAmountMinusOrderedWithdraw"], {:ok, [is_validator]} <- data["isValidator"], {:ok, [was_validator_count]} <- data["validatorCounter"], {:ok, [is_banned]} <- data["isValidatorBanned"], @@ -42,6 +43,7 @@ defmodule Explorer.Staking.PoolsReader do is_active: is_active, delegators_count: delegators_count, staked_amount: staked_amount, + self_staked_amount: self_staked_amount, is_validator: is_validator, was_validator_count: was_validator_count, is_banned: is_banned, @@ -77,14 +79,15 @@ defmodule Explorer.Staking.PoolsReader do contract_abi = abi("staking.json") ++ abi("validators.json") methods = [ - {:staking, "isPoolActive", staking_address}, - {:staking, "poolDelegators", staking_address}, - {:staking, "stakeAmountTotalMinusOrderedWithdraw", staking_address}, - {:validators, "isValidator", mining_address}, - {:validators, "validatorCounter", mining_address}, - {:validators, "isValidatorBanned", mining_address}, - {:validators, "bannedUntil", mining_address}, - {:validators, "banCounter", mining_address} + {:staking, "isPoolActive", [staking_address]}, + {:staking, "poolDelegators", [staking_address]}, + {:staking, "stakeAmountTotalMinusOrderedWithdraw", [staking_address]}, + {:staking, "stakeAmountMinusOrderedWithdraw", [staking_address, staking_address]}, + {:validators, "isValidator", [mining_address]}, + {:validators, "validatorCounter", [mining_address]}, + {:validators, "isValidatorBanned", [mining_address]}, + {:validators, "bannedUntil", [mining_address]}, + {:validators, "banCounter", [mining_address]}, ] methods @@ -96,11 +99,11 @@ defmodule Explorer.Staking.PoolsReader do end) end - defp format_request({contract_name, function_name, param}) do + defp format_request({contract_name, function_name, params}) do %{ contract_address: contract(contract_name), function_name: function_name, - args: [param] + args: params } end From ff1fb1ffd107b2b282ddc9b210d89f279eccf603 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Tue, 7 May 2019 13:15:27 +0300 Subject: [PATCH 047/191] Add CHANGELOG entry --- CHANGELOG.md | 1 + apps/block_scout_web/lib/block_scout_web/views/layout_view.ex | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f2c2605a4..920d3e4c7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - [#1814](https://github.com/poanetwork/blockscout/pull/1814) - Clear build artefacts script - [#1837](https://github.com/poanetwork/blockscout/pull/1837) - Add -f flag to clear_build.sh script delete static folder +- [#1900](https://github.com/poanetwork/blockscout/pull/1900) - SUPPORTED_CHAINS ENV var ## 1.3.10-beta diff --git a/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex b/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex index 92c39f7b84..39a4d8c90b 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex @@ -98,8 +98,8 @@ defmodule BlockScoutWeb.LayoutView do :block_scout_web |> Application.get_env(:other_networks) |> Poison.decode!() - |> Enum.map(fn chain -> - chain = for {key, val} <- chain, into: %{}, do: {String.to_atom(key), val} + |> Enum.map(fn chain -> + for {key, val} <- chain, into: %{}, do: {String.to_atom(key), val} end) |> Enum.reject(fn %{title: title} -> title == subnetwork_title() From 201158ca03ad9c4511a2eec39496bdec47267bbc Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Tue, 7 May 2019 14:49:57 +0300 Subject: [PATCH 048/191] Rsk theme scss file --- .../assets/css/theme/_rsk_variables.scss | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 apps/block_scout_web/assets/css/theme/_rsk_variables.scss diff --git a/apps/block_scout_web/assets/css/theme/_rsk_variables.scss b/apps/block_scout_web/assets/css/theme/_rsk_variables.scss new file mode 100644 index 0000000000..c357f0f571 --- /dev/null +++ b/apps/block_scout_web/assets/css/theme/_rsk_variables.scss @@ -0,0 +1,50 @@ +// general +$primary: #101f25; +$secondary: #27ac8d; +$tertiary: #e39a54; +$additional-font: #a1ded1; + +// footer +$footer-background-color: $primary; +$footer-title-color: #fff; +$footer-text-color: $additional-font; +$footer-item-disc-color: $secondary; +.footer-logo { filter: brightness(0) invert(1); } + +// dashboard +$dashboard-line-color-price: $tertiary; // price left border + +$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels + +$dashboard-stats-item-value-color: $additional-font; // stat values + +$dashboard-stats-item-border-color: $secondary; // stat border + +$dashboard-banner-gradient-start: $primary; // gradient begin + +$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end + +$dashboard-banner-network-plain-container-background-color: #1a323b; // stats bg + + +// navigation +.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow +$header-icon-border-color-hover: $secondary; // top border on hover +$header-icon-color-hover: $secondary; // nav icon on hover +.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover + +// buttons +$btn-line-bg: #fff; // button bg +$btn-line-color: $secondary; // button border and font color && hover bg color +$btn-copy-color: $secondary; // btn copy +$btn-qr-color: $secondary; // btn qr-code + +//links & tile +.tile a { color: $secondary !important; } // links color for badges +.tile-type-block { + border-left: 4px solid $secondary; +} // tab active bg + +// card +$card-background-1: $secondary; +$card-tab-active: $secondary; \ No newline at end of file From 7da2f26d3b020058aea5b47efa467f8791b02c4a Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Tue, 7 May 2019 14:50:58 +0300 Subject: [PATCH 049/191] Rsk logo --- .../assets/static/images/rsk_logo.svg | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 apps/block_scout_web/assets/static/images/rsk_logo.svg diff --git a/apps/block_scout_web/assets/static/images/rsk_logo.svg b/apps/block_scout_web/assets/static/images/rsk_logo.svg new file mode 100644 index 0000000000..8502c921e5 --- /dev/null +++ b/apps/block_scout_web/assets/static/images/rsk_logo.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 2c3a549577f392ba34fdbc088b4c64d4976f2307 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Tue, 7 May 2019 14:54:20 +0300 Subject: [PATCH 050/191] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f2c2605a4..58ad50f180 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## Current ### Features - +- [#1903](https://github.com/poanetwork/blockscout/pull/1874) - added rsk theme and rsk logo - [#1895](https://github.com/poanetwork/blockscout/pull/1874) - add changes to poa theme and poa logo - [#1812](https://github.com/poanetwork/blockscout/pull/1812) - add pagination to addresses page - [#1874](https://github.com/poanetwork/blockscout/pull/1874) - add changes to ethereum theme and ethereum logo From d6e6601365a6c35734275e0088f8f51db103b53b Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Tue, 7 May 2019 14:56:14 +0300 Subject: [PATCH 051/191] Update CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58ad50f180..708ab60e5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ ## Current ### Features -- [#1903](https://github.com/poanetwork/blockscout/pull/1874) - added rsk theme and rsk logo -- [#1895](https://github.com/poanetwork/blockscout/pull/1874) - add changes to poa theme and poa logo +- [#1903](https://github.com/poanetwork/blockscout/pull/1903) - added rsk theme and rsk logo +- [#1895](https://github.com/poanetwork/blockscout/pull/1895) - add changes to poa theme and poa logo - [#1812](https://github.com/poanetwork/blockscout/pull/1812) - add pagination to addresses page - [#1874](https://github.com/poanetwork/blockscout/pull/1874) - add changes to ethereum theme and ethereum logo - [#1815](https://github.com/poanetwork/blockscout/pull/1815) - able to search without prefix "0x" From be1623b07eef672132e5e949e07ea4ee71348a43 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 7 May 2019 14:56:43 +0300 Subject: [PATCH 052/191] fix System.get_env("BLOCK_COUNT_CACHE_TTL") type --- apps/explorer/config/config.exs | 3 ++- apps/explorer/lib/explorer/chain/block_count_cache.ex | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index ace69884ea..f40e10371b 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -82,7 +82,8 @@ config :spandex_ecto, SpandexEcto.EctoLogger, tracer: Explorer.Tracer, otp_app: :explorer -config :explorer, Explorer.Chain.BlockCountCache, ttl: System.get_env("BLOCK_COUNT_CACHE_TTL") +config :explorer, Explorer.Chain.BlockCountCache, + ttl: System.get_env("BLOCK_COUNT_CACHE_TTL") && String.to_integer(System.get_env("BLOCK_COUNT_CACHE_TTL")) # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. diff --git a/apps/explorer/lib/explorer/chain/block_count_cache.ex b/apps/explorer/lib/explorer/chain/block_count_cache.ex index 7c900bfedd..84f016dd44 100644 --- a/apps/explorer/lib/explorer/chain/block_count_cache.ex +++ b/apps/explorer/lib/explorer/chain/block_count_cache.ex @@ -6,8 +6,8 @@ defmodule Explorer.Chain.BlockCountCache do alias Explorer.Chain @tab :block_count_cache - # 1 minutes - @cache_period 1_000 * 60 + # 10 minutes + @cache_period 1_000 * 60 * 10 @key "count" @opts_key "opts" From b72cdaecdfbab39aa20b9c570e9d9c47f81845eb Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 7 May 2019 14:59:08 +0300 Subject: [PATCH 053/191] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ef0fe2319..2bb5799000 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ - [#1885](https://github.com/poanetwork/blockscout/pull/1885) - highlight reserved words in decompiled code - [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete - [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance +- [#1904](https://github.com/poanetwork/blockscout/pull/1904) - fix `BLOCK_COUNT_CACHE_TTL` env var type ### Chore From 624cb0057d38aa7acf418e3fe88e4e11c1da3169 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 7 May 2019 15:29:57 +0300 Subject: [PATCH 054/191] fix reorgs, uncles pagination --- .../controllers/block_controller.ex | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/block_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/block_controller.ex index b2f6a89a68..9fa211d870 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/block_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/block_controller.ex @@ -8,14 +8,24 @@ defmodule BlockScoutWeb.BlockController do alias Phoenix.View def index(conn, params) do - [ - necessity_by_association: %{ - :transactions => :optional, - [miner: :names] => :optional, - :rewards => :optional - } - ] - |> handle_render(conn, params) + case params["block_type"] do + "Uncle" -> + uncle(conn, params) + + "Reorg" -> + reorg(conn, params) + + _ -> + [ + necessity_by_association: %{ + :transactions => :optional, + [miner: :names] => :optional, + :rewards => :optional + }, + block_type: "Block" + ] + |> handle_render(conn, params) + end end def show(conn, %{"hash_or_number" => hash_or_number}) do @@ -64,7 +74,7 @@ defmodule BlockScoutWeb.BlockController do block_path( conn, :index, - Map.delete(next_page_params, "type") + next_page_params ) end From e1684ee265eea0ae38a26d97c66bddefe38526dd Mon Sep 17 00:00:00 2001 From: Michael Ira Krufky Date: Tue, 7 May 2019 12:57:23 -0400 Subject: [PATCH 055/191] README.md: add blocks.ether1.wattpool.net for Ether-1 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 289a3d35ed..9755475dbe 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ Currently available block explorers (i.e. Etherscan and Etherchain) are closed s * [SpringChain](https://explorer.springrole.com/) * [PIRL](http://pirl.es/) * [Petrichor](https://explorer.petrichor-dev.com/) +* [Ether-1](https://blocks.ether1.wattpool.net/) ### Visual Interface From 76fdd30fcaf7a902242cc16a7257e36d8e28b535 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Tue, 7 May 2019 20:52:29 +0300 Subject: [PATCH 056/191] Update _lukso_variables.scss --- apps/block_scout_web/assets/css/theme/_lukso_variables.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/block_scout_web/assets/css/theme/_lukso_variables.scss b/apps/block_scout_web/assets/css/theme/_lukso_variables.scss index a09049e7c8..c1d8d630f9 100644 --- a/apps/block_scout_web/assets/css/theme/_lukso_variables.scss +++ b/apps/block_scout_web/assets/css/theme/_lukso_variables.scss @@ -12,7 +12,7 @@ $dashboard-stats-item-value-color: $primary; $dashboard-stats-item-border-color: $primary; $header-links-color-active: #333; - +.dropdown-item:hover, .dropdown-item:focus { background-color: $primary !important; } $tile-type-block-color: $secondary; $navbar-logo-height: 18px; From 630cce349a5375a57de1b3566bc6180100a347e5 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Tue, 7 May 2019 20:53:02 +0300 Subject: [PATCH 057/191] Update _tooltip.scss --- apps/block_scout_web/assets/css/components/_tooltip.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/block_scout_web/assets/css/components/_tooltip.scss b/apps/block_scout_web/assets/css/components/_tooltip.scss index 1cd7797785..9a1027b782 100644 --- a/apps/block_scout_web/assets/css/components/_tooltip.scss +++ b/apps/block_scout_web/assets/css/components/_tooltip.scss @@ -13,6 +13,7 @@ $tooltip-color: #fff !default; } .arrow::before { - border-top-color: $tooltip-background-color; + border-top-color: $tooltip-background-color !important; + border-bottom-color: $tooltip-background-color !important; } } From 0135f09b45a8522134b128ecc975eb442575cbab Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Tue, 7 May 2019 20:54:42 +0300 Subject: [PATCH 058/191] Update _tooltip.scss --- apps/block_scout_web/assets/css/components/_tooltip.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/block_scout_web/assets/css/components/_tooltip.scss b/apps/block_scout_web/assets/css/components/_tooltip.scss index 9a1027b782..4c845a7c1c 100644 --- a/apps/block_scout_web/assets/css/components/_tooltip.scss +++ b/apps/block_scout_web/assets/css/components/_tooltip.scss @@ -13,7 +13,7 @@ $tooltip-color: #fff !default; } .arrow::before { - border-top-color: $tooltip-background-color !important; - border-bottom-color: $tooltip-background-color !important; + border-top-color: $tooltip-background-color; + border-bottom-color: $tooltip-background-color; } } From 417027b80ffba3bd3d7fdceba216347e7bda85cf Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Tue, 7 May 2019 20:57:12 +0300 Subject: [PATCH 059/191] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 708ab60e5b..9301cff144 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Current ### Features +- [#1907](https://github.com/poanetwork/blockscout/pull/1907) - dropdown color bug fix (lukso theme) and tooltip color bug fix - [#1903](https://github.com/poanetwork/blockscout/pull/1903) - added rsk theme and rsk logo - [#1895](https://github.com/poanetwork/blockscout/pull/1895) - add changes to poa theme and poa logo - [#1812](https://github.com/poanetwork/blockscout/pull/1812) - add pagination to addresses page From e08b9f7ecc2cff2d6b9f97d6f8e4ba327f8232ab Mon Sep 17 00:00:00 2001 From: zachdaniel Date: Wed, 1 May 2019 10:33:09 -0400 Subject: [PATCH 060/191] fix: resolve false positive constructor arguments --- CHANGELOG.md | 1 + .../smart_contract/solidity/code_compiler.ex | 6 ++++ .../lib/explorer/smart_contract/verifier.ex | 31 ++++++++++++++----- .../explorer/smart_contract/verifier_test.exs | 18 ++++++++++- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed4b8db4d5..ca08e35fee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - [#1885](https://github.com/poanetwork/blockscout/pull/1885) - highlight reserved words in decompiled code - [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete - [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance +- [#1875](https://github.com/poanetwork/blockscout/pull/1875) - fix: resolve false positive constructor arguments ### Chore diff --git a/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex b/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex index 72c5bae186..3ded8ba9f1 100644 --- a/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex +++ b/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex @@ -63,6 +63,7 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do } } """ + @spec run(Keyword.t()) :: {:ok, map} | {:error, :compilation | :name} def run(params) do name = Keyword.fetch!(params, :name) compiler_version = Keyword.fetch!(params, :compiler_version) @@ -108,9 +109,14 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do {:error, %Jason.DecodeError{}} -> {:error, :compilation} + {:error, reason} when reason in [:name, :compilation] -> + {:error, reason} + error -> parse_error(error) end + else + {:error, :compilation} end end diff --git a/apps/explorer/lib/explorer/smart_contract/verifier.ex b/apps/explorer/lib/explorer/smart_contract/verifier.ex index 0fc9f6b21b..746ba610aa 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier.ex @@ -86,17 +86,32 @@ defmodule Explorer.SmartContract.Verifier do In order to discover the bytecode we need to remove the `swarm source` from the hash. - `64` characters to the left of `0029` are the `swarm source`. The rest on - the left is the `bytecode` to be validated. + For more information on the swarm hash, check out: + https://solidity.readthedocs.io/en/v0.5.3/metadata.html#encoding-of-the-metadata-hash-in-the-bytecode """ + def extract_bytecode("0x" <> code) do + "0x" <> extract_bytecode(code) + end + def extract_bytecode(code) do - {bytecode, _swarm_source} = - code - |> String.split("0029") - |> List.first() - |> String.split_at(-64) + do_extract_bytecode([], String.downcase(code)) + end - bytecode + defp do_extract_bytecode(extracted, remaining) do + case remaining do + <<>> -> + extracted + |> Enum.reverse() + |> :binary.list_to_bin() + + "a165627a7a72305820" <> <<_::binary-size(64)>> <> "0029" <> _constructor_arguments -> + extracted + |> Enum.reverse() + |> :binary.list_to_bin() + + <> <> rest -> + do_extract_bytecode([next | extracted], rest) + end end def next_evm_version(current_evm_version) do diff --git a/apps/explorer/test/explorer/smart_contract/verifier_test.exs b/apps/explorer/test/explorer/smart_contract/verifier_test.exs index 631c15695e..6786e559df 100644 --- a/apps/explorer/test/explorer/smart_contract/verifier_test.exs +++ b/apps/explorer/test/explorer/smart_contract/verifier_test.exs @@ -181,7 +181,7 @@ defmodule Explorer.SmartContract.VerifierTest do swarm_source = "3c381c1b48b38d050c54d7ef296ecd411040e19420dfec94772b9c49ae106a0b" bytecode = - "0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a72305820" + "0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600" assert bytecode == Verifier.extract_bytecode(code) assert bytecode != code @@ -189,5 +189,21 @@ defmodule Explorer.SmartContract.VerifierTest do assert String.contains?(bytecode, "0029") == false assert String.contains?(bytecode, swarm_source) == false end + + test "extracts everything to the left of the swarm hash" do + code = + "0x608060405234801561001057600080fd5b5060df80610010029f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a723058203c381c1b48b38d050c54d7ef296ecd411040e19420dfec94772b9c49ae106a0b0029" + + swarm_source = "3c381c1b48b38d050c54d7ef296ecd411040e19420dfec94772b9c49ae106a0b" + + bytecode = + "0x608060405234801561001057600080fd5b5060df80610010029f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600" + + assert bytecode == Verifier.extract_bytecode(code) + assert bytecode != code + assert String.contains?(code, bytecode) == true + assert String.contains?(bytecode, "0029") == true + assert String.contains?(bytecode, swarm_source) == false + end end end From c3a5218ff5579aa97863ea2d58a632e64085063a Mon Sep 17 00:00:00 2001 From: zachdaniel Date: Tue, 7 May 2019 12:41:49 -0400 Subject: [PATCH 061/191] fix: split constructor args for verification --- .../smart_contract/solidity/code_compiler.ex | 18 ++++++++++--- .../verifier/constructor_arguments.ex | 25 ++++++++++--------- apps/explorer/priv/compile_solc.js | 4 +-- .../verifier/constructor_arguments_test.exs | 14 ++++++----- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex b/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex index 3ded8ba9f1..656f1b9734 100644 --- a/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex +++ b/apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex @@ -5,6 +5,8 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do alias Explorer.SmartContract.SolcDownloader + require Logger + @new_contract_name "New.sol" @allowed_evm_versions ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg"] @@ -101,7 +103,8 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do ] ) - with {:ok, contracts} <- Jason.decode(response), + with {:ok, decoded} <- Jason.decode(response), + {:ok, contracts} <- get_contracts(decoded), %{"abi" => abi, "evm" => %{"deployedBytecode" => %{"object" => bytecode}}} <- get_contract_info(contracts, name) do {:ok, %{"abi" => abi, "bytecode" => bytecode, "name" => name}} @@ -113,7 +116,9 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do {:error, reason} error -> - parse_error(error) + error = parse_error(error) + Logger.warn(["There was an error compiling a provided contract: ", inspect(error)]) + {:error, :compilation} end else {:error, :compilation} @@ -139,10 +144,15 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do end end - def parse_error(%{"error" => error}), do: {:error, [error]} - def parse_error(%{"errors" => errors}), do: {:error, errors} + def parse_error({:error, %{"error" => error}}), do: {:error, [error]} + def parse_error({:error, %{"errors" => errors}}), do: {:error, errors} def parse_error({:error, _} = error), do: error + # Older solc-bin versions don't use filename as contract key + defp get_contracts(%{"contracts" => %{"New.sol" => contracts}}), do: {:ok, contracts} + defp get_contracts(%{"contracts" => %{"" => contracts}}), do: {:ok, contracts} + defp get_contracts(response), do: {:error, response} + defp optimize_value(false), do: "0" defp optimize_value("false"), do: "0" diff --git a/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex b/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex index b60bd01927..aa32d85bb6 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex @@ -7,20 +7,21 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do def verify(address_hash, arguments_data) do arguments_data = String.replace(arguments_data, "0x", "") - creation_input_data = Chain.contract_creation_input_data(address_hash) - data_with_swarm = - creation_input_data - |> String.split("0029") - |> List.first() - |> Kernel.<>("0029") + address_hash + |> Chain.contract_creation_input_data() + |> String.replace("0x", "") + |> extract_constructor_arguments() + |> Kernel.==(arguments_data) + end + + defp extract_constructor_arguments(<<>>), do: "" - expected_arguments_data = - creation_input_data - |> String.split(data_with_swarm) - |> List.last() - |> String.replace("0x", "") + defp extract_constructor_arguments("a165627a7a72305820" <> <<_::binary-size(64)>> <> "0029" <> constructor_arguments) do + constructor_arguments + end - expected_arguments_data == arguments_data + defp extract_constructor_arguments(<<_::binary-size(2)>> <> rest) do + extract_constructor_arguments(rest) end end diff --git a/apps/explorer/priv/compile_solc.js b/apps/explorer/priv/compile_solc.js index 5aaf3f54d7..eea727802e 100755 --- a/apps/explorer/priv/compile_solc.js +++ b/apps/explorer/priv/compile_solc.js @@ -39,6 +39,4 @@ const input = { const output = JSON.parse(solc.compile(JSON.stringify(input))) -/** Older solc-bin versions don't use filename as contract key */ -const response = output.contracts[newContractName] || output.contracts[''] -console.log(JSON.stringify(response)); +console.log(JSON.stringify(output)); diff --git a/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs b/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs index 9fe219719d..a5e019c86f 100644 --- a/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs +++ b/apps/explorer/test/explorer/smart_contract/verifier/constructor_arguments_test.exs @@ -7,17 +7,19 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArgumentsTest do alias Explorer.SmartContract.Verifier.ConstructorArguments test "veriies constructor constructor arguments with whisper data" do - constructor_arguments = "0x0405" + constructor_arguments = Base.encode16(:crypto.strong_rand_bytes(64), case: :lower) address = insert(:address) - input = %Data{ - bytes: - <<1, 2, 3, 93, 148, 60, 87, 91, 232, 162, 174, 226, 187, 119, 55, 167, 101, 253, 210, 198, 228, 155, 116, 205, - 44, 146, 171, 15, 168, 228, 40, 45, 26, 117, 174, 0, 41, 4, 5>> + input = + "a165627a7a72305820" <> + Base.encode16(:crypto.strong_rand_bytes(32), case: :lower) <> "0029" <> constructor_arguments + + input_data = %Data{ + bytes: Base.decode16!(input, case: :lower) } :transaction - |> insert(created_contract_address_hash: address.hash, input: input) + |> insert(created_contract_address_hash: address.hash, input: input_data) |> with_block() assert ConstructorArguments.verify(address.hash, constructor_arguments) From 809c396c6b70c921229e19e5d139036f6c1869b6 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Tue, 7 May 2019 23:30:15 +0300 Subject: [PATCH 062/191] Default value for supported chains --- .../lib/block_scout_web/views/layout_view.ex | 76 +++++++++++++++++-- 1 file changed, 70 insertions(+), 6 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex b/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex index 39a4d8c90b..4d9b4297d1 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/layout_view.ex @@ -4,6 +4,65 @@ defmodule BlockScoutWeb.LayoutView do alias Plug.Conn @issue_url "https://github.com/poanetwork/blockscout/issues/new" + @default_other_networks [ + %{ + title: "POA Core", + url: "https://blockscout.com/poa/core" + }, + %{ + title: "POA Sokol", + url: "https://blockscout.com/poa/sokol", + test_net?: true + }, + %{ + title: "xDai Chain", + url: "https://blockscout.com/poa/dai" + }, + %{ + title: "Ethereum Mainnet", + url: "https://blockscout.com/eth/mainnet" + }, + %{ + title: "Kovan Testnet", + url: "https://blockscout.com/eth/kovan", + test_net?: true + }, + %{ + title: "Ropsten Testnet", + url: "https://blockscout.com/eth/ropsten", + test_net?: true + }, + %{ + title: "Goerli Testnet", + url: "https://blockscout.com/eth/goerli", + test_net?: true + }, + %{ + title: "Rinkeby Testnet", + url: "https://blockscout.com/eth/rinkeby", + test_net?: true + }, + %{ + title: "Ethereum Classic", + url: "https://blockscout.com/etc/mainnet", + other?: true + }, + %{ + title: "Aerum Mainnet", + url: "https://blockscout.com/aerum/mainnet", + other?: true + }, + %{ + title: "Callisto Mainnet", + url: "https://blockscout.com/callisto/mainnet", + other?: true + }, + %{ + title: "RSK Mainnet", + url: "https://blockscout.com/rsk/mainnet", + other?: true + } + ] alias BlockScoutWeb.SocialMedia @@ -95,12 +154,17 @@ defmodule BlockScoutWeb.LayoutView do def ignore_version?(_), do: false def other_networks do - :block_scout_web - |> Application.get_env(:other_networks) - |> Poison.decode!() - |> Enum.map(fn chain -> - for {key, val} <- chain, into: %{}, do: {String.to_atom(key), val} - end) + if Application.get_env(:block_scout_web, :other_networks) do + :block_scout_web + |> Application.get_env(:other_networks) + |> Poison.decode!() + |> Kernel.||(@default_other_networks) + |> Enum.map(fn chain -> + for {key, val} <- chain, into: %{}, do: {String.to_atom(key), val} + end) + else + @default_other_networks + end |> Enum.reject(fn %{title: title} -> title == subnetwork_title() end) From 2164c286e201b60050c70f50e3591fc4d7f90eac Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 8 May 2019 00:39:01 +0300 Subject: [PATCH 063/191] hide_in_dropdown flag for networks --- .../templates/layout/_footer.html.eex | 4 +- .../templates/layout/_topnav.html.eex | 6 +-- .../lib/block_scout_web/views/layout_view.ex | 49 +++++++++++-------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex index 09b5aabf05..b03b9f964f 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_footer.html.eex @@ -37,7 +37,7 @@
  • <%= gettext("Support") %>
  • - <% main_nets = main_nets() %> + <% main_nets = main_nets(other_networks()) %> <%= unless Enum.empty?(main_nets) do %> <% end %> - <% test_nets = test_nets() %> + <% test_nets = test_nets(other_networks()) %> <%= unless Enum.empty?(test_nets) do %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex index 7d85d33c90..272942fea0 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/block/overview.html.eex @@ -20,8 +20,10 @@ <%= gettext "%{count} Transactions", count: @block_transaction_count %> + <%= if @block.size do %> - <%= Cldr.Unit.new(:byte, @block.size) |> cldr_unit_to_string!() %> + <%= Cldr.Unit.new(:byte, @block.size) |> cldr_unit_to_string!() %> + <% end %> diff --git a/apps/block_scout_web/test/block_scout_web/controllers/block_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/block_controller_test.exs index 93352e96a8..3145ce1273 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/block_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/block_controller_test.exs @@ -91,7 +91,8 @@ defmodule BlockScoutWeb.BlockControllerTest do expected_path = block_path(conn, :index, %{ - block_number: number + block_number: number, + block_type: "Block" }) assert Map.get(json_response(conn, 200), "next_page_path") == expected_path From 9b50fb82c76cec5552904f67ad268d2dad897599 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 8 May 2019 11:24:17 +0300 Subject: [PATCH 068/191] fix gettext --- apps/block_scout_web/priv/gettext/default.pot | 34 +++++++++---------- .../priv/gettext/en/LC_MESSAGES/default.po | 34 +++++++++---------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 6f198f8793..ad82cb33d4 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -353,7 +353,7 @@ msgid "Details" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:56 +#: lib/block_scout_web/templates/block/overview.html.eex:58 msgid "Difficulty" msgstr "" @@ -427,16 +427,16 @@ msgid "GET" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/_tile.html.eex:54 -#: lib/block_scout_web/templates/block/overview.html.eex:103 -#: lib/block_scout_web/templates/block/overview.html.eex:150 +#: lib/block_scout_web/templates/block/_tile.html.eex:56 +#: lib/block_scout_web/templates/block/overview.html.eex:105 +#: lib/block_scout_web/templates/block/overview.html.eex:152 msgid "Gas Limit" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/_tile.html.eex:59 -#: lib/block_scout_web/templates/block/overview.html.eex:96 -#: lib/block_scout_web/templates/block/overview.html.eex:144 +#: lib/block_scout_web/templates/block/_tile.html.eex:61 +#: lib/block_scout_web/templates/block/overview.html.eex:98 +#: lib/block_scout_web/templates/block/overview.html.eex:146 msgid "Gas Used" msgstr "" @@ -452,7 +452,7 @@ msgid "Gwei" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:36 +#: lib/block_scout_web/templates/block/overview.html.eex:38 msgid "Hash" msgstr "" @@ -524,8 +524,8 @@ msgid "Max of" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/_tile.html.eex:36 -#: lib/block_scout_web/templates/block/overview.html.eex:119 +#: lib/block_scout_web/templates/block/_tile.html.eex:38 +#: lib/block_scout_web/templates/block/overview.html.eex:121 #: lib/block_scout_web/templates/chain/_block.html.eex:15 msgid "Miner" msgstr "" @@ -594,7 +594,7 @@ msgid "No" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:71 +#: lib/block_scout_web/templates/block/overview.html.eex:73 #: lib/block_scout_web/templates/transaction/overview.html.eex:77 msgid "Nonce" msgstr "" @@ -641,7 +641,7 @@ msgid "Parameters" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:43 +#: lib/block_scout_web/templates/block/overview.html.eex:45 msgid "Parent Hash" msgstr "" @@ -659,7 +659,7 @@ msgid "Pending Transactions" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:82 +#: lib/block_scout_web/templates/block/overview.html.eex:84 msgid "Position %{index}" msgstr "" @@ -891,7 +891,7 @@ msgid "Topics" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:65 +#: lib/block_scout_web/templates/block/overview.html.eex:67 msgid "Total Difficulty" msgstr "" @@ -958,7 +958,7 @@ msgid "Twitter" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:78 +#: lib/block_scout_web/templates/block/overview.html.eex:80 #: lib/block_scout_web/templates/layout/_topnav.html.eex:23 msgid "Uncles" msgstr "" @@ -1103,7 +1103,7 @@ msgid "Delegate Call" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/_tile.html.eex:45 +#: lib/block_scout_web/templates/block/_tile.html.eex:47 #: lib/block_scout_web/templates/chain/_block.html.eex:23 #: lib/block_scout_web/views/internal_transaction_view.ex:27 msgid "Reward" @@ -1432,7 +1432,7 @@ msgid "Validator Info" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:137 +#: lib/block_scout_web/templates/block/overview.html.eex:139 msgid "Block Rewards" 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 64201bee65..02fb552764 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 @@ -353,7 +353,7 @@ msgid "Details" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:56 +#: lib/block_scout_web/templates/block/overview.html.eex:58 msgid "Difficulty" msgstr "" @@ -427,16 +427,16 @@ msgid "GET" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/_tile.html.eex:54 -#: lib/block_scout_web/templates/block/overview.html.eex:103 -#: lib/block_scout_web/templates/block/overview.html.eex:150 +#: lib/block_scout_web/templates/block/_tile.html.eex:56 +#: lib/block_scout_web/templates/block/overview.html.eex:105 +#: lib/block_scout_web/templates/block/overview.html.eex:152 msgid "Gas Limit" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/_tile.html.eex:59 -#: lib/block_scout_web/templates/block/overview.html.eex:96 -#: lib/block_scout_web/templates/block/overview.html.eex:144 +#: lib/block_scout_web/templates/block/_tile.html.eex:61 +#: lib/block_scout_web/templates/block/overview.html.eex:98 +#: lib/block_scout_web/templates/block/overview.html.eex:146 msgid "Gas Used" msgstr "" @@ -452,7 +452,7 @@ msgid "Gwei" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:36 +#: lib/block_scout_web/templates/block/overview.html.eex:38 msgid "Hash" msgstr "" @@ -524,8 +524,8 @@ msgid "Max of" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/_tile.html.eex:36 -#: lib/block_scout_web/templates/block/overview.html.eex:119 +#: lib/block_scout_web/templates/block/_tile.html.eex:38 +#: lib/block_scout_web/templates/block/overview.html.eex:121 #: lib/block_scout_web/templates/chain/_block.html.eex:15 msgid "Miner" msgstr "" @@ -594,7 +594,7 @@ msgid "No" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:71 +#: lib/block_scout_web/templates/block/overview.html.eex:73 #: lib/block_scout_web/templates/transaction/overview.html.eex:77 msgid "Nonce" msgstr "" @@ -641,7 +641,7 @@ msgid "Parameters" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:43 +#: lib/block_scout_web/templates/block/overview.html.eex:45 msgid "Parent Hash" msgstr "" @@ -659,7 +659,7 @@ msgid "Pending Transactions" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:82 +#: lib/block_scout_web/templates/block/overview.html.eex:84 msgid "Position %{index}" msgstr "" @@ -891,7 +891,7 @@ msgid "Topics" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:65 +#: lib/block_scout_web/templates/block/overview.html.eex:67 msgid "Total Difficulty" msgstr "" @@ -958,7 +958,7 @@ msgid "Twitter" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:78 +#: lib/block_scout_web/templates/block/overview.html.eex:80 #: lib/block_scout_web/templates/layout/_topnav.html.eex:23 msgid "Uncles" msgstr "" @@ -1103,7 +1103,7 @@ msgid "Delegate Call" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/_tile.html.eex:45 +#: lib/block_scout_web/templates/block/_tile.html.eex:47 #: lib/block_scout_web/templates/chain/_block.html.eex:23 #: lib/block_scout_web/views/internal_transaction_view.ex:27 msgid "Reward" @@ -1432,7 +1432,7 @@ msgid "Validator Info" msgstr "" #, elixir-format -#: lib/block_scout_web/templates/block/overview.html.eex:137 +#: lib/block_scout_web/templates/block/overview.html.eex:139 msgid "Block Rewards" msgstr "" From 7cb07f3610f9b4a38c972ab7580f4d337a122a7a Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 8 May 2019 11:49:44 +0300 Subject: [PATCH 069/191] remove workers from indexer readme --- apps/indexer/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/indexer/README.md b/apps/indexer/README.md index d0844c57d6..34fb6e6ef3 100644 --- a/apps/indexer/README.md +++ b/apps/indexer/README.md @@ -91,8 +91,6 @@ These workers are created for fetching information, which previously wasn't fetc After all deployed instances get all needed data, these fetchers should be deprecated and removed. - `uncataloged_token_transfers`: extracts token transfers from logs, which previously weren't parsed due to unknown format -- `addresses_without_codes`: forces complete refetch of blocks, which have created contract addresses without contract code -- `failed_created_addresses`: forces refetch of contract code for failed transactions, which previously got incorrectly overwritten - `uncles_without_index`: adds previously unfetched `index` field for unfetched blocks in `block_second_degree_relations` ## Memory Usage @@ -156,4 +154,3 @@ mix test --exclude no_geth |:----------|:--------------------------------------------------| | HTTP | `https://mainnet.infura.io/8lTvJTKmHPCHazkneJsY` | | WebSocket | `wss://mainnet.infura.io/ws/8lTvJTKmHPCHazkneJsY` | - From 7dcc04ebf0d53ce404db9e095e36a0acec608b91 Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 12:40:25 +0300 Subject: [PATCH 070/191] delete custom postgres function --- apps/explorer/lib/explorer/chain.ex | 5 +--- ...2094552_create_estimate_count_function.exs | 24 ------------------- 2 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 apps/explorer/priv/repo/migrations/20190502094552_create_estimate_count_function.exs diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index cb82fd1fac..356517fa30 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1960,10 +1960,7 @@ defmodule Explorer.Chain do cached_value = BlockCountCache.count() if is_nil(cached_value) do - %Postgrex.Result{rows: [[rows]]} = - SQL.query!(Repo, "SELECT count_estimate('SELECT 1 FROM blocks WHERE consensus = true');") - - rows + block_consensus_count() else cached_value end diff --git a/apps/explorer/priv/repo/migrations/20190502094552_create_estimate_count_function.exs b/apps/explorer/priv/repo/migrations/20190502094552_create_estimate_count_function.exs deleted file mode 100644 index 718a2aa3a6..0000000000 --- a/apps/explorer/priv/repo/migrations/20190502094552_create_estimate_count_function.exs +++ /dev/null @@ -1,24 +0,0 @@ -defmodule Explorer.Repo.Migrations.CreateEstimateCountFunction do - use Ecto.Migration - - def up do - execute(""" - CREATE FUNCTION count_estimate(query text) RETURNS integer AS $$ - DECLARE - rec record; - rows integer; - BEGIN - FOR rec IN EXECUTE 'EXPLAIN ' || query LOOP - rows := substring(rec."QUERY PLAN" FROM ' rows=([[:digit:]]+)'); - EXIT WHEN rows IS NOT NULL; - END LOOP; - RETURN rows; - END; - $$ LANGUAGE plpgsql VOLATILE STRICT; - """) - end - - def down do - execute("DROP FUNCTION count_estimate") - end -end From f46730c999e93e5e1bfd8ee305e435e5e1cf13fc Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 12:55:49 +0300 Subject: [PATCH 071/191] format --- apps/explorer/config/config.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index 579d1e07b2..e6eb5c4813 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -81,7 +81,7 @@ config :spandex_ecto, SpandexEcto.EctoLogger, service: :ecto, tracer: Explorer.Tracer, otp_app: :explorer - + # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" From 0d80fd14f58097cd5ae86fe9ed320d134714bf52 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Wed, 8 May 2019 14:06:26 +0300 Subject: [PATCH 072/191] Add files via upload --- .../assets/css/theme/_aerum_variables.scss | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 apps/block_scout_web/assets/css/theme/_aerum_variables.scss diff --git a/apps/block_scout_web/assets/css/theme/_aerum_variables.scss b/apps/block_scout_web/assets/css/theme/_aerum_variables.scss new file mode 100644 index 0000000000..62a7e6d841 --- /dev/null +++ b/apps/block_scout_web/assets/css/theme/_aerum_variables.scss @@ -0,0 +1,50 @@ +// general +$primary: #2b2b2b; +$secondary: #01b9c5; +$tertiary: #00ae83; +$additional-font: #ffffff; + +// footer +$footer-background-color: $primary; +$footer-title-color: #fff; +$footer-text-color: #7e7e7e; +$footer-item-disc-color: $secondary; +.footer-logo { filter: brightness(0) invert(1); } + +// dashboard +$dashboard-line-color-price: $tertiary; // price left border + +$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels + +$dashboard-stats-item-value-color: $additional-font; // stat values + +$dashboard-stats-item-border-color: $tertiary; // stat border + +$dashboard-banner-gradient-start: $primary; // gradient begin + +$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end + +$dashboard-banner-network-plain-container-background-color: #424242; // stats bg + + +// navigation +.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow +$header-icon-border-color-hover: $secondary; // top border on hover +$header-icon-color-hover: $secondary; // nav icon on hover +.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover + +// buttons +$btn-line-bg: #fff; // button bg +$btn-line-color: $tertiary; // button border and font color && hover bg color +$btn-copy-color: $tertiary; // btn copy +$btn-qr-color: $tertiary; // btn qr-code + +//links & tile +.tile a { color: $secondary !important; } // links color for badges +.tile-type-block { + border-left: 4px solid $tertiary; +} // tab active bg + +// card +$card-background-1: $secondary; +$card-tab-active: $secondary; \ No newline at end of file From aeba606fe033a13f3d5f3686e3325fc65ec0b03b Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Wed, 8 May 2019 14:07:03 +0300 Subject: [PATCH 073/191] Add files via upload --- .../assets/static/images/aerum_logo.svg | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 apps/block_scout_web/assets/static/images/aerum_logo.svg diff --git a/apps/block_scout_web/assets/static/images/aerum_logo.svg b/apps/block_scout_web/assets/static/images/aerum_logo.svg new file mode 100644 index 0000000000..62efd365ff --- /dev/null +++ b/apps/block_scout_web/assets/static/images/aerum_logo.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From a76def8c4e5819c92912eb06d26ce2896a5ff848 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Wed, 8 May 2019 14:09:38 +0300 Subject: [PATCH 074/191] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9301cff144..7572ba56b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Current ### Features +- [#1913](https://github.com/poanetwork/blockscout/pull/1913) - added aerum theme and aerum logo - [#1907](https://github.com/poanetwork/blockscout/pull/1907) - dropdown color bug fix (lukso theme) and tooltip color bug fix - [#1903](https://github.com/poanetwork/blockscout/pull/1903) - added rsk theme and rsk logo - [#1895](https://github.com/poanetwork/blockscout/pull/1895) - add changes to poa theme and poa logo From 7c9fe671a4b6451818e6b449c54a0350674a6fb5 Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 14:28:11 +0300 Subject: [PATCH 075/191] fetching staking epoch info --- apps/explorer/config/config.exs | 6 +- apps/explorer/lib/explorer/application.ex | 7 +- .../lib/explorer/staking/epoch_counter.ex | 118 +++ .../priv/contracts_abi/pos/staking.json | 802 ++++++++++-------- 4 files changed, 590 insertions(+), 343 deletions(-) create mode 100644 apps/explorer/lib/explorer/staking/epoch_counter.ex diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index ace69884ea..c1981fcde8 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -58,6 +58,10 @@ config :explorer, Explorer.Staking.PoolsReader, validators_contract_address: System.get_env("POS_VALIDATORS_CONTRACT"), staking_contract_address: System.get_env("POS_STAKING_CONTRACT") +config :explorer, Explorer.Staking.EpochCounter, + enabled: false, + staking_contract_address: System.get_env("POS_STAKING_CONTRACT") + if System.get_env("SUPPLY_MODULE") == "TokenBridge" do config :explorer, supply: Explorer.Chain.Supply.TokenBridge end @@ -82,8 +86,6 @@ config :spandex_ecto, SpandexEcto.EctoLogger, tracer: Explorer.Tracer, otp_app: :explorer -config :explorer, Explorer.Chain.BlockCountCache, ttl: System.get_env("BLOCK_COUNT_CACHE_TTL") - # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index b4f8589a57..d886dd8a0b 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -29,7 +29,8 @@ defmodule Explorer.Application do Explorer.SmartContract.SolcDownloader, {Registry, keys: :duplicate, name: Registry.ChainEvents, id: Registry.ChainEvents}, {Admin.Recovery, [[], [name: Admin.Recovery]]}, - {TransactionCountCache, [[], []]} + {TransactionCountCache, [[], []]}, + {BlockCountCache, []} ] children = base_children ++ configurable_children() @@ -39,7 +40,6 @@ defmodule Explorer.Application do res = Supervisor.start_link(children, opts) BlockNumberCache.setup() - BlockCountCache.setup() res end @@ -51,7 +51,8 @@ defmodule Explorer.Application do configure(Explorer.Market.History.Cataloger), configure(Explorer.Counters.AddressesWithBalanceCounter), configure(Explorer.Counters.AverageBlockTime), - configure(Explorer.Validator.MetadataProcessor) + configure(Explorer.Validator.MetadataProcessor), + configure(Explorer.Staking.EpochCounter) ] |> List.flatten() end diff --git a/apps/explorer/lib/explorer/staking/epoch_counter.ex b/apps/explorer/lib/explorer/staking/epoch_counter.ex new file mode 100644 index 0000000000..256bc6fe0b --- /dev/null +++ b/apps/explorer/lib/explorer/staking/epoch_counter.ex @@ -0,0 +1,118 @@ +defmodule Explorer.Staking.EpochCounter do + @moduledoc """ + Counts staking epoch + """ + + use GenServer + + alias Explorer.Chain.Events.Subscriber + alias Explorer.SmartContract.Reader + + @table_name __MODULE__ + @epoch_key "epoch_num" + @epoch_end_key "epoch_end_block" + + @doc "Current staking epoch number" + def epoch_number do + case :ets.lookup(@table_name, @epoch_key) do + [{_, epoch_num}] -> + epoch_num + + _ -> + 0 + end + end + + @doc "Block number on which will start new epoch" + def epoch_end_block do + case :ets.lookup(@table_name, @epoch_end_key) do + [{_, epoch_end}] -> + epoch_end + + _ -> + 0 + end + end + + def start_link([]) do + GenServer.start_link(__MODULE__, [], name: __MODULE__) + end + + def init([]) do + if :ets.whereis(@table_name) == :undefined do + :ets.new(@table_name, [ + :set, + :named_table, + :public, + write_concurrency: true + ]) + end + + Subscriber.to(:blocks, :realtime) + {:ok, [], {:continue, :epoch_info}} + end + + def handle_continue(:epoch_info, state) do + fetch_epoch_info() + {:noreply, state} + end + + def handle_info({:chain_event, :blocks, :realtime, blocks}, state) do + new_block = Enum.max_by(blocks, &Map.get(&1, :number), fn -> 0 end) + block_number = new_block.number + + case :ets.lookup(@table_name, @epoch_end_key) do + [] -> + fetch_epoch_info() + + [{_, epoch_end_block}] when epoch_end_block < block_number -> + fetch_epoch_info() + + _ -> + :ok + end + + {:noreply, state} + end + + defp fetch_epoch_info do + with data <- get_epoch_info(), + {:ok, [epoch_num]} <- data["stakingEpoch"], + {:ok, [epoch_end_block]} <- data["stakingEpochEndBlock"] do + :ets.insert(@table_name, {@epoch_key, epoch_num}) + :ets.insert(@table_name, {@epoch_end_key, epoch_end_block}) + end + end + + defp get_epoch_info do + contract_abi = abi("staking.json") + + functions = ["stakingEpoch", "stakingEpochEndBlock"] + + functions + |> Enum.map(fn function -> + %{ + contract_address: staking_address(), + function_name: function, + args: [] + } + end) + |> Reader.query_contracts(contract_abi) + |> Enum.zip(functions) + |> Enum.into(%{}, fn {response, function} -> + {function, response} + end) + end + + defp staking_address do + Application.get_env(:explorer, __MODULE__, [])[:staking_contract_address] + end + + # sobelow_skip ["Traversal"] + defp abi(file_name) do + :explorer + |> Application.app_dir("priv/contracts_abi/pos/#{file_name}") + |> File.read!() + |> Jason.decode!() + end +end diff --git a/apps/explorer/priv/contracts_abi/pos/staking.json b/apps/explorer/priv/contracts_abi/pos/staking.json index 7bcbcfb18c..33f773ea61 100644 --- a/apps/explorer/priv/contracts_abi/pos/staking.json +++ b/apps/explorer/priv/contracts_abi/pos/staking.json @@ -1,36 +1,17 @@ [ { "constant": true, - "inputs": [], - "name": "STAKE_UNIT", - "outputs": [ + "inputs": [ { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_DELEGATORS_PER_POOL", - "outputs": [ + "name": "_poolStakingAddress", + "type": "address" + }, { - "name": "", - "type": "uint256" + "name": "_delegator", + "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_CANDIDATES", + "name": "poolDelegatorIndex", "outputs": [ { "name": "", @@ -42,154 +23,55 @@ "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "fromPoolStakingAddress", - "type": "address" - }, - { - "indexed": true, - "name": "staker", - "type": "address" - }, - { - "indexed": true, - "name": "stakingEpoch", - "type": "uint256" - }, - { - "indexed": false, - "name": "amount", - "type": "uint256" - } - ], - "name": "Claimed", - "type": "event" - }, - { - "anonymous": false, + "constant": true, "inputs": [ { - "indexed": true, - "name": "toPoolStakingAddress", - "type": "address" - }, - { - "indexed": true, - "name": "staker", + "name": "_poolStakingAddress", "type": "address" - }, - { - "indexed": true, - "name": "stakingEpoch", - "type": "uint256" - }, - { - "indexed": false, - "name": "amount", - "type": "uint256" } ], - "name": "Staked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "fromPoolStakingAddress", - "type": "address" - }, - { - "indexed": true, - "name": "toPoolStakingAddress", - "type": "address" - }, - { - "indexed": true, - "name": "staker", - "type": "address" - }, - { - "indexed": true, - "name": "stakingEpoch", - "type": "uint256" - }, + "name": "stakeAmountTotalMinusOrderedWithdraw", + "outputs": [ { - "indexed": false, - "name": "amount", + "name": "", "type": "uint256" } ], - "name": "StakeMoved", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, + "constant": false, "inputs": [ { - "indexed": true, - "name": "fromPoolStakingAddress", - "type": "address" - }, - { - "indexed": true, - "name": "staker", + "name": "_erc20TokenContract", "type": "address" - }, - { - "indexed": true, - "name": "stakingEpoch", - "type": "uint256" - }, - { - "indexed": false, - "name": "amount", - "type": "int256" } ], - "name": "WithdrawalOrdered", - "type": "event" + "name": "setErc20TokenContract", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, + "constant": false, "inputs": [ { - "indexed": true, - "name": "fromPoolStakingAddress", + "name": "_fromPoolStakingAddress", "type": "address" }, { - "indexed": true, - "name": "staker", + "name": "_toPoolStakingAddress", "type": "address" }, { - "indexed": true, - "name": "stakingEpoch", - "type": "uint256" - }, - { - "indexed": false, - "name": "amount", + "name": "_amount", "type": "uint256" } ], - "name": "Withdrawn", - "type": "event" - }, - { - "constant": false, - "inputs": [ - { - "name": "_unremovableStakingAddress", - "type": "address" - } - ], - "name": "clearUnremovableValidator", + "name": "moveStake", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -197,8 +79,13 @@ }, { "constant": false, - "inputs": [], - "name": "incrementStakingEpoch", + "inputs": [ + { + "name": "_minStake", + "type": "uint256" + } + ], + "name": "setDelegatorMinStake", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -231,132 +118,75 @@ "constant": false, "inputs": [ { - "name": "_fromPoolStakingAddress", - "type": "address" - }, - { - "name": "_toPoolStakingAddress", - "type": "address" - }, - { - "name": "_amount", + "name": "_minStake", "type": "uint256" } ], - "name": "moveStake", + "name": "setCandidateMinStake", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, + "constant": true, "inputs": [ { - "name": "_toPoolStakingAddress", + "name": "_poolStakingAddress", "type": "address" - }, - { - "name": "_amount", - "type": "uint256" } ], - "name": "stake", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_fromPoolStakingAddress", - "type": "address" - }, + "name": "stakeAmountTotal", + "outputs": [ { - "name": "_amount", + "name": "", "type": "uint256" } ], - "name": "withdraw", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "constant": false, + "constant": true, "inputs": [ { "name": "_poolStakingAddress", "type": "address" }, { - "name": "_amount", - "type": "int256" - } - ], - "name": "orderWithdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_poolStakingAddress", + "name": "_staker", "type": "address" } ], - "name": "claimOrderedWithdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ + "name": "stakeAmountMinusOrderedWithdraw", + "outputs": [ { - "name": "_erc20TokenContract", - "type": "address" + "name": "", + "type": "uint256" } ], - "name": "setErc20TokenContract", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "constant": false, + "constant": true, "inputs": [ { - "name": "_minStake", - "type": "uint256" + "name": "_stakingAddress", + "type": "address" } ], - "name": "setCandidateMinStake", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ + "name": "poolInactiveIndex", + "outputs": [ { - "name": "_minStake", + "name": "", "type": "uint256" } ], - "name": "setDelegatorMinStake", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -375,12 +205,21 @@ }, { "constant": true, - "inputs": [], - "name": "getPoolsInactive", + "inputs": [ + { + "name": "_poolStakingAddress", + "type": "address" + }, + { + "name": "_staker", + "type": "address" + } + ], + "name": "maxWithdrawAllowed", "outputs": [ { "name": "", - "type": "address[]" + "type": "uint256" } ], "payable": false, @@ -389,30 +228,21 @@ }, { "constant": true, - "inputs": [], - "name": "getPoolsLikelihood", - "outputs": [ + "inputs": [ { - "name": "likelihoods", - "type": "int256[]" + "name": "_poolStakingAddress", + "type": "address" }, { - "name": "sum", - "type": "int256" + "name": "_staker", + "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getPoolsToBeElected", + "name": "stakeAmountByCurrentEpoch", "outputs": [ { "name": "", - "type": "address[]" + "type": "uint256" } ], "payable": false, @@ -422,11 +252,11 @@ { "constant": true, "inputs": [], - "name": "getPoolsToBeRemoved", + "name": "stakingEpoch", "outputs": [ { "name": "", - "type": "address[]" + "type": "uint256" } ], "payable": false, @@ -436,11 +266,11 @@ { "constant": true, "inputs": [], - "name": "areStakeAndWithdrawAllowed", + "name": "getDelegatorMinStake", "outputs": [ { "name": "", - "type": "bool" + "type": "uint256" } ], "payable": false, @@ -477,8 +307,17 @@ }, { "constant": true, - "inputs": [], - "name": "getDelegatorMinStake", + "inputs": [ + { + "name": "_poolStakingAddress", + "type": "address" + }, + { + "name": "_staker", + "type": "address" + } + ], + "name": "maxWithdrawOrderAllowed", "outputs": [ { "name": "", @@ -493,15 +332,19 @@ "constant": true, "inputs": [ { - "name": "_stakingAddress", + "name": "_poolStakingAddress", + "type": "address" + }, + { + "name": "_delegator", "type": "address" } ], - "name": "isPoolActive", + "name": "poolDelegatorInactiveIndex", "outputs": [ { "name": "", - "type": "bool" + "type": "uint256" } ], "payable": false, @@ -510,21 +353,49 @@ }, { "constant": true, + "inputs": [], + "name": "getPoolsLikelihood", + "outputs": [ + { + "name": "likelihoods", + "type": "int256[]" + }, + { + "name": "sum", + "type": "int256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, "inputs": [ { - "name": "_poolStakingAddress", + "name": "_unremovableStakingAddress", "type": "address" - }, + } + ], + "name": "clearUnremovableValidator", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ { - "name": "_staker", + "name": "_poolStakingAddress", "type": "address" } ], - "name": "maxWithdrawAllowed", + "name": "poolDelegators", "outputs": [ { "name": "", - "type": "uint256" + "type": "address[]" } ], "payable": false, @@ -543,7 +414,7 @@ "type": "address" } ], - "name": "maxWithdrawOrderAllowed", + "name": "orderWithdrawEpoch", "outputs": [ { "name": "", @@ -581,6 +452,20 @@ "stateMutability": "pure", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "getPoolsToBeElected", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [ @@ -593,7 +478,7 @@ "type": "address" } ], - "name": "orderedWithdrawAmount", + "name": "stakeAmount", "outputs": [ { "name": "", @@ -608,34 +493,80 @@ "constant": true, "inputs": [ { - "name": "_poolStakingAddress", + "name": "_stakingAddress", "type": "address" } ], - "name": "orderedWithdrawAmountTotal", + "name": "isPoolActive", "outputs": [ { "name": "", - "type": "uint256" + "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_toPoolStakingAddress", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, + "inputs": [ + { + "name": "_stakingAddress", + "type": "address" + } + ], + "name": "poolIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, "inputs": [ { "name": "_poolStakingAddress", "type": "address" }, { - "name": "_staker", - "type": "address" + "name": "_amount", + "type": "int256" } ], - "name": "orderWithdrawEpoch", + "name": "orderWithdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "STAKE_UNIT", "outputs": [ { "name": "", @@ -646,6 +577,34 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "_poolStakingAddress", + "type": "address" + } + ], + "name": "claimOrderedWithdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getPoolsToBeRemoved", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [ @@ -654,7 +613,7 @@ "type": "address" } ], - "name": "stakeAmountTotal", + "name": "orderedWithdrawAmountTotal", "outputs": [ { "name": "", @@ -665,19 +624,51 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "getPoolsInactive", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "validatorSetContract", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [ { "name": "_poolStakingAddress", "type": "address" + }, + { + "name": "_staker", + "type": "address" } ], - "name": "poolDelegators", + "name": "orderedWithdrawAmount", "outputs": [ { "name": "", - "type": "address[]" + "type": "uint256" } ], "payable": false, @@ -686,17 +677,8 @@ }, { "constant": true, - "inputs": [ - { - "name": "_poolStakingAddress", - "type": "address" - }, - { - "name": "_delegator", - "type": "address" - } - ], - "name": "poolDelegatorIndex", + "inputs": [], + "name": "MAX_DELEGATORS_PER_POOL", "outputs": [ { "name": "", @@ -711,15 +693,11 @@ "constant": true, "inputs": [ { - "name": "_poolStakingAddress", - "type": "address" - }, - { - "name": "_delegator", + "name": "_stakingAddress", "type": "address" } ], - "name": "poolDelegatorInactiveIndex", + "name": "poolToBeRemovedIndex", "outputs": [ { "name": "", @@ -730,15 +708,19 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [], + "name": "incrementStakingEpoch", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, - "inputs": [ - { - "name": "_stakingAddress", - "type": "address" - } - ], - "name": "poolIndex", + "inputs": [], + "name": "MAX_CANDIDATES", "outputs": [ { "name": "", @@ -750,22 +732,21 @@ "type": "function" }, { - "constant": true, + "constant": false, "inputs": [ { - "name": "_stakingAddress", + "name": "_fromPoolStakingAddress", "type": "address" - } - ], - "name": "poolInactiveIndex", - "outputs": [ + }, { - "name": "", + "name": "_amount", "type": "uint256" } ], + "name": "withdraw", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { @@ -788,87 +769,223 @@ "type": "function" }, { - "constant": true, + "anonymous": false, "inputs": [ { - "name": "_stakingAddress", + "indexed": true, + "name": "fromPoolStakingAddress", + "type": "address" + }, + { + "indexed": true, + "name": "staker", "type": "address" + }, + { + "indexed": true, + "name": "stakingEpoch", + "type": "uint256" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" } ], - "name": "poolToBeRemovedIndex", - "outputs": [ + "name": "Claimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "name": "", + "indexed": true, + "name": "toPoolStakingAddress", + "type": "address" + }, + { + "indexed": true, + "name": "staker", + "type": "address" + }, + { + "indexed": true, + "name": "stakingEpoch", + "type": "uint256" + }, + { + "indexed": false, + "name": "amount", "type": "uint256" } ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "Staked", + "type": "event" }, { - "constant": true, + "anonymous": false, "inputs": [ { - "name": "_poolStakingAddress", + "indexed": false, + "name": "fromPoolStakingAddress", "type": "address" }, { - "name": "_staker", + "indexed": true, + "name": "toPoolStakingAddress", + "type": "address" + }, + { + "indexed": true, + "name": "staker", "type": "address" + }, + { + "indexed": true, + "name": "stakingEpoch", + "type": "uint256" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" } ], - "name": "stakeAmount", - "outputs": [ + "name": "StakeMoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "name": "", + "indexed": true, + "name": "fromPoolStakingAddress", + "type": "address" + }, + { + "indexed": true, + "name": "staker", + "type": "address" + }, + { + "indexed": true, + "name": "stakingEpoch", "type": "uint256" + }, + { + "indexed": false, + "name": "amount", + "type": "int256" } ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "WithdrawalOrdered", + "type": "event" }, { - "constant": true, + "anonymous": false, "inputs": [ { - "name": "_poolStakingAddress", + "indexed": true, + "name": "fromPoolStakingAddress", "type": "address" }, { - "name": "_staker", + "indexed": true, + "name": "staker", "type": "address" + }, + { + "indexed": true, + "name": "stakingEpoch", + "type": "uint256" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" } ], - "name": "stakeAmountByCurrentEpoch", - "outputs": [ + "name": "Withdrawn", + "type": "event" + }, + { + "constant": false, + "inputs": [ { - "name": "", + "name": "_amount", "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" } ], + "name": "addPool", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, + "constant": false, "inputs": [ { - "name": "_poolStakingAddress", + "name": "_validatorSetContract", "type": "address" }, { - "name": "_staker", + "name": "_erc20TokenContract", "type": "address" + }, + { + "name": "_initialStakingAddresses", + "type": "address[]" + }, + { + "name": "_delegatorMinStake", + "type": "uint256" + }, + { + "name": "_candidateMinStake", + "type": "uint256" + }, + { + "name": "_stakingEpochDuration", + "type": "uint256" + }, + { + "name": "_stakeWithdrawDisallowPeriod", + "type": "uint256" } ], - "name": "stakeAmountMinusOrderedWithdraw", + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_blockNumber", + "type": "uint256" + } + ], + "name": "setStakingEpochStartBlock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "areStakeAndWithdrawAllowed", "outputs": [ { "name": "", - "type": "uint256" + "type": "bool" } ], "payable": false, @@ -877,13 +994,22 @@ }, { "constant": true, - "inputs": [ + "inputs": [], + "name": "stakeWithdrawDisallowPeriod", + "outputs": [ { - "name": "_poolStakingAddress", - "type": "address" + "name": "", + "type": "uint256" } ], - "name": "stakeAmountTotalMinusOrderedWithdraw", + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "stakingEpochDuration", "outputs": [ { "name": "", @@ -897,7 +1023,7 @@ { "constant": true, "inputs": [], - "name": "stakingEpoch", + "name": "stakingEpochStartBlock", "outputs": [ { "name": "", @@ -911,11 +1037,11 @@ { "constant": true, "inputs": [], - "name": "validatorSetContract", + "name": "stakingEpochEndBlock", "outputs": [ { "name": "", - "type": "address" + "type": "uint256" } ], "payable": false, From f587ecc6dd9610b7e6a3e3ce7448ede1e2d99f5a Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 15:08:15 +0300 Subject: [PATCH 076/191] remove unwanted changes --- apps/explorer/lib/explorer/application.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index d886dd8a0b..d609205d41 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -29,8 +29,7 @@ defmodule Explorer.Application do Explorer.SmartContract.SolcDownloader, {Registry, keys: :duplicate, name: Registry.ChainEvents, id: Registry.ChainEvents}, {Admin.Recovery, [[], [name: Admin.Recovery]]}, - {TransactionCountCache, [[], []]}, - {BlockCountCache, []} + {TransactionCountCache, [[], []]} ] children = base_children ++ configurable_children() @@ -40,6 +39,7 @@ defmodule Explorer.Application do res = Supervisor.start_link(children, opts) BlockNumberCache.setup() + BlockCountCache.setup() res end From 632fb29d1ec29988d718f20b532407fa821ef488 Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 16:00:34 +0300 Subject: [PATCH 077/191] add epoch counter test --- .../lib/explorer/staking/epoch_counter.ex | 30 +++--- .../explorer/staking/epoch_counter_test.exs | 97 +++++++++++++++++++ 2 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 apps/explorer/test/explorer/staking/epoch_counter_test.exs diff --git a/apps/explorer/lib/explorer/staking/epoch_counter.ex b/apps/explorer/lib/explorer/staking/epoch_counter.ex index 256bc6fe0b..ecaf3e3307 100644 --- a/apps/explorer/lib/explorer/staking/epoch_counter.ex +++ b/apps/explorer/lib/explorer/staking/epoch_counter.ex @@ -1,6 +1,6 @@ defmodule Explorer.Staking.EpochCounter do @moduledoc """ - Counts staking epoch + Fetches current staking epoch number and the epoch end block number """ use GenServer @@ -14,23 +14,27 @@ defmodule Explorer.Staking.EpochCounter do @doc "Current staking epoch number" def epoch_number do - case :ets.lookup(@table_name, @epoch_key) do - [{_, epoch_num}] -> - epoch_num - - _ -> - 0 + if :ets.info(@table_name) != :undefined do + case :ets.lookup(@table_name, @epoch_key) do + [{_, epoch_num}] -> + epoch_num + + _ -> + 0 + end end end @doc "Block number on which will start new epoch" def epoch_end_block do - case :ets.lookup(@table_name, @epoch_end_key) do - [{_, epoch_end}] -> - epoch_end - - _ -> - 0 + if :ets.info(@table_name) != :undefined do + case :ets.lookup(@table_name, @epoch_end_key) do + [{_, epoch_end}] -> + epoch_end + + _ -> + 0 + end end end diff --git a/apps/explorer/test/explorer/staking/epoch_counter_test.exs b/apps/explorer/test/explorer/staking/epoch_counter_test.exs new file mode 100644 index 0000000000..b280f28aa4 --- /dev/null +++ b/apps/explorer/test/explorer/staking/epoch_counter_test.exs @@ -0,0 +1,97 @@ +defmodule Explorer.Staking.EpochCounterTest do + use ExUnit.Case, async: false + + import Mox + + alias Explorer.Staking.EpochCounter + alias Explorer.Chain.Events.Publisher + + setup :verify_on_exit! + setup :set_mox_global + + test "when disabled, it returns nil" do + assert EpochCounter.epoch_number() == nil + assert EpochCounter.epoch_end_block() == nil + end + + test "fetch epoch data" do + set_mox(10, 880) + Application.put_env(:explorer, EpochCounter, enabled: true) + start_supervised!(EpochCounter) + + Process.sleep(1_000) + + assert EpochCounter.epoch_number() == 10 + assert EpochCounter.epoch_end_block() == 880 + end + + test "fetch new epoch data" do + set_mox(10, 880) + Application.put_env(:explorer, EpochCounter, enabled: true) + start_supervised!(EpochCounter) + + Process.sleep(1_000) + + assert EpochCounter.epoch_number() == 10 + assert EpochCounter.epoch_end_block() == 880 + + event_type = :blocks + broadcast_type = :realtime + event_data = [%{number: 881}] + + set_mox(11, 960) + Publisher.broadcast([{event_type, event_data}], broadcast_type) + + Process.sleep(1_000) + + assert EpochCounter.epoch_number() == 11 + assert EpochCounter.epoch_end_block() == 960 + end + + defp set_mox(epoch_num, end_block_num) do + expect( + EthereumJSONRPC.Mox, + :json_rpc, + fn [ + %{ + id: 0, + jsonrpc: "2.0", + method: "eth_call", + params: _ + }, + %{ + id: 1, + jsonrpc: "2.0", + method: "eth_call", + params: _ + } + ], _options -> + {:ok, + [ + %{ + id: 0, + jsonrpc: "2.0", + result: encode_num(epoch_num) + }, + %{ + id: 1, + jsonrpc: "2.0", + result: encode_num(end_block_num) + } + ] + } + end + ) + end + + defp encode_num(num) do + selector = %ABI.FunctionSelector{function: nil, types: [uint: 32]} + + encoded_num = + [num] + |> ABI.TypeEncoder.encode(selector) + |> Base.encode16(case: :lower) + + "0x" <> encoded_num + end +end From 7833654c162557adcdf1253af798027d5a4c237d Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 16:12:51 +0300 Subject: [PATCH 078/191] update pools reader test --- .../explorer/staking/pools_reader_test.exs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/apps/explorer/test/explorer/staking/pools_reader_test.exs b/apps/explorer/test/explorer/staking/pools_reader_test.exs index ac6a600722..1795f247b2 100644 --- a/apps/explorer/test/explorer/staking/pools_reader_test.exs +++ b/apps/explorer/test/explorer/staking/pools_reader_test.exs @@ -1,6 +1,5 @@ defmodule Explorer.Token.PoolsReaderTest do use EthereumJSONRPC.Case - use Explorer.DataCase alias Explorer.Staking.PoolsReader @@ -44,6 +43,7 @@ defmodule Explorer.Token.PoolsReaderTest do mining_address: <<187, 202, 168, 212, 130, 137, 187, 31, 252, 249, 128, 141, 154, 164, 177, 210, 21, 5, 76, 120>>, staked_amount: 0, + self_staked_amount: 0, staking_address: <<11, 47, 94, 47, 60, 189, 134, 78, 170, 44, 100, 46, 55, 105, 193, 88, 35, 97, 202, 246>>, was_banned_count: 0, was_validator_count: 2 @@ -162,6 +162,24 @@ defmodule Explorer.Token.PoolsReaderTest do result: "0x0000000000000000000000000000000000000000000000000000000000000000" } + # stakeAmountMinusOrderedWithdraw + %{ + id: id, + jsonrpc: "2.0", + method: "eth_call", + params: [ + %{ + data: "0x58daab6a0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf60000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", + to: _ + }, + "latest" + ] + } -> + %{ + id: id, + result: "0x0000000000000000000000000000000000000000000000000000000000000000" + } + # isValidator %{ id: id, From f370e885bd06bd68a515c98bdfad5737a3004eed Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 16:16:21 +0300 Subject: [PATCH 079/191] mix format --- .../lib/explorer/staking/pools_reader.ex | 2 +- .../explorer/staking/epoch_counter_test.exs | 52 +++++++++---------- .../explorer/staking/pools_reader_test.exs | 31 +++++------ 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/pools_reader.ex b/apps/explorer/lib/explorer/staking/pools_reader.ex index e3bb27084f..608fea3863 100644 --- a/apps/explorer/lib/explorer/staking/pools_reader.ex +++ b/apps/explorer/lib/explorer/staking/pools_reader.ex @@ -87,7 +87,7 @@ defmodule Explorer.Staking.PoolsReader do {:validators, "validatorCounter", [mining_address]}, {:validators, "isValidatorBanned", [mining_address]}, {:validators, "bannedUntil", [mining_address]}, - {:validators, "banCounter", [mining_address]}, + {:validators, "banCounter", [mining_address]} ] methods diff --git a/apps/explorer/test/explorer/staking/epoch_counter_test.exs b/apps/explorer/test/explorer/staking/epoch_counter_test.exs index b280f28aa4..5232a71edb 100644 --- a/apps/explorer/test/explorer/staking/epoch_counter_test.exs +++ b/apps/explorer/test/explorer/staking/epoch_counter_test.exs @@ -53,33 +53,33 @@ defmodule Explorer.Staking.EpochCounterTest do EthereumJSONRPC.Mox, :json_rpc, fn [ - %{ - id: 0, - jsonrpc: "2.0", - method: "eth_call", - params: _ - }, - %{ - id: 1, - jsonrpc: "2.0", - method: "eth_call", - params: _ - } - ], _options -> + %{ + id: 0, + jsonrpc: "2.0", + method: "eth_call", + params: _ + }, + %{ + id: 1, + jsonrpc: "2.0", + method: "eth_call", + params: _ + } + ], + _options -> {:ok, - [ - %{ - id: 0, - jsonrpc: "2.0", - result: encode_num(epoch_num) - }, - %{ - id: 1, - jsonrpc: "2.0", - result: encode_num(end_block_num) - } - ] - } + [ + %{ + id: 0, + jsonrpc: "2.0", + result: encode_num(epoch_num) + }, + %{ + id: 1, + jsonrpc: "2.0", + result: encode_num(end_block_num) + } + ]} end ) end diff --git a/apps/explorer/test/explorer/staking/pools_reader_test.exs b/apps/explorer/test/explorer/staking/pools_reader_test.exs index 1795f247b2..bb3af9fbcc 100644 --- a/apps/explorer/test/explorer/staking/pools_reader_test.exs +++ b/apps/explorer/test/explorer/staking/pools_reader_test.exs @@ -164,21 +164,22 @@ defmodule Explorer.Token.PoolsReaderTest do # stakeAmountMinusOrderedWithdraw %{ - id: id, - jsonrpc: "2.0", - method: "eth_call", - params: [ - %{ - data: "0x58daab6a0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf60000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", - to: _ - }, - "latest" - ] - } -> - %{ - id: id, - result: "0x0000000000000000000000000000000000000000000000000000000000000000" - } + id: id, + jsonrpc: "2.0", + method: "eth_call", + params: [ + %{ + data: + "0x58daab6a0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf60000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", + to: _ + }, + "latest" + ] + } -> + %{ + id: id, + result: "0x0000000000000000000000000000000000000000000000000000000000000000" + } # isValidator %{ From 107edb42f5f0d474a6228190b974369709d514be Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 8 May 2019 16:38:05 +0300 Subject: [PATCH 080/191] fallback to 2 evm versions --- .../lib/explorer/smart_contract/verifier.ex | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/apps/explorer/lib/explorer/smart_contract/verifier.ex b/apps/explorer/lib/explorer/smart_contract/verifier.ex index 4b521fba35..662bde1515 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier.ex @@ -17,13 +17,28 @@ defmodule Explorer.SmartContract.Verifier do do: {:error, :contract_source_code} def evaluate_authenticity(address_hash, params) do + evm_version = Map.get(params, "evm_version", "petersburg") + + Enum.reduce([evm_version | previous_evm_versions(evm_version)], false, fn version, acc -> + case acc do + {:ok, _} = result -> + result + + _ -> + cur_params = Map.put(params, "evm_version", version) + verify(address_hash, cur_params) + end + end) + end + + defp verify(address_hash, params) do name = Map.fetch!(params, "name") contract_source_code = Map.fetch!(params, "contract_source_code") optimization = Map.fetch!(params, "optimization") compiler_version = Map.fetch!(params, "compiler_version") external_libraries = Map.get(params, "external_libraries", %{}) constructor_arguments = Map.get(params, "constructor_arguments", "") - evm_version = Map.get(params, "evm_version", "byzantium") + evm_version = Map.get(params, "evm_version") optimization_runs = Map.get(params, "optimization_runs", 200) solc_output = @@ -37,25 +52,7 @@ defmodule Explorer.SmartContract.Verifier do external_libs: external_libraries ) - case compare_bytecodes(solc_output, address_hash, constructor_arguments) do - {:error, :generated_bytecode} -> - next_evm_version = next_evm_version(evm_version) - - second_solc_output = - CodeCompiler.run( - name: name, - compiler_version: compiler_version, - code: contract_source_code, - optimize: optimization, - evm_version: next_evm_version, - external_libs: external_libraries - ) - - compare_bytecodes(second_solc_output, address_hash, constructor_arguments) - - result -> - result - end + compare_bytecodes(solc_output, address_hash, constructor_arguments) end defp compare_bytecodes({:error, :name}, _, _), do: {:error, :name} @@ -99,16 +96,21 @@ defmodule Explorer.SmartContract.Verifier do bytecode end - def next_evm_version(current_evm_version) do - [prev_version, last_version] = - CodeCompiler.allowed_evm_versions() - |> Enum.reverse() - |> Enum.take(2) + def previous_evm_versions(current_evm_version) do + index = Enum.find_index(CodeCompiler.allowed_evm_versions(), fn el -> el == current_evm_version end) + + cond do + index == 0 -> + [] - if current_evm_version != last_version do - last_version - else - prev_version + index == 1 -> + [List.first(CodeCompiler.allowed_evm_versions())] + + true -> + [ + Enum.at(CodeCompiler.allowed_evm_versions(), index - 1), + Enum.at(CodeCompiler.allowed_evm_versions(), index - 2) + ] end end From 5e66eda0425bc80f5df7529bf5b23156f6376521 Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 18:02:47 +0300 Subject: [PATCH 081/191] test getting staking pools --- apps/explorer/lib/explorer/chain.ex | 69 +++++++++++++--------- apps/explorer/test/explorer/chain_test.exs | 49 +++++++++++++++ 2 files changed, 89 insertions(+), 29 deletions(-) diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 840b2fb288..b2964c85b0 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -2832,13 +2832,27 @@ defmodule Explorer.Chain do value end - @doc """ - List of staking pools which are validators - """ - @spec validators_pools(lim :: integer, off :: integer) :: [map] - def validators_pools(lim, off) when is_integer(lim) and is_integer(off) do + @doc "Get staking pools from the DB" + @spec staking_pools(filter :: :validator | :active | :inactive, lim :: integer, off :: integer) :: [map()] + def staking_pools(filter, lim, off) when is_integer(lim) and is_integer(off) do Address.Name - |> where( + |> staking_pool_filter(filter) + |> limit(^lim) + |> offset(^off) + |> Repo.all() + end + + @doc "Get count of staking pools from the DB" + @spec staking_pools_count(filter :: :validator | :active | :inactive) :: integer + def staking_pools_count(filter) do + Address.Name + |> staking_pool_filter(filter) + |> Repo.aggregate(:count, :address_hash) + end + + defp staking_pool_filter(query, :validator) do + where( + query, [_], fragment(""" (metadata->>'is_active')::boolean = true and @@ -2846,35 +2860,32 @@ defmodule Explorer.Chain do (metadata->>'is_validator')::boolean = true """) ) - |> limit(^lim) - |> offset(^off) - |> Repo.all() end - @doc """ - List of active pools - """ - @spec active_pools(lim :: integer, off :: integer) :: [map] - def active_pools(lim, off) when is_integer(lim) and is_integer(off) do - Address.Name - |> where([_], fragment("(metadata->>'is_active')::boolean = true")) - |> limit(^lim) - |> offset(^off) - |> Repo.all() + defp staking_pool_filter(query, :active) do + where( + query, + [_], + fragment(""" + (metadata->>'is_active')::boolean = true and + (metadata->>'deleted')::boolean is not true + """) + ) end - @doc """ - List of inactive pools - """ - @spec inactive_pools(lim :: integer, off :: integer) :: [map] - def inactive_pools(lim, off) when is_integer(lim) and is_integer(off) do - Address.Name - |> where([_], fragment("(metadata->>'is_active')::boolean = false")) - |> limit(^lim) - |> offset(^off) - |> Repo.all() + defp staking_pool_filter(query, :inactive) do + where( + query, + [_], + fragment(""" + (metadata->>'is_active')::boolean = false and + (metadata->>'deleted')::boolean is not true + """) + ) end + defp staking_pool_filter(query, _), do: query + defp with_decompiled_code_flag(query, hash) do has_decompiled_code_query = from(decompiled_contract in DecompiledSmartContract, diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index a9b479c3bd..ec4fe63196 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -3903,4 +3903,53 @@ defmodule Explorer.ChainTest do refute Chain.contract_address?(to_string(hash), 1, json_rpc_named_arguments) end end + + describe "staking_pools/3" do + test "validators staking pools" do + inserted_validator = insert(:address_name, primary: true, metadata: %{is_active: true, is_validator: true}) + insert(:address_name, primary: true, metadata: %{is_active: true, is_validator: false}) + + assert [gotten_validator] = Chain.staking_pools(:validator, 20, 0) + assert inserted_validator.address_hash == gotten_validator.address_hash + end + + test "active staking pools" do + inserted_validator = insert(:address_name, primary: true, metadata: %{is_active: true}) + insert(:address_name, primary: true, metadata: %{is_active: false}) + + assert [gotten_validator] = Chain.staking_pools(:active, 20, 0) + assert inserted_validator.address_hash == gotten_validator.address_hash + end + + test "inactive staking pools" do + insert(:address_name, primary: true, metadata: %{is_active: true}) + inserted_validator = insert(:address_name, primary: true, metadata: %{is_active: false}) + + assert [gotten_validator] = Chain.staking_pools(:inactive, 20, 0) + assert inserted_validator.address_hash == gotten_validator.address_hash + end + end + + describe "staking_pools_count/1" do + test "validators staking pools" do + insert(:address_name, primary: true, metadata: %{is_active: true, is_validator: true}) + insert(:address_name, primary: true, metadata: %{is_active: true, is_validator: false}) + + assert Chain.staking_pools_count(:validator) == 1 + end + + test "active staking pools" do + insert(:address_name, primary: true, metadata: %{is_active: true}) + insert(:address_name, primary: true, metadata: %{is_active: false}) + + assert Chain.staking_pools_count(:active) == 1 + end + + test "inactive staking pools" do + insert(:address_name, primary: true, metadata: %{is_active: true}) + insert(:address_name, primary: true, metadata: %{is_active: false}) + + assert Chain.staking_pools_count(:inactive) == 1 + end + end end From 57f924f440e4c040c8691b527d956119120c1f43 Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 18:18:08 +0300 Subject: [PATCH 082/191] edit config --- apps/explorer/config/config.exs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index 529f4698cf..7e7800524d 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -58,9 +58,13 @@ config :explorer, Explorer.Staking.PoolsReader, validators_contract_address: System.get_env("POS_VALIDATORS_CONTRACT"), staking_contract_address: System.get_env("POS_STAKING_CONTRACT") -config :explorer, Explorer.Staking.EpochCounter, - enabled: false, - staking_contract_address: System.get_env("POS_STAKING_CONTRACT") +if System.get_env("POS_STAKING_CONTRACT") do + config :explorer, Explorer.Staking.EpochCounter, + enabled: true, + staking_contract_address: System.get_env("POS_STAKING_CONTRACT") +else + config :explorer, Explorer.Staking.EpochCounter, enabled: false +end if System.get_env("SUPPLY_MODULE") == "TokenBridge" do config :explorer, supply: Explorer.Chain.Supply.TokenBridge From 147f0c43474cd4e3e088225320f6bdd882c0391f Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 18:41:21 +0300 Subject: [PATCH 083/191] edit staking pools fetcher test --- .../indexer/fetcher/staking_pools_test.exs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/apps/indexer/test/indexer/fetcher/staking_pools_test.exs b/apps/indexer/test/indexer/fetcher/staking_pools_test.exs index 8f985537bf..13e2c0d7ee 100644 --- a/apps/indexer/test/indexer/fetcher/staking_pools_test.exs +++ b/apps/indexer/test/indexer/fetcher/staking_pools_test.exs @@ -129,6 +129,25 @@ defmodule Indexer.Fetcher.StakingPoolsTest do result: "0x0000000000000000000000000000000000000000000000000000000000000000" } + # stakeAmountMinusOrderedWithdraw + %{ + id: id, + jsonrpc: "2.0", + method: "eth_call", + params: [ + %{ + data: + "0x58daab6a0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf60000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6", + to: _ + }, + "latest" + ] + } -> + %{ + id: id, + result: "0x0000000000000000000000000000000000000000000000000000000000000000" + } + # isValidator %{ id: id, From 2f4d569acd9d90d14176186323c1b1d79b9f11a0 Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 18:58:11 +0300 Subject: [PATCH 084/191] additional changes --- apps/explorer/lib/explorer/staking/epoch_counter.ex | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/explorer/lib/explorer/staking/epoch_counter.ex b/apps/explorer/lib/explorer/staking/epoch_counter.ex index ecaf3e3307..9b50d983de 100644 --- a/apps/explorer/lib/explorer/staking/epoch_counter.ex +++ b/apps/explorer/lib/explorer/staking/epoch_counter.ex @@ -62,14 +62,16 @@ defmodule Explorer.Staking.EpochCounter do end def handle_info({:chain_event, :blocks, :realtime, blocks}, state) do - new_block = Enum.max_by(blocks, &Map.get(&1, :number), fn -> 0 end) - block_number = new_block.number + new_block_number = + blocks + |> Enum.map(& &1[:number]) + |> Enum.max(fn -> 0 end) case :ets.lookup(@table_name, @epoch_end_key) do [] -> fetch_epoch_info() - [{_, epoch_end_block}] when epoch_end_block < block_number -> + [{_, epoch_end_block}] when epoch_end_block < new_block_number -> fetch_epoch_info() _ -> From 4b759a309620784d4f99ce0de75a3b91002c7ca5 Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 8 May 2019 19:22:47 +0300 Subject: [PATCH 085/191] add entry to the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd2a8dcb2f..347633868f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request - [#1857](https://github.com/poanetwork/blockscout/pull/1857) - Re-implement Geth JS internal transaction tracer in Elixir - [#1859](https://github.com/poanetwork/blockscout/pull/1859) - feat: show raw transaction traces +- [#1876](https://github.com/poanetwork/blockscout/pull/1876) - async calculate a count of blocks ### Fixes From 1d2c11c0ff6e6b5df9f3a2b3317fe59296702321 Mon Sep 17 00:00:00 2001 From: zachdaniel Date: Wed, 8 May 2019 10:31:37 -0400 Subject: [PATCH 086/191] fix: remove source code fields from list endpoint --- CHANGELOG.md | 1 + .../api/rpc/contract_controller.ex | 21 +++-- .../lib/block_scout_web/etherscan.ex | 82 ++++++++++--------- .../views/api/rpc/contract_view.ex | 54 +++++++----- .../api/rpc/contract_controller_test.exs | 32 ++------ apps/explorer/lib/explorer/chain.ex | 8 ++ apps/explorer/lib/explorer/chain/address.ex | 2 +- 7 files changed, 110 insertions(+), 90 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aa12cfdef..3b60266c26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - [#1806](https://github.com/poanetwork/blockscout/pull/1806) - verify contracts with a post request - [#1857](https://github.com/poanetwork/blockscout/pull/1857) - Re-implement Geth JS internal transaction tracer in Elixir - [#1859](https://github.com/poanetwork/blockscout/pull/1859) - feat: show raw transaction traces +- [#1920](https://github.com/poanetwork/blockscout/pull/1920) - fix: remove source code fields from list endpoint ### Fixes diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/contract_controller.ex index 146626cce5..886bbcd575 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/contract_controller.ex @@ -8,16 +8,21 @@ defmodule BlockScoutWeb.API.RPC.ContractController do def verify(conn, %{"addressHash" => address_hash} = params) do with {:params, {:ok, fetched_params}} <- {:params, fetch_verify_params(params)}, + {:format, {:ok, casted_address_hash}} <- to_address_hash(address_hash), {:params, external_libraries} <- {:params, fetch_external_libraries(params)}, - {:publish, {:ok, smart_contract}} <- - {:publish, Publisher.publish(address_hash, fetched_params, external_libraries)}, - preloaded_smart_contract <- SmartContract.preload_decompiled_smart_contract(smart_contract) do - render(conn, :verify, %{contract: preloaded_smart_contract, address_hash: address_hash}) + {:publish, {:ok, _}} <- + {:publish, Publisher.publish(address_hash, fetched_params, external_libraries)} do + address = Chain.address_hash_to_address_with_source_code(casted_address_hash) + + render(conn, :verify, %{contract: address}) else {:publish, _} -> render(conn, :error, error: "Something went wrong while publishing the contract.") + {:format, :error} -> + render(conn, :error, error: "Invalid address hash") + {:params, {:error, error}} -> render(conn, :error, error: error) end @@ -63,11 +68,11 @@ defmodule BlockScoutWeb.API.RPC.ContractController do def getsourcecode(conn, params) do with {:address_param, {:ok, address_param}} <- fetch_address(params), - {:format, {:ok, address_hash}} <- to_address_hash(address_param), - {:contract, {:ok, contract}} <- to_smart_contract(address_hash) do + {:format, {:ok, address_hash}} <- to_address_hash(address_param) do + address = Chain.address_hash_to_address_with_source_code(address_hash) + render(conn, :getsourcecode, %{ - contract: contract, - address_hash: address_hash + contract: address }) else {:address_param, :error} -> diff --git a/apps/block_scout_web/lib/block_scout_web/etherscan.ex b/apps/block_scout_web/lib/block_scout_web/etherscan.ex index 88cdb04944..27bc197195 100644 --- a/apps/block_scout_web/lib/block_scout_web/etherscan.ex +++ b/apps/block_scout_web/lib/block_scout_web/etherscan.ex @@ -825,48 +825,11 @@ defmodule BlockScoutWeb.Etherscan do name: "Contract", fields: %{ "Address" => @address_hash_type, - "SourceCode" => %{ - type: "contract source code", - definition: "The contract's source code.", - example: """ - "pragma solidity >0.4.24; - - contract Test { - constructor() public { b = hex"12345678901234567890123456789012"; } - event Event(uint indexed a, bytes32 b); - event Event2(uint indexed a, bytes32 b); - function foo(uint a) public { emit Event(a, b); } - bytes32 b; - }" - """ - }, "DecompilerVersion" => %{ type: "decompiler version", definition: "When decompiled source code is present, the decompiler version with which it was generated.", example: "decompiler.version" }, - "DecompiledSourceCode" => %{ - type: "contract decompiled source code", - definition: "The contract's decompiled source code.", - example: """ - const name() = 'CryptoKitties' - const GEN0_STARTING_PRICE() = 10^16 - const GEN0_AUCTION_DURATION() = 86400 - const GEN0_CREATION_LIMIT() = 45000 - const symbol() = 'CK' - const PROMO_CREATION_LIMIT() = 5000 - def storage: - ceoAddress is addr # mask(160, 0) at storage #0 - cfoAddress is addr # mask(160, 0) at storage #1 - stor1.768 is uint16 => uint256 # mask(256, 768) at storage #1 - cooAddress is addr # mask(160, 0) at storage #2 - stor2.0 is uint256 => uint256 # mask(256, 0) at storage #2 - paused is uint8 # mask(8, 160) at storage #2 - stor2.256 is uint256 => uint256 # mask(256, 256) at storage #2 - stor3 is uint32 # - ... - """ - }, "ABI" => %{ type: "ABI", definition: "JSON string for the contract's Application Binary Interface (ABI)", @@ -899,6 +862,49 @@ defmodule BlockScoutWeb.Etherscan do } } + @contract_source_code_type %{ + type: "contract source code", + definition: "The contract's source code.", + example: """ + "pragma solidity >0.4.24; + + contract Test { + constructor() public { b = hex"12345678901234567890123456789012"; } + event Event(uint indexed a, bytes32 b); + event Event2(uint indexed a, bytes32 b); + function foo(uint a) public { emit Event(a, b); } + bytes32 b; + }" + """ + } + + @contract_decompiled_source_code_type %{ + type: "contract decompiled source code", + definition: "The contract's decompiled source code.", + example: """ + const name() = 'CryptoKitties' + const GEN0_STARTING_PRICE() = 10^16 + const GEN0_AUCTION_DURATION() = 86400 + const GEN0_CREATION_LIMIT() = 45000 + const symbol() = 'CK' + const PROMO_CREATION_LIMIT() = 5000 + def storage: + ceoAddress is addr # mask(160, 0) at storage #0 + cfoAddress is addr # mask(160, 0) at storage #1 + stor1.768 is uint16 => uint256 # mask(256, 768) at storage #1 + cooAddress is addr # mask(160, 0) at storage #2 + stor2.0 is uint256 => uint256 # mask(256, 0) at storage #2 + paused is uint8 # mask(8, 160) at storage #2 + stor2.256 is uint256 => uint256 # mask(256, 256) at storage #2 + stor3 is uint32 # + ... + """ + } + + @contract_with_sourcecode_model @contract_model + |> put_in([:fields, "SourceCode"], @contract_source_code_type) + |> put_in([:fields, "DecompiledSourceCode"], @contract_decompiled_source_code_type) + @transaction_receipt_status_model %{ name: "TransactionReceiptStatus", fields: %{ @@ -1971,7 +1977,7 @@ defmodule BlockScoutWeb.Etherscan do message: @message_type, result: %{ type: "array", - array_type: @contract_model + array_type: @contract_with_sourcecode_model } } } diff --git a/apps/block_scout_web/lib/block_scout_web/views/api/rpc/contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api/rpc/contract_view.ex index 27e049dfc3..86bac53410 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/api/rpc/contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/api/rpc/contract_view.ex @@ -14,43 +14,63 @@ defmodule BlockScoutWeb.API.RPC.ContractView do RPCView.render("show.json", data: Jason.encode!(abi)) end - def render("getsourcecode.json", %{contract: contract, address_hash: address_hash}) do - RPCView.render("show.json", data: [prepare_source_code_contract(contract, address_hash)]) + def render("getsourcecode.json", %{contract: contract}) do + RPCView.render("show.json", data: [prepare_source_code_contract(contract)]) end def render("error.json", assigns) do RPCView.render("error.json", assigns) end - def render("verify.json", %{contract: contract, address_hash: address_hash}) do - RPCView.render("show.json", data: prepare_source_code_contract(contract, address_hash)) + def render("verify.json", %{contract: contract}) do + RPCView.render("show.json", data: prepare_source_code_contract(contract)) end - defp prepare_source_code_contract(nil, address_hash) do + defp prepare_source_code_contract(nil) do %{ - "Address" => to_string(address_hash), + "Address" => "", "SourceCode" => "", "ABI" => "Contract source code not verified", "ContractName" => "", "CompilerVersion" => "", "DecompiledSourceCode" => "", - "DecompilerVersion" => "", + "DecompilerVersion" => decompiler_version(nil), "OptimizationUsed" => "" } end - defp prepare_source_code_contract(contract, _) do - decompiled_smart_contract = latest_decompiled_smart_contract(contract.decompiled_smart_contracts) + defp prepare_source_code_contract(address) do + decompiled_smart_contract = latest_decompiled_smart_contract(address.decompiled_smart_contracts) + contract = address.smart_contract || %{} + + contract_abi = + if is_nil(address.smart_contract) do + "Contract source code not verified" + else + Jason.encode!(contract.abi) + end + + contract_optimization = + case Map.get(contract, :optimization, "") do + true -> + "1" + + false -> + "0" + + "" -> + "" + end %{ - "Address" => to_string(contract.address_hash), - "SourceCode" => contract.contract_source_code, - "ABI" => Jason.encode!(contract.abi), - "ContractName" => contract.name, + "Address" => to_string(address.hash), + "SourceCode" => Map.get(contract, :contract_source_code, ""), + "ABI" => contract_abi, + "ContractName" => Map.get(contract, :name, ""), "DecompiledSourceCode" => decompiled_source_code(decompiled_smart_contract), "DecompilerVersion" => decompiler_version(decompiled_smart_contract), - "CompilerVersion" => contract.compiler_version, - "OptimizationUsed" => if(contract.optimization, do: "1", else: "0") + "CompilerVersion" => Map.get(contract, :compiler_version, ""), + "OptimizationUsed" => contract_optimization } end @@ -63,10 +83,8 @@ defmodule BlockScoutWeb.API.RPC.ContractView do %{ "Address" => to_string(hash), - "SourceCode" => "", "ABI" => "Contract source code not verified", "ContractName" => "", - "DecompiledSourceCode" => decompiled_source_code(decompiled_smart_contract), "DecompilerVersion" => decompiler_version(decompiled_smart_contract), "CompilerVersion" => "", "OptimizationUsed" => "" @@ -82,10 +100,8 @@ defmodule BlockScoutWeb.API.RPC.ContractView do %{ "Address" => to_string(hash), - "SourceCode" => contract.contract_source_code, "ABI" => Jason.encode!(contract.abi), "ContractName" => contract.name, - "DecompiledSourceCode" => decompiled_source_code(decompiled_smart_contract), "DecompilerVersion" => decompiler_version(decompiled_smart_contract), "CompilerVersion" => contract.compiler_version, "OptimizationUsed" => if(contract.optimization, do: "1", else: "0") diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs index 632809863f..43169a65d2 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs @@ -47,10 +47,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do "Address" => to_string(contract.address_hash), "CompilerVersion" => contract.compiler_version, "ContractName" => contract.name, - "DecompiledSourceCode" => "Contract source code not decompiled.", "DecompilerVersion" => "", - "OptimizationUsed" => if(contract.optimization, do: "1", else: "0"), - "SourceCode" => contract.contract_source_code + "OptimizationUsed" => if(contract.optimization, do: "1", else: "0") } ] end @@ -72,10 +70,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do "Address" => to_string(address.hash), "CompilerVersion" => "", "ContractName" => "", - "DecompiledSourceCode" => "Contract source code not decompiled.", "DecompilerVersion" => "", - "OptimizationUsed" => "", - "SourceCode" => "" + "OptimizationUsed" => "" } ] end @@ -98,10 +94,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do "Address" => to_string(address.hash), "CompilerVersion" => "", "ContractName" => "", - "DecompiledSourceCode" => "Contract source code not decompiled.", "DecompilerVersion" => "", - "OptimizationUsed" => "", - "SourceCode" => "" + "OptimizationUsed" => "" } ] end @@ -123,11 +117,9 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do "ABI" => Jason.encode!(contract.abi), "Address" => to_string(contract.address_hash), "CompilerVersion" => contract.compiler_version, - "DecompiledSourceCode" => "Contract source code not decompiled.", "DecompilerVersion" => "", "ContractName" => contract.name, - "OptimizationUsed" => if(contract.optimization, do: "1", else: "0"), - "SourceCode" => contract.contract_source_code + "OptimizationUsed" => if(contract.optimization, do: "1", else: "0") } ] end @@ -150,10 +142,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do "Address" => to_string(decompiled_smart_contract.address_hash), "CompilerVersion" => "", "ContractName" => "", - "DecompiledSourceCode" => decompiled_smart_contract.decompiled_source_code, "DecompilerVersion" => "test_decompiler", - "OptimizationUsed" => "", - "SourceCode" => "" + "OptimizationUsed" => "" } ] end @@ -176,10 +166,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do "Address" => to_string(smart_contract.address_hash), "CompilerVersion" => "", "ContractName" => "", - "DecompiledSourceCode" => smart_contract.decompiled_source_code, "DecompilerVersion" => "bizbuz", - "OptimizationUsed" => "", - "SourceCode" => "" + "OptimizationUsed" => "" } ] end @@ -204,10 +192,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do "Address" => to_string(smart_contract.address_hash), "CompilerVersion" => "", "ContractName" => "", - "DecompiledSourceCode" => smart_contract.decompiled_source_code, "DecompilerVersion" => "bizbuz", - "OptimizationUsed" => "", - "SourceCode" => "" + "OptimizationUsed" => "" } ] end @@ -231,10 +217,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do "Address" => to_string(contract_address.hash), "CompilerVersion" => "", "ContractName" => "", - "DecompiledSourceCode" => "Contract source code not decompiled.", "DecompilerVersion" => "", - "OptimizationUsed" => "", - "SourceCode" => "" + "OptimizationUsed" => "" } ] end diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index e6fb9c011e..6838f86b42 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -2233,6 +2233,14 @@ defmodule Explorer.Chain do |> repo.insert(on_conflict: :nothing, conflict_target: [:address_hash, :name]) end + @spec address_hash_to_address_with_source_code(%Explorer.Chain.Hash{}) :: %Explorer.Chain.Address{} | nil + def address_hash_to_address_with_source_code(%Explorer.Chain.Hash{} = address_hash) do + case Repo.get(Address, address_hash) do + nil -> nil + address -> Repo.preload(address, [:smart_contract, :decompiled_smart_contracts]) + end + end + @spec address_hash_to_smart_contract(%Explorer.Chain.Hash{}) :: %Explorer.Chain.SmartContract{} | nil def address_hash_to_smart_contract(%Explorer.Chain.Hash{} = address_hash) do query = diff --git a/apps/explorer/lib/explorer/chain/address.ex b/apps/explorer/lib/explorer/chain/address.ex index d4b5bc8174..be2866fa35 100644 --- a/apps/explorer/lib/explorer/chain/address.ex +++ b/apps/explorer/lib/explorer/chain/address.ex @@ -62,7 +62,7 @@ defmodule Explorer.Chain.Address do except: [ :__meta__, :smart_contract, - :decompiled_smart_contract, + :decompiled_smart_contracts, :token, :contracts_creation_internal_transaction, :contracts_creation_transaction, From 3e95ca87719faf7ef87262d20f8aae1c6e55ff78 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 9 May 2019 09:13:43 +0300 Subject: [PATCH 087/191] fix CR issues --- CHANGELOG.md | 1 + apps/explorer/lib/explorer/smart_contract/verifier.ex | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd2a8dcb2f..128f91bde1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance - [#1904](https://github.com/poanetwork/blockscout/pull/1904) - fix `BLOCK_COUNT_CACHE_TTL` env var type - [#1898](https://github.com/poanetwork/blockscout/pull/1898) - check if the constructor has arguments before verifying constructor arguments +- [#1915](https://github.com/poanetwork/blockscout/pull/1915) - fallback to 2 latest evm versions ### Chore diff --git a/apps/explorer/lib/explorer/smart_contract/verifier.ex b/apps/explorer/lib/explorer/smart_contract/verifier.ex index 662bde1515..cece61e356 100644 --- a/apps/explorer/lib/explorer/smart_contract/verifier.ex +++ b/apps/explorer/lib/explorer/smart_contract/verifier.ex @@ -17,7 +17,8 @@ defmodule Explorer.SmartContract.Verifier do do: {:error, :contract_source_code} def evaluate_authenticity(address_hash, params) do - evm_version = Map.get(params, "evm_version", "petersburg") + latest_evm_version = List.last(CodeCompiler.allowed_evm_versions()) + evm_version = Map.get(params, "evm_version", latest_evm_version) Enum.reduce([evm_version | previous_evm_versions(evm_version)], false, fn version, acc -> case acc do From 951e8a6fef2ddb30988bea3bd6ddcc509defab6b Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 9 May 2019 09:17:30 +0300 Subject: [PATCH 088/191] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed4b8db4d5..8500bd6533 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - [#1885](https://github.com/poanetwork/blockscout/pull/1885) - highlight reserved words in decompiled code - [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete - [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance +- [#1905](https://github.com/poanetwork/blockscout/pull/1905) - fix reorgs, uncles pagination ### Chore From 42b210934988a4240d4f292d6c3df8e2de8e0112 Mon Sep 17 00:00:00 2001 From: saneery Date: Thu, 9 May 2019 10:44:05 +0300 Subject: [PATCH 089/191] module doc --- apps/explorer/lib/explorer/staking/epoch_counter.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/explorer/lib/explorer/staking/epoch_counter.ex b/apps/explorer/lib/explorer/staking/epoch_counter.ex index 9b50d983de..2ada66bf65 100644 --- a/apps/explorer/lib/explorer/staking/epoch_counter.ex +++ b/apps/explorer/lib/explorer/staking/epoch_counter.ex @@ -1,6 +1,7 @@ defmodule Explorer.Staking.EpochCounter do @moduledoc """ - Fetches current staking epoch number and the epoch end block number + Fetches current staking epoch number and the epoch end block number. + It subscribes to handle new blocks and conclude whether the epoch is over. """ use GenServer From 7680df043946af0838ce3e270317e6d17ec6b198 Mon Sep 17 00:00:00 2001 From: saneery Date: Thu, 9 May 2019 10:49:20 +0300 Subject: [PATCH 090/191] function doc --- apps/explorer/lib/explorer/staking/epoch_counter.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/explorer/lib/explorer/staking/epoch_counter.ex b/apps/explorer/lib/explorer/staking/epoch_counter.ex index 2ada66bf65..a53425ce9c 100644 --- a/apps/explorer/lib/explorer/staking/epoch_counter.ex +++ b/apps/explorer/lib/explorer/staking/epoch_counter.ex @@ -62,6 +62,7 @@ defmodule Explorer.Staking.EpochCounter do {:noreply, state} end + @doc "Handles new blocks and decides to fetch new epoch info" def handle_info({:chain_event, :blocks, :realtime, blocks}, state) do new_block_number = blocks From 792149a82f6ebc818944027c768dbefc8b0202c4 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Thu, 9 May 2019 14:54:03 +0300 Subject: [PATCH 091/191] Update _ethereum_classic_variables.scss --- .../theme/_ethereum_classic_variables.scss | 52 +++++++++++++++++-- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss b/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss index b04cf1234b..490ae2376b 100644 --- a/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss +++ b/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss @@ -1,8 +1,50 @@ -$primary: #1b1b39; -$secondary: #4beba0; -$tertiary: #4beba0; +// general +$primary: #1c1c3d; +$secondary: #4ad7a7; +$tertiary: #5959d8; +$additional-font: #bdbdff; +// footer $footer-background-color: $primary; $footer-title-color: #fff; -$footer-text-color: #fff; -$footer-item-disc-color: $secondary; +$footer-text-color: $additional-font; +$footer-item-disc-color: $tertiary; +.footer-logo { filter: brightness(0) invert(1); } + +// dashboard +$dashboard-line-color-price: $tertiary; // price left border + +$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels + +$dashboard-stats-item-value-color: $additional-font; // stat values + +$dashboard-stats-item-border-color: $secondary; // stat border + +$dashboard-banner-gradient-start: $primary; // gradient begin + +$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end + +$dashboard-banner-network-plain-container-background-color: #2d2d69; // stats bg + + +// navigation +.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow +$header-icon-border-color-hover: $tertiary; // top border on hover +$header-icon-color-hover: $tertiary; // nav icon on hover +.dropdown-item:hover, .dropdown-item:focus { background-color: $tertiary !important; } // dropdown item on hover + +// buttons +$btn-line-bg: #fff; // button bg +$btn-line-color: #27275e; // button border and font color && hover bg color +$btn-copy-color: #27275e; // btn copy +$btn-qr-color: #27275e; // btn qr-code + +//links & tile +.tile a { color: $tertiary !important; } // links color for badges +.tile-type-block { + border-left: 4px solid #27275e; +} // tab active bg + +// card +$card-background-1: $tertiary; +$card-tab-active: $tertiary; From e18348ed7118349ca908e2892434e1e9f279a66b Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Thu, 9 May 2019 14:56:15 +0300 Subject: [PATCH 092/191] Update classic_ethereum_logo.svg --- .../assets/static/images/classic_ethereum_logo.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/block_scout_web/assets/static/images/classic_ethereum_logo.svg b/apps/block_scout_web/assets/static/images/classic_ethereum_logo.svg index dd7928216e..51ef19cc31 100644 --- a/apps/block_scout_web/assets/static/images/classic_ethereum_logo.svg +++ b/apps/block_scout_web/assets/static/images/classic_ethereum_logo.svg @@ -1 +1 @@ -classic_ethereum_logo \ No newline at end of file + From 0e91d6e57a685ecdd382b1be250ce41c64fa978e Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Thu, 9 May 2019 15:03:20 +0300 Subject: [PATCH 093/191] Delete _aerum_variables.scss --- .../assets/css/theme/_aerum_variables.scss | 50 ------------------- 1 file changed, 50 deletions(-) delete mode 100644 apps/block_scout_web/assets/css/theme/_aerum_variables.scss diff --git a/apps/block_scout_web/assets/css/theme/_aerum_variables.scss b/apps/block_scout_web/assets/css/theme/_aerum_variables.scss deleted file mode 100644 index 62a7e6d841..0000000000 --- a/apps/block_scout_web/assets/css/theme/_aerum_variables.scss +++ /dev/null @@ -1,50 +0,0 @@ -// general -$primary: #2b2b2b; -$secondary: #01b9c5; -$tertiary: #00ae83; -$additional-font: #ffffff; - -// footer -$footer-background-color: $primary; -$footer-title-color: #fff; -$footer-text-color: #7e7e7e; -$footer-item-disc-color: $secondary; -.footer-logo { filter: brightness(0) invert(1); } - -// dashboard -$dashboard-line-color-price: $tertiary; // price left border - -$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels - -$dashboard-stats-item-value-color: $additional-font; // stat values - -$dashboard-stats-item-border-color: $tertiary; // stat border - -$dashboard-banner-gradient-start: $primary; // gradient begin - -$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end - -$dashboard-banner-network-plain-container-background-color: #424242; // stats bg - - -// navigation -.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow -$header-icon-border-color-hover: $secondary; // top border on hover -$header-icon-color-hover: $secondary; // nav icon on hover -.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover - -// buttons -$btn-line-bg: #fff; // button bg -$btn-line-color: $tertiary; // button border and font color && hover bg color -$btn-copy-color: $tertiary; // btn copy -$btn-qr-color: $tertiary; // btn qr-code - -//links & tile -.tile a { color: $secondary !important; } // links color for badges -.tile-type-block { - border-left: 4px solid $tertiary; -} // tab active bg - -// card -$card-background-1: $secondary; -$card-tab-active: $secondary; \ No newline at end of file From 227d3b5252ebdfff89910e745c08ef0dc6cc1406 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Thu, 9 May 2019 15:04:32 +0300 Subject: [PATCH 094/191] Delete aerum_logo.svg --- .../assets/static/images/aerum_logo.svg | 72 ------------------- 1 file changed, 72 deletions(-) delete mode 100644 apps/block_scout_web/assets/static/images/aerum_logo.svg diff --git a/apps/block_scout_web/assets/static/images/aerum_logo.svg b/apps/block_scout_web/assets/static/images/aerum_logo.svg deleted file mode 100644 index 62efd365ff..0000000000 --- a/apps/block_scout_web/assets/static/images/aerum_logo.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 1c3f537128ed559a8e81169871f070de5ab452c4 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Thu, 9 May 2019 15:06:43 +0300 Subject: [PATCH 095/191] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7572ba56b4..7d08868c29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## Current ### Features -- [#1913](https://github.com/poanetwork/blockscout/pull/1913) - added aerum theme and aerum logo +- [#1922](https://github.com/poanetwork/blockscout/pull/1922) - added ethereum classic theme and logo - [#1907](https://github.com/poanetwork/blockscout/pull/1907) - dropdown color bug fix (lukso theme) and tooltip color bug fix - [#1903](https://github.com/poanetwork/blockscout/pull/1903) - added rsk theme and rsk logo - [#1895](https://github.com/poanetwork/blockscout/pull/1895) - add changes to poa theme and poa logo From 91a7fc1380de9a9402dc175a61e0294cdb583f3a Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Fri, 10 May 2019 14:54:36 +0300 Subject: [PATCH 096/191] Update _dai_variables.scss --- .../assets/css/theme/_dai_variables.scss | 111 ++++++++---------- 1 file changed, 50 insertions(+), 61 deletions(-) diff --git a/apps/block_scout_web/assets/css/theme/_dai_variables.scss b/apps/block_scout_web/assets/css/theme/_dai_variables.scss index e331dc725c..8746489faa 100644 --- a/apps/block_scout_web/assets/css/theme/_dai_variables.scss +++ b/apps/block_scout_web/assets/css/theme/_dai_variables.scss @@ -1,61 +1,50 @@ -$primary: #fec042; -$secondary: #53546a; -$tertiary: #1755e4; - -.navbar.navbar-primary { - background-color: #f2f6f8; - - &.navbar-dark .navbar-nav .nav-link { - color: $secondary; - - &:hover, - &:focus { - color: rgba($secondary, 0.75); - } - } - - .form-control { - color: $secondary; - - &::-webkit-input-placeholder { - /* Chrome/Opera/Safari */ - color: transparentize($secondary, 0.5); - } - &::-moz-placeholder { - /* Firefox 19+ */ - color: transparentize($secondary, 0.5); - } - &:-ms-input-placeholder { - /* IE 10+ */ - color: transparentize($secondary, 0.5); - } - &:-moz-placeholder { - /* Firefox 18- */ - color: transparentize($secondary, 0.5); - } - } -} - -.navbar-logo { - height: 1.75em; -} - -.navbar.navbar-dark .navbar-toggler { - color: $secondary; - border-color: $secondary; - - .navbar-toggler-icon { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{transparentize($secondary, 0.5)}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); - } -} - -.button.button-secondary { - color: $secondary; - border-color: $secondary; - - &:hover, - &:focus { - background-color: $secondary; - border-color: $secondary; - } -} +// general +$primary: #2b2b2b; +$secondary: #ffb045; +$tertiary: #929292; +$additional-font: #ffffff; + +// footer +$footer-background-color: $primary; +$footer-title-color: #fff; +$footer-text-color: #7e7e7e; +$footer-item-disc-color: $secondary; +.footer-logo { filter: brightness(0) invert(1); } + +// dashboard +$dashboard-line-color-price: $tertiary; // price left border + +$dashboard-banner-chart-legend-value-color: $additional-font; // chart labels + +$dashboard-stats-item-value-color: $additional-font; // stat values + +$dashboard-stats-item-border-color: $secondary; // stat border + +$dashboard-banner-gradient-start: $primary; // gradient begin + +$dashboard-banner-gradient-end: lighten($primary, 5); // gradient end + +$dashboard-banner-network-plain-container-background-color: #424242; // stats bg + + +// navigation +.navbar { box-shadow: 0px 0px 30px 0px rgba(21, 53, 80, 0.12); } // header shadow +$header-icon-border-color-hover: $secondary; // top border on hover +$header-icon-color-hover: $secondary; // nav icon on hover +.dropdown-item:hover, .dropdown-item:focus { background-color: $secondary !important; } // dropdown item on hover + +// buttons +$btn-line-bg: #fff; // button bg +$btn-line-color: #424242; // button border and font color && hover bg color +$btn-copy-color: #424242; // btn copy +$btn-qr-color: #424242; // btn qr-code + +//links & tile +.tile a { color: #4b89fb !important; } // links color for badges +.tile-type-block { + border-left: 4px solid $secondary; +} // tab active bg + +// card +$card-background-1: $secondary; +$card-tab-active: $secondary; From d2376612901b9a86f3d5a3630e697b7bcbba0b58 Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Fri, 10 May 2019 14:56:00 +0300 Subject: [PATCH 097/191] Update dai_logo.svg --- .../assets/static/images/dai_logo.svg | 50 +------------------ 1 file changed, 1 insertion(+), 49 deletions(-) diff --git a/apps/block_scout_web/assets/static/images/dai_logo.svg b/apps/block_scout_web/assets/static/images/dai_logo.svg index 1eb9630359..582cb97f2e 100644 --- a/apps/block_scout_web/assets/static/images/dai_logo.svg +++ b/apps/block_scout_web/assets/static/images/dai_logo.svg @@ -1,49 +1 @@ - - - - - - - - - - - - - - - - - - - - - - dai_logo - - - - - - - - - - - - - - + From 0297a2e5204e955994899d85ecc8ce8e251a1a2f Mon Sep 17 00:00:00 2001 From: maxgrapps <50101080+maxgrapps@users.noreply.github.com> Date: Fri, 10 May 2019 14:57:46 +0300 Subject: [PATCH 098/191] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d08868c29..9004dde9b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Current ### Features +- [#1925](https://github.com/poanetwork/blockscout/pull/1925) - added dai theme and logo - [#1922](https://github.com/poanetwork/blockscout/pull/1922) - added ethereum classic theme and logo - [#1907](https://github.com/poanetwork/blockscout/pull/1907) - dropdown color bug fix (lukso theme) and tooltip color bug fix - [#1903](https://github.com/poanetwork/blockscout/pull/1903) - added rsk theme and rsk logo From 2d5f0017497de5b9ba2b8cde8557516777c09f2c Mon Sep 17 00:00:00 2001 From: Gabriel Rodriguez Alsina Date: Fri, 10 May 2019 10:55:59 -0300 Subject: [PATCH 099/191] (fix) status label alignment --- apps/block_scout_web/assets/css/components/_tile.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/block_scout_web/assets/css/components/_tile.scss b/apps/block_scout_web/assets/css/components/_tile.scss index 339c42232b..4ed5bc6515 100644 --- a/apps/block_scout_web/assets/css/components/_tile.scss +++ b/apps/block_scout_web/assets/css/components/_tile.scss @@ -77,6 +77,7 @@ $tile-padding: 1rem; font-weight: 700; line-height: 1.2; margin: 0 0 2px; + text-align: center; &:last-child { margin-bottom: 0; @@ -116,6 +117,8 @@ $tile-padding: 1rem; font-size: 12px; font-weight: 400; line-height: 1.2; + text-align: center; + padding: 0 5px; } .tile-bottom-contents { From e0030ae6ccfb99a277c0e83e911ead0673a4a50c Mon Sep 17 00:00:00 2001 From: Gabriel Rodriguez Alsina Date: Fri, 10 May 2019 11:00:48 -0300 Subject: [PATCH 100/191] (update) changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bf2c37f03..8591b50492 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ ### Fixes +- [#1926](https://github.com/poanetwork/blockscout/pull/1926) - status label alignment - [#1829](https://github.com/poanetwork/blockscout/pull/1829) - Handle nil quantities in block decoding routine - [#1830](https://github.com/poanetwork/blockscout/pull/1830) - Make block size field nullable - [#1840](https://github.com/poanetwork/blockscout/pull/1840) - Handle case when total supply is nil @@ -28,7 +29,7 @@ - [#1896](https://github.com/poanetwork/blockscout/pull/1896) - re-query tokens in top nav automplete - [#1881](https://github.com/poanetwork/blockscout/pull/1881) - fix: store solc versions locally for performance - [#1905](https://github.com/poanetwork/blockscout/pull/1905) - fix reorgs, uncles pagination -- [#1875](https://github.com/poanetwork/blockscout/pull/1875) - fix: resolve false positive constructor arguments +- [#1875](https://github.com/poanetwork/blockscout/pull/1875) - fix: resolve false positive constructor arguments - [#1904](https://github.com/poanetwork/blockscout/pull/1904) - fix `BLOCK_COUNT_CACHE_TTL` env var type - [#1898](https://github.com/poanetwork/blockscout/pull/1898) - check if the constructor has arguments before verifying constructor arguments - [#1915](https://github.com/poanetwork/blockscout/pull/1915) - fallback to 2 latest evm versions From 4635c152b31ed96c50ecadeedaeb57aa7e3370b5 Mon Sep 17 00:00:00 2001 From: Gabriel Rodriguez Alsina Date: Fri, 10 May 2019 16:15:25 -0300 Subject: [PATCH 101/191] (add) new pagination component for accounts section --- apps/block_scout_web/assets/css/app.scss | 2 +- .../assets/css/components/_pagination.scss | 42 -------- .../css/components/_pagination_container.scss | 98 +++++++++++++++++++ .../templates/address/index.html.eex | 28 +----- .../common_components/_pagination.html.eex | 9 -- .../_pagination_container.html.eex | 52 ++++++++++ 6 files changed, 156 insertions(+), 75 deletions(-) delete mode 100644 apps/block_scout_web/assets/css/components/_pagination.scss create mode 100644 apps/block_scout_web/assets/css/components/_pagination_container.scss delete mode 100644 apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination.html.eex create mode 100644 apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex diff --git a/apps/block_scout_web/assets/css/app.scss b/apps/block_scout_web/assets/css/app.scss index 990583ecdf..567f3b0abf 100644 --- a/apps/block_scout_web/assets/css/app.scss +++ b/apps/block_scout_web/assets/css/app.scss @@ -69,7 +69,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts"; @import "components/panels"; @import "components/nav_tabs"; @import "components/dot"; -@import "components/pagination"; +@import "components/pagination_container"; @import "components/address_link"; @import "components/footer"; @import "components/filter"; diff --git a/apps/block_scout_web/assets/css/components/_pagination.scss b/apps/block_scout_web/assets/css/components/_pagination.scss deleted file mode 100644 index b044e004bf..0000000000 --- a/apps/block_scout_web/assets/css/components/_pagination.scss +++ /dev/null @@ -1,42 +0,0 @@ -$pagination-page-link-background: #f5f6fa !default; -$pagination-page-link-color: #a3a9b5 !default; -$pagination-page-link-background-active: $primary !default; -$pagination-page-link-color-active: #fff !default; - -.pagination { - margin: 0; - padding: 30px; - - .page-item { - margin: 0 10px 0 0; - - &:last-child { - margin-right: 0; - } - } - - .page-link { - background-color: $pagination-page-link-background; - border: 1px solid $pagination-page-link-background; - color: $pagination-page-link-color; - display: block; - line-height: 1.25; - margin: 0; - padding: 0.5rem 0.75rem; - position: relative; - - &:hover { - background-color: darken($pagination-page-link-background, 5%); - border-color: darken($pagination-page-link-background, 5%); - } - - .active & { - &, - &:hover { - background-color: $pagination-page-link-background-active; - border-color: $pagination-page-link-background-active; - color: $pagination-page-link-color-active; - } - } - } -} diff --git a/apps/block_scout_web/assets/css/components/_pagination_container.scss b/apps/block_scout_web/assets/css/components/_pagination_container.scss new file mode 100644 index 0000000000..0ff6d96335 --- /dev/null +++ b/apps/block_scout_web/assets/css/components/_pagination_container.scss @@ -0,0 +1,98 @@ +$pagination-page-link-background: #f5f6fa !default; +$pagination-page-link-color: #a3a9b5 !default; +$pagination-page-link-background-active: $primary !default; +$pagination-page-link-color-active: #fff !default; + +@mixin pagination-container-base($background-color, $text-color) { + background-color: $background-color; + border: 1px solid $background-color; + color: $text-color; + + path { + fill: $text-color; + } +} + +.pagination-container { + display: flex; + justify-content: space-between; + + &.position-bottom { + padding-top: 30px; + } + + &.position-top { + padding-bottom: 30px; + } + + .pagination-limit { + align-items: center; + color: #033333; + display: flex; + font-size: 12px; + font-weight: 600; + line-height: 1.2; + + select { + margin: 0 10px; + } + } + + .pagination { + margin: 0 0 0 auto; + padding: 0; + + .page-item { + margin: 0 10px 0 0; + + &:last-child { + margin-right: 0; + } + + &.active .page-link { + @include pagination-container-base($pagination-page-link-background-active, $pagination-page-link-color-active); + cursor: default; + pointer-events: none; + + &:hover { + @include pagination-container-base($pagination-page-link-background-active, $pagination-page-link-color-active); + } + } + } + + .page-link { + @include pagination-container-base($pagination-page-link-background, $pagination-page-link-color); + align-items: center; + border-radius: 2px; + display: flex; + font-size: 12px; + font-weight: 600; + height: 24px; + margin: 0; + padding: 0 10px; + position: relative; + user-select: none; + + &:not(.no-hover):hover { + @include pagination-container-base($pagination-page-link-background-active, $pagination-page-link-color-active); + } + + &[href=''] { + pointer-events: none; + } + + &.no-hover { + cursor: default; + } + + &[disabled] { + @include pagination-container-base($pagination-page-link-background, $pagination-page-link-color); + cursor: not-allowed; + opacity: 0.4; + outline: none; + pointer-events: none; + } + } + } + +} \ No newline at end of file diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex index fca5d5b50d..7a0c24a5d7 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex @@ -1,16 +1,7 @@
    - <%= if @next_page_path do %> - " class="button button-secondary button-small float-right ml-1"> - <%= gettext("Next") %> - - <% end %> - <%= if @prev_page_path do %> - " class="button button-secondary button-small float-right"> - <%= gettext("Back") %> - - <% end %> + <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", prev_page_path: @prev_page_path, next_page_path: @next_page_path, cur_page_number: @cur_page_number, show_pagination_limit: true %>

    <%= gettext "Addresses" %>

    @@ -23,25 +14,16 @@ <%= Cldr.Number.to_string!(@cur_page_number, format: "#,###)") %>

    - +
    <%= for {{address, tx_count}, index} <- Enum.with_index(@address_tx_count_pairs, 1) do %> <%= render "_tile.html", address: address, index: index, exchange_rate: @exchange_rate, total_supply: @total_supply, tx_count: tx_count, validation_count: validation_count(address) %> <% end %> -
    - <%= if @next_page_path do %> - " class="button button-secondary button-small float-right mt-0 mb-0 ml-1"> - <%= gettext("Next") %> - - <% end %> - <%= if @prev_page_path do %> - " class="button button-secondary button-small float-right mt-0 mb-0"> - <%= gettext("Back") %> - - <% end %> - +
    + + <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", prev_page_path: @prev_page_path, next_page_path: @next_page_path, cur_page_number: @cur_page_number, show_pagination_limit: true %>
    diff --git a/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination.html.eex deleted file mode 100644 index 84ab89ee80..0000000000 --- a/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination.html.eex +++ /dev/null @@ -1,9 +0,0 @@ - \ No newline at end of file diff --git a/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex new file mode 100644 index 0000000000..18db2182ed --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex @@ -0,0 +1,52 @@ + \ No newline at end of file From cee0d68d2b41224b079b6ec4c3d437759e516b7e Mon Sep 17 00:00:00 2001 From: Gabriel Rodriguez Alsina Date: Fri, 10 May 2019 16:31:30 -0300 Subject: [PATCH 102/191] (add) pagination component to transactions and blocks sections. --- .../assets/css/components/_card.scss | 2 +- .../css/components/_pagination_container.scss | 14 ++++++++++++-- .../templates/address/index.html.eex | 4 ++-- .../templates/block/index.html.eex | 18 ++++++++++++++---- .../pending_transaction/index.html.eex | 9 +++++++++ .../templates/transaction/index.html.eex | 7 +++++++ 6 files changed, 45 insertions(+), 9 deletions(-) diff --git a/apps/block_scout_web/assets/css/components/_card.scss b/apps/block_scout_web/assets/css/components/_card.scss index 2e2cba08a9..4c34e4a31b 100644 --- a/apps/block_scout_web/assets/css/components/_card.scss +++ b/apps/block_scout_web/assets/css/components/_card.scss @@ -67,7 +67,7 @@ $card-background-1-text-color: #fff !default; } .card-subtitle { - color: #aaa; + color: #333; font-size: 12px; font-weight: normal; line-height: 1.2; diff --git a/apps/block_scout_web/assets/css/components/_pagination_container.scss b/apps/block_scout_web/assets/css/components/_pagination_container.scss index 0ff6d96335..a97b338c29 100644 --- a/apps/block_scout_web/assets/css/components/_pagination_container.scss +++ b/apps/block_scout_web/assets/css/components/_pagination_container.scss @@ -17,6 +17,10 @@ $pagination-page-link-color-active: #fff !default; display: flex; justify-content: space-between; + @include media-breakpoint-down(sm) { + flex-direction: column; + } + &.position-bottom { padding-top: 30px; } @@ -33,6 +37,10 @@ $pagination-page-link-color-active: #fff !default; font-weight: 600; line-height: 1.2; + @include media-breakpoint-down(sm) { + margin-bottom: 15px; + } + select { margin: 0 10px; } @@ -43,7 +51,7 @@ $pagination-page-link-color-active: #fff !default; padding: 0; .page-item { - margin: 0 10px 0 0; + margin: 0 5px 0 0; &:last-child { margin-right: 0; @@ -69,9 +77,11 @@ $pagination-page-link-color-active: #fff !default; font-weight: 600; height: 24px; margin: 0; - padding: 0 10px; + padding: 0 8px; position: relative; user-select: none; + text-align: center; + white-space: nowrap; &:not(.no-hover):hover { @include pagination-container-base($pagination-page-link-background-active, $pagination-page-link-color-active); diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex index 7a0c24a5d7..080102d2c9 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/index.html.eex @@ -1,8 +1,6 @@
    - <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", prev_page_path: @prev_page_path, next_page_path: @next_page_path, cur_page_number: @cur_page_number, show_pagination_limit: true %> -

    <%= gettext "Addresses" %>

    <%= gettext "Showing " %> @@ -14,6 +12,8 @@ <%= Cldr.Number.to_string!(@cur_page_number, format: "#,###)") %>

    + <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", prev_page_path: @prev_page_path, next_page_path: @next_page_path, cur_page_number: @cur_page_number, show_pagination_limit: true %> +
    <%= for {{address, tx_count}, index} <- Enum.with_index(@address_tx_count_pairs, 1) do %> <%= render "_tile.html", diff --git a/apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex index 3a832e45a0..43941ca359 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/block/index.html.eex @@ -6,7 +6,11 @@ <%= gettext "Connection Lost, click to load newer blocks" %>
    +

    <%= gettext("%{block_type}s", block_type: @block_type) %>

    + + <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", prev_page_path: "#", next_page_path: "#", cur_page_number: "1", show_pagination_limit: true %> +
    @@ -18,10 +22,15 @@
    <%= gettext "There are no blocks." %>
    -
    - + + <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", prev_page_path: "#", next_page_path: "#", cur_page_number: "1", show_pagination_limit: true %> + + + +
    diff --git a/apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex index cbd3b28eca..361d459179 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/pending_transaction/index.html.eex @@ -7,6 +7,9 @@ <%= Cldr.Number.to_string!(@pending_transaction_count, format: "#,###") %> <%= gettext("Pending Transactions") %>

    + + <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", prev_page_path: "#", next_page_path: "#", cur_page_number: "1", show_pagination_limit: true %> +
    <%= gettext "More transactions have come in" %> @@ -33,9 +36,15 @@ <%= gettext("Loading") %>...
    + + <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", prev_page_path: "#", next_page_path: "#", cur_page_number: "1", show_pagination_limit: true %> + + +
    diff --git a/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex index ee7890af6a..6f33bcf854 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/common_components/_pagination_container.html.eex @@ -1,5 +1,6 @@
    <%= if assigns[:show_pagination_limit] do %> +
    <%= gettext "Show" %>