Merge pull request #8742 from blockscout/mf-merge-rsk-into-main

Merge rsk branch into the master branch
ap-main-page-event-handler
Victor Baranov 12 months ago committed by GitHub
commit abce79ed49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 71
      .github/workflows/config.yml
  2. 1
      CHANGELOG.md
  3. 16
      apps/block_scout_web/lib/block_scout_web/views/api/v2/block_view.ex
  4. 6
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex
  5. 96
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block.ex
  6. 12
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/blocks.ex
  7. 17
      apps/ethereum_jsonrpc/test/ethereum_jsonrpc/block_test.exs
  8. 1
      apps/explorer/config/config.exs
  9. 60
      apps/explorer/lib/explorer/chain/block.ex
  10. 13
      apps/explorer/priv/rsk/migrations/20230724094744_add_rootstock_fields_to_blocks.exs
  11. 170
      apps/indexer/lib/indexer/fetcher/rootstock_data.ex
  12. 2
      apps/indexer/lib/indexer/supervisor.ex
  13. 136
      apps/indexer/test/indexer/fetcher/rootstock_data_test.exs
  14. 17
      apps/indexer/test/support/indexer/fetcher/rootstock_data_supervisor_case.ex
  15. 3
      config/config_helper.exs
  16. 29
      config/runtime.exs
  17. 5
      docker-compose/envs/common-blockscout.env

@ -27,11 +27,23 @@ on:
env:
MIX_ENV: test
OTP_VERSION: '25.2.1'
ELIXIR_VERSION: '1.14.5'
ACCOUNT_AUTH0_DOMAIN: 'blockscoutcom.us.auth0.com'
OTP_VERSION: "25.2.1"
ELIXIR_VERSION: "1.14.5"
ACCOUNT_AUTH0_DOMAIN: "blockscoutcom.us.auth0.com"
jobs:
matrix-builder:
name: Build matrix
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- id: set-matrix
run: |
echo "matrix=$matrixStringifiedObject" >> $GITHUB_OUTPUT
env:
matrixStringifiedObject: '{"chain-type": ["ethereum", "polygon_edge", "polygon_zkevm", "rsk", "suave", "stability"]}'
build-and-cache:
name: Build and Cache deps
runs-on: ubuntu-latest
@ -142,10 +154,16 @@ jobs:
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
- run: mix format --check-formatted
dialyzer:
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }}
name: Dialyzer static analysis
runs-on: ubuntu-latest
needs: build-and-cache
needs:
- build-and-cache
- matrix-builder
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
@ -169,18 +187,22 @@ jobs:
id: dialyzer-cache
with:
path: priv/plts
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-mixlockhash_25-${{ hashFiles('mix.lock') }}
key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-${{ matrix.chain-type }}-dialyzer-mixlockhash_25-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-"
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-${{ matrix.chain-type }}-dialyzer-"
- name: Conditionally build Dialyzer Cache
if: steps.dialyzer-cache.output.cache-hit != 'true'
run: |
mkdir -p priv/plts
mix dialyzer --plt
env:
CHAIN_TYPE: ${{ matrix.chain-type }}
- name: Run Dialyzer
run: mix dialyzer --halt-exit-status
env:
CHAIN_TYPE: ${{ matrix.chain-type }}
gettext:
name: Missing translation keys check
@ -370,9 +392,14 @@ jobs:
working-directory: apps/block_scout_web/assets
test_nethermind_mox_ethereum_jsonrpc:
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }}
name: EthereumJSONRPC Tests
runs-on: ubuntu-latest
needs: build-and-cache
needs:
- build-and-cache
- matrix-builder
services:
postgres:
image: postgres
@ -423,10 +450,16 @@ jobs:
PGUSER: postgres
ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox"
ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox"
CHAIN_TYPE: "${{ matrix.chain-type }}"
test_nethermind_mox_explorer:
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }}
name: Explorer Tests
runs-on: ubuntu-latest
needs: build-and-cache
needs:
- build-and-cache
- matrix-builder
services:
postgres:
image: postgres
@ -488,10 +521,16 @@ jobs:
PGUSER: postgres
ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox"
ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox"
CHAIN_TYPE: "${{ matrix.chain-type }}"
test_nethermind_mox_indexer:
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }}
name: Indexer Tests
runs-on: ubuntu-latest
needs: build-and-cache
needs:
- build-and-cache
- matrix-builder
services:
postgres:
image: postgres
@ -529,7 +568,6 @@ jobs:
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
- run: ./bin/install_chrome_headless.sh
- name: mix test --exclude no_nethermind
@ -546,14 +584,19 @@ jobs:
PGUSER: postgres
ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox"
ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox"
CHAIN_TYPE: "${{ matrix.chain-type }}"
test_nethermind_mox_block_scout_web:
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }}
name: Blockscout Web Tests
runs-on: ubuntu-latest
needs: build-and-cache
needs:
- build-and-cache
- matrix-builder
services:
redis_db:
image: 'redis:alpine'
image: "redis:alpine"
ports:
- 6379:6379
@ -593,7 +636,6 @@ jobs:
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
- name: Restore Explorer NPM Cache
uses: actions/cache@v2
id: explorer-npm-cache
@ -638,3 +680,4 @@ jobs:
ACCOUNT_ENABLED: "true"
ACCOUNT_REDIS_URL: "redis://localhost:6379"
SOURCIFY_INTEGRATION_ENABLED: "true"
CHAIN_TYPE: "${{ matrix.chain-type }}"

