From 8a1d20b1c86883a5d21dee0a1c2ed0a606d55c24 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 6 Aug 2019 13:20:05 +0300 Subject: [PATCH 01/20] add POA emission rewards importer --- .../lib/explorer/chain_spec/poa/importer.ex | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 apps/explorer/lib/explorer/chain_spec/poa/importer.ex diff --git a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex new file mode 100644 index 0000000000..45e18e6d1c --- /dev/null +++ b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex @@ -0,0 +1,79 @@ +defmodule Explorer.ChainSpec.POA.Importer do + @moduledoc """ + Imports emission reward range for POA chain. + """ + + alias Explorer.Chain.Wei + alias Explorer.Repo + alias Explorer.SmartContract.Reader + alias Explorer.Chain.Block.{EmissionReward, Range} + + @reward_by_block_contract_address "0xeca443e8e1ab29971a45a9c57a6a9875701698a5" + @block_reward_amount_abi %{ + "type" => "function", + "stateMutability" => "view", + "payable" => false, + "outputs" => [%{"type" => "uint256", "name" => ""}], + "name" => "blockRewardAmount", + "inputs" => [], + "constant" => true + } + @block_reward_amount_params %{"blockRewardAmount" => []} + @emission_funds_amount_abi %{ + "type" => "function", + "stateMutability" => "view", + "payable" => false, + "outputs" => [%{"type" => "uint256", "name" => ""}], + "name" => "emissionFundsAmount", + "inputs" => [], + "constant" => true + } + @emission_funds_amount_params %{"emissionFundsAmount" => []} + @emission_funds_block_start 5_098_087 + + def import_emission_rewards do + block_reward = block_reward_amount() + emission_funds = emission_funds_amount() + + rewards = [ + %{ + block_range: %Range{from: 0, to: @emission_funds_block_start}, + reward: %Wei{value: block_reward} + }, + %{ + block_range: %Range{from: @emission_funds_block_start + 1, to: :infinity}, + reward: %Wei{value: Decimal.add(block_reward, emission_funds)} + } + ] + + {_, nil} = Repo.delete_all(EmissionReward) + {_, nil} = Repo.insert_all(EmissionReward, rewards) + end + + def block_reward_amount do + call_contract(@reward_by_block_contract_address, @block_reward_amount_abi, @block_reward_amount_params) + end + + def emission_funds_amount do + call_contract(@reward_by_block_contract_address, @emission_funds_amount_abi, @emission_funds_amount_params) + end + + defp call_contract(address, abi, params) do + abi = [abi] + + method_name = + params + |> Enum.map(fn {key, _value} -> key end) + |> List.first() + + Reader.query_contract(address, abi, params) + + value = + case Reader.query_contract(address, abi, params) do + %{^method_name => {:ok, [result]}} -> result + _ -> 0 + end + + Decimal.new(value) + end +end From dd2a8116452d14e862b6d55d7c13fdcb4ee042a2 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 16 Aug 2019 16:17:07 +0300 Subject: [PATCH 02/20] add verification submission comment --- .../templates/address_contract/index.html.eex | 2 +- .../views/address_contract_view.ex | 9 +++++--- apps/explorer/lib/explorer/chain.ex | 22 +++++++++++++++++-- .../lib/explorer/chain/smart_contract.ex | 22 +++++++++++++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex index e8d6501e02..0b2f4f7574 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex @@ -66,7 +66,7 @@
-
<%= for {line, number} <- contract_lines_with_index(@address.smart_contract.contract_source_code) do %>
<%= line %>
<% end %>
+
<%= for {line, number} <- contract_lines_with_index(@address.smart_contract) do %>
<%= line %>
<% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex index 57c6e11da7..0ad32985c4 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex @@ -2,7 +2,7 @@ defmodule BlockScoutWeb.AddressContractView do use BlockScoutWeb, :view alias ABI.{FunctionSelector, TypeDecoder} - alias Explorer.Chain.{Address, Data, InternalTransaction} + alias Explorer.Chain.{Address, Data, InternalTransaction, SmartContract} def render("scripts.html", %{conn: conn}) do render_scripts(conn, "address_contract/code_highlighting.js") @@ -63,8 +63,11 @@ defmodule BlockScoutWeb.AddressContractView do end) end - def contract_lines_with_index(contract_source_code) do - contract_lines = String.split(contract_source_code, "\n") + def contract_lines_with_index(contract_contract) do + contract_lines = + contract_contract.contract_source_code + |> String.split("\n") + |> SmartContract.add_submitted_comment(contract_contract.inserted_at) max_digits = contract_lines diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 58253c0f27..979e5975a8 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -2532,8 +2532,26 @@ defmodule Explorer.Chain do @spec address_hash_to_address_with_source_code(Hash.Address.t()) :: Address.t() | nil def address_hash_to_address_with_source_code(address_hash) do case Repo.get(Address, address_hash) do - nil -> nil - address -> Repo.preload(address, [:smart_contract, :decompiled_smart_contracts]) + nil -> + nil + + address -> + address_with_smart_contract = Repo.preload(address, [:smart_contract, :decompiled_smart_contracts]) + + if address_with_smart_contract.smart_contract do + formatted_code = + SmartContract.add_submitted_comment( + address_with_smart_contract.smart_contract.contract_source_code, + address_with_smart_contract.smart_contract.inserted_at + ) + + %{ + address_with_smart_contract + | smart_contract: %{address_with_smart_contract.smart_contract | contract_source_code: formatted_code} + } + else + address_with_smart_contract + end end end diff --git a/apps/explorer/lib/explorer/chain/smart_contract.ex b/apps/explorer/lib/explorer/chain/smart_contract.ex index ed579e8e00..e11e8a6d78 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract.ex @@ -271,6 +271,28 @@ defmodule Explorer.Chain.SmartContract do |> add_error(:contract_source_code, error_message(error)) end + def add_submitted_comment(code, inserted_at) when is_binary(code) do + code + |> String.split("\n") + |> add_submitted_commet(inserted_at) + |> Enum.join("\n") + end + + def add_submitted_comment(contract_lines, inserted_at) when is_list(contract_lines) do + index = + Enum.find(contract_lines, fn line -> + String.contains?(line, "Submitted for verification at Etherscan.io") + end) + + if index do + List.replace_at(contract_lines, index, "* Submitted for verification at blockscout.com") + else + header = ["/**", "* Submitted for verification at blockscout.com on #{inserted_at}", "*/"] + + header ++ contract_lines + end + end + defp upsert_contract_methods(%Ecto.Changeset{changes: %{abi: abi}} = changeset) do ContractMethod.upsert_from_abi(abi, get_field(changeset, :address_hash)) From 5d035b9a0256efdc41ea4f949c62eeb9dfc2094a Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 16 Aug 2019 16:21:33 +0300 Subject: [PATCH 03/20] fix typo --- apps/explorer/lib/explorer/chain/smart_contract.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/explorer/lib/explorer/chain/smart_contract.ex b/apps/explorer/lib/explorer/chain/smart_contract.ex index e11e8a6d78..7a88110f71 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract.ex @@ -274,7 +274,7 @@ defmodule Explorer.Chain.SmartContract do def add_submitted_comment(code, inserted_at) when is_binary(code) do code |> String.split("\n") - |> add_submitted_commet(inserted_at) + |> add_submitted_comment(inserted_at) |> Enum.join("\n") end From 01ab9a5a317efb6d3bc96c68c0cba4506a35406f Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 16 Aug 2019 16:22:53 +0300 Subject: [PATCH 04/20] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f006769dbf..a58616d9bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Current ### Features +- [#1588](https://github.com/poanetwork/blockscout/pull/2588) - add verification submission comment - [#2561](https://github.com/poanetwork/blockscout/pull/2561) - Add token's type to the response of tokenlist method - [#2499](https://github.com/poanetwork/blockscout/pull/2499) - import emission reward ranges - [#2497](https://github.com/poanetwork/blockscout/pull/2497) - Add generic Ordered Cache behaviour and implementation From c15c9bd70565c54f1502c514fd1cb3b7391f7a34 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Fri, 16 Aug 2019 16:40:55 +0300 Subject: [PATCH 05/20] fix tests --- .../templates/address_contract/index.html.eex | 2 +- .../views/address_contract_view.ex | 6 +-- .../views/address_contract_view_test.exs | 47 ++++++++++++------- .../lib/explorer/chain/smart_contract.ex | 2 +- 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex index 0b2f4f7574..1e98048169 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex @@ -66,7 +66,7 @@
-
<%= for {line, number} <- contract_lines_with_index(@address.smart_contract) do %>
<%= line %>
<% end %>
+
<%= for {line, number} <- contract_lines_with_index(@address.smart_contract.contract_source_code, @address.smart_contract.inserted_at) do %>
<%= line %>
<% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex index 0ad32985c4..f9128dfb11 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/address_contract_view.ex @@ -63,11 +63,11 @@ defmodule BlockScoutWeb.AddressContractView do end) end - def contract_lines_with_index(contract_contract) do + def contract_lines_with_index(source_code, inserted_at \\ nil) do contract_lines = - contract_contract.contract_source_code + source_code |> String.split("\n") - |> SmartContract.add_submitted_comment(contract_contract.inserted_at) + |> SmartContract.add_submitted_comment(inserted_at) max_digits = contract_lines diff --git a/apps/block_scout_web/test/block_scout_web/views/address_contract_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/address_contract_view_test.exs index 4bcb1eb2bf..9f0314fb88 100644 --- a/apps/block_scout_web/test/block_scout_web/views/address_contract_view_test.exs +++ b/apps/block_scout_web/test/block_scout_web/views/address_contract_view_test.exs @@ -38,22 +38,25 @@ defmodule BlockScoutWeb.AddressContractViewTest do result = AddressContractView.contract_lines_with_index(code) assert result == [ - {"pragma solidity >=0.4.22 <0.6.0;", " 1"}, - {"", " 2"}, - {"struct Proposal {", " 3"}, - {" uint voteCount;", " 4"}, - {"}", " 5"}, - {"", " 6"}, - {"address chairperson;", " 7"}, - {"mapping(address => Voter) voters;", " 8"}, - {"Proposal[] proposals;", " 9"}, - {"", "10"}, - {"constructor(uint8 _numProposals) public {", "11"}, - {" chairperson = msg.sender;", "12"}, - {" voters[chairperson].weight = 1;", "13"}, - {" proposals.length = _numProposals;", "14"}, - {"}", "15"}, - {"", "16"} + {"/**", " 1"}, + {"* Submitted for verification at blockscout.com on ", " 2"}, + {"*/", " 3"}, + {"pragma solidity >=0.4.22 <0.6.0;", " 4"}, + {"", " 5"}, + {"struct Proposal {", " 6"}, + {" uint voteCount;", " 7"}, + {"}", " 8"}, + {"", " 9"}, + {"address chairperson;", "10"}, + {"mapping(address => Voter) voters;", "11"}, + {"Proposal[] proposals;", "12"}, + {"", "13"}, + {"constructor(uint8 _numProposals) public {", "14"}, + {" chairperson = msg.sender;", "15"}, + {" voters[chairperson].weight = 1;", "16"}, + {" proposals.length = _numProposals;", "17"}, + {"}", "18"}, + {"", "19"} ] end @@ -66,7 +69,17 @@ defmodule BlockScoutWeb.AddressContractViewTest do test "returns a list of tuples and the first element is just a line from the original string" do result = AddressContractView.contract_lines_with_index("a\nb\nc\nd\ne") - assert Enum.map(result, fn {line, _number} -> line end) == ["a", "b", "c", "d", "e"] + + assert Enum.map(result, fn {line, _number} -> line end) == [ + "/**", + "* Submitted for verification at blockscout.com on ", + "*/", + "a", + "b", + "c", + "d", + "e" + ] end end end diff --git a/apps/explorer/lib/explorer/chain/smart_contract.ex b/apps/explorer/lib/explorer/chain/smart_contract.ex index 7a88110f71..bbddd51100 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract.ex @@ -285,7 +285,7 @@ defmodule Explorer.Chain.SmartContract do end) if index do - List.replace_at(contract_lines, index, "* Submitted for verification at blockscout.com") + List.replace_at(contract_lines, index, "* Submitted for verification at blockscout.com on #{inserted_at}") else header = ["/**", "* Submitted for verification at blockscout.com on #{inserted_at}", "*/"] From cb3cc8eb65bcd942cc0a9deaa47248838e42d5c6 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 19 Aug 2019 10:54:01 +0300 Subject: [PATCH 06/20] fix api/rpc/contract_controller_test --- .../api/rpc/contract_controller_test.exs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) 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 e070cf8e57..af9daffed8 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 @@ -1,6 +1,6 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do use BlockScoutWeb.ConnCase - alias Explorer.Factory + alias Explorer.{Chain, Factory} describe "listcontracts" do setup do @@ -422,7 +422,9 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do expected_result = [ %{ "Address" => to_string(contract.address_hash), - "SourceCode" => contract.contract_source_code, + "SourceCode" => + "/**\n* Submitted for verification at blockscout.com on #{contract.inserted_at}\n*/\n" <> + contract.contract_source_code, "ABI" => Jason.encode!(contract.abi), "ContractName" => contract.name, "CompilerVersion" => contract.compiler_version, @@ -467,9 +469,13 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do |> get("/api", params) |> json_response(200) + verified_contract = Chain.address_hash_to_smart_contract(contract_address.hash) + expected_result = %{ "Address" => to_string(contract_address.hash), - "SourceCode" => contract_code_info.source_code, + "SourceCode" => + "/**\n* Submitted for verification at blockscout.com on #{verified_contract.inserted_at}\n*/\n" <> + contract_code_info.source_code, "ABI" => Jason.encode!(contract_code_info.abi), "ContractName" => contract_code_info.name, "CompilerVersion" => contract_code_info.version, @@ -533,8 +539,14 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do result = response["result"] + verified_contract = Chain.address_hash_to_smart_contract(contract_address.hash) + assert result["Address"] == to_string(contract_address.hash) - assert result["SourceCode"] == contract_source_code + + assert result["SourceCode"] == + "/**\n* Submitted for verification at blockscout.com on #{verified_contract.inserted_at}\n*/\n" <> + contract_source_code + assert result["ContractName"] == name assert result["DecompiledSourceCode"] == "Contract source code not decompiled." assert result["DecompilerVersion"] == "" From e73280aafcc5e561d03307f66ad2802e9c38086a Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 19 Aug 2019 14:48:36 +0300 Subject: [PATCH 07/20] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a58616d9bb..203f2dcce1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## Current ### Features -- [#1588](https://github.com/poanetwork/blockscout/pull/2588) - add verification submission comment +- [#2588](https://github.com/poanetwork/blockscout/pull/2588) - add verification submission comment - [#2561](https://github.com/poanetwork/blockscout/pull/2561) - Add token's type to the response of tokenlist method - [#2499](https://github.com/poanetwork/blockscout/pull/2499) - import emission reward ranges - [#2497](https://github.com/poanetwork/blockscout/pull/2497) - Add generic Ordered Cache behaviour and implementation From f9676bc04833c735df3558b422a657fdf7821d23 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 19 Aug 2019 15:13:34 +0300 Subject: [PATCH 08/20] integrate poa emission rewards to supervision tree --- apps/explorer/config/config.exs | 6 +++++- .../lib/explorer/chain_spec/parity/importer.ex | 18 ++++++++++++++---- .../lib/explorer/chain_spec/poa/importer.ex | 9 ++++++--- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index 95c80ba445..e4ba8ef577 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -27,7 +27,11 @@ config :explorer, Explorer.Counters.AverageBlockTime, enabled: true, period: average_block_period -config :explorer, Explorer.ChainSpec.GenesisData, enabled: true, chain_spec_path: System.get_env("CHAIN_SPEC_PATH") +config :explorer, Explorer.ChainSpec.GenesisData, + enabled: true, + chain_spec_path: System.get_env("CHAIN_SPEC_PATH"), + emission_format: System.get_env("EMISSION_FORMAT", "DEFAULT"), + rewards_contract_address: System.get_env("REWARDS_CONTRACT_ADDRESS", "0xeca443e8e1ab29971a45a9c57a6a9875701698a5") config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: true diff --git a/apps/explorer/lib/explorer/chain_spec/parity/importer.ex b/apps/explorer/lib/explorer/chain_spec/parity/importer.ex index 6b560bf530..620acfb934 100644 --- a/apps/explorer/lib/explorer/chain_spec/parity/importer.ex +++ b/apps/explorer/lib/explorer/chain_spec/parity/importer.ex @@ -7,14 +7,17 @@ defmodule Explorer.ChainSpec.Parity.Importer do alias Explorer.Chain.Block.{EmissionReward, Range} alias Explorer.Chain.Hash.Address, as: AddressHash alias Explorer.Chain.Wei + alias Explorer.ChainSpec.GenesisData + alias Explorer.ChainSpec.POA.Importer, as: PoaEmissionImporter @max_block_number :infinity def import_emission_rewards(chain_spec) do - rewards = emission_rewards(chain_spec) - - {_, nil} = Repo.delete_all(EmissionReward) - {_, nil} = Repo.insert_all(EmissionReward, rewards) + if Application.get_env(:explorer, GenesisData)[:emission_format] == "POA" do + PoaEmissionImporter.import_emission_rewards() + else + import_rewards_from_chain_spec(chain_spec) + end end def import_genesis_coin_balances(chain_spec) do @@ -38,6 +41,13 @@ defmodule Explorer.ChainSpec.Parity.Importer do Chain.import(params) end + defp import_rewards_from_chain_spec(chain_spec) do + rewards = emission_rewards(chain_spec) + + {_, nil} = Repo.delete_all(EmissionReward) + {_, nil} = Repo.insert_all(EmissionReward, rewards) + end + def genesis_coin_balances(chain_spec) do accounts = chain_spec["accounts"] diff --git a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex index 45e18e6d1c..80d2c23696 100644 --- a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex +++ b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex @@ -8,7 +8,6 @@ defmodule Explorer.ChainSpec.POA.Importer do alias Explorer.SmartContract.Reader alias Explorer.Chain.Block.{EmissionReward, Range} - @reward_by_block_contract_address "0xeca443e8e1ab29971a45a9c57a6a9875701698a5" @block_reward_amount_abi %{ "type" => "function", "stateMutability" => "view", @@ -51,11 +50,15 @@ defmodule Explorer.ChainSpec.POA.Importer do end def block_reward_amount do - call_contract(@reward_by_block_contract_address, @block_reward_amount_abi, @block_reward_amount_params) + call_contract(rewards_contract_address(), @block_reward_amount_abi, @block_reward_amount_params) end def emission_funds_amount do - call_contract(@reward_by_block_contract_address, @emission_funds_amount_abi, @emission_funds_amount_params) + call_contract(rewards_contract_address(), @emission_funds_amount_abi, @emission_funds_amount_params) + end + + defp rewards_contract_address do + Application.get_env(:explorer, GenesisData)[:rewards_contract_address] end defp call_contract(address, abi, params) do From e76400aa5816b26a47b21ad92625d1b6d641e06a Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 19 Aug 2019 15:14:03 +0300 Subject: [PATCH 09/20] add env vars --- docs/env-variables.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/env-variables.md b/docs/env-variables.md index 60c9eee442..83d0de41ab 100644 --- a/docs/env-variables.md +++ b/docs/env-variables.md @@ -54,6 +54,8 @@ $ export NETWORK=POA | `LINK_TO_OTHER_EXPLORERS` | | true/false. If true, links to other explorers are added in the footer | (empty) | v1.3.0+ | | `COINMARKETCAP_PAGES` | | the number of pages on coinmarketcap to list in order to find token's price | 10 | v1.3.10+ | | `CHAIN_SPEC_PATH` | | Chain specification path (absolute file system path or url) to import block emission reward ranges and genesis account balances from | (empty) | master | +| `EMISSION_FORMAT` | | Should be set to `POA` if you have block emission indentical to POA Network. This env var is used only if `CHAIN_SPEC_PATH` is set | `STANDARD` | master +| `REWARDS_CONTRACT_ADDRESS` | | Emission rewards contract address. This env var is used only if `EMISSION_FORMAT` is set to `POA` | `0xeca443e8e1ab29971a45a9c57a6a9875701698a5` | master | `SUPPORTED_CHAINS` | | Array of supported chains that displays in the footer and in the chains dropdown. This var was introduced in this PR [#1900](https://github.com/poanetwork/blockscout/pull/1900) and looks like an array of JSON objects. | (empty) | v2.0.0+ | | `BLOCK_COUNT_CACHE_PERIOD ` | | time to live of cache in seconds. This var was introduced in [#1876](https://github.com/poanetwork/blockscout/pull/1876) | 600 | v2.0.0+ | | `ALLOWED_EVM_VERSIONS ` | | the comma-separated list of allowed EVM versions for contracts verification. This var was introduced in [#1964](https://github.com/poanetwork/blockscout/pull/1964) | "homestead, tangerineWhistle, spuriousDragon, byzantium, constantinople, petersburg" | v2.0.0+ | From f3f72fdf6c9c54cd360ca4d2c3089c9dd8782ae2 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 19 Aug 2019 15:24:20 +0300 Subject: [PATCH 10/20] fix POA Importer --- .../lib/explorer/chain_spec/poa/importer.ex | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex index 80d2c23696..154d904703 100644 --- a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex +++ b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex @@ -7,6 +7,7 @@ defmodule Explorer.ChainSpec.POA.Importer do alias Explorer.Repo alias Explorer.SmartContract.Reader alias Explorer.Chain.Block.{EmissionReward, Range} + alias Explorer.ChainSpec.GenesisData @block_reward_amount_abi %{ "type" => "function", @@ -34,16 +35,17 @@ defmodule Explorer.ChainSpec.POA.Importer do block_reward = block_reward_amount() emission_funds = emission_funds_amount() - rewards = [ - %{ - block_range: %Range{from: 0, to: @emission_funds_block_start}, - reward: %Wei{value: block_reward} - }, - %{ - block_range: %Range{from: @emission_funds_block_start + 1, to: :infinity}, - reward: %Wei{value: Decimal.add(block_reward, emission_funds)} - } - ] + rewards = + [ + %{ + block_range: %Range{from: 0, to: @emission_funds_block_start}, + reward: %Wei{value: block_reward} + }, + %{ + block_range: %Range{from: @emission_funds_block_start + 1, to: :infinity}, + reward: %Wei{value: Decimal.add(block_reward, emission_funds)} + } + ] {_, nil} = Repo.delete_all(EmissionReward) {_, nil} = Repo.insert_all(EmissionReward, rewards) From 7b174fad2ea767e46c81a3ab5091bc8644d648e6 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 19 Aug 2019 15:25:56 +0300 Subject: [PATCH 11/20] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f006769dbf..167578e6a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Current ### Features +- [#2505](https://github.com/poanetwork/blockscout/pull/2505) - support POA Network emission rewards - [#2561](https://github.com/poanetwork/blockscout/pull/2561) - Add token's type to the response of tokenlist method - [#2499](https://github.com/poanetwork/blockscout/pull/2499) - import emission reward ranges - [#2497](https://github.com/poanetwork/blockscout/pull/2497) - Add generic Ordered Cache behaviour and implementation From e51efc5e062c6c65b626718ea7943698fca4afca Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 19 Aug 2019 15:53:10 +0300 Subject: [PATCH 12/20] mix format --- .../lib/explorer/chain_spec/poa/importer.ex | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex index 154d904703..d731f08aa6 100644 --- a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex +++ b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex @@ -35,17 +35,16 @@ defmodule Explorer.ChainSpec.POA.Importer do block_reward = block_reward_amount() emission_funds = emission_funds_amount() - rewards = - [ - %{ - block_range: %Range{from: 0, to: @emission_funds_block_start}, - reward: %Wei{value: block_reward} - }, - %{ - block_range: %Range{from: @emission_funds_block_start + 1, to: :infinity}, - reward: %Wei{value: Decimal.add(block_reward, emission_funds)} - } - ] + rewards = [ + %{ + block_range: %Range{from: 0, to: @emission_funds_block_start}, + reward: %Wei{value: block_reward} + }, + %{ + block_range: %Range{from: @emission_funds_block_start + 1, to: :infinity}, + reward: %Wei{value: Decimal.add(block_reward, emission_funds)} + } + ] {_, nil} = Repo.delete_all(EmissionReward) {_, nil} = Repo.insert_all(EmissionReward, rewards) From c58723f641a63ae1e7eb6200a9c50e2e251131c9 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 20 Aug 2019 15:27:56 +0300 Subject: [PATCH 13/20] do not try to parse data if there is none --- .../lib/explorer/chain_spec/parity/importer.ex | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/explorer/lib/explorer/chain_spec/parity/importer.ex b/apps/explorer/lib/explorer/chain_spec/parity/importer.ex index 620acfb934..8c3527d9e4 100644 --- a/apps/explorer/lib/explorer/chain_spec/parity/importer.ex +++ b/apps/explorer/lib/explorer/chain_spec/parity/importer.ex @@ -51,15 +51,23 @@ defmodule Explorer.ChainSpec.Parity.Importer do def genesis_coin_balances(chain_spec) do accounts = chain_spec["accounts"] - parse_accounts(accounts) + if accounts do + parse_accounts(accounts) + else + Logger.warn(fn -> "No accounts are defined in chain spec" end) + end end def emission_rewards(chain_spec) do rewards = chain_spec["engine"]["Ethash"]["params"]["blockReward"] - rewards - |> parse_hex_numbers() - |> format_ranges() + if rewards do + rewards + |> parse_hex_numbers() + |> format_ranges() + else + Logger.warn(fn -> "No rewards are defined in chain spec" end) + end end defp parse_accounts(accounts) do From c6b0a86c0b836ea558b85857fa43475d5366e391 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 20 Aug 2019 15:31:06 +0300 Subject: [PATCH 14/20] require logger --- apps/explorer/lib/explorer/chain_spec/poa/importer.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex index d731f08aa6..00d54a3d74 100644 --- a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex +++ b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex @@ -3,6 +3,8 @@ defmodule Explorer.ChainSpec.POA.Importer do Imports emission reward range for POA chain. """ + require Logger + alias Explorer.Chain.Wei alias Explorer.Repo alias Explorer.SmartContract.Reader From 44ac58116ff458e2d431c9e308fd02aa68c48445 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 20 Aug 2019 15:36:25 +0300 Subject: [PATCH 15/20] add logger to poa rewards importer --- .../explorer/chain_spec/parity/importer.ex | 2 ++ .../lib/explorer/chain_spec/poa/importer.ex | 32 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/apps/explorer/lib/explorer/chain_spec/parity/importer.ex b/apps/explorer/lib/explorer/chain_spec/parity/importer.ex index 8c3527d9e4..a1f620ec6c 100644 --- a/apps/explorer/lib/explorer/chain_spec/parity/importer.ex +++ b/apps/explorer/lib/explorer/chain_spec/parity/importer.ex @@ -3,6 +3,8 @@ defmodule Explorer.ChainSpec.Parity.Importer do Imports data from parity chain spec. """ + require Logger + alias Explorer.{Chain, Repo} alias Explorer.Chain.Block.{EmissionReward, Range} alias Explorer.Chain.Hash.Address, as: AddressHash diff --git a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex index 00d54a3d74..03935d85b2 100644 --- a/apps/explorer/lib/explorer/chain_spec/poa/importer.ex +++ b/apps/explorer/lib/explorer/chain_spec/poa/importer.ex @@ -34,22 +34,26 @@ defmodule Explorer.ChainSpec.POA.Importer do @emission_funds_block_start 5_098_087 def import_emission_rewards do - block_reward = block_reward_amount() - emission_funds = emission_funds_amount() + if is_nil(rewards_contract_address()) do + Logger.warn(fn -> "No rewards contract address is defined" end) + else + block_reward = block_reward_amount() + emission_funds = emission_funds_amount() - rewards = [ - %{ - block_range: %Range{from: 0, to: @emission_funds_block_start}, - reward: %Wei{value: block_reward} - }, - %{ - block_range: %Range{from: @emission_funds_block_start + 1, to: :infinity}, - reward: %Wei{value: Decimal.add(block_reward, emission_funds)} - } - ] + rewards = [ + %{ + block_range: %Range{from: 0, to: @emission_funds_block_start}, + reward: %Wei{value: block_reward} + }, + %{ + block_range: %Range{from: @emission_funds_block_start + 1, to: :infinity}, + reward: %Wei{value: Decimal.add(block_reward, emission_funds)} + } + ] - {_, nil} = Repo.delete_all(EmissionReward) - {_, nil} = Repo.insert_all(EmissionReward, rewards) + {_, nil} = Repo.delete_all(EmissionReward) + {_, nil} = Repo.insert_all(EmissionReward, rewards) + end end def block_reward_amount do From a89f96944eed7911406a7c39b0f8f80f605230df Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 28 Aug 2019 10:25:57 +0300 Subject: [PATCH 16/20] update env-vars doc file --- docs/env-variables.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/env-variables.md b/docs/env-variables.md index e79dd4473f..8a1165839f 100644 --- a/docs/env-variables.md +++ b/docs/env-variables.md @@ -54,8 +54,8 @@ $ export NETWORK=POA | `LINK_TO_OTHER_EXPLORERS` | | true/false. If true, links to other explorers are added in the footer | (empty) | v1.3.0+ | | `COINMARKETCAP_PAGES` | | the number of pages on coinmarketcap to list in order to find token's price | 10 | v1.3.10+ | | `CHAIN_SPEC_PATH` | | Chain specification path (absolute file system path or url) to import block emission reward ranges and genesis account balances from | (empty) | master | -| `EMISSION_FORMAT` | | Should be set to `POA` if you have block emission indentical to POA Network. This env var is used only if `CHAIN_SPEC_PATH` is set | `STANDARD` | master -| `REWARDS_CONTRACT_ADDRESS` | | Emission rewards contract address. This env var is used only if `EMISSION_FORMAT` is set to `POA` | `0xeca443e8e1ab29971a45a9c57a6a9875701698a5` | master +| `EMISSION_FORMAT` | | Should be set to `POA` if you have block emission indentical to POA Network. This env var is used only if `CHAIN_SPEC_PATH` is set | `STANDARD` | master | +| `REWARDS_CONTRACT_ADDRESS` | | Emission rewards contract address. This env var is used only if `EMISSION_FORMAT` is set to `POA` | `0xeca443e8e1ab29971a45a9c57a6a9875701698a5` | master | | `SUPPORTED_CHAINS` | | Array of supported chains that displays in the footer and in the chains dropdown. This var was introduced in this PR [#1900](https://github.com/poanetwork/blockscout/pull/1900) and looks like an array of JSON objects. | (empty) | v2.0.0+ | | `BLOCK_COUNT_CACHE_PERIOD ` | | time to live of cache in seconds. This var was introduced in [#1876](https://github.com/poanetwork/blockscout/pull/1876) | 600 | v2.0.0+ | | `ALLOWED_EVM_VERSIONS ` | | the comma-separated list of allowed EVM versions for contracts verification. This var was introduced in [#1964](https://github.com/poanetwork/blockscout/pull/1964) | "homestead, tangerineWhistle, spuriousDragon, byzantium, constantinople, petersburg" | v2.0.0+ | From 4b9ef3dad3580fe529b60a01be716ab7a9d2476f Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 28 Aug 2019 11:18:19 +0300 Subject: [PATCH 17/20] parse decimal data from genesis chain spec --- .../lib/explorer/chain_spec/parity/importer.ex | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/explorer/lib/explorer/chain_spec/parity/importer.ex b/apps/explorer/lib/explorer/chain_spec/parity/importer.ex index a1f620ec6c..fa16ee0739 100644 --- a/apps/explorer/lib/explorer/chain_spec/parity/importer.ex +++ b/apps/explorer/lib/explorer/chain_spec/parity/importer.ex @@ -57,6 +57,8 @@ defmodule Explorer.ChainSpec.Parity.Importer do parse_accounts(accounts) else Logger.warn(fn -> "No accounts are defined in chain spec" end) + + [] end end @@ -69,6 +71,8 @@ defmodule Explorer.ChainSpec.Parity.Importer do |> format_ranges() else Logger.warn(fn -> "No rewards are defined in chain spec" end) + + [] end end @@ -79,7 +83,7 @@ defmodule Explorer.ChainSpec.Parity.Importer do end) |> Stream.map(fn {address, %{"balance" => value}} -> {:ok, address_hash} = AddressHash.cast(address) - balance = parse_hex_number(value) + balance = parse_number(value) %{address_hash: address_hash, value: balance} end) @@ -112,16 +116,22 @@ defmodule Explorer.ChainSpec.Parity.Importer do defp parse_hex_numbers(rewards) do Enum.map(rewards, fn {hex_block_number, hex_reward} -> - block_number = parse_hex_number(hex_block_number) - {:ok, reward} = hex_reward |> parse_hex_number() |> Wei.cast() + block_number = parse_number(hex_block_number) + {:ok, reward} = hex_reward |> parse_number() |> Wei.cast() {block_number, reward} end) end - defp parse_hex_number("0x" <> hex_number) do + defp parse_number("0x" <> hex_number) do {number, ""} = Integer.parse(hex_number, 16) number end + + defp parse_number(string_number) do + {number, ""} = Integer.parse(string_number, 10) + + number + end end From f28e866f8fd766d91bb8d6d63a8f42214d5c2e9d Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 2 Sep 2019 11:27:45 +0300 Subject: [PATCH 18/20] check if blockscout comment is already added --- .../lib/explorer/chain/smart_contract.ex | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/smart_contract.ex b/apps/explorer/lib/explorer/chain/smart_contract.ex index bbddd51100..a3c198c642 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract.ex @@ -279,17 +279,34 @@ defmodule Explorer.Chain.SmartContract do end def add_submitted_comment(contract_lines, inserted_at) when is_list(contract_lines) do - index = + etherscan_index = Enum.find(contract_lines, fn line -> String.contains?(line, "Submitted for verification at Etherscan.io") end) - if index do - List.replace_at(contract_lines, index, "* Submitted for verification at blockscout.com on #{inserted_at}") - else - header = ["/**", "* Submitted for verification at blockscout.com on #{inserted_at}", "*/"] + blockscout_index = + Enum.find(contract_lines, fn line -> + String.contains?(line, "Submitted for verification at blockscout.com") + end) + + cond do + etherscan_index && blockscout_index -> + List.replace_at(contract_lines, etherscan_index, "*") + + etherscan_index && !blockscout_index -> + List.replace_at( + contract_lines, + etherscan_index, + "* Submitted for verification at blockscout.com on #{inserted_at}" + ) + + !etherscan_index && !blockscout_index -> + header = ["/**", "* Submitted for verification at blockscout.com on #{inserted_at}", "*/"] + + header ++ contract_lines - header ++ contract_lines + true -> + contract_lines end end From 327b762528f5fbffb478ee5aead16c276725eef4 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 3 Sep 2019 12:56:38 +0300 Subject: [PATCH 19/20] find index of the comment instead of item --- apps/explorer/lib/explorer/chain/smart_contract.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/smart_contract.ex b/apps/explorer/lib/explorer/chain/smart_contract.ex index a3c198c642..0db7d7e613 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract.ex @@ -280,12 +280,12 @@ defmodule Explorer.Chain.SmartContract do def add_submitted_comment(contract_lines, inserted_at) when is_list(contract_lines) do etherscan_index = - Enum.find(contract_lines, fn line -> + Enum.find_index(contract_lines, fn line -> String.contains?(line, "Submitted for verification at Etherscan.io") end) blockscout_index = - Enum.find(contract_lines, fn line -> + Enum.find_index(contract_lines, fn line -> String.contains?(line, "Submitted for verification at blockscout.com") end) From c856a5926096ee644d12ab5ade22eec339b0c217 Mon Sep 17 00:00:00 2001 From: saneery Date: Wed, 21 Aug 2019 14:52:38 +0300 Subject: [PATCH 20/20] Add caches updating independently from Indexer --- CHANGELOG.md | 1 + apps/explorer/config/config.exs | 13 +++++- apps/explorer/lib/explorer/application.ex | 4 +- .../lib/explorer/chain/cache/block_number.ex | 4 +- .../lib/explorer/chain/cache/blocks.ex | 4 +- .../lib/explorer/chain/cache/transactions.ex | 4 +- .../lib/explorer/chain/ordered_cache.ex | 42 +++++++++++++++---- .../chain/cache/block_number_test.exs | 6 +-- 8 files changed, 61 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f347667b27..4d8ddf8ca0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - [#2497](https://github.com/poanetwork/blockscout/pull/2497) - Add generic Ordered Cache behaviour and implementation ### Fixes +- [#2612](https://github.com/poanetwork/blockscout/pull/2612) - Add cache updating independently from Indexer - [#2659](https://github.com/poanetwork/blockscout/pull/2659) - Multipurpose front-end part update - [#2468](https://github.com/poanetwork/blockscout/pull/2468) - fix confirmations for non consensus blocks - [#2610](https://github.com/poanetwork/blockscout/pull/2610) - use CoinGecko instead of CoinMarketcap for exchange rates diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index 10e8a66e82..e118362b40 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -29,7 +29,10 @@ config :explorer, Explorer.Counters.AverageBlockTime, config :explorer, Explorer.ChainSpec.GenesisData, enabled: false, chain_spec_path: System.get_env("CHAIN_SPEC_PATH") -config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: true +config :explorer, Explorer.Chain.Cache.BlockNumber, + enabled: true, + ttl_check_interval: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(1), else: false), + global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5)) config :explorer, Explorer.ExchangeRates.Source.CoinGecko, coin_id: System.get_env("COIN_GECKO_ID", "poa-network") @@ -123,6 +126,14 @@ market_history_cache_period = config :explorer, Explorer.Market.MarketHistoryCache, period: market_history_cache_period +config :explorer, Explorer.Chain.Cache.Blocks, + ttl_check_interval: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(1), else: false), + global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5)) + +config :explorer, Explorer.Chain.Cache.Transactions, + ttl_check_interval: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(1), else: false), + global_ttl: if(System.get_env("DISABLE_INDEXER") == "true", do: :timer.seconds(5)) + # 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 1bd2778762..7c55d28f76 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -56,9 +56,7 @@ defmodule Explorer.Application do opts = [strategy: :one_for_one, name: Explorer.Supervisor] - res = Supervisor.start_link(children, opts) - - res + Supervisor.start_link(children, opts) end defp configurable_children do diff --git a/apps/explorer/lib/explorer/chain/cache/block_number.ex b/apps/explorer/lib/explorer/chain/cache/block_number.ex index d19551fa59..fb5f1b515a 100644 --- a/apps/explorer/lib/explorer/chain/cache/block_number.ex +++ b/apps/explorer/lib/explorer/chain/cache/block_number.ex @@ -7,7 +7,9 @@ defmodule Explorer.Chain.Cache.BlockNumber do use Explorer.Chain.MapCache, name: :block_number, - keys: [:min, :max] + keys: [:min, :max], + ttl_check_interval: Application.get_env(:explorer, __MODULE__)[:ttl_check_interval], + global_ttl: Application.get_env(:explorer, __MODULE__)[:global_ttl] alias Explorer.Chain diff --git a/apps/explorer/lib/explorer/chain/cache/blocks.ex b/apps/explorer/lib/explorer/chain/cache/blocks.ex index 4a18646d37..d2a5b47061 100644 --- a/apps/explorer/lib/explorer/chain/cache/blocks.ex +++ b/apps/explorer/lib/explorer/chain/cache/blocks.ex @@ -11,7 +11,9 @@ defmodule Explorer.Chain.Cache.Blocks do ids_list_key: "block_numbers", preload: :transactions, preload: [miner: :names], - preload: :rewards + preload: :rewards, + ttl_check_interval: Application.get_env(:explorer, __MODULE__)[:ttl_check_interval], + global_ttl: Application.get_env(:explorer, __MODULE__)[:global_ttl] @type element :: Block.t() diff --git a/apps/explorer/lib/explorer/chain/cache/transactions.ex b/apps/explorer/lib/explorer/chain/cache/transactions.ex index 7dee7ec87d..e9b8a40a9e 100644 --- a/apps/explorer/lib/explorer/chain/cache/transactions.ex +++ b/apps/explorer/lib/explorer/chain/cache/transactions.ex @@ -16,7 +16,9 @@ defmodule Explorer.Chain.Cache.Transactions do token_transfers: :token, token_transfers: :from_address, token_transfers: :to_address - ] + ], + ttl_check_interval: Application.get_env(:explorer, __MODULE__)[:ttl_check_interval], + global_ttl: Application.get_env(:explorer, __MODULE__)[:global_ttl] @type element :: Transaction.t() diff --git a/apps/explorer/lib/explorer/chain/ordered_cache.ex b/apps/explorer/lib/explorer/chain/ordered_cache.ex index 2a1c0fc689..5365fe0f76 100644 --- a/apps/explorer/lib/explorer/chain/ordered_cache.ex +++ b/apps/explorer/lib/explorer/chain/ordered_cache.ex @@ -26,7 +26,10 @@ defmodule Explorer.Chain.OrderedCache do preload: [transaction: :hash] ``` Additionally all of the options accepted by `ConCache.start_link/1` can be - provided as well. By default only `ttl_check_interval:` is set (to `false`). + provided as well. Unless specified, only these values have defaults: + - `:ttl_check_interval` is set (to `false`). + - `:callback` is only set if `:ttl_check_interval` is not `false` to call the + `remove_deleted_from_index` function, that removes expired values from the index. It's also possible, and advised, to override the implementation of the `c:prevails?/2` and `c:element_to_id/1` callbacks. @@ -131,10 +134,7 @@ defmodule Explorer.Chain.OrderedCache do max_size = Keyword.get(opts, :max_size, 100) preloads = Keyword.get(opts, :preloads) || Keyword.get_values(opts, :preload) - concache_params = - opts - |> Keyword.drop([:ids_list_key, :max_size, :preloads, :preload]) - |> Keyword.put_new(:ttl_check_interval, false) + concache_params = Keyword.drop(opts, [:ids_list_key, :max_size, :preloads, :preload]) # credo:disable-for-next-line Credo.Check.Refactor.LongQuoteBlocks quote do @@ -206,6 +206,19 @@ defmodule Explorer.Chain.OrderedCache do ### Updating function + def remove_deleted_from_index({:delete, _cache_pid, id}) do + # simply check with `ConCache.get` because it is faster + if Enum.member?(ids_list(), id) do + ConCache.update(cache_name(), ids_list_key(), fn ids -> + updated_list = List.delete(ids || [], id) + # ids_list is set to never expire + {:ok, %ConCache.Item{value: updated_list, ttl: :infinity}} + end) + end + end + + def remove_deleted_from_index(_), do: nil + @impl OrderedCache def update(elements) when is_nil(elements), do: :ok @@ -217,7 +230,8 @@ defmodule Explorer.Chain.OrderedCache do |> Enum.sort(&prevails?(&1, &2)) |> merge_and_update(ids || [], max_size()) - {:ok, updated_list} + # ids_list is set to never expire + {:ok, %ConCache.Item{value: updated_list, ttl: :infinity}} end) end @@ -308,7 +322,21 @@ defmodule Explorer.Chain.OrderedCache do provided to this function will override the ones set by using the macro """ def child_spec(params) do - params = Keyword.merge(unquote(concache_params), params) + # params specified in `use` + merged_params = + unquote(concache_params) + # params specified in `child_spec` + |> Keyword.merge(params) + # `:ttl_check_interval` needs to be specified, defaults to `false` + |> Keyword.put_new(:ttl_check_interval, false) + + # if `:ttl_check_interval` is not `false` the expired values need to be + # removed from the cache's index + params = + case merged_params[:ttl_check_interval] do + false -> merged_params + _ -> Keyword.put_new(merged_params, :callback, &remove_deleted_from_index/1) + end Supervisor.child_spec({ConCache, params}, id: child_id()) end diff --git a/apps/explorer/test/explorer/chain/cache/block_number_test.exs b/apps/explorer/test/explorer/chain/cache/block_number_test.exs index 64170695eb..87107fe45c 100644 --- a/apps/explorer/test/explorer/chain/cache/block_number_test.exs +++ b/apps/explorer/test/explorer/chain/cache/block_number_test.exs @@ -11,7 +11,7 @@ defmodule Explorer.Chain.Cache.BlockNumberTest do end) end - describe "get_max/1" do + describe "get_max/0" do test "returns max number" do insert(:block, number: 5) @@ -19,7 +19,7 @@ defmodule Explorer.Chain.Cache.BlockNumberTest do end end - describe "get_min/1" do + describe "get_min/0" do test "returns min number" do insert(:block, number: 2) @@ -27,7 +27,7 @@ defmodule Explorer.Chain.Cache.BlockNumberTest do end end - describe "get_all/1" do + describe "get_all/0" do test "returns min and max number" do insert(:block, number: 6)