parent
fa320dc3ec
commit
8780fdfdac
@ -0,0 +1,46 @@ |
||||
defmodule Explorer.Application.Constants do |
||||
@moduledoc """ |
||||
Tracks some kv info |
||||
""" |
||||
|
||||
use Explorer.Schema |
||||
alias Explorer.Repo |
||||
|
||||
@keys_manager_contract_address_key "keys_manager_contract_address" |
||||
|
||||
@primary_key false |
||||
schema "constants" do |
||||
field(:key, :string, primary_key: true) |
||||
field(:value, :string) |
||||
|
||||
timestamps() |
||||
end |
||||
|
||||
def changeset(attrs) do |
||||
%__MODULE__{} |
||||
|> changeset(attrs) |
||||
end |
||||
|
||||
@required_attrs ~w(key value)a |
||||
def changeset(%__MODULE__{} = constant, attrs) do |
||||
constant |
||||
|> cast(attrs, @required_attrs) |
||||
|> validate_required(@required_attrs) |
||||
end |
||||
|
||||
def get_constant_by_key(key) do |
||||
__MODULE__ |
||||
|> where([constant], constant.key == ^key) |
||||
|> Repo.one() |
||||
end |
||||
|
||||
def insert_keys_manager_contract_address(value) do |
||||
%{key: @keys_manager_contract_address_key, value: value} |
||||
|> changeset() |
||||
|> Repo.insert!() |
||||
end |
||||
|
||||
def get_keys_manager_contract_address do |
||||
get_constant_by_key(@keys_manager_contract_address_key) |
||||
end |
||||
end |
@ -0,0 +1,69 @@ |
||||
defmodule Explorer.Chain.Fetcher.FetchValidatorInfoOnDemand do |
||||
@moduledoc """ |
||||
On demand fetcher info about validator |
||||
""" |
||||
|
||||
use GenServer |
||||
|
||||
alias Explorer.Application.Constants |
||||
alias Explorer.Chain.Block.Reward |
||||
alias Explorer.Chain.Cache.BlockNumber |
||||
alias Explorer.Chain.Validator |
||||
|
||||
def trigger_fetch(address_hash) do |
||||
GenServer.cast(__MODULE__, {:fetch_or_update, address_hash}) |
||||
end |
||||
|
||||
defp actualize_validator_info(address_hash) do |
||||
contract_address_from_db = Constants.get_keys_manager_contract_address() |
||||
|
||||
contract_address_from_env = |
||||
Application.get_env(:explorer, Explorer.Chain.Block.Reward, %{})[:keys_manager_contract_address] |
||||
|
||||
cond do |
||||
is_nil(contract_address_from_env) -> |
||||
:ignore |
||||
|
||||
is_nil(contract_address_from_db) -> |
||||
Validator.drop_all_validators() |
||||
Constants.insert_keys_manager_contract_address(contract_address_from_env) |
||||
fetch_and_store_validator_info(address_hash) |
||||
|
||||
String.downcase(contract_address_from_db.value) == contract_address_from_env |> String.downcase() -> |
||||
fetch_and_store_validator_info(address_hash) |
||||
|
||||
true -> |
||||
Validator.drop_all_validators() |
||||
Constants.insert_keys_manager_contract_address(contract_address_from_env) |
||||
fetch_and_store_validator_info(address_hash) |
||||
end |
||||
end |
||||
|
||||
defp fetch_and_store_validator_info(validator_address) do |
||||
validator = Validator.get_validator_by_address_hash(validator_address) |
||||
%{is_validator: is_validator, payout_key: payout_key} = Reward.get_validator_payout_key_by_mining(validator_address) |
||||
|
||||
Validator.insert_or_update(validator, %{ |
||||
address_hash: validator_address, |
||||
is_validator: is_validator, |
||||
payout_key_hash: payout_key, |
||||
last_block_updated_at: BlockNumber.get_max() |
||||
}) |
||||
end |
||||
|
||||
def start_link(_) do |
||||
GenServer.start_link(__MODULE__, :ok, name: __MODULE__) |
||||
end |
||||
|
||||
@impl true |
||||
def init(opts) do |
||||
{:ok, opts} |
||||
end |
||||
|
||||
@impl true |
||||
def handle_cast({:fetch_or_update, address_hash}, state) do |
||||
actualize_validator_info(address_hash) |
||||
|
||||
{:noreply, state} |
||||
end |
||||
end |
@ -0,0 +1,56 @@ |
||||
defmodule Explorer.Chain.Validator do |
||||
@moduledoc """ |
||||
Tracks info about POA validator |
||||
""" |
||||
|
||||
use Explorer.Schema |
||||
alias Explorer.Chain.Hash.Address |
||||
alias Explorer.Repo |
||||
|
||||
@primary_key false |
||||
schema "validators" do |
||||
field(:address_hash, Address, primary_key: true) |
||||
field(:is_validator, :boolean) |
||||
field(:payout_key_hash, Address) |
||||
field(:last_block_updated_at, :integer) |
||||
|
||||
timestamps() |
||||
end |
||||
|
||||
def insert_or_update(nil, attrs) do |
||||
attrs |
||||
|> changeset() |
||||
|> Repo.insert() |
||||
end |
||||
|
||||
def insert_or_update(validator, attrs) do |
||||
validator |
||||
|> changeset(attrs) |
||||
|> Repo.update() |
||||
end |
||||
|
||||
def changeset(attrs) do |
||||
%__MODULE__{} |
||||
|> changeset(attrs) |
||||
end |
||||
|
||||
@required_attrs ~w(address_hash)a |
||||
@optional_attrs ~w(is_validator payout_key_hash last_block_updated_at)a |
||||
def changeset(%__MODULE__{} = constant, attrs) do |
||||
constant |
||||
|> cast(attrs, @required_attrs ++ @optional_attrs) |
||||
|> validate_required(@required_attrs) |
||||
|> unique_constraint(:address_hash) |
||||
end |
||||
|
||||
def get_validator_by_address_hash(address_hash) do |
||||
__MODULE__ |
||||
|> where([validator], validator.address_hash == ^address_hash) |
||||
|> Repo.one() |
||||
end |
||||
|
||||
def drop_all_validators() do |
||||
__MODULE__ |
||||
|> Repo.delete_all() |
||||
end |
||||
end |
@ -0,0 +1,21 @@ |
||||
defmodule Explorer.Repo.Migrations.AddValidatorsAndConstantsTables do |
||||
use Ecto.Migration |
||||
|
||||
def change do |
||||
create table(:constants, primary_key: false) do |
||||
add(:key, :string, primary_key: true, null: false) |
||||
add(:value, :string) |
||||
|
||||
timestamps() |
||||
end |
||||
|
||||
create table(:validators, primary_key: false) do |
||||
add(:address_hash, :bytea, primary_key: true, null: false) |
||||
add(:is_validator, :boolean) |
||||
add(:payout_key_hash, :bytea) |
||||
add(:last_block_updated_at, :bigint) |
||||
|
||||
timestamps() |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue