optimize epoch registry processing (#5412)
This commit is contained in:
parent
cc13e0b7e0
commit
10ec7be686
|
@ -669,12 +669,14 @@ template `[]`*[T](a: seq[T], b: ValidatorIndex): auto = # Also var seq (!)
|
||||||
|
|
||||||
iterator vindices*(
|
iterator vindices*(
|
||||||
a: HashList[Validator, Limit VALIDATOR_REGISTRY_LIMIT]): ValidatorIndex =
|
a: HashList[Validator, Limit VALIDATOR_REGISTRY_LIMIT]): ValidatorIndex =
|
||||||
for i in 0..<a.len():
|
static: doAssert distinctBase(ValidatorIndex) is uint32
|
||||||
|
for i in 0..<a.len.uint32:
|
||||||
yield i.ValidatorIndex
|
yield i.ValidatorIndex
|
||||||
|
|
||||||
iterator vindices*(
|
iterator vindices*(
|
||||||
a: List[Validator, Limit VALIDATOR_REGISTRY_LIMIT]): ValidatorIndex =
|
a: List[Validator, Limit VALIDATOR_REGISTRY_LIMIT]): ValidatorIndex =
|
||||||
for i in 0..<a.len():
|
static: doAssert distinctBase(ValidatorIndex) is uint32
|
||||||
|
for i in 0..<a.len.uint32:
|
||||||
yield i.ValidatorIndex
|
yield i.ValidatorIndex
|
||||||
|
|
||||||
template `==`*(x, y: JustificationBits): bool =
|
template `==`*(x, y: JustificationBits): bool =
|
||||||
|
|
|
@ -27,7 +27,6 @@ import
|
||||||
../extras,
|
../extras,
|
||||||
"."/[beaconstate, eth2_merkleization, validator]
|
"."/[beaconstate, eth2_merkleization, validator]
|
||||||
|
|
||||||
from std/algorithm import sort
|
|
||||||
from std/math import sum, `^`
|
from std/math import sum, `^`
|
||||||
from ./datatypes/capella import
|
from ./datatypes/capella import
|
||||||
BeaconState, HistoricalSummary, Withdrawal, WithdrawalIndex
|
BeaconState, HistoricalSummary, Withdrawal, WithdrawalIndex
|
||||||
|
@ -811,7 +810,9 @@ func process_rewards_and_penalties*(
|
||||||
decrease_balance(balance, info.validators[vidx].delta.penalties)
|
decrease_balance(balance, info.validators[vidx].delta.penalties)
|
||||||
state.balances.asSeq()[vidx] = balance
|
state.balances.asSeq()[vidx] = balance
|
||||||
|
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/beacon-chain.md#registry-updates
|
from std/heapqueue import HeapQueue, `[]`, len, push, replace
|
||||||
|
|
||||||
|
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/beacon-chain.md#registry-updates
|
||||||
func process_registry_updates*(
|
func process_registry_updates*(
|
||||||
cfg: RuntimeConfig, state: var ForkyBeaconState, cache: var StateCache):
|
cfg: RuntimeConfig, state: var ForkyBeaconState, cache: var StateCache):
|
||||||
Result[void, cstring] =
|
Result[void, cstring] =
|
||||||
|
@ -832,6 +833,13 @@ func process_registry_updates*(
|
||||||
# the current epoch, 1 + MAX_SEED_LOOKAHEAD epochs ahead. Thus caches
|
# the current epoch, 1 + MAX_SEED_LOOKAHEAD epochs ahead. Thus caches
|
||||||
# remain valid for this epoch through though this function along with
|
# remain valid for this epoch through though this function along with
|
||||||
# the rest of the epoch transition.
|
# the rest of the epoch transition.
|
||||||
|
#
|
||||||
|
# This implementation fuses the two loops over all validators in the
|
||||||
|
# spec code.
|
||||||
|
|
||||||
|
## Queue validators eligible for activation and not dequeued for activation
|
||||||
|
var activation_queue: HeapQueue[(uint64, uint32)]
|
||||||
|
let churn_limit = get_validator_churn_limit(cfg, state, cache)
|
||||||
for vidx in state.validators.vindices:
|
for vidx in state.validators.vindices:
|
||||||
if is_eligible_for_activation_queue(state.validators.item(vidx)):
|
if is_eligible_for_activation_queue(state.validators.item(vidx)):
|
||||||
state.validators.mitem(vidx).activation_eligibility_epoch =
|
state.validators.mitem(vidx).activation_eligibility_epoch =
|
||||||
|
@ -841,25 +849,23 @@ func process_registry_updates*(
|
||||||
state.validators.item(vidx).effective_balance <= cfg.EJECTION_BALANCE:
|
state.validators.item(vidx).effective_balance <= cfg.EJECTION_BALANCE:
|
||||||
? initiate_validator_exit(cfg, state, vidx, cache)
|
? initiate_validator_exit(cfg, state, vidx, cache)
|
||||||
|
|
||||||
## Queue validators eligible for activation and not dequeued for activation
|
|
||||||
var activation_queue : seq[tuple[a: Epoch, b: ValidatorIndex]] = @[]
|
|
||||||
for vidx in state.validators.vindices:
|
|
||||||
let validator = unsafeAddr state.validators.item(vidx)
|
let validator = unsafeAddr state.validators.item(vidx)
|
||||||
if is_eligible_for_activation(state, validator[]):
|
if is_eligible_for_activation(state, validator[]):
|
||||||
activation_queue.add (
|
let val_key =
|
||||||
validator[].activation_eligibility_epoch, vidx)
|
(FAR_FUTURE_EPOCH - validator[].activation_eligibility_epoch,
|
||||||
|
high(distinctBase(ValidatorIndex)) - distinctBase(vidx))
|
||||||
activation_queue.sort(system.cmp)
|
if activation_queue.len.uint64 < churn_limit:
|
||||||
|
activation_queue.push val_key
|
||||||
|
elif val_key > activation_queue[0]:
|
||||||
|
discard activation_queue.replace val_key
|
||||||
|
|
||||||
## Dequeued validators for activation up to churn limit (without resetting
|
## Dequeued validators for activation up to churn limit (without resetting
|
||||||
## activation epoch)
|
## activation epoch)
|
||||||
let churn_limit = get_validator_churn_limit(cfg, state, cache)
|
doAssert activation_queue.len.uint64 <= churn_limit
|
||||||
for i, epoch_and_index in activation_queue:
|
for i in 0 ..< activation_queue.len:
|
||||||
if i.uint64 >= churn_limit:
|
let (_, vidx_complement) = activation_queue[i]
|
||||||
break
|
state.validators.mitem(
|
||||||
let
|
high(distinctBase(ValidatorIndex)) - vidx_complement).activation_epoch =
|
||||||
(_, vidx) = epoch_and_index
|
|
||||||
state.validators.mitem(vidx).activation_epoch =
|
|
||||||
compute_activation_exit_epoch(get_current_epoch(state))
|
compute_activation_exit_epoch(get_current_epoch(state))
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
|
|
Loading…
Reference in New Issue