Skip to content

Commit

Permalink
Add network rewards
Browse files Browse the repository at this point in the history
  • Loading branch information
nalepae committed Aug 2, 2023
1 parent 82f2eef commit ef041fd
Show file tree
Hide file tree
Showing 7 changed files with 893 additions and 338 deletions.
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,17 +146,28 @@ name | description
`suboptimal_attestations_rate` | Suboptimal attestations rate
`keys_count` | Keys count
`bad_relay_count` | Bad relay count
`suboptimal_sources_rate` | Suboptimal sources rate
`suboptimal_targets_rate` | Suboptimal targets rate
`suboptimal_heads_rate` | Suboptimal heads rate
`ideal_sources_count` | Ideal sources count
`ideal_targets_count` | Ideal targets count
`ideal_heads_count` | Ideal heads count
`actual_positive_sources_count` | Actual positive sources count
`actual_negative_sources_count` | Actual negative sources count
`actual_positive_targets_count` | Actual positive targets count
`actual_negative_targets_count` | Actual negative targets count
`actual_heads_count` | Actual heads count
`net_suboptimal_sources_rate` | Network suboptimal sources rate
`net_suboptimal_targets_rate` | Network suboptimal targets rate
`net_suboptimal_heads_rate` | Network suboptimal heads rate
`net_ideal_sources_count` | Network ideal sources count
`net_ideal_targets_count` | Network ideal targets count
`net_ideal_heads_count` | Network ideal heads count
`net_actual_pos_sources_count` | Network actual positive sources count
`net_actual_neg_sources_count` | Network actual negative sources count
`net_actual_pos_targets_count` | Network actual positive targets count
`net_actual_neg_targets_count` | Network actual negative targets count
`net_actual_heads_count` | Network actual heads count
`our_suboptimal_sources_rate` | Our suboptimal sources rate
`our_suboptimal_targets_rate` | Our suboptimal targets rate
`our_suboptimal_heads_rate` | Our suboptimal heads rate
`our_ideal_sources_count` | Our ideal sources count
`our_ideal_targets_count` | Our ideal targets count
`our_ideal_heads_count` | Our ideal heads count
`our_actual_pos_sources_count` | Our actual positive sources count
`our_actual_neg_sources_count` | Our actual negative sources count
`our_actual_pos_targets_count` | Our actual positive targets count
`our_actual_neg_targets_count` | Our actual negative targets count
`our_actual_heads_count` | Our actual heads count

Installation
------------
Expand Down
14 changes: 11 additions & 3 deletions eth_validator_watcher/beacon.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,19 @@ def get_duty_slot_to_committee_index_to_validators_index(
return result

def get_rewards(
self, beacon_type: BeaconType, epoch: int, validators_index: set[int]
self,
beacon_type: BeaconType,
epoch: int,
validators_index: Optional[set[int]] = None,
) -> Rewards:
"""Get rewards.
Parameters:
beacon_type : Type of beacon node
epoch : Epoch corresponding to the rewards to retrieve
validators_index: Set of validator indexes corresponding to the rewards to
retrieve
retrieve. If None, rewards for all validators will be
retrieved.
"""

# On Prysm, because of
Expand All @@ -214,7 +218,11 @@ def get_rewards(

response = self.__post(
f"{self.__url}/eth/v1/beacon/rewards/attestations/{epoch}",
json=[str(index) for index in sorted(validators_index)],
json=(
[str(index) for index in sorted(validators_index)]
if validators_index is not None
else []
),
timeout=10,
)

Expand Down
161 changes: 68 additions & 93 deletions eth_validator_watcher/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from .beacon import Beacon
from .coinbase import Coinbase
from .entry_queue import export_duration_sec as export_entry_queue_duration_sec
from .entry_queue import export_duration_sec as export_entry_queue_dur_sec
from .execution import Execution
from .exited_validators import ExitedValidators
from .fee_recipient import process_fee_recipient
Expand Down Expand Up @@ -42,20 +42,20 @@

from .relays import Relays

StatusEnum = Validators.DataItem.StatusEnum
Status = Validators.DataItem.StatusEnum


app = typer.Typer(add_completion=False)

slot_gauge = Gauge("slot", "Slot")
epoch_gauge = Gauge("epoch", "Epoch")

our_pending_queued_validators_gauge = Gauge(
our_queued_vals_gauge = Gauge(
"our_pending_queued_validators_count",
"Our pending queued validators count",
)

total_pending_queued_validators_gauge = Gauge(
net_pending_q_vals_gauge = Gauge(
"total_pending_queued_validators_count",
"Total pending queued validators count",
)
Expand All @@ -65,7 +65,7 @@
"Our active validators count",
)

total_active_validators_gauge = Gauge(
net_active_validators_gauge = Gauge(
"total_active_validators_count",
"Total active validators count",
)
Expand Down Expand Up @@ -224,18 +224,19 @@ def _handler(
relays = Relays(relays_url)

our_pubkeys: set[str] = set()
our_active_index_to_validator: dict[int, Validators.DataItem.Validator] = {}
our_active_idx2val: dict[int, Validators.DataItem.Validator] = {}
our_validators_indexes_that_missed_attestation: set[int] = set()
our_validators_indexes_that_missed_previous_attestation: set[int] = set()
previous_epoch: Optional[int] = None
our_epoch2active_idx2val = LimitedDict(3)
net_epoch2active_idx2val = LimitedDict(3)

exited_validators = ExitedValidators(slack)
slashed_validators = SlashedValidators(slack)

last_missed_attestations_process_epoch: Optional[int] = None
last_rewards_process_epoch: Optional[int] = None
epoch_to_our_active_index_to_validator = LimitedDict(4)

previous_epoch: Optional[int] = None
genesis = beacon.get_genesis()

for slot, slot_start_time_sec in slots(genesis.data.genesis_time):
Expand All @@ -253,99 +254,67 @@ def _handler(
except ValueError:
raise typer.BadParameter("Some pubkeys are invalid")

total_status_to_index_to_validator = (
beacon.get_status_to_index_to_validator()
)
# Network validators
# ------------------
net_status2idx2val = beacon.get_status_to_index_to_validator()

net_pending_q_idx2val = net_status2idx2val.get(Status.pendingQueued, {})
nb_total_pending_q_vals = len(net_pending_q_idx2val)
net_pending_q_vals_gauge.set(nb_total_pending_q_vals)

active_ongoing = net_status2idx2val.get(Status.activeOngoing, {})
active_exiting = net_status2idx2val.get(Status.activeExiting, {})
active_slashed = net_status2idx2val.get(Status.activeSlashed, {})
net_active_idx2val = active_ongoing | active_exiting | active_slashed
net_epoch2active_idx2val[epoch] = net_active_idx2val

our_status_to_index_to_validator = {
net_active_vals_count = len(net_active_idx2val)
net_active_validators_gauge.set(net_active_vals_count)

net_exited_s_idx2val = net_status2idx2val.get(Status.exitedSlashed, {})

with_poss = net_status2idx2val.get(Status.withdrawalPossible, {})
with_done = net_status2idx2val.get(Status.withdrawalDone, {})
net_withdrawable_idx2val = with_poss | with_done

# Our validators
# --------------
our_status2idx2val = {
status: {
index: validator
for index, validator in validator.items()
if validator.pubkey in our_pubkeys
}
for status, validator in total_status_to_index_to_validator.items()
for status, validator in net_status2idx2val.items()
}

our_pending_queued_index_to_validator = (
our_status_to_index_to_validator.get(StatusEnum.pendingQueued, {})
)
our_queued_idx2val = our_status2idx2val.get(Status.pendingQueued, {})
our_queued_vals_gauge.set(len(our_queued_idx2val))

our_pending_queued_validators_gauge.set(
len(our_pending_queued_index_to_validator)
)
ongoing = our_status2idx2val.get(Status.activeOngoing, {})
active_exiting = our_status2idx2val.get(Status.activeExiting, {})
active_slashed = our_status2idx2val.get(Status.activeSlashed, {})
our_active_idx2val = ongoing | active_exiting | active_slashed
our_epoch2active_idx2val[epoch] = our_active_idx2val

our_active_index_to_validator = (
our_status_to_index_to_validator.get(StatusEnum.activeOngoing, {})
| our_status_to_index_to_validator.get(StatusEnum.activeExiting, {})
| our_status_to_index_to_validator.get(StatusEnum.activeSlashed, {})
)

epoch_to_our_active_index_to_validator[
epoch
] = our_active_index_to_validator
our_active_validators_gauge.set(len(our_active_idx2val))
our_exited_u_idx2val = our_status2idx2val.get(Status.exitedUnslashed, {})
our_exited_s_idx2val = our_status2idx2val.get(Status.exitedSlashed, {})

our_active_validators_gauge.set(len(our_active_index_to_validator))
with_poss = our_status2idx2val.get(Status.withdrawalPossible, {})
with_done = our_status2idx2val.get(Status.withdrawalDone, {})
our_withdrawable_idx2val = with_poss | with_done

our_exited_unslashed_index_to_validator = (
our_status_to_index_to_validator.get(StatusEnum.exitedUnslashed, {})
)

our_exited_slashed_index_to_validator = (
our_status_to_index_to_validator.get(StatusEnum.exitedSlashed, {})
)

our_withdrawable_index_to_validator = our_status_to_index_to_validator.get(
StatusEnum.withdrawalPossible, {}
) | our_status_to_index_to_validator.get(StatusEnum.withdrawalDone, {})

total_pending_queued_index_to_validator = (
total_status_to_index_to_validator.get(StatusEnum.pendingQueued, {})
)

nb_total_pending_queued_validators = len(
total_pending_queued_index_to_validator
)

total_pending_queued_validators_gauge.set(
nb_total_pending_queued_validators
)

total_active_index_to_validator = (
total_status_to_index_to_validator.get(StatusEnum.activeOngoing, {})
| total_status_to_index_to_validator.get(StatusEnum.activeExiting, {})
| total_status_to_index_to_validator.get(StatusEnum.activeSlashed, {})
)

nb_total_active_validators = len(total_active_index_to_validator)
total_active_validators_gauge.set(nb_total_active_validators)

total_exited_slashed_index_to_validator = (
total_status_to_index_to_validator.get(StatusEnum.exitedSlashed, {})
)

total_withdrawable_index_to_validator = (
total_status_to_index_to_validator.get(
StatusEnum.withdrawalPossible, {}
)
| total_status_to_index_to_validator.get(StatusEnum.withdrawalDone, {})
)

exited_validators.process(
our_exited_unslashed_index_to_validator,
our_withdrawable_index_to_validator,
)
exited_validators.process(our_exited_u_idx2val, our_withdrawable_idx2val)

slashed_validators.process(
total_exited_slashed_index_to_validator,
our_exited_slashed_index_to_validator,
total_withdrawable_index_to_validator,
our_withdrawable_index_to_validator,
)

export_entry_queue_duration_sec(
nb_total_active_validators, nb_total_pending_queued_validators
net_exited_s_idx2val,
our_exited_s_idx2val,
net_withdrawable_idx2val,
our_withdrawable_idx2val,
)

export_entry_queue_dur_sec(net_active_vals_count, nb_total_pending_q_vals)
coinbase.emit_eth_usd_conversion_rate()

if previous_epoch is not None and previous_epoch != epoch:
Expand All @@ -362,27 +331,33 @@ def _handler(
if should_process_missed_attestations:
our_validators_indexes_that_missed_attestation = (
process_missed_attestations(
beacon, beacon_type, epoch_to_our_active_index_to_validator, epoch
beacon, beacon_type, our_epoch2active_idx2val, epoch
)
)

process_double_missed_attestations(
our_validators_indexes_that_missed_attestation,
our_validators_indexes_that_missed_previous_attestation,
epoch_to_our_active_index_to_validator,
our_epoch2active_idx2val,
epoch,
slack,
)

last_missed_attestations_process_epoch = epoch

should_process_rewards = slot_in_epoch >= SLOT_FOR_REWARDS_PROCESS and (
last_rewards_process_epoch is None or last_rewards_process_epoch != epoch
)
is_slot_big_enough = slot_in_epoch >= SLOT_FOR_REWARDS_PROCESS
is_last_rewards_epoch_none = last_rewards_process_epoch is None
is_new_rewards_epoch = last_rewards_process_epoch != epoch
epoch_condition = is_last_rewards_epoch_none or is_new_rewards_epoch
should_process_rewards = is_slot_big_enough and epoch_condition

if should_process_rewards:
process_rewards(
beacon, beacon_type, epoch, epoch_to_our_active_index_to_validator
beacon,
beacon_type,
epoch,
net_epoch2active_idx2val,
our_epoch2active_idx2val,
)

last_rewards_process_epoch = epoch
Expand All @@ -401,11 +376,11 @@ def _handler(
beacon,
block,
slot,
our_active_index_to_validator,
our_active_idx2val,
)

process_fee_recipient(
block, our_active_index_to_validator, execution, fee_recipient, slack
block, our_active_idx2val, execution, fee_recipient, slack
)

is_our_validator = process_missed_blocks(
Expand Down
Loading

0 comments on commit ef041fd

Please sign in to comment.