2018-11-28 19:49:03 +00:00
# beacon_chain
2024-01-06 14:26:56 +00:00
# Copyright (c) 2018-2024 Status Research & Development GmbH
2018-11-28 19:49:03 +00:00
# Licensed and distributed under either of
2019-11-25 15:30:02 +00:00
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
2018-11-28 19:49:03 +00:00
# at your option. This file may not be copied, modified, or distributed except according to those terms.
2023-01-20 14:14:37 +00:00
{. push raises : [ ] . }
2020-04-22 05:53:02 +00:00
2018-11-28 19:49:03 +00:00
import
performance fixes (#2259)
* performance fixes
* don't mark tree cache as dirty on read-only List accesses
* store only blob in memory for keys and signatures, parse blob lazily
* compare public keys by blob instead of parsing / converting to raw
* compare Eth2Digest using non-constant-time comparison
* avoid some unnecessary validator copying
This branch will in particular speed up deposit processing which has
been slowing down block replay.
Pre (mainnet, 1600 blocks):
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3450.269, 0.000, 3450.269, 3450.269, 1, Initialize DB
0.417, 0.822, 0.036, 21.098, 1400, Load block from database
16.521, 0.000, 16.521, 16.521, 1, Load state from database
27.906, 50.846, 8.104, 1507.633, 1350, Apply block
52.617, 37.029, 20.640, 135.938, 50, Apply epoch block
```
Post:
```
3502.715, 0.000, 3502.715, 3502.715, 1, Initialize DB
0.080, 0.560, 0.035, 21.015, 1400, Load block from database
17.595, 0.000, 17.595, 17.595, 1, Load state from database
15.706, 11.028, 8.300, 107.537, 1350, Apply block
33.217, 12.622, 17.331, 60.580, 50, Apply epoch block
```
* more perf fixes
* load EpochRef cache into StateCache more aggressively
* point out security concern with public key cache
* reuse proposer index from state when processing block
* avoid genericAssign in a few more places
* don't parse key when signature is unparseable
* fix `==` overload for Eth2Digest
* preallocate validator list when getting active validators
* speed up proposer index calculation a little bit
* reuse cache when replaying blocks in ncli_db
* avoid a few more copying loops
```
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3279.158, 0.000, 3279.158, 3279.158, 1, Initialize DB
0.072, 0.357, 0.035, 13.400, 1400, Load block from database
17.295, 0.000, 17.295, 17.295, 1, Load state from database
5.918, 9.896, 0.198, 98.028, 1350, Apply block
15.888, 10.951, 7.902, 39.535, 50, Apply epoch block
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
* clear full balance cache before processing rewards and penalties
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3947.901, 0.000, 3947.901, 3947.901, 1, Initialize DB
0.124, 0.506, 0.026, 202.370, 363345, Load block from database
97.614, 0.000, 97.614, 97.614, 1, Load state from database
0.186, 0.188, 0.012, 99.561, 357262, Advance slot, non-epoch
14.161, 5.966, 1.099, 395.511, 11524, Advance slot, epoch
1.372, 4.170, 0.017, 276.401, 363345, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
2021-01-25 12:04:18 +00:00
stew / assign2 ,
2020-11-27 22:16:13 +00:00
json_serialization / std / sets ,
chronicles ,
2022-01-06 11:25:35 +00:00
. / datatypes / [ phase0 , altair , bellatrix ] ,
2021-12-03 14:46:56 +00:00
" . " / [ eth2_merkleization , forks , signatures , validator ]
2018-11-28 19:49:03 +00:00
2022-12-08 16:21:53 +00:00
from std / algorithm import fill
2023-08-02 23:03:40 +00:00
from std / sequtils import anyIt , mapIt , toSeq
2022-10-27 06:29:24 +00:00
from . / datatypes / capella import BeaconState , ExecutionPayloadHeader , Withdrawal
2023-02-23 02:10:07 +00:00
export extras , forks , validator , chronicles
2021-05-28 15:25:58 +00:00
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#increase_balance
performance fixes (#2259)
* performance fixes
* don't mark tree cache as dirty on read-only List accesses
* store only blob in memory for keys and signatures, parse blob lazily
* compare public keys by blob instead of parsing / converting to raw
* compare Eth2Digest using non-constant-time comparison
* avoid some unnecessary validator copying
This branch will in particular speed up deposit processing which has
been slowing down block replay.
Pre (mainnet, 1600 blocks):
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3450.269, 0.000, 3450.269, 3450.269, 1, Initialize DB
0.417, 0.822, 0.036, 21.098, 1400, Load block from database
16.521, 0.000, 16.521, 16.521, 1, Load state from database
27.906, 50.846, 8.104, 1507.633, 1350, Apply block
52.617, 37.029, 20.640, 135.938, 50, Apply epoch block
```
Post:
```
3502.715, 0.000, 3502.715, 3502.715, 1, Initialize DB
0.080, 0.560, 0.035, 21.015, 1400, Load block from database
17.595, 0.000, 17.595, 17.595, 1, Load state from database
15.706, 11.028, 8.300, 107.537, 1350, Apply block
33.217, 12.622, 17.331, 60.580, 50, Apply epoch block
```
* more perf fixes
* load EpochRef cache into StateCache more aggressively
* point out security concern with public key cache
* reuse proposer index from state when processing block
* avoid genericAssign in a few more places
* don't parse key when signature is unparseable
* fix `==` overload for Eth2Digest
* preallocate validator list when getting active validators
* speed up proposer index calculation a little bit
* reuse cache when replaying blocks in ncli_db
* avoid a few more copying loops
```
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3279.158, 0.000, 3279.158, 3279.158, 1, Initialize DB
0.072, 0.357, 0.035, 13.400, 1400, Load block from database
17.295, 0.000, 17.295, 17.295, 1, Load state from database
5.918, 9.896, 0.198, 98.028, 1350, Apply block
15.888, 10.951, 7.902, 39.535, 50, Apply epoch block
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
* clear full balance cache before processing rewards and penalties
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3947.901, 0.000, 3947.901, 3947.901, 1, Initialize DB
0.124, 0.506, 0.026, 202.370, 363345, Load block from database
97.614, 0.000, 97.614, 97.614, 1, Load state from database
0.186, 0.188, 0.012, 99.561, 357262, Advance slot, non-epoch
14.161, 5.966, 1.099, 395.511, 11524, Advance slot, epoch
1.372, 4.170, 0.017, 276.401, 363345, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
2021-01-25 12:04:18 +00:00
func increase_balance * ( balance : var Gwei , delta : Gwei ) =
balance + = delta
2019-05-09 12:27:37 +00:00
func increase_balance * (
2021-11-05 07:34:34 +00:00
state : var ForkyBeaconState , index : ValidatorIndex , delta : Gwei ) =
2020-09-08 08:54:55 +00:00
## Increase the validator balance at index ``index`` by ``delta``.
2024-03-19 13:22:07 +00:00
if delta ! = 0 . Gwei : # avoid dirtying the balance cache if not needed
2022-05-30 13:30:42 +00:00
increase_balance ( state . balances . mitem ( index ) , delta )
2019-03-08 17:44:31 +00:00
2024-04-18 01:00:04 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#decrease_balance
performance fixes (#2259)
* performance fixes
* don't mark tree cache as dirty on read-only List accesses
* store only blob in memory for keys and signatures, parse blob lazily
* compare public keys by blob instead of parsing / converting to raw
* compare Eth2Digest using non-constant-time comparison
* avoid some unnecessary validator copying
This branch will in particular speed up deposit processing which has
been slowing down block replay.
Pre (mainnet, 1600 blocks):
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3450.269, 0.000, 3450.269, 3450.269, 1, Initialize DB
0.417, 0.822, 0.036, 21.098, 1400, Load block from database
16.521, 0.000, 16.521, 16.521, 1, Load state from database
27.906, 50.846, 8.104, 1507.633, 1350, Apply block
52.617, 37.029, 20.640, 135.938, 50, Apply epoch block
```
Post:
```
3502.715, 0.000, 3502.715, 3502.715, 1, Initialize DB
0.080, 0.560, 0.035, 21.015, 1400, Load block from database
17.595, 0.000, 17.595, 17.595, 1, Load state from database
15.706, 11.028, 8.300, 107.537, 1350, Apply block
33.217, 12.622, 17.331, 60.580, 50, Apply epoch block
```
* more perf fixes
* load EpochRef cache into StateCache more aggressively
* point out security concern with public key cache
* reuse proposer index from state when processing block
* avoid genericAssign in a few more places
* don't parse key when signature is unparseable
* fix `==` overload for Eth2Digest
* preallocate validator list when getting active validators
* speed up proposer index calculation a little bit
* reuse cache when replaying blocks in ncli_db
* avoid a few more copying loops
```
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3279.158, 0.000, 3279.158, 3279.158, 1, Initialize DB
0.072, 0.357, 0.035, 13.400, 1400, Load block from database
17.295, 0.000, 17.295, 17.295, 1, Load state from database
5.918, 9.896, 0.198, 98.028, 1350, Apply block
15.888, 10.951, 7.902, 39.535, 50, Apply epoch block
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
* clear full balance cache before processing rewards and penalties
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3947.901, 0.000, 3947.901, 3947.901, 1, Initialize DB
0.124, 0.506, 0.026, 202.370, 363345, Load block from database
97.614, 0.000, 97.614, 97.614, 1, Load state from database
0.186, 0.188, 0.012, 99.561, 357262, Advance slot, non-epoch
14.161, 5.966, 1.099, 395.511, 11524, Advance slot, epoch
1.372, 4.170, 0.017, 276.401, 363345, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
2021-01-25 12:04:18 +00:00
func decrease_balance * ( balance : var Gwei , delta : Gwei ) =
balance =
if delta > balance :
2024-03-19 13:22:07 +00:00
0 . Gwei
performance fixes (#2259)
* performance fixes
* don't mark tree cache as dirty on read-only List accesses
* store only blob in memory for keys and signatures, parse blob lazily
* compare public keys by blob instead of parsing / converting to raw
* compare Eth2Digest using non-constant-time comparison
* avoid some unnecessary validator copying
This branch will in particular speed up deposit processing which has
been slowing down block replay.
Pre (mainnet, 1600 blocks):
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3450.269, 0.000, 3450.269, 3450.269, 1, Initialize DB
0.417, 0.822, 0.036, 21.098, 1400, Load block from database
16.521, 0.000, 16.521, 16.521, 1, Load state from database
27.906, 50.846, 8.104, 1507.633, 1350, Apply block
52.617, 37.029, 20.640, 135.938, 50, Apply epoch block
```
Post:
```
3502.715, 0.000, 3502.715, 3502.715, 1, Initialize DB
0.080, 0.560, 0.035, 21.015, 1400, Load block from database
17.595, 0.000, 17.595, 17.595, 1, Load state from database
15.706, 11.028, 8.300, 107.537, 1350, Apply block
33.217, 12.622, 17.331, 60.580, 50, Apply epoch block
```
* more perf fixes
* load EpochRef cache into StateCache more aggressively
* point out security concern with public key cache
* reuse proposer index from state when processing block
* avoid genericAssign in a few more places
* don't parse key when signature is unparseable
* fix `==` overload for Eth2Digest
* preallocate validator list when getting active validators
* speed up proposer index calculation a little bit
* reuse cache when replaying blocks in ncli_db
* avoid a few more copying loops
```
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3279.158, 0.000, 3279.158, 3279.158, 1, Initialize DB
0.072, 0.357, 0.035, 13.400, 1400, Load block from database
17.295, 0.000, 17.295, 17.295, 1, Load state from database
5.918, 9.896, 0.198, 98.028, 1350, Apply block
15.888, 10.951, 7.902, 39.535, 50, Apply epoch block
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
* clear full balance cache before processing rewards and penalties
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3947.901, 0.000, 3947.901, 3947.901, 1, Initialize DB
0.124, 0.506, 0.026, 202.370, 363345, Load block from database
97.614, 0.000, 97.614, 97.614, 1, Load state from database
0.186, 0.188, 0.012, 99.561, 357262, Advance slot, non-epoch
14.161, 5.966, 1.099, 395.511, 11524, Advance slot, epoch
1.372, 4.170, 0.017, 276.401, 363345, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
2021-01-25 12:04:18 +00:00
else :
balance - delta
2019-05-09 12:27:37 +00:00
func decrease_balance * (
2021-11-05 07:34:34 +00:00
state : var ForkyBeaconState , index : ValidatorIndex , delta : Gwei ) =
2020-09-08 08:54:55 +00:00
## Decrease the validator balance at index ``index`` by ``delta``, with
## underflow protection.
2024-03-19 13:22:07 +00:00
if delta ! = 0 . Gwei : # avoid dirtying the balance cache if not needed
2022-05-30 13:30:42 +00:00
decrease_balance ( state . balances . mitem ( index ) , delta )
2019-05-09 12:27:37 +00:00
2023-06-13 14:03:49 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/beacon-chain.md#deposits
2023-05-05 20:38:51 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/altair/beacon-chain.md#modified-apply_deposit
2024-04-26 07:18:44 +00:00
func get_validator_from_deposit * (
state : phase0 . BeaconState | altair . BeaconState | bellatrix . BeaconState |
capella . BeaconState | deneb . BeaconState ,
deposit : DepositData ) : Validator =
2020-07-27 10:59:57 +00:00
let
2020-11-14 21:43:27 +00:00
amount = deposit . amount
2020-07-27 10:59:57 +00:00
effective_balance = min (
2024-03-19 13:22:07 +00:00
amount - amount mod EFFECTIVE_BALANCE_INCREMENT . Gwei ,
MAX_EFFECTIVE_BALANCE . Gwei )
2020-07-27 10:59:57 +00:00
Validator (
2024-02-21 19:06:19 +00:00
pubkeyData : HashedValidatorPubKey . init ( deposit . pubkey ) ,
2020-11-14 21:43:27 +00:00
withdrawal_credentials : deposit . withdrawal_credentials ,
2020-07-27 10:59:57 +00:00
activation_eligibility_epoch : FAR_FUTURE_EPOCH ,
activation_epoch : FAR_FUTURE_EPOCH ,
exit_epoch : FAR_FUTURE_EPOCH ,
withdrawable_epoch : FAR_FUTURE_EPOCH ,
effective_balance : effective_balance
)
2024-04-26 07:18:44 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#updated-get_validator_from_deposit
func get_validator_from_deposit * (
state : electra . BeaconState , deposit : DepositData ) : Validator =
Validator (
pubkeyData : HashedValidatorPubKey . init ( deposit . pubkey ) ,
withdrawal_credentials : deposit . withdrawal_credentials ,
activation_eligibility_epoch : FAR_FUTURE_EPOCH ,
activation_epoch : FAR_FUTURE_EPOCH ,
exit_epoch : FAR_FUTURE_EPOCH ,
withdrawable_epoch : FAR_FUTURE_EPOCH ,
effective_balance : 0 . Gwei # [Modified in Electra:EIP7251]
)
2024-02-22 02:42:57 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/phase0/beacon-chain.md#compute_activation_exit_epoch
2021-10-12 11:36:52 +00:00
func compute_activation_exit_epoch * ( epoch : Epoch ) : Epoch =
More 0.8.0 updates (#311)
* replace BeaconState.finalized_{epoch,root} with BeaconState.finalized_checkpoint; rename get_delayed_activation_exit_epoch(...) to compute_activation_exit_epoch(...) and mark as 0.8.0; update get_churn_limit(...)/get_validator_churn_limit(...) to 0.8.0; update process_registry_updates(...) to 0.8.0
* update process_crosslinks(...) to 0.8.0; mark compute_start_slot_of_epoch(...) and get_committee_count(...) as 0.8.0
* mark Fork, is_slashable_validator(...), and get_beacon_proposer_index(...) as 0.8.0
* rename LATEST_SLASHED_EXIT_LENGTH to EPOCHS_PER_SLASHINGS_VECTOR; update process_slashings(...) to 0.8.0; remove pointless type conversion warning in get_previous_epoch(...)
* convert remaining references to finalized_epoch to finalized_checkpoint.epoch
* update slash_validator(...) to 0.8.0; mark inital value, Gwei, and time constants as 0.8.0; mark hash(...) and processBlockHeader(...) as 0.8.0
* rename WHISTLEBLOWING_REWARD_QUOTIENT to WHISTLEBLOWER_REWARD_QUOTIENT; rename LATEST_ACTIVE_INDEX_ROOTS_LENGTH to EPOCHS_PER_HISTORICAL_VECTOR (randao will also get merged into this); remove get_active_index_root(...); mark time parameter, signature domain types, and max operations per block constants as 0.8.0; update rewards and penalties constants to 0.8.0
* update is_valid_indexed_attestation(...) to 0.8.0; mark process_slot(...) as 0.8.0
* replace BeaconState.{current,previous}_justified_{epoch,root} with BeaconState.{current,previous}_justified_checkpoint
2019-07-05 08:30:05 +00:00
## Return the epoch during which validator activations and exits initiated in
## ``epoch`` take effect.
initial 0.9.0 spec sync (#509)
* rename compute_epoch_of_slot(...) to compute_epoch_at_slot(...)
* remove some unnecessary imports; remove some crosslink-related code and tests; complete renaming of compute_epoch_of_slot(...) to compute_epoch_at_slot(...)
* rm more transfer-related code and tests; rm more unnecessary strutils imports
* rm remaining unused imports
* remove useless get_empty_per_epoch_cache(...)/compute_start_slot_of_epoch(...) calls
* rename compute_start_slot_of_epoch(...) to compute_start_slot_at_epoch(...)
* rename ACTIVATION_EXIT_DELAY to MAX_SEED_LOOKAHEAD
* update domain types to 0.9.0
* mark AttesterSlashing, IndexedAttestation, AttestationDataAndCustodyBit, DepositData, BeaconBlockHeader, Fork, integer_squareroot(...), and process_voluntary_exit(...) as 0.9.0
* mark increase_balance(...), decrease_balance(...), get_block_root(...), CheckPoint, Deposit, PendingAttestation, HistoricalBatch, is_active_validator(...), and is_slashable_attestation_data(...) as 0.9.0
* mark compute_activation_exit_epoch(...), bls_verify(...), Validator, get_active_validator_indices(...), get_current_epoch(...), get_total_active_balance(...), and get_previous_epoch(...) as 0.9.0
* mark get_block_root_at_slot(...), ProposerSlashing, get_domain(...), VoluntaryExit, mainnet preset Gwei values, minimal preset max operations, process_block_header(...), and is_slashable_validator(...) as 0.9.0
* mark makeWithdrawalCredentials(...), get_validator_churn_limit(...), get_total_balance(...), is_valid_indexed_attestation(...), bls_aggregate_pubkeys(...), initial genesis value/constants, Attestation, get_randao_mix(...), mainnet preset max operations per block constants, minimal preset Gwei values and time parameters, process_eth1_data(...), get_shuffled_seq(...), compute_committee(...), and process_slots(...) as 0.9.0; partially update get_indexed_attestation(...) to 0.9.0 by removing crosslink refs and associated tests
* mark initiate_validator_exit(...), process_registry_updates(...), BeaconBlock, Eth1Data, compute_domain(...), process_randao(...), process_attester_slashing(...), get_base_reward(...), and process_slot(...) as 0.9.0
2019-10-30 19:41:19 +00:00
epoch + 1 + MAX_SEED_LOOKAHEAD
2019-01-29 03:22:22 +00:00
2024-04-17 03:51:16 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#get_validator_churn_limit
2021-10-12 11:36:52 +00:00
func get_validator_churn_limit * (
2021-11-05 07:34:34 +00:00
cfg : RuntimeConfig , state : ForkyBeaconState , cache : var StateCache ) :
2021-05-28 15:25:58 +00:00
uint64 =
2020-09-08 08:54:55 +00:00
## Return the validator churn limit for the current epoch.
2020-07-23 17:01:07 +00:00
max (
Implement split preset/config support (#2710)
* Implement split preset/config support
This is the initial bulk refactor to introduce runtime config values in
a number of places, somewhat replacing the existing mechanism of loading
network metadata.
It still needs more work, this is the initial refactor that introduces
runtime configuration in some of the places that need it.
The PR changes the way presets and constants work, to match the spec. In
particular, a "preset" now refers to the compile-time configuration
while a "cfg" or "RuntimeConfig" is the dynamic part.
A single binary can support either mainnet or minimal, but not both.
Support for other presets has been removed completely (can be readded,
in case there's need).
There's a number of outstanding tasks:
* `SECONDS_PER_SLOT` still needs fixing
* loading custom runtime configs needs redoing
* checking constants against YAML file
* yeerongpilly support
`build/nimbus_beacon_node --network=yeerongpilly --discv5:no --log-level=DEBUG`
* load fork epoch from config
* fix fork digest sent in status
* nicer error string for request failures
* fix tools
* one more
* fixup
* fixup
* fixup
* use "standard" network definition folder in local testnet
Files are loaded from their standard locations, including genesis etc,
to conform to the format used in the `eth2-networks` repo.
* fix launch scripts, allow unknown config values
* fix base config of rest test
* cleanups
* bundle mainnet config using common loader
* fix spec links and names
* only include supported preset in binary
* drop yeerongpilly, add altair-devnet-0, support boot_enr.yaml
2021-07-12 13:01:38 +00:00
cfg . MIN_PER_EPOCH_CHURN_LIMIT ,
2020-07-23 17:01:07 +00:00
count_active_validators (
Implement split preset/config support (#2710)
* Implement split preset/config support
This is the initial bulk refactor to introduce runtime config values in
a number of places, somewhat replacing the existing mechanism of loading
network metadata.
It still needs more work, this is the initial refactor that introduces
runtime configuration in some of the places that need it.
The PR changes the way presets and constants work, to match the spec. In
particular, a "preset" now refers to the compile-time configuration
while a "cfg" or "RuntimeConfig" is the dynamic part.
A single binary can support either mainnet or minimal, but not both.
Support for other presets has been removed completely (can be readded,
in case there's need).
There's a number of outstanding tasks:
* `SECONDS_PER_SLOT` still needs fixing
* loading custom runtime configs needs redoing
* checking constants against YAML file
* yeerongpilly support
`build/nimbus_beacon_node --network=yeerongpilly --discv5:no --log-level=DEBUG`
* load fork epoch from config
* fix fork digest sent in status
* nicer error string for request failures
* fix tools
* one more
* fixup
* fixup
* fixup
* use "standard" network definition folder in local testnet
Files are loaded from their standard locations, including genesis etc,
to conform to the format used in the `eth2-networks` repo.
* fix launch scripts, allow unknown config values
* fix base config of rest test
* cleanups
* bundle mainnet config using common loader
* fix spec links and names
* only include supported preset in binary
* drop yeerongpilly, add altair-devnet-0, support boot_enr.yaml
2021-07-12 13:01:38 +00:00
state , state . get_current_epoch ( ) , cache ) div cfg . CHURN_LIMIT_QUOTIENT )
More 0.6.1 updates (#274)
* implement get_churn_limit from 0.6.1; update initiate_validator_exit and get_previous_epoch to 0.6.1; remove obsoleted/non-spec reduce_balance, replaced by decrease_balance; mark BeaconBlock as 0.6.1
* rename get_block_root to get_block_root_at_slot and introduce epoch-oriented get_block_root; implement get_attestation_slot, get_matching_source_attestations, get_matching_target_attestations, get_matching_head_attestations, 0.6.1 get_attesting_indices, get_unslashed_attesting_indices, get_attestation_deltas, process_rewards_and_penalties; rm get_inactivity_penalty
* update Validator and processVoluntaryExits to 0.6.1; rm obsolete inclusion_slots/inclusion_distances
* rm removed activate_validator; mark DepositData, misc values, Gwei values, Randao processing, state caching as 0.6.1; update GENESIS_SLOT to 64, since it doesn't quite yet work at 0
* mark BeaconBlockHeader as 0.6.1; update BeaconBlockBody to 0.6.1; rename WHISTLEBLOWER_REWARD_QUOTIENT to WHISTLEBLOWING_REWARD_QUOTIENT; update slash_validator to 0.6.1
* implement 0.6.2 is_slashable_validator; update processProposerSlashings to 0.6.2; mark state caching as 0.6.2
* mark get_total_active_balance and process_slashings as 0.6.2; update get_base_reward to 0.6.2
* rm prepare_validator_for_withdrawal, process_exit_queue; mark mainnet misc constants as 0.6.2; update process block header to 0.6.2
* address mratsim's code review comment
2019-05-29 10:08:56 +00:00
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#new-get_validator_activation_churn_limit
2023-09-20 11:39:56 +00:00
func get_validator_activation_churn_limit * (
2024-02-26 06:49:12 +00:00
cfg : RuntimeConfig , state : deneb . BeaconState | electra . BeaconState ,
cache : var StateCache ) : uint64 =
2023-09-20 11:39:56 +00:00
## Return the validator activation churn limit for the current epoch.
min (
cfg . MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT ,
get_validator_churn_limit ( cfg , state , cache ) )
2024-04-02 12:18:40 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#initiate_validator_exit
2024-04-24 12:28:47 +00:00
func get_state_exit_queue_info * (
state : phase0 . BeaconState | altair . BeaconState | bellatrix . BeaconState |
capella . BeaconState | deneb . BeaconState ) : ExitQueueInfo =
2024-03-27 08:18:50 +00:00
var
exit_queue_epoch = compute_activation_exit_epoch ( get_current_epoch ( state ) )
exit_queue_churn : uint64
2020-11-02 17:34:23 +00:00
# Compute max exit epoch
performance fixes (#2259)
* performance fixes
* don't mark tree cache as dirty on read-only List accesses
* store only blob in memory for keys and signatures, parse blob lazily
* compare public keys by blob instead of parsing / converting to raw
* compare Eth2Digest using non-constant-time comparison
* avoid some unnecessary validator copying
This branch will in particular speed up deposit processing which has
been slowing down block replay.
Pre (mainnet, 1600 blocks):
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3450.269, 0.000, 3450.269, 3450.269, 1, Initialize DB
0.417, 0.822, 0.036, 21.098, 1400, Load block from database
16.521, 0.000, 16.521, 16.521, 1, Load state from database
27.906, 50.846, 8.104, 1507.633, 1350, Apply block
52.617, 37.029, 20.640, 135.938, 50, Apply epoch block
```
Post:
```
3502.715, 0.000, 3502.715, 3502.715, 1, Initialize DB
0.080, 0.560, 0.035, 21.015, 1400, Load block from database
17.595, 0.000, 17.595, 17.595, 1, Load state from database
15.706, 11.028, 8.300, 107.537, 1350, Apply block
33.217, 12.622, 17.331, 60.580, 50, Apply epoch block
```
* more perf fixes
* load EpochRef cache into StateCache more aggressively
* point out security concern with public key cache
* reuse proposer index from state when processing block
* avoid genericAssign in a few more places
* don't parse key when signature is unparseable
* fix `==` overload for Eth2Digest
* preallocate validator list when getting active validators
* speed up proposer index calculation a little bit
* reuse cache when replaying blocks in ncli_db
* avoid a few more copying loops
```
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3279.158, 0.000, 3279.158, 3279.158, 1, Initialize DB
0.072, 0.357, 0.035, 13.400, 1400, Load block from database
17.295, 0.000, 17.295, 17.295, 1, Load state from database
5.918, 9.896, 0.198, 98.028, 1350, Apply block
15.888, 10.951, 7.902, 39.535, 50, Apply epoch block
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
* clear full balance cache before processing rewards and penalties
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3947.901, 0.000, 3947.901, 3947.901, 1, Initialize DB
0.124, 0.506, 0.026, 202.370, 363345, Load block from database
97.614, 0.000, 97.614, 97.614, 1, Load state from database
0.186, 0.188, 0.012, 99.561, 357262, Advance slot, non-epoch
14.161, 5.966, 1.099, 395.511, 11524, Advance slot, epoch
1.372, 4.170, 0.017, 276.401, 363345, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
2021-01-25 12:04:18 +00:00
for idx in 0 .. < state . validators . len :
2022-05-30 13:30:42 +00:00
let exit_epoch = state . validators . item ( idx ) . exit_epoch
performance fixes (#2259)
* performance fixes
* don't mark tree cache as dirty on read-only List accesses
* store only blob in memory for keys and signatures, parse blob lazily
* compare public keys by blob instead of parsing / converting to raw
* compare Eth2Digest using non-constant-time comparison
* avoid some unnecessary validator copying
This branch will in particular speed up deposit processing which has
been slowing down block replay.
Pre (mainnet, 1600 blocks):
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3450.269, 0.000, 3450.269, 3450.269, 1, Initialize DB
0.417, 0.822, 0.036, 21.098, 1400, Load block from database
16.521, 0.000, 16.521, 16.521, 1, Load state from database
27.906, 50.846, 8.104, 1507.633, 1350, Apply block
52.617, 37.029, 20.640, 135.938, 50, Apply epoch block
```
Post:
```
3502.715, 0.000, 3502.715, 3502.715, 1, Initialize DB
0.080, 0.560, 0.035, 21.015, 1400, Load block from database
17.595, 0.000, 17.595, 17.595, 1, Load state from database
15.706, 11.028, 8.300, 107.537, 1350, Apply block
33.217, 12.622, 17.331, 60.580, 50, Apply epoch block
```
* more perf fixes
* load EpochRef cache into StateCache more aggressively
* point out security concern with public key cache
* reuse proposer index from state when processing block
* avoid genericAssign in a few more places
* don't parse key when signature is unparseable
* fix `==` overload for Eth2Digest
* preallocate validator list when getting active validators
* speed up proposer index calculation a little bit
* reuse cache when replaying blocks in ncli_db
* avoid a few more copying loops
```
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3279.158, 0.000, 3279.158, 3279.158, 1, Initialize DB
0.072, 0.357, 0.035, 13.400, 1400, Load block from database
17.295, 0.000, 17.295, 17.295, 1, Load state from database
5.918, 9.896, 0.198, 98.028, 1350, Apply block
15.888, 10.951, 7.902, 39.535, 50, Apply epoch block
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
* clear full balance cache before processing rewards and penalties
```
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
3947.901, 0.000, 3947.901, 3947.901, 1, Initialize DB
0.124, 0.506, 0.026, 202.370, 363345, Load block from database
97.614, 0.000, 97.614, 97.614, 1, Load state from database
0.186, 0.188, 0.012, 99.561, 357262, Advance slot, non-epoch
14.161, 5.966, 1.099, 395.511, 11524, Advance slot, epoch
1.372, 4.170, 0.017, 276.401, 363345, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database block store
```
2021-01-25 12:04:18 +00:00
if exit_epoch ! = FAR_FUTURE_EPOCH and exit_epoch > exit_queue_epoch :
exit_queue_epoch = exit_epoch
2020-11-02 17:34:23 +00:00
2024-03-27 08:18:50 +00:00
# Reset exit queue churn counter as the expected exit_queue_epoch updates
# via this essentially max()-but-not-FAR_FUTURE_EPOCH loop to restart the
# counting the second for loop in spec version does. Only the last count,
# the one corresponding to the ultimately correct exit_queue_epoch, won't
# be reset.
exit_queue_churn = 0
# Second spec loop body, which there is responsible for taking the already
# known exit_queue_epoch, scanning for all validators with that exit epoch
# and checking if they'll reach validator_churn_limit(state). Do that here
# incrementally to fuse the two loops and save an all-validator iteration.
if exit_epoch = = exit_queue_epoch :
2024-03-27 03:34:56 +00:00
inc exit_queue_churn
2024-04-02 12:18:40 +00:00
ExitQueueInfo (
exit_queue_epoch : exit_queue_epoch , exit_queue_churn : exit_queue_churn )
2024-04-24 12:28:47 +00:00
func get_state_exit_queue_info * ( state : electra . BeaconState ) : ExitQueueInfo =
# Electra initiate_validator_exit doesn't have same quadratic aspect given
# StateCache balance caching
default ( ExitQueueInfo )
2024-04-02 12:18:40 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#initiate_validator_exit
func initiate_validator_exit * (
2024-04-24 12:28:47 +00:00
cfg : RuntimeConfig ,
state : var ( phase0 . BeaconState | altair . BeaconState |
bellatrix . BeaconState | capella . BeaconState |
deneb . BeaconState ) ,
index : ValidatorIndex , exit_queue_info : ExitQueueInfo ,
cache : var StateCache ) : Result [ ExitQueueInfo , cstring ] =
2024-04-02 12:18:40 +00:00
## Initiate the exit of the validator with index ``index``.
if state . validators . item ( index ) . exit_epoch ! = FAR_FUTURE_EPOCH :
return ok ( exit_queue_info ) # Before touching cache
# Return if validator already initiated exit
let validator = addr state . validators . mitem ( index )
var
exit_queue_epoch = exit_queue_info . exit_queue_epoch
exit_queue_churn = exit_queue_info . exit_queue_churn
2024-03-27 08:18:50 +00:00
if exit_queue_churn > = get_validator_churn_limit ( cfg , state , cache ) :
inc exit_queue_epoch
More 0.6.1 updates (#274)
* implement get_churn_limit from 0.6.1; update initiate_validator_exit and get_previous_epoch to 0.6.1; remove obsoleted/non-spec reduce_balance, replaced by decrease_balance; mark BeaconBlock as 0.6.1
* rename get_block_root to get_block_root_at_slot and introduce epoch-oriented get_block_root; implement get_attestation_slot, get_matching_source_attestations, get_matching_target_attestations, get_matching_head_attestations, 0.6.1 get_attesting_indices, get_unslashed_attesting_indices, get_attestation_deltas, process_rewards_and_penalties; rm get_inactivity_penalty
* update Validator and processVoluntaryExits to 0.6.1; rm obsolete inclusion_slots/inclusion_distances
* rm removed activate_validator; mark DepositData, misc values, Gwei values, Randao processing, state caching as 0.6.1; update GENESIS_SLOT to 64, since it doesn't quite yet work at 0
* mark BeaconBlockHeader as 0.6.1; update BeaconBlockBody to 0.6.1; rename WHISTLEBLOWER_REWARD_QUOTIENT to WHISTLEBLOWING_REWARD_QUOTIENT; update slash_validator to 0.6.1
* implement 0.6.2 is_slashable_validator; update processProposerSlashings to 0.6.2; mark state caching as 0.6.2
* mark get_total_active_balance and process_slashings as 0.6.2; update get_base_reward to 0.6.2
* rm prepare_validator_for_withdrawal, process_exit_queue; mark mainnet misc constants as 0.6.2; update process block header to 0.6.2
* address mratsim's code review comment
2019-05-29 10:08:56 +00:00
2024-04-02 12:18:40 +00:00
# Bookkeeping for inter-operation caching; include this exit for next time
exit_queue_churn = 1
else :
inc exit_queue_churn
More 0.6.1 updates (#274)
* implement get_churn_limit from 0.6.1; update initiate_validator_exit and get_previous_epoch to 0.6.1; remove obsoleted/non-spec reduce_balance, replaced by decrease_balance; mark BeaconBlock as 0.6.1
* rename get_block_root to get_block_root_at_slot and introduce epoch-oriented get_block_root; implement get_attestation_slot, get_matching_source_attestations, get_matching_target_attestations, get_matching_head_attestations, 0.6.1 get_attesting_indices, get_unslashed_attesting_indices, get_attestation_deltas, process_rewards_and_penalties; rm get_inactivity_penalty
* update Validator and processVoluntaryExits to 0.6.1; rm obsolete inclusion_slots/inclusion_distances
* rm removed activate_validator; mark DepositData, misc values, Gwei values, Randao processing, state caching as 0.6.1; update GENESIS_SLOT to 64, since it doesn't quite yet work at 0
* mark BeaconBlockHeader as 0.6.1; update BeaconBlockBody to 0.6.1; rename WHISTLEBLOWER_REWARD_QUOTIENT to WHISTLEBLOWING_REWARD_QUOTIENT; update slash_validator to 0.6.1
* implement 0.6.2 is_slashable_validator; update processProposerSlashings to 0.6.2; mark state caching as 0.6.2
* mark get_total_active_balance and process_slashings as 0.6.2; update get_base_reward to 0.6.2
* rm prepare_validator_for_withdrawal, process_exit_queue; mark mainnet misc constants as 0.6.2; update process block header to 0.6.2
* address mratsim's code review comment
2019-05-29 10:08:56 +00:00
# Set validator exit epoch and withdrawable epoch
validator . exit_epoch = exit_queue_epoch
2022-05-25 13:49:29 +00:00
if validator . exit_epoch + cfg . MIN_VALIDATOR_WITHDRAWABILITY_DELAY <
validator . exit_epoch :
return err ( " initiate_validator_exit: exit_epoch overflowed " )
More 0.6.1 updates (#274)
* implement get_churn_limit from 0.6.1; update initiate_validator_exit and get_previous_epoch to 0.6.1; remove obsoleted/non-spec reduce_balance, replaced by decrease_balance; mark BeaconBlock as 0.6.1
* rename get_block_root to get_block_root_at_slot and introduce epoch-oriented get_block_root; implement get_attestation_slot, get_matching_source_attestations, get_matching_target_attestations, get_matching_head_attestations, 0.6.1 get_attesting_indices, get_unslashed_attesting_indices, get_attestation_deltas, process_rewards_and_penalties; rm get_inactivity_penalty
* update Validator and processVoluntaryExits to 0.6.1; rm obsolete inclusion_slots/inclusion_distances
* rm removed activate_validator; mark DepositData, misc values, Gwei values, Randao processing, state caching as 0.6.1; update GENESIS_SLOT to 64, since it doesn't quite yet work at 0
* mark BeaconBlockHeader as 0.6.1; update BeaconBlockBody to 0.6.1; rename WHISTLEBLOWER_REWARD_QUOTIENT to WHISTLEBLOWING_REWARD_QUOTIENT; update slash_validator to 0.6.1
* implement 0.6.2 is_slashable_validator; update processProposerSlashings to 0.6.2; mark state caching as 0.6.2
* mark get_total_active_balance and process_slashings as 0.6.2; update get_base_reward to 0.6.2
* rm prepare_validator_for_withdrawal, process_exit_queue; mark mainnet misc constants as 0.6.2; update process block header to 0.6.2
* address mratsim's code review comment
2019-05-29 10:08:56 +00:00
validator . withdrawable_epoch =
Implement split preset/config support (#2710)
* Implement split preset/config support
This is the initial bulk refactor to introduce runtime config values in
a number of places, somewhat replacing the existing mechanism of loading
network metadata.
It still needs more work, this is the initial refactor that introduces
runtime configuration in some of the places that need it.
The PR changes the way presets and constants work, to match the spec. In
particular, a "preset" now refers to the compile-time configuration
while a "cfg" or "RuntimeConfig" is the dynamic part.
A single binary can support either mainnet or minimal, but not both.
Support for other presets has been removed completely (can be readded,
in case there's need).
There's a number of outstanding tasks:
* `SECONDS_PER_SLOT` still needs fixing
* loading custom runtime configs needs redoing
* checking constants against YAML file
* yeerongpilly support
`build/nimbus_beacon_node --network=yeerongpilly --discv5:no --log-level=DEBUG`
* load fork epoch from config
* fix fork digest sent in status
* nicer error string for request failures
* fix tools
* one more
* fixup
* fixup
* fixup
* use "standard" network definition folder in local testnet
Files are loaded from their standard locations, including genesis etc,
to conform to the format used in the `eth2-networks` repo.
* fix launch scripts, allow unknown config values
* fix base config of rest test
* cleanups
* bundle mainnet config using common loader
* fix spec links and names
* only include supported preset in binary
* drop yeerongpilly, add altair-devnet-0, support boot_enr.yaml
2021-07-12 13:01:38 +00:00
validator . exit_epoch + cfg . MIN_VALIDATOR_WITHDRAWABILITY_DELAY
2018-12-13 16:00:55 +00:00
2024-04-02 12:18:40 +00:00
ok ( ExitQueueInfo (
exit_queue_epoch : exit_queue_epoch , exit_queue_churn : exit_queue_churn ) )
2022-05-25 13:49:29 +00:00
2024-04-24 12:28:47 +00:00
func get_total_active_balance * ( state : ForkyBeaconState , cache : var StateCache ) : Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-get_balance_churn_limit
func get_balance_churn_limit (
cfg : RuntimeConfig , state : electra . BeaconState ,
cache : var StateCache ) : Gwei =
## Return the churn limit for the current epoch.
let churn = max (
cfg . MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA . Gwei ,
get_total_active_balance ( state , cache ) div cfg . CHURN_LIMIT_QUOTIENT
)
churn - churn mod EFFECTIVE_BALANCE_INCREMENT . Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-get_activation_exit_churn_limit
func get_activation_exit_churn_limit * (
cfg : RuntimeConfig , state : electra . BeaconState , cache : var StateCache ) :
Gwei =
## Return the churn limit for the current epoch dedicated to activations and
## exits.
min (
cfg . MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT . Gwei ,
get_balance_churn_limit ( cfg , state , cache ) )
2024-04-25 18:50:54 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-get_consolidation_churn_limit
func get_consolidation_churn_limit * (
cfg : RuntimeConfig , state : electra . BeaconState , cache : var StateCache ) :
Gwei =
get_balance_churn_limit ( cfg , state , cache ) -
get_activation_exit_churn_limit ( cfg , state , cache )
2024-04-24 12:28:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-compute_exit_epoch_and_update_churn
2024-04-25 08:41:17 +00:00
func compute_exit_epoch_and_update_churn * (
2024-04-24 12:28:47 +00:00
cfg : RuntimeConfig , state : var electra . BeaconState , exit_balance : Gwei ,
cache : var StateCache ) : Epoch =
var earliest_exit_epoch = max ( state . earliest_exit_epoch ,
compute_activation_exit_epoch ( get_current_epoch ( state ) ) )
let per_epoch_churn = get_activation_exit_churn_limit ( cfg , state , cache )
# New epoch for exits.
var exit_balance_to_consume =
if state . earliest_exit_epoch < earliest_exit_epoch :
per_epoch_churn
else :
state . exit_balance_to_consume
# Exit doesn't fit in the current earliest epoch.
if exit_balance > exit_balance_to_consume :
let
balance_to_process = exit_balance - exit_balance_to_consume
additional_epochs = ( balance_to_process - 1 . Gwei ) div per_epoch_churn + 1
earliest_exit_epoch + = additional_epochs
exit_balance_to_consume + = additional_epochs * per_epoch_churn
# Consume the balance and update state variables.
state . exit_balance_to_consume = exit_balance_to_consume - exit_balance
state . earliest_exit_epoch = earliest_exit_epoch
state . earliest_exit_epoch
2024-04-25 18:50:54 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-compute_consolidation_epoch_and_update_churn
func compute_consolidation_epoch_and_update_churn * (
cfg : RuntimeConfig , state : var electra . BeaconState ,
consolidation_balance : Gwei , cache : var StateCache ) : Epoch =
var earliest_consolidation_epoch = max ( state . earliest_consolidation_epoch ,
compute_activation_exit_epoch ( get_current_epoch ( state ) ) )
let per_epoch_consolidation_churn =
get_consolidation_churn_limit ( cfg , state , cache )
# New epoch for consolidations.
var consolidation_balance_to_consume =
if state . earliest_consolidation_epoch < earliest_consolidation_epoch :
per_epoch_consolidation_churn
else :
state . consolidation_balance_to_consume
# Consolidation doesn't fit in the current earliest epoch.
if consolidation_balance > consolidation_balance_to_consume :
let
balance_to_process = consolidation_balance - consolidation_balance_to_consume
additional_epochs = ( balance_to_process - 1 . Gwei ) div per_epoch_consolidation_churn + 1
earliest_consolidation_epoch + = additional_epochs
consolidation_balance_to_consume + = additional_epochs * per_epoch_consolidation_churn
# Consume the balance and update state variables.
state . consolidation_balance_to_consume = consolidation_balance_to_consume - consolidation_balance
state . earliest_consolidation_epoch = earliest_consolidation_epoch
state . earliest_consolidation_epoch
2024-04-24 12:28:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#updated--initiate_validator_exit
func initiate_validator_exit * (
cfg : RuntimeConfig , state : var electra . BeaconState ,
index : ValidatorIndex , exit_queue_info : ExitQueueInfo ,
cache : var StateCache ) : Result [ ExitQueueInfo , cstring ] =
## Initiate the exit of the validator with index ``index``.
# Return if validator already initiated exit
var validator = state . validators . item ( index )
if validator . exit_epoch ! = FAR_FUTURE_EPOCH :
2024-04-25 08:41:17 +00:00
return ok ( static ( default ( ExitQueueInfo ) ) )
2024-04-24 12:28:47 +00:00
# Compute exit queue epoch [Modified in Electra:EIP7251]
let exit_queue_epoch = compute_exit_epoch_and_update_churn (
cfg , state , validator . effective_balance , cache )
# Set validator exit epoch and withdrawable epoch
validator . exit_epoch = exit_queue_epoch
validator . withdrawable_epoch =
Epoch ( validator . exit_epoch + cfg . MIN_VALIDATOR_WITHDRAWABILITY_DELAY )
if validator . withdrawable_epoch < validator . exit_epoch :
return err ( " Invalid large withdrawable epoch " )
state . validators . mitem ( index ) = validator
# The Electra initiate_validator_exit() isn't accidentally quadratic; ignore
ok ( static ( default ( ExitQueueInfo ) ) )
2023-02-22 13:10:00 +00:00
from . / datatypes / deneb import BeaconState
2022-12-06 12:40:13 +00:00
2024-04-18 01:00:04 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#slash_validator
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#modified-slash_validator
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/bellatrix/beacon-chain.md#modified-slash_validator
2024-04-25 08:41:17 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#updated-slash_validator
func get_slashing_penalty * (
state : ForkyBeaconState , validator_effective_balance : Gwei ) : Gwei =
2021-12-29 02:50:49 +00:00
when state is phase0 . BeaconState :
2024-04-25 08:41:17 +00:00
validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT
2021-12-29 02:50:49 +00:00
elif state is altair . BeaconState :
2024-04-25 08:41:17 +00:00
validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR
2022-12-06 12:40:13 +00:00
elif state is bellatrix . BeaconState or state is capella . BeaconState or
2024-04-25 08:41:17 +00:00
state is deneb . BeaconState :
validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX
elif state is electra . BeaconState :
validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA
2021-12-29 02:50:49 +00:00
else :
2022-01-17 12:58:33 +00:00
{. fatal : " invalid BeaconState type " . }
2021-12-29 02:50:49 +00:00
2024-02-22 02:42:57 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/phase0/beacon-chain.md#slash_validator
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#modified-slash_validator
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/bellatrix/beacon-chain.md#modified-slash_validator
2024-04-25 08:41:17 +00:00
func get_whistleblower_reward * (
state : phase0 . BeaconState | altair . BeaconState | bellatrix . BeaconState |
capella . BeaconState | deneb . BeaconState ,
validator_effective_balance : Gwei ) : Gwei =
2021-12-29 02:50:49 +00:00
validator_effective_balance div WHISTLEBLOWER_REWARD_QUOTIENT
2024-04-25 08:41:17 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#updated-slash_validator
func get_whistleblower_reward * (
state : electra . BeaconState , validator_effective_balance : Gwei ) : Gwei =
validator_effective_balance div WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA
2024-04-17 03:51:16 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#slash_validator
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#modified-slash_validator
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/bellatrix/beacon-chain.md#modified-slash_validator
2022-01-17 12:58:33 +00:00
func get_proposer_reward ( state : ForkyBeaconState , whistleblower_reward : Gwei ) : Gwei =
2021-12-29 02:50:49 +00:00
when state is phase0 . BeaconState :
whistleblower_reward div PROPOSER_REWARD_QUOTIENT
2022-10-27 06:29:24 +00:00
elif state is altair . BeaconState or state is bellatrix . BeaconState or
2024-02-26 06:49:12 +00:00
state is capella . BeaconState or state is deneb . BeaconState or
state is electra . BeaconState :
2021-12-29 02:50:49 +00:00
whistleblower_reward * PROPOSER_WEIGHT div WEIGHT_DENOMINATOR
else :
2022-01-17 12:58:33 +00:00
{. fatal : " invalid BeaconState type " . }
2021-12-29 02:50:49 +00:00
2024-02-22 02:42:57 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/phase0/beacon-chain.md#slash_validator
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#modified-slash_validator
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/bellatrix/beacon-chain.md#modified-slash_validator
Implement split preset/config support (#2710)
* Implement split preset/config support
This is the initial bulk refactor to introduce runtime config values in
a number of places, somewhat replacing the existing mechanism of loading
network metadata.
It still needs more work, this is the initial refactor that introduces
runtime configuration in some of the places that need it.
The PR changes the way presets and constants work, to match the spec. In
particular, a "preset" now refers to the compile-time configuration
while a "cfg" or "RuntimeConfig" is the dynamic part.
A single binary can support either mainnet or minimal, but not both.
Support for other presets has been removed completely (can be readded,
in case there's need).
There's a number of outstanding tasks:
* `SECONDS_PER_SLOT` still needs fixing
* loading custom runtime configs needs redoing
* checking constants against YAML file
* yeerongpilly support
`build/nimbus_beacon_node --network=yeerongpilly --discv5:no --log-level=DEBUG`
* load fork epoch from config
* fix fork digest sent in status
* nicer error string for request failures
* fix tools
* one more
* fixup
* fixup
* fixup
* use "standard" network definition folder in local testnet
Files are loaded from their standard locations, including genesis etc,
to conform to the format used in the `eth2-networks` repo.
* fix launch scripts, allow unknown config values
* fix base config of rest test
* cleanups
* bundle mainnet config using common loader
* fix spec links and names
* only include supported preset in binary
* drop yeerongpilly, add altair-devnet-0, support boot_enr.yaml
2021-07-12 13:01:38 +00:00
proc slash_validator * (
2021-11-05 07:34:34 +00:00
cfg : RuntimeConfig , state : var ForkyBeaconState ,
2024-04-02 12:18:40 +00:00
slashed_index : ValidatorIndex , pre_exit_queue_info : ExitQueueInfo ,
cache : var StateCache ) : Result [ ( Gwei , ExitQueueInfo ) , cstring ] =
2020-09-08 08:54:55 +00:00
## Slash the validator with index ``index``.
2024-04-02 12:18:40 +00:00
let
epoch = get_current_epoch ( state )
post_exit_queue_info = ? initiate_validator_exit (
cfg , state , slashed_index , pre_exit_queue_info , cache )
2022-05-30 13:30:42 +00:00
let validator = addr state . validators . mitem ( slashed_index )
2019-11-25 08:22:16 +00:00
More 0.8.0 updates (#311)
* replace BeaconState.finalized_{epoch,root} with BeaconState.finalized_checkpoint; rename get_delayed_activation_exit_epoch(...) to compute_activation_exit_epoch(...) and mark as 0.8.0; update get_churn_limit(...)/get_validator_churn_limit(...) to 0.8.0; update process_registry_updates(...) to 0.8.0
* update process_crosslinks(...) to 0.8.0; mark compute_start_slot_of_epoch(...) and get_committee_count(...) as 0.8.0
* mark Fork, is_slashable_validator(...), and get_beacon_proposer_index(...) as 0.8.0
* rename LATEST_SLASHED_EXIT_LENGTH to EPOCHS_PER_SLASHINGS_VECTOR; update process_slashings(...) to 0.8.0; remove pointless type conversion warning in get_previous_epoch(...)
* convert remaining references to finalized_epoch to finalized_checkpoint.epoch
* update slash_validator(...) to 0.8.0; mark inital value, Gwei, and time constants as 0.8.0; mark hash(...) and processBlockHeader(...) as 0.8.0
* rename WHISTLEBLOWING_REWARD_QUOTIENT to WHISTLEBLOWER_REWARD_QUOTIENT; rename LATEST_ACTIVE_INDEX_ROOTS_LENGTH to EPOCHS_PER_HISTORICAL_VECTOR (randao will also get merged into this); remove get_active_index_root(...); mark time parameter, signature domain types, and max operations per block constants as 0.8.0; update rewards and penalties constants to 0.8.0
* update is_valid_indexed_attestation(...) to 0.8.0; mark process_slot(...) as 0.8.0
* replace BeaconState.{current,previous}_justified_{epoch,root} with BeaconState.{current,previous}_justified_checkpoint
2019-07-05 08:30:05 +00:00
validator . slashed = true
validator . withdrawable_epoch =
max ( validator . withdrawable_epoch , epoch + EPOCHS_PER_SLASHINGS_VECTOR )
2022-05-30 13:30:42 +00:00
state . slashings . mitem ( int ( epoch mod EPOCHS_PER_SLASHINGS_VECTOR ) ) + =
More 0.8.0 updates (#311)
* replace BeaconState.finalized_{epoch,root} with BeaconState.finalized_checkpoint; rename get_delayed_activation_exit_epoch(...) to compute_activation_exit_epoch(...) and mark as 0.8.0; update get_churn_limit(...)/get_validator_churn_limit(...) to 0.8.0; update process_registry_updates(...) to 0.8.0
* update process_crosslinks(...) to 0.8.0; mark compute_start_slot_of_epoch(...) and get_committee_count(...) as 0.8.0
* mark Fork, is_slashable_validator(...), and get_beacon_proposer_index(...) as 0.8.0
* rename LATEST_SLASHED_EXIT_LENGTH to EPOCHS_PER_SLASHINGS_VECTOR; update process_slashings(...) to 0.8.0; remove pointless type conversion warning in get_previous_epoch(...)
* convert remaining references to finalized_epoch to finalized_checkpoint.epoch
* update slash_validator(...) to 0.8.0; mark inital value, Gwei, and time constants as 0.8.0; mark hash(...) and processBlockHeader(...) as 0.8.0
* rename WHISTLEBLOWING_REWARD_QUOTIENT to WHISTLEBLOWER_REWARD_QUOTIENT; rename LATEST_ACTIVE_INDEX_ROOTS_LENGTH to EPOCHS_PER_HISTORICAL_VECTOR (randao will also get merged into this); remove get_active_index_root(...); mark time parameter, signature domain types, and max operations per block constants as 0.8.0; update rewards and penalties constants to 0.8.0
* update is_valid_indexed_attestation(...) to 0.8.0; mark process_slot(...) as 0.8.0
* replace BeaconState.{current,previous}_justified_{epoch,root} with BeaconState.{current,previous}_justified_checkpoint
2019-07-05 08:30:05 +00:00
validator . effective_balance
2021-05-28 15:25:58 +00:00
2021-12-29 02:50:49 +00:00
decrease_balance ( state , slashed_index ,
get_slashing_penalty ( state , validator . effective_balance ) )
2019-02-20 20:35:27 +00:00
2019-12-04 10:49:59 +00:00
# The rest doesn't make sense without there being any proposer index, so skip
2023-01-11 12:29:21 +00:00
let proposer_index = get_beacon_proposer_index ( state , cache ) . valueOr :
2019-12-04 10:49:59 +00:00
debug " No beacon proposer index and probably no active validators "
2024-04-02 12:18:40 +00:00
return ok ( ( 0 . Gwei , post_exit_queue_info ) )
2019-12-04 10:49:59 +00:00
2020-07-08 08:56:25 +00:00
# Apply proposer and whistleblower rewards
2019-01-29 03:22:22 +00:00
let
2019-06-12 07:48:49 +00:00
# Spec has whistleblower_index as optional param, but it's never used.
2023-01-11 12:29:21 +00:00
whistleblower_index = proposer_index
2024-04-25 08:41:17 +00:00
whistleblower_reward =
get_whistleblower_reward ( state , validator . effective_balance )
2021-12-29 02:50:49 +00:00
proposer_reward = get_proposer_reward ( state , whistleblower_reward )
2021-05-28 15:25:58 +00:00
2023-01-11 12:29:21 +00:00
increase_balance ( state , proposer_index , proposer_reward )
2019-09-10 22:03:06 +00:00
# TODO: evaluate if spec bug / underflow can be triggered
2024-04-02 12:18:40 +00:00
doAssert (
whistleblower_reward > = proposer_reward ,
" Spec bug: underflow in slash_validator " )
More 0.6.1 updates (#274)
* implement get_churn_limit from 0.6.1; update initiate_validator_exit and get_previous_epoch to 0.6.1; remove obsoleted/non-spec reduce_balance, replaced by decrease_balance; mark BeaconBlock as 0.6.1
* rename get_block_root to get_block_root_at_slot and introduce epoch-oriented get_block_root; implement get_attestation_slot, get_matching_source_attestations, get_matching_target_attestations, get_matching_head_attestations, 0.6.1 get_attesting_indices, get_unslashed_attesting_indices, get_attestation_deltas, process_rewards_and_penalties; rm get_inactivity_penalty
* update Validator and processVoluntaryExits to 0.6.1; rm obsolete inclusion_slots/inclusion_distances
* rm removed activate_validator; mark DepositData, misc values, Gwei values, Randao processing, state caching as 0.6.1; update GENESIS_SLOT to 64, since it doesn't quite yet work at 0
* mark BeaconBlockHeader as 0.6.1; update BeaconBlockBody to 0.6.1; rename WHISTLEBLOWER_REWARD_QUOTIENT to WHISTLEBLOWING_REWARD_QUOTIENT; update slash_validator to 0.6.1
* implement 0.6.2 is_slashable_validator; update processProposerSlashings to 0.6.2; mark state caching as 0.6.2
* mark get_total_active_balance and process_slashings as 0.6.2; update get_base_reward to 0.6.2
* rm prepare_validator_for_withdrawal, process_exit_queue; mark mainnet misc constants as 0.6.2; update process block header to 0.6.2
* address mratsim's code review comment
2019-05-29 10:08:56 +00:00
increase_balance (
2021-05-28 15:25:58 +00:00
state , whistleblower_index , whistleblower_reward - proposer_reward )
2019-01-16 13:39:34 +00:00
2024-04-02 12:18:40 +00:00
ok ( ( proposer_reward , post_exit_queue_info ) )
2022-05-25 13:49:29 +00:00
2023-10-24 01:58:52 +00:00
func genesis_time_from_eth1_timestamp (
cfg : RuntimeConfig , eth1_timestamp : uint64 ) : uint64 =
Implement split preset/config support (#2710)
* Implement split preset/config support
This is the initial bulk refactor to introduce runtime config values in
a number of places, somewhat replacing the existing mechanism of loading
network metadata.
It still needs more work, this is the initial refactor that introduces
runtime configuration in some of the places that need it.
The PR changes the way presets and constants work, to match the spec. In
particular, a "preset" now refers to the compile-time configuration
while a "cfg" or "RuntimeConfig" is the dynamic part.
A single binary can support either mainnet or minimal, but not both.
Support for other presets has been removed completely (can be readded,
in case there's need).
There's a number of outstanding tasks:
* `SECONDS_PER_SLOT` still needs fixing
* loading custom runtime configs needs redoing
* checking constants against YAML file
* yeerongpilly support
`build/nimbus_beacon_node --network=yeerongpilly --discv5:no --log-level=DEBUG`
* load fork epoch from config
* fix fork digest sent in status
* nicer error string for request failures
* fix tools
* one more
* fixup
* fixup
* fixup
* use "standard" network definition folder in local testnet
Files are loaded from their standard locations, including genesis etc,
to conform to the format used in the `eth2-networks` repo.
* fix launch scripts, allow unknown config values
* fix base config of rest test
* cleanups
* bundle mainnet config using common loader
* fix spec links and names
* only include supported preset in binary
* drop yeerongpilly, add altair-devnet-0, support boot_enr.yaml
2021-07-12 13:01:38 +00:00
eth1_timestamp + cfg . GENESIS_DELAY
2020-06-27 12:01:19 +00:00
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#genesis-block
2021-11-18 12:02:43 +00:00
func get_initial_beacon_block * ( state : phase0 . HashedBeaconState ) :
2021-05-28 15:25:58 +00:00
phase0 . TrustedSignedBeaconBlock =
2021-05-17 16:37:26 +00:00
# The genesis block is implicitly trusted
2021-05-28 15:25:58 +00:00
let message = phase0 . TrustedBeaconBlock (
2021-11-18 12:02:43 +00:00
slot : state . data . slot ,
state_root : state . root )
2020-09-22 20:42:42 +00:00
# parent_root, randao_reveal, eth1_data, signature, and body automatically
# initialized to default values.
2021-05-28 15:25:58 +00:00
phase0 . TrustedSignedBeaconBlock (
message : message , root : hash_tree_root ( message ) )
2019-09-08 18:27:09 +00:00
2023-05-05 20:38:51 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/altair/beacon-chain.md#initialize-state-for-pure-altair-testnets-and-test-vectors
2021-11-18 12:02:43 +00:00
func get_initial_beacon_block * ( state : altair . HashedBeaconState ) :
2021-11-10 11:39:08 +00:00
altair . TrustedSignedBeaconBlock =
# The genesis block is implicitly trusted
let message = altair . TrustedBeaconBlock (
2021-11-18 12:02:43 +00:00
slot : state . data . slot ,
state_root : state . root )
2021-11-10 11:39:08 +00:00
# parent_root, randao_reveal, eth1_data, signature, and body automatically
# initialized to default values.
altair . TrustedSignedBeaconBlock (
message : message , root : hash_tree_root ( message ) )
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/bellatrix/beacon-chain.md#testing
2022-01-06 11:25:35 +00:00
func get_initial_beacon_block * ( state : bellatrix . HashedBeaconState ) :
bellatrix . TrustedSignedBeaconBlock =
2021-11-10 11:39:08 +00:00
# The genesis block is implicitly trusted
2022-01-06 11:25:35 +00:00
let message = bellatrix . TrustedBeaconBlock (
2021-11-18 12:02:43 +00:00
slot : state . data . slot ,
2021-12-23 14:58:54 +00:00
state_root : state . root )
2021-11-10 11:39:08 +00:00
# parent_root, randao_reveal, eth1_data, signature, and body automatically
# initialized to default values.
2022-01-06 11:25:35 +00:00
bellatrix . TrustedSignedBeaconBlock (
2021-11-10 11:39:08 +00:00
message : message , root : hash_tree_root ( message ) )
2024-04-17 03:51:16 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/capella/beacon-chain.md#testing
2023-05-06 10:32:59 +00:00
func get_initial_beacon_block * ( state : capella . HashedBeaconState ) :
capella . TrustedSignedBeaconBlock =
2022-12-07 16:47:23 +00:00
# The genesis block is implicitly trusted
2023-05-06 10:32:59 +00:00
let message = capella . TrustedBeaconBlock (
2022-12-07 16:47:23 +00:00
slot : state . data . slot ,
state_root : state . root )
# parent_root, randao_reveal, eth1_data, signature, and body automatically
# initialized to default values.
2023-05-06 10:32:59 +00:00
capella . TrustedSignedBeaconBlock (
2022-12-07 16:47:23 +00:00
message : message , root : hash_tree_root ( message ) )
2023-05-06 10:32:59 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/beacon-chain.md#testing
func get_initial_beacon_block * ( state : deneb . HashedBeaconState ) :
deneb . TrustedSignedBeaconBlock =
2022-11-02 16:23:30 +00:00
# The genesis block is implicitly trusted
2023-05-06 10:32:59 +00:00
let message = deneb . TrustedBeaconBlock (
2022-11-02 16:23:30 +00:00
slot : state . data . slot ,
state_root : state . root )
# parent_root, randao_reveal, eth1_data, signature, and body automatically
# initialized to default values.
2023-05-06 10:32:59 +00:00
deneb . TrustedSignedBeaconBlock (
2022-11-02 16:23:30 +00:00
message : message , root : hash_tree_root ( message ) )
2024-04-24 12:28:47 +00:00
from . / datatypes / electra import
HashedBeaconState , PendingBalanceDeposit , TrustedSignedBeaconBlock
2024-02-26 06:49:12 +00:00
# TODO spec link here when it exists
func get_initial_beacon_block * ( state : electra . HashedBeaconState ) :
electra . TrustedSignedBeaconBlock =
# The genesis block is implicitly trusted
let message = electra . TrustedBeaconBlock (
slot : state . data . slot ,
state_root : state . root )
# parent_root, randao_reveal, eth1_data, signature, and body automatically
# initialized to default values.
electra . TrustedSignedBeaconBlock (
message : message , root : hash_tree_root ( message ) )
2021-11-10 11:39:08 +00:00
func get_initial_beacon_block * ( state : ForkedHashedBeaconState ) :
ForkedTrustedSignedBeaconBlock =
withState ( state ) :
2022-08-26 14:14:18 +00:00
ForkedTrustedSignedBeaconBlock . init ( get_initial_beacon_block ( forkyState ) )
2021-11-10 11:39:08 +00:00
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#get_block_root_at_slot
2021-11-05 07:34:34 +00:00
func get_block_root_at_slot * ( state : ForkyBeaconState , slot : Slot ) : Eth2Digest =
2020-09-08 08:54:55 +00:00
## Return the block root at a recent ``slot``.
2019-02-13 10:26:32 +00:00
2020-09-02 16:16:25 +00:00
# Potential overflow/wrap shouldn't occur, as get_block_root_at_slot() called
# from internally controlled sources, but flag this explicitly, in case.
doAssert slot + SLOTS_PER_HISTORICAL_ROOT > slot
2019-03-16 19:52:37 +00:00
doAssert state . slot < = slot + SLOTS_PER_HISTORICAL_ROOT
2018-12-14 16:12:39 +00:00
doAssert slot < state . slot
2019-07-01 07:53:42 +00:00
state . block_roots [ slot mod SLOTS_PER_HISTORICAL_ROOT ]
2018-11-29 05:23:40 +00:00
2022-07-06 10:33:02 +00:00
func get_block_root_at_slot * (
state : ForkedHashedBeaconState , slot : Slot ) : Eth2Digest =
2021-11-05 07:34:34 +00:00
## Return the block root at a recent ``slot``.
withState ( state ) :
2022-08-26 14:14:18 +00:00
get_block_root_at_slot ( forkyState . data , slot )
2021-11-05 07:34:34 +00:00
2024-04-18 01:00:04 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#get_block_root
2021-11-05 07:34:34 +00:00
func get_block_root * ( state : ForkyBeaconState , epoch : Epoch ) : Eth2Digest =
2020-09-08 08:54:55 +00:00
## Return the block root at the start of a recent ``epoch``.
2022-01-11 10:01:54 +00:00
get_block_root_at_slot ( state , epoch . start_slot ( ) )
More 0.6.1 updates (#274)
* implement get_churn_limit from 0.6.1; update initiate_validator_exit and get_previous_epoch to 0.6.1; remove obsoleted/non-spec reduce_balance, replaced by decrease_balance; mark BeaconBlock as 0.6.1
* rename get_block_root to get_block_root_at_slot and introduce epoch-oriented get_block_root; implement get_attestation_slot, get_matching_source_attestations, get_matching_target_attestations, get_matching_head_attestations, 0.6.1 get_attesting_indices, get_unslashed_attesting_indices, get_attestation_deltas, process_rewards_and_penalties; rm get_inactivity_penalty
* update Validator and processVoluntaryExits to 0.6.1; rm obsolete inclusion_slots/inclusion_distances
* rm removed activate_validator; mark DepositData, misc values, Gwei values, Randao processing, state caching as 0.6.1; update GENESIS_SLOT to 64, since it doesn't quite yet work at 0
* mark BeaconBlockHeader as 0.6.1; update BeaconBlockBody to 0.6.1; rename WHISTLEBLOWER_REWARD_QUOTIENT to WHISTLEBLOWING_REWARD_QUOTIENT; update slash_validator to 0.6.1
* implement 0.6.2 is_slashable_validator; update processProposerSlashings to 0.6.2; mark state caching as 0.6.2
* mark get_total_active_balance and process_slashings as 0.6.2; update get_base_reward to 0.6.2
* rm prepare_validator_for_withdrawal, process_exit_queue; mark mainnet misc constants as 0.6.2; update process block header to 0.6.2
* address mratsim's code review comment
2019-05-29 10:08:56 +00:00
2023-10-24 01:58:52 +00:00
func get_block_root ( state : ForkedHashedBeaconState , epoch : Epoch ) : Eth2Digest =
2022-07-06 10:33:02 +00:00
## Return the block root at the start of a recent ``epoch``.
withState ( state ) :
2022-08-26 14:14:18 +00:00
get_block_root ( forkyState . data , epoch )
2022-07-06 10:33:02 +00:00
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#get_total_balance
2021-08-25 14:43:00 +00:00
template get_total_balance (
2021-11-05 07:34:34 +00:00
state : ForkyBeaconState , validator_indices : untyped ) : Gwei =
2020-03-30 11:31:44 +00:00
## Return the combined effective balance of the ``indices``.
## ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
2022-07-06 10:33:02 +00:00
## Math safe up to ~10B ETH, after which this overflows uint64.
2021-08-24 20:09:03 +00:00
var res = 0 . Gwei
for validator_index in validator_indices :
2022-05-30 13:30:42 +00:00
res + = state . validators [ validator_index ] . effective_balance
2024-03-19 13:22:07 +00:00
max ( EFFECTIVE_BALANCE_INCREMENT . Gwei , res )
2019-02-22 18:46:45 +00:00
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#is_eligible_for_activation_queue
2021-10-12 11:36:52 +00:00
func is_eligible_for_activation_queue * ( validator : Validator ) : bool =
2020-09-08 08:54:55 +00:00
## Check if ``validator`` is eligible to be placed into the activation queue.
2019-12-16 18:08:50 +00:00
validator . activation_eligibility_epoch = = FAR_FUTURE_EPOCH and
2024-03-19 13:22:07 +00:00
validator . effective_balance = = MAX_EFFECTIVE_BALANCE . Gwei
2019-12-16 18:08:50 +00:00
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#is_eligible_for_activation
2022-07-06 10:33:02 +00:00
func is_eligible_for_activation * (
state : ForkyBeaconState , validator : Validator ) : bool =
2020-09-08 08:54:55 +00:00
## Check if ``validator`` is eligible for activation.
2019-12-16 18:08:50 +00:00
# Placement in queue is finalized
validator . activation_eligibility_epoch < = state . finalized_checkpoint . epoch and
# Has not yet been activated
validator . activation_epoch = = FAR_FUTURE_EPOCH
2024-04-17 03:51:16 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#is_valid_indexed_attestation
2020-07-23 14:38:28 +00:00
proc is_valid_indexed_attestation * (
2024-04-25 08:41:17 +00:00
state : ForkyBeaconState ,
indexed_attestation : SomeIndexedAttestation | ElectraIndexedAttestation |
TrustedElectraIndexedAttestation ,
2020-08-13 13:47:06 +00:00
flags : UpdateFlags ) : Result [ void , cstring ] =
2020-09-08 08:54:55 +00:00
## Check if ``indexed_attestation`` is not empty, has sorted and unique
## indices and has a valid aggregate signature.
2020-06-22 10:37:47 +00:00
template is_sorted_and_unique ( s : untyped ) : bool =
2020-08-13 13:47:06 +00:00
var res = true
2020-06-22 10:37:47 +00:00
for i in 1 .. < s . len :
if s [ i - 1 ] . uint64 > = s [ i ] . uint64 :
2020-08-13 13:47:06 +00:00
res = false
break
res
2020-06-22 10:37:47 +00:00
2020-08-13 13:47:06 +00:00
if len ( indexed_attestation . attesting_indices ) = = 0 :
return err ( " indexed_attestation: no attesting indices " )
2020-06-22 10:37:47 +00:00
# Not from spec, but this function gets used in front-line roles, not just
# behind firewall.
2020-07-26 18:55:48 +00:00
let num_validators = state . validators . lenu64
2020-06-22 10:37:47 +00:00
if anyIt ( indexed_attestation . attesting_indices , it > = num_validators ) :
2020-08-13 13:47:06 +00:00
return err ( " indexed attestation: not all indices valid validators " )
2019-06-12 07:48:49 +00:00
2020-08-13 13:47:06 +00:00
if not is_sorted_and_unique ( indexed_attestation . attesting_indices ) :
return err ( " indexed attestation: indices not sorted and unique " )
2019-06-12 07:48:49 +00:00
2019-06-14 07:50:14 +00:00
# Verify aggregate signature
2022-04-14 15:39:37 +00:00
if not ( skipBlsValidation in flags or indexed_attestation . signature is TrustedSig ) :
2020-08-13 13:47:06 +00:00
let pubkeys = mapIt (
indexed_attestation . attesting_indices , state . validators [ it ] . pubkey )
2020-06-16 05:45:04 +00:00
if not verify_attestation_signature (
state . fork , state . genesis_validators_root , indexed_attestation . data ,
pubkeys , indexed_attestation . signature ) :
2020-08-13 13:47:06 +00:00
return err ( " indexed attestation: signature verification failure " )
2019-11-21 09:57:59 +00:00
2020-08-13 13:47:06 +00:00
ok ( )
2019-06-12 07:48:49 +00:00
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#get_attesting_indices
2023-08-02 23:03:40 +00:00
iterator get_attesting_indices_iter * ( state : ForkyBeaconState ,
data : AttestationData ,
2024-04-28 00:52:14 +00:00
bits : CommitteeValidatorsBits ,
2023-08-02 23:03:40 +00:00
cache : var StateCache ) : ValidatorIndex =
2022-01-08 23:28:49 +00:00
## Return the set of attesting indices corresponding to ``data`` and ``bits``
## or nothing if `data` is invalid
2023-08-02 23:03:40 +00:00
## This iterator must not be called in functions using a
## ForkedHashedBeaconState due to https://github.com/nim-lang/Nim/issues/18188
2022-01-08 23:28:49 +00:00
let committee_index = CommitteeIndex . init ( data . index )
if committee_index . isErr ( ) or bits . lenu64 ! = get_beacon_committee_len (
state , data . slot , committee_index . get ( ) , cache ) :
trace " get_attesting_indices: invalid attestation data "
2020-10-22 10:53:33 +00:00
else :
2022-01-08 23:28:49 +00:00
for index_in_committee , validator_index in get_beacon_committee (
2022-05-10 10:03:40 +00:00
state , data . slot , committee_index . get ( ) , cache ) :
2022-01-08 23:28:49 +00:00
if bits [ index_in_committee ] :
2023-08-02 23:03:40 +00:00
yield validator_index
2019-06-12 07:48:49 +00:00
2024-04-28 00:52:14 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#modified-get_attesting_indices
iterator get_attesting_indices_iter * (
state : electra . BeaconState ,
data : AttestationData ,
aggregation_bits : ElectraCommitteeValidatorsBits ,
committee_bits : auto ,
cache : var StateCache ) : ValidatorIndex =
debugRaiseAssert " replace this implementation with actual iterator, after checking on conditions re repeat vals, ordering, etc; this is almost direct transcription of spec link algorithm in one of the places it doesn ' t make sense "
## Return the set of attesting indices corresponding to ``aggregation_bits``
## and ``committee_bits``.
var output : HashSet [ ValidatorIndex ]
let committee_indices = toSeq ( committee_bits . oneIndices )
var committee_offset = 0
for index in committee_indices :
let committee = get_beacon_committee ( state , data . slot , index . CommitteeIndex , cache )
var committee_attesters : HashSet [ ValidatorIndex ]
for i , index in committee :
if aggregation_bits [ committee_offset + i ] :
committee_attesters . incl index
output . incl committee_attesters
committee_offset + = len ( committee )
for validatorIndex in output :
yield validatorIndex
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#get_attesting_indices
2024-04-28 00:52:14 +00:00
func get_attesting_indices * (
state : ForkyBeaconState , data : AttestationData ,
aggregation_bits : CommitteeValidatorsBits , cache : var StateCache ) :
seq [ ValidatorIndex ] =
2023-08-02 23:03:40 +00:00
## Return the set of attesting indices corresponding to ``data`` and ``bits``
## or nothing if `data` is invalid
2024-04-28 00:52:14 +00:00
toSeq ( get_attesting_indices_iter ( state , data , aggregation_bits , cache ) )
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#get_attesting_indices
func get_attesting_indices * (
state : ForkyBeaconState , data : AttestationData ,
aggregation_bits : ElectraCommitteeValidatorsBits , committee_bits : auto ,
cache : var StateCache ) : seq [ ValidatorIndex ] =
## Return the set of attesting indices corresponding to ``data`` and ``bits``
## or nothing if `data` is invalid
toSeq ( get_attesting_indices_iter ( state , data , aggregation_bits , committee_bits , cache ) )
2021-06-11 17:51:46 +00:00
2022-01-08 23:28:49 +00:00
func get_attesting_indices * ( state : ForkedHashedBeaconState ;
2021-11-05 07:34:34 +00:00
data : AttestationData ;
2024-04-28 00:52:14 +00:00
bits : CommitteeValidatorsBits ;
2021-11-05 07:34:34 +00:00
cache : var StateCache ) : seq [ ValidatorIndex ] =
# TODO when https://github.com/nim-lang/Nim/issues/18188 fixed, use an
# iterator
var idxBuf : seq [ ValidatorIndex ]
withState ( state ) :
2022-08-26 14:14:18 +00:00
for vidx in forkyState . data . get_attesting_indices ( data , bits , cache ) :
2021-11-05 07:34:34 +00:00
idxBuf . add vidx
idxBuf
2024-04-28 00:52:14 +00:00
func get_attesting_indices * ( state : ForkedHashedBeaconState ;
data : AttestationData ;
aggregation_bits : ElectraCommitteeValidatorsBits ;
committee_bits : auto ,
cache : var StateCache ) : seq [ ValidatorIndex ] =
# TODO when https://github.com/nim-lang/Nim/issues/18188 fixed, use an
# iterator
var idxBuf : seq [ ValidatorIndex ]
withState ( state ) :
when consensusFork > = ConsensusFork . Electra :
for vidx in forkyState . data . get_attesting_indices ( data , aggregation_bits , committee_bits , cache ) :
idxBuf . add vidx
idxBuf
2023-10-24 01:58:52 +00:00
proc is_valid_indexed_attestation (
2024-04-28 00:52:14 +00:00
state : ForkyBeaconState ,
attestation : SomeAttestation ,
flags : UpdateFlags , cache : var StateCache ) : Result [ void , cstring ] =
2021-04-14 14:43:29 +00:00
# This is a variation on `is_valid_indexed_attestation` that works directly
# with an attestation instead of first constructing an `IndexedAttestation`
# and then validating it - for the purpose of validating the signature, the
# order doesn't matter and we can proceed straight to validating the
# signature instead
2019-06-12 07:48:49 +00:00
2021-04-14 14:43:29 +00:00
let sigs = attestation . aggregation_bits . countOnes ( )
if sigs = = 0 :
return err ( " is_valid_indexed_attestation: no attesting indices " )
# Verify aggregate signature
2022-04-14 15:39:37 +00:00
if not ( skipBlsValidation in flags or attestation . signature is TrustedSig ) :
2021-04-14 14:43:29 +00:00
var
pubkeys = newSeqOfCap [ ValidatorPubKey ] ( sigs )
2023-08-02 23:03:40 +00:00
for index in get_attesting_indices_iter (
2021-04-14 14:43:29 +00:00
state , attestation . data , attestation . aggregation_bits , cache ) :
pubkeys . add ( state . validators [ index ] . pubkey )
if not verify_attestation_signature (
state . fork , state . genesis_validators_root , attestation . data ,
pubkeys , attestation . signature ) :
return err ( " indexed attestation: signature verification failure " )
ok ( )
2020-06-25 10:23:10 +00:00
2024-04-28 00:52:14 +00:00
proc is_valid_indexed_attestation (
state : ForkyBeaconState ,
attestation : electra . Attestation | electra . TrustedAttestation ,
flags : UpdateFlags , cache : var StateCache ) : Result [ void , cstring ] =
# This is a variation on `is_valid_indexed_attestation` that works directly
# with an attestation instead of first constructing an `IndexedAttestation`
# and then validating it - for the purpose of validating the signature, the
# order doesn't matter and we can proceed straight to validating the
# signature instead
let sigs = attestation . aggregation_bits . countOnes ( )
if sigs = = 0 :
return err ( " is_valid_indexed_attestation: no attesting indices " )
# Verify aggregate signature
if not ( skipBlsValidation in flags or attestation . signature is TrustedSig ) :
var
pubkeys = newSeqOfCap [ ValidatorPubKey ] ( sigs )
for index in get_attesting_indices_iter (
state , attestation . data , attestation . aggregation_bits , attestation . committee_bits , cache ) :
pubkeys . add ( state . validators [ index ] . pubkey )
if not verify_attestation_signature (
state . fork , state . genesis_validators_root , attestation . data ,
pubkeys , attestation . signature ) :
return err ( " indexed attestation: signature verification failure " )
ok ( )
2020-06-10 06:58:12 +00:00
# Attestation validation
# ------------------------------------------------------------------------------------------
2024-04-17 03:51:16 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#attestations
2023-05-05 20:38:51 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/p2p-interface.md#beacon_attestation_subnet_id
2020-06-10 06:58:12 +00:00
2022-01-08 23:28:49 +00:00
func check_attestation_slot_target * ( data : AttestationData ) : Result [ Slot , cstring ] =
2022-01-11 10:01:54 +00:00
if not ( data . target . epoch = = epoch ( data . slot ) ) :
2020-07-27 16:04:44 +00:00
return err ( " Target epoch doesn ' t match attestation slot " )
2020-06-10 06:58:12 +00:00
2022-01-08 23:28:49 +00:00
ok ( data . slot )
2020-06-10 06:58:12 +00:00
2020-10-20 08:54:11 +00:00
func check_attestation_target_epoch (
2022-01-08 23:28:49 +00:00
data : AttestationData , current_epoch : Epoch ) : Result [ Epoch , cstring ] =
2020-07-27 16:04:44 +00:00
if not ( data . target . epoch = = get_previous_epoch ( current_epoch ) or
data . target . epoch = = current_epoch ) :
return err ( " Target epoch not current or previous epoch " )
2020-06-10 06:58:12 +00:00
2022-01-08 23:28:49 +00:00
ok ( data . target . epoch )
2020-06-10 06:58:12 +00:00
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#attestations
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#modified-process_attestation
2024-04-18 01:00:04 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#modified-process_attestation
2023-06-24 12:27:15 +00:00
func check_attestation_inclusion (
consensusFork : static ConsensusFork , attestation_slot : Slot ,
current_slot : Slot ) : Result [ void , cstring ] =
2020-09-02 16:16:25 +00:00
# Check for overflow
static :
doAssert SLOTS_PER_EPOCH > = MIN_ATTESTATION_INCLUSION_DELAY
2022-01-08 23:28:49 +00:00
if attestation_slot + SLOTS_PER_EPOCH < = attestation_slot :
2020-09-02 16:16:25 +00:00
return err ( " attestation data.slot overflow, malicious? " )
2022-01-08 23:28:49 +00:00
if not ( attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY < = current_slot ) :
2020-07-27 16:04:44 +00:00
return err ( " Attestation too new " )
2020-06-10 06:58:12 +00:00
2023-06-24 12:27:15 +00:00
when consensusFork < ConsensusFork . Deneb :
if not ( current_slot < = attestation_slot + SLOTS_PER_EPOCH ) :
return err ( " Attestation too old " )
2020-07-27 16:04:44 +00:00
ok ( )
2022-01-08 23:28:49 +00:00
func check_attestation_index * (
index , committees_per_slot : uint64 ) :
Result [ CommitteeIndex , cstring ] =
CommitteeIndex . init ( index , committees_per_slot )
2020-07-27 16:04:44 +00:00
2023-10-24 01:58:52 +00:00
func check_attestation_index (
2022-01-08 23:28:49 +00:00
data : AttestationData , committees_per_slot : uint64 ) :
Result [ CommitteeIndex , cstring ] =
check_attestation_index ( data . index , committees_per_slot )
2020-07-27 16:04:44 +00:00
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_attestation_participation_flag_indices
2022-10-27 06:29:24 +00:00
func get_attestation_participation_flag_indices (
2023-06-24 12:27:15 +00:00
state : altair . BeaconState | bellatrix . BeaconState | capella . BeaconState ,
2023-08-02 23:03:40 +00:00
data : AttestationData , inclusion_delay : uint64 ) : set [ TimelyFlag ] =
2021-05-28 15:25:58 +00:00
## Return the flag indices that are satisfied by an attestation.
let justified_checkpoint =
if data . target . epoch = = get_current_epoch ( state ) :
state . current_justified_checkpoint
else :
state . previous_justified_checkpoint
# Matching roots
let
is_matching_source = data . source = = justified_checkpoint
2023-06-24 12:27:15 +00:00
is_matching_target =
is_matching_source and
data . target . root = = get_block_root ( state , data . target . epoch )
is_matching_head =
is_matching_target and
data . beacon_block_root = = get_block_root_at_slot ( state , data . slot )
# Checked by check_attestation()
2021-05-28 15:25:58 +00:00
doAssert is_matching_source
2023-08-02 23:03:40 +00:00
var participation_flag_indices : set [ TimelyFlag ]
2023-09-24 08:50:48 +00:00
if is_matching_source and inclusion_delay < =
static ( integer_squareroot ( SLOTS_PER_EPOCH ) ) :
2023-08-02 23:03:40 +00:00
participation_flag_indices . incl ( TIMELY_SOURCE_FLAG_INDEX )
2021-05-28 15:25:58 +00:00
if is_matching_target and inclusion_delay < = SLOTS_PER_EPOCH :
2023-08-02 23:03:40 +00:00
participation_flag_indices . incl ( TIMELY_TARGET_FLAG_INDEX )
2021-05-28 15:25:58 +00:00
if is_matching_head and inclusion_delay = = MIN_ATTESTATION_INCLUSION_DELAY :
2023-08-02 23:03:40 +00:00
participation_flag_indices . incl ( TIMELY_HEAD_FLAG_INDEX )
2021-05-28 15:25:58 +00:00
participation_flag_indices
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#modified-get_attestation_participation_flag_indices
2023-06-24 12:27:15 +00:00
func get_attestation_participation_flag_indices (
2024-02-26 06:49:12 +00:00
state : deneb . BeaconState | electra . BeaconState ,
2023-08-02 23:03:40 +00:00
data : AttestationData , inclusion_delay : uint64 ) : set [ TimelyFlag ] =
2023-06-24 12:27:15 +00:00
## Return the flag indices that are satisfied by an attestation.
let justified_checkpoint =
if data . target . epoch = = get_current_epoch ( state ) :
state . current_justified_checkpoint
else :
state . previous_justified_checkpoint
# Matching roots
let
is_matching_source = data . source = = justified_checkpoint
is_matching_target =
is_matching_source and
data . target . root = = get_block_root ( state , data . target . epoch )
is_matching_head =
is_matching_target and
data . beacon_block_root = = get_block_root_at_slot ( state , data . slot )
# Checked by check_attestation
doAssert is_matching_source
2023-08-02 23:03:40 +00:00
var participation_flag_indices : set [ TimelyFlag ]
2023-06-24 12:27:15 +00:00
if is_matching_source and inclusion_delay < = integer_squareroot ( SLOTS_PER_EPOCH ) :
2023-08-02 23:03:40 +00:00
participation_flag_indices . incl ( TIMELY_SOURCE_FLAG_INDEX )
2023-06-24 12:27:15 +00:00
if is_matching_target : # [Modified in Deneb:EIP7045]
2023-08-02 23:03:40 +00:00
participation_flag_indices . incl ( TIMELY_TARGET_FLAG_INDEX )
2023-06-24 12:27:15 +00:00
if is_matching_head and inclusion_delay = = MIN_ATTESTATION_INCLUSION_DELAY :
2023-08-02 23:03:40 +00:00
participation_flag_indices . incl ( TIMELY_HEAD_FLAG_INDEX )
2023-06-24 12:27:15 +00:00
participation_flag_indices
2021-05-28 15:25:58 +00:00
# TODO these aren't great here
# TODO these duplicate some stuff in state_transition_epoch which uses TotalBalances
# better to centralize around that if feasible
2024-04-18 01:00:04 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/beacon-chain.md#get_total_active_balance
2021-11-05 07:34:34 +00:00
func get_total_active_balance * ( state : ForkyBeaconState , cache : var StateCache ) : Gwei =
2021-05-28 15:25:58 +00:00
## Return the combined effective balance of the active validators.
2023-05-05 20:37:56 +00:00
## Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei
## minimum to avoid divisions by zero.
2021-05-28 15:25:58 +00:00
let epoch = state . get_current_epoch ( )
2022-12-19 12:01:49 +00:00
cache . total_active_balance . withValue ( epoch , tab ) do :
return tab [ ]
do :
let tab = get_total_balance (
state , cache . get_shuffled_active_validator_indices ( state , epoch ) )
cache . total_active_balance [ epoch ] = tab
return tab
2021-05-28 15:25:58 +00:00
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_base_reward_per_increment
2023-10-24 01:58:52 +00:00
func get_base_reward_per_increment_sqrt (
2021-10-13 14:24:36 +00:00
total_active_balance_sqrt : uint64 ) : Gwei =
2024-03-19 13:22:07 +00:00
EFFECTIVE_BALANCE_INCREMENT . Gwei * BASE_REWARD_FACTOR div
total_active_balance_sqrt
2021-10-13 14:24:36 +00:00
2021-07-01 08:55:16 +00:00
func get_base_reward_per_increment * (
2021-10-13 14:24:36 +00:00
total_active_balance : Gwei ) : Gwei =
2024-03-19 13:22:07 +00:00
get_base_reward_per_increment_sqrt (
integer_squareroot ( distinctBase ( total_active_balance ) ) )
2021-05-28 15:25:58 +00:00
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_base_reward
2021-06-28 06:54:06 +00:00
func get_base_reward (
2022-12-06 12:40:13 +00:00
state : altair . BeaconState | bellatrix . BeaconState | capella . BeaconState |
2024-02-26 06:49:12 +00:00
deneb . BeaconState | electra . BeaconState ,
2022-10-27 06:29:24 +00:00
index : ValidatorIndex , base_reward_per_increment : Gwei ) : Gwei =
2021-06-28 06:54:06 +00:00
## Return the base reward for the validator defined by ``index`` with respect
## to the current ``state``.
let increments =
2024-03-19 13:22:07 +00:00
state . validators [ index ] . effective_balance div
EFFECTIVE_BALANCE_INCREMENT . Gwei
2021-06-28 06:54:06 +00:00
increments * base_reward_per_increment
2021-05-28 15:25:58 +00:00
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#attestations
2019-08-19 16:41:13 +00:00
proc check_attestation * (
2021-11-05 07:34:34 +00:00
state : ForkyBeaconState , attestation : SomeAttestation , flags : UpdateFlags ,
2020-07-27 16:04:44 +00:00
cache : var StateCache ) : Result [ void , cstring ] =
2018-12-11 17:55:45 +00:00
## Check that an attestation follows the rules of being included in the state
2018-12-27 20:14:37 +00:00
## at the current slot. When acting as a proposer, the same rules need to
## be followed!
2018-12-11 17:55:45 +00:00
2020-03-19 23:48:03 +00:00
let
data = attestation . data
2022-01-08 23:28:49 +00:00
epoch = ? check_attestation_target_epoch ( data , state . get_current_epoch ( ) )
slot = ? check_attestation_slot_target ( data )
committee_index = ? check_attestation_index (
2020-07-27 16:04:44 +00:00
data ,
2022-01-08 23:28:49 +00:00
get_committee_count_per_slot ( state , epoch , cache ) )
2023-09-27 15:10:28 +00:00
? check_attestation_inclusion ( ( typeof state ) . kind , slot , state . slot )
2019-08-14 08:56:32 +00:00
2020-07-27 16:04:44 +00:00
let committee_len = get_beacon_committee_len (
2022-01-08 23:28:49 +00:00
state , slot , committee_index , cache )
2020-07-27 10:59:57 +00:00
2020-07-27 16:04:44 +00:00
if attestation . aggregation_bits . lenu64 ! = committee_len :
return err ( " Inconsistent aggregation and committee length " )
2019-06-24 09:21:56 +00:00
2022-01-08 23:28:49 +00:00
if epoch = = get_current_epoch ( state ) :
2020-07-27 16:04:44 +00:00
if not ( data . source = = state . current_justified_checkpoint ) :
return err ( " FFG data not matching current justified epoch " )
2019-06-24 09:21:56 +00:00
else :
2020-07-27 16:04:44 +00:00
if not ( data . source = = state . previous_justified_checkpoint ) :
return err ( " FFG data not matching previous justified epoch " )
2019-06-24 09:21:56 +00:00
2021-04-14 14:43:29 +00:00
? is_valid_indexed_attestation ( state , attestation , flags , cache )
2019-06-12 07:48:49 +00:00
2020-07-27 16:04:44 +00:00
ok ( )
2019-02-13 10:26:32 +00:00
2024-04-22 09:00:38 +00:00
proc check_attestation * (
2024-04-28 00:52:14 +00:00
state : electra . BeaconState ,
attestation : electra . Attestation | electra . TrustedAttestation ,
flags : UpdateFlags , cache : var StateCache ) : Result [ void , cstring ] =
## Check that an attestation follows the rules of being included in the state
## at the current slot. When acting as a proposer, the same rules need to
## be followed!
let
data = attestation . data
epoch = ? check_attestation_target_epoch ( data , state . get_current_epoch ( ) )
slot = ? check_attestation_slot_target ( data )
? check_attestation_inclusion ( ( typeof state ) . kind , slot , state . slot )
# [Modified in Electra:EIP7549]
if not ( data . index = = 0 ) :
return err ( " Electra attestation data index not 0 " )
var participants_count = 0
debugRaiseAssert " cache doesn ' t know about forks "
for index in attestation . committee_bits . oneIndices :
if not ( index . uint64 < get_committee_count_per_slot (
state , data . target . epoch , cache ) ) :
return err ( " foo " )
let committee = get_beacon_committee ( state , data . slot , index . CommitteeIndex , cache )
participants_count + = len ( committee )
if not ( len ( attestation . aggregation_bits ) = = participants_count ) :
return err ( " " )
if epoch = = get_current_epoch ( state ) :
if not ( data . source = = state . current_justified_checkpoint ) :
return err ( " FFG data not matching current justified epoch " )
else :
if not ( data . source = = state . previous_justified_checkpoint ) :
return err ( " FFG data not matching previous justified epoch " )
? is_valid_indexed_attestation ( state , attestation , flags , cache )
2024-04-22 09:00:38 +00:00
ok ( )
2023-12-05 02:34:45 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#new-process_bls_to_execution_change
2023-02-17 13:35:12 +00:00
proc check_bls_to_execution_change * (
2024-02-26 06:49:12 +00:00
genesisFork : Fork ,
state : capella . BeaconState | deneb . BeaconState | electra . BeaconState ,
2023-02-17 13:35:12 +00:00
signed_address_change : SignedBLSToExecutionChange , flags : UpdateFlags ) :
Result [ void , cstring ] =
let address_change = signed_address_change . message
if not ( address_change . validator_index < state . validators . lenu64 ) :
return err ( " process_bls_to_execution_change: invalid validator index " )
var withdrawal_credentials =
state . validators . item ( address_change . validator_index ) . withdrawal_credentials
if not ( withdrawal_credentials . data [ 0 ] = = BLS_WITHDRAWAL_PREFIX ) :
return err ( " process_bls_to_execution_change: invalid withdrawal prefix " )
if not ( withdrawal_credentials . data . toOpenArray ( 1 , 31 ) = =
eth2digest ( address_change . from_bls_pubkey . blob ) . data . toOpenArray ( 1 , 31 ) ) :
return err ( " process_bls_to_execution_change: invalid withdrawal credentials " )
doAssert flags + { skipBlsValidation } = = { skipBlsValidation }
if skipBlsValidation notin flags and
not verify_bls_to_execution_change_signature (
genesisFork , state . genesis_validators_root , signed_address_change ,
address_change . from_bls_pubkey , signed_address_change . signature ) :
return err ( " process_bls_to_execution_change: invalid signature " )
ok ( )
2024-03-19 13:22:07 +00:00
func get_proposer_reward * (
state : ForkyBeaconState ,
attestation : SomeAttestation ,
base_reward_per_increment : Gwei ,
cache : var StateCache ,
epoch_participation : var EpochParticipationFlags ) : Gwei =
2021-12-29 02:50:49 +00:00
let participation_flag_indices = get_attestation_participation_flag_indices (
state , attestation . data , state . slot - attestation . data . slot )
2023-08-02 23:03:40 +00:00
for index in get_attesting_indices_iter (
2021-12-29 02:50:49 +00:00
state , attestation . data , attestation . aggregation_bits , cache ) :
2022-12-19 12:01:49 +00:00
let
base_reward = get_base_reward ( state , index , base_reward_per_increment )
2021-12-29 02:50:49 +00:00
for flag_index , weight in PARTICIPATION_FLAG_WEIGHTS :
if flag_index in participation_flag_indices and
2022-05-30 13:30:42 +00:00
not has_flag ( epoch_participation . item ( index ) , flag_index ) :
2022-12-19 12:01:49 +00:00
asList ( epoch_participation ) [ index ] =
2022-05-30 13:30:42 +00:00
add_flag ( epoch_participation . item ( index ) , flag_index )
2021-12-29 02:50:49 +00:00
# these are all valid; TODO statically verify or do it type-safely
2022-12-19 12:01:49 +00:00
result + = base_reward * weight . uint64
2021-12-29 02:50:49 +00:00
let proposer_reward_denominator =
( WEIGHT_DENOMINATOR . uint64 - PROPOSER_WEIGHT . uint64 ) *
WEIGHT_DENOMINATOR . uint64 div PROPOSER_WEIGHT . uint64
2024-03-19 13:22:07 +00:00
result div proposer_reward_denominator
2021-12-29 02:50:49 +00:00
2024-04-22 09:00:38 +00:00
func get_proposer_reward * (
state : ForkyBeaconState ,
attestation : electra . Attestation | electra . TrustedAttestation ,
base_reward_per_increment : Gwei ,
cache : var StateCache ,
epoch_participation : var EpochParticipationFlags ) : Gwei =
2024-04-28 00:52:14 +00:00
let participation_flag_indices = get_attestation_participation_flag_indices (
state , attestation . data , state . slot - attestation . data . slot )
for index in get_attesting_indices_iter (
state , attestation . data , attestation . aggregation_bits , attestation . committee_bits , cache ) :
let
base_reward = get_base_reward ( state , index , base_reward_per_increment )
for flag_index , weight in PARTICIPATION_FLAG_WEIGHTS :
if flag_index in participation_flag_indices and
not has_flag ( epoch_participation . item ( index ) , flag_index ) :
asList ( epoch_participation ) [ index ] =
add_flag ( epoch_participation . item ( index ) , flag_index )
# these are all valid; TODO statically verify or do it type-safely
result + = base_reward * weight . uint64
let proposer_reward_denominator =
( WEIGHT_DENOMINATOR . uint64 - PROPOSER_WEIGHT . uint64 ) *
WEIGHT_DENOMINATOR . uint64 div PROPOSER_WEIGHT . uint64
result div proposer_reward_denominator
2024-04-22 09:00:38 +00:00
2019-08-19 16:41:13 +00:00
proc process_attestation * (
2021-11-05 07:34:34 +00:00
state : var ForkyBeaconState , attestation : SomeAttestation , flags : UpdateFlags ,
2021-07-06 06:19:06 +00:00
base_reward_per_increment : Gwei , cache : var StateCache ) :
2024-03-04 17:00:46 +00:00
Result [ Gwei , cstring ] =
2019-08-19 16:41:13 +00:00
# In the spec, attestation validation is mixed with state mutation, so here
# we've split it into two functions so that the validation logic can be
# reused when looking for suitable blocks to include in attestations.
2021-06-11 17:51:46 +00:00
#
# TODO this should be two separate functions, but
# https://github.com/nim-lang/Nim/issues/18202 means that this being called
# by process_operations() in state_transition_block fails that way.
2019-12-04 10:49:59 +00:00
2023-01-11 12:29:21 +00:00
let proposer_index = get_beacon_proposer_index ( state , cache ) . valueOr :
2020-07-03 17:03:14 +00:00
return err ( " process_attestation: no beacon proposer index and probably no active validators " )
2019-12-04 10:49:59 +00:00
2020-07-27 16:04:44 +00:00
? check_attestation ( state , attestation , flags , cache )
2019-08-19 16:41:13 +00:00
2021-05-28 15:25:58 +00:00
when state is phase0 . BeaconState :
2023-06-24 12:27:15 +00:00
template addPendingAttestation ( attestations : typed ) =
# The genericSeqAssign generated by the compiler to copy the attestation
# data sadly is a processing hotspot - the business with the addDefault
# pointer is here simply to work around the poor codegen
let pa = attestations . addDefault ( )
if pa . isNil :
return err ( " process_attestation: too many pending attestations " )
assign ( pa [ ] . aggregation_bits , attestation . aggregation_bits )
pa [ ] . data = attestation . data
pa [ ] . inclusion_delay = state . slot - attestation . data . slot
pa [ ] . proposer_index = proposer_index . uint64
2021-07-06 06:19:06 +00:00
doAssert base_reward_per_increment = = 0 . Gwei
2021-05-28 15:25:58 +00:00
if attestation . data . target . epoch = = get_current_epoch ( state ) :
addPendingAttestation ( state . current_epoch_attestations )
else :
addPendingAttestation ( state . previous_epoch_attestations )
2024-03-04 17:00:46 +00:00
const proposer_reward = 0 . Gwei
else :
template updateParticipationFlags ( epoch_participation : untyped ) : Gwei =
2023-06-24 12:27:15 +00:00
let proposer_reward = get_proposer_reward (
state , attestation , base_reward_per_increment , cache , epoch_participation )
increase_balance ( state , proposer_index , proposer_reward )
2024-03-04 17:00:46 +00:00
proposer_reward
2023-06-24 12:27:15 +00:00
2021-07-06 06:19:06 +00:00
doAssert base_reward_per_increment > 0 . Gwei
2024-03-04 17:00:46 +00:00
let proposer_reward =
if attestation . data . target . epoch = = get_current_epoch ( state ) :
updateParticipationFlags ( state . current_epoch_participation )
else :
updateParticipationFlags ( state . previous_epoch_participation )
2020-07-27 16:04:44 +00:00
2024-03-04 17:00:46 +00:00
ok ( proposer_reward )
2021-05-28 15:25:58 +00:00
2024-04-22 09:00:38 +00:00
proc process_attestation * (
state : var ForkyBeaconState ,
attestation : electra . Attestation | electra . TrustedAttestation ,
flags : UpdateFlags , base_reward_per_increment : Gwei ,
cache : var StateCache ) : Result [ Gwei , cstring ] =
2024-04-28 00:52:14 +00:00
? check_attestation ( state , attestation , flags , cache )
let proposer_index = get_beacon_proposer_index ( state , cache ) . valueOr :
return err ( " process_attestation: no beacon proposer index and probably no active validators " )
template updateParticipationFlags ( epoch_participation : untyped ) : Gwei =
let proposer_reward = get_proposer_reward (
state , attestation , base_reward_per_increment , cache , epoch_participation )
increase_balance ( state , proposer_index , proposer_reward )
proposer_reward
doAssert base_reward_per_increment > 0 . Gwei
let proposer_reward =
if attestation . data . target . epoch = = get_current_epoch ( state ) :
updateParticipationFlags ( state . current_epoch_participation )
else :
updateParticipationFlags ( state . previous_epoch_participation )
ok ( proposer_reward )
2024-04-22 09:00:38 +00:00
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_next_sync_committee_indices
2022-10-27 06:29:24 +00:00
func get_next_sync_committee_keys (
2022-12-06 16:43:11 +00:00
state : altair . BeaconState | bellatrix . BeaconState | capella . BeaconState |
2024-02-26 06:49:12 +00:00
deneb . BeaconState | electra . BeaconState ) :
2021-10-13 14:24:36 +00:00
array [ SYNC_COMMITTEE_SIZE , ValidatorPubKey ] =
2022-01-27 19:52:08 +00:00
## Return the sequence of sync committee indices, with possible duplicates,
## for the next sync committee.
Speed up altair block processing 2x (#3115)
* Speed up altair block processing >2x
Like #3089, this PR drastially speeds up historical REST queries and
other long state replays.
* cache sync committee validator indices
* use ~80mb less memory for validator pubkey mappings
* batch-verify sync aggregate signature (fixes #2985)
* document sync committee hack with head block vs sync message block
* add batch signature verification failure tests
Before:
```
../env.sh nim c -d:release -r ncli_db --db:mainnet_0/db bench --start-slot:-1000
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
5830.675, 0.000, 5830.675, 5830.675, 1, Initialize DB
0.481, 1.878, 0.215, 59.167, 981, Load block from database
8422.566, 0.000, 8422.566, 8422.566, 1, Load state from database
6.996, 1.678, 0.042, 14.385, 969, Advance slot, non-epoch
93.217, 8.318, 84.192, 122.209, 32, Advance slot, epoch
20.513, 23.665, 11.510, 201.561, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
After:
```
7081.422, 0.000, 7081.422, 7081.422, 1, Initialize DB
0.553, 2.122, 0.175, 66.692, 981, Load block from database
5439.446, 0.000, 5439.446, 5439.446, 1, Load state from database
6.829, 1.575, 0.043, 12.156, 969, Advance slot, non-epoch
94.716, 2.749, 88.395, 100.026, 32, Advance slot, epoch
11.636, 23.766, 4.889, 205.250, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
* add comment
2021-11-24 12:43:50 +00:00
# The sync committe depends on seed and effective balance - it can
# thus only be computed for the current epoch of the state, after balance
# updates have been performed
2021-05-28 15:25:58 +00:00
2021-05-31 12:54:53 +00:00
let epoch = get_current_epoch ( state ) + 1
2021-05-28 15:25:58 +00:00
const MAX_RANDOM_BYTE = 255
let
active_validator_indices = get_active_validator_indices ( state , epoch )
active_validator_count = uint64 ( len ( active_validator_indices ) )
seed = get_seed ( state , epoch , DOMAIN_SYNC_COMMITTEE )
var
i = 0 'u64
2021-10-13 14:24:36 +00:00
index = 0
res : array [ SYNC_COMMITTEE_SIZE , ValidatorPubKey ]
2021-05-28 15:25:58 +00:00
hash_buffer : array [ 40 , byte ]
hash_buffer [ 0 .. 31 ] = seed . data
2021-10-13 14:24:36 +00:00
while index < SYNC_COMMITTEE_SIZE :
2022-01-08 20:06:34 +00:00
hash_buffer [ 32 .. 39 ] = uint_to_bytes ( uint64 ( i div 32 ) )
2021-05-28 15:25:58 +00:00
let
2022-01-27 19:52:08 +00:00
shuffled_index = compute_shuffled_index (
uint64 ( i mod active_validator_count ) , active_validator_count , seed )
2021-05-28 15:25:58 +00:00
candidate_index = active_validator_indices [ shuffled_index ]
random_byte = eth2digest ( hash_buffer ) . data [ i mod 32 ]
effective_balance = state . validators [ candidate_index ] . effective_balance
2024-03-19 13:22:07 +00:00
if effective_balance * MAX_RANDOM_BYTE > =
MAX_EFFECTIVE_BALANCE . Gwei * random_byte :
2021-10-13 14:24:36 +00:00
res [ index ] = state . validators [ candidate_index ] . pubkey
inc index
2021-05-28 15:25:58 +00:00
i + = 1 'u64
2021-10-13 14:24:36 +00:00
res
2021-05-28 15:25:58 +00:00
2023-12-05 02:34:45 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#has_eth1_withdrawal_credential
2023-03-02 16:13:35 +00:00
func has_eth1_withdrawal_credential * ( validator : Validator ) : bool =
2023-01-06 21:01:10 +00:00
## Check if ``validator`` has an 0x01 prefixed "eth1" withdrawal credential.
validator . withdrawal_credentials . data [ 0 ] = = ETH1_ADDRESS_WITHDRAWAL_PREFIX
2024-04-18 01:00:04 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/capella/beacon-chain.md#is_fully_withdrawable_validator
2023-01-06 21:01:10 +00:00
func is_fully_withdrawable_validator (
validator : Validator , balance : Gwei , epoch : Epoch ) : bool =
## Check if ``validator`` is fully withdrawable.
has_eth1_withdrawal_credential ( validator ) and
2024-03-19 13:22:07 +00:00
validator . withdrawable_epoch < = epoch and balance > 0 . Gwei
2023-01-06 21:01:10 +00:00
2023-12-05 02:34:45 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#is_partially_withdrawable_validator
2023-01-06 21:01:10 +00:00
func is_partially_withdrawable_validator (
validator : Validator , balance : Gwei ) : bool =
## Check if ``validator`` is partially withdrawable.
let
has_max_effective_balance =
2024-03-19 13:22:07 +00:00
validator . effective_balance = = MAX_EFFECTIVE_BALANCE . Gwei
has_excess_balance = balance > MAX_EFFECTIVE_BALANCE . Gwei
2023-01-06 21:01:10 +00:00
has_eth1_withdrawal_credential ( validator ) and
has_max_effective_balance and has_excess_balance
2024-04-25 08:41:17 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-is_compounding_withdrawal_credential
2024-04-26 07:18:44 +00:00
func is_compounding_withdrawal_credential * (
2024-04-18 10:12:37 +00:00
withdrawal_credentials : Eth2Digest ) : bool =
withdrawal_credentials . data [ 0 ] = = COMPOUNDING_WITHDRAWAL_PREFIX
2024-04-25 08:41:17 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-has_compounding_withdrawal_credential
func has_compounding_withdrawal_credential * ( validator : Validator ) : bool =
2024-04-18 10:12:37 +00:00
## Check if ``validator`` has an 0x02 prefixed "compounding" withdrawal
## credential.
is_compounding_withdrawal_credential ( validator . withdrawal_credentials )
2024-04-25 08:41:17 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-has_execution_withdrawal_credential
func has_execution_withdrawal_credential * ( validator : Validator ) : bool =
2024-04-18 10:12:37 +00:00
## Check if ``validator`` has a 0x01 or 0x02 prefixed withdrawal credential.
has_compounding_withdrawal_credential ( validator ) or
has_eth1_withdrawal_credential ( validator )
2024-04-24 12:28:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#get_validator_max_effective_balance
func get_validator_max_effective_balance ( validator : Validator ) : Gwei =
## Get max effective balance for ``validator``.
if has_compounding_withdrawal_credential ( validator ) :
MAX_EFFECTIVE_BALANCE_ELECTRA . Gwei
else :
MIN_ACTIVATION_BALANCE . Gwei
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-get_active_balance
func get_active_balance * (
state : electra . BeaconState , validator_index : ValidatorIndex ) : Gwei =
let max_effective_balance =
get_validator_max_effective_balance ( state . validators [ validator_index ] )
min ( state . balances [ validator_index ] , max_effective_balance )
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-queue_excess_active_balance
func queue_excess_active_balance (
state : var electra . BeaconState , index : ValidatorIndex ) =
let balance = state . balances . item ( index )
if balance > MIN_ACTIVATION_BALANCE . Gwei :
let excess_balance = balance - MIN_ACTIVATION_BALANCE . Gwei
state . balances . mitem ( index ) = MIN_ACTIVATION_BALANCE . Gwei
debugRaiseAssert " maybe check return value "
discard state . pending_balance_deposits . add (
PendingBalanceDeposit ( index : index . uint64 , amount : excess_balance )
)
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-switch_to_compounding_validator
func switch_to_compounding_validator * (
state : var electra . BeaconState , index : ValidatorIndex ) =
let validator = addr state . validators . mitem ( index )
if has_eth1_withdrawal_credential ( validator [ ] ) :
validator . withdrawal_credentials . data [ 0 ] = COMPOUNDING_WITHDRAWAL_PREFIX
queue_excess_active_balance ( state , index )
2024-04-25 08:41:17 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.0/specs/electra/beacon-chain.md#new-get_pending_balance_to_withdraw
func get_pending_balance_to_withdraw * (
state : Electra . BeaconState , validator_index : ValidatorIndex ) : Gwei =
var pending_balance : Gwei
for withdrawal in state . pending_partial_withdrawals :
if withdrawal . index = = validator_index :
pending_balance + = withdrawal . amount
pending_balance
2023-12-05 02:34:45 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#new-get_expected_withdrawals
2023-01-09 14:15:43 +00:00
func get_expected_withdrawals * (
2024-02-26 06:49:12 +00:00
state : capella . BeaconState | deneb . BeaconState | electra . BeaconState ) :
seq [ Withdrawal ] =
2023-01-06 21:01:10 +00:00
let
epoch = get_current_epoch ( state )
num_validators = lenu64 ( state . validators )
var
withdrawal_index = state . next_withdrawal_index
validator_index = state . next_withdrawal_validator_index
withdrawals : seq [ Withdrawal ] = @ [ ]
bound = min ( len ( state . validators ) , MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP )
for _ in 0 .. < bound :
let
validator = state . validators [ validator_index ]
balance = state . balances [ validator_index ]
if is_fully_withdrawable_validator ( validator , balance , epoch ) :
var w = Withdrawal (
index : withdrawal_index ,
validator_index : validator_index ,
amount : balance )
w . address . data [ 0 .. 19 ] = validator . withdrawal_credentials . data [ 12 .. ^ 1 ]
withdrawals . add w
withdrawal_index = WithdrawalIndex ( withdrawal_index + 1 )
elif is_partially_withdrawable_validator ( validator , balance ) :
var w = Withdrawal (
index : withdrawal_index ,
validator_index : validator_index ,
2024-03-19 13:22:07 +00:00
amount : balance - MAX_EFFECTIVE_BALANCE . Gwei )
2023-01-06 21:01:10 +00:00
w . address . data [ 0 .. 19 ] = validator . withdrawal_credentials . data [ 12 .. ^ 1 ]
withdrawals . add w
withdrawal_index = WithdrawalIndex ( withdrawal_index + 1 )
if len ( withdrawals ) = = MAX_WITHDRAWALS_PER_PAYLOAD :
break
validator_index = ( validator_index + 1 ) mod num_validators
withdrawals
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/altair/beacon-chain.md#get_next_sync_committee
2022-10-27 06:29:24 +00:00
func get_next_sync_committee * (
2022-12-06 16:43:11 +00:00
state : altair . BeaconState | bellatrix . BeaconState | capella . BeaconState |
2024-02-26 06:49:12 +00:00
deneb . BeaconState | electra . BeaconState ) :
2021-09-27 14:22:58 +00:00
SyncCommittee =
2023-05-05 20:37:56 +00:00
## Return the next sync committee, with possible pubkey duplicates.
2021-06-14 17:42:46 +00:00
var res : SyncCommittee
2021-10-13 14:24:36 +00:00
res . pubkeys . data = get_next_sync_committee_keys ( state )
2021-05-31 12:54:53 +00:00
2021-05-28 15:25:58 +00:00
# see signatures_batch, TODO shouldn't be here
2021-05-31 12:54:53 +00:00
# Deposit processing ensures all keys are valid
2021-06-14 17:42:46 +00:00
var attestersAgg : AggregatePublicKey
Speed up altair block processing 2x (#3115)
* Speed up altair block processing >2x
Like #3089, this PR drastially speeds up historical REST queries and
other long state replays.
* cache sync committee validator indices
* use ~80mb less memory for validator pubkey mappings
* batch-verify sync aggregate signature (fixes #2985)
* document sync committee hack with head block vs sync message block
* add batch signature verification failure tests
Before:
```
../env.sh nim c -d:release -r ncli_db --db:mainnet_0/db bench --start-slot:-1000
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
5830.675, 0.000, 5830.675, 5830.675, 1, Initialize DB
0.481, 1.878, 0.215, 59.167, 981, Load block from database
8422.566, 0.000, 8422.566, 8422.566, 1, Load state from database
6.996, 1.678, 0.042, 14.385, 969, Advance slot, non-epoch
93.217, 8.318, 84.192, 122.209, 32, Advance slot, epoch
20.513, 23.665, 11.510, 201.561, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
After:
```
7081.422, 0.000, 7081.422, 7081.422, 1, Initialize DB
0.553, 2.122, 0.175, 66.692, 981, Load block from database
5439.446, 0.000, 5439.446, 5439.446, 1, Load state from database
6.829, 1.575, 0.043, 12.156, 969, Advance slot, non-epoch
94.716, 2.749, 88.395, 100.026, 32, Advance slot, epoch
11.636, 23.766, 4.889, 205.250, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
* add comment
2021-11-24 12:43:50 +00:00
attestersAgg . init ( res . pubkeys . data [ 0 ] . load ( ) . get )
2021-06-14 17:42:46 +00:00
for i in 1 .. < res . pubkeys . data . len :
Speed up altair block processing 2x (#3115)
* Speed up altair block processing >2x
Like #3089, this PR drastially speeds up historical REST queries and
other long state replays.
* cache sync committee validator indices
* use ~80mb less memory for validator pubkey mappings
* batch-verify sync aggregate signature (fixes #2985)
* document sync committee hack with head block vs sync message block
* add batch signature verification failure tests
Before:
```
../env.sh nim c -d:release -r ncli_db --db:mainnet_0/db bench --start-slot:-1000
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
5830.675, 0.000, 5830.675, 5830.675, 1, Initialize DB
0.481, 1.878, 0.215, 59.167, 981, Load block from database
8422.566, 0.000, 8422.566, 8422.566, 1, Load state from database
6.996, 1.678, 0.042, 14.385, 969, Advance slot, non-epoch
93.217, 8.318, 84.192, 122.209, 32, Advance slot, epoch
20.513, 23.665, 11.510, 201.561, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
After:
```
7081.422, 0.000, 7081.422, 7081.422, 1, Initialize DB
0.553, 2.122, 0.175, 66.692, 981, Load block from database
5439.446, 0.000, 5439.446, 5439.446, 1, Load state from database
6.829, 1.575, 0.043, 12.156, 969, Advance slot, non-epoch
94.716, 2.749, 88.395, 100.026, 32, Advance slot, epoch
11.636, 23.766, 4.889, 205.250, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
* add comment
2021-11-24 12:43:50 +00:00
attestersAgg . aggregate ( res . pubkeys . data [ i ] . load ( ) . get )
2021-06-14 17:42:46 +00:00
res . aggregate_pubkey = finish ( attestersAgg ) . toPubKey ( )
2021-05-28 15:25:58 +00:00
res
2021-05-31 12:54:53 +00:00
2024-01-11 17:34:44 +00:00
func compute_deposit_root ( deposits : openArray [ DepositData ] ) : Eth2Digest =
var merkleizer = createMerkleizer2 ( DEPOSIT_CONTRACT_TREE_DEPTH + 1 )
for i , deposit in deposits :
let htr = hash_tree_root ( deposit )
merkleizer . addChunk ( htr . data )
mixInLength ( merkleizer . getFinalHash ( ) , deposits . len )
2023-06-13 14:03:49 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/beacon-chain.md#genesis
2023-10-24 01:58:52 +00:00
proc initialize_beacon_state_from_eth1 (
2023-02-23 02:10:07 +00:00
cfg : RuntimeConfig ,
eth1_block_hash : Eth2Digest ,
eth1_timestamp : uint64 ,
deposits : openArray [ DepositData ] ,
flags : UpdateFlags = { } ) : phase0 . BeaconState =
## Get the genesis ``BeaconState``.
##
## Before the beacon chain starts, validators will register in the Eth1 chain
## and deposit ETH. When enough many validators have registered, a
## `ChainStart` log will be emitted and the beacon chain can start beaconing.
##
## Because the state root hash is part of the genesis block, the beacon state
## must be calculated before creating the genesis block.
# Induct validators
# Not in spec: the system doesn't work unless there are at least SLOTS_PER_EPOCH
# validators - there needs to be at least one member in each committee -
# good to know for testing, though arguably the system is not that useful at
2023-05-05 20:37:56 +00:00
# that point :)
2023-02-23 02:10:07 +00:00
doAssert deposits . lenu64 > = SLOTS_PER_EPOCH
# TODO https://github.com/nim-lang/Nim/issues/19094
template state ( ) : untyped = result
state = phase0 . BeaconState (
fork : genesisFork ( cfg ) ,
genesis_time : genesis_time_from_eth1_timestamp ( cfg , eth1_timestamp ) ,
2024-01-11 17:34:44 +00:00
eth1_data : Eth1Data (
deposit_count : deposits . lenu64 ,
deposit_root : compute_deposit_root ( deposits ) ,
block_hash : eth1_block_hash ) ,
eth1_deposit_index : deposits . lenu64 ,
2023-02-23 02:10:07 +00:00
latest_block_header :
BeaconBlockHeader (
body_root : hash_tree_root ( default ( phase0 . BeaconBlockBody ) ) ) )
# Seed RANDAO with Eth1 entropy
state . randao_mixes . fill ( eth1_block_hash )
var pubkeyToIndex = initTable [ ValidatorPubKey , ValidatorIndex ] ( )
for idx , deposit in deposits :
let
pubkey = deposit . pubkey
amount = deposit . amount
pubkeyToIndex . withValue ( pubkey , foundIdx ) do :
# Increase balance by deposit amount
increase_balance ( state , foundIdx [ ] , amount )
do :
if skipBlsValidation in flags or
verify_deposit_signature ( cfg , deposit ) :
pubkeyToIndex [ pubkey ] = ValidatorIndex ( state . validators . len )
2024-04-26 07:18:44 +00:00
if not state . validators . add ( get_validator_from_deposit ( state , deposit ) ) :
2023-02-23 02:10:07 +00:00
raiseAssert " too many validators "
if not state . balances . add ( amount ) :
raiseAssert " same as validators "
else :
# Invalid deposits are perfectly possible
trace " Skipping deposit with invalid signature " ,
deposit = shortLog ( deposit )
# Process activations
for vidx in state . validators . vindices :
let
balance = state . balances . item ( vidx )
validator = addr state . validators . mitem ( vidx )
validator . effective_balance = min (
2024-03-19 13:22:07 +00:00
balance - balance mod EFFECTIVE_BALANCE_INCREMENT . Gwei ,
MAX_EFFECTIVE_BALANCE . Gwei )
2023-02-23 02:10:07 +00:00
2024-03-19 13:22:07 +00:00
if validator . effective_balance = = MAX_EFFECTIVE_BALANCE . Gwei :
2023-02-23 02:10:07 +00:00
validator . activation_eligibility_epoch = GENESIS_EPOCH
validator . activation_epoch = GENESIS_EPOCH
# Set genesis validators root for domain separation and chain versioning
state . genesis_validators_root = hash_tree_root ( state . validators )
# TODO https://github.com/nim-lang/Nim/issues/19094
# state
proc initialize_hashed_beacon_state_from_eth1 * (
cfg : RuntimeConfig ,
eth1_block_hash : Eth2Digest ,
eth1_timestamp : uint64 ,
deposits : openArray [ DepositData ] ,
flags : UpdateFlags = { } ) : phase0 . HashedBeaconState =
# TODO https://github.com/nim-lang/Nim/issues/19094
result = phase0 . HashedBeaconState (
data : initialize_beacon_state_from_eth1 (
cfg , eth1_block_hash , eth1_timestamp , deposits , flags ) )
result . root = hash_tree_root ( result . data )
2024-03-14 06:26:36 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/bellatrix/beacon-chain.md#testing
2024-04-17 03:51:16 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/capella/beacon-chain.md#testing
2023-05-05 20:38:51 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/beacon-chain.md#testing
2023-02-23 02:10:07 +00:00
proc initialize_beacon_state_from_eth1 * (
cfg : RuntimeConfig ,
eth1_block_hash : Eth2Digest ,
eth1_timestamp : uint64 ,
deposits : openArray [ DepositData ] ,
execution_payload_header : ForkyExecutionPayloadHeader ,
flags : UpdateFlags = { } ) : auto =
## Get the genesis ``BeaconState``.
##
## Before the beacon chain starts, validators will register in the Eth1 chain
## and deposit ETH. When enough many validators have registered, a
## `ChainStart` log will be emitted and the beacon chain can start beaconing.
##
## Because the state root hash is part of the genesis block, the beacon state
## must be calculated before creating the genesis block.
# Induct validators
# Not in spec: the system doesn't work unless there are at least SLOTS_PER_EPOCH
# validators - there needs to be at least one member in each committee -
# good to know for testing, though arguably the system is not that useful at
# at that point :)
doAssert deposits . lenu64 > = SLOTS_PER_EPOCH
2023-09-27 15:10:28 +00:00
const consensusFork = typeof ( execution_payload_header ) . kind
2023-02-23 02:10:07 +00:00
let
forkVersion = cfg . forkVersion ( consensusFork )
fork = Fork (
previous_version : forkVersion ,
current_version : forkVersion ,
epoch : GENESIS_EPOCH )
# TODO https://github.com/nim-lang/Nim/issues/19094
template state ( ) : untyped = result
2023-10-05 12:01:40 +00:00
result = consensusFork . BeaconState (
2023-02-23 02:10:07 +00:00
fork : fork ,
genesis_time : genesis_time_from_eth1_timestamp ( cfg , eth1_timestamp ) ,
2023-10-05 12:01:40 +00:00
eth1_data : Eth1Data (
2024-01-11 17:34:44 +00:00
deposit_count : deposits . lenu64 ,
deposit_root : compute_deposit_root ( deposits ) ,
block_hash : eth1_block_hash ) ,
eth1_deposit_index : deposits . lenu64 ,
2023-10-05 12:01:40 +00:00
latest_block_header : BeaconBlockHeader (
body_root : hash_tree_root ( default consensusFork . BeaconBlockBody ) ) )
2023-02-23 02:10:07 +00:00
# Seed RANDAO with Eth1 entropy
state . randao_mixes . data . fill ( eth1_block_hash )
var pubkeyToIndex = initTable [ ValidatorPubKey , ValidatorIndex ] ( )
for idx , deposit in deposits :
let
pubkey = deposit . pubkey
amount = deposit . amount
pubkeyToIndex . withValue ( pubkey , foundIdx ) do :
# Increase balance by deposit amount
increase_balance ( state , foundIdx [ ] , amount )
do :
if skipBlsValidation in flags or
verify_deposit_signature ( cfg , deposit ) :
pubkeyToIndex [ pubkey ] = ValidatorIndex ( state . validators . len )
2024-04-26 07:18:44 +00:00
if not state . validators . add get_validator_from_deposit ( state , deposit ) :
2023-02-23 02:10:07 +00:00
raiseAssert " too many validators "
if not state . balances . add ( amount ) :
raiseAssert " same as validators "
else :
# Invalid deposits are perfectly possible
trace " Skipping deposit with invalid signature " ,
deposit = shortLog ( deposit )
# Initialize epoch participations - TODO (This must be added to the spec)
var
empty_participation : EpochParticipationFlags
inactivity_scores = HashList [ uint64 , Limit VALIDATOR_REGISTRY_LIMIT ] ( )
doAssert empty_participation . asList . setLen ( state . validators . len )
doAssert inactivity_scores . data . setLen ( state . validators . len )
inactivity_scores . resetCache ( )
state . previous_epoch_participation = empty_participation
state . current_epoch_participation = empty_participation
state . inactivity_scores = inactivity_scores
# Process activations
for vidx in state . validators . vindices :
let
balance = state . balances . item ( vidx )
validator = addr state . validators . mitem ( vidx )
validator . effective_balance = min (
2024-03-19 13:22:07 +00:00
balance - balance mod EFFECTIVE_BALANCE_INCREMENT . Gwei ,
MAX_EFFECTIVE_BALANCE . Gwei )
2023-02-23 02:10:07 +00:00
2024-03-19 13:22:07 +00:00
if validator . effective_balance = = MAX_EFFECTIVE_BALANCE . Gwei :
2023-02-23 02:10:07 +00:00
validator . activation_eligibility_epoch = GENESIS_EPOCH
validator . activation_epoch = GENESIS_EPOCH
# Set genesis validators root for domain separation and chain versioning
state . genesis_validators_root = hash_tree_root ( state . validators )
# Fill in sync committees
# Note: A duplicate committee is assigned for the current and next committee at genesis
state . current_sync_committee = get_next_sync_committee ( state )
state . next_sync_committee = get_next_sync_committee ( state )
# [New in Bellatrix] Initialize the execution payload header
# If empty, will initialize a chain that has not yet gone through the Merge transition
state . latest_execution_payload_header = execution_payload_header
# TODO https://github.com/nim-lang/Nim/issues/19094
# state
2023-08-09 03:58:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/fork.md#upgrading-the-state
2021-05-31 12:54:53 +00:00
func translate_participation (
state : var altair . BeaconState ,
pending_attestations : openArray [ phase0 . PendingAttestation ] ) =
2021-06-25 12:51:25 +00:00
var cache = StateCache ( )
2021-05-31 12:54:53 +00:00
for attestation in pending_attestations :
let
data = attestation . data
inclusion_delay = attestation . inclusion_delay
# Translate attestation inclusion info to flag indices
participation_flag_indices =
get_attestation_participation_flag_indices ( state , data , inclusion_delay )
# Apply flags to all attesting validators
2023-08-02 23:03:40 +00:00
for index in get_attesting_indices_iter (
2021-05-31 12:54:53 +00:00
state , data , attestation . aggregation_bits , cache ) :
for flag_index in participation_flag_indices :
state . previous_epoch_participation [ index ] =
2022-05-30 13:30:42 +00:00
add_flag ( state . previous_epoch_participation . item ( index ) , flag_index )
2021-05-31 12:54:53 +00:00
2022-02-17 11:53:55 +00:00
func upgrade_to_altair * ( cfg : RuntimeConfig , pre : phase0 . BeaconState ) :
ref altair . BeaconState =
2021-05-31 12:54:53 +00:00
var
2022-06-20 05:38:56 +00:00
empty_participation : EpochParticipationFlags
2021-05-31 12:54:53 +00:00
inactivity_scores = HashList [ uint64 , Limit VALIDATOR_REGISTRY_LIMIT ] ( )
2021-06-25 12:51:25 +00:00
2022-12-19 12:01:49 +00:00
doAssert empty_participation . asList . setLen ( pre . validators . len )
2021-06-25 12:51:25 +00:00
doAssert inactivity_scores . data . setLen ( pre . validators . len )
inactivity_scores . resetCache ( )
2021-05-31 12:54:53 +00:00
2022-02-20 20:13:06 +00:00
let post = ( ref altair . BeaconState ) (
2021-05-31 12:54:53 +00:00
genesis_time : pre . genesis_time ,
genesis_validators_root : pre . genesis_validators_root ,
slot : pre . slot ,
2021-08-10 20:46:35 +00:00
fork : altairFork ( cfg ) ,
2021-05-31 12:54:53 +00:00
# History
latest_block_header : pre . latest_block_header ,
block_roots : pre . block_roots ,
state_roots : pre . state_roots ,
historical_roots : pre . historical_roots ,
# Eth1
eth1_data : pre . eth1_data ,
eth1_data_votes : pre . eth1_data_votes ,
eth1_deposit_index : pre . eth1_deposit_index ,
# Registry
validators : pre . validators ,
balances : pre . balances ,
# Randomness
randao_mixes : pre . randao_mixes ,
# Slashings
slashings : pre . slashings ,
# Attestations
previous_epoch_participation : empty_participation ,
current_epoch_participation : empty_participation ,
# Finality
justification_bits : pre . justification_bits ,
previous_justified_checkpoint : pre . previous_justified_checkpoint ,
current_justified_checkpoint : pre . current_justified_checkpoint ,
finalized_checkpoint : pre . finalized_checkpoint ,
# Inactivity
inactivity_scores : inactivity_scores
)
# Fill in previous epoch participation from the pre state's pending
# attestations
2021-06-04 10:38:00 +00:00
translate_participation ( post [ ] , pre . previous_epoch_attestations . asSeq )
2021-05-31 12:54:53 +00:00
# Fill in sync committees
# Note: A duplicate committee is assigned for the current and next committee
# at the fork boundary
2021-06-04 10:38:00 +00:00
post [ ] . current_sync_committee = get_next_sync_committee ( post [ ] )
post [ ] . next_sync_committee = get_next_sync_committee ( post [ ] )
2021-05-31 12:54:53 +00:00
post
2021-09-11 08:01:05 +00:00
2023-08-09 03:58:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/bellatrix/fork.md#upgrading-the-state
2022-01-10 09:39:43 +00:00
func upgrade_to_bellatrix * ( cfg : RuntimeConfig , pre : altair . BeaconState ) :
2022-01-06 11:25:35 +00:00
ref bellatrix . BeaconState =
2021-09-11 08:01:05 +00:00
let epoch = get_current_epoch ( pre )
2022-01-06 11:25:35 +00:00
( ref bellatrix . BeaconState ) (
2021-09-11 08:01:05 +00:00
# Versioning
genesis_time : pre . genesis_time ,
genesis_validators_root : pre . genesis_validators_root ,
slot : pre . slot ,
fork : Fork (
previous_version : pre . fork . current_version ,
2022-01-20 08:30:33 +00:00
current_version : cfg . BELLATRIX_FORK_VERSION ,
2021-09-11 08:01:05 +00:00
epoch : epoch ,
) ,
# History
latest_block_header : pre . latest_block_header ,
block_roots : pre . block_roots ,
state_roots : pre . state_roots ,
historical_roots : pre . historical_roots ,
# Eth1
eth1_data : pre . eth1_data ,
eth1_data_votes : pre . eth1_data_votes ,
eth1_deposit_index : pre . eth1_deposit_index ,
# Registry
validators : pre . validators ,
balances : pre . balances ,
# Randomness
randao_mixes : pre . randao_mixes ,
# Slashings
slashings : pre . slashings ,
# Participation
previous_epoch_participation : pre . previous_epoch_participation ,
current_epoch_participation : pre . current_epoch_participation ,
# Finality
justification_bits : pre . justification_bits ,
previous_justified_checkpoint : pre . previous_justified_checkpoint ,
current_justified_checkpoint : pre . current_justified_checkpoint ,
finalized_checkpoint : pre . finalized_checkpoint ,
# Inactivity
inactivity_scores : pre . inactivity_scores ,
# Sync
current_sync_committee : pre . current_sync_committee ,
next_sync_committee : pre . next_sync_committee ,
# Execution-layer
2022-10-27 06:29:24 +00:00
latest_execution_payload_header : default ( bellatrix . ExecutionPayloadHeader )
)
2023-08-09 03:58:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/capella/fork.md#upgrading-the-state
2022-10-27 06:29:24 +00:00
func upgrade_to_capella * ( cfg : RuntimeConfig , pre : bellatrix . BeaconState ) :
ref capella . BeaconState =
let
epoch = get_current_epoch ( pre )
latest_execution_payload_header = capella . ExecutionPayloadHeader (
parent_hash : pre . latest_execution_payload_header . parent_hash ,
fee_recipient : pre . latest_execution_payload_header . fee_recipient ,
state_root : pre . latest_execution_payload_header . state_root ,
receipts_root : pre . latest_execution_payload_header . receipts_root ,
logs_bloom : pre . latest_execution_payload_header . logs_bloom ,
prev_randao : pre . latest_execution_payload_header . prev_randao ,
block_number : pre . latest_execution_payload_header . block_number ,
gas_limit : pre . latest_execution_payload_header . gas_limit ,
gas_used : pre . latest_execution_payload_header . gas_used ,
timestamp : pre . latest_execution_payload_header . timestamp ,
extra_data : pre . latest_execution_payload_header . extra_data ,
base_fee_per_gas : pre . latest_execution_payload_header . base_fee_per_gas ,
block_hash : pre . latest_execution_payload_header . block_hash ,
transactions_root : pre . latest_execution_payload_header . transactions_root ,
withdrawals_root : Eth2Digest ( ) # [New in Capella]
)
( ref capella . BeaconState ) (
# Versioning
genesis_time : pre . genesis_time ,
genesis_validators_root : pre . genesis_validators_root ,
slot : pre . slot ,
fork : Fork (
previous_version : pre . fork . current_version ,
current_version : cfg . CAPELLA_FORK_VERSION ,
epoch : epoch ,
) ,
# History
latest_block_header : pre . latest_block_header ,
block_roots : pre . block_roots ,
state_roots : pre . state_roots ,
historical_roots : pre . historical_roots ,
# Eth1
eth1_data : pre . eth1_data ,
eth1_data_votes : pre . eth1_data_votes ,
eth1_deposit_index : pre . eth1_deposit_index ,
# Registry
validators : pre . validators ,
balances : pre . balances ,
# Randomness
randao_mixes : pre . randao_mixes ,
# Slashings
slashings : pre . slashings ,
# Participation
previous_epoch_participation : pre . previous_epoch_participation ,
current_epoch_participation : pre . current_epoch_participation ,
# Finality
justification_bits : pre . justification_bits ,
previous_justified_checkpoint : pre . previous_justified_checkpoint ,
current_justified_checkpoint : pre . current_justified_checkpoint ,
finalized_checkpoint : pre . finalized_checkpoint ,
# Inactivity
inactivity_scores : pre . inactivity_scores ,
# Sync
current_sync_committee : pre . current_sync_committee ,
next_sync_committee : pre . next_sync_committee ,
# Execution-layer
latest_execution_payload_header : latest_execution_payload_header ,
# Withdrawals
next_withdrawal_index : 0 ,
2022-11-21 07:44:49 +00:00
next_withdrawal_validator_index : 0
2023-04-18 22:00:06 +00:00
# Deep history valid from Capella onwards [New in Capella]
# historical_summaries initialized to correct default automatically
2021-09-11 08:01:05 +00:00
)
2021-11-07 21:03:23 +00:00
2024-01-20 11:19:47 +00:00
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/deneb/fork.md#upgrading-the-state
2023-03-11 14:28:55 +00:00
func upgrade_to_deneb * ( cfg : RuntimeConfig , pre : capella . BeaconState ) :
2023-02-22 13:10:00 +00:00
ref deneb . BeaconState =
2022-12-06 16:43:11 +00:00
let
epoch = get_current_epoch ( pre )
2023-02-22 13:10:00 +00:00
latest_execution_payload_header = deneb . ExecutionPayloadHeader (
2022-12-06 16:43:11 +00:00
parent_hash : pre . latest_execution_payload_header . parent_hash ,
fee_recipient : pre . latest_execution_payload_header . fee_recipient ,
state_root : pre . latest_execution_payload_header . state_root ,
receipts_root : pre . latest_execution_payload_header . receipts_root ,
logs_bloom : pre . latest_execution_payload_header . logs_bloom ,
prev_randao : pre . latest_execution_payload_header . prev_randao ,
block_number : pre . latest_execution_payload_header . block_number ,
gas_limit : pre . latest_execution_payload_header . gas_limit ,
gas_used : pre . latest_execution_payload_header . gas_used ,
timestamp : pre . latest_execution_payload_header . timestamp ,
extra_data : pre . latest_execution_payload_header . extra_data ,
base_fee_per_gas : pre . latest_execution_payload_header . base_fee_per_gas ,
block_hash : pre . latest_execution_payload_header . block_hash ,
transactions_root : pre . latest_execution_payload_header . transactions_root ,
2023-05-05 23:15:47 +00:00
withdrawals_root : pre . latest_execution_payload_header . withdrawals_root ,
2023-08-02 22:07:57 +00:00
blob_gas_used : 0 , # [New in Deneb]
excess_blob_gas : 0 # [New in Deneb]
2022-12-06 16:43:11 +00:00
)
2023-02-22 13:10:00 +00:00
( ref deneb . BeaconState ) (
2022-12-06 16:43:11 +00:00
# Versioning
genesis_time : pre . genesis_time ,
genesis_validators_root : pre . genesis_validators_root ,
slot : pre . slot ,
fork : Fork (
previous_version : pre . fork . current_version ,
2023-03-11 14:28:55 +00:00
current_version : cfg . DENEB_FORK_VERSION , # [Modified in Deneb]
2022-12-06 16:43:11 +00:00
epoch : epoch
) ,
# History
latest_block_header : pre . latest_block_header ,
block_roots : pre . block_roots ,
state_roots : pre . state_roots ,
historical_roots : pre . historical_roots ,
# Eth1
eth1_data : pre . eth1_data ,
eth1_data_votes : pre . eth1_data_votes ,
eth1_deposit_index : pre . eth1_deposit_index ,
# Registry
validators : pre . validators ,
balances : pre . balances ,
# Randomness
randao_mixes : pre . randao_mixes ,
2024-04-07 07:58:11 +00:00
# Slashings
slashings : pre . slashings ,
# Participation
previous_epoch_participation : pre . previous_epoch_participation ,
current_epoch_participation : pre . current_epoch_participation ,
# Finality
justification_bits : pre . justification_bits ,
previous_justified_checkpoint : pre . previous_justified_checkpoint ,
current_justified_checkpoint : pre . current_justified_checkpoint ,
finalized_checkpoint : pre . finalized_checkpoint ,
# Inactivity
inactivity_scores : pre . inactivity_scores ,
# Sync
current_sync_committee : pre . current_sync_committee ,
next_sync_committee : pre . next_sync_committee ,
# Execution-layer
latest_execution_payload_header : latest_execution_payload_header , # [Modified in Deneb]
# Withdrawals
next_withdrawal_index : pre . next_withdrawal_index ,
next_withdrawal_validator_index : pre . next_withdrawal_validator_index ,
# Deep history valid from Capella onwards
historical_summaries : pre . historical_summaries
)
func upgrade_to_electra * ( cfg : RuntimeConfig , pre : deneb . BeaconState ) :
ref electra . BeaconState =
debugRaiseAssert " verify upgrade_to_electra "
let
epoch = get_current_epoch ( pre )
latest_execution_payload_header = electra . ExecutionPayloadHeader (
parent_hash : pre . latest_execution_payload_header . parent_hash ,
fee_recipient : pre . latest_execution_payload_header . fee_recipient ,
state_root : pre . latest_execution_payload_header . state_root ,
receipts_root : pre . latest_execution_payload_header . receipts_root ,
logs_bloom : pre . latest_execution_payload_header . logs_bloom ,
prev_randao : pre . latest_execution_payload_header . prev_randao ,
block_number : pre . latest_execution_payload_header . block_number ,
gas_limit : pre . latest_execution_payload_header . gas_limit ,
gas_used : pre . latest_execution_payload_header . gas_used ,
timestamp : pre . latest_execution_payload_header . timestamp ,
extra_data : pre . latest_execution_payload_header . extra_data ,
base_fee_per_gas : pre . latest_execution_payload_header . base_fee_per_gas ,
block_hash : pre . latest_execution_payload_header . block_hash ,
transactions_root : pre . latest_execution_payload_header . transactions_root ,
withdrawals_root : pre . latest_execution_payload_header . withdrawals_root ,
blob_gas_used : 0 , # [New in Deneb]
excess_blob_gas : 0 # [New in Deneb]
)
( ref electra . BeaconState ) (
# Versioning
genesis_time : pre . genesis_time ,
genesis_validators_root : pre . genesis_validators_root ,
slot : pre . slot ,
fork : Fork (
previous_version : pre . fork . current_version ,
current_version : cfg . ELECTRA_FORK_VERSION , # [Modified in Deneb]
epoch : epoch
) ,
# History
latest_block_header : pre . latest_block_header ,
block_roots : pre . block_roots ,
state_roots : pre . state_roots ,
historical_roots : pre . historical_roots ,
# Eth1
eth1_data : pre . eth1_data ,
eth1_data_votes : pre . eth1_data_votes ,
eth1_deposit_index : pre . eth1_deposit_index ,
# Registry
validators : pre . validators ,
balances : pre . balances ,
# Randomness
randao_mixes : pre . randao_mixes ,
2022-12-06 16:43:11 +00:00
# Slashings
slashings : pre . slashings ,
# Participation
previous_epoch_participation : pre . previous_epoch_participation ,
current_epoch_participation : pre . current_epoch_participation ,
# Finality
justification_bits : pre . justification_bits ,
previous_justified_checkpoint : pre . previous_justified_checkpoint ,
current_justified_checkpoint : pre . current_justified_checkpoint ,
finalized_checkpoint : pre . finalized_checkpoint ,
# Inactivity
inactivity_scores : pre . inactivity_scores ,
2023-03-11 14:28:55 +00:00
2022-12-06 16:43:11 +00:00
# Sync
current_sync_committee : pre . current_sync_committee ,
next_sync_committee : pre . next_sync_committee ,
# Execution-layer
2023-03-11 14:28:55 +00:00
latest_execution_payload_header : latest_execution_payload_header , # [Modified in Deneb]
2022-12-06 16:43:11 +00:00
# Withdrawals
next_withdrawal_index : pre . next_withdrawal_index ,
2023-01-11 17:21:16 +00:00
next_withdrawal_validator_index : pre . next_withdrawal_validator_index ,
# Deep history valid from Capella onwards
historical_summaries : pre . historical_summaries
2022-12-06 16:43:11 +00:00
)
2023-10-24 01:58:52 +00:00
func latest_block_root ( state : ForkyBeaconState , state_root : Eth2Digest ) :
Eth2Digest =
2021-11-18 12:02:43 +00:00
# The root of the last block that was successfully applied to this state -
# normally, when a block is applied, the data from the header is stored in
# the state without the state root - on the next process_slot, the state root
# is added to the header and the block root can now be computed and added to
# the block roots table. If process_slot has not yet run on top of the new
# block, we must fill in the state root ourselves.
if state . slot = = state . latest_block_header . slot :
# process_slot will not yet have updated the header of the "current" block -
# similar to block creation, we fill it in with the state root
var tmp = state . latest_block_header
tmp . state_root = state_root
hash_tree_root ( tmp )
elif state . slot < =
( state . latest_block_header . slot + SLOTS_PER_HISTORICAL_ROOT ) :
# block_roots is limited to about a day - see assert in
# `get_block_root_at_slot`
state . get_block_root_at_slot ( state . latest_block_header . slot )
else :
# Reallly long periods of empty slots - unlikely but possible
hash_tree_root ( state . latest_block_header )
func latest_block_root * ( state : ForkyHashedBeaconState ) : Eth2Digest =
latest_block_root ( state . data , state . root )
Speed up altair block processing 2x (#3115)
* Speed up altair block processing >2x
Like #3089, this PR drastially speeds up historical REST queries and
other long state replays.
* cache sync committee validator indices
* use ~80mb less memory for validator pubkey mappings
* batch-verify sync aggregate signature (fixes #2985)
* document sync committee hack with head block vs sync message block
* add batch signature verification failure tests
Before:
```
../env.sh nim c -d:release -r ncli_db --db:mainnet_0/db bench --start-slot:-1000
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
5830.675, 0.000, 5830.675, 5830.675, 1, Initialize DB
0.481, 1.878, 0.215, 59.167, 981, Load block from database
8422.566, 0.000, 8422.566, 8422.566, 1, Load state from database
6.996, 1.678, 0.042, 14.385, 969, Advance slot, non-epoch
93.217, 8.318, 84.192, 122.209, 32, Advance slot, epoch
20.513, 23.665, 11.510, 201.561, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
After:
```
7081.422, 0.000, 7081.422, 7081.422, 1, Initialize DB
0.553, 2.122, 0.175, 66.692, 981, Load block from database
5439.446, 0.000, 5439.446, 5439.446, 1, Load state from database
6.829, 1.575, 0.043, 12.156, 969, Advance slot, non-epoch
94.716, 2.749, 88.395, 100.026, 32, Advance slot, epoch
11.636, 23.766, 4.889, 205.250, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
* add comment
2021-11-24 12:43:50 +00:00
2022-03-16 07:20:40 +00:00
func latest_block_root * ( state : ForkedHashedBeaconState ) : Eth2Digest =
2022-09-13 11:53:12 +00:00
withState ( state ) : latest_block_root ( forkyState )
2022-03-16 07:20:40 +00:00
Speed up altair block processing 2x (#3115)
* Speed up altair block processing >2x
Like #3089, this PR drastially speeds up historical REST queries and
other long state replays.
* cache sync committee validator indices
* use ~80mb less memory for validator pubkey mappings
* batch-verify sync aggregate signature (fixes #2985)
* document sync committee hack with head block vs sync message block
* add batch signature verification failure tests
Before:
```
../env.sh nim c -d:release -r ncli_db --db:mainnet_0/db bench --start-slot:-1000
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
5830.675, 0.000, 5830.675, 5830.675, 1, Initialize DB
0.481, 1.878, 0.215, 59.167, 981, Load block from database
8422.566, 0.000, 8422.566, 8422.566, 1, Load state from database
6.996, 1.678, 0.042, 14.385, 969, Advance slot, non-epoch
93.217, 8.318, 84.192, 122.209, 32, Advance slot, epoch
20.513, 23.665, 11.510, 201.561, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
After:
```
7081.422, 0.000, 7081.422, 7081.422, 1, Initialize DB
0.553, 2.122, 0.175, 66.692, 981, Load block from database
5439.446, 0.000, 5439.446, 5439.446, 1, Load state from database
6.829, 1.575, 0.043, 12.156, 969, Advance slot, non-epoch
94.716, 2.749, 88.395, 100.026, 32, Advance slot, epoch
11.636, 23.766, 4.889, 205.250, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
* add comment
2021-11-24 12:43:50 +00:00
func get_sync_committee_cache * (
2022-12-06 12:40:13 +00:00
state : altair . BeaconState | bellatrix . BeaconState | capella . BeaconState |
2024-02-26 06:49:12 +00:00
deneb . BeaconState | electra . BeaconState ,
2022-10-27 06:29:24 +00:00
cache : var StateCache ) : SyncCommitteeCache =
Speed up altair block processing 2x (#3115)
* Speed up altair block processing >2x
Like #3089, this PR drastially speeds up historical REST queries and
other long state replays.
* cache sync committee validator indices
* use ~80mb less memory for validator pubkey mappings
* batch-verify sync aggregate signature (fixes #2985)
* document sync committee hack with head block vs sync message block
* add batch signature verification failure tests
Before:
```
../env.sh nim c -d:release -r ncli_db --db:mainnet_0/db bench --start-slot:-1000
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
5830.675, 0.000, 5830.675, 5830.675, 1, Initialize DB
0.481, 1.878, 0.215, 59.167, 981, Load block from database
8422.566, 0.000, 8422.566, 8422.566, 1, Load state from database
6.996, 1.678, 0.042, 14.385, 969, Advance slot, non-epoch
93.217, 8.318, 84.192, 122.209, 32, Advance slot, epoch
20.513, 23.665, 11.510, 201.561, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
After:
```
7081.422, 0.000, 7081.422, 7081.422, 1, Initialize DB
0.553, 2.122, 0.175, 66.692, 981, Load block from database
5439.446, 0.000, 5439.446, 5439.446, 1, Load state from database
6.829, 1.575, 0.043, 12.156, 969, Advance slot, non-epoch
94.716, 2.749, 88.395, 100.026, 32, Advance slot, epoch
11.636, 23.766, 4.889, 205.250, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
* add comment
2021-11-24 12:43:50 +00:00
let period = state . slot . sync_committee_period ( )
cache . sync_committees . withValue ( period , v ) do :
return v [ ]
var
s = toHashSet ( state . current_sync_committee . pubkeys . data )
for pk in state . next_sync_committee . pubkeys . data :
s . incl ( pk )
var pubkeyIndices : Table [ ValidatorPubKey , ValidatorIndex ]
2022-05-23 23:39:08 +00:00
for vidx in state . validators . vindices :
let pubkey = state . validators [ vidx ] . pubkey
if pubkey in s :
pubkeyIndices [ pubkey ] = vidx
Speed up altair block processing 2x (#3115)
* Speed up altair block processing >2x
Like #3089, this PR drastially speeds up historical REST queries and
other long state replays.
* cache sync committee validator indices
* use ~80mb less memory for validator pubkey mappings
* batch-verify sync aggregate signature (fixes #2985)
* document sync committee hack with head block vs sync message block
* add batch signature verification failure tests
Before:
```
../env.sh nim c -d:release -r ncli_db --db:mainnet_0/db bench --start-slot:-1000
All time are ms
Average, StdDev, Min, Max, Samples, Test
Validation is turned off meaning that no BLS operations are performed
5830.675, 0.000, 5830.675, 5830.675, 1, Initialize DB
0.481, 1.878, 0.215, 59.167, 981, Load block from database
8422.566, 0.000, 8422.566, 8422.566, 1, Load state from database
6.996, 1.678, 0.042, 14.385, 969, Advance slot, non-epoch
93.217, 8.318, 84.192, 122.209, 32, Advance slot, epoch
20.513, 23.665, 11.510, 201.561, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
After:
```
7081.422, 0.000, 7081.422, 7081.422, 1, Initialize DB
0.553, 2.122, 0.175, 66.692, 981, Load block from database
5439.446, 0.000, 5439.446, 5439.446, 1, Load state from database
6.829, 1.575, 0.043, 12.156, 969, Advance slot, non-epoch
94.716, 2.749, 88.395, 100.026, 32, Advance slot, epoch
11.636, 23.766, 4.889, 205.250, 981, Apply block, no slot processing
0.000, 0.000, 0.000, 0.000, 0, Database load
0.000, 0.000, 0.000, 0.000, 0, Database store
```
* add comment
2021-11-24 12:43:50 +00:00
var res : SyncCommitteeCache
try :
for i in 0 .. < res . current_sync_committee . len ( ) :
res . current_sync_committee [ i ] =
pubkeyIndices [ state . current_sync_committee . pubkeys [ i ] ]
res . next_sync_committee [ i ] =
pubkeyIndices [ state . next_sync_committee . pubkeys [ i ] ]
except KeyError :
raiseAssert " table constructed just above "
cache . sync_committees [ period ] = res
res
2022-03-15 08:24:55 +00:00
func dependent_root * ( state : ForkyHashedBeaconState , epoch : Epoch ) : Eth2Digest =
## Return the root of the last block that contributed to the shuffling in the
## given epoch
if epoch > state . data . slot . epoch :
state . latest_block_root
elif epoch = = Epoch ( 0 ) :
if state . data . slot = = Slot ( 0 ) :
state . latest_block_root
else :
state . data . get_block_root_at_slot ( Slot ( 0 ) )
else :
let dependent_slot = epoch . start_slot - 1
if state . data . slot < = dependent_slot + SLOTS_PER_HISTORICAL_ROOT :
state . data . get_block_root_at_slot ( epoch . start_slot - 1 )
else :
Eth2Digest ( ) # "don't know"
func proposer_dependent_root * ( state : ForkyHashedBeaconState ) : Eth2Digest =
state . dependent_root ( state . data . slot . epoch )
func attester_dependent_root * ( state : ForkyHashedBeaconState ) : Eth2Digest =
2022-09-19 10:28:52 +00:00
state . dependent_root ( state . data . slot . epoch . get_previous_epoch )
2022-03-16 07:20:40 +00:00
2022-03-16 15:00:18 +00:00
func latest_block_id * ( state : ForkyHashedBeaconState ) : BlockId =
## Block id of the latest block applied to this state
BlockId (
root : state . latest_block_root ,
slot : state . data . latest_block_header . slot )
func latest_block_id * ( state : ForkedHashedBeaconState ) : BlockId =
## Block id of the latest block applied to this state
2022-09-13 11:53:12 +00:00
withState ( state ) : forkyState . latest_block_id ( )
2022-03-16 15:00:18 +00:00
2023-10-24 01:58:52 +00:00
func matches_block (
2022-03-16 07:20:40 +00:00
state : ForkyHashedBeaconState , block_root : Eth2Digest ) : bool =
## Return true iff the latest block applied to this state matches the given
## `block_root`
block_root = = state . latest_block_root
2022-03-16 15:00:18 +00:00
2022-03-16 07:20:40 +00:00
func matches_block * (
state : ForkedHashedBeaconState , block_root : Eth2Digest ) : bool =
2022-09-13 11:53:12 +00:00
withState ( state ) : forkyState . matches_block ( block_root )
2022-03-16 07:20:40 +00:00
2023-10-24 01:58:52 +00:00
func matches_block_slot (
2022-03-16 07:20:40 +00:00
state : ForkyHashedBeaconState , block_root : Eth2Digest , slot : Slot ) : bool =
## Return true iff the latest block applied to this state matches the given
## `block_root` and the state slot has been advanced to the given slot
slot = = state . data . slot and block_root = = state . latest_block_root
func matches_block_slot * (
state : ForkedHashedBeaconState , block_root : Eth2Digest , slot : Slot ) : bool =
2022-09-13 11:53:12 +00:00
withState ( state ) : forkyState . matches_block_slot ( block_root , slot )
2022-03-16 07:20:40 +00:00
2023-10-24 01:58:52 +00:00
func can_advance_slots (
2022-03-16 07:20:40 +00:00
state : ForkyHashedBeaconState , block_root : Eth2Digest , target_slot : Slot ) : bool =
## Return true iff we can reach the given block/slot combination simply by
2022-11-10 10:44:47 +00:00
## advancing 0 or more slots
2022-03-16 07:20:40 +00:00
target_slot > = state . data . slot and block_root = = state . latest_block_root
func can_advance_slots * (
state : ForkedHashedBeaconState , block_root : Eth2Digest , target_slot : Slot ) : bool =
2022-09-13 11:53:12 +00:00
withState ( state ) : forkyState . can_advance_slots ( block_root , target_slot )