@ -27,6 +27,7 @@
- [#8832](https://github.com/blockscout/blockscout/pull/8832) - Log more details in regards 413 error
- [#8802](https://github.com/blockscout/blockscout/pull/8802) - Enable API v2 by default
- [#8742](https://github.com/blockscout/blockscout/pull/8742) - Merge rsk branch into the master branch
- [#8728](https://github.com/blockscout/blockscout/pull/8728) - Remove repos_list (default value for ecto repos) from Explorer.ReleaseTasks
<details>

@ -61,6 +61,7 @@ defmodule BlockScoutWeb.API.V2.BlockView do
"tx_fees" => tx_fees,
"withdrawals_count" => count_withdrawals(block)
}
|> chain_type_fields(block, single_block?)
end
def prepare_rewards(rewards, block, single_block?) do
@ -115,4 +116,19 @@ defmodule BlockScoutWeb.API.V2.BlockView do
def count_withdrawals(%Block{withdrawals: withdrawals}) when is_list(withdrawals), do: Enum.count(withdrawals)
def count_withdrawals(_), do: nil
defp chain_type_fields(result, block, single_block?) do
case single_block? && Application.get_env(:explorer, :chain_type) do
"rsk" ->
result
|> Map.put("minimum_gas_price", block.minimum_gas_price)
|> Map.put("bitcoin_merged_mining_header", block.bitcoin_merged_mining_header)
|> Map.put("bitcoin_merged_mining_coinbase_transaction", block.bitcoin_merged_mining_coinbase_transaction)
|> Map.put("bitcoin_merged_mining_merkle_proof", block.bitcoin_merged_mining_merkle_proof)
|> Map.put("hash_for_merged_mining", block.hash_for_merged_mining)
_ ->
result
end
end
end

@ -277,12 +277,12 @@ defmodule EthereumJSONRPC do
@doc """
Fetches blocks by block number list.
"""
@spec fetch_blocks_by_numbers([block_number()], json_rpc_named_arguments) ::
@spec fetch_blocks_by_numbers([block_number()], json_rpc_named_arguments, boolean()) ::
{:ok, Blocks.t()} | {:error, reason :: term}
def fetch_blocks_by_numbers(block_numbers, json_rpc_named_arguments) do
def fetch_blocks_by_numbers(block_numbers, json_rpc_named_arguments, with_transactions? \\ true) do
block_numbers
|> Enum.map(fn number -> %{number: number} end)
|> fetch_blocks_by_params(&Block.ByNumber.request/1, json_rpc_named_arguments)
|> fetch_blocks_by_params(&Block.ByNumber.request(&1, with_transactions?), json_rpc_named_arguments)
end
@doc """

@ -8,8 +8,23 @@ defmodule EthereumJSONRPC.Block do
alias EthereumJSONRPC.{Transactions, Uncles, Withdrawals}
if Application.compile_env(:explorer, :chain_type) == "rsk" do
@rootstock_fields quote(
do: [
bitcoin_merged_mining_header: EthereumJSONRPC.data(),
bitcoin_merged_mining_coinbase_transaction: EthereumJSONRPC.data(),
bitcoin_merged_mining_merkle_proof: EthereumJSONRPC.data(),
hash_for_merged_mining: EthereumJSONRPC.data(),
minimum_gas_price: non_neg_integer()
]
)
else
@rootstock_fields quote(do: [])
end
@type elixir :: %{String.t() => non_neg_integer | DateTime.t() | String.t() | nil}
@type params :: %{
unquote_splicing(@rootstock_fields),
difficulty: pos_integer(),
extra_data: EthereumJSONRPC.hash(),
gas_limit: non_neg_integer(),
@ -69,6 +84,15 @@ defmodule EthereumJSONRPC.Block do
`t:EthereumJSONRPC.hash/0`.
* `"baseFeePerGas"` - `t:EthereumJSONRPC.quantity/0` of wei to denote amount of fee burned per unit gas used. Introduced in [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md)
* `"withdrawalsRoot"` - `t:EthereumJSONRPC.hash/0` of the root of the withdrawals.
#{if Application.compile_env(:explorer, :chain_type) == "rsk" do
"""
* `"minimumGasPrice"` - `t:EthereumJSONRPC.quantity/0` of the minimum gas price for this block.
* `"bitcoinMergedMiningHeader"` - `t:EthereumJSONRPC.data/0` of the Bitcoin merged mining header.
* `"bitcoinMergedMiningCoinbaseTransaction"` - `t:EthereumJSONRPC.data/0` of the Bitcoin merged mining coinbase transaction.
* `"bitcoinMergedMiningMerkleProof"` - `t:EthereumJSONRPC.data/0` of the Bitcoin merged mining merkle proof.
* `"hashForMergedMining"` - `t:EthereumJSONRPC.data/0` of the hash for merged mining.
"""
end}
"""
@type t :: %{String.t() => EthereumJSONRPC.data() | EthereumJSONRPC.hash() | EthereumJSONRPC.quantity() | nil}
@ -119,7 +143,17 @@ defmodule EthereumJSONRPC.Block do
...> "timestamp" => Timex.parse!("2017-12-15T21:03:30Z", "{ISO:Extended:Z}"),
...> "totalDifficulty" => 340282366920938463463374607431465668165,
...> "transactions" => [],
...> "transactionsRoot" => "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
...> "transactionsRoot" => "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",\
#{if Application.compile_env(:explorer, :chain_type) == "rsk" do
"""
...> "minimumGasPrice" => 345786,
...> "bitcoinMergedMiningHeader" => "0x00006d20ffd048280094a6ea0851d854036aacaa25ee0f23f0040200000000000000000078d2638fe0b4477c54601e6449051afba8228e0a88ff06b0c91f091fd34d5da57487c76402610517372c2fe9",
...> "bitcoinMergedMiningCoinbaseTransaction" => "0x00000000000000805bf0dc9203da49a3b4e3ec913806e43102cc07db991272dc8b7018da57eb5abe59a32d070000ffffffff03449a4d26000000001976a914536ffa992491508dca0354e52f32a3a7a679a53a88ac00000000000000002b6a2952534b424c4f434b3ad2508d21d28c8f89d495923c0758ec3f64bd6755b4ec416f5601312600542a400000000000000000266a24aa21a9ed4ae42ea6dca2687aaed665714bf58b055c4e11f2fb038605930d630b49ad7b9d00000000",
...> "bitcoinMergedMiningMerkleProof" => "0x8e5a4ba74eb4eb2f9ad4cabc2913aeed380a5becf7cd4d513341617efb798002bd83a783c31c66a8a8f6cc56c071c2d471cb610e3dc13054b9d216021d8c7e9112f622564449ebedcedf7d4ccb6fe0ffac861b7ed1446c310813cdf712e1e6add28b1fe1c0ae5e916194ba4f285a9340aba41e91bf847bf31acf37a9623a04a2348a37ab9faa5908122db45596bbc03e9c3644b0d4589471c4ff30fc139f3ba50506e9136fa0df799b487494de3e2b3dec937338f1a2e18da057c1f60590a9723672a4355b9914b1d01af9f582d9e856f6e1744be00f268b0b01d559329f7e0685aa63ffeb7c28486d7462292021d1345cddbf7c920ca34bb7aa4c6cdbe068806e35d0db662e7fcda03cb4d779594638c62a1fdd7ec98d1fb6d240d853958abe57561d9b9d0465cf8b9d6ee3c58b0d8b07d6c4c5d8f348e43fe3c06011b6a0008db4e0b16c77ececc3981f9008201cea5939869d648e59a09bd2094b1196ff61126bffb626153deed2563e1745436247c94a85d2947756b606d67633781c99d7",
...> "hashForMergedMining" => "0xd2508d21d28c8f89d495923c0758ec3f64bd6755b4ec416f5601312600542a40",\
"""
end}
...> "uncles" => []
...> }
...> )
@ -142,7 +176,17 @@ defmodule EthereumJSONRPC.Block do
timestamp: Timex.parse!("2017-12-15T21:03:30Z", "{ISO:Extended:Z}"),
total_difficulty: 340282366920938463463374607431465668165,
transactions_root: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
uncles: [],
uncles: [],\
#{if Application.compile_env(:explorer, :chain_type) == "rsk" do
"""
bitcoin_merged_mining_coinbase_transaction: "0x00000000000000805bf0dc9203da49a3b4e3ec913806e43102cc07db991272dc8b7018da57eb5abe59a32d070000ffffffff03449a4d26000000001976a914536ffa992491508dca0354e52f32a3a7a679a53a88ac00000000000000002b6a2952534b424c4f434b3ad2508d21d28c8f89d495923c0758ec3f64bd6755b4ec416f5601312600542a400000000000000000266a24aa21a9ed4ae42ea6dca2687aaed665714bf58b055c4e11f2fb038605930d630b49ad7b9d00000000",
bitcoin_merged_mining_header: "0x00006d20ffd048280094a6ea0851d854036aacaa25ee0f23f0040200000000000000000078d2638fe0b4477c54601e6449051afba8228e0a88ff06b0c91f091fd34d5da57487c76402610517372c2fe9",
bitcoin_merged_mining_merkle_proof: "0x8e5a4ba74eb4eb2f9ad4cabc2913aeed380a5becf7cd4d513341617efb798002bd83a783c31c66a8a8f6cc56c071c2d471cb610e3dc13054b9d216021d8c7e9112f622564449ebedcedf7d4ccb6fe0ffac861b7ed1446c310813cdf712e1e6add28b1fe1c0ae5e916194ba4f285a9340aba41e91bf847bf31acf37a9623a04a2348a37ab9faa5908122db45596bbc03e9c3644b0d4589471c4ff30fc139f3ba50506e9136fa0df799b487494de3e2b3dec937338f1a2e18da057c1f60590a9723672a4355b9914b1d01af9f582d9e856f6e1744be00f268b0b01d559329f7e0685aa63ffeb7c28486d7462292021d1345cddbf7c920ca34bb7aa4c6cdbe068806e35d0db662e7fcda03cb4d779594638c62a1fdd7ec98d1fb6d240d853958abe57561d9b9d0465cf8b9d6ee3c58b0d8b07d6c4c5d8f348e43fe3c06011b6a0008db4e0b16c77ececc3981f9008201cea5939869d648e59a09bd2094b1196ff61126bffb626153deed2563e1745436247c94a85d2947756b606d67633781c99d7",
hash_for_merged_mining: "0xd2508d21d28c8f89d495923c0758ec3f64bd6755b4ec416f5601312600542a40",
minimum_gas_price: 345786,\
"""
end}
withdrawals_root: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}
@ -191,13 +235,28 @@ defmodule EthereumJSONRPC.Block do
timestamp: Timex.parse!("2015-07-30T15:32:07Z", "{ISO:Extended:Z}"),
total_difficulty: 1039309006117,
transactions_root: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
uncles: [],
uncles: [],\
#{if Application.compile_env(:explorer, :chain_type) == "rsk" do
"""
bitcoin_merged_mining_coinbase_transaction: nil,
bitcoin_merged_mining_header: nil,
bitcoin_merged_mining_merkle_proof: nil,
hash_for_merged_mining: nil,
minimum_gas_price: nil,\
"""
end}
withdrawals_root: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}
"""
@spec elixir_to_params(elixir) :: params
def elixir_to_params(
def elixir_to_params(elixir) do
elixir
|> do_elixir_to_params()
|> chain_type_fields(elixir)
end
defp do_elixir_to_params(
%{
"difficulty" => difficulty,
"extraData" => extra_data,
@ -245,7 +304,7 @@ defmodule EthereumJSONRPC.Block do
}
end
def elixir_to_params(
defp do_elixir_to_params(
%{
"difficulty" => difficulty,
"extraData" => extra_data,
@ -291,7 +350,7 @@ defmodule EthereumJSONRPC.Block do
}
end
def elixir_to_params(
defp do_elixir_to_params(
%{
"difficulty" => difficulty,
"extraData" => extra_data,
@ -338,7 +397,7 @@ defmodule EthereumJSONRPC.Block do
end
# Geth: a response from eth_getblockbyhash for uncle blocks is without `totalDifficulty` param
def elixir_to_params(
defp do_elixir_to_params(
%{
"difficulty" => difficulty,
"extraData" => extra_data,
@ -382,6 +441,23 @@ defmodule EthereumJSONRPC.Block do
}
end
defp chain_type_fields(params, elixir) do
case Application.get_env(:explorer, :chain_type) do
"rsk" ->
params
|> Map.merge(%{
minimum_gas_price: Map.get(elixir, "minimumGasPrice"),
bitcoin_merged_mining_header: Map.get(elixir, "bitcoinMergedMiningHeader"),
bitcoin_merged_mining_coinbase_transaction: Map.get(elixir, "bitcoinMergedMiningCoinbaseTransaction"),
bitcoin_merged_mining_merkle_proof: Map.get(elixir, "bitcoinMergedMiningMerkleProof"),
hash_for_merged_mining: Map.get(elixir, "hashForMergedMining")
})
_ ->
params
end
end
@doc """
Get `t:EthereumJSONRPC.Transactions.elixir/0` from `t:elixir/0`
@ -685,7 +761,7 @@ defmodule EthereumJSONRPC.Block do
end
defp entry_to_elixir({key, quantity}, _block)
when key in ~w(difficulty gasLimit gasUsed minimumGasPrice baseFeePerGas number size cumulativeDifficulty totalDifficulty paidFees) and
when key in ~w(difficulty gasLimit gasUsed minimumGasPrice baseFeePerGas number size cumulativeDifficulty totalDifficulty paidFees minimumGasPrice) and
not is_nil(quantity) do
{key, quantity_to_integer(quantity)}
end
@ -700,7 +776,7 @@ defmodule EthereumJSONRPC.Block do
# hash format
defp entry_to_elixir({key, _} = entry, _block)
when key in ~w(author extraData hash logsBloom miner mixHash nonce parentHash receiptsRoot sealFields sha3Uncles
signature stateRoot step transactionsRoot uncles withdrawalsRoot),
signature stateRoot step transactionsRoot uncles withdrawalsRoot bitcoinMergedMiningHeader bitcoinMergedMiningCoinbaseTransaction bitcoinMergedMiningMerkleProof hashForMergedMining),
do: entry
defp entry_to_elixir({"timestamp" = key, timestamp}, _block) do

