double altair epoch slot processing speed (#2811)
* approximately double altair epoch processing speed * don't redundantly clear state balances cache * only invalidate altair state balances cache once in process_rewards_and_penalties()
This commit is contained in:
parent
ba06f13942
commit
98547e0c6b
|
@ -19,7 +19,7 @@ import
|
|||
|
||||
export extras, phase0, altair, merge
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#is_valid_merkle_branch
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#is_valid_merkle_branch
|
||||
func is_valid_merkle_branch*(leaf: Eth2Digest, branch: openArray[Eth2Digest],
|
||||
depth: int, index: uint64,
|
||||
root: Eth2Digest): bool {.nbench.}=
|
||||
|
@ -39,7 +39,7 @@ func is_valid_merkle_branch*(leaf: Eth2Digest, branch: openArray[Eth2Digest],
|
|||
value = eth2digest(buf)
|
||||
value == root
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#increase_balance
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#increase_balance
|
||||
func increase_balance*(balance: var Gwei, delta: Gwei) =
|
||||
balance += delta
|
||||
|
||||
|
@ -49,7 +49,7 @@ func increase_balance*(
|
|||
if delta != 0: # avoid dirtying the balance cache if not needed
|
||||
increase_balance(state.balances[index], delta)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#decrease_balance
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#decrease_balance
|
||||
func decrease_balance*(balance: var Gwei, delta: Gwei) =
|
||||
balance =
|
||||
if delta > balance:
|
||||
|
@ -64,8 +64,8 @@ func decrease_balance*(
|
|||
if delta != 0: # avoid dirtying the balance cache if not needed
|
||||
decrease_balance(state.balances[index], delta)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#deposits
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.6/specs/altair/beacon-chain.md#modified-process_deposit
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#deposits
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/beacon-chain.md#modified-process_deposit
|
||||
func get_validator_from_deposit*(deposit: DepositData):
|
||||
Validator =
|
||||
let
|
||||
|
@ -83,13 +83,13 @@ func get_validator_from_deposit*(deposit: DepositData):
|
|||
effective_balance: effective_balance
|
||||
)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_activation_exit_epoch
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_activation_exit_epoch
|
||||
func compute_activation_exit_epoch(epoch: Epoch): Epoch =
|
||||
## Return the epoch during which validator activations and exits initiated in
|
||||
## ``epoch`` take effect.
|
||||
epoch + 1 + MAX_SEED_LOOKAHEAD
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_validator_churn_limit
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_validator_churn_limit
|
||||
func get_validator_churn_limit(
|
||||
cfg: RuntimeConfig, state: SomeBeaconState, cache: var StateCache):
|
||||
uint64 =
|
||||
|
@ -99,7 +99,7 @@ func get_validator_churn_limit(
|
|||
count_active_validators(
|
||||
state, state.get_current_epoch(), cache) div cfg.CHURN_LIMIT_QUOTIENT)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#initiate_validator_exit
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#initiate_validator_exit
|
||||
func initiate_validator_exit*(cfg: RuntimeConfig, state: var SomeBeaconState,
|
||||
index: ValidatorIndex, cache: var StateCache) =
|
||||
## Initiate the exit of the validator with index ``index``.
|
||||
|
@ -139,8 +139,8 @@ func initiate_validator_exit*(cfg: RuntimeConfig, state: var SomeBeaconState,
|
|||
validator.withdrawable_epoch =
|
||||
validator.exit_epoch + cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#slash_validator
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.6/specs/altair/beacon-chain.md#modified-slash_validator
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#slash_validator
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/beacon-chain.md#modified-slash_validator
|
||||
proc slash_validator*(
|
||||
cfg: RuntimeConfig, state: var SomeBeaconState,
|
||||
slashed_index: ValidatorIndex, cache: var StateCache) =
|
||||
|
@ -216,7 +216,7 @@ func altairFork*(cfg: RuntimeConfig): Fork =
|
|||
current_version: cfg.ALTAIR_FORK_VERSION,
|
||||
epoch: cfg.ALTAIR_FORK_EPOCH)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#genesis
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#genesis
|
||||
proc initialize_beacon_state_from_eth1*(
|
||||
cfg: RuntimeConfig,
|
||||
eth1_block_hash: Eth2Digest,
|
||||
|
@ -314,7 +314,7 @@ proc initialize_hashed_beacon_state_from_eth1*(
|
|||
phase0.HashedBeaconState(
|
||||
data: genesisState[], root: hash_tree_root(genesisState[]))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#genesis-block
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#genesis-block
|
||||
func get_initial_beacon_block*(state: phase0.BeaconState):
|
||||
phase0.TrustedSignedBeaconBlock =
|
||||
# The genesis block is implicitly trusted
|
||||
|
@ -326,7 +326,7 @@ func get_initial_beacon_block*(state: phase0.BeaconState):
|
|||
phase0.TrustedSignedBeaconBlock(
|
||||
message: message, root: hash_tree_root(message))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_block_root_at_slot
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_block_root_at_slot
|
||||
func get_block_root_at_slot*(state: SomeBeaconState,
|
||||
slot: Slot): Eth2Digest =
|
||||
## Return the block root at a recent ``slot``.
|
||||
|
@ -339,27 +339,29 @@ func get_block_root_at_slot*(state: SomeBeaconState,
|
|||
doAssert slot < state.slot
|
||||
state.block_roots[slot mod SLOTS_PER_HISTORICAL_ROOT]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_block_root
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_block_root
|
||||
func get_block_root*(state: SomeBeaconState, epoch: Epoch): Eth2Digest =
|
||||
## Return the block root at the start of a recent ``epoch``.
|
||||
get_block_root_at_slot(state, compute_start_slot_at_epoch(epoch))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_total_balance
|
||||
func get_total_balance*(state: SomeBeaconState, validators: auto): Gwei =
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_total_balance
|
||||
template get_total_balance*(
|
||||
state: SomeBeaconState, validator_indices: untyped): Gwei =
|
||||
## Return the combined effective balance of the ``indices``.
|
||||
## ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
|
||||
## Math safe up to ~10B ETH, afterwhich this overflows uint64.
|
||||
max(EFFECTIVE_BALANCE_INCREMENT,
|
||||
foldl(validators, a + state.validators[b].effective_balance, 0'u64)
|
||||
)
|
||||
var res = 0.Gwei
|
||||
for validator_index in validator_indices:
|
||||
res += state.validators.asSeq()[validator_index].effective_balance
|
||||
max(EFFECTIVE_BALANCE_INCREMENT, res)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#is_eligible_for_activation_queue
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#is_eligible_for_activation_queue
|
||||
func is_eligible_for_activation_queue(validator: Validator): bool =
|
||||
## Check if ``validator`` is eligible to be placed into the activation queue.
|
||||
validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH and
|
||||
validator.effective_balance == MAX_EFFECTIVE_BALANCE
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#is_eligible_for_activation
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#is_eligible_for_activation
|
||||
func is_eligible_for_activation(state: SomeBeaconState, validator: Validator):
|
||||
bool =
|
||||
## Check if ``validator`` is eligible for activation.
|
||||
|
@ -369,7 +371,7 @@ func is_eligible_for_activation(state: SomeBeaconState, validator: Validator):
|
|||
# Has not yet been activated
|
||||
validator.activation_epoch == FAR_FUTURE_EPOCH
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#registry-updates
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#registry-updates
|
||||
proc process_registry_updates*(
|
||||
cfg: RuntimeConfig, state: var SomeBeaconState, cache: var StateCache) {.nbench.} =
|
||||
## Process activation eligibility and ejections
|
||||
|
@ -419,7 +421,7 @@ proc process_registry_updates*(
|
|||
state.validators[index].activation_epoch =
|
||||
compute_activation_exit_epoch(get_current_epoch(state))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#is_valid_indexed_attestation
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#is_valid_indexed_attestation
|
||||
proc is_valid_indexed_attestation*(
|
||||
state: SomeBeaconState, indexed_attestation: SomeIndexedAttestation,
|
||||
flags: UpdateFlags): Result[void, cstring] =
|
||||
|
@ -457,7 +459,7 @@ proc is_valid_indexed_attestation*(
|
|||
|
||||
ok()
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_attesting_indices
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_attesting_indices
|
||||
func get_attesting_indices*(state: SomeBeaconState,
|
||||
data: AttestationData,
|
||||
bits: CommitteeValidatorsBits,
|
||||
|
@ -509,8 +511,8 @@ proc is_valid_indexed_attestation*(
|
|||
|
||||
# Attestation validation
|
||||
# ------------------------------------------------------------------------------------------
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#attestations
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/p2p-interface.md#beacon_attestation_subnet_id
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#attestations
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/p2p-interface.md#beacon_attestation_subnet_id
|
||||
|
||||
func check_attestation_slot_target*(data: AttestationData): Result[void, cstring] =
|
||||
if not (data.target.epoch == compute_epoch_at_slot(data.slot)):
|
||||
|
@ -549,7 +551,7 @@ func check_attestation_index(
|
|||
|
||||
ok()
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.7/specs/altair/beacon-chain.md#get_attestation_participation_flag_indices
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/beacon-chain.md#get_attestation_participation_flag_indices
|
||||
func get_attestation_participation_flag_indices(state: altair.BeaconState,
|
||||
data: AttestationData,
|
||||
inclusion_delay: uint64): seq[int] =
|
||||
|
@ -583,7 +585,7 @@ func get_attestation_participation_flag_indices(state: altair.BeaconState,
|
|||
# TODO these duplicate some stuff in state_transition_epoch which uses TotalBalances
|
||||
# better to centralize around that if feasible
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_total_active_balance
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_total_active_balance
|
||||
func get_total_active_balance*(state: SomeBeaconState, cache: var StateCache): Gwei =
|
||||
## Return the combined effective balance of the active validators.
|
||||
# Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei
|
||||
|
@ -594,13 +596,13 @@ func get_total_active_balance*(state: SomeBeaconState, cache: var StateCache): G
|
|||
get_total_balance(
|
||||
state, cache.get_shuffled_active_validator_indices(state, epoch))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.8/specs/altair/beacon-chain.md#get_base_reward_per_increment
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/beacon-chain.md#get_base_reward_per_increment
|
||||
func get_base_reward_per_increment*(
|
||||
state: altair.BeaconState, cache: var StateCache): Gwei =
|
||||
EFFECTIVE_BALANCE_INCREMENT * BASE_REWARD_FACTOR div
|
||||
integer_squareroot(get_total_active_balance(state, cache))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.8/specs/altair/beacon-chain.md#get_base_reward
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/beacon-chain.md#get_base_reward
|
||||
func get_base_reward(
|
||||
state: altair.BeaconState, index: ValidatorIndex,
|
||||
base_reward_per_increment: Gwei): Gwei =
|
||||
|
@ -610,7 +612,7 @@ func get_base_reward(
|
|||
state.validators[index].effective_balance div EFFECTIVE_BALANCE_INCREMENT
|
||||
increments * base_reward_per_increment
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#attestations
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#attestations
|
||||
proc check_attestation*(
|
||||
state: SomeBeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
||||
cache: var StateCache): Result[void, cstring] =
|
||||
|
@ -717,7 +719,7 @@ proc process_attestation*(
|
|||
|
||||
ok()
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.7/specs/altair/beacon-chain.md#get_next_sync_committee_indices
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-alpha.7/specs/altair/beacon-chain.md#get_next_sync_committee_indices
|
||||
func get_next_sync_committee_indices(state: altair.BeaconState):
|
||||
seq[ValidatorIndex] =
|
||||
## Return the sequence of sync committee indices (which may include
|
||||
|
@ -749,7 +751,7 @@ func get_next_sync_committee_indices(state: altair.BeaconState):
|
|||
i += 1'u64
|
||||
sync_committee_indices
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.7/specs/altair/beacon-chain.md#get_next_sync_committee
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-alpha.7/specs/altair/beacon-chain.md#get_next_sync_committee
|
||||
proc get_next_sync_committee*(state: altair.BeaconState): SyncCommittee =
|
||||
## Return the *next* sync committee for a given ``state``.
|
||||
let indices = get_next_sync_committee_indices(state)
|
||||
|
@ -771,7 +773,7 @@ proc get_next_sync_committee*(state: altair.BeaconState): SyncCommittee =
|
|||
res.aggregate_pubkey = finish(attestersAgg).toPubKey()
|
||||
res
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.6/specs/altair/fork.md#upgrading-the-state
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/fork.md#upgrading-the-state
|
||||
func translate_participation(
|
||||
state: var altair.BeaconState,
|
||||
pending_attestations: openArray[phase0.PendingAttestation]) =
|
||||
|
|
|
@ -23,7 +23,7 @@ import
|
|||
export
|
||||
phase0, altair, eth2_merkleization, ssz_codec
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#integer_squareroot
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#integer_squareroot
|
||||
func integer_squareroot*(n: SomeInteger): SomeInteger =
|
||||
## Return the largest integer ``x`` such that ``x**2 <= n``.
|
||||
doAssert n >= 0'u64
|
||||
|
@ -36,7 +36,7 @@ func integer_squareroot*(n: SomeInteger): SomeInteger =
|
|||
y = (x + n div x) div 2
|
||||
x
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_epoch_at_slot
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_epoch_at_slot
|
||||
func compute_epoch_at_slot*(slot: Slot|uint64): Epoch =
|
||||
## Return the epoch number at ``slot``.
|
||||
(slot div SLOTS_PER_EPOCH).Epoch
|
||||
|
@ -53,24 +53,30 @@ template syncCommitteePeriod*(epoch: Epoch): uint64 =
|
|||
template syncCommitteePeriod*(slot: Slot): uint64 =
|
||||
epoch(slot) div EPOCHS_PER_SYNC_COMMITTEE_PERIOD
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_start_slot_at_epoch
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_start_slot_at_epoch
|
||||
func compute_start_slot_at_epoch*(epoch: Epoch): Slot =
|
||||
## Return the start slot of ``epoch``.
|
||||
(epoch * SLOTS_PER_EPOCH).Slot
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#is_active_validator
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#is_active_validator
|
||||
func is_active_validator*(validator: Validator, epoch: Epoch): bool =
|
||||
## Check if ``validator`` is active
|
||||
validator.activation_epoch <= epoch and epoch < validator.exit_epoch
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_active_validator_indices
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_active_validator_indices
|
||||
iterator get_active_validator_indices*(state: SomeBeaconState, epoch: Epoch):
|
||||
ValidatorIndex =
|
||||
for idx in 0..<state.validators.len:
|
||||
if is_active_validator(state.validators[idx], epoch):
|
||||
yield idx.ValidatorIndex
|
||||
|
||||
func get_active_validator_indices*(state: SomeBeaconState, epoch: Epoch):
|
||||
seq[ValidatorIndex] =
|
||||
## Return the sequence of active validator indices at ``epoch``.
|
||||
result = newSeqOfCap[ValidatorIndex](state.validators.len)
|
||||
for idx in 0..<state.validators.len:
|
||||
if is_active_validator(state.validators[idx], epoch):
|
||||
result.add idx.ValidatorIndex
|
||||
var res = newSeqOfCap[ValidatorIndex](state.validators.len)
|
||||
for idx in get_active_validator_indices(state, epoch):
|
||||
res.add idx.ValidatorIndex
|
||||
res
|
||||
|
||||
func get_active_validator_indices_len*(state: SomeBeaconState, epoch: Epoch):
|
||||
uint64 =
|
||||
|
@ -78,13 +84,13 @@ func get_active_validator_indices_len*(state: SomeBeaconState, epoch: Epoch):
|
|||
if is_active_validator(state.validators[idx], epoch):
|
||||
inc result
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_current_epoch
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_current_epoch
|
||||
func get_current_epoch*(state: SomeBeaconState): Epoch =
|
||||
## Return the current epoch.
|
||||
doAssert state.slot >= GENESIS_SLOT, $state.slot
|
||||
compute_epoch_at_slot(state.slot)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_randao_mix
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_randao_mix
|
||||
func get_randao_mix*(state: SomeBeaconState, epoch: Epoch): Eth2Digest =
|
||||
## Returns the randao mix at a recent ``epoch``.
|
||||
state.randao_mixes[epoch mod EPOCHS_PER_HISTORICAL_VECTOR]
|
||||
|
@ -109,7 +115,7 @@ func uint_to_bytes4*(x: uint64): array[4, byte] =
|
|||
result[2] = ((x shr 16) and 0xff).byte
|
||||
result[3] = ((x shr 24) and 0xff).byte
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_fork_data_root
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_fork_data_root
|
||||
func compute_fork_data_root(current_version: Version,
|
||||
genesis_validators_root: Eth2Digest): Eth2Digest =
|
||||
## Return the 32-byte fork data root for the ``current_version`` and
|
||||
|
@ -121,7 +127,7 @@ func compute_fork_data_root(current_version: Version,
|
|||
genesis_validators_root: genesis_validators_root
|
||||
))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_fork_digest
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_fork_digest
|
||||
func compute_fork_digest*(current_version: Version,
|
||||
genesis_validators_root: Eth2Digest): ForkDigest =
|
||||
## Return the 4-byte fork digest for the ``current_version`` and
|
||||
|
@ -132,7 +138,7 @@ func compute_fork_digest*(current_version: Version,
|
|||
compute_fork_data_root(
|
||||
current_version, genesis_validators_root).data.toOpenArray(0, 3)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_domain
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_domain
|
||||
func compute_domain*(
|
||||
domain_type: DomainType,
|
||||
fork_version: Version,
|
||||
|
@ -143,7 +149,7 @@ func compute_domain*(
|
|||
result[0..3] = uint_to_bytes4(domain_type.uint64)
|
||||
result[4..31] = fork_data_root.data.toOpenArray(0, 27)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_domain
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_domain
|
||||
func get_domain*(
|
||||
fork: Fork,
|
||||
domain_type: DomainType,
|
||||
|
@ -164,7 +170,7 @@ func get_domain*(
|
|||
## of a message.
|
||||
get_domain(state.fork, domain_type, epoch, state.genesis_validators_root)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_signing_root
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_signing_root
|
||||
func compute_signing_root*(ssz_object: auto, domain: Eth2Domain): Eth2Digest =
|
||||
## Return the signing root of an object by calculating the root of the
|
||||
## object-domain tree.
|
||||
|
@ -174,7 +180,7 @@ func compute_signing_root*(ssz_object: auto, domain: Eth2Domain): Eth2Digest =
|
|||
)
|
||||
hash_tree_root(domain_wrapped_object)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_seed
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_seed
|
||||
func get_seed*(state: SomeBeaconState, epoch: Epoch, domain_type: DomainType):
|
||||
Eth2Digest =
|
||||
## Return the seed at ``epoch``.
|
||||
|
@ -192,12 +198,12 @@ func get_seed*(state: SomeBeaconState, epoch: Epoch, domain_type: DomainType):
|
|||
epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD - 1).data
|
||||
eth2digest(seed_input)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.8/specs/altair/beacon-chain.md#add_flag
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/beacon-chain.md#add_flag
|
||||
func add_flag*(flags: ParticipationFlags, flag_index: int): ParticipationFlags =
|
||||
let flag = ParticipationFlags(1'u8 shl flag_index)
|
||||
flags or flag
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.8/specs/altair/beacon-chain.md#has_flag
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/beacon-chain.md#has_flag
|
||||
func has_flag*(flags: ParticipationFlags, flag_index: int): bool =
|
||||
let flag = ParticipationFlags(1'u8 shl flag_index)
|
||||
(flags and flag) == flag
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
{.push raises: [Defect].}
|
||||
|
||||
import
|
||||
std/[math, sequtils, sets, tables, algorithm],
|
||||
std/[math, sets, tables, algorithm],
|
||||
stew/[bitops2], chronicles,
|
||||
../extras,
|
||||
./datatypes/[phase0, altair],
|
||||
|
@ -160,27 +160,63 @@ func is_eligible_validator*(validator: RewardStatus): bool =
|
|||
# --------------------------------------------------------
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/beacon-chain.md#get_unslashed_participating_indices
|
||||
iterator get_unslashed_participating_indices(
|
||||
state: altair.BeaconState, flag_index: int, epoch: Epoch):
|
||||
ValidatorIndex =
|
||||
## Return the set of validator indices that are both active and unslashed for
|
||||
## the given ``flag_index`` and ``epoch``.
|
||||
doAssert epoch in [get_previous_epoch(state), get_current_epoch(state)]
|
||||
let epoch_participation =
|
||||
if epoch == get_current_epoch(state):
|
||||
unsafeAddr state.current_epoch_participation
|
||||
else:
|
||||
unsafeAddr state.previous_epoch_participation
|
||||
|
||||
for validator_index in get_active_validator_indices(state, epoch):
|
||||
if has_flag(epoch_participation[][validator_index], flag_index) and
|
||||
not state.validators[validator_index].slashed:
|
||||
yield validator_index
|
||||
|
||||
func get_unslashed_participating_indices(
|
||||
state: altair.BeaconState, flag_index: int, epoch: Epoch):
|
||||
HashSet[ValidatorIndex] =
|
||||
## Return the set of validator indices that are both active and unslashed for
|
||||
## the given ``flag_index`` and ``epoch``.
|
||||
doAssert epoch in [get_previous_epoch(state), get_current_epoch(state)]
|
||||
let
|
||||
epoch_participation =
|
||||
if epoch == get_current_epoch(state):
|
||||
state.current_epoch_participation
|
||||
else:
|
||||
state.previous_epoch_participation
|
||||
|
||||
# TODO use cached version, or similar
|
||||
active_validator_indices = get_active_validator_indices(state, epoch)
|
||||
|
||||
var res: HashSet[ValidatorIndex]
|
||||
for validator_index in active_validator_indices:
|
||||
if has_flag(epoch_participation[validator_index], flag_index) and
|
||||
not state.validators[validator_index].slashed:
|
||||
res.incl validator_index
|
||||
for validator_index in get_unslashed_participating_indices(
|
||||
state, flag_index, epoch):
|
||||
res.incl validator_index
|
||||
res
|
||||
|
||||
# For the first couple of beacon chain years there are likely to be more
|
||||
# active validators than any other sort. As Ethereum matures, this won't
|
||||
# continue to hold, and alternative optimization can be pursued.
|
||||
iterator get_slashed_or_nonparticipating_indices(
|
||||
state: altair.BeaconState, flag_index: int, epoch: Epoch):
|
||||
ValidatorIndex =
|
||||
## Return the set of validator indices that are both active and unslashed for
|
||||
## the given ``flag_index`` and ``epoch``.
|
||||
doAssert epoch in [get_previous_epoch(state), get_current_epoch(state)]
|
||||
let epoch_participation =
|
||||
if epoch == get_current_epoch(state):
|
||||
unsafeAddr state.current_epoch_participation
|
||||
else:
|
||||
unsafeAddr state.previous_epoch_participation
|
||||
|
||||
for validator_index in get_active_validator_indices(state, epoch):
|
||||
if not has_flag(epoch_participation[][validator_index], flag_index) or
|
||||
state.validators[validator_index].slashed:
|
||||
yield validator_index
|
||||
|
||||
func get_slashed_or_nonparticipating_indices(
|
||||
state: altair.BeaconState, flag_index: int, epoch: Epoch):
|
||||
HashSet[ValidatorIndex] =
|
||||
## Return the set of validator indices that are both active and unslashed for
|
||||
## the given ``flag_index`` and ``epoch``.
|
||||
var res: HashSet[ValidatorIndex]
|
||||
for validator_index in get_slashed_or_nonparticipating_indices(
|
||||
state, flag_index, epoch):
|
||||
res.incl validator_index
|
||||
res
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#justification-and-finalization
|
||||
|
@ -383,15 +419,19 @@ proc process_justification_and_finalization*(state: var altair.BeaconState,
|
|||
# result in modifying this stub.
|
||||
if get_current_epoch(state) <= GENESIS_EPOCH + 1:
|
||||
return
|
||||
|
||||
# These ultimately differ from phase0 only in these lines, with the phase 0
|
||||
# version effectively embedding weigh_justification_and_finalization(), for
|
||||
# historical reasons.
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/phase0/beacon-chain.md#justification-and-finalization
|
||||
let
|
||||
# these ultimately differ from phase0 only in these lines
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/phase0/beacon-chain.md#justification-and-finalization
|
||||
previous_indices = get_unslashed_participating_indices(
|
||||
state, TIMELY_TARGET_FLAG_INDEX, get_previous_epoch(state))
|
||||
current_indices = get_unslashed_participating_indices(
|
||||
state, TIMELY_TARGET_FLAG_INDEX, get_current_epoch(state))
|
||||
previous_target_balance = get_total_balance(state, previous_indices)
|
||||
current_target_balance = get_total_balance(state, current_indices)
|
||||
previous_target_balance = get_total_balance(state,
|
||||
get_unslashed_participating_indices(
|
||||
state, TIMELY_TARGET_FLAG_INDEX, get_previous_epoch(state)))
|
||||
current_target_balance = get_total_balance(state,
|
||||
get_unslashed_participating_indices(
|
||||
state, TIMELY_TARGET_FLAG_INDEX, get_current_epoch(state)))
|
||||
|
||||
weigh_justification_and_finalization(
|
||||
state, total_active_balance, previous_target_balance,
|
||||
current_target_balance, flags)
|
||||
|
@ -401,7 +441,7 @@ func get_base_reward_sqrt*(state: phase0.BeaconState, index: ValidatorIndex,
|
|||
total_balance_sqrt: auto): Gwei =
|
||||
# Spec function recalculates total_balance every time, which creates an
|
||||
# O(n^2) situation.
|
||||
let effective_balance = state.validators[index].effective_balance
|
||||
let effective_balance = state.validators.asSeq()[index].effective_balance
|
||||
effective_balance * BASE_REWARD_FACTOR div
|
||||
total_balance_sqrt div BASE_REWARDS_PER_EPOCH
|
||||
|
||||
|
@ -622,11 +662,13 @@ iterator get_inactivity_penalty_deltas(cfg: RuntimeConfig, state: altair.BeaconS
|
|||
## Return the inactivity penalty deltas by considering timely target
|
||||
## participation flags and inactivity scores.
|
||||
let
|
||||
previous_epoch = get_previous_epoch(state)
|
||||
matching_target_indices =
|
||||
get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, previous_epoch)
|
||||
penalty_denominator =
|
||||
cfg.INACTIVITY_SCORE_BIAS * INACTIVITY_PENALTY_QUOTIENT_ALTAIR
|
||||
previous_epoch = get_previous_epoch(state)
|
||||
|
||||
# This is the set-complement of what the spec calls matching_target_indices
|
||||
nontarget_indices = get_slashed_or_nonparticipating_indices(
|
||||
state, TIMELY_TARGET_FLAG_INDEX, previous_epoch)
|
||||
|
||||
for index in 0 ..< state.validators.len:
|
||||
# get_eligible_validator_indices()
|
||||
|
@ -636,7 +678,7 @@ iterator get_inactivity_penalty_deltas(cfg: RuntimeConfig, state: altair.BeaconS
|
|||
continue
|
||||
|
||||
template vidx: untyped = index.ValidatorIndex
|
||||
if not (vidx in matching_target_indices):
|
||||
if vidx in nontarget_indices:
|
||||
let
|
||||
penalty_numerator = state.validators[index].effective_balance *
|
||||
state.inactivity_scores[index]
|
||||
|
@ -660,8 +702,10 @@ func process_rewards_and_penalties(
|
|||
# update the raw list directly
|
||||
state.balances.clearCache()
|
||||
for idx, v in rewards.statuses:
|
||||
increase_balance(state.balances.asSeq()[idx], v.delta.rewards)
|
||||
decrease_balance(state.balances.asSeq()[idx], v.delta.penalties)
|
||||
var balance = state.balances.asSeq()[idx]
|
||||
increase_balance(balance, v.delta.rewards)
|
||||
decrease_balance(balance, v.delta.penalties)
|
||||
state.balances.asSeq()[idx] = balance
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/beacon-chain.md#rewards-and-penalties
|
||||
func process_rewards_and_penalties(
|
||||
|
@ -690,9 +734,12 @@ func process_rewards_and_penalties(
|
|||
for validator_index, penalty in get_inactivity_penalty_deltas(cfg, state):
|
||||
penalties[validator_index] += penalty
|
||||
|
||||
state.balances.clearCache()
|
||||
for index in 0 ..< len(state.validators):
|
||||
increase_balance(state, ValidatorIndex(index), rewards[index])
|
||||
decrease_balance(state, ValidatorIndex(index), penalties[index])
|
||||
var balance = state.balances.asSeq()[index]
|
||||
increase_balance(balance, rewards[index])
|
||||
decrease_balance(balance, penalties[index])
|
||||
state.balances.asSeq()[index] = balance
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#slashings
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.2/specs/altair/beacon-chain.md#slashings
|
||||
|
@ -818,24 +865,27 @@ func process_inactivity_updates*(cfg: RuntimeConfig, state: var altair.BeaconSta
|
|||
# TODO actually implement get_eligible_validator_indices() as an iterator
|
||||
let
|
||||
previous_epoch = get_previous_epoch(state) # get_eligible_validator_indices()
|
||||
unslashed_participating_indices =
|
||||
get_unslashed_participating_indices(
|
||||
slashed_or_nonparticipating_indices =
|
||||
get_slashed_or_nonparticipating_indices(
|
||||
state, TIMELY_TARGET_FLAG_INDEX, get_previous_epoch(state))
|
||||
let not_in_inactivity_leak = not is_in_inactivity_leak(state)
|
||||
for index in 0'u64 ..< state.validators.lenu64:
|
||||
# get_eligible_validator_indices()
|
||||
let v = state.validators[index]
|
||||
let v = state.validators.asSeq()[index]
|
||||
if not (is_active_validator(v, previous_epoch) or (v.slashed and previous_epoch + 1 < v.withdrawable_epoch)):
|
||||
continue
|
||||
|
||||
# Increase the inactivity score of inactive validators
|
||||
if index.ValidatorIndex in unslashed_participating_indices:
|
||||
state.inactivity_scores[index] -= min(1'u64, state.inactivity_scores[index])
|
||||
var inactivity_score = state.inactivity_scores[index]
|
||||
if index.ValidatorIndex notin slashed_or_nonparticipating_indices:
|
||||
inactivity_score -= min(1'u64, inactivity_score)
|
||||
else:
|
||||
state.inactivity_scores[index] += cfg.INACTIVITY_SCORE_BIAS
|
||||
inactivity_score += cfg.INACTIVITY_SCORE_BIAS
|
||||
# Decrease the inactivity score of all eligible validators during a
|
||||
# leak-free epoch
|
||||
if not is_in_inactivity_leak(state):
|
||||
state.inactivity_scores[index] -= min(INACTIVITY_SCORE_RECOVERY_RATE.uint64, state.inactivity_scores[index])
|
||||
if not_in_inactivity_leak:
|
||||
inactivity_score -= min(INACTIVITY_SCORE_RECOVERY_RATE.uint64, inactivity_score)
|
||||
state.inactivity_scores[index] = inactivity_score
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#epoch-processing
|
||||
proc process_epoch*(
|
||||
|
|
Loading…
Reference in New Issue