Merge pull request #3585 from poanetwork/va-staking-dapp-eth-blocknumber-autoswitching

Add autoswitching from eth_subscribe to eth_blockNumber in Staking DApp
pull/3600/head
Victor Baranov 4 years ago committed by GitHub
commit aff90fbd65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 10
      apps/block_scout_web/lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex
  3. 56
      apps/block_scout_web/priv/gettext/default.pot
  4. 56
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  5. 4
      apps/explorer/config/config.exs
  6. 2
      apps/explorer/lib/explorer/staking/contract_reader.ex
  7. 207
      apps/explorer/lib/explorer/staking/contract_state.ex
  8. 32
      apps/explorer/test/explorer/staking/contract_state_test.exs
  9. 6
      apps/indexer/lib/indexer/block/realtime/fetcher.ex

@ -8,6 +8,7 @@
- [#3583](https://github.com/poanetwork/blockscout/pull/3583) - Reduce RPC requests and DB changes by Staking DApp
### Chore
- [#3585](https://github.com/poanetwork/blockscout/pull/3585) - Add autoswitching from eth_subscribe to eth_blockNumber in Staking DApp
- [#3574](https://github.com/poanetwork/blockscout/pull/3574) - Correct UNI token price
- [#3567](https://github.com/poanetwork/blockscout/pull/3567) - Force to show filter at the page where filtered items list is empty
- [#3565](https://github.com/poanetwork/blockscout/pull/3565) - Staking dapp: unhealthy state alert message

@ -2,7 +2,7 @@
<div class="modal-dialog modal-dialog-centered modal-delegators-info" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><%= gettext("Delegators") %></h5>
<h5 class="modal-title"><%= gettext("Delegators of ") %><%= @pool.staking_address_hash %></h5>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_modal_close_button.html" %>
<div class="modal-body">
@ -49,15 +49,15 @@
<%=
title =
if @show_snapshotted_data do
gettext("Potential Reward Percent") <> "<br />(" <> gettext("Current Reward Percent") <> ")"
gettext("Potential Reward Share") <> "<br />(" <> gettext("Current Reward Share") <> ")"
else
gettext("Potential Reward Percent")
gettext("Potential Reward Share")
end
tooltip =
gettext("Reward distribution is based on stake amount. Validator receives a minimum of %{min}%.", min: @validator_min_reward_percent) <>
gettext("Reward distribution is based on stake amount. Validator receives at least %{min}% of the pool reward.", min: @validator_min_reward_percent) <>
if @show_snapshotted_data do
" " <> gettext("Current Reward Percent is calculated based on the Working Stake Amount.")
" " <> gettext("Current Reward Share is calculated based on the Working Stake Amount.")
else
""
end

@ -2126,18 +2126,6 @@ msgstr ""
msgid "Claim the Amount"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:52
msgid "Current Reward Percent"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:60
msgid "Current Reward Percent is calculated based on the Working Stake Amount."
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:32
@ -2156,7 +2144,6 @@ msgid "DApp for Staking %{symbol} tokens"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:5
#: lib/block_scout_web/templates/stakes/_stakes_progress.html.eex:31
#: lib/block_scout_web/templates/stakes/_table.html.eex:38
msgid "Delegators"
@ -2284,13 +2271,6 @@ msgstr ""
msgid "Pools searching is already in progress for this address"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:52
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:54
msgid "Potential Reward Percent"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:16
msgid "Reason for Ban: %{ban_reason}"
@ -2317,12 +2297,6 @@ msgstr ""
msgid "Reward calculating is already in progress for this address"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:58
msgid "Reward distribution is based on stake amount. Validator receives a minimum of %{min}%."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:9
msgid "Searching for pools you have ever staked into. Please, wait..."
@ -2658,3 +2632,33 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_topnav.html.eex:247
msgid "Press / and focus will be moved to the search field"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:52
msgid "Current Reward Share"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:60
msgid "Current Reward Share is calculated based on the Working Stake Amount."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:5
msgid "Delegators of "
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:52
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:54
msgid "Potential Reward Share"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:58
msgid "Reward distribution is based on stake amount. Validator receives at least %{min}% of the pool reward."
msgstr ""

@ -2126,18 +2126,6 @@ msgstr ""
msgid "Claim the Amount"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:52
msgid "Current Reward Percent"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:60
msgid "Current Reward Percent is calculated based on the Working Stake Amount."
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:32
@ -2156,7 +2144,6 @@ msgid "DApp for Staking %{symbol} tokens"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:5
#: lib/block_scout_web/templates/stakes/_stakes_progress.html.eex:31
#: lib/block_scout_web/templates/stakes/_table.html.eex:38
msgid "Delegators"
@ -2284,13 +2271,6 @@ msgstr ""
msgid "Pools searching is already in progress for this address"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:52
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:54
msgid "Potential Reward Percent"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/stakes/_stakes_modal_pool_info.html.eex:16
msgid "Reason for Ban: %{ban_reason}"
@ -2317,12 +2297,6 @@ msgstr ""
msgid "Reward calculating is already in progress for this address"
msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:58
msgid "Reward distribution is based on stake amount. Validator receives a minimum of %{min}%."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/stakes/_stakes_modal_claim_reward.html.eex:9
msgid "Searching for pools you have ever staked into. Please, wait..."
@ -2658,3 +2632,33 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_topnav.html.eex:247
msgid "Press / and focus will be moved to the search field"
msgstr ""
#, elixir-format, fuzzy
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:52
msgid "Current Reward Share"
msgstr ""
#, elixir-format, fuzzy
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:60
msgid "Current Reward Share is calculated based on the Working Stake Amount."
msgstr ""
#, elixir-format, fuzzy
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:5
msgid "Delegators of "
msgstr ""
#, elixir-format, fuzzy
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:52
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:54
msgid "Potential Reward Share"
msgstr ""
#, elixir-format, fuzzy
#:
#: lib/block_scout_web/templates/stakes/_stakes_modal_delegators_list.html.eex:58
msgid "Reward distribution is based on stake amount. Validator receives at least %{min}% of the pool reward."
msgstr ""

@ -224,7 +224,9 @@ config :explorer, Explorer.Chain.Block.Reward,
if System.get_env("POS_STAKING_CONTRACT") do
config :explorer, Explorer.Staking.ContractState,
enabled: true,
staking_contract_address: System.get_env("POS_STAKING_CONTRACT")
staking_contract_address: System.get_env("POS_STAKING_CONTRACT"),
eth_subscribe_max_delay: System.get_env("POS_ETH_SUBSCRIBE_MAX_DELAY", "60"),
eth_blocknumber_pull_interval: System.get_env("POS_ETH_BLOCKNUMBER_PULL_INTERVAL", "500")
else
config :explorer, Explorer.Staking.ContractState, enabled: false
end

@ -19,6 +19,8 @@ defmodule Explorer.Staking.ContractReader do
inactive_pools: {:staking, "df6f55f5", [], block_number},
# f0786096 = keccak256(MAX_CANDIDATES())
max_candidates: {:staking, "f0786096", [], block_number},
# 714897df = keccak256(MAX_VALIDATORS())
max_validators: {:validator_set, "714897df", [], block_number},
# 5fef7643 = keccak256(candidateMinStake())
min_candidate_stake: {:staking, "5fef7643", [], block_number},
# da7a9b6a = keccak256(delegatorMinStake())

@ -27,6 +27,7 @@ defmodule Explorer.Staking.ContractState do
:max_candidates,
:min_candidate_stake,
:min_delegator_stake,
:seen_block,
:snapshotted_epoch_number,
:staking_allowed,
:staking_contract,
@ -37,12 +38,14 @@ defmodule Explorer.Staking.ContractState do
:validator_set_contract
]
# frequency in blocks
# token renewal frequency in blocks
@token_renew_frequency 10
defstruct [
:seen_block,
:eth_blocknumber_pull_interval,
:eth_subscribe_max_delay,
:snapshotting_finished,
:timer,
:contracts,
:abi
]
@ -78,7 +81,15 @@ defmodule Explorer.Staking.ContractState do
block_reward_abi = abi("BlockRewardAuRa")
token_abi = abi("Token")
staking_contract_address = Application.get_env(:explorer, __MODULE__)[:staking_contract_address]
module_env = Application.get_env(:explorer, __MODULE__)
# eth_blockNumber pull interval, in milliseconds
eth_blocknumber_pull_interval = String.to_integer(module_env[:eth_blocknumber_pull_interval])
# eth_subscribe max delay to switch to eth_blockNumber, in seconds
eth_subscribe_max_delay = String.to_integer(module_env[:eth_subscribe_max_delay])
staking_contract_address = module_env[:staking_contract_address]
# 2d21d217 = keccak256(erc677TokenContract())
erc_677_token_contract_signature = "2d21d217"
@ -103,8 +114,10 @@ defmodule Explorer.Staking.ContractState do
})
state = %__MODULE__{
seen_block: 0,
eth_blocknumber_pull_interval: eth_blocknumber_pull_interval,
eth_subscribe_max_delay: eth_subscribe_max_delay,
snapshotting_finished: false,
timer: nil,
contracts: %{
staking: staking_contract_address,
validator_set: validator_set_contract_address,
@ -117,6 +130,7 @@ defmodule Explorer.Staking.ContractState do
block_reward_contract: %{abi: block_reward_abi, address: block_reward_contract_address},
is_snapshotting: false,
last_change_block: 0,
seen_block: 0,
snapshotted_epoch_number: -1,
staking_contract: %{abi: staking_abi, address: staking_contract_address},
token_contract: %{abi: token_abi, address: token_contract_address},
@ -128,7 +142,10 @@ defmodule Explorer.Staking.ContractState do
end
def handle_continue(_, state) do
{:noreply, state}
# if eth_subscribe doesn't work during the first eth_subscribe_max_delay seconds
# after server start, use eth_blockNumber
timer = Process.send_after(self(), :eth_subscribe_stopped, state.eth_subscribe_max_delay * 1000)
{:noreply, %{state | timer: timer}}
end
# handles an event about snapshotting finishing
@ -136,58 +153,60 @@ defmodule Explorer.Staking.ContractState do
{:noreply, %{state | snapshotting_finished: true}}
end
# handles new blocks and decides to fetch fresh chain info
def handle_info({:chain_event, :last_block_number, :realtime, block_number}, state) do
if block_number > state.seen_block do
# read general info from the contracts (including pool list and validator list)
global_responses =
ContractReader.perform_requests(ContractReader.global_requests(block_number), state.contracts, state.abi)
epoch_very_beginning = global_responses.epoch_start_block == block_number + 1
if global_responses.epoch_number > get(:epoch_number) and not epoch_very_beginning and state.seen_block > 0 do
# if the previous staking epoch finished and we have blocks gap,
# call fetch_state in a loop until the blocks gap is closed
loop_block_start = state.seen_block + 1
loop_block_end = block_number - 1
if loop_block_end >= loop_block_start do
for bn <- loop_block_start..loop_block_end do
gr = ContractReader.perform_requests(ContractReader.global_requests(bn), state.contracts, state.abi)
fetch_state(state, gr, bn, gr.epoch_start_block == bn + 1)
end
end
# received when eth_subscribe is stopped
def handle_info(:eth_subscribe_stopped, state) do
state =
if Process.read_timer(state.timer) == false do
{microseconds, state} =
:timer.tc(
fn st -> fetch_state(st, get_current_block_number()) end,
[state]
)
# sleep up to eth_blocknumber_pull_interval milliseconds before the next eth_blockNumber request
Process.send_after(
self(),
:eth_subscribe_stopped,
max(state.eth_blocknumber_pull_interval - round(microseconds / 1000), 0)
)
state
else
state
end
fetch_state(state, global_responses, block_number, epoch_very_beginning)
{:noreply, state}
end
# catches a new block number from eth_subscribe
def handle_info({:chain_event, :last_block_number, :realtime, block_number}, state) do
if state.timer != nil do
Process.cancel_timer(state.timer)
end
state =
if state.snapshotting_finished do
%{state | snapshotting_finished: false}
else
state
end
state = fetch_state(state, block_number)
{:noreply, %{state | seen_block: block_number}}
timer = Process.send_after(self(), :eth_subscribe_stopped, state.eth_subscribe_max_delay * 1000)
{:noreply, %{state | timer: timer}}
end
# handles new block and decides to fetch fresh chain info
defp fetch_state(state, block_number) do
if block_number <= get(:seen_block) do
state
else
{:noreply, state}
fetch_state_internal(state, block_number)
end
end
defp fetch_state(state, global_responses, block_number, epoch_very_beginning) do
contracts = state.contracts
abi = state.abi
snapshotting_finished = state.snapshotting_finished
first_fetch = get(:epoch_end_block, 0) == 0
defp fetch_state_internal(state, block_number) do
# read general info from the contracts (including pool list and validator list)
global_responses =
ContractReader.perform_requests(ContractReader.global_requests(block_number), state.contracts, state.abi)
validator_min_reward_percent =
get_validator_min_reward_percent(global_responses.epoch_number, block_number, contracts, abi)
epoch_very_beginning = global_responses.epoch_start_block == block_number + 1
start_snapshotting =
global_responses.epoch_number > get(:snapshotted_epoch_number) && global_responses.epoch_number > 0 &&
not get(:is_snapshotting)
active_pools_length = Enum.count(global_responses.active_pools)
start_snapshotting = start_snapshotting?(global_responses)
# determine if something changed in contracts state since the previous seen block.
# if something changed or the `fetch_state` function is called for the first time
@ -196,17 +215,13 @@ defmodule Explorer.Staking.ContractState do
last_change_block =
max(global_responses.staking_last_change_block, global_responses.validator_set_last_change_block)
first_fetch = get(:epoch_end_block, 0) == 0
should_update_db =
start_snapshotting or snapshotting_finished or first_fetch or last_change_block > get(:last_change_block)
start_snapshotting or state.snapshotting_finished or first_fetch or last_change_block > get(:last_change_block)
# save the general info to ETS (excluding pool list and validator list)
settings =
global_responses
|> get_settings(validator_min_reward_percent, block_number)
|> Enum.concat(active_pools_length: active_pools_length)
|> Enum.concat(last_change_block: last_change_block)
:ets.insert(@table_name, settings)
set_settings(global_responses, state, block_number, last_change_block)
if epoch_very_beginning or start_snapshotting do
# if the block_number is the latest block of the finished staking epoch
@ -218,12 +233,19 @@ defmodule Explorer.Staking.ContractState do
# we should update database as something changed in contracts state
if should_update_db do
update_database(epoch_very_beginning, start_snapshotting, global_responses, contracts, abi, block_number)
update_database(
epoch_very_beginning,
start_snapshotting,
global_responses,
state.contracts,
state.abi,
block_number
)
end
# notify the UI about a new block
data = %{
active_pools_length: active_pools_length,
active_pools_length: get(:active_pools_length),
block_number: block_number,
epoch_end_block: global_responses.epoch_end_block,
epoch_number: global_responses.epoch_number,
@ -234,6 +256,17 @@ defmodule Explorer.Staking.ContractState do
}
Publisher.broadcast([{:staking_update, data}], :realtime)
if state.snapshotting_finished do
%{state | snapshotting_finished: false}
else
state
end
end
defp start_snapshotting?(global_responses) do
global_responses.epoch_number > get(:snapshotted_epoch_number) && global_responses.epoch_number > 0 &&
not get(:is_snapshotting)
end
defp update_database(epoch_very_beginning, start_snapshotting, global_responses, contracts, abi, block_number) do
@ -295,9 +328,6 @@ defmodule Explorer.Staking.ContractState do
block_number
)
# calculate total amount staked into all active pools
staked_total = Enum.sum(for {_, pool} <- pool_staking_responses, pool.is_active, do: pool.total_staked_amount)
# calculate likelihood of becoming a validator on the next epoch
[likelihood_values, total_likelihood] = global_responses.pools_likelihood
# array of pool addresses (staking addresses)
@ -332,8 +362,7 @@ defmodule Explorer.Staking.ContractState do
global_responses: global_responses,
snapshotted_epoch_number: snapshotted_epoch_number,
likelihood: likelihood,
total_likelihood: total_likelihood,
staked_total: staked_total
total_likelihood: total_likelihood
})
# perform SQL queries
@ -356,7 +385,29 @@ defmodule Explorer.Staking.ContractState do
end
end
defp get_settings(global_responses, validator_min_reward_percent, block_number) do
defp get_current_block_number do
json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
result =
%{id: 0, method: "eth_blockNumber", params: []}
|> EthereumJSONRPC.request()
|> EthereumJSONRPC.json_rpc(json_rpc_named_arguments)
case result do
{:ok, response} ->
response
|> String.replace_leading("0x", "")
|> String.to_integer(16)
_ ->
0
end
end
defp get_settings(global_responses, state, block_number) do
validator_min_reward_percent =
get_validator_min_reward_percent(global_responses.epoch_number, block_number, state.contracts, state.abi)
base_settings = get_base_settings(global_responses, validator_min_reward_percent)
update_token =
@ -371,6 +422,17 @@ defmodule Explorer.Staking.ContractState do
end
end
defp set_settings(global_responses, state, block_number, last_change_block) do
settings =
global_responses
|> get_settings(state, block_number)
|> Enum.concat(active_pools_length: Enum.count(global_responses.active_pools))
|> Enum.concat(last_change_block: last_change_block)
|> Enum.concat(seen_block: block_number)
:ets.insert(@table_name, settings)
end
defp get_mining_to_staking_address(validators, contracts, abi, block_number) do
validators.all
|> Enum.map(&ContractReader.staking_by_mining_request(&1, block_number))
@ -600,9 +662,11 @@ defmodule Explorer.Staking.ContractState do
global_responses: global_responses,
snapshotted_epoch_number: snapshotted_epoch_number,
likelihood: likelihood,
total_likelihood: total_likelihood,
staked_total: staked_total
total_likelihood: total_likelihood
}) do
# total amount staked into all active pools
staked_total = Enum.sum(for {_, pool} <- pool_staking_responses, pool.is_active, do: pool.total_staked_amount)
Enum.map(pools, fn pool_staking_address ->
staking_resp = pool_staking_responses[pool_staking_address]
mining_resp = pool_mining_responses[pool_staking_address]
@ -622,6 +686,15 @@ defmodule Explorer.Staking.ContractState do
0
end
is_unremovable = address_bytes_to_string(pool_staking_address) == global_responses.unremovable_validator
likelihood_value =
if get(:active_pools_length) > global_responses.max_validators and not is_unremovable do
ratio(likelihood[pool_staking_address] || 0, total_likelihood)
else
100
end
%{
staking_address_hash: pool_staking_address,
delegators_count: delegators_count,
@ -632,11 +705,11 @@ defmodule Explorer.Staking.ContractState do
0
end,
validator_reward_ratio: Float.floor(candidate_reward_resp.validator_share / 10_000, 2),
likelihood: ratio(likelihood[pool_staking_address] || 0, total_likelihood),
likelihood: likelihood_value,
validator_reward_percent: staking_resp.validator_reward_percent / 10_000,
is_deleted: false,
is_validator: is_validator,
is_unremovable: address_bytes_to_string(pool_staking_address) == global_responses.unremovable_validator,
is_unremovable: is_unremovable,
ban_reason: binary_to_string(mining_resp.ban_reason)
}
|> Map.merge(

@ -25,7 +25,9 @@ defmodule Explorer.Staking.ContractStateTest do
Application.put_env(:explorer, ContractState,
enabled: true,
staking_contract_address: "0x1100000000000000000000000000000000000001"
staking_contract_address: "0x1100000000000000000000000000000000000001",
eth_blocknumber_pull_interval: "500",
eth_subscribe_max_delay: "60"
)
start_supervised!(ContractState)
@ -99,7 +101,7 @@ defmodule Explorer.Staking.ContractStateTest do
EthereumJSONRPC.Mox,
:json_rpc,
fn requests, _opts ->
assert length(requests) == 17
assert length(requests) == 18
{:ok,
format_responses([
@ -114,28 +116,30 @@ defmodule Explorer.Staking.ContractStateTest do
# 5 StakingAuRa.getPoolsInactive
"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000",
# 6 StakingAuRa.MAX_CANDIDATES
"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000bb8",
# 7 StakingAuRa.candidateMinStake
"0x0000000000000000000000000000000000000000000000000000000000000bb8",
# 7 StakingAuRa.MAX_VALIDATORS
"0x0000000000000000000000000000000000000000000000000000000000000013",
# 8 StakingAuRa.candidateMinStake
"0x0000000000000000000000000000000000000000000000000de0b6b3a7640000",
# 8 StakingAuRa.delegatorMinStake
# 9 StakingAuRa.delegatorMinStake
"0x0000000000000000000000000000000000000000000000000de0b6b3a7640000",
# 9 StakingAuRa.getPoolsLikelihood
# 10 StakingAuRa.getPoolsLikelihood
"0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000098a7d9b8314c000000000000000000000000000000000000000000000000000029a2241af62c0000",
# 10 StakingAuRa.getPoolsToBeElected
# 11 StakingAuRa.getPoolsToBeElected
"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000b916e7e1f4bcb13549602ed042d36746fd0d96c9000000000000000000000000db9cb2478d917719c53862008672166808258577000000000000000000000000b6695f5c2e3f5eff8036b5f5f3a9d83a5310e51e",
# 11 StakingAuRa.areStakeAndWithdrawAllowed
# 12 StakingAuRa.areStakeAndWithdrawAllowed
"0x0000000000000000000000000000000000000000000000000000000000000000",
# 12 StakingAuRa.lastChangeBlock
# 13 StakingAuRa.lastChangeBlock
"0x0000000000000000000000000000000000000000000000000000000000000000",
# 13 StakingAuRa.erc677TokenContract
# 14 StakingAuRa.erc677TokenContract
"0x0000000000000000000000006f7a73c96bd56f8b0debc795511eda135e105ea3",
# 14 ValidatorSetAuRa.unremovableValidator
# 15 ValidatorSetAuRa.unremovableValidator
"0x0000000000000000000000000b2f5e2f3cbd864eaa2c642e3769c1582361caf6",
# 15 ValidatorSetAuRa.getValidators
# 16 ValidatorSetAuRa.getValidators
"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000bbcaa8d48289bb1ffcf9808d9aa4b1d215054c7800000000000000000000000075df42383afe6bf5194aa8fa0e9b3d5f9e869441000000000000000000000000522df396ae70a058bd69778408630fdb023389b2",
# 16 ValidatorSetAuRa.validatorSetApplyBlock
# 17 ValidatorSetAuRa.validatorSetApplyBlock
"0x0000000000000000000000000000000000000000000000000000000000000000",
# 17 ValidatorSetAuRa.lastChangeBlock
# 18 ValidatorSetAuRa.lastChangeBlock
"0x0000000000000000000000000000000000000000000000000000000000000000"
])}
end

@ -86,7 +86,11 @@ defmodule Indexer.Block.Realtime.Fetcher do
)
when is_binary(quantity) do
number = quantity_to_integer(quantity)
Publisher.broadcast([{:last_block_number, number}], :realtime)
if number > 0 do
Publisher.broadcast([{:last_block_number, number}], :realtime)
end
# Subscriptions don't support getting all the blocks and transactions data,
# so we need to go back and get the full block
start_fetch_and_import(number, block_fetcher, previous_number, max_number_seen)

Loading…
Cancel
Save