@ -116,7 +116,17 @@ defmodule EthereumJSONRPC.Blocks do
timestamp: Timex.parse!("1970-01-01T00:00:00Z", "{ISO:Extended:Z}"),
total_difficulty: 131072,
transactions_root: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
uncles: ["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273311"],
uncles: ["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273311"],\
#{if Application.compile_env(:explorer, :chain_type) == "rsk" do
"""
bitcoin_merged_mining_coinbase_transaction: nil,
bitcoin_merged_mining_header: nil,
bitcoin_merged_mining_merkle_proof: nil,
hash_for_merged_mining: nil,
minimum_gas_price: nil,\
"""
end}
withdrawals_root: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}
]

@ -32,7 +32,8 @@ defmodule EthereumJSONRPC.BlockTest do
"uncles" => []
})
assert result == %{
assert result ==
%{
difficulty: 17_561_410_778,
extra_data: "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32",
gas_limit: 5000,
@ -55,6 +56,20 @@ defmodule EthereumJSONRPC.BlockTest do
uncles: [],
withdrawals_root: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}
|> (&if(Application.get_env(:explorer, :chain_type) == "rsk",
do:
Map.merge(
&1,
%{
bitcoin_merged_mining_coinbase_transaction: nil,
bitcoin_merged_mining_header: nil,
bitcoin_merged_mining_merkle_proof: nil,
hash_for_merged_mining: nil,
minimum_gas_price: nil
}
),
else: &1
)).()
end
end

@ -11,6 +11,7 @@ import Config
# General application configuration
config :explorer,
chain_type: ConfigHelper.chain_type(),
ecto_repos: ConfigHelper.repos(),
token_functions_reader_max_retries: 3,
# for not fully indexed blockchains

@ -11,6 +11,14 @@ defmodule Explorer.Chain.Block do
alias Explorer.Chain.Block.{Reward, SecondDegreeRelation}
@optional_attrs ~w(size refetch_needed total_difficulty difficulty base_fee_per_gas)a
|> (&(case Application.compile_env(:explorer, :chain_type) do
"rsk" ->
&1 ++
~w(minimum_gas_price bitcoin_merged_mining_header bitcoin_merged_mining_coinbase_transaction bitcoin_merged_mining_merkle_proof hash_for_merged_mining)a
_ ->
&1
end)).()
@required_attrs ~w(consensus gas_limit gas_used hash miner_hash nonce number parent_hash timestamp)a
@ -26,6 +34,20 @@ defmodule Explorer.Chain.Block do
"""
@type block_number :: non_neg_integer()
if Application.compile_env(:explorer, :chain_type) == "rsk" do
@rootstock_fields quote(
do: [
bitcoin_merged_mining_header: binary(),
bitcoin_merged_mining_coinbase_transaction: binary(),
bitcoin_merged_mining_merkle_proof: binary(),
hash_for_merged_mining: binary(),
minimum_gas_price: Decimal.t()
]
)
else
@rootstock_fields quote(do: [])
end
@typedoc """
* `consensus`
* `true` - this is a block on the longest consensus agreed upon chain.
@ -47,8 +69,18 @@ defmodule Explorer.Chain.Block do
* `total_difficulty` - the total `difficulty` of the chain until this block.
* `transactions` - the `t:Explorer.Chain.Transaction.t/0` in this block.
* `base_fee_per_gas` - Minimum fee required per unit of gas. Fee adjusts based on network congestion.
#{if Application.compile_env(:explorer, :chain_type) == "rsk" do
"""
* `bitcoin_merged_mining_header` - Bitcoin merged mining header on Rootstock chains.
* `bitcoin_merged_mining_coinbase_transaction` - Bitcoin merged mining coinbase transaction on Rootstock chains.
* `bitcoin_merged_mining_merkle_proof` - Bitcoin merged mining merkle proof on Rootstock chains.
* `hash_for_merged_mining` - Hash for merged mining on Rootstock chains.
* `minimum_gas_price` - Minimum block gas price on Rootstock chains.
"""
end}
"""
@type t :: %__MODULE__{
unquote_splicing(@rootstock_fields),
consensus: boolean(),
difficulty: difficulty(),
gas_limit: Gas.t(),
@ -83,6 +115,14 @@ defmodule Explorer.Chain.Block do
field(:base_fee_per_gas, Wei)
field(:is_empty, :boolean)
if Application.compile_env(:explorer, :chain_type) == "rsk" do
field(:bitcoin_merged_mining_header, :binary)
field(:bitcoin_merged_mining_coinbase_transaction, :binary)
field(:bitcoin_merged_mining_merkle_proof, :binary)
field(:hash_for_merged_mining, :binary)
field(:minimum_gas_price, :decimal)
end
timestamps()
belongs_to(:miner, Address, foreign_key: :miner_hash, references: :hash, type: Hash.Address)
@ -159,4 +199,24 @@ defmodule Explorer.Chain.Block do
end
def block_type_filter(query, "Uncle"), do: where(query, [block], block.consensus == false)
@doc """
Returns query that fetches up to `limit` of consensus blocks
that are missing rootstock data ordered by number desc.
"""
@spec blocks_without_rootstock_data_query(non_neg_integer()) :: Ecto.Query.t()
def blocks_without_rootstock_data_query(limit) do
from(
block in __MODULE__,
where:
is_nil(block.minimum_gas_price) or
is_nil(block.bitcoin_merged_mining_header) or
is_nil(block.bitcoin_merged_mining_coinbase_transaction) or
is_nil(block.bitcoin_merged_mining_merkle_proof) or
is_nil(block.hash_for_merged_mining),
where: block.consensus == true,
limit: ^limit,
order_by: [desc: block.number]
)
end
end

@ -0,0 +1,13 @@
defmodule Explorer.Repo.RSK.Migrations.AddRootstockFieldsToBlocks do
use Ecto.Migration
def change do
alter table(:blocks) do
add(:minimum_gas_price, :decimal)
add(:bitcoin_merged_mining_header, :bytea)
add(:bitcoin_merged_mining_coinbase_transaction, :bytea)
add(:bitcoin_merged_mining_merkle_proof, :bytea)
add(:hash_for_merged_mining, :bytea)
end
end
end

@ -0,0 +1,170 @@
defmodule Indexer.Fetcher.RootstockData do
@moduledoc """
Refetch `minimum_gas_price`, `bitcoin_merged_mining_header`, `bitcoin_merged_mining_coinbase_transaction`,
`bitcoin_merged_mining_merkle_proof`, `hash_for_merged_mining` fields for blocks that were indexed before app update.
"""
use GenServer
use Indexer.Fetcher
require Logger
alias EthereumJSONRPC.Blocks
alias Explorer.Chain.Block
alias Explorer.Repo
@interval :timer.seconds(3)
@batch_size 10
@concurrency 5
@db_batch_size 300
defstruct blocks_to_fetch: [],
interval: @interval,
json_rpc_named_arguments: [],
batch_size: @batch_size,
max_concurrency: @concurrency,
db_batch_size: @db_batch_size
def child_spec([init_arguments]) do
child_spec([init_arguments, []])
end
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do
default = %{
id: __MODULE__,
start: {__MODULE__, :start_link, start_link_arguments}
}
Supervisor.child_spec(default, restart: :transient)
end
def start_link(arguments, gen_server_options \\ []) do
GenServer.start_link(__MODULE__, arguments, gen_server_options)
end
@impl GenServer
def init(opts) when is_list(opts) do
Logger.metadata(fetcher: :rootstock_data)
json_rpc_named_arguments = opts[:json_rpc_named_arguments]
unless json_rpc_named_arguments do
raise ArgumentError,
":json_rpc_named_arguments must be provided to `#{__MODULE__}.init to allow for json_rpc calls when running."
end
state = %__MODULE__{
blocks_to_fetch: nil,
interval: opts[:interval] || Application.get_env(:indexer, __MODULE__)[:interval],
json_rpc_named_arguments: json_rpc_named_arguments,
batch_size: opts[:batch_size] || Application.get_env(:indexer, __MODULE__)[:batch_size],
max_concurrency: opts[:max_concurrency] || Application.get_env(:indexer, __MODULE__)[:max_concurrency],
db_batch_size: opts[:db_batch_size] || Application.get_env(:indexer, __MODULE__)[:db_batch_size]
}
Process.send_after(self(), :fetch_rootstock_data, state.interval)
{:ok, state, {:continue, :fetch_blocks}}
end
@impl GenServer
def handle_continue(:fetch_blocks, state), do: fetch_blocks(state)
@impl GenServer
def handle_info(:fetch_blocks, state), do: fetch_blocks(state)
@impl GenServer
def handle_info(
:fetch_rootstock_data,
%__MODULE__{
blocks_to_fetch: blocks_to_fetch,
interval: interval,
json_rpc_named_arguments: json_rpc_named_arguments,
batch_size: batch_size,
max_concurrency: concurrency
} = state
) do
if Enum.empty?(blocks_to_fetch) do
send(self(), :fetch_blocks)
{:noreply, state}
else
new_blocks_to_fetch =
blocks_to_fetch
|> Stream.chunk_every(batch_size)
|> Task.async_stream(
&{EthereumJSONRPC.fetch_blocks_by_numbers(
Enum.map(&1, fn b -> b.number end),
json_rpc_named_arguments,
false
), &1},
max_concurrency: concurrency,
timeout: :infinity,
zip_input_on_exit: true
)
|> Enum.reduce([], &fetch_reducer/2)
Process.send_after(self(), :fetch_rootstock_data, interval)
{:noreply, %__MODULE__{state | blocks_to_fetch: new_blocks_to_fetch}}
end
end
def handle_info({ref, _result}, state) do
Process.demonitor(ref, [:flush])
{:noreply, state}
end
def handle_info(
{:DOWN, _ref, :process, _pid, reason},
state
) do
if reason === :normal do
{:noreply, state}
else
Logger.error(fn -> "Rootstock data fetcher task exited due to #{inspect(reason)}." end)
{:noreply, state}
end
end
defp fetch_blocks(%__MODULE__{db_batch_size: db_batch_size, interval: interval} = state) do
blocks_to_fetch = db_batch_size |> Block.blocks_without_rootstock_data_query() |> Repo.all()
if Enum.empty?(blocks_to_fetch) do
Logger.info("Rootstock data from old blocks are fetched.")
{:stop, :normal, state}
else
[%Block{number: max_number} | _] = blocks_to_fetch
Logger.info(
"Rootstock data will now be fetched for #{Enum.count(blocks_to_fetch)} blocks starting from #{max_number}."
)
Process.send_after(self(), :fetch_rootstock_data, interval)
{:noreply, %__MODULE__{state | blocks_to_fetch: blocks_to_fetch}}
end
end
defp fetch_reducer({:ok, {{:ok, %Blocks{blocks_params: block_params}}, blocks}}, acc) do
blocks_map = Map.new(blocks, fn b -> {b.number, b} end)
for block_param <- block_params,
block = blocks_map[block_param.number],
block_param.hash == to_string(block.hash) do
block |> Block.changeset(block_param) |> Repo.update()
end
acc
end
defp fetch_reducer({:ok, {{:error, reason}, blocks}}, acc) do
Logger.error("failed to fetch: " <> inspect(reason) <> ". Retrying.")
[blocks | acc] |> List.flatten()
end
defp fetch_reducer({:exit, {blocks, reason}}, acc) do
Logger.error("failed to fetch: " <> inspect(reason) <> ". Retrying.")
[blocks | acc] |> List.flatten()
end
end

@ -29,6 +29,7 @@ defmodule Indexer.Supervisor do
PendingTransaction,
PolygonEdge,
ReplacedTransaction,
RootstockData,
Token,
TokenBalance,
TokenTotalSupplyUpdater,
@ -153,6 +154,7 @@ defmodule Indexer.Supervisor do
[[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor]]},
{PendingOpsCleaner, [[], []]},
{PendingBlockOperationsSanitizer, [[]]},
{RootstockData.Supervisor, [[json_rpc_named_arguments: json_rpc_named_arguments]]},
# Block fetchers
configure(BlockRealtime.Supervisor, [

@ -0,0 +1,136 @@
defmodule Indexer.Fetcher.RootstockDataTest do
use EthereumJSONRPC.Case
use Explorer.DataCase
import Mox
import EthereumJSONRPC, only: [integer_to_quantity: 1]
alias Indexer.Fetcher.RootstockData
setup :verify_on_exit!
setup :set_mox_global
if Application.compile_env(:explorer, :chain_type) == "rsk" do
test "do not start when all old blocks are fetched", %{json_rpc_named_arguments: json_rpc_named_arguments} do
RootstockData.Supervisor.Case.start_supervised!(json_rpc_named_arguments: json_rpc_named_arguments)
:timer.sleep(300)
assert [{Indexer.Fetcher.RootstockData, :undefined, :worker, [Indexer.Fetcher.RootstockData]} | _] =
RootstockData.Supervisor |> Supervisor.which_children()
end
test "stops when all old blocks are fetched", %{json_rpc_named_arguments: json_rpc_named_arguments} do
block_a = insert(:block)
block_b = insert(:block)
block_a_number_string = integer_to_quantity(block_a.number)
block_b_number_string = integer_to_quantity(block_b.number)
EthereumJSONRPC.Mox
|> stub(:json_rpc, fn requests, _options ->
{:ok,
Enum.map(requests, fn
%{id: id, method: "eth_getBlockByNumber", params: [^block_a_number_string, false]} ->
%{
id: id,
result: %{
"author" => "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c",
"difficulty" => "0x6bc767dd80781",
"extraData" => "0x5050594520737061726b706f6f6c2d6574682d7477",
"gasLimit" => "0x7a121d",
"gasUsed" => "0x79cbe9",
"hash" => to_string(block_a.hash),
"logsBloom" =>
"0x044d42d008801488400e1809190200a80d06105bc0c4100b047895c0d518327048496108388040140010b8208006288102e206160e21052322440924002090c1c808a0817405ab238086d028211014058e949401012403210314896702d06880c815c3060a0f0809987c81044488292cc11d57882c912a808ca10471c84460460040000c0001012804022000a42106591881d34407420ba401e1c08a8d00a000a34c11821a80222818a4102152c8a0c044032080c6462644223104d618e0e544072008120104408205c60510542264808488220403000106281a0290404220112c10b080145028c8000300b18a2c8280701c882e702210b00410834840108084",
"miner" => to_string(block_a.miner),
"mixHash" => "0xda53ae7c2b3c529783d6cdacdb90587fd70eb651c0f04253e8ff17de97844010",
"nonce" => "0x0946e5f01fce12bc",
"number" => block_a_number_string,
"parentHash" => to_string(block_a.parent_hash),
"receiptsRoot" => "0xa7d2b82bd8526de11736c18bd5cc8cfe2692106c4364526f3310ad56d78669c4",
"sealFields" => [
"0xa0da53ae7c2b3c529783d6cdacdb90587fd70eb651c0f04253e8ff17de97844010",
"0x880946e5f01fce12bc"
],
"sha3Uncles" => "0x483a8a21a5825ad270f358b3ea56e060bbb8b3082d9a92ec8fa17a5c7e6fc1b6",
"size" => "0x544c",
"stateRoot" => "0x85daa9cd528004c1609d4cb3520fd958e85983bb4183124a4a9f7137fd39c691",
"timestamp" => "0x5c8bc76e",
"totalDifficulty" => "0x201a42c35142ae94458",
"transactions" => [],
"transactionsRoot" => "0xcd6c12fa43cd4e92ad5c0bf232b30488bbcbfe273c5b4af0366fced0767d54db",
"uncles" => [],
"withdrawals" => [],
"minimumGasPrice" => "0x0",
"bitcoinMergedMiningHeader" =>
"0x00006d20ffd048280094a6ea0851d854036aacaa25ee0f23f0040200000000000000000078d2638fe0b4477c54601e6449051afba8228e0a88ff06b0c91f091fd34d5da57487c76402610517372c2fe9",
"bitcoinMergedMiningCoinbaseTransaction" =>
"0x00000000000000805bf0dc9203da49a3b4e3ec913806e43102cc07db991272dc8b7018da57eb5abe59a32d070000ffffffff03449a4d26000000001976a914536ffa992491508dca0354e52f32a3a7a679a53a88ac00000000000000002b6a2952534b424c4f434b3ad2508d21d28c8f89d495923c0758ec3f64bd6755b4ec416f5601312600542a400000000000000000266a24aa21a9ed4ae42ea6dca2687aaed665714bf58b055c4e11f2fb038605930d630b49ad7b9d00000000",
"bitcoinMergedMiningMerkleProof" =>
"0x8e5a4ba74eb4eb2f9ad4cabc2913aeed380a5becf7cd4d513341617efb798002bd83a783c31c66a8a8f6cc56c071c2d471cb610e3dc13054b9d216021d8c7e9112f622564449ebedcedf7d4ccb6fe0ffac861b7ed1446c310813cdf712e1e6add28b1fe1c0ae5e916194ba4f285a9340aba41e91bf847bf31acf37a9623a04a2348a37ab9faa5908122db45596bbc03e9c3644b0d4589471c4ff30fc139f3ba50506e9136fa0df799b487494de3e2b3dec937338f1a2e18da057c1f60590a9723672a4355b9914b1d01af9f582d9e856f6e1744be00f268b0b01d559329f7e0685aa63ffeb7c28486d7462292021d1345cddbf7c920ca34bb7aa4c6cdbe068806e35d0db662e7fcda03cb4d779594638c62a1fdd7ec98d1fb6d240d853958abe57561d9b9d0465cf8b9d6ee3c58b0d8b07d6c4c5d8f348e43fe3c06011b6a0008db4e0b16c77ececc3981f9008201cea5939869d648e59a09bd2094b1196ff61126bffb626153deed2563e1745436247c94a85d2947756b606d67633781c99d7",
"hashForMergedMining" => "0xd2508d21d28c8f89d495923c0758ec3f64bd6755b4ec416f5601312600542a40"
}
}
%{id: id, method: "eth_getBlockByNumber", params: [^block_b_number_string, false]} ->
%{
id: id,
result: %{
"author" => "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c",
"difficulty" => "0x6bc767dd80781",
"extraData" => "0x5050594520737061726b706f6f6c2d6574682d7477",
"gasLimit" => "0x7a121d",
"gasUsed" => "0x79cbe9",
"hash" => to_string(block_b.hash),
"logsBloom" =>
"0x044d42d008801488400e1809190200a80d06105bc0c4100b047895c0d518327048496108388040140010b8208006288102e206160e21052322440924002090c1c808a0817405ab238086d028211014058e949401012403210314896702d06880c815c3060a0f0809987c81044488292cc11d57882c912a808ca10471c84460460040000c0001012804022000a42106591881d34407420ba401e1c08a8d00a000a34c11821a80222818a4102152c8a0c044032080c6462644223104d618e0e544072008120104408205c60510542264808488220403000106281a0290404220112c10b080145028c8000300b18a2c8280701c882e702210b00410834840108084",
"miner" => to_string(block_b.miner),
"mixHash" => "0xda53ae7c2b3c529783d6cdacdb90587fd70eb651c0f04253e8ff17de97844010",
"nonce" => "0x0946e5f01fce12bc",
"number" => block_b_number_string,
"parentHash" => to_string(block_b.parent_hash),
"receiptsRoot" => "0xa7d2b82bd8526de11736c18bd5cc8cfe2692106c4364526f3310ad56d78669c4",
"sealFields" => [
"0xa0da53ae7c2b3c529783d6cdacdb90587fd70eb651c0f04253e8ff17de97844010",
"0x880946e5f01fce12bc"
],
"sha3Uncles" => "0x483a8a21a5825ad270f358b3ea56e060bbb8b3082d9a92ec8fa17a5c7e6fc1b6",
"size" => "0x544c",
"stateRoot" => "0x85daa9cd528004c1609d4cb3520fd958e85983bb4183124a4a9f7137fd39c691",
"timestamp" => "0x5c8bc76e",
"totalDifficulty" => "0x201a42c35142ae94458",
"transactions" => [],
"transactionsRoot" => "0xcd6c12fa43cd4e92ad5c0bf232b30488bbcbfe273c5b4af0366fced0767d54db",
"uncles" => [],
"withdrawals" => [],
"minimumGasPrice" => "0x1",
"bitcoinMergedMiningHeader" =>
"0x00006d20ffd048280094a6ea0851d854036aacaa25ee0f23f0040200000000000000000078d2638fe0b4477c54601e6449051afba8228e0a88ff06b0c91f091fd34d5da57487c76402610517372c2fe9",
"bitcoinMergedMiningCoinbaseTransaction" =>
"0x00000000000000805bf0dc9203da49a3b4e3ec913806e43102cc07db991272dc8b7018da57eb5abe59a32d070000ffffffff03449a4d26000000001976a914536ffa992491508dca0354e52f32a3a7a679a53a88ac00000000000000002b6a2952534b424c4f434b3ad2508d21d28c8f89d495923c0758ec3f64bd6755b4ec416f5601312600542a400000000000000000266a24aa21a9ed4ae42ea6dca2687aaed665714bf58b055c4e11f2fb038605930d630b49ad7b9d00000000",
"bitcoinMergedMiningMerkleProof" =>
"0x8e5a4ba74eb4eb2f9ad4cabc2913aeed380a5becf7cd4d513341617efb798002bd83a783c31c66a8a8f6cc56c071c2d471cb610e3dc13054b9d216021d8c7e9112f622564449ebedcedf7d4ccb6fe0ffac861b7ed1446c310813cdf712e1e6add28b1fe1c0ae5e916194ba4f285a9340aba41e91bf847bf31acf37a9623a04a2348a37ab9faa5908122db45596bbc03e9c3644b0d4589471c4ff30fc139f3ba50506e9136fa0df799b487494de3e2b3dec937338f1a2e18da057c1f60590a9723672a4355b9914b1d01af9f582d9e856f6e1744be00f268b0b01d559329f7e0685aa63ffeb7c28486d7462292021d1345cddbf7c920ca34bb7aa4c6cdbe068806e35d0db662e7fcda03cb4d779594638c62a1fdd7ec98d1fb6d240d853958abe57561d9b9d0465cf8b9d6ee3c58b0d8b07d6c4c5d8f348e43fe3c06011b6a0008db4e0b16c77ececc3981f9008201cea5939869d648e59a09bd2094b1196ff61126bffb626153deed2563e1745436247c94a85d2947756b606d67633781c99d7",
"hashForMergedMining" => "0xd2508d21d28c8f89d495923c0758ec3f64bd6755b4ec416f5601312600542a40"
}
}
end)}
end)
pid = RootstockData.Supervisor.Case.start_supervised!(json_rpc_named_arguments: json_rpc_named_arguments)
assert [{Indexer.Fetcher.RootstockData, worker_pid, :worker, [Indexer.Fetcher.RootstockData]} | _] =
RootstockData.Supervisor |> Supervisor.which_children()
assert is_pid(worker_pid)
:timer.sleep(300)
assert [{Indexer.Fetcher.RootstockData, :undefined, :worker, [Indexer.Fetcher.RootstockData]} | _] =
RootstockData.Supervisor |> Supervisor.which_children()
# Terminates the process so it finishes all Ecto processes.
GenServer.stop(pid)
end
end
end

@ -0,0 +1,17 @@
defmodule Indexer.Fetcher.RootstockData.Supervisor.Case do
alias Indexer.Fetcher.RootstockData
def start_supervised!(fetcher_arguments \\ []) when is_list(fetcher_arguments) do
merged_fetcher_arguments =
Keyword.merge(
fetcher_arguments,
interval: 1,
batch_size: 1,
max_concurrency: 1
)
[merged_fetcher_arguments]
|> RootstockData.Supervisor.child_spec()
|> ExUnit.Callbacks.start_supervised!()
end
end

@ -179,4 +179,7 @@ defmodule ConfigHelper do
rescue
err -> raise "Invalid JSON in environment variable #{env_var}: #{inspect(err)}"
end
@spec chain_type() :: String.t()
def chain_type, do: System.get_env("CHAIN_TYPE") || "ethereum"
end

@ -4,8 +4,6 @@ import Config
|> Path.join()
|> Code.eval_file()
chain_type = System.get_env("CHAIN_TYPE") || "ethereum"
######################
### BlockScout Web ###
######################
@ -162,7 +160,7 @@ config :ethereum_jsonrpc, EthereumJSONRPC.HTTP,
config :ethereum_jsonrpc, EthereumJSONRPC.Geth,
debug_trace_transaction_timeout: System.get_env("ETHEREUM_JSONRPC_DEBUG_TRACE_TRANSACTION_TIMEOUT", "5s"),
tracer:
if(chain_type == "polygon_edge",
if(ConfigHelper.chain_type() == "polygon_edge",
do: "polygon_edge",
else: System.get_env("INDEXER_INTERNAL_TRANSACTIONS_TRACER_TYPE", "call_tracer")
)
@ -185,7 +183,6 @@ checksum_function = System.get_env("CHECKSUM_FUNCTION")
exchange_rates_coin = System.get_env("EXCHANGE_RATES_COIN")
config :explorer,
chain_type: chain_type,
coin: System.get_env("COIN") || exchange_rates_coin || "ETH",
coin_name: System.get_env("COIN_NAME") || exchange_rates_coin || "ETH",
allowed_solidity_evm_versions:
@ -590,15 +587,19 @@ config :indexer, Indexer.Fetcher.Withdrawal.Supervisor,
config :indexer, Indexer.Fetcher.Withdrawal, first_block: System.get_env("WITHDRAWALS_FIRST_BLOCK")
config :indexer, Indexer.Fetcher.PolygonEdge.Supervisor, disabled?: !(chain_type == "polygon_edge")
config :indexer, Indexer.Fetcher.PolygonEdge.Supervisor, disabled?: !(ConfigHelper.chain_type() == "polygon_edge")
config :indexer, Indexer.Fetcher.PolygonEdge.Deposit.Supervisor, disabled?: !(chain_type == "polygon_edge")
config :indexer, Indexer.Fetcher.PolygonEdge.Deposit.Supervisor,
disabled?: !(ConfigHelper.chain_type() == "polygon_edge")
config :indexer, Indexer.Fetcher.PolygonEdge.DepositExecute.Supervisor, disabled?: !(chain_type == "polygon_edge")
config :indexer, Indexer.Fetcher.PolygonEdge.DepositExecute.Supervisor,
disabled?: !(ConfigHelper.chain_type() == "polygon_edge")
config :indexer, Indexer.Fetcher.PolygonEdge.Withdrawal.Supervisor, disabled?: !(chain_type == "polygon_edge")
config :indexer, Indexer.Fetcher.PolygonEdge.Withdrawal.Supervisor,
disabled?: !(ConfigHelper.chain_type() == "polygon_edge")
config :indexer, Indexer.Fetcher.PolygonEdge.WithdrawalExit.Supervisor, disabled?: !(chain_type == "polygon_edge")
config :indexer, Indexer.Fetcher.PolygonEdge.WithdrawalExit.Supervisor,
disabled?: !(ConfigHelper.chain_type() == "polygon_edge")
config :indexer, Indexer.Fetcher.PolygonEdge,
polygon_edge_l1_rpc: System.get_env("INDEXER_POLYGON_EDGE_L1_RPC"),
@ -630,6 +631,16 @@ config :indexer, Indexer.Fetcher.Zkevm.TransactionBatch.Supervisor,
System.get_env("CHAIN_TYPE", "ethereum") == "polygon_zkevm" &&
ConfigHelper.parse_bool_env_var("INDEXER_ZKEVM_BATCHES_ENABLED")
config :indexer, Indexer.Fetcher.RootstockData.Supervisor,
disabled?:
ConfigHelper.chain_type() != "rsk" || ConfigHelper.parse_bool_env_var("INDEXER_DISABLE_ROOTSTOCK_DATA_FETCHER")
config :indexer, Indexer.Fetcher.RootstockData,
interval: ConfigHelper.parse_time_env_var("INDEXER_ROOTSTOCK_DATA_FETCHER_INTERVAL", "3s"),
batch_size: ConfigHelper.parse_integer_env_var("INDEXER_ROOTSTOCK_DATA_FETCHER_BATCH_SIZE", 10),
max_concurrency: ConfigHelper.parse_integer_env_var("INDEXER_ROOTSTOCK_DATA_FETCHER_CONCURRENCY", 5),
db_batch_size: ConfigHelper.parse_integer_env_var("INDEXER_ROOTSTOCK_DATA_FETCHER_DB_BATCH_SIZE", 300)
Code.require_file("#{config_env()}.exs", "config/runtime")
for config <- "../apps/*/config/runtime/#{config_env()}.exs" |> Path.expand(__DIR__) |> Path.wildcard() do

@ -155,6 +155,11 @@ INDEXER_DISABLE_INTERNAL_TRANSACTIONS_FETCHER=false
# ROOTSTOCK_BRIDGE_ADDRESS=
# ROOTSTOCK_LOCKED_BTC_CACHE_PERIOD=
# ROOTSTOCK_LOCKING_CAP=
# INDEXER_DISABLE_ROOTSTOCK_DATA_FETCHER=
# INDEXER_ROOTSTOCK_DATA_FETCHER_INTERVAL=
# INDEXER_ROOTSTOCK_DATA_FETCHER_BATCH_SIZE=
# INDEXER_ROOTSTOCK_DATA_FETCHER_CONCURRENCY=
# INDEXER_ROOTSTOCK_DATA_FETCHER_DB_BATCH_SIZE=
# TOKEN_ID_MIGRATION_FIRST_BLOCK=
# TOKEN_ID_MIGRATION_CONCURRENCY=
# TOKEN_ID_MIGRATION_BATCH_SIZE=

Loading…
Cancel
Save