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,
|
2021-12-03 14:46:56 +00:00
|
|
|
"."/[eth2_merkleization, forks, signatures, validator]
|
2018-11-28 19:49:03 +00:00
|
|
|
|
2024-04-28 14:13:17 +00:00
|
|
|
from std/algorithm import fill, sort
|
2023-08-02 23:03:40 +00:00
|
|
|
from std/sequtils import anyIt, mapIt, toSeq
|
2022-10-27 06:29:24 +00:00
|
|
|
|
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
|
|
|
|
2024-10-06 11:15:56 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/beacon-chain.md#new-is_compounding_withdrawal_credential
|
|
|
|
func is_compounding_withdrawal_credential*(
|
|
|
|
withdrawal_credentials: Eth2Digest): bool =
|
|
|
|
withdrawal_credentials.data[0] == COMPOUNDING_WITHDRAWAL_PREFIX
|
|
|
|
|
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/beacon-chain.md#new-has_compounding_withdrawal_credential
|
|
|
|
func has_compounding_withdrawal_credential*(validator: Validator): bool =
|
|
|
|
## Check if ``validator`` has an 0x02 prefixed "compounding" withdrawal
|
|
|
|
## credential.
|
|
|
|
is_compounding_withdrawal_credential(validator.withdrawal_credentials)
|
|
|
|
|
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.7/specs/electra/beacon-chain.md#new-get_max_effective_balance
|
|
|
|
func get_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
|
|
|
|
|
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*(
|
2024-10-06 11:15:56 +00:00
|
|
|
_: phase0.BeaconState | altair.BeaconState | bellatrix.BeaconState |
|
|
|
|
capella.BeaconState | deneb.BeaconState,
|
|
|
|
pubkey: ValidatorPubKey, withdrawal_credentials: Eth2Digest, amount: Gwei):
|
|
|
|
Validator =
|
2020-07-27 10:59:57 +00:00
|
|
|
let
|
|
|
|
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-10-06 11:15:56 +00:00
|
|
|
pubkeyData: HashedValidatorPubKey.init(pubkey),
|
|
|
|
withdrawal_credentials: 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-10-06 11:15:56 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.7/specs/electra/beacon-chain.md#deposits
|
2024-04-26 07:18:44 +00:00
|
|
|
func get_validator_from_deposit*(
|
2024-11-24 08:47:36 +00:00
|
|
|
_: electra.BeaconState | fulu.BeaconState,
|
2024-11-13 03:29:14 +00:00
|
|
|
pubkey: ValidatorPubKey,
|
2024-10-06 11:15:56 +00:00
|
|
|
withdrawal_credentials: Eth2Digest, amount: Gwei): Validator =
|
|
|
|
var validator = Validator(
|
|
|
|
pubkeyData: HashedValidatorPubKey.init(pubkey),
|
|
|
|
withdrawal_credentials: withdrawal_credentials,
|
2024-04-26 07:18:44 +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: 0.Gwei # [Modified in Electra:EIP7251]
|
|
|
|
)
|
|
|
|
|
2024-10-06 11:15:56 +00:00
|
|
|
# [Modified in Electra:EIP7251]
|
|
|
|
let max_effective_balance = get_max_effective_balance(validator)
|
|
|
|
validator.effective_balance = min(
|
|
|
|
amount - amount mod static(Gwei(EFFECTIVE_BALANCE_INCREMENT)),
|
|
|
|
max_effective_balance)
|
|
|
|
|
|
|
|
validator
|
|
|
|
|
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.7/specs/electra/beacon-chain.md#modified-add_validator_to_registry
|
|
|
|
func add_validator_to_registry*(
|
|
|
|
state: var ForkyBeaconState, deposit_data: DepositData, amount: Gwei):
|
|
|
|
Result[void, cstring] =
|
|
|
|
# New validator! Add validator and balance entries
|
|
|
|
if not state.validators.add(get_validator_from_deposit(
|
|
|
|
state, deposit_data.pubkey, deposit_data.withdrawal_credentials, amount)):
|
|
|
|
return err("apply_deposit: too many validators")
|
|
|
|
|
|
|
|
if not state.balances.add(amount):
|
|
|
|
static: doAssert state.balances.maxLen == state.validators.maxLen
|
|
|
|
raiseAssert "adding validator succeeded, so should balances"
|
|
|
|
|
|
|
|
when typeof(state).kind >= ConsensusFork.Altair:
|
|
|
|
if not state.previous_epoch_participation.add(ParticipationFlags(0)):
|
|
|
|
return err("apply_deposit: too many validators (previous_epoch_participation)")
|
|
|
|
if not state.current_epoch_participation.add(ParticipationFlags(0)):
|
|
|
|
return err("apply_deposit: too many validators (current_epoch_participation)")
|
|
|
|
if not state.inactivity_scores.add(0'u64):
|
|
|
|
return err("apply_deposit: too many validators (inactivity_scores)")
|
|
|
|
|
|
|
|
ok()
|
|
|
|
|
2024-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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-11-24 08:47:36 +00:00
|
|
|
func get_state_exit_queue_info*(state: electra.BeaconState |
|
2024-11-13 03:29:14 +00:00
|
|
|
fulu.BeaconState):
|
|
|
|
ExitQueueInfo =
|
2024-04-24 12:28:47 +00:00
|
|
|
# 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
|
|
|
|
|
2024-10-07 10:30:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.7/specs/electra/beacon-chain.md#new-get_balance_churn_limit
|
2024-04-24 12:28:47 +00:00
|
|
|
func get_balance_churn_limit(
|
2024-11-13 03:29:14 +00:00
|
|
|
cfg: RuntimeConfig, state: electra.BeaconState |
|
|
|
|
fulu.BeaconState,
|
2024-04-24 12:28:47 +00:00
|
|
|
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*(
|
2024-11-13 03:29:14 +00:00
|
|
|
cfg: RuntimeConfig, state: electra.BeaconState | fulu.BeaconState, cache: var StateCache):
|
2024-04-24 12:28:47 +00:00
|
|
|
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*(
|
2024-11-13 03:29:14 +00:00
|
|
|
cfg: RuntimeConfig, state: electra.BeaconState | fulu.BeaconState, cache: var StateCache):
|
2024-04-25 18:50:54 +00:00
|
|
|
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-11-13 03:29:14 +00:00
|
|
|
cfg: RuntimeConfig, state: var (electra.BeaconState | fulu.BeaconState),
|
|
|
|
exit_balance: Gwei,
|
2024-04-24 12:28:47 +00:00
|
|
|
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*(
|
2024-11-13 03:29:14 +00:00
|
|
|
cfg: RuntimeConfig, state: var (electra.BeaconState | fulu.BeaconState),
|
2024-04-25 18:50:54 +00:00
|
|
|
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-09-21 04:53:34 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.6/specs/electra/beacon-chain.md#modified-initiate_validator_exit
|
2024-04-24 12:28:47 +00:00
|
|
|
func initiate_validator_exit*(
|
2024-11-13 03:29:14 +00:00
|
|
|
cfg: RuntimeConfig, state: var (electra.BeaconState | fulu.BeaconState),
|
2024-04-24 12:28:47 +00:00
|
|
|
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 =
|
2024-05-22 11:56:37 +00:00
|
|
|
validator.exit_epoch + cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
2024-04-24 12:28:47 +00:00
|
|
|
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)))
|
|
|
|
|
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-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/phase0/beacon-chain.md#slash_validator
|
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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
|
2024-11-13 03:29:14 +00:00
|
|
|
elif state is electra.BeaconState or
|
|
|
|
state is fulu.BeaconState:
|
2024-04-25 08:41:17 +00:00
|
|
|
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-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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
|
2024-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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-08-21 12:25:19 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.5/specs/electra/beacon-chain.md#modified-slash_validator
|
2024-04-25 08:41:17 +00:00
|
|
|
func get_whistleblower_reward*(
|
2024-11-24 08:47:36 +00:00
|
|
|
state: electra.BeaconState | fulu.BeaconState,
|
2024-11-13 03:29:14 +00:00
|
|
|
validator_effective_balance: Gwei): Gwei =
|
2024-04-25 08:41:17 +00:00
|
|
|
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-11-24 12:16:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/specs/altair/beacon-chain.md#modified-slash_validator
|
2024-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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
|
2024-11-13 03:29:14 +00:00
|
|
|
state is electra.BeaconState or state is fulu.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
|
2024-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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
|
|
|
|
2024-11-24 12:16:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/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-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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-06-16 00:59:25 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/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-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))
|
|
|
|
|
2024-11-13 03:29:14 +00:00
|
|
|
func get_initial_beacon_block*(state: fulu.HashedBeaconState):
|
|
|
|
fulu.TrustedSignedBeaconBlock =
|
|
|
|
# The genesis block is implicitly trusted
|
|
|
|
let message = fulu.TrustedBeaconBlock(
|
|
|
|
slot: state.data.slot,
|
|
|
|
state_root: state.root)
|
|
|
|
# parent_root, randao_reveal, eth1_data, signature, and body automatically
|
|
|
|
# initialized to default values.
|
|
|
|
fulu.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-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/phase0/beacon-chain.md#is_eligible_for_activation_queue
|
2024-07-15 19:08:20 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/beacon-chain.md#updated-is_eligible_for_activation_queue
|
|
|
|
func is_eligible_for_activation_queue*(
|
|
|
|
fork: static ConsensusFork, validator: Validator): bool =
|
2020-09-08 08:54:55 +00:00
|
|
|
## Check if ``validator`` is eligible to be placed into the activation queue.
|
2024-07-15 19:08:20 +00:00
|
|
|
when fork <= ConsensusFork.Deneb:
|
|
|
|
validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH and
|
|
|
|
validator.effective_balance == MAX_EFFECTIVE_BALANCE.Gwei
|
|
|
|
else:
|
|
|
|
# [Modified in Electra:EIP7251]
|
|
|
|
validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH and
|
|
|
|
validator.effective_balance >= MIN_ACTIVATION_BALANCE.Gwei
|
2019-12-16 18:08:50 +00:00
|
|
|
|
2024-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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,
|
2024-09-26 06:11:58 +00:00
|
|
|
# phase0.SomeIndexedAttestation | electra.SomeIndexedAttestation:
|
|
|
|
# https://github.com/nim-lang/Nim/issues/18095
|
|
|
|
indexed_attestation:
|
|
|
|
phase0.IndexedAttestation | phase0.TrustedIndexedAttestation |
|
|
|
|
electra.IndexedAttestation | electra.TrustedIndexedAttestation,
|
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-06-22 05:28:19 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/beacon-chain.md#modified-get_attesting_indices
|
2024-04-28 00:52:14 +00:00
|
|
|
iterator get_attesting_indices_iter*(
|
2024-11-13 03:29:14 +00:00
|
|
|
state: electra.BeaconState | fulu.BeaconState,
|
2024-04-28 00:52:14 +00:00
|
|
|
data: AttestationData,
|
|
|
|
aggregation_bits: ElectraCommitteeValidatorsBits,
|
|
|
|
committee_bits: auto,
|
|
|
|
cache: var StateCache): ValidatorIndex =
|
|
|
|
## Return the set of attesting indices corresponding to ``aggregation_bits``
|
|
|
|
## and ``committee_bits``.
|
2024-05-17 12:37:41 +00:00
|
|
|
var pos = 0
|
|
|
|
for committee_index in get_committee_indices(committee_bits):
|
|
|
|
for _, validator_index in get_beacon_committee(
|
|
|
|
state, data.slot, committee_index, cache):
|
|
|
|
|
|
|
|
if aggregation_bits[pos]:
|
|
|
|
yield validator_index
|
|
|
|
pos += 1
|
2024-04-28 00:52:14 +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
|
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))
|
|
|
|
|
2024-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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: 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-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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-11-24 12:16:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/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-11-13 03:29:14 +00:00
|
|
|
state: deneb.BeaconState | electra.BeaconState | fulu.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-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/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-11-24 12:16:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/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-11-13 03:29:14 +00:00
|
|
|
deneb.BeaconState | electra.BeaconState | fulu.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,
|
2024-05-17 12:37:41 +00:00
|
|
|
cache: var StateCache, on_chain: static bool = true): 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-11-24 08:47:36 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/specs/electra/beacon-chain.md#modified-process_attestation
|
2024-04-22 09:00:38 +00:00
|
|
|
proc check_attestation*(
|
2024-11-13 03:29:14 +00:00
|
|
|
state: electra.BeaconState | fulu.BeaconState,
|
2024-04-28 00:52:14 +00:00
|
|
|
attestation: electra.Attestation | electra.TrustedAttestation,
|
2024-05-17 12:37:41 +00:00
|
|
|
flags: UpdateFlags, cache: var StateCache, on_chain: static bool): Result[void, cstring] =
|
2024-04-28 00:52:14 +00:00
|
|
|
## 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")
|
|
|
|
|
2024-05-17 12:37:41 +00:00
|
|
|
when on_chain:
|
2024-11-24 08:47:36 +00:00
|
|
|
var committee_offset = 0
|
|
|
|
for committee_index in attestation.committee_bits.oneIndices:
|
|
|
|
if not (committee_index.uint64 < get_committee_count_per_slot(
|
2024-05-17 12:37:41 +00:00
|
|
|
state, data.target.epoch, cache)):
|
|
|
|
return err("attestation wrong committee index len")
|
2024-11-24 08:47:36 +00:00
|
|
|
let committee = get_beacon_committee(
|
|
|
|
state, data.slot, committee_index.CommitteeIndex, cache)
|
|
|
|
|
|
|
|
if attestation.aggregation_bits.len < committee_offset + len(committee):
|
|
|
|
# This would overflow; see invalid_too_many_committee_bits test case
|
|
|
|
return err("Electra attestation has too many committee bits")
|
|
|
|
|
|
|
|
# This construction modified slightly from spec version to early-exit and
|
|
|
|
# not create the actual set, but the result is it uses a flag variable to
|
|
|
|
# look similar.
|
|
|
|
var committee_attesters_nonzero = false
|
|
|
|
for i, attester_index in committee:
|
|
|
|
if attestation.aggregation_bits[committee_offset + i]:
|
|
|
|
committee_attesters_nonzero = true
|
|
|
|
break
|
|
|
|
if not committee_attesters_nonzero:
|
|
|
|
return err("Electra attestation committee not present in aggregated bits")
|
|
|
|
|
|
|
|
committee_offset += len(committee)
|
|
|
|
|
|
|
|
if not (len(attestation.aggregation_bits) == committee_offset):
|
2024-05-17 12:37:41 +00:00
|
|
|
return err("attestation wrong aggregation bit length")
|
|
|
|
else:
|
|
|
|
let
|
|
|
|
committee_index = get_committee_index_one(attestation.committee_bits).valueOr:
|
|
|
|
return err("Network attestation without single committee index")
|
2024-04-28 00:52:14 +00:00
|
|
|
|
2024-05-17 12:37:41 +00:00
|
|
|
if not (lenu64(attestation.aggregation_bits) ==
|
|
|
|
get_beacon_committee_len(state, data.slot, committee_index, cache)):
|
|
|
|
return err("attestation wrong aggregation bit length")
|
2024-04-28 00:52:14 +00:00
|
|
|
|
|
|
|
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()
|
|
|
|
|
2024-11-24 12:16:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/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,
|
2024-11-13 03:29:14 +00:00
|
|
|
state: capella.BeaconState | deneb.BeaconState | electra.BeaconState |
|
|
|
|
fulu.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-05-17 12:37:41 +00:00
|
|
|
? check_attestation(state, attestation, flags, cache, true)
|
2024-04-28 00:52:14 +00:00
|
|
|
|
|
|
|
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-11-24 12:16:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/specs/altair/beacon-chain.md#get_next_sync_committee_indices
|
2024-06-15 22:15:27 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/beacon-chain.md#modified-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-11-13 03:29:14 +00:00
|
|
|
deneb.BeaconState | electra.BeaconState | fulu.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-06-15 22:15:27 +00:00
|
|
|
const meb =
|
2024-06-20 19:09:41 +00:00
|
|
|
when typeof(state).kind >= ConsensusFork.Electra:
|
2024-06-15 22:15:27 +00:00
|
|
|
MAX_EFFECTIVE_BALANCE_ELECTRA.Gwei # [Modified in Electra:EIP7251]
|
|
|
|
else:
|
|
|
|
MAX_EFFECTIVE_BALANCE.Gwei
|
|
|
|
|
|
|
|
if effective_balance * MAX_RANDOM_BYTE >= meb * 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
|
|
|
|
2024-11-24 12:16:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/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-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-11-24 12:16:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/specs/capella/beacon-chain.md#is_fully_withdrawable_validator
|
2024-06-15 22:15:27 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/beacon-chain.md#updated-is_fully_withdrawable_validator
|
|
|
|
func is_fully_withdrawable_validator(
|
|
|
|
fork: static ConsensusFork, validator: Validator, balance: Gwei,
|
|
|
|
epoch: Epoch): bool =
|
|
|
|
## Check if ``validator`` is fully withdrawable.
|
|
|
|
when fork >= ConsensusFork.Electra:
|
|
|
|
# [Modified in Electra:EIP7251]
|
|
|
|
has_execution_withdrawal_credential(validator) and
|
|
|
|
validator.withdrawable_epoch <= epoch and balance > 0.Gwei
|
|
|
|
else:
|
|
|
|
has_eth1_withdrawal_credential(validator) and
|
|
|
|
validator.withdrawable_epoch <= epoch and balance > 0.Gwei
|
|
|
|
|
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#is_partially_withdrawable_validator
|
2024-10-07 10:30:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.7/specs/electra/beacon-chain.md#modified-is_partially_withdrawable_validator
|
2024-06-15 22:15:27 +00:00
|
|
|
func is_partially_withdrawable_validator(
|
|
|
|
fork: static ConsensusFork, validator: Validator, balance: Gwei): bool =
|
|
|
|
## Check if ``validator`` is partially withdrawable.
|
|
|
|
when fork >= ConsensusFork.Electra:
|
|
|
|
# [Modified in Electra:EIP7251]
|
|
|
|
let
|
2024-10-06 11:15:56 +00:00
|
|
|
max_effective_balance = get_max_effective_balance(validator)
|
2024-06-15 22:15:27 +00:00
|
|
|
has_max_effective_balance =
|
|
|
|
validator.effective_balance == max_effective_balance
|
|
|
|
has_excess_balance =
|
|
|
|
balance > max_effective_balance # [Modified in Electra:EIP7251]
|
|
|
|
has_execution_withdrawal_credential(validator) and
|
|
|
|
has_max_effective_balance and has_excess_balance
|
|
|
|
else:
|
|
|
|
let
|
|
|
|
has_max_effective_balance =
|
|
|
|
validator.effective_balance == static(MAX_EFFECTIVE_BALANCE.Gwei)
|
|
|
|
has_excess_balance = balance > static(MAX_EFFECTIVE_BALANCE.Gwei)
|
|
|
|
has_eth1_withdrawal_credential(validator) and
|
|
|
|
has_max_effective_balance and has_excess_balance
|
|
|
|
|
2024-10-06 11:15:56 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.7/specs/electra/beacon-chain.md#new-queue_excess_active_balance
|
2024-04-24 12:28:47 +00:00
|
|
|
func queue_excess_active_balance(
|
2024-11-13 03:29:14 +00:00
|
|
|
state: var (electra.BeaconState | fulu.BeaconState),
|
|
|
|
index: uint64) =
|
2024-04-24 12:28:47 +00:00
|
|
|
let balance = state.balances.item(index)
|
2024-10-06 11:15:56 +00:00
|
|
|
if balance > static(MIN_ACTIVATION_BALANCE.Gwei):
|
|
|
|
let excess_balance = balance - static(MIN_ACTIVATION_BALANCE.Gwei)
|
|
|
|
state.balances.mitem(index) = static(MIN_ACTIVATION_BALANCE.Gwei)
|
|
|
|
let validator = state.validators.item(index)
|
|
|
|
# Use bls.G2_POINT_AT_INFINITY as a signature field placeholder and
|
|
|
|
# GENESIS_SLOT to distinguish from a pending deposit request
|
|
|
|
discard state.pending_deposits.add(PendingDeposit(
|
|
|
|
pubkey: validator.pubkey,
|
|
|
|
withdrawal_credentials: validator.withdrawal_credentials,
|
|
|
|
amount: excess_balance,
|
|
|
|
signature: ValidatorSig.infinity,
|
|
|
|
slot: GENESIS_SLOT))
|
|
|
|
|
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.7/specs/electra/beacon-chain.md#new-switch_to_compounding_validator
|
2024-04-24 12:28:47 +00:00
|
|
|
func switch_to_compounding_validator*(
|
2024-11-13 03:29:14 +00:00
|
|
|
state: var (electra.BeaconState | fulu.BeaconState),
|
|
|
|
index: ValidatorIndex) =
|
2024-04-24 12:28:47 +00:00
|
|
|
let validator = addr state.validators.mitem(index)
|
2024-10-06 11:15:56 +00:00
|
|
|
validator.withdrawal_credentials.data[0] = COMPOUNDING_WITHDRAWAL_PREFIX
|
|
|
|
queue_excess_active_balance(state, index.uint64)
|
2024-04-24 12:28:47 +00:00
|
|
|
|
2024-10-09 04:33:17 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/electra/beacon-chain.md#new-get_pending_balance_to_withdraw
|
2024-04-25 08:41:17 +00:00
|
|
|
func get_pending_balance_to_withdraw*(
|
2024-11-24 08:47:36 +00:00
|
|
|
state: electra.BeaconState | fulu.BeaconState,
|
2024-11-13 03:29:14 +00:00
|
|
|
validator_index: ValidatorIndex): Gwei =
|
2024-04-25 08:41:17 +00:00
|
|
|
var pending_balance: Gwei
|
|
|
|
for withdrawal in state.pending_partial_withdrawals:
|
|
|
|
if withdrawal.index == validator_index:
|
|
|
|
pending_balance += withdrawal.amount
|
|
|
|
|
|
|
|
pending_balance
|
|
|
|
|
2024-08-06 11:33:16 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/phase0/beacon-chain.md#effective-balances-updates
|
|
|
|
template effective_balance_might_update*(
|
|
|
|
balance: Gwei, effective_balance: Gwei): bool =
|
|
|
|
const
|
|
|
|
HYSTERESIS_INCREMENT =
|
|
|
|
EFFECTIVE_BALANCE_INCREMENT.Gwei div HYSTERESIS_QUOTIENT
|
|
|
|
DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER
|
|
|
|
UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER
|
|
|
|
balance + DOWNWARD_THRESHOLD < effective_balance or
|
|
|
|
effective_balance + UPWARD_THRESHOLD < balance
|
|
|
|
|
2024-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/phase0/beacon-chain.md#effective-balances-updates
|
2024-08-06 11:33:16 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.1/specs/electra/beacon-chain.md#updated-process_effective_balance_updates
|
|
|
|
template get_effective_balance_update*(
|
|
|
|
consensusFork: static ConsensusFork, balance: Gwei,
|
|
|
|
effective_balance: Gwei, vidx: uint64): Gwei =
|
|
|
|
when consensusFork <= ConsensusFork.Deneb:
|
|
|
|
min(
|
|
|
|
balance - balance mod EFFECTIVE_BALANCE_INCREMENT.Gwei,
|
|
|
|
MAX_EFFECTIVE_BALANCE.Gwei)
|
|
|
|
else:
|
|
|
|
let effective_balance_limit =
|
|
|
|
if has_compounding_withdrawal_credential(state.validators.item(vidx)):
|
|
|
|
MAX_EFFECTIVE_BALANCE_ELECTRA.Gwei
|
|
|
|
else:
|
|
|
|
MIN_ACTIVATION_BALANCE.Gwei
|
|
|
|
min(
|
|
|
|
balance - balance mod EFFECTIVE_BALANCE_INCREMENT.Gwei,
|
|
|
|
effective_balance_limit)
|
|
|
|
|
|
|
|
template get_updated_effective_balance*(
|
|
|
|
consensusFork: static ConsensusFork, balance: Gwei,
|
|
|
|
effective_balance: Gwei, vidx: uint64): Gwei =
|
|
|
|
if effective_balance_might_update(balance, effective_balance):
|
|
|
|
get_effective_balance_update(consensusFork, balance, effective_balance, vidx)
|
|
|
|
else:
|
|
|
|
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
|
2024-08-06 11:33:16 +00:00
|
|
|
template get_expected_withdrawals_aux*(
|
|
|
|
state: capella.BeaconState | deneb.BeaconState, epoch: Epoch,
|
|
|
|
fetch_balance: untyped): seq[Withdrawal] =
|
2023-01-06 21:01:10 +00:00
|
|
|
let
|
|
|
|
num_validators = lenu64(state.validators)
|
2024-06-15 22:15:27 +00:00
|
|
|
bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
2023-01-06 21:01:10 +00:00
|
|
|
var
|
|
|
|
withdrawal_index = state.next_withdrawal_index
|
2024-08-06 11:33:16 +00:00
|
|
|
validator_index {.inject.} = state.next_withdrawal_validator_index
|
2023-01-06 21:01:10 +00:00
|
|
|
withdrawals: seq[Withdrawal] = @[]
|
|
|
|
for _ in 0 ..< bound:
|
|
|
|
let
|
|
|
|
validator = state.validators[validator_index]
|
2024-08-06 11:33:16 +00:00
|
|
|
balance = fetch_balance
|
2024-06-15 22:15:27 +00:00
|
|
|
if is_fully_withdrawable_validator(
|
|
|
|
typeof(state).kind, validator, balance, epoch):
|
2023-01-06 21:01:10 +00:00
|
|
|
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)
|
2024-06-15 22:15:27 +00:00
|
|
|
elif is_partially_withdrawable_validator(
|
|
|
|
typeof(state).kind, validator, balance):
|
2023-01-06 21:01:10 +00:00
|
|
|
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-08-06 11:33:16 +00:00
|
|
|
func get_expected_withdrawals*(
|
|
|
|
state: capella.BeaconState | deneb.BeaconState): seq[Withdrawal] =
|
|
|
|
get_expected_withdrawals_aux(state, get_current_epoch(state)) do:
|
|
|
|
state.balances[validator_index]
|
|
|
|
|
2024-10-09 04:33:17 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/electra/beacon-chain.md#modified-get_expected_withdrawals
|
2024-06-15 22:15:27 +00:00
|
|
|
# This partials count is used in exactly one place, while in general being able
|
|
|
|
# to cleanly treat the results of get_expected_withdrawals as a seq[Withdrawal]
|
|
|
|
# are valuable enough to make that the default version of this spec function.
|
2024-08-06 11:33:16 +00:00
|
|
|
template get_expected_withdrawals_with_partial_count_aux*(
|
2024-11-24 08:47:36 +00:00
|
|
|
state: electra.BeaconState | fulu.BeaconState,
|
2024-11-13 03:29:14 +00:00
|
|
|
epoch: Epoch, fetch_balance: untyped):
|
2024-06-15 22:15:27 +00:00
|
|
|
(seq[Withdrawal], uint64) =
|
2024-08-06 11:33:16 +00:00
|
|
|
doAssert epoch - get_current_epoch(state) in [0'u64, 1'u64]
|
|
|
|
|
2024-06-15 22:15:27 +00:00
|
|
|
var
|
|
|
|
withdrawal_index = state.next_withdrawal_index
|
|
|
|
withdrawals: seq[Withdrawal] = @[]
|
2024-11-24 08:47:36 +00:00
|
|
|
processed_partial_withdrawals_count: uint64 = 0
|
2024-06-15 22:15:27 +00:00
|
|
|
|
|
|
|
# [New in Electra:EIP7251] Consume pending partial withdrawals
|
|
|
|
for withdrawal in state.pending_partial_withdrawals:
|
|
|
|
if withdrawal.withdrawable_epoch > epoch or
|
|
|
|
len(withdrawals) == MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP:
|
|
|
|
break
|
|
|
|
|
|
|
|
let
|
2024-08-06 11:33:16 +00:00
|
|
|
validator = state.validators.item(withdrawal.index)
|
|
|
|
|
|
|
|
# Keep a uniform variable name available for injected code
|
|
|
|
validator_index {.inject.} = withdrawal.index
|
|
|
|
|
|
|
|
# Here, can't use the pre-stored effective balance because this template
|
|
|
|
# might be called on the next slot and therefore next epoch, after which
|
|
|
|
# the effective balance might have updated.
|
|
|
|
effective_balance_at_slot =
|
|
|
|
if epoch == get_current_epoch(state):
|
|
|
|
validator.effective_balance
|
|
|
|
else:
|
|
|
|
get_updated_effective_balance(
|
|
|
|
typeof(state).kind, fetch_balance, validator.effective_balance,
|
|
|
|
validator_index)
|
|
|
|
|
2024-06-15 22:15:27 +00:00
|
|
|
has_sufficient_effective_balance =
|
2024-08-06 11:33:16 +00:00
|
|
|
effective_balance_at_slot >= static(MIN_ACTIVATION_BALANCE.Gwei)
|
|
|
|
has_excess_balance = fetch_balance > static(MIN_ACTIVATION_BALANCE.Gwei)
|
2024-06-15 22:15:27 +00:00
|
|
|
if validator.exit_epoch == FAR_FUTURE_EPOCH and
|
|
|
|
has_sufficient_effective_balance and has_excess_balance:
|
2024-08-06 11:33:16 +00:00
|
|
|
let
|
|
|
|
withdrawable_balance = min(
|
|
|
|
fetch_balance - static(MIN_ACTIVATION_BALANCE.Gwei),
|
|
|
|
withdrawal.amount)
|
2024-06-15 22:15:27 +00:00
|
|
|
var w = Withdrawal(
|
|
|
|
index: withdrawal_index,
|
|
|
|
validator_index: withdrawal.index,
|
|
|
|
amount: withdrawable_balance)
|
|
|
|
w.address.data[0..19] = validator.withdrawal_credentials.data[12..^1]
|
|
|
|
withdrawals.add w
|
|
|
|
withdrawal_index += 1
|
|
|
|
|
2024-11-24 08:47:36 +00:00
|
|
|
processed_partial_withdrawals_count += 1
|
2024-06-15 22:15:27 +00:00
|
|
|
|
|
|
|
let
|
|
|
|
bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
|
|
|
num_validators = lenu64(state.validators)
|
2024-08-06 11:33:16 +00:00
|
|
|
var validator_index {.inject.} = state.next_withdrawal_validator_index
|
2024-06-15 22:15:27 +00:00
|
|
|
|
|
|
|
# Sweep for remaining.
|
|
|
|
for _ in 0 ..< bound:
|
|
|
|
let
|
2024-08-06 11:33:16 +00:00
|
|
|
validator = state.validators.item(validator_index)
|
2024-11-24 08:47:36 +00:00
|
|
|
# [Modified in Electra:EIP7251]
|
|
|
|
partially_withdrawn_balance = block:
|
|
|
|
var subtot: Gwei
|
|
|
|
for withdrawal in withdrawals:
|
|
|
|
if withdrawal.validator_index == validator_index:
|
|
|
|
subtot += withdrawal.amount
|
|
|
|
subtot
|
|
|
|
balance = fetch_balance - partially_withdrawn_balance
|
2024-06-15 22:15:27 +00:00
|
|
|
if is_fully_withdrawable_validator(
|
|
|
|
typeof(state).kind, 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(
|
|
|
|
typeof(state).kind, validator, balance):
|
|
|
|
var w = Withdrawal(
|
|
|
|
index: withdrawal_index,
|
|
|
|
validator_index: validator_index,
|
|
|
|
# [Modified in Electra:EIP7251]
|
2024-10-06 11:15:56 +00:00
|
|
|
amount: balance - get_max_effective_balance(validator))
|
2024-06-15 22:15:27 +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
|
|
|
|
|
2024-11-24 08:47:36 +00:00
|
|
|
(withdrawals, processed_partial_withdrawals_count)
|
2024-06-15 22:15:27 +00:00
|
|
|
|
2024-08-06 11:33:16 +00:00
|
|
|
template get_expected_withdrawals_with_partial_count*(
|
2024-11-13 03:29:14 +00:00
|
|
|
state: electra.BeaconState | fulu.BeaconState): (seq[Withdrawal], uint64) =
|
2024-08-06 11:33:16 +00:00
|
|
|
get_expected_withdrawals_with_partial_count_aux(
|
|
|
|
state, get_current_epoch(state)) do:
|
|
|
|
state.balances.item(validator_index)
|
|
|
|
|
2024-11-24 08:47:36 +00:00
|
|
|
func get_expected_withdrawals*(state: electra.BeaconState | fulu.BeaconState):
|
2024-11-13 03:29:14 +00:00
|
|
|
seq[Withdrawal] =
|
2024-06-15 22:15:27 +00:00
|
|
|
get_expected_withdrawals_with_partial_count(state)[0]
|
|
|
|
|
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-11-13 03:29:14 +00:00
|
|
|
deneb.BeaconState | electra.BeaconState | fulu.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-10-06 11:15:56 +00:00
|
|
|
if not state.validators.add(get_validator_from_deposit(
|
|
|
|
state, deposit.pubkey, deposit.withdrawal_credentials,
|
|
|
|
deposit.amount)):
|
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-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/bellatrix/beacon-chain.md#testing
|
2024-06-16 00:59:25 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/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-10-06 11:15:56 +00:00
|
|
|
if not state.validators.add get_validator_from_deposit(
|
|
|
|
state, deposit.pubkey, deposit.withdrawal_credentials,
|
|
|
|
deposit.amount):
|
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-11-24 12:16:09 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/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
|
|
|
|
)
|
|
|
|
|
2024-10-09 06:37:35 +00:00
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/electra/fork.md#upgrading-the-state
|
2024-04-28 14:13:17 +00:00
|
|
|
func upgrade_to_electra*(
|
|
|
|
cfg: RuntimeConfig, pre: deneb.BeaconState, cache: var StateCache):
|
2024-04-07 07:58:11 +00:00
|
|
|
ref electra.BeaconState =
|
|
|
|
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,
|
2024-10-17 00:15:34 +00:00
|
|
|
blob_gas_used: pre.latest_execution_payload_header.blob_gas_used,
|
|
|
|
excess_blob_gas: pre.latest_execution_payload_header.excess_blob_gas)
|
2024-04-07 07:58:11 +00:00
|
|
|
|
2024-11-24 08:47:36 +00:00
|
|
|
var earliest_exit_epoch =
|
|
|
|
compute_activation_exit_epoch(get_current_epoch(pre))
|
2024-04-28 14:13:17 +00:00
|
|
|
for v in pre.validators:
|
|
|
|
if v.exit_epoch != FAR_FUTURE_EPOCH:
|
2024-11-24 08:47:36 +00:00
|
|
|
if v.exit_epoch > earliest_exit_epoch:
|
|
|
|
earliest_exit_epoch = v.exit_epoch
|
|
|
|
earliest_exit_epoch += 1
|
2024-04-28 14:13:17 +00:00
|
|
|
|
|
|
|
let post = (ref electra.BeaconState)(
|
2024-04-07 07:58: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,
|
2024-04-28 14:13:17 +00:00
|
|
|
current_version: cfg.ELECTRA_FORK_VERSION, # [Modified in Electra:EIP6110]
|
2024-04-07 07:58: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,
|
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
|
2024-04-28 14:13:17 +00:00
|
|
|
latest_execution_payload_header: latest_execution_payload_header,
|
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
|
2024-04-28 14:13:17 +00:00
|
|
|
historical_summaries: pre.historical_summaries,
|
|
|
|
|
|
|
|
# [New in Electra:EIP6110]
|
2024-06-15 22:15:27 +00:00
|
|
|
deposit_requests_start_index: UNSET_DEPOSIT_REQUESTS_START_INDEX,
|
2024-04-28 14:13:17 +00:00
|
|
|
|
|
|
|
# [New in Electra:EIP7251]
|
|
|
|
deposit_balance_to_consume: 0.Gwei,
|
|
|
|
exit_balance_to_consume: 0.Gwei,
|
|
|
|
earliest_exit_epoch: earliest_exit_epoch,
|
|
|
|
consolidation_balance_to_consume: 0.Gwei,
|
|
|
|
earliest_consolidation_epoch:
|
|
|
|
compute_activation_exit_epoch(get_current_epoch(pre))
|
|
|
|
|
|
|
|
# pending_balance_deposits, pending_partial_withdrawals, and
|
|
|
|
# pending_consolidations are default empty lists
|
2022-12-06 16:43:11 +00:00
|
|
|
)
|
|
|
|
|
2024-04-28 14:13:17 +00:00
|
|
|
post.exit_balance_to_consume =
|
|
|
|
get_activation_exit_churn_limit(cfg, post[], cache)
|
|
|
|
post.consolidation_balance_to_consume =
|
|
|
|
get_consolidation_churn_limit(cfg, post[], cache)
|
|
|
|
|
|
|
|
# [New in Electra:EIP7251]
|
|
|
|
# add validators that are not yet active to pending balance deposits
|
|
|
|
var pre_activation: seq[(Epoch, uint64)]
|
|
|
|
for index, validator in post.validators:
|
|
|
|
if validator.activation_epoch == FAR_FUTURE_EPOCH:
|
|
|
|
pre_activation.add((validator.activation_eligibility_epoch, index.uint64))
|
|
|
|
sort(pre_activation)
|
|
|
|
|
|
|
|
for (_, index) in pre_activation:
|
2024-10-06 11:15:56 +00:00
|
|
|
let balance = post.balances.item(index)
|
|
|
|
post.balances[index] = 0.Gwei
|
|
|
|
let validator = addr post.validators.mitem(index)
|
|
|
|
validator[].effective_balance = 0.Gwei
|
|
|
|
validator[].activation_eligibility_epoch = FAR_FUTURE_EPOCH
|
|
|
|
# Use bls.G2_POINT_AT_INFINITY as a signature field placeholder and
|
|
|
|
# GENESIS_SLOT to distinguish from a pending deposit request
|
|
|
|
discard post.pending_deposits.add PendingDeposit(
|
|
|
|
pubkey: validator[].pubkey,
|
|
|
|
withdrawal_credentials: validator[].withdrawal_credentials,
|
|
|
|
amount: balance,
|
|
|
|
signature: ValidatorSig.infinity,
|
|
|
|
slot: GENESIS_SLOT)
|
2024-04-28 14:13:17 +00:00
|
|
|
|
|
|
|
# Ensure early adopters of compounding credentials go through the activation
|
|
|
|
# churn
|
|
|
|
for index, validator in post.validators:
|
|
|
|
if has_compounding_withdrawal_credential(validator):
|
2024-09-13 08:07:06 +00:00
|
|
|
queue_excess_active_balance(post[], index.uint64)
|
2024-04-28 14:13:17 +00:00
|
|
|
|
|
|
|
post
|
|
|
|
|
2024-11-13 03:29:14 +00:00
|
|
|
func upgrade_to_fulu*(
|
|
|
|
cfg: RuntimeConfig, pre: electra.BeaconState, cache: var StateCache):
|
|
|
|
ref fulu.BeaconState =
|
|
|
|
let
|
|
|
|
epoch = get_current_epoch(pre)
|
|
|
|
latest_execution_payload_header = fulu.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: pre.latest_execution_payload_header.blob_gas_used,
|
|
|
|
excess_blob_gas: pre.latest_execution_payload_header.excess_blob_gas)
|
|
|
|
|
|
|
|
var max_exit_epoch = FAR_FUTURE_EPOCH
|
|
|
|
for v in pre.validators:
|
|
|
|
if v.exit_epoch != FAR_FUTURE_EPOCH:
|
|
|
|
max_exit_epoch =
|
|
|
|
if max_exit_epoch == FAR_FUTURE_EPOCH:
|
|
|
|
v.exit_epoch
|
|
|
|
else:
|
|
|
|
max(max_exit_epoch, v.exit_epoch)
|
|
|
|
if max_exit_epoch == FAR_FUTURE_EPOCH:
|
|
|
|
max_exit_epoch = get_current_epoch(pre)
|
|
|
|
let earliest_exit_epoch = max_exit_epoch + 1
|
|
|
|
|
|
|
|
let post = (ref fulu.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.FULU_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: pre.next_withdrawal_index,
|
|
|
|
next_withdrawal_validator_index: pre.next_withdrawal_validator_index,
|
|
|
|
|
|
|
|
# Deep history valid from Capella onwards
|
|
|
|
historical_summaries: pre.historical_summaries,
|
|
|
|
|
|
|
|
# [New in Electra:EIP6110]
|
|
|
|
deposit_requests_start_index: UNSET_DEPOSIT_REQUESTS_START_INDEX,
|
|
|
|
|
|
|
|
# [New in Electra:EIP7251]
|
|
|
|
deposit_balance_to_consume: 0.Gwei,
|
|
|
|
exit_balance_to_consume: 0.Gwei,
|
|
|
|
earliest_exit_epoch: earliest_exit_epoch,
|
|
|
|
consolidation_balance_to_consume: 0.Gwei,
|
|
|
|
earliest_consolidation_epoch:
|
|
|
|
compute_activation_exit_epoch(get_current_epoch(pre))
|
|
|
|
|
|
|
|
# pending_balance_deposits, pending_partial_withdrawals, and
|
|
|
|
# pending_consolidations are default empty lists
|
|
|
|
)
|
|
|
|
|
|
|
|
post.exit_balance_to_consume =
|
|
|
|
get_activation_exit_churn_limit(cfg, post[], cache)
|
|
|
|
post.consolidation_balance_to_consume =
|
|
|
|
get_consolidation_churn_limit(cfg, post[], cache)
|
|
|
|
|
|
|
|
# [New in Electra:EIP7251]
|
|
|
|
# add validators that are not yet active to pending balance deposits
|
|
|
|
var pre_activation: seq[(Epoch, uint64)]
|
|
|
|
for index, validator in post.validators:
|
|
|
|
if validator.activation_epoch == FAR_FUTURE_EPOCH:
|
|
|
|
pre_activation.add((validator.activation_eligibility_epoch, index.uint64))
|
|
|
|
sort(pre_activation)
|
|
|
|
|
|
|
|
for (_, index) in pre_activation:
|
|
|
|
let balance = post.balances.item(index)
|
|
|
|
post.balances[index] = 0.Gwei
|
|
|
|
let validator = addr post.validators.mitem(index)
|
|
|
|
validator[].effective_balance = 0.Gwei
|
|
|
|
validator[].activation_eligibility_epoch = FAR_FUTURE_EPOCH
|
|
|
|
# Use bls.G2_POINT_AT_INFINITY as a signature field placeholder and
|
|
|
|
# GENESIS_SLOT to distinguish from a pending deposit request
|
|
|
|
discard post.pending_deposits.add PendingDeposit(
|
|
|
|
pubkey: validator[].pubkey,
|
|
|
|
withdrawal_credentials: validator[].withdrawal_credentials,
|
|
|
|
amount: balance,
|
|
|
|
signature: ValidatorSig.infinity,
|
|
|
|
slot: GENESIS_SLOT)
|
|
|
|
|
|
|
|
# Ensure early adopters of compounding credentials go through the activation
|
|
|
|
# churn
|
|
|
|
for index, validator in post.validators:
|
|
|
|
if has_compounding_withdrawal_credential(validator):
|
|
|
|
queue_excess_active_balance(post[], index.uint64)
|
|
|
|
|
|
|
|
post
|
|
|
|
|
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-11-13 03:29:14 +00:00
|
|
|
deneb.BeaconState | electra.BeaconState | fulu.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)
|