Update go to 1.19.3 (#11630)

* Update go to 1.19.3

* Update other items to 1.19

* Update golangci-lint to latest release

* Run gofmt -s with go1.19

* Huge gofmt changes

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
Preston Van Loon 2022-11-18 14:12:19 -05:00 committed by GitHub
parent 07d0a00f88
commit 4b033f4cc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 1603 additions and 1470 deletions

View File

@ -26,10 +26,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Go 1.18 - name: Set up Go 1.19
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: 1.19
- name: Run Gosec Security Scanner - name: Run Gosec Security Scanner
run: | # https://github.com/securego/gosec/issues/469 run: | # https://github.com/securego/gosec/issues/469
export PATH=$PATH:$(go env GOPATH)/bin export PATH=$PATH:$(go env GOPATH)/bin
@ -43,16 +43,16 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Go 1.18 - name: Set up Go 1.19
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: 1.19
id: go id: go
- name: Golangci-lint - name: Golangci-lint
uses: golangci/golangci-lint-action@v3 uses: golangci/golangci-lint-action@v3
with: with:
version: v1.47.2 version: v1.50.1
args: --config=.golangci.yml --out-${NO_FUTURE}format colored-line-number args: --config=.golangci.yml --out-${NO_FUTURE}format colored-line-number
build: build:
@ -62,7 +62,7 @@ jobs:
- name: Set up Go 1.x - name: Set up Go 1.x
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.18 go-version: 1.19
id: go id: go
- name: Check out code into the Go module directory - name: Check out code into the Go module directory

View File

@ -6,7 +6,7 @@ run:
- proto - proto
- tools/analyzers - tools/analyzers
timeout: 10m timeout: 10m
go: '1.18' go: '1.19'
linters: linters:
disable-all: true disable-all: true

View File

@ -176,7 +176,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe
go_rules_dependencies() go_rules_dependencies()
go_register_toolchains( go_register_toolchains(
go_version = "1.18.5", go_version = "1.19.3",
nogo = "@//:nogo", nogo = "@//:nogo",
) )

View File

@ -1,6 +1,5 @@
/* /*
Package beacon provides a client for interacting with the standard Eth Beacon Node API. Package beacon provides a client for interacting with the standard Eth Beacon Node API.
Interactive swagger documentation for the API is available here: https://ethereum.github.io/beacon-APIs/ Interactive swagger documentation for the API is available here: https://ethereum.github.io/beacon-APIs/
*/ */
package beacon package beacon

View File

@ -3,7 +3,9 @@ Copyright 2017 Albert Tedja
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

View File

@ -3,7 +3,9 @@ Copyright 2017 Albert Tedja
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

View File

@ -22,20 +22,21 @@ import (
// validateMergeBlock validates terminal block hash in the event of manual overrides before checking for total difficulty. // validateMergeBlock validates terminal block hash in the event of manual overrides before checking for total difficulty.
// //
// def validate_merge_block(block: BeaconBlock) -> None: // def validate_merge_block(block: BeaconBlock) -> None:
// if TERMINAL_BLOCK_HASH != Hash32():
// # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
// assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
// assert block.body.execution_payload.parent_hash == TERMINAL_BLOCK_HASH
// return
// //
// pow_block = get_pow_block(block.body.execution_payload.parent_hash) // if TERMINAL_BLOCK_HASH != Hash32():
// # Check if `pow_block` is available // # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
// assert pow_block is not None // assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
// pow_parent = get_pow_block(pow_block.parent_hash) // assert block.body.execution_payload.parent_hash == TERMINAL_BLOCK_HASH
// # Check if `pow_parent` is available // return
// assert pow_parent is not None //
// # Check if `pow_block` is a valid terminal PoW block // pow_block = get_pow_block(block.body.execution_payload.parent_hash)
// assert is_valid_terminal_pow_block(pow_block, pow_parent) // # Check if `pow_block` is available
// assert pow_block is not None
// pow_parent = get_pow_block(pow_block.parent_hash)
// # Check if `pow_parent` is available
// assert pow_parent is not None
// # Check if `pow_block` is a valid terminal PoW block
// assert is_valid_terminal_pow_block(pow_block, pow_parent)
func (s *Service) validateMergeBlock(ctx context.Context, b interfaces.SignedBeaconBlock) error { func (s *Service) validateMergeBlock(ctx context.Context, b interfaces.SignedBeaconBlock) error {
if err := blocks.BeaconBlockIsNil(b); err != nil { if err := blocks.BeaconBlockIsNil(b); err != nil {
return err return err
@ -105,10 +106,11 @@ func (s *Service) getBlkParentHashAndTD(ctx context.Context, blkHash []byte) ([]
// validateTerminalBlockHash validates if the merge block is a valid terminal PoW block. // validateTerminalBlockHash validates if the merge block is a valid terminal PoW block.
// spec code: // spec code:
// if TERMINAL_BLOCK_HASH != Hash32(): // if TERMINAL_BLOCK_HASH != Hash32():
// # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached. //
// assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH // # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
// assert block.body.execution_payload.parent_hash == TERMINAL_BLOCK_HASH // assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
// return // assert block.body.execution_payload.parent_hash == TERMINAL_BLOCK_HASH
// return
func validateTerminalBlockHash(blkSlot types.Slot, payload interfaces.ExecutionData) error { func validateTerminalBlockHash(blkSlot types.Slot, payload interfaces.ExecutionData) error {
if bytesutil.ToBytes32(params.BeaconConfig().TerminalBlockHash.Bytes()) == [32]byte{} { if bytesutil.ToBytes32(params.BeaconConfig().TerminalBlockHash.Bytes()) == [32]byte{} {
return nil return nil
@ -125,9 +127,10 @@ func validateTerminalBlockHash(blkSlot types.Slot, payload interfaces.ExecutionD
// validateTerminalBlockDifficulties validates terminal pow block by comparing own total difficulty with parent's total difficulty. // validateTerminalBlockDifficulties validates terminal pow block by comparing own total difficulty with parent's total difficulty.
// //
// def is_valid_terminal_pow_block(block: PowBlock, parent: PowBlock) -> bool: // def is_valid_terminal_pow_block(block: PowBlock, parent: PowBlock) -> bool:
// is_total_difficulty_reached = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY //
// is_parent_total_difficulty_valid = parent.total_difficulty < TERMINAL_TOTAL_DIFFICULTY // is_total_difficulty_reached = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
// return is_total_difficulty_reached and is_parent_total_difficulty_valid // is_parent_total_difficulty_valid = parent.total_difficulty < TERMINAL_TOTAL_DIFFICULTY
// return is_total_difficulty_reached and is_parent_total_difficulty_valid
func validateTerminalBlockDifficulties(currentDifficulty *uint256.Int, parentDifficulty *uint256.Int) (bool, error) { func validateTerminalBlockDifficulties(currentDifficulty *uint256.Int, parentDifficulty *uint256.Int) (bool, error) {
b, ok := new(big.Int).SetString(params.BeaconConfig().TerminalTotalDifficulty, 10) b, ok := new(big.Int).SetString(params.BeaconConfig().TerminalTotalDifficulty, 10)
if !ok { if !ok {

View File

@ -19,23 +19,24 @@ import (
// The delay is handled by the caller in `processAttestations`. // The delay is handled by the caller in `processAttestations`.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def on_attestation(store: Store, attestation: Attestation) -> None:
// """
// Run ``on_attestation`` upon receiving a new ``attestation`` from either within a block or directly on the wire.
// //
// An ``attestation`` that is asserted as invalid may be valid at a later time, // def on_attestation(store: Store, attestation: Attestation) -> None:
// consider scheduling it for later processing in such case. // """
// """ // Run ``on_attestation`` upon receiving a new ``attestation`` from either within a block or directly on the wire.
// validate_on_attestation(store, attestation)
// store_target_checkpoint_state(store, attestation.data.target)
// //
// # Get state at the `target` to fully validate attestation // An ``attestation`` that is asserted as invalid may be valid at a later time,
// target_state = store.checkpoint_states[attestation.data.target] // consider scheduling it for later processing in such case.
// indexed_attestation = get_indexed_attestation(target_state, attestation) // """
// assert is_valid_indexed_attestation(target_state, indexed_attestation) // validate_on_attestation(store, attestation)
// store_target_checkpoint_state(store, attestation.data.target)
// //
// # Update latest messages for attesting indices // # Get state at the `target` to fully validate attestation
// update_latest_messages(store, indexed_attestation.attesting_indices, attestation) // target_state = store.checkpoint_states[attestation.data.target]
// indexed_attestation = get_indexed_attestation(target_state, attestation)
// assert is_valid_indexed_attestation(target_state, indexed_attestation)
//
// # Update latest messages for attesting indices
// update_latest_messages(store, indexed_attestation.attesting_indices, attestation)
func (s *Service) OnAttestation(ctx context.Context, a *ethpb.Attestation) error { func (s *Service) OnAttestation(ctx context.Context, a *ethpb.Attestation) error {
ctx, span := trace.StartSpan(ctx, "blockChain.onAttestation") ctx, span := trace.StartSpan(ctx, "blockChain.onAttestation")
defer span.End() defer span.End()

View File

@ -45,52 +45,53 @@ var initialSyncBlockCacheSize = uint64(2 * params.BeaconConfig().SlotsPerEpoch)
// computation in this method and methods it calls into. // computation in this method and methods it calls into.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
// block = signed_block.message
// # Parent block must be known
// assert block.parent_root in store.block_states
// # Make a copy of the state to avoid mutability issues
// pre_state = copy(store.block_states[block.parent_root])
// # Blocks cannot be in the future. If they are, their consideration must be delayed until the are in the past.
// assert get_current_slot(store) >= block.slot
// //
// # Check that block is later than the finalized epoch slot (optimization to reduce calls to get_ancestor) // def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
// finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch) // block = signed_block.message
// assert block.slot > finalized_slot // # Parent block must be known
// # Check block is a descendant of the finalized block at the checkpoint finalized slot // assert block.parent_root in store.block_states
// assert get_ancestor(store, block.parent_root, finalized_slot) == store.finalized_checkpoint.root // # Make a copy of the state to avoid mutability issues
// pre_state = copy(store.block_states[block.parent_root])
// # Blocks cannot be in the future. If they are, their consideration must be delayed until the are in the past.
// assert get_current_slot(store) >= block.slot
// //
// # Check the block is valid and compute the post-state // # Check that block is later than the finalized epoch slot (optimization to reduce calls to get_ancestor)
// state = pre_state.copy() // finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)
// state_transition(state, signed_block, True) // assert block.slot > finalized_slot
// # Add new block to the store // # Check block is a descendant of the finalized block at the checkpoint finalized slot
// store.blocks[hash_tree_root(block)] = block // assert get_ancestor(store, block.parent_root, finalized_slot) == store.finalized_checkpoint.root
// # Add new state for this block to the store
// store.block_states[hash_tree_root(block)] = state
// //
// # Update justified checkpoint // # Check the block is valid and compute the post-state
// if state.current_justified_checkpoint.epoch > store.justified_checkpoint.epoch: // state = pre_state.copy()
// if state.current_justified_checkpoint.epoch > store.best_justified_checkpoint.epoch: // state_transition(state, signed_block, True)
// store.best_justified_checkpoint = state.current_justified_checkpoint // # Add new block to the store
// if should_update_justified_checkpoint(store, state.current_justified_checkpoint): // store.blocks[hash_tree_root(block)] = block
// store.justified_checkpoint = state.current_justified_checkpoint // # Add new state for this block to the store
// store.block_states[hash_tree_root(block)] = state
// //
// # Update finalized checkpoint // # Update justified checkpoint
// if state.finalized_checkpoint.epoch > store.finalized_checkpoint.epoch: // if state.current_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
// store.finalized_checkpoint = state.finalized_checkpoint // if state.current_justified_checkpoint.epoch > store.best_justified_checkpoint.epoch:
// store.best_justified_checkpoint = state.current_justified_checkpoint
// if should_update_justified_checkpoint(store, state.current_justified_checkpoint):
// store.justified_checkpoint = state.current_justified_checkpoint
// //
// # Potentially update justified if different from store // # Update finalized checkpoint
// if store.justified_checkpoint != state.current_justified_checkpoint: // if state.finalized_checkpoint.epoch > store.finalized_checkpoint.epoch:
// # Update justified if new justified is later than store justified // store.finalized_checkpoint = state.finalized_checkpoint
// if state.current_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
// store.justified_checkpoint = state.current_justified_checkpoint
// return
// //
// # Update justified if store justified is not in chain with finalized checkpoint // # Potentially update justified if different from store
// finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch) // if store.justified_checkpoint != state.current_justified_checkpoint:
// ancestor_at_finalized_slot = get_ancestor(store, store.justified_checkpoint.root, finalized_slot) // # Update justified if new justified is later than store justified
// if ancestor_at_finalized_slot != store.finalized_checkpoint.root: // if state.current_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
// store.justified_checkpoint = state.current_justified_checkpoint // store.justified_checkpoint = state.current_justified_checkpoint
// return
//
// # Update justified if store justified is not in chain with finalized checkpoint
// finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)
// ancestor_at_finalized_slot = get_ancestor(store, store.justified_checkpoint.root, finalized_slot)
// if ancestor_at_finalized_slot != store.finalized_checkpoint.root:
// store.justified_checkpoint = state.current_justified_checkpoint
func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlock, blockRoot [32]byte) error { func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlock, blockRoot [32]byte) error {
ctx, span := trace.StartSpan(ctx, "blockChain.onBlock") ctx, span := trace.StartSpan(ctx, "blockChain.onBlock")
defer span.End() defer span.End()

View File

@ -185,15 +185,16 @@ func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) err
// ancestor returns the block root of an ancestry block from the input block root. // ancestor returns the block root of an ancestry block from the input block root.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_ancestor(store: Store, root: Root, slot: Slot) -> Root: //
// block = store.blocks[root] // def get_ancestor(store: Store, root: Root, slot: Slot) -> Root:
// if block.slot > slot: // block = store.blocks[root]
// return get_ancestor(store, block.parent_root, slot) // if block.slot > slot:
// elif block.slot == slot: // return get_ancestor(store, block.parent_root, slot)
// return root // elif block.slot == slot:
// else: // return root
// # root is older than queried slot, thus a skip slot. Return most recent root prior to slot // else:
// return root // # root is older than queried slot, thus a skip slot. Return most recent root prior to slot
// return root
func (s *Service) ancestor(ctx context.Context, root []byte, slot types.Slot) ([]byte, error) { func (s *Service) ancestor(ctx context.Context, root []byte, slot types.Slot) ([]byte, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.ancestor") ctx, span := trace.StartSpan(ctx, "blockChain.ancestor")
defer span.End() defer span.End()

View File

@ -446,9 +446,12 @@ func TestFillForkChoiceMissingBlocks_FinalizedSibling(t *testing.T) {
} }
// blockTree1 constructs the following tree: // blockTree1 constructs the following tree:
// /- B1 //
// /- B1
//
// B0 /- B5 - B7 // B0 /- B5 - B7
// \- B3 - B4 - B6 - B8 //
// \- B3 - B4 - B6 - B8
func blockTree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][]byte, error) { func blockTree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][]byte, error) {
genesisRoot = bytesutil.PadTo(genesisRoot, 32) genesisRoot = bytesutil.PadTo(genesisRoot, 32)
b0 := util.NewBeaconBlock() b0 := util.NewBeaconBlock()

View File

@ -32,9 +32,9 @@ type SlashingReceiver interface {
// ReceiveBlock is a function that defines the operations (minus pubsub) // ReceiveBlock is a function that defines the operations (minus pubsub)
// that are performed on a received block. The operations consist of: // that are performed on a received block. The operations consist of:
// 1. Validate block, apply state transition and update checkpoints // 1. Validate block, apply state transition and update checkpoints
// 2. Apply fork choice to the processed block // 2. Apply fork choice to the processed block
// 3. Save latest head info // 3. Save latest head info
func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.SignedBeaconBlock, blockRoot [32]byte) error { func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.SignedBeaconBlock, blockRoot [32]byte) error {
ctx, span := trace.StartSpan(ctx, "blockChain.ReceiveBlock") ctx, span := trace.StartSpan(ctx, "blockChain.ReceiveBlock")
defer span.End() defer span.End()

View File

@ -82,23 +82,24 @@ func ProcessAttestationNoVerifySignature(
// the proposer in state. // the proposer in state.
// //
// Spec code: // Spec code:
// # Update epoch participation flags
// if data.target.epoch == get_current_epoch(state):
// epoch_participation = state.current_epoch_participation
// else:
// epoch_participation = state.previous_epoch_participation
// //
// proposer_reward_numerator = 0 // # Update epoch participation flags
// for index in get_attesting_indices(state, data, attestation.aggregation_bits): // if data.target.epoch == get_current_epoch(state):
// for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS): // epoch_participation = state.current_epoch_participation
// if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index): // else:
// epoch_participation[index] = add_flag(epoch_participation[index], flag_index) // epoch_participation = state.previous_epoch_participation
// proposer_reward_numerator += get_base_reward(state, index) * weight
// //
// # Reward proposer // proposer_reward_numerator = 0
// proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT // for index in get_attesting_indices(state, data, attestation.aggregation_bits):
// proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator) // for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS):
// increase_balance(state, get_beacon_proposer_index(state), proposer_reward) // if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index):
// epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
// proposer_reward_numerator += get_base_reward(state, index) * weight
//
// # Reward proposer
// proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT
// proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator)
// increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
func SetParticipationAndRewardProposer( func SetParticipationAndRewardProposer(
ctx context.Context, ctx context.Context,
beaconState state.BeaconState, beaconState state.BeaconState,
@ -157,12 +158,13 @@ func AddValidatorFlag(flag, flagPosition uint8) (uint8, error) {
// EpochParticipation sets and returns the proposer reward numerator and epoch participation. // EpochParticipation sets and returns the proposer reward numerator and epoch participation.
// //
// Spec code: // Spec code:
// proposer_reward_numerator = 0 //
// for index in get_attesting_indices(state, data, attestation.aggregation_bits): // proposer_reward_numerator = 0
// for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS): // for index in get_attesting_indices(state, data, attestation.aggregation_bits):
// if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index): // for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS):
// epoch_participation[index] = add_flag(epoch_participation[index], flag_index) // if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index):
// proposer_reward_numerator += get_base_reward(state, index) * weight // epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
// proposer_reward_numerator += get_base_reward(state, index) * weight
func EpochParticipation(beaconState state.BeaconState, indices []uint64, epochParticipation []byte, participatedFlags map[uint8]bool, totalBalance uint64) (uint64, []byte, error) { func EpochParticipation(beaconState state.BeaconState, indices []uint64, epochParticipation []byte, participatedFlags map[uint8]bool, totalBalance uint64) (uint64, []byte, error) {
cfg := params.BeaconConfig() cfg := params.BeaconConfig()
sourceFlagIndex := cfg.TimelySourceFlagIndex sourceFlagIndex := cfg.TimelySourceFlagIndex
@ -218,9 +220,10 @@ func EpochParticipation(beaconState state.BeaconState, indices []uint64, epochPa
// RewardProposer rewards proposer by increasing proposer's balance with input reward numerator and calculated reward denominator. // RewardProposer rewards proposer by increasing proposer's balance with input reward numerator and calculated reward denominator.
// //
// Spec code: // Spec code:
// proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT //
// proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator) // proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT
// increase_balance(state, get_beacon_proposer_index(state), proposer_reward) // proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator)
// increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
func RewardProposer(ctx context.Context, beaconState state.BeaconState, proposerRewardNumerator uint64) error { func RewardProposer(ctx context.Context, beaconState state.BeaconState, proposerRewardNumerator uint64) error {
cfg := params.BeaconConfig() cfg := params.BeaconConfig()
d := (cfg.WeightDenominator - cfg.ProposerWeight) * cfg.WeightDenominator / cfg.ProposerWeight d := (cfg.WeightDenominator - cfg.ProposerWeight) * cfg.WeightDenominator / cfg.ProposerWeight
@ -238,31 +241,32 @@ func RewardProposer(ctx context.Context, beaconState state.BeaconState, proposer
// //
// Spec code: // Spec code:
// def get_attestation_participation_flag_indices(state: BeaconState, // def get_attestation_participation_flag_indices(state: BeaconState,
// data: AttestationData,
// inclusion_delay: uint64) -> Sequence[int]:
// """
// Return the flag indices that are satisfied by an attestation.
// """
// if data.target.epoch == get_current_epoch(state):
// justified_checkpoint = state.current_justified_checkpoint
// else:
// justified_checkpoint = state.previous_justified_checkpoint
// //
// # Matching roots // data: AttestationData,
// is_matching_source = data.source == justified_checkpoint // inclusion_delay: uint64) -> Sequence[int]:
// 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) // Return the flag indices that are satisfied by an attestation.
// assert is_matching_source // """
// if data.target.epoch == get_current_epoch(state):
// justified_checkpoint = state.current_justified_checkpoint
// else:
// justified_checkpoint = state.previous_justified_checkpoint
// //
// participation_flag_indices = [] // # Matching roots
// if is_matching_source and inclusion_delay <= integer_squareroot(SLOTS_PER_EPOCH): // is_matching_source = data.source == justified_checkpoint
// participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX) // is_matching_target = is_matching_source and data.target.root == get_block_root(state, data.target.epoch)
// if is_matching_target and inclusion_delay <= SLOTS_PER_EPOCH: // is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot(state, data.slot)
// participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX) // assert is_matching_source
// if is_matching_head and inclusion_delay == MIN_ATTESTATION_INCLUSION_DELAY:
// participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX)
// //
// return participation_flag_indices // participation_flag_indices = []
// if is_matching_source and inclusion_delay <= integer_squareroot(SLOTS_PER_EPOCH):
// participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX)
// if is_matching_target and inclusion_delay <= SLOTS_PER_EPOCH:
// participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX)
// if is_matching_head and inclusion_delay == MIN_ATTESTATION_INCLUSION_DELAY:
// participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX)
//
// return participation_flag_indices
func AttestationParticipationFlagIndices(beaconState state.BeaconState, data *ethpb.AttestationData, delay types.Slot) (map[uint8]bool, error) { func AttestationParticipationFlagIndices(beaconState state.BeaconState, data *ethpb.AttestationData, delay types.Slot) (map[uint8]bool, error) {
currEpoch := time.CurrentEpoch(beaconState) currEpoch := time.CurrentEpoch(beaconState)
var justifiedCheckpt *ethpb.Checkpoint var justifiedCheckpt *ethpb.Checkpoint
@ -304,9 +308,10 @@ func AttestationParticipationFlagIndices(beaconState state.BeaconState, data *et
// MatchingStatus returns the matching statues for attestation data's source target and head. // MatchingStatus returns the matching statues for attestation data's source target and head.
// //
// Spec code: // Spec code:
// 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_source = data.source == justified_checkpoint
// is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot(state, data.slot) // 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)
func MatchingStatus(beaconState state.BeaconState, data *ethpb.AttestationData, cp *ethpb.Checkpoint) (matchedSrc, matchedTgt, matchedHead bool, err error) { func MatchingStatus(beaconState state.BeaconState, data *ethpb.AttestationData, cp *ethpb.Checkpoint) (matchedSrc, matchedTgt, matchedHead bool, err error) {
matchedSrc = attestation.CheckPointIsEqual(data.Source, cp) matchedSrc = attestation.CheckPointIsEqual(data.Source, cp)

View File

@ -20,30 +20,31 @@ import (
// //
// Spec code: // Spec code:
// def process_sync_aggregate(state: BeaconState, sync_aggregate: SyncAggregate) -> None: // def process_sync_aggregate(state: BeaconState, sync_aggregate: SyncAggregate) -> None:
// # Verify sync committee aggregate signature signing over the previous slot block root
// committee_pubkeys = state.current_sync_committee.pubkeys
// participant_pubkeys = [pubkey for pubkey, bit in zip(committee_pubkeys, sync_aggregate.sync_committee_bits) if bit]
// previous_slot = max(state.slot, Slot(1)) - Slot(1)
// domain = get_domain(state, DOMAIN_SYNC_COMMITTEE, compute_epoch_at_slot(previous_slot))
// signing_root = compute_signing_root(get_block_root_at_slot(state, previous_slot), domain)
// assert eth2_fast_aggregate_verify(participant_pubkeys, signing_root, sync_aggregate.sync_committee_signature)
// //
// # Compute participant and proposer rewards // # Verify sync committee aggregate signature signing over the previous slot block root
// total_active_increments = get_total_active_balance(state) // EFFECTIVE_BALANCE_INCREMENT // committee_pubkeys = state.current_sync_committee.pubkeys
// total_base_rewards = Gwei(get_base_reward_per_increment(state) * total_active_increments) // participant_pubkeys = [pubkey for pubkey, bit in zip(committee_pubkeys, sync_aggregate.sync_committee_bits) if bit]
// max_participant_rewards = Gwei(total_base_rewards * SYNC_REWARD_WEIGHT // WEIGHT_DENOMINATOR // SLOTS_PER_EPOCH) // previous_slot = max(state.slot, Slot(1)) - Slot(1)
// participant_reward = Gwei(max_participant_rewards // SYNC_COMMITTEE_SIZE) // domain = get_domain(state, DOMAIN_SYNC_COMMITTEE, compute_epoch_at_slot(previous_slot))
// proposer_reward = Gwei(participant_reward * PROPOSER_WEIGHT // (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT)) // signing_root = compute_signing_root(get_block_root_at_slot(state, previous_slot), domain)
// assert eth2_fast_aggregate_verify(participant_pubkeys, signing_root, sync_aggregate.sync_committee_signature)
// //
// # Apply participant and proposer rewards // # Compute participant and proposer rewards
// all_pubkeys = [v.pubkey for v in state.validators] // total_active_increments = get_total_active_balance(state) // EFFECTIVE_BALANCE_INCREMENT
// committee_indices = [ValidatorIndex(all_pubkeys.index(pubkey)) for pubkey in state.current_sync_committee.pubkeys] // total_base_rewards = Gwei(get_base_reward_per_increment(state) * total_active_increments)
// for participant_index, participation_bit in zip(committee_indices, sync_aggregate.sync_committee_bits): // max_participant_rewards = Gwei(total_base_rewards * SYNC_REWARD_WEIGHT // WEIGHT_DENOMINATOR // SLOTS_PER_EPOCH)
// if participation_bit: // participant_reward = Gwei(max_participant_rewards // SYNC_COMMITTEE_SIZE)
// increase_balance(state, participant_index, participant_reward) // proposer_reward = Gwei(participant_reward * PROPOSER_WEIGHT // (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT))
// increase_balance(state, get_beacon_proposer_index(state), proposer_reward) //
// else: // # Apply participant and proposer rewards
// decrease_balance(state, participant_index, participant_reward) // all_pubkeys = [v.pubkey for v in state.validators]
// committee_indices = [ValidatorIndex(all_pubkeys.index(pubkey)) for pubkey in state.current_sync_committee.pubkeys]
// for participant_index, participation_bit in zip(committee_indices, sync_aggregate.sync_committee_bits):
// if participation_bit:
// increase_balance(state, participant_index, participant_reward)
// increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
// else:
// decrease_balance(state, participant_index, participant_reward)
func ProcessSyncAggregate(ctx context.Context, s state.BeaconState, sync *ethpb.SyncAggregate) (state.BeaconState, error) { func ProcessSyncAggregate(ctx context.Context, s state.BeaconState, sync *ethpb.SyncAggregate) (state.BeaconState, error) {
votedKeys, votedIndices, didntVoteIndices, err := FilterSyncCommitteeVotes(s, sync) votedKeys, votedIndices, didntVoteIndices, err := FilterSyncCommitteeVotes(s, sync)
if err != nil { if err != nil {

View File

@ -68,9 +68,10 @@ func InitializePrecomputeValidators(ctx context.Context, beaconState state.Beaco
// For fully inactive validators and perfect active validators, the effect is the same as before Altair. // For fully inactive validators and perfect active validators, the effect is the same as before Altair.
// For a validator is inactive and the chain fails to finalize, the inactivity score increases by a fixed number, the total loss after N epochs is proportional to N**2/2. // For a validator is inactive and the chain fails to finalize, the inactivity score increases by a fixed number, the total loss after N epochs is proportional to N**2/2.
// For imperfectly active validators. The inactivity score's behavior is specified by this function: // For imperfectly active validators. The inactivity score's behavior is specified by this function:
// If a validator fails to submit an attestation with the correct target, their inactivity score goes up by 4. //
// If they successfully submit an attestation with the correct source and target, their inactivity score drops by 1 // If a validator fails to submit an attestation with the correct target, their inactivity score goes up by 4.
// If the chain has recently finalized, each validator's score drops by 16. // If they successfully submit an attestation with the correct source and target, their inactivity score drops by 1
// If the chain has recently finalized, each validator's score drops by 16.
func ProcessInactivityScores( func ProcessInactivityScores(
ctx context.Context, ctx context.Context,
beaconState state.BeaconState, beaconState state.BeaconState,
@ -132,12 +133,13 @@ func ProcessInactivityScores(
// it also tracks and updates epoch attesting balances. // it also tracks and updates epoch attesting balances.
// Spec code: // Spec code:
// if epoch == get_current_epoch(state): // if epoch == get_current_epoch(state):
// epoch_participation = state.current_epoch_participation //
// else: // epoch_participation = state.current_epoch_participation
// epoch_participation = state.previous_epoch_participation // else:
// active_validator_indices = get_active_validator_indices(state, epoch) // epoch_participation = state.previous_epoch_participation
// participating_indices = [i for i in active_validator_indices if has_flag(epoch_participation[i], flag_index)] // active_validator_indices = get_active_validator_indices(state, epoch)
// return set(filter(lambda index: not state.validators[index].slashed, participating_indices)) // participating_indices = [i for i in active_validator_indices if has_flag(epoch_participation[i], flag_index)]
// return set(filter(lambda index: not state.validators[index].slashed, participating_indices))
func ProcessEpochParticipation( func ProcessEpochParticipation(
ctx context.Context, ctx context.Context,
beaconState state.BeaconState, beaconState state.BeaconState,

View File

@ -14,10 +14,11 @@ import (
// //
// Spec code: // Spec code:
// def process_sync_committee_updates(state: BeaconState) -> None: // def process_sync_committee_updates(state: BeaconState) -> None:
// next_epoch = get_current_epoch(state) + Epoch(1) //
// if next_epoch % EPOCHS_PER_SYNC_COMMITTEE_PERIOD == 0: // next_epoch = get_current_epoch(state) + Epoch(1)
// state.current_sync_committee = state.next_sync_committee // if next_epoch % EPOCHS_PER_SYNC_COMMITTEE_PERIOD == 0:
// state.next_sync_committee = get_next_sync_committee(state) // state.current_sync_committee = state.next_sync_committee
// state.next_sync_committee = get_next_sync_committee(state)
func ProcessSyncCommitteeUpdates(ctx context.Context, beaconState state.BeaconState) (state.BeaconState, error) { func ProcessSyncCommitteeUpdates(ctx context.Context, beaconState state.BeaconState) (state.BeaconState, error) {
nextEpoch := time.NextEpoch(beaconState) nextEpoch := time.NextEpoch(beaconState)
if nextEpoch%params.BeaconConfig().EpochsPerSyncCommitteePeriod == 0 { if nextEpoch%params.BeaconConfig().EpochsPerSyncCommitteePeriod == 0 {
@ -46,8 +47,9 @@ func ProcessSyncCommitteeUpdates(ctx context.Context, beaconState state.BeaconSt
// //
// Spec code: // Spec code:
// def process_participation_flag_updates(state: BeaconState) -> None: // def process_participation_flag_updates(state: BeaconState) -> None:
// state.previous_epoch_participation = state.current_epoch_participation //
// state.current_epoch_participation = [ParticipationFlags(0b0000_0000) for _ in range(len(state.validators))] // state.previous_epoch_participation = state.current_epoch_participation
// state.current_epoch_participation = [ParticipationFlags(0b0000_0000) for _ in range(len(state.validators))]
func ProcessParticipationFlagUpdates(beaconState state.BeaconState) (state.BeaconState, error) { func ProcessParticipationFlagUpdates(beaconState state.BeaconState) (state.BeaconState, error) {
c, err := beaconState.CurrentEpochParticipation() c, err := beaconState.CurrentEpochParticipation()
if err != nil { if err != nil {

View File

@ -13,16 +13,17 @@ import (
// individual validator's base reward. // individual validator's base reward.
// //
// Spec code: // Spec code:
// def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
// """
// Return the base reward for the validator defined by ``index`` with respect to the current ``state``.
// //
// Note: An optimally performing validator can earn one base reward per epoch over a long time horizon. // def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
// This takes into account both per-epoch (e.g. attestation) and intermittent duties (e.g. block proposal // """
// and sync committees). // Return the base reward for the validator defined by ``index`` with respect to the current ``state``.
// """ //
// increments = state.validators[index].effective_balance // EFFECTIVE_BALANCE_INCREMENT // Note: An optimally performing validator can earn one base reward per epoch over a long time horizon.
// return Gwei(increments * get_base_reward_per_increment(state)) // This takes into account both per-epoch (e.g. attestation) and intermittent duties (e.g. block proposal
// and sync committees).
// """
// increments = state.validators[index].effective_balance // EFFECTIVE_BALANCE_INCREMENT
// return Gwei(increments * get_base_reward_per_increment(state))
func BaseReward(s state.ReadOnlyBeaconState, index types.ValidatorIndex) (uint64, error) { func BaseReward(s state.ReadOnlyBeaconState, index types.ValidatorIndex) (uint64, error) {
totalBalance, err := helpers.TotalActiveBalance(s) totalBalance, err := helpers.TotalActiveBalance(s)
if err != nil { if err != nil {
@ -50,7 +51,8 @@ func BaseRewardWithTotalBalance(s state.ReadOnlyBeaconState, index types.Validat
// //
// Spec code: // Spec code:
// def get_base_reward_per_increment(state: BeaconState) -> Gwei: // def get_base_reward_per_increment(state: BeaconState) -> Gwei:
// return Gwei(EFFECTIVE_BALANCE_INCREMENT * BASE_REWARD_FACTOR // integer_squareroot(get_total_active_balance(state))) //
// return Gwei(EFFECTIVE_BALANCE_INCREMENT * BASE_REWARD_FACTOR // integer_squareroot(get_total_active_balance(state)))
func BaseRewardPerIncrement(activeBalance uint64) (uint64, error) { func BaseRewardPerIncrement(activeBalance uint64) (uint64, error) {
if activeBalance == 0 { if activeBalance == 0 {
return 0, errors.New("active balance can't be 0") return 0, errors.New("active balance can't be 0")

View File

@ -47,13 +47,14 @@ func ValidateNilSyncContribution(s *ethpb.SignedContributionAndProof) error {
// //
// Spec code: // Spec code:
// def get_next_sync_committee(state: BeaconState) -> SyncCommittee: // def get_next_sync_committee(state: BeaconState) -> SyncCommittee:
// """ //
// Return the next sync committee, with possible pubkey duplicates. // """
// """ // Return the next sync committee, with possible pubkey duplicates.
// indices = get_next_sync_committee_indices(state) // """
// pubkeys = [state.validators[index].pubkey for index in indices] // indices = get_next_sync_committee_indices(state)
// aggregate_pubkey = bls.AggregatePKs(pubkeys) // pubkeys = [state.validators[index].pubkey for index in indices]
// return SyncCommittee(pubkeys=pubkeys, aggregate_pubkey=aggregate_pubkey) // aggregate_pubkey = bls.AggregatePKs(pubkeys)
// return SyncCommittee(pubkeys=pubkeys, aggregate_pubkey=aggregate_pubkey)
func NextSyncCommittee(ctx context.Context, s state.BeaconState) (*ethpb.SyncCommittee, error) { func NextSyncCommittee(ctx context.Context, s state.BeaconState) (*ethpb.SyncCommittee, error) {
indices, err := NextSyncCommitteeIndices(ctx, s) indices, err := NextSyncCommitteeIndices(ctx, s)
if err != nil { if err != nil {
@ -78,26 +79,27 @@ func NextSyncCommittee(ctx context.Context, s state.BeaconState) (*ethpb.SyncCom
// //
// Spec code: // Spec code:
// def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorIndex]: // def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorIndex]:
// """
// Return the sync committee indices, with possible duplicates, for the next sync committee.
// """
// epoch = Epoch(get_current_epoch(state) + 1)
// //
// MAX_RANDOM_BYTE = 2**8 - 1 // """
// active_validator_indices = get_active_validator_indices(state, epoch) // Return the sync committee indices, with possible duplicates, for the next sync committee.
// active_validator_count = uint64(len(active_validator_indices)) // """
// seed = get_seed(state, epoch, DOMAIN_SYNC_COMMITTEE) // epoch = Epoch(get_current_epoch(state) + 1)
// i = 0 //
// sync_committee_indices: List[ValidatorIndex] = [] // MAX_RANDOM_BYTE = 2**8 - 1
// while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE: // active_validator_indices = get_active_validator_indices(state, epoch)
// shuffled_index = compute_shuffled_index(uint64(i % active_validator_count), active_validator_count, seed) // active_validator_count = uint64(len(active_validator_indices))
// candidate_index = active_validator_indices[shuffled_index] // seed = get_seed(state, epoch, DOMAIN_SYNC_COMMITTEE)
// random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32] // i = 0
// effective_balance = state.validators[candidate_index].effective_balance // sync_committee_indices: List[ValidatorIndex] = []
// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte: // while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE:
// sync_committee_indices.append(candidate_index) // shuffled_index = compute_shuffled_index(uint64(i % active_validator_count), active_validator_count, seed)
// i += 1 // candidate_index = active_validator_indices[shuffled_index]
// return sync_committee_indices // random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32]
// effective_balance = state.validators[candidate_index].effective_balance
// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte:
// sync_committee_indices.append(candidate_index)
// i += 1
// return sync_committee_indices
func NextSyncCommitteeIndices(ctx context.Context, s state.BeaconState) ([]types.ValidatorIndex, error) { func NextSyncCommitteeIndices(ctx context.Context, s state.BeaconState) ([]types.ValidatorIndex, error) {
epoch := coreTime.NextEpoch(s) epoch := coreTime.NextEpoch(s)
indices, err := helpers.ActiveValidatorIndices(ctx, s, epoch) indices, err := helpers.ActiveValidatorIndices(ctx, s, epoch)
@ -144,18 +146,19 @@ func NextSyncCommitteeIndices(ctx context.Context, s state.BeaconState) ([]types
// SyncSubCommitteePubkeys returns the pubkeys participating in a sync subcommittee. // SyncSubCommitteePubkeys returns the pubkeys participating in a sync subcommittee.
// //
// def get_sync_subcommittee_pubkeys(state: BeaconState, subcommittee_index: uint64) -> Sequence[BLSPubkey]: // def get_sync_subcommittee_pubkeys(state: BeaconState, subcommittee_index: uint64) -> Sequence[BLSPubkey]:
// # Committees assigned to `slot` sign for `slot - 1`
// # This creates the exceptional logic below when transitioning between sync committee periods
// next_slot_epoch = compute_epoch_at_slot(Slot(state.slot + 1))
// if compute_sync_committee_period(get_current_epoch(state)) == compute_sync_committee_period(next_slot_epoch):
// sync_committee = state.current_sync_committee
// else:
// sync_committee = state.next_sync_committee
// //
// # Return pubkeys for the subcommittee index // # Committees assigned to `slot` sign for `slot - 1`
// sync_subcommittee_size = SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT // # This creates the exceptional logic below when transitioning between sync committee periods
// i = subcommittee_index * sync_subcommittee_size // next_slot_epoch = compute_epoch_at_slot(Slot(state.slot + 1))
// return sync_committee.pubkeys[i:i + sync_subcommittee_size] // if compute_sync_committee_period(get_current_epoch(state)) == compute_sync_committee_period(next_slot_epoch):
// sync_committee = state.current_sync_committee
// else:
// sync_committee = state.next_sync_committee
//
// # Return pubkeys for the subcommittee index
// sync_subcommittee_size = SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT
// i = subcommittee_index * sync_subcommittee_size
// return sync_committee.pubkeys[i:i + sync_subcommittee_size]
func SyncSubCommitteePubkeys(syncCommittee *ethpb.SyncCommittee, subComIdx types.CommitteeIndex) ([][]byte, error) { func SyncSubCommitteePubkeys(syncCommittee *ethpb.SyncCommittee, subComIdx types.CommitteeIndex) ([][]byte, error) {
cfg := params.BeaconConfig() cfg := params.BeaconConfig()
subCommSize := cfg.SyncCommitteeSize / cfg.SyncCommitteeSubnetCount subCommSize := cfg.SyncCommitteeSize / cfg.SyncCommitteeSubnetCount
@ -172,8 +175,9 @@ func SyncSubCommitteePubkeys(syncCommittee *ethpb.SyncCommittee, subComIdx types
// aggregator. // aggregator.
// //
// def is_sync_committee_aggregator(signature: BLSSignature) -> bool: // def is_sync_committee_aggregator(signature: BLSSignature) -> bool:
// modulo = max(1, SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT // TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE) //
// return bytes_to_uint64(hash(signature)[0:8]) % modulo == 0 // modulo = max(1, SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT // TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE)
// return bytes_to_uint64(hash(signature)[0:8]) % modulo == 0
func IsSyncCommitteeAggregator(sig []byte) (bool, error) { func IsSyncCommitteeAggregator(sig []byte) (bool, error) {
if len(sig) != fieldparams.BLSSignatureLength { if len(sig) != fieldparams.BLSSignatureLength {
return false, errors.New("incorrect sig length") return false, errors.New("incorrect sig length")

View File

@ -15,18 +15,19 @@ import (
// //
// Spec code: // Spec code:
// def process_epoch(state: BeaconState) -> None: // def process_epoch(state: BeaconState) -> None:
// process_justification_and_finalization(state) # [Modified in Altair] //
// process_inactivity_updates(state) # [New in Altair] // process_justification_and_finalization(state) # [Modified in Altair]
// process_rewards_and_penalties(state) # [Modified in Altair] // process_inactivity_updates(state) # [New in Altair]
// process_registry_updates(state) // process_rewards_and_penalties(state) # [Modified in Altair]
// process_slashings(state) # [Modified in Altair] // process_registry_updates(state)
// process_eth1_data_reset(state) // process_slashings(state) # [Modified in Altair]
// process_effective_balance_updates(state) // process_eth1_data_reset(state)
// process_slashings_reset(state) // process_effective_balance_updates(state)
// process_randao_mixes_reset(state) // process_slashings_reset(state)
// process_historical_roots_update(state) // process_randao_mixes_reset(state)
// process_participation_flag_updates(state) # [New in Altair] // process_historical_roots_update(state)
// process_sync_committee_updates(state) # [New in Altair] // process_participation_flag_updates(state) # [New in Altair]
// process_sync_committee_updates(state) # [New in Altair]
func ProcessEpoch(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { func ProcessEpoch(ctx context.Context, state state.BeaconState) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "altair.ProcessEpoch") ctx, span := trace.StartSpan(ctx, "altair.ProcessEpoch")
defer span.End() defer span.End()

View File

@ -16,52 +16,53 @@ import (
// //
// Spec code: // Spec code:
// def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState: // def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState:
// epoch = phase0.get_current_epoch(pre)
// post = 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=ALTAIR_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=[ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators))],
// current_epoch_participation=[ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators))],
// # 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=[uint64(0) for _ in range(len(pre.validators))],
// )
// # Fill in previous epoch participation from the pre state's pending attestations
// translate_participation(post, pre.previous_epoch_attestations)
// //
// # Fill in sync committees // epoch = phase0.get_current_epoch(pre)
// # Note: A duplicate committee is assigned for the current and next committee at the fork boundary // post = BeaconState(
// post.current_sync_committee = get_next_sync_committee(post) // # Versioning
// post.next_sync_committee = get_next_sync_committee(post) // genesis_time=pre.genesis_time,
// return post // genesis_validators_root=pre.genesis_validators_root,
// slot=pre.slot,
// fork=Fork(
// previous_version=pre.fork.current_version,
// current_version=ALTAIR_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=[ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators))],
// current_epoch_participation=[ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators))],
// # 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=[uint64(0) for _ in range(len(pre.validators))],
// )
// # Fill in previous epoch participation from the pre state's pending attestations
// translate_participation(post, pre.previous_epoch_attestations)
//
// # Fill in sync committees
// # Note: A duplicate committee is assigned for the current and next committee at the fork boundary
// post.current_sync_committee = get_next_sync_committee(post)
// post.next_sync_committee = get_next_sync_committee(post)
// return post
func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.BeaconState, error) {
epoch := time.CurrentEpoch(state) epoch := time.CurrentEpoch(state)
@ -126,17 +127,18 @@ func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.Beacon
// //
// Spec code: // Spec code:
// def translate_participation(state: BeaconState, pending_attestations: Sequence[phase0.PendingAttestation]) -> None: // def translate_participation(state: BeaconState, pending_attestations: Sequence[phase0.PendingAttestation]) -> None:
// for attestation in pending_attestations:
// 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 // for attestation in pending_attestations:
// epoch_participation = state.previous_epoch_participation // data = attestation.data
// for index in get_attesting_indices(state, data, attestation.aggregation_bits): // inclusion_delay = attestation.inclusion_delay
// for flag_index in participation_flag_indices: // # Translate attestation inclusion info to flag indices
// epoch_participation[index] = add_flag(epoch_participation[index], flag_index) // participation_flag_indices = get_attestation_participation_flag_indices(state, data, inclusion_delay)
//
// # Apply flags to all attesting validators
// epoch_participation = state.previous_epoch_participation
// for index in get_attesting_indices(state, data, attestation.aggregation_bits):
// for flag_index in participation_flag_indices:
// epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
func TranslateParticipation(ctx context.Context, state state.BeaconState, atts []*ethpb.PendingAttestation) (state.BeaconState, error) { func TranslateParticipation(ctx context.Context, state state.BeaconState, atts []*ethpb.PendingAttestation) (state.BeaconState, error) {
epochParticipation, err := state.PreviousEpochParticipation() epochParticipation, err := state.PreviousEpochParticipation()
if err != nil { if err != nil {

View File

@ -185,19 +185,20 @@ func VerifyAttestationSignature(ctx context.Context, beaconState state.ReadOnlyB
// VerifyIndexedAttestation determines the validity of an indexed attestation. // VerifyIndexedAttestation determines the validity of an indexed attestation.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: IndexedAttestation) -> bool: //
// """ // def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: IndexedAttestation) -> bool:
// Check if ``indexed_attestation`` is not empty, has sorted and unique indices and has a valid aggregate signature. // """
// """ // Check if ``indexed_attestation`` is not empty, has sorted and unique indices and has a valid aggregate signature.
// # Verify indices are sorted and unique // """
// indices = indexed_attestation.attesting_indices // # Verify indices are sorted and unique
// if len(indices) == 0 or not indices == sorted(set(indices)): // indices = indexed_attestation.attesting_indices
// return False // if len(indices) == 0 or not indices == sorted(set(indices)):
// # Verify aggregate signature // return False
// pubkeys = [state.validators[i].pubkey for i in indices] // # Verify aggregate signature
// domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch) // pubkeys = [state.validators[i].pubkey for i in indices]
// signing_root = compute_signing_root(indexed_attestation.data, domain) // domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
// return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature) // signing_root = compute_signing_root(indexed_attestation.data, domain)
// return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature)
func VerifyIndexedAttestation(ctx context.Context, beaconState state.ReadOnlyBeaconState, indexedAtt *ethpb.IndexedAttestation) error { func VerifyIndexedAttestation(ctx context.Context, beaconState state.ReadOnlyBeaconState, indexedAtt *ethpb.IndexedAttestation) error {
ctx, span := trace.StartSpan(ctx, "core.VerifyIndexedAttestation") ctx, span := trace.StartSpan(ctx, "core.VerifyIndexedAttestation")
defer span.End() defer span.End()

View File

@ -71,8 +71,9 @@ func ActivateValidatorWithEffectiveBalance(beaconState state.BeaconState, deposi
// into the beacon chain. // into the beacon chain.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// For each deposit in block.body.deposits: //
// process_deposit(state, deposit) // For each deposit in block.body.deposits:
// process_deposit(state, deposit)
func ProcessDeposits( func ProcessDeposits(
ctx context.Context, ctx context.Context,
beaconState state.BeaconState, beaconState state.BeaconState,
@ -120,40 +121,41 @@ func BatchVerifyDepositsSignatures(ctx context.Context, deposits []*ethpb.Deposi
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_deposit(state: BeaconState, deposit: Deposit) -> None: // def process_deposit(state: BeaconState, deposit: Deposit) -> None:
// # Verify the Merkle branch
// assert is_valid_merkle_branch(
// leaf=hash_tree_root(deposit.data),
// branch=deposit.proof,
// depth=DEPOSIT_CONTRACT_TREE_DEPTH + 1, # Add 1 for the List length mix-in
// index=state.eth1_deposit_index,
// root=state.eth1_data.deposit_root,
// )
// //
// # Deposits must be processed in order // # Verify the Merkle branch
// state.eth1_deposit_index += 1 // assert is_valid_merkle_branch(
// leaf=hash_tree_root(deposit.data),
// branch=deposit.proof,
// depth=DEPOSIT_CONTRACT_TREE_DEPTH + 1, # Add 1 for the List length mix-in
// index=state.eth1_deposit_index,
// root=state.eth1_data.deposit_root,
// )
// //
// pubkey = deposit.data.pubkey // # Deposits must be processed in order
// amount = deposit.data.amount // state.eth1_deposit_index += 1
// validator_pubkeys = [v.pubkey for v in state.validators]
// if pubkey not in validator_pubkeys:
// # Verify the deposit signature (proof of possession) which is not checked by the deposit contract
// deposit_message = DepositMessage(
// pubkey=deposit.data.pubkey,
// withdrawal_credentials=deposit.data.withdrawal_credentials,
// amount=deposit.data.amount,
// )
// domain = compute_domain(DOMAIN_DEPOSIT) # Fork-agnostic domain since deposits are valid across forks
// signing_root = compute_signing_root(deposit_message, domain)
// if not bls.Verify(pubkey, signing_root, deposit.data.signature):
// return
// //
// # Add validator and balance entries // pubkey = deposit.data.pubkey
// state.validators.append(get_validator_from_deposit(state, deposit)) // amount = deposit.data.amount
// state.balances.append(amount) // validator_pubkeys = [v.pubkey for v in state.validators]
// else: // if pubkey not in validator_pubkeys:
// # Increase balance by deposit amount // # Verify the deposit signature (proof of possession) which is not checked by the deposit contract
// index = ValidatorIndex(validator_pubkeys.index(pubkey)) // deposit_message = DepositMessage(
// increase_balance(state, index, amount) // pubkey=deposit.data.pubkey,
// withdrawal_credentials=deposit.data.withdrawal_credentials,
// amount=deposit.data.amount,
// )
// domain = compute_domain(DOMAIN_DEPOSIT) # Fork-agnostic domain since deposits are valid across forks
// signing_root = compute_signing_root(deposit_message, domain)
// if not bls.Verify(pubkey, signing_root, deposit.data.signature):
// return
//
// # Add validator and balance entries
// state.validators.append(get_validator_from_deposit(state, deposit))
// state.balances.append(amount)
// else:
// # Increase balance by deposit amount
// index = ValidatorIndex(validator_pubkeys.index(pubkey))
// increase_balance(state, index, amount)
func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (state.BeaconState, bool, error) { func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (state.BeaconState, bool, error) {
var newValidator bool var newValidator bool
if err := verifyDeposit(beaconState, deposit); err != nil { if err := verifyDeposit(beaconState, deposit); err != nil {

View File

@ -15,10 +15,11 @@ import (
// into the beacon state. // into the beacon state.
// //
// Official spec definition: // Official spec definition:
// def process_eth1_data(state: BeaconState, body: BeaconBlockBody) -> None: //
// state.eth1_data_votes.append(body.eth1_data) // def process_eth1_data(state: BeaconState, body: BeaconBlockBody) -> None:
// if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH: // state.eth1_data_votes.append(body.eth1_data)
// state.eth1_data = body.eth1_data // if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH:
// state.eth1_data = body.eth1_data
func ProcessEth1DataInBlock(_ context.Context, beaconState state.BeaconState, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) { func ProcessEth1DataInBlock(_ context.Context, beaconState state.BeaconState, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {
if beaconState == nil || beaconState.IsNil() { if beaconState == nil || beaconState.IsNil() {
return nil, errors.New("nil state") return nil, errors.New("nil state")

View File

@ -27,23 +27,24 @@ var ValidatorCannotExitYetMsg = "validator has not been active long enough to ex
// should exit the state's validator registry. // should exit the state's validator registry.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None: //
// voluntary_exit = signed_voluntary_exit.message // def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None:
// validator = state.validators[voluntary_exit.validator_index] // voluntary_exit = signed_voluntary_exit.message
// # Verify the validator is active // validator = state.validators[voluntary_exit.validator_index]
// assert is_active_validator(validator, get_current_epoch(state)) // # Verify the validator is active
// # Verify exit has not been initiated // assert is_active_validator(validator, get_current_epoch(state))
// assert validator.exit_epoch == FAR_FUTURE_EPOCH // # Verify exit has not been initiated
// # Exits must specify an epoch when they become valid; they are not valid before then // assert validator.exit_epoch == FAR_FUTURE_EPOCH
// assert get_current_epoch(state) >= voluntary_exit.epoch // # Exits must specify an epoch when they become valid; they are not valid before then
// # Verify the validator has been active long enough // assert get_current_epoch(state) >= voluntary_exit.epoch
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD // # Verify the validator has been active long enough
// # Verify signature // assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch) // # Verify signature
// signing_root = compute_signing_root(voluntary_exit, domain) // domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
// assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature) // signing_root = compute_signing_root(voluntary_exit, domain)
// # Initiate exit // assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
// initiate_validator_exit(state, voluntary_exit.validator_index) // # Initiate exit
// initiate_validator_exit(state, voluntary_exit.validator_index)
func ProcessVoluntaryExits( func ProcessVoluntaryExits(
ctx context.Context, ctx context.Context,
beaconState state.BeaconState, beaconState state.BeaconState,
@ -71,23 +72,24 @@ func ProcessVoluntaryExits(
// VerifyExitAndSignature implements the spec defined validation for voluntary exits. // VerifyExitAndSignature implements the spec defined validation for voluntary exits.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None: //
// voluntary_exit = signed_voluntary_exit.message // def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None:
// validator = state.validators[voluntary_exit.validator_index] // voluntary_exit = signed_voluntary_exit.message
// # Verify the validator is active // validator = state.validators[voluntary_exit.validator_index]
// assert is_active_validator(validator, get_current_epoch(state)) // # Verify the validator is active
// # Verify exit has not been initiated // assert is_active_validator(validator, get_current_epoch(state))
// assert validator.exit_epoch == FAR_FUTURE_EPOCH // # Verify exit has not been initiated
// # Exits must specify an epoch when they become valid; they are not valid before then // assert validator.exit_epoch == FAR_FUTURE_EPOCH
// assert get_current_epoch(state) >= voluntary_exit.epoch // # Exits must specify an epoch when they become valid; they are not valid before then
// # Verify the validator has been active long enough // assert get_current_epoch(state) >= voluntary_exit.epoch
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD // # Verify the validator has been active long enough
// # Verify signature // assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch) // # Verify signature
// signing_root = compute_signing_root(voluntary_exit, domain) // domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
// assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature) // signing_root = compute_signing_root(voluntary_exit, domain)
// # Initiate exit // assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
// initiate_validator_exit(state, voluntary_exit.validator_index) // # Initiate exit
// initiate_validator_exit(state, voluntary_exit.validator_index)
func VerifyExitAndSignature( func VerifyExitAndSignature(
validator state.ReadOnlyValidator, validator state.ReadOnlyValidator,
currentSlot types.Slot, currentSlot types.Slot,
@ -117,23 +119,24 @@ func VerifyExitAndSignature(
// verifyExitConditions implements the spec defined validation for voluntary exits(excluding signatures). // verifyExitConditions implements the spec defined validation for voluntary exits(excluding signatures).
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None: //
// voluntary_exit = signed_voluntary_exit.message // def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None:
// validator = state.validators[voluntary_exit.validator_index] // voluntary_exit = signed_voluntary_exit.message
// # Verify the validator is active // validator = state.validators[voluntary_exit.validator_index]
// assert is_active_validator(validator, get_current_epoch(state)) // # Verify the validator is active
// # Verify exit has not been initiated // assert is_active_validator(validator, get_current_epoch(state))
// assert validator.exit_epoch == FAR_FUTURE_EPOCH // # Verify exit has not been initiated
// # Exits must specify an epoch when they become valid; they are not valid before then // assert validator.exit_epoch == FAR_FUTURE_EPOCH
// assert get_current_epoch(state) >= voluntary_exit.epoch // # Exits must specify an epoch when they become valid; they are not valid before then
// # Verify the validator has been active long enough // assert get_current_epoch(state) >= voluntary_exit.epoch
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD // # Verify the validator has been active long enough
// # Verify signature // assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch) // # Verify signature
// signing_root = compute_signing_root(voluntary_exit, domain) // domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
// assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature) // signing_root = compute_signing_root(voluntary_exit, domain)
// # Initiate exit // assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
// initiate_validator_exit(state, voluntary_exit.validator_index) // # Initiate exit
// initiate_validator_exit(state, voluntary_exit.validator_index)
func verifyExitConditions(validator state.ReadOnlyValidator, currentSlot types.Slot, exit *ethpb.VoluntaryExit) error { func verifyExitConditions(validator state.ReadOnlyValidator, currentSlot types.Slot, exit *ethpb.VoluntaryExit) error {
currentEpoch := slots.ToEpoch(currentSlot) currentEpoch := slots.ToEpoch(currentSlot)
// Verify the validator is active. // Verify the validator is active.

View File

@ -18,27 +18,27 @@ import (
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// //
// def process_block_header(state: BeaconState, block: BeaconBlock) -> None: // def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
// # Verify that the slots match // # Verify that the slots match
// assert block.slot == state.slot // assert block.slot == state.slot
// # Verify that the block is newer than latest block header // # Verify that the block is newer than latest block header
// assert block.slot > state.latest_block_header.slot // assert block.slot > state.latest_block_header.slot
// # Verify that proposer index is the correct index // # Verify that proposer index is the correct index
// assert block.proposer_index == get_beacon_proposer_index(state) // assert block.proposer_index == get_beacon_proposer_index(state)
// # Verify that the parent matches // # Verify that the parent matches
// assert block.parent_root == hash_tree_root(state.latest_block_header) // assert block.parent_root == hash_tree_root(state.latest_block_header)
// # Cache current block as the new latest block // # Cache current block as the new latest block
// state.latest_block_header = BeaconBlockHeader( // state.latest_block_header = BeaconBlockHeader(
// slot=block.slot, // slot=block.slot,
// proposer_index=block.proposer_index, // proposer_index=block.proposer_index,
// parent_root=block.parent_root, // parent_root=block.parent_root,
// state_root=Bytes32(), # Overwritten in the next process_slot call // state_root=Bytes32(), # Overwritten in the next process_slot call
// body_root=hash_tree_root(block.body), // body_root=hash_tree_root(block.body),
// ) // )
// //
// # Verify proposer is not slashed // # Verify proposer is not slashed
// proposer = state.validators[block.proposer_index] // proposer = state.validators[block.proposer_index]
// assert not proposer.slashed // assert not proposer.slashed
func ProcessBlockHeader( func ProcessBlockHeader(
ctx context.Context, ctx context.Context,
beaconState state.BeaconState, beaconState state.BeaconState,
@ -73,27 +73,28 @@ func ProcessBlockHeader(
// using a unsigned block. // using a unsigned block.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
// # Verify that the slots match
// assert block.slot == state.slot
// # Verify that the block is newer than latest block header
// assert block.slot > state.latest_block_header.slot
// # Verify that proposer index is the correct index
// assert block.proposer_index == get_beacon_proposer_index(state)
// # Verify that the parent matches
// assert block.parent_root == hash_tree_root(state.latest_block_header)
// # Cache current block as the new latest block
// state.latest_block_header = BeaconBlockHeader(
// slot=block.slot,
// proposer_index=block.proposer_index,
// parent_root=block.parent_root,
// state_root=Bytes32(), # Overwritten in the next process_slot call
// body_root=hash_tree_root(block.body),
// )
// //
// # Verify proposer is not slashed // def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
// proposer = state.validators[block.proposer_index] // # Verify that the slots match
// assert not proposer.slashed // assert block.slot == state.slot
// # Verify that the block is newer than latest block header
// assert block.slot > state.latest_block_header.slot
// # Verify that proposer index is the correct index
// assert block.proposer_index == get_beacon_proposer_index(state)
// # Verify that the parent matches
// assert block.parent_root == hash_tree_root(state.latest_block_header)
// # Cache current block as the new latest block
// state.latest_block_header = BeaconBlockHeader(
// slot=block.slot,
// proposer_index=block.proposer_index,
// parent_root=block.parent_root,
// state_root=Bytes32(), # Overwritten in the next process_slot call
// body_root=hash_tree_root(block.body),
// )
//
// # Verify proposer is not slashed
// proposer = state.validators[block.proposer_index]
// assert not proposer.slashed
func ProcessBlockHeaderNoVerify( func ProcessBlockHeaderNoVerify(
ctx context.Context, ctx context.Context,
beaconState state.BeaconState, beaconState state.BeaconState,

View File

@ -25,7 +25,8 @@ var (
// //
// Spec code: // Spec code:
// def is_merge_transition_complete(state: BeaconState) -> bool: // def is_merge_transition_complete(state: BeaconState) -> bool:
// return state.latest_execution_payload_header != ExecutionPayloadHeader() //
// return state.latest_execution_payload_header != ExecutionPayloadHeader()
func IsMergeTransitionComplete(st state.BeaconState) (bool, error) { func IsMergeTransitionComplete(st state.BeaconState) (bool, error) {
if st == nil { if st == nil {
return false, errors.New("nil state") return false, errors.New("nil state")
@ -51,7 +52,8 @@ func IsMergeTransitionComplete(st state.BeaconState) (bool, error) {
// //
// Spec code: // Spec code:
// def is_execution_block(block: BeaconBlock) -> bool: // def is_execution_block(block: BeaconBlock) -> bool:
// return block.body.execution_payload != ExecutionPayload() //
// return block.body.execution_payload != ExecutionPayload()
func IsExecutionBlock(body interfaces.BeaconBlockBody) (bool, error) { func IsExecutionBlock(body interfaces.BeaconBlockBody) (bool, error) {
if body == nil { if body == nil {
return false, errors.New("nil block body") return false, errors.New("nil block body")
@ -76,7 +78,8 @@ func IsExecutionBlock(body interfaces.BeaconBlockBody) (bool, error) {
// //
// Spec code: // Spec code:
// def is_execution_enabled(state: BeaconState, body: BeaconBlockBody) -> bool: // def is_execution_enabled(state: BeaconState, body: BeaconBlockBody) -> bool:
// return is_merge_block(state, body) or is_merge_complete(state) //
// return is_merge_block(state, body) or is_merge_complete(state)
func IsExecutionEnabled(st state.BeaconState, body interfaces.BeaconBlockBody) (bool, error) { func IsExecutionEnabled(st state.BeaconState, body interfaces.BeaconBlockBody) (bool, error) {
if st == nil || body == nil { if st == nil || body == nil {
return false, errors.New("nil state or block body") return false, errors.New("nil state or block body")
@ -116,9 +119,10 @@ func IsPreBellatrixVersion(v int) bool {
// These validation steps ONLY apply to post merge. // These validation steps ONLY apply to post merge.
// //
// Spec code: // Spec code:
// # Verify consistency of the parent hash with respect to the previous execution payload header //
// if is_merge_complete(state): // # Verify consistency of the parent hash with respect to the previous execution payload header
// assert payload.parent_hash == state.latest_execution_payload_header.block_hash // if is_merge_complete(state):
// assert payload.parent_hash == state.latest_execution_payload_header.block_hash
func ValidatePayloadWhenMergeCompletes(st state.BeaconState, payload interfaces.ExecutionData) error { func ValidatePayloadWhenMergeCompletes(st state.BeaconState, payload interfaces.ExecutionData) error {
complete, err := IsMergeTransitionComplete(st) complete, err := IsMergeTransitionComplete(st)
if err != nil { if err != nil {
@ -141,10 +145,11 @@ func ValidatePayloadWhenMergeCompletes(st state.BeaconState, payload interfaces.
// These validation steps apply to both pre merge and post merge. // These validation steps apply to both pre merge and post merge.
// //
// Spec code: // Spec code:
// # Verify random //
// assert payload.random == get_randao_mix(state, get_current_epoch(state)) // # Verify random
// # Verify timestamp // assert payload.random == get_randao_mix(state, get_current_epoch(state))
// assert payload.timestamp == compute_timestamp_at_slot(state, state.slot) // # Verify timestamp
// assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
func ValidatePayload(st state.BeaconState, payload interfaces.ExecutionData) error { func ValidatePayload(st state.BeaconState, payload interfaces.ExecutionData) error {
random, err := helpers.RandaoMix(st, time.CurrentEpoch(st)) random, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
if err != nil { if err != nil {
@ -170,32 +175,33 @@ func ValidatePayload(st state.BeaconState, payload interfaces.ExecutionData) err
// //
// Spec code: // Spec code:
// def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None: // def process_execution_payload(state: BeaconState, payload: ExecutionPayload, execution_engine: ExecutionEngine) -> None:
// # Verify consistency of the parent hash with respect to the previous execution payload header //
// if is_merge_complete(state): // # Verify consistency of the parent hash with respect to the previous execution payload header
// assert payload.parent_hash == state.latest_execution_payload_header.block_hash // if is_merge_complete(state):
// # Verify random // assert payload.parent_hash == state.latest_execution_payload_header.block_hash
// assert payload.random == get_randao_mix(state, get_current_epoch(state)) // # Verify random
// # Verify timestamp // assert payload.random == get_randao_mix(state, get_current_epoch(state))
// assert payload.timestamp == compute_timestamp_at_slot(state, state.slot) // # Verify timestamp
// # Verify the execution payload is valid // assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
// assert execution_engine.execute_payload(payload) // # Verify the execution payload is valid
// # Cache execution payload header // assert execution_engine.execute_payload(payload)
// state.latest_execution_payload_header = ExecutionPayloadHeader( // # Cache execution payload header
// parent_hash=payload.parent_hash, // state.latest_execution_payload_header = ExecutionPayloadHeader(
// FeeRecipient=payload.FeeRecipient, // parent_hash=payload.parent_hash,
// state_root=payload.state_root, // FeeRecipient=payload.FeeRecipient,
// receipt_root=payload.receipt_root, // state_root=payload.state_root,
// logs_bloom=payload.logs_bloom, // receipt_root=payload.receipt_root,
// random=payload.random, // logs_bloom=payload.logs_bloom,
// block_number=payload.block_number, // random=payload.random,
// gas_limit=payload.gas_limit, // block_number=payload.block_number,
// gas_used=payload.gas_used, // gas_limit=payload.gas_limit,
// timestamp=payload.timestamp, // gas_used=payload.gas_used,
// extra_data=payload.extra_data, // timestamp=payload.timestamp,
// base_fee_per_gas=payload.base_fee_per_gas, // extra_data=payload.extra_data,
// block_hash=payload.block_hash, // base_fee_per_gas=payload.base_fee_per_gas,
// transactions_root=hash_tree_root(payload.transactions), // block_hash=payload.block_hash,
// ) // transactions_root=hash_tree_root(payload.transactions),
// )
func ProcessPayload(st state.BeaconState, payload interfaces.ExecutionData) (state.BeaconState, error) { func ProcessPayload(st state.BeaconState, payload interfaces.ExecutionData) (state.BeaconState, error) {
if st.Version() >= version.Capella { if st.Version() >= version.Capella {
withdrawals, err := payload.Withdrawals() withdrawals, err := payload.Withdrawals()

View File

@ -17,15 +17,16 @@ import (
// in the beacon state's latest randao mixes slice. // in the beacon state's latest randao mixes slice.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_randao(state: BeaconState, body: BeaconBlockBody) -> None: //
// epoch = get_current_epoch(state) // def process_randao(state: BeaconState, body: BeaconBlockBody) -> None:
// # Verify RANDAO reveal // epoch = get_current_epoch(state)
// proposer = state.validators[get_beacon_proposer_index(state)] // # Verify RANDAO reveal
// signing_root = compute_signing_root(epoch, get_domain(state, DOMAIN_RANDAO)) // proposer = state.validators[get_beacon_proposer_index(state)]
// assert bls.Verify(proposer.pubkey, signing_root, body.randao_reveal) // signing_root = compute_signing_root(epoch, get_domain(state, DOMAIN_RANDAO))
// # Mix in RANDAO reveal // assert bls.Verify(proposer.pubkey, signing_root, body.randao_reveal)
// mix = xor(get_randao_mix(state, epoch), hash(body.randao_reveal)) // # Mix in RANDAO reveal
// state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix // mix = xor(get_randao_mix(state, epoch), hash(body.randao_reveal))
// state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix
func ProcessRandao( func ProcessRandao(
ctx context.Context, ctx context.Context,
beaconState state.BeaconState, beaconState state.BeaconState,
@ -56,11 +57,12 @@ func ProcessRandao(
// in the beacon state's latest randao mixes slice. // in the beacon state's latest randao mixes slice.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// # Mix it in //
// state.latest_randao_mixes[get_current_epoch(state) % LATEST_RANDAO_MIXES_LENGTH] = ( // # Mix it in
// xor(get_randao_mix(state, get_current_epoch(state)), // state.latest_randao_mixes[get_current_epoch(state) % LATEST_RANDAO_MIXES_LENGTH] = (
// hash(body.randao_reveal)) // xor(get_randao_mix(state, get_current_epoch(state)),
// ) // hash(body.randao_reveal))
// )
func ProcessRandaoNoVerify( func ProcessRandaoNoVerify(
beaconState state.BeaconState, beaconState state.BeaconState,
randaoReveal []byte, randaoReveal []byte,

View File

@ -23,22 +23,22 @@ const executionToBLSPadding = 12
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// //
//def process_bls_to_execution_change(state: BeaconState, signed_address_change: SignedBLSToExecutionChange) -> None: // def process_bls_to_execution_change(state: BeaconState, signed_address_change: SignedBLSToExecutionChange) -> None:
// validator = state.validators[address_change.validator_index]
// //
// assert validator.withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX // validator = state.validators[address_change.validator_index]
// assert validator.withdrawal_credentials[1:] == hash(address_change.from_bls_pubkey)[1:]
// //
// domain = get_domain(state, DOMAIN_BLS_TO_EXECUTION_CHANGE) // assert validator.withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX
// signing_root = compute_signing_root(address_change, domain) // assert validator.withdrawal_credentials[1:] == hash(address_change.from_bls_pubkey)[1:]
// assert bls.Verify(address_change.from_bls_pubkey, signing_root, signed_address_change.signature)
// //
// validator.withdrawal_credentials = ( // domain = get_domain(state, DOMAIN_BLS_TO_EXECUTION_CHANGE)
// ETH1_ADDRESS_WITHDRAWAL_PREFIX // signing_root = compute_signing_root(address_change, domain)
// + b'\x00' * 11 // assert bls.Verify(address_change.from_bls_pubkey, signing_root, signed_address_change.signature)
// + address_change.to_execution_address
// )
// //
// validator.withdrawal_credentials = (
// ETH1_ADDRESS_WITHDRAWAL_PREFIX
// + b'\x00' * 11
// + address_change.to_execution_address
// )
func ProcessBLSToExecutionChange(st state.BeaconState, signed *ethpb.SignedBLSToExecutionChange) (state.BeaconState, error) { func ProcessBLSToExecutionChange(st state.BeaconState, signed *ethpb.SignedBLSToExecutionChange) (state.BeaconState, error) {
if signed == nil { if signed == nil {
return st, errNilSignedWithdrawalMessage return st, errNilSignedWithdrawalMessage

View File

@ -49,12 +49,13 @@ func (s sortableIndices) Less(i, j int) bool {
// need to get attesting balance from attestations. // need to get attesting balance from attestations.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_attesting_balance(state: BeaconState, attestations: Sequence[PendingAttestation]) -> Gwei: //
// """ // def get_attesting_balance(state: BeaconState, attestations: Sequence[PendingAttestation]) -> Gwei:
// Return the combined effective balance of the set of unslashed validators participating in ``attestations``. // """
// Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero. // Return the combined effective balance of the set of unslashed validators participating in ``attestations``.
// """ // Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
// return get_total_balance(state, get_unslashed_attesting_indices(state, attestations)) // """
// return get_total_balance(state, get_unslashed_attesting_indices(state, attestations))
func AttestingBalance(ctx context.Context, state state.ReadOnlyBeaconState, atts []*ethpb.PendingAttestation) (uint64, error) { func AttestingBalance(ctx context.Context, state state.ReadOnlyBeaconState, atts []*ethpb.PendingAttestation) (uint64, error) {
indices, err := UnslashedAttestingIndices(ctx, state, atts) indices, err := UnslashedAttestingIndices(ctx, state, atts)
if err != nil { if err != nil {
@ -67,25 +68,26 @@ func AttestingBalance(ctx context.Context, state state.ReadOnlyBeaconState, atts
// the amount to rotate is determined churn limit. // the amount to rotate is determined churn limit.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_registry_updates(state: BeaconState) -> None:
// # Process activation eligibility and ejections
// for index, validator in enumerate(state.validators):
// if is_eligible_for_activation_queue(validator):
// validator.activation_eligibility_epoch = get_current_epoch(state) + 1
// //
// if is_active_validator(validator, get_current_epoch(state)) and validator.effective_balance <= EJECTION_BALANCE: // def process_registry_updates(state: BeaconState) -> None:
// initiate_validator_exit(state, ValidatorIndex(index)) // # Process activation eligibility and ejections
// for index, validator in enumerate(state.validators):
// if is_eligible_for_activation_queue(validator):
// validator.activation_eligibility_epoch = get_current_epoch(state) + 1
// //
// # Queue validators eligible for activation and not yet dequeued for activation // if is_active_validator(validator, get_current_epoch(state)) and validator.effective_balance <= EJECTION_BALANCE:
// activation_queue = sorted([ // initiate_validator_exit(state, ValidatorIndex(index))
// index for index, validator in enumerate(state.validators) //
// if is_eligible_for_activation(state, validator) // # Queue validators eligible for activation and not yet dequeued for activation
// # Order by the sequence of activation_eligibility_epoch setting and then index // activation_queue = sorted([
// ], key=lambda index: (state.validators[index].activation_eligibility_epoch, index)) // index for index, validator in enumerate(state.validators)
// # Dequeued validators for activation up to churn limit // if is_eligible_for_activation(state, validator)
// for index in activation_queue[:get_validator_churn_limit(state)]: // # Order by the sequence of activation_eligibility_epoch setting and then index
// validator = state.validators[index] // ], key=lambda index: (state.validators[index].activation_eligibility_epoch, index))
// validator.activation_epoch = compute_activation_exit_epoch(get_current_epoch(state)) // # Dequeued validators for activation up to churn limit
// for index in activation_queue[:get_validator_churn_limit(state)]:
// validator = state.validators[index]
// validator.activation_epoch = compute_activation_exit_epoch(get_current_epoch(state))
func ProcessRegistryUpdates(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { func ProcessRegistryUpdates(ctx context.Context, state state.BeaconState) (state.BeaconState, error) {
currentEpoch := time.CurrentEpoch(state) currentEpoch := time.CurrentEpoch(state)
vals := state.Validators() vals := state.Validators()
@ -155,16 +157,16 @@ func ProcessRegistryUpdates(ctx context.Context, state state.BeaconState) (state
// ProcessSlashings processes the slashed validators during epoch processing, // ProcessSlashings processes the slashed validators during epoch processing,
// //
// def process_slashings(state: BeaconState) -> None: // def process_slashings(state: BeaconState) -> None:
// epoch = get_current_epoch(state) // epoch = get_current_epoch(state)
// total_balance = get_total_active_balance(state) // total_balance = get_total_active_balance(state)
// adjusted_total_slashing_balance = min(sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER, total_balance) // adjusted_total_slashing_balance = min(sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER, total_balance)
// for index, validator in enumerate(state.validators): // for index, validator in enumerate(state.validators):
// if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch: // if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch:
// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow // increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow
// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance // penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance
// penalty = penalty_numerator // total_balance * increment // penalty = penalty_numerator // total_balance * increment
// decrease_balance(state, ValidatorIndex(index), penalty) // decrease_balance(state, ValidatorIndex(index), penalty)
func ProcessSlashings(state state.BeaconState, slashingMultiplier uint64) (state.BeaconState, error) { func ProcessSlashings(state state.BeaconState, slashingMultiplier uint64) (state.BeaconState, error) {
currentEpoch := time.CurrentEpoch(state) currentEpoch := time.CurrentEpoch(state)
totalBalance, err := helpers.TotalActiveBalance(state) totalBalance, err := helpers.TotalActiveBalance(state)
@ -207,11 +209,12 @@ func ProcessSlashings(state state.BeaconState, slashingMultiplier uint64) (state
// ProcessEth1DataReset processes updates to ETH1 data votes during epoch processing. // ProcessEth1DataReset processes updates to ETH1 data votes during epoch processing.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_eth1_data_reset(state: BeaconState) -> None: //
// next_epoch = Epoch(get_current_epoch(state) + 1) // def process_eth1_data_reset(state: BeaconState) -> None:
// # Reset eth1 data votes // next_epoch = Epoch(get_current_epoch(state) + 1)
// if next_epoch % EPOCHS_PER_ETH1_VOTING_PERIOD == 0: // # Reset eth1 data votes
// state.eth1_data_votes = [] // if next_epoch % EPOCHS_PER_ETH1_VOTING_PERIOD == 0:
// state.eth1_data_votes = []
func ProcessEth1DataReset(state state.BeaconState) (state.BeaconState, error) { func ProcessEth1DataReset(state state.BeaconState) (state.BeaconState, error) {
currentEpoch := time.CurrentEpoch(state) currentEpoch := time.CurrentEpoch(state)
nextEpoch := currentEpoch + 1 nextEpoch := currentEpoch + 1
@ -229,18 +232,19 @@ func ProcessEth1DataReset(state state.BeaconState) (state.BeaconState, error) {
// ProcessEffectiveBalanceUpdates processes effective balance updates during epoch processing. // ProcessEffectiveBalanceUpdates processes effective balance updates during epoch processing.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_effective_balance_updates(state: BeaconState) -> None: //
// # Update effective balances with hysteresis // def process_effective_balance_updates(state: BeaconState) -> None:
// for index, validator in enumerate(state.validators): // # Update effective balances with hysteresis
// balance = state.balances[index] // for index, validator in enumerate(state.validators):
// HYSTERESIS_INCREMENT = uint64(EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT) // balance = state.balances[index]
// DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER // HYSTERESIS_INCREMENT = uint64(EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT)
// UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER // DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER
// if ( // UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER
// balance + DOWNWARD_THRESHOLD < validator.effective_balance // if (
// or validator.effective_balance + UPWARD_THRESHOLD < balance // balance + DOWNWARD_THRESHOLD < validator.effective_balance
// ): // or validator.effective_balance + UPWARD_THRESHOLD < balance
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) // ):
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
func ProcessEffectiveBalanceUpdates(state state.BeaconState) (state.BeaconState, error) { func ProcessEffectiveBalanceUpdates(state state.BeaconState) (state.BeaconState, error) {
effBalanceInc := params.BeaconConfig().EffectiveBalanceIncrement effBalanceInc := params.BeaconConfig().EffectiveBalanceIncrement
maxEffBalance := params.BeaconConfig().MaxEffectiveBalance maxEffBalance := params.BeaconConfig().MaxEffectiveBalance
@ -285,10 +289,11 @@ func ProcessEffectiveBalanceUpdates(state state.BeaconState) (state.BeaconState,
// ProcessSlashingsReset processes the total slashing balances updates during epoch processing. // ProcessSlashingsReset processes the total slashing balances updates during epoch processing.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_slashings_reset(state: BeaconState) -> None: //
// next_epoch = Epoch(get_current_epoch(state) + 1) // def process_slashings_reset(state: BeaconState) -> None:
// # Reset slashings // next_epoch = Epoch(get_current_epoch(state) + 1)
// state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0) // # Reset slashings
// state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0)
func ProcessSlashingsReset(state state.BeaconState) (state.BeaconState, error) { func ProcessSlashingsReset(state state.BeaconState) (state.BeaconState, error) {
currentEpoch := time.CurrentEpoch(state) currentEpoch := time.CurrentEpoch(state)
nextEpoch := currentEpoch + 1 nextEpoch := currentEpoch + 1
@ -314,11 +319,12 @@ func ProcessSlashingsReset(state state.BeaconState) (state.BeaconState, error) {
// ProcessRandaoMixesReset processes the final updates to RANDAO mix during epoch processing. // ProcessRandaoMixesReset processes the final updates to RANDAO mix during epoch processing.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_randao_mixes_reset(state: BeaconState) -> None: //
// current_epoch = get_current_epoch(state) // def process_randao_mixes_reset(state: BeaconState) -> None:
// next_epoch = Epoch(current_epoch + 1) // current_epoch = get_current_epoch(state)
// # Set randao mix // next_epoch = Epoch(current_epoch + 1)
// state.randao_mixes[next_epoch % EPOCHS_PER_HISTORICAL_VECTOR] = get_randao_mix(state, current_epoch) // # Set randao mix
// state.randao_mixes[next_epoch % EPOCHS_PER_HISTORICAL_VECTOR] = get_randao_mix(state, current_epoch)
func ProcessRandaoMixesReset(state state.BeaconState) (state.BeaconState, error) { func ProcessRandaoMixesReset(state state.BeaconState) (state.BeaconState, error) {
currentEpoch := time.CurrentEpoch(state) currentEpoch := time.CurrentEpoch(state)
nextEpoch := currentEpoch + 1 nextEpoch := currentEpoch + 1
@ -346,12 +352,13 @@ func ProcessRandaoMixesReset(state state.BeaconState) (state.BeaconState, error)
// ProcessHistoricalRootsUpdate processes the updates to historical root accumulator during epoch processing. // ProcessHistoricalRootsUpdate processes the updates to historical root accumulator during epoch processing.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_historical_roots_update(state: BeaconState) -> None: //
// # Set historical root accumulator // def process_historical_roots_update(state: BeaconState) -> None:
// next_epoch = Epoch(get_current_epoch(state) + 1) // # Set historical root accumulator
// if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0: // next_epoch = Epoch(get_current_epoch(state) + 1)
// historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots) // if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
// state.historical_roots.append(hash_tree_root(historical_batch)) // historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots)
// state.historical_roots.append(hash_tree_root(historical_batch))
func ProcessHistoricalRootsUpdate(state state.BeaconState) (state.BeaconState, error) { func ProcessHistoricalRootsUpdate(state state.BeaconState) (state.BeaconState, error) {
currentEpoch := time.CurrentEpoch(state) currentEpoch := time.CurrentEpoch(state)
nextEpoch := currentEpoch + 1 nextEpoch := currentEpoch + 1
@ -378,10 +385,11 @@ func ProcessHistoricalRootsUpdate(state state.BeaconState) (state.BeaconState, e
// ProcessParticipationRecordUpdates rotates current/previous epoch attestations during epoch processing. // ProcessParticipationRecordUpdates rotates current/previous epoch attestations during epoch processing.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_participation_record_updates(state: BeaconState) -> None: //
// # Rotate current/previous epoch attestations // def process_participation_record_updates(state: BeaconState) -> None:
// state.previous_epoch_attestations = state.current_epoch_attestations // # Rotate current/previous epoch attestations
// state.current_epoch_attestations = [] // state.previous_epoch_attestations = state.current_epoch_attestations
// state.current_epoch_attestations = []
func ProcessParticipationRecordUpdates(state state.BeaconState) (state.BeaconState, error) { func ProcessParticipationRecordUpdates(state state.BeaconState) (state.BeaconState, error) {
if err := state.RotateAttestations(); err != nil { if err := state.RotateAttestations(); err != nil {
return nil, err return nil, err
@ -436,12 +444,13 @@ func ProcessFinalUpdates(state state.BeaconState) (state.BeaconState, error) {
// it sorts the indices and filters out the slashed ones. // it sorts the indices and filters out the slashed ones.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_unslashed_attesting_indices(state: BeaconState, //
// attestations: Sequence[PendingAttestation]) -> Set[ValidatorIndex]: // def get_unslashed_attesting_indices(state: BeaconState,
// output = set() # type: Set[ValidatorIndex] // attestations: Sequence[PendingAttestation]) -> Set[ValidatorIndex]:
// for a in attestations: // output = set() # type: Set[ValidatorIndex]
// output = output.union(get_attesting_indices(state, a.data, a.aggregation_bits)) // for a in attestations:
// return set(filter(lambda index: not state.validators[index].slashed, output)) // output = output.union(get_attesting_indices(state, a.data, a.aggregation_bits))
// return set(filter(lambda index: not state.validators[index].slashed, output))
func UnslashedAttestingIndices(ctx context.Context, state state.ReadOnlyBeaconState, atts []*ethpb.PendingAttestation) ([]types.ValidatorIndex, error) { func UnslashedAttestingIndices(ctx context.Context, state state.ReadOnlyBeaconState, atts []*ethpb.PendingAttestation) ([]types.ValidatorIndex, error) {
var setIndices []types.ValidatorIndex var setIndices []types.ValidatorIndex
seen := make(map[uint64]bool) seen := make(map[uint64]bool)

View File

@ -42,17 +42,18 @@ func UnrealizedCheckpoints(st state.BeaconState) (uint64, *ethpb.Checkpoint, *et
// Note: this is an optimized version by passing in precomputed total and attesting balances. // Note: this is an optimized version by passing in precomputed total and attesting balances.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_justification_and_finalization(state: BeaconState) -> None: //
// # Initial FFG checkpoint values have a `0x00` stub for `root`. // def process_justification_and_finalization(state: BeaconState) -> None:
// # Skip FFG updates in the first two epochs to avoid corner cases that might result in modifying this stub. // # Initial FFG checkpoint values have a `0x00` stub for `root`.
// if get_current_epoch(state) <= GENESIS_EPOCH + 1: // # Skip FFG updates in the first two epochs to avoid corner cases that might result in modifying this stub.
// return // if get_current_epoch(state) <= GENESIS_EPOCH + 1:
// previous_attestations = get_matching_target_attestations(state, get_previous_epoch(state)) // return
// current_attestations = get_matching_target_attestations(state, get_current_epoch(state)) // previous_attestations = get_matching_target_attestations(state, get_previous_epoch(state))
// total_active_balance = get_total_active_balance(state) // current_attestations = get_matching_target_attestations(state, get_current_epoch(state))
// previous_target_balance = get_attesting_balance(state, previous_attestations) // total_active_balance = get_total_active_balance(state)
// current_target_balance = get_attesting_balance(state, current_attestations) // previous_target_balance = get_attesting_balance(state, previous_attestations)
// weigh_justification_and_finalization(state, total_active_balance, previous_target_balance, current_target_balance) // current_target_balance = get_attesting_balance(state, current_attestations)
// weigh_justification_and_finalization(state, total_active_balance, previous_target_balance, current_target_balance)
func ProcessJustificationAndFinalizationPreCompute(state state.BeaconState, pBal *Balance) (state.BeaconState, error) { func ProcessJustificationAndFinalizationPreCompute(state state.BeaconState, pBal *Balance) (state.BeaconState, error) {
canProcessSlot, err := slots.EpochStart(2 /*epoch*/) canProcessSlot, err := slots.EpochStart(2 /*epoch*/)
if err != nil { if err != nil {
@ -113,41 +114,42 @@ func weighJustificationAndFinalization(state state.BeaconState, newBits bitfield
// checkpoints at epoch transition // checkpoints at epoch transition
// Spec pseudocode definition: // Spec pseudocode definition:
// def weigh_justification_and_finalization(state: BeaconState, // def weigh_justification_and_finalization(state: BeaconState,
// total_active_balance: Gwei,
// previous_epoch_target_balance: Gwei,
// current_epoch_target_balance: Gwei) -> None:
// previous_epoch = get_previous_epoch(state)
// current_epoch = get_current_epoch(state)
// old_previous_justified_checkpoint = state.previous_justified_checkpoint
// old_current_justified_checkpoint = state.current_justified_checkpoint
// //
// # Process justifications // total_active_balance: Gwei,
// state.previous_justified_checkpoint = state.current_justified_checkpoint // previous_epoch_target_balance: Gwei,
// state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1] // current_epoch_target_balance: Gwei) -> None:
// state.justification_bits[0] = 0b0 // previous_epoch = get_previous_epoch(state)
// if previous_epoch_target_balance * 3 >= total_active_balance * 2: // current_epoch = get_current_epoch(state)
// state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch, // old_previous_justified_checkpoint = state.previous_justified_checkpoint
// root=get_block_root(state, previous_epoch)) // old_current_justified_checkpoint = state.current_justified_checkpoint
// state.justification_bits[1] = 0b1
// if current_epoch_target_balance * 3 >= total_active_balance * 2:
// state.current_justified_checkpoint = Checkpoint(epoch=current_epoch,
// root=get_block_root(state, current_epoch))
// state.justification_bits[0] = 0b1
// //
// # Process finalizations // # Process justifications
// bits = state.justification_bits // state.previous_justified_checkpoint = state.current_justified_checkpoint
// # The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source // state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1]
// if all(bits[1:4]) and old_previous_justified_checkpoint.epoch + 3 == current_epoch: // state.justification_bits[0] = 0b0
// state.finalized_checkpoint = old_previous_justified_checkpoint // if previous_epoch_target_balance * 3 >= total_active_balance * 2:
// # The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source // state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch,
// if all(bits[1:3]) and old_previous_justified_checkpoint.epoch + 2 == current_epoch: // root=get_block_root(state, previous_epoch))
// state.finalized_checkpoint = old_previous_justified_checkpoint // state.justification_bits[1] = 0b1
// # The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source // if current_epoch_target_balance * 3 >= total_active_balance * 2:
// if all(bits[0:3]) and old_current_justified_checkpoint.epoch + 2 == current_epoch: // state.current_justified_checkpoint = Checkpoint(epoch=current_epoch,
// state.finalized_checkpoint = old_current_justified_checkpoint // root=get_block_root(state, current_epoch))
// # The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source // state.justification_bits[0] = 0b1
// if all(bits[0:2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch: //
// state.finalized_checkpoint = old_current_justified_checkpoint // # Process finalizations
// bits = state.justification_bits
// # The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source
// if all(bits[1:4]) and old_previous_justified_checkpoint.epoch + 3 == current_epoch:
// state.finalized_checkpoint = old_previous_justified_checkpoint
// # The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source
// if all(bits[1:3]) and old_previous_justified_checkpoint.epoch + 2 == current_epoch:
// state.finalized_checkpoint = old_previous_justified_checkpoint
// # The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source
// if all(bits[0:3]) and old_current_justified_checkpoint.epoch + 2 == current_epoch:
// state.finalized_checkpoint = old_current_justified_checkpoint
// # The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source
// if all(bits[0:2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch:
// state.finalized_checkpoint = old_current_justified_checkpoint
func computeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) { func computeCheckpoints(state state.BeaconState, newBits bitfield.Bitvector4) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) {
prevEpoch := time.PrevEpoch(state) prevEpoch := time.PrevEpoch(state)
currentEpoch := time.CurrentEpoch(state) currentEpoch := time.CurrentEpoch(state)

View File

@ -358,10 +358,11 @@ func TestProposerDeltaPrecompute_SlashedCase(t *testing.T) {
// individual validator's base reward quotient. // individual validator's base reward quotient.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei: //
// total_balance = get_total_active_balance(state) // def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
// effective_balance = state.validators[index].effective_balance // total_balance = get_total_active_balance(state)
// return Gwei(effective_balance * BASE_REWARD_FACTOR // integer_squareroot(total_balance) // BASE_REWARDS_PER_EPOCH) // effective_balance = state.validators[index].effective_balance
// return Gwei(effective_balance * BASE_REWARD_FACTOR // integer_squareroot(total_balance) // BASE_REWARDS_PER_EPOCH)
func baseReward(state state.ReadOnlyBeaconState, index types.ValidatorIndex) (uint64, error) { func baseReward(state state.ReadOnlyBeaconState, index types.ValidatorIndex) (uint64, error) {
totalBalance, err := helpers.TotalActiveBalance(state) totalBalance, err := helpers.TotalActiveBalance(state)
if err != nil { if err != nil {

View File

@ -35,14 +35,15 @@ var (
// count. // count.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_committee_count_per_slot(state: BeaconState, epoch: Epoch) -> uint64: //
// """ // def get_committee_count_per_slot(state: BeaconState, epoch: Epoch) -> uint64:
// Return the number of committees in each slot for the given ``epoch``. // """
// """ // Return the number of committees in each slot for the given ``epoch``.
// return max(uint64(1), min( // """
// MAX_COMMITTEES_PER_SLOT, // return max(uint64(1), min(
// uint64(len(get_active_validator_indices(state, epoch))) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE, // MAX_COMMITTEES_PER_SLOT,
// )) // uint64(len(get_active_validator_indices(state, epoch))) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
// ))
func SlotCommitteeCount(activeValidatorCount uint64) uint64 { func SlotCommitteeCount(activeValidatorCount uint64) uint64 {
var committeesPerSlot = activeValidatorCount / uint64(params.BeaconConfig().SlotsPerEpoch) / params.BeaconConfig().TargetCommitteeSize var committeesPerSlot = activeValidatorCount / uint64(params.BeaconConfig().SlotsPerEpoch) / params.BeaconConfig().TargetCommitteeSize
@ -61,18 +62,19 @@ func SlotCommitteeCount(activeValidatorCount uint64) uint64 {
// becomes expensive, consider using BeaconCommittee below. // becomes expensive, consider using BeaconCommittee below.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) -> Sequence[ValidatorIndex]: //
// """ // def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) -> Sequence[ValidatorIndex]:
// Return the beacon committee at ``slot`` for ``index``. // """
// """ // Return the beacon committee at ``slot`` for ``index``.
// epoch = compute_epoch_at_slot(slot) // """
// committees_per_slot = get_committee_count_per_slot(state, epoch) // epoch = compute_epoch_at_slot(slot)
// return compute_committee( // committees_per_slot = get_committee_count_per_slot(state, epoch)
// indices=get_active_validator_indices(state, epoch), // return compute_committee(
// seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER), // indices=get_active_validator_indices(state, epoch),
// index=(slot % SLOTS_PER_EPOCH) * committees_per_slot + index, // seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER),
// count=committees_per_slot * SLOTS_PER_EPOCH, // index=(slot % SLOTS_PER_EPOCH) * committees_per_slot + index,
// ) // count=committees_per_slot * SLOTS_PER_EPOCH,
// )
func BeaconCommitteeFromState(ctx context.Context, state state.ReadOnlyBeaconState, slot types.Slot, committeeIndex types.CommitteeIndex) ([]types.ValidatorIndex, error) { func BeaconCommitteeFromState(ctx context.Context, state state.ReadOnlyBeaconState, slot types.Slot, committeeIndex types.CommitteeIndex) ([]types.ValidatorIndex, error) {
epoch := slots.ToEpoch(slot) epoch := slots.ToEpoch(slot)
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester) seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
@ -101,18 +103,19 @@ func BeaconCommitteeFromState(ctx context.Context, state state.ReadOnlyBeaconSta
// from the spec definition. Having them as an argument allows for cheaper computation run time. // from the spec definition. Having them as an argument allows for cheaper computation run time.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) -> Sequence[ValidatorIndex]: //
// """ // def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) -> Sequence[ValidatorIndex]:
// Return the beacon committee at ``slot`` for ``index``. // """
// """ // Return the beacon committee at ``slot`` for ``index``.
// epoch = compute_epoch_at_slot(slot) // """
// committees_per_slot = get_committee_count_per_slot(state, epoch) // epoch = compute_epoch_at_slot(slot)
// return compute_committee( // committees_per_slot = get_committee_count_per_slot(state, epoch)
// indices=get_active_validator_indices(state, epoch), // return compute_committee(
// seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER), // indices=get_active_validator_indices(state, epoch),
// index=(slot % SLOTS_PER_EPOCH) * committees_per_slot + index, // seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER),
// count=committees_per_slot * SLOTS_PER_EPOCH, // index=(slot % SLOTS_PER_EPOCH) * committees_per_slot + index,
// ) // count=committees_per_slot * SLOTS_PER_EPOCH,
// )
func BeaconCommittee( func BeaconCommittee(
ctx context.Context, ctx context.Context,
validatorIndices []types.ValidatorIndex, validatorIndices []types.ValidatorIndex,
@ -381,16 +384,17 @@ func ClearCache() {
// validator indices and seed. // validator indices and seed.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def compute_committee(indices: Sequence[ValidatorIndex], //
// seed: Bytes32, // def compute_committee(indices: Sequence[ValidatorIndex],
// index: uint64, // seed: Bytes32,
// count: uint64) -> Sequence[ValidatorIndex]: // index: uint64,
// """ // count: uint64) -> Sequence[ValidatorIndex]:
// Return the committee corresponding to ``indices``, ``seed``, ``index``, and committee ``count``. // """
// """ // Return the committee corresponding to ``indices``, ``seed``, ``index``, and committee ``count``.
// start = (len(indices) * index) // count // """
// end = (len(indices) * uint64(index + 1)) // count // start = (len(indices) * index) // count
// return [indices[compute_shuffled_index(uint64(i), uint64(len(indices)), seed)] for i in range(start, end)] // end = (len(indices) * uint64(index + 1)) // count
// return [indices[compute_shuffled_index(uint64(i), uint64(len(indices)), seed)] for i in range(start, end)]
func computeCommittee( func computeCommittee(
indices []types.ValidatorIndex, indices []types.ValidatorIndex,
seed [32]byte, seed [32]byte,

View File

@ -14,12 +14,13 @@ import (
// It returns an error if the requested block root is not within the slot range. // It returns an error if the requested block root is not within the slot range.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_block_root_at_slot(state: BeaconState, slot: Slot) -> Root: //
// """ // def get_block_root_at_slot(state: BeaconState, slot: Slot) -> Root:
// Return the block root at a recent ``slot``. // """
// """ // Return the block root at a recent ``slot``.
// assert slot < state.slot <= slot + SLOTS_PER_HISTORICAL_ROOT // """
// return state.block_roots[slot % SLOTS_PER_HISTORICAL_ROOT] // assert slot < state.slot <= slot + SLOTS_PER_HISTORICAL_ROOT
// return state.block_roots[slot % SLOTS_PER_HISTORICAL_ROOT]
func BlockRootAtSlot(state state.ReadOnlyBeaconState, slot types.Slot) ([]byte, error) { func BlockRootAtSlot(state state.ReadOnlyBeaconState, slot types.Slot) ([]byte, error) {
if math.MaxUint64-slot < params.BeaconConfig().SlotsPerHistoricalRoot { if math.MaxUint64-slot < params.BeaconConfig().SlotsPerHistoricalRoot {
return []byte{}, errors.New("slot overflows uint64") return []byte{}, errors.New("slot overflows uint64")
@ -42,11 +43,12 @@ func StateRootAtSlot(state state.ReadOnlyBeaconState, slot types.Slot) ([]byte,
// BlockRoot returns the block root stored in the BeaconState for epoch start slot. // BlockRoot returns the block root stored in the BeaconState for epoch start slot.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_block_root(state: BeaconState, epoch: Epoch) -> Root: //
// """ // def get_block_root(state: BeaconState, epoch: Epoch) -> Root:
// Return the block root at the start of a recent ``epoch``. // """
// """ // Return the block root at the start of a recent ``epoch``.
// return get_block_root_at_slot(state, compute_start_slot_at_epoch(epoch)) // """
// return get_block_root_at_slot(state, compute_start_slot_at_epoch(epoch))
func BlockRoot(state state.ReadOnlyBeaconState, epoch types.Epoch) ([]byte, error) { func BlockRoot(state state.ReadOnlyBeaconState, epoch types.Epoch) ([]byte, error) {
s, err := slots.EpochStart(epoch) s, err := slots.EpochStart(epoch)
if err != nil { if err != nil {

View File

@ -12,12 +12,13 @@ import (
// Seed returns the randao seed used for shuffling of a given epoch. // Seed returns the randao seed used for shuffling of a given epoch.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Bytes32: //
// """ // def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Bytes32:
// Return the seed at ``epoch``. // """
// """ // Return the seed at ``epoch``.
// mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD - 1)) # Avoid underflow // """
// return hash(domain_type + uint_to_bytes(epoch) + mix) // mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD - 1)) # Avoid underflow
// return hash(domain_type + uint_to_bytes(epoch) + mix)
func Seed(state state.ReadOnlyBeaconState, epoch types.Epoch, domain [bls.DomainByteLength]byte) ([32]byte, error) { func Seed(state state.ReadOnlyBeaconState, epoch types.Epoch, domain [bls.DomainByteLength]byte) ([32]byte, error) {
// See https://github.com/ethereum/consensus-specs/pull/1296 for // See https://github.com/ethereum/consensus-specs/pull/1296 for
// rationale on why offset has to look down by 1. // rationale on why offset has to look down by 1.
@ -40,11 +41,12 @@ func Seed(state state.ReadOnlyBeaconState, epoch types.Epoch, domain [bls.Domain
// of a given slot. It is used to shuffle validators. // of a given slot. It is used to shuffle validators.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_randao_mix(state: BeaconState, epoch: Epoch) -> Bytes32: //
// """ // def get_randao_mix(state: BeaconState, epoch: Epoch) -> Bytes32:
// Return the randao mix at a recent ``epoch``. // """
// """ // Return the randao mix at a recent ``epoch``.
// return state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] // """
// return state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR]
func RandaoMix(state state.ReadOnlyBeaconState, epoch types.Epoch) ([]byte, error) { func RandaoMix(state state.ReadOnlyBeaconState, epoch types.Epoch) ([]byte, error) {
return state.RandaoMixAtIndex(uint64(epoch % params.BeaconConfig().EpochsPerHistoricalVector)) return state.RandaoMixAtIndex(uint64(epoch % params.BeaconConfig().EpochsPerHistoricalVector))
} }

View File

@ -17,13 +17,14 @@ var balanceCache = cache.NewEffectiveBalanceCache()
// of input validators. // of input validators.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei: //
// """ // def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei:
// Return the combined effective balance of the ``indices``. // """
// ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero. // Return the combined effective balance of the ``indices``.
// Math safe up to ~10B ETH, afterwhich this overflows uint64. // ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
// """ // Math safe up to ~10B ETH, afterwhich this overflows uint64.
// return Gwei(max(EFFECTIVE_BALANCE_INCREMENT, sum([state.validators[index].effective_balance for index in indices]))) // """
// return Gwei(max(EFFECTIVE_BALANCE_INCREMENT, sum([state.validators[index].effective_balance for index in indices])))
func TotalBalance(state state.ReadOnlyValidators, indices []types.ValidatorIndex) uint64 { func TotalBalance(state state.ReadOnlyValidators, indices []types.ValidatorIndex) uint64 {
total := uint64(0) total := uint64(0)
@ -47,12 +48,13 @@ func TotalBalance(state state.ReadOnlyValidators, indices []types.ValidatorIndex
// of active validators. // of active validators.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_total_active_balance(state: BeaconState) -> Gwei: //
// """ // def get_total_active_balance(state: BeaconState) -> Gwei:
// Return the combined effective balance of the active validators. // """
// Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero. // Return the combined effective balance of the active validators.
// """ // Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
// return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state)))) // """
// return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state))))
func TotalActiveBalance(s state.ReadOnlyBeaconState) (uint64, error) { func TotalActiveBalance(s state.ReadOnlyBeaconState) (uint64, error) {
bal, err := balanceCache.Get(s) bal, err := balanceCache.Get(s)
switch { switch {
@ -88,11 +90,12 @@ func TotalActiveBalance(s state.ReadOnlyBeaconState) (uint64, error) {
// IncreaseBalance increases validator with the given 'index' balance by 'delta' in Gwei. // IncreaseBalance increases validator with the given 'index' balance by 'delta' in Gwei.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def increase_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None: //
// """ // def increase_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
// Increase the validator balance at index ``index`` by ``delta``. // """
// """ // Increase the validator balance at index ``index`` by ``delta``.
// state.balances[index] += delta // """
// state.balances[index] += delta
func IncreaseBalance(state state.BeaconState, idx types.ValidatorIndex, delta uint64) error { func IncreaseBalance(state state.BeaconState, idx types.ValidatorIndex, delta uint64) error {
balAtIdx, err := state.BalanceAtIndex(idx) balAtIdx, err := state.BalanceAtIndex(idx)
if err != nil { if err != nil {
@ -110,11 +113,12 @@ func IncreaseBalance(state state.BeaconState, idx types.ValidatorIndex, delta ui
// the post balance. // the post balance.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def increase_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None: //
// """ // def increase_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
// Increase the validator balance at index ``index`` by ``delta``. // """
// """ // Increase the validator balance at index ``index`` by ``delta``.
// state.balances[index] += delta // """
// state.balances[index] += delta
func IncreaseBalanceWithVal(currBalance, delta uint64) (uint64, error) { func IncreaseBalanceWithVal(currBalance, delta uint64) (uint64, error) {
return mathutil.Add64(currBalance, delta) return mathutil.Add64(currBalance, delta)
} }
@ -122,11 +126,12 @@ func IncreaseBalanceWithVal(currBalance, delta uint64) (uint64, error) {
// DecreaseBalance decreases validator with the given 'index' balance by 'delta' in Gwei. // DecreaseBalance decreases validator with the given 'index' balance by 'delta' in Gwei.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def decrease_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None: //
// """ // def decrease_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
// Decrease the validator balance at index ``index`` by ``delta``, with underflow protection. // """
// """ // Decrease the validator balance at index ``index`` by ``delta``, with underflow protection.
// state.balances[index] = 0 if delta > state.balances[index] else state.balances[index] - delta // """
// state.balances[index] = 0 if delta > state.balances[index] else state.balances[index] - delta
func DecreaseBalance(state state.BeaconState, idx types.ValidatorIndex, delta uint64) error { func DecreaseBalance(state state.BeaconState, idx types.ValidatorIndex, delta uint64) error {
balAtIdx, err := state.BalanceAtIndex(idx) balAtIdx, err := state.BalanceAtIndex(idx)
if err != nil { if err != nil {
@ -140,11 +145,12 @@ func DecreaseBalance(state state.BeaconState, idx types.ValidatorIndex, delta ui
// the post balance. // the post balance.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def decrease_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None: //
// """ // def decrease_balance(state: BeaconState, index: ValidatorIndex, delta: Gwei) -> None:
// Decrease the validator balance at index ``index`` by ``delta``, with underflow protection. // """
// """ // Decrease the validator balance at index ``index`` by ``delta``, with underflow protection.
// state.balances[index] = 0 if delta > state.balances[index] else state.balances[index] - delta // """
// state.balances[index] = 0 if delta > state.balances[index] else state.balances[index] - delta
func DecreaseBalanceWithVal(currBalance, delta uint64) uint64 { func DecreaseBalanceWithVal(currBalance, delta uint64) uint64 {
if delta > currBalance { if delta > currBalance {
return 0 return 0
@ -156,7 +162,8 @@ func DecreaseBalanceWithVal(currBalance, delta uint64) uint64 {
// //
// Spec code: // Spec code:
// def is_in_inactivity_leak(state: BeaconState) -> bool: // def is_in_inactivity_leak(state: BeaconState) -> bool:
// return get_finality_delay(state) > MIN_EPOCHS_TO_INACTIVITY_PENALTY //
// return get_finality_delay(state) > MIN_EPOCHS_TO_INACTIVITY_PENALTY
func IsInInactivityLeak(prevEpoch, finalizedEpoch types.Epoch) bool { func IsInInactivityLeak(prevEpoch, finalizedEpoch types.Epoch) bool {
return FinalityDelay(prevEpoch, finalizedEpoch) > params.BeaconConfig().MinEpochsToInactivityPenalty return FinalityDelay(prevEpoch, finalizedEpoch) > params.BeaconConfig().MinEpochsToInactivityPenalty
} }
@ -165,7 +172,8 @@ func IsInInactivityLeak(prevEpoch, finalizedEpoch types.Epoch) bool {
// //
// Spec code: // Spec code:
// def get_finality_delay(state: BeaconState) -> uint64: // def get_finality_delay(state: BeaconState) -> uint64:
// return get_previous_epoch(state) - state.finalized_checkpoint.epoch //
// return get_previous_epoch(state) - state.finalized_checkpoint.epoch
func FinalityDelay(prevEpoch, finalizedEpoch types.Epoch) types.Epoch { func FinalityDelay(prevEpoch, finalizedEpoch types.Epoch) types.Epoch {
return prevEpoch - finalizedEpoch return prevEpoch - finalizedEpoch
} }

View File

@ -31,7 +31,7 @@ func SplitIndices(l []uint64, n uint64) [][]uint64 {
return divided return divided
} }
// ShuffledIndex returns `p(index)` in a pseudorandom permutation `p` of `0...list_size - 1` with ``seed`` as entropy. // ShuffledIndex returns `p(index)` in a pseudorandom permutation `p` of `0...list_size - 1` with “seed“ as entropy.
// We utilize 'swap or not' shuffling in this implementation; we are allocating the memory with the seed that stays // We utilize 'swap or not' shuffling in this implementation; we are allocating the memory with the seed that stays
// constant between iterations instead of reallocating it each iteration as in the spec. This implementation is based // constant between iterations instead of reallocating it each iteration as in the spec. This implementation is based
// on the original implementation from protolambda, https://github.com/protolambda/eth2-shuffle // on the original implementation from protolambda, https://github.com/protolambda/eth2-shuffle
@ -47,28 +47,29 @@ func UnShuffledIndex(index types.ValidatorIndex, indexCount uint64, seed [32]byt
// ComputeShuffledIndex returns the shuffled validator index corresponding to seed and index count. // ComputeShuffledIndex returns the shuffled validator index corresponding to seed and index count.
// Spec pseudocode definition: // Spec pseudocode definition:
// def compute_shuffled_index(index: uint64, index_count: uint64, seed: Bytes32) -> uint64:
// """
// Return the shuffled index corresponding to ``seed`` (and ``index_count``).
// """
// assert index < index_count
// //
// # Swap or not (https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf) // def compute_shuffled_index(index: uint64, index_count: uint64, seed: Bytes32) -> uint64:
// # See the 'generalized domain' algorithm on page 3 // """
// for current_round in range(SHUFFLE_ROUND_COUNT): // Return the shuffled index corresponding to ``seed`` (and ``index_count``).
// pivot = bytes_to_uint64(hash(seed + uint_to_bytes(uint8(current_round)))[0:8]) % index_count // """
// flip = (pivot + index_count - index) % index_count // assert index < index_count
// position = max(index, flip)
// source = hash(
// seed
// + uint_to_bytes(uint8(current_round))
// + uint_to_bytes(uint32(position // 256))
// )
// byte = uint8(source[(position % 256) // 8])
// bit = (byte >> (position % 8)) % 2
// index = flip if bit else index
// //
// return index // # Swap or not (https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf)
// # See the 'generalized domain' algorithm on page 3
// for current_round in range(SHUFFLE_ROUND_COUNT):
// pivot = bytes_to_uint64(hash(seed + uint_to_bytes(uint8(current_round)))[0:8]) % index_count
// flip = (pivot + index_count - index) % index_count
// position = max(index, flip)
// source = hash(
// seed
// + uint_to_bytes(uint8(current_round))
// + uint_to_bytes(uint32(position // 256))
// )
// byte = uint8(source[(position % 256) // 8])
// bit = (byte >> (position % 8)) % 2
// index = flip if bit else index
//
// return index
func ComputeShuffledIndex(index types.ValidatorIndex, indexCount uint64, seed [32]byte, shuffle bool) (types.ValidatorIndex, error) { func ComputeShuffledIndex(index types.ValidatorIndex, indexCount uint64, seed [32]byte, shuffle bool) (types.ValidatorIndex, error) {
if params.BeaconConfig().ShuffleRoundCount == 0 { if params.BeaconConfig().ShuffleRoundCount == 0 {
return index, nil return index, nil
@ -135,20 +136,21 @@ func ComputeShuffledIndex(index types.ValidatorIndex, indexCount uint64, seed [3
return index, nil return index, nil
} }
// ShuffleList returns list of shuffled indexes in a pseudorandom permutation `p` of `0...list_size - 1` with ``seed`` as entropy. // ShuffleList returns list of shuffled indexes in a pseudorandom permutation `p` of `0...list_size - 1` with “seed“ as entropy.
// We utilize 'swap or not' shuffling in this implementation; we are allocating the memory with the seed that stays // We utilize 'swap or not' shuffling in this implementation; we are allocating the memory with the seed that stays
// constant between iterations instead of reallocating it each iteration as in the spec. This implementation is based // constant between iterations instead of reallocating it each iteration as in the spec. This implementation is based
// on the original implementation from protolambda, https://github.com/protolambda/eth2-shuffle // on the original implementation from protolambda, https://github.com/protolambda/eth2-shuffle
// improvements: //
// - seed is always the first 32 bytes of the hash input, we just copy it into the buffer one time. // improvements:
// - add round byte to seed and hash that part of the buffer. // - seed is always the first 32 bytes of the hash input, we just copy it into the buffer one time.
// - split up the for-loop in two: // - add round byte to seed and hash that part of the buffer.
// 1. Handle the part from 0 (incl) to pivot (incl). This is mirrored around (pivot / 2). // - split up the for-loop in two:
// 2. Handle the part from pivot (excl) to N (excl). This is mirrored around ((pivot / 2) + (size/2)). // 1. Handle the part from 0 (incl) to pivot (incl). This is mirrored around (pivot / 2).
// - hash source every 256 iterations. // 2. Handle the part from pivot (excl) to N (excl). This is mirrored around ((pivot / 2) + (size/2)).
// - change byteV every 8 iterations. // - hash source every 256 iterations.
// - we start at the edges, and work back to the mirror point. // - change byteV every 8 iterations.
// this makes us process each pear exactly once (instead of unnecessarily twice, like in the spec). // - we start at the edges, and work back to the mirror point.
// this makes us process each pear exactly once (instead of unnecessarily twice, like in the spec).
func ShuffleList(input []types.ValidatorIndex, seed [32]byte) ([]types.ValidatorIndex, error) { func ShuffleList(input []types.ValidatorIndex, seed [32]byte) ([]types.ValidatorIndex, error) {
return innerShuffleList(input, seed, true /* shuffle */) return innerShuffleList(input, seed, true /* shuffle */)
} }

View File

@ -28,11 +28,12 @@ var CommitteeCacheInProgressHit = promauto.NewCounter(prometheus.CounterOpts{
// is active or not. // is active or not.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def is_active_validator(validator: Validator, epoch: Epoch) -> bool: //
// """ // def is_active_validator(validator: Validator, epoch: Epoch) -> bool:
// Check if ``validator`` is active. // """
// """ // Check if ``validator`` is active.
// return validator.activation_epoch <= epoch < validator.exit_epoch // """
// return validator.activation_epoch <= epoch < validator.exit_epoch
func IsActiveValidator(validator *ethpb.Validator, epoch types.Epoch) bool { func IsActiveValidator(validator *ethpb.Validator, epoch types.Epoch) bool {
return checkValidatorActiveStatus(validator.ActivationEpoch, validator.ExitEpoch, epoch) return checkValidatorActiveStatus(validator.ActivationEpoch, validator.ExitEpoch, epoch)
} }
@ -50,11 +51,12 @@ func checkValidatorActiveStatus(activationEpoch, exitEpoch, epoch types.Epoch) b
// is slashable or not. // is slashable or not.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def is_slashable_validator(validator: Validator, epoch: Epoch) -> bool: //
// """ // def is_slashable_validator(validator: Validator, epoch: Epoch) -> bool:
// Check if ``validator`` is slashable. // """
// """ // Check if ``validator`` is slashable.
// return (not validator.slashed) and (validator.activation_epoch <= epoch < validator.withdrawable_epoch) // """
// return (not validator.slashed) and (validator.activation_epoch <= epoch < validator.withdrawable_epoch)
func IsSlashableValidator(activationEpoch, withdrawableEpoch types.Epoch, slashed bool, epoch types.Epoch) bool { func IsSlashableValidator(activationEpoch, withdrawableEpoch types.Epoch, slashed bool, epoch types.Epoch) bool {
return checkValidatorSlashable(activationEpoch, withdrawableEpoch, slashed, epoch) return checkValidatorSlashable(activationEpoch, withdrawableEpoch, slashed, epoch)
} }
@ -78,11 +80,12 @@ func checkValidatorSlashable(activationEpoch, withdrawableEpoch types.Epoch, sla
// need the active validator indices for some specific reason. // need the active validator indices for some specific reason.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_active_validator_indices(state: BeaconState, epoch: Epoch) -> Sequence[ValidatorIndex]: //
// """ // def get_active_validator_indices(state: BeaconState, epoch: Epoch) -> Sequence[ValidatorIndex]:
// Return the sequence of active validator indices at ``epoch``. // """
// """ // Return the sequence of active validator indices at ``epoch``.
// return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)] // """
// return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)]
func ActiveValidatorIndices(ctx context.Context, s state.ReadOnlyBeaconState, epoch types.Epoch) ([]types.ValidatorIndex, error) { func ActiveValidatorIndices(ctx context.Context, s state.ReadOnlyBeaconState, epoch types.Epoch) ([]types.ValidatorIndex, error) {
seed, err := Seed(s, epoch, params.BeaconConfig().DomainBeaconAttester) seed, err := Seed(s, epoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil { if err != nil {
@ -186,11 +189,12 @@ func ActiveValidatorCount(ctx context.Context, s state.ReadOnlyBeaconState, epoc
// the validator is eligible for activation and exit. // the validator is eligible for activation and exit.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def compute_activation_exit_epoch(epoch: Epoch) -> Epoch: //
// """ // def compute_activation_exit_epoch(epoch: Epoch) -> Epoch:
// Return the epoch during which validator activations and exits initiated in ``epoch`` take effect. // """
// """ // Return the epoch during which validator activations and exits initiated in ``epoch`` take effect.
// return Epoch(epoch + 1 + MAX_SEED_LOOKAHEAD) // """
// return Epoch(epoch + 1 + MAX_SEED_LOOKAHEAD)
func ActivationExitEpoch(epoch types.Epoch) types.Epoch { func ActivationExitEpoch(epoch types.Epoch) types.Epoch {
return epoch + 1 + params.BeaconConfig().MaxSeedLookahead return epoch + 1 + params.BeaconConfig().MaxSeedLookahead
} }
@ -199,12 +203,13 @@ func ActivationExitEpoch(epoch types.Epoch) types.Epoch {
// enter and exit validator pool for an epoch. // enter and exit validator pool for an epoch.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_validator_churn_limit(state: BeaconState) -> uint64: //
// """ // def get_validator_churn_limit(state: BeaconState) -> uint64:
// Return the validator churn limit for the current epoch. // """
// """ // Return the validator churn limit for the current epoch.
// active_validator_indices = get_active_validator_indices(state, get_current_epoch(state)) // """
// return max(MIN_PER_EPOCH_CHURN_LIMIT, uint64(len(active_validator_indices)) // CHURN_LIMIT_QUOTIENT) // active_validator_indices = get_active_validator_indices(state, get_current_epoch(state))
// return max(MIN_PER_EPOCH_CHURN_LIMIT, uint64(len(active_validator_indices)) // CHURN_LIMIT_QUOTIENT)
func ValidatorChurnLimit(activeValidatorCount uint64) (uint64, error) { func ValidatorChurnLimit(activeValidatorCount uint64) (uint64, error) {
churnLimit := activeValidatorCount / params.BeaconConfig().ChurnLimitQuotient churnLimit := activeValidatorCount / params.BeaconConfig().ChurnLimitQuotient
if churnLimit < params.BeaconConfig().MinPerEpochChurnLimit { if churnLimit < params.BeaconConfig().MinPerEpochChurnLimit {
@ -216,14 +221,15 @@ func ValidatorChurnLimit(activeValidatorCount uint64) (uint64, error) {
// BeaconProposerIndex returns proposer index of a current slot. // BeaconProposerIndex returns proposer index of a current slot.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_beacon_proposer_index(state: BeaconState) -> ValidatorIndex: //
// """ // def get_beacon_proposer_index(state: BeaconState) -> ValidatorIndex:
// Return the beacon proposer index at the current slot. // """
// """ // Return the beacon proposer index at the current slot.
// epoch = get_current_epoch(state) // """
// seed = hash(get_seed(state, epoch, DOMAIN_BEACON_PROPOSER) + uint_to_bytes(state.slot)) // epoch = get_current_epoch(state)
// indices = get_active_validator_indices(state, epoch) // seed = hash(get_seed(state, epoch, DOMAIN_BEACON_PROPOSER) + uint_to_bytes(state.slot))
// return compute_proposer_index(state, indices, seed) // indices = get_active_validator_indices(state, epoch)
// return compute_proposer_index(state, indices, seed)
func BeaconProposerIndex(ctx context.Context, state state.ReadOnlyBeaconState) (types.ValidatorIndex, error) { func BeaconProposerIndex(ctx context.Context, state state.ReadOnlyBeaconState) (types.ValidatorIndex, error) {
e := time.CurrentEpoch(state) e := time.CurrentEpoch(state)
// The cache uses the state root of the previous epoch - minimum_seed_lookahead last slot as key. (e.g. Starting epoch 1, slot 32, the key would be block root at slot 31) // The cache uses the state root of the previous epoch - minimum_seed_lookahead last slot as key. (e.g. Starting epoch 1, slot 32, the key would be block root at slot 31)
@ -274,21 +280,22 @@ func BeaconProposerIndex(ctx context.Context, state state.ReadOnlyBeaconState) (
// ComputeProposerIndex returns the index sampled by effective balance, which is used to calculate proposer. // ComputeProposerIndex returns the index sampled by effective balance, which is used to calculate proposer.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def compute_proposer_index(state: BeaconState, indices: Sequence[ValidatorIndex], seed: Bytes32) -> ValidatorIndex: //
// """ // def compute_proposer_index(state: BeaconState, indices: Sequence[ValidatorIndex], seed: Bytes32) -> ValidatorIndex:
// Return from ``indices`` a random index sampled by effective balance. // """
// """ // Return from ``indices`` a random index sampled by effective balance.
// assert len(indices) > 0 // """
// MAX_RANDOM_BYTE = 2**8 - 1 // assert len(indices) > 0
// i = uint64(0) // MAX_RANDOM_BYTE = 2**8 - 1
// total = uint64(len(indices)) // i = uint64(0)
// while True: // total = uint64(len(indices))
// candidate_index = indices[compute_shuffled_index(i % total, total, seed)] // while True:
// random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32] // candidate_index = indices[compute_shuffled_index(i % total, total, seed)]
// effective_balance = state.validators[candidate_index].effective_balance // random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32]
// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte: // effective_balance = state.validators[candidate_index].effective_balance
// return candidate_index // if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte:
// i += 1 // return candidate_index
// i += 1
func ComputeProposerIndex(bState state.ReadOnlyValidators, activeIndices []types.ValidatorIndex, seed [32]byte) (types.ValidatorIndex, error) { func ComputeProposerIndex(bState state.ReadOnlyValidators, activeIndices []types.ValidatorIndex, seed [32]byte) (types.ValidatorIndex, error) {
length := uint64(len(activeIndices)) length := uint64(len(activeIndices))
if length == 0 { if length == 0 {
@ -324,14 +331,15 @@ func ComputeProposerIndex(bState state.ReadOnlyValidators, activeIndices []types
// be placed into the activation queue. // be placed into the activation queue.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def is_eligible_for_activation_queue(validator: Validator) -> bool: //
// """ // def is_eligible_for_activation_queue(validator: Validator) -> bool:
// Check if ``validator`` is eligible to be placed into the activation queue. // """
// """ // Check if ``validator`` is eligible to be placed into the activation queue.
// return ( // """
// validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH // return (
// and validator.effective_balance == MAX_EFFECTIVE_BALANCE // validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH
// ) // and validator.effective_balance == MAX_EFFECTIVE_BALANCE
// )
func IsEligibleForActivationQueue(validator *ethpb.Validator) bool { func IsEligibleForActivationQueue(validator *ethpb.Validator) bool {
return isEligibileForActivationQueue(validator.ActivationEligibilityEpoch, validator.EffectiveBalance) return isEligibileForActivationQueue(validator.ActivationEligibilityEpoch, validator.EffectiveBalance)
} }
@ -351,16 +359,17 @@ func isEligibileForActivationQueue(activationEligibilityEpoch types.Epoch, effec
// IsEligibleForActivation checks if the validator is eligible for activation. // IsEligibleForActivation checks if the validator is eligible for activation.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def is_eligible_for_activation(state: BeaconState, validator: Validator) -> bool: //
// """ // def is_eligible_for_activation(state: BeaconState, validator: Validator) -> bool:
// Check if ``validator`` is eligible for activation. // """
// """ // Check if ``validator`` is eligible for activation.
// return ( // """
// # Placement in queue is finalized // return (
// validator.activation_eligibility_epoch <= state.finalized_checkpoint.epoch // # Placement in queue is finalized
// # Has not yet been activated // validator.activation_eligibility_epoch <= state.finalized_checkpoint.epoch
// and validator.activation_epoch == FAR_FUTURE_EPOCH // # Has not yet been activated
// ) // and validator.activation_epoch == FAR_FUTURE_EPOCH
// )
func IsEligibleForActivation(state state.ReadOnlyCheckpoint, validator *ethpb.Validator) bool { func IsEligibleForActivation(state state.ReadOnlyCheckpoint, validator *ethpb.Validator) bool {
finalizedEpoch := state.FinalizedCheckpointEpoch() finalizedEpoch := state.FinalizedCheckpointEpoch()
return isEligibleForActivation(validator.ActivationEligibilityEpoch, validator.ActivationEpoch, finalizedEpoch) return isEligibleForActivation(validator.ActivationEligibilityEpoch, validator.ActivationEpoch, finalizedEpoch)

View File

@ -25,36 +25,37 @@ import (
// https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/weak-subjectivity.md#calculating-the-weak-subjectivity-period // https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/weak-subjectivity.md#calculating-the-weak-subjectivity-period
// //
// def compute_weak_subjectivity_period(state: BeaconState) -> uint64: // def compute_weak_subjectivity_period(state: BeaconState) -> uint64:
// """
// Returns the weak subjectivity period for the current ``state``.
// This computation takes into account the effect of:
// - validator set churn (bounded by ``get_validator_churn_limit()`` per epoch), and
// - validator balance top-ups (bounded by ``MAX_DEPOSITS * SLOTS_PER_EPOCH`` per epoch).
// A detailed calculation can be found at:
// https://github.com/runtimeverification/beacon-chain-verification/blob/master/weak-subjectivity/weak-subjectivity-analysis.pdf
// """
// ws_period = MIN_VALIDATOR_WITHDRAWABILITY_DELAY
// N = len(get_active_validator_indices(state, get_current_epoch(state)))
// t = get_total_active_balance(state) // N // ETH_TO_GWEI
// T = MAX_EFFECTIVE_BALANCE // ETH_TO_GWEI
// delta = get_validator_churn_limit(state)
// Delta = MAX_DEPOSITS * SLOTS_PER_EPOCH
// D = SAFETY_DECAY
// //
// if T * (200 + 3 * D) < t * (200 + 12 * D): // """
// epochs_for_validator_set_churn = ( // Returns the weak subjectivity period for the current ``state``.
// N * (t * (200 + 12 * D) - T * (200 + 3 * D)) // (600 * delta * (2 * t + T)) // This computation takes into account the effect of:
// ) // - validator set churn (bounded by ``get_validator_churn_limit()`` per epoch), and
// epochs_for_balance_top_ups = ( // - validator balance top-ups (bounded by ``MAX_DEPOSITS * SLOTS_PER_EPOCH`` per epoch).
// N * (200 + 3 * D) // (600 * Delta) // A detailed calculation can be found at:
// ) // https://github.com/runtimeverification/beacon-chain-verification/blob/master/weak-subjectivity/weak-subjectivity-analysis.pdf
// ws_period += max(epochs_for_validator_set_churn, epochs_for_balance_top_ups) // """
// else: // ws_period = MIN_VALIDATOR_WITHDRAWABILITY_DELAY
// ws_period += ( // N = len(get_active_validator_indices(state, get_current_epoch(state)))
// 3 * N * D * t // (200 * Delta * (T - t)) // t = get_total_active_balance(state) // N // ETH_TO_GWEI
// ) // T = MAX_EFFECTIVE_BALANCE // ETH_TO_GWEI
// delta = get_validator_churn_limit(state)
// Delta = MAX_DEPOSITS * SLOTS_PER_EPOCH
// D = SAFETY_DECAY
// //
// return ws_period // if T * (200 + 3 * D) < t * (200 + 12 * D):
// epochs_for_validator_set_churn = (
// N * (t * (200 + 12 * D) - T * (200 + 3 * D)) // (600 * delta * (2 * t + T))
// )
// epochs_for_balance_top_ups = (
// N * (200 + 3 * D) // (600 * Delta)
// )
// ws_period += max(epochs_for_validator_set_churn, epochs_for_balance_top_ups)
// else:
// ws_period += (
// 3 * N * D * t // (200 * Delta * (T - t))
// )
//
// return ws_period
func ComputeWeakSubjectivityPeriod(ctx context.Context, st state.ReadOnlyBeaconState, cfg *params.BeaconChainConfig) (types.Epoch, error) { func ComputeWeakSubjectivityPeriod(ctx context.Context, st state.ReadOnlyBeaconState, cfg *params.BeaconChainConfig) (types.Epoch, error) {
// Weak subjectivity period cannot be smaller than withdrawal delay. // Weak subjectivity period cannot be smaller than withdrawal delay.
wsp := uint64(cfg.MinValidatorWithdrawabilityDelay) wsp := uint64(cfg.MinValidatorWithdrawabilityDelay)
@ -114,14 +115,15 @@ func ComputeWeakSubjectivityPeriod(ctx context.Context, st state.ReadOnlyBeaconS
// https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/weak-subjectivity.md#checking-for-stale-weak-subjectivity-checkpoint // https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/weak-subjectivity.md#checking-for-stale-weak-subjectivity-checkpoint
// //
// def is_within_weak_subjectivity_period(store: Store, ws_state: BeaconState, ws_checkpoint: Checkpoint) -> bool: // def is_within_weak_subjectivity_period(store: Store, ws_state: BeaconState, ws_checkpoint: Checkpoint) -> bool:
// # Clients may choose to validate the input state against the input Weak Subjectivity Checkpoint
// assert ws_state.latest_block_header.state_root == ws_checkpoint.root
// assert compute_epoch_at_slot(ws_state.slot) == ws_checkpoint.epoch
// //
// ws_period = compute_weak_subjectivity_period(ws_state) // # Clients may choose to validate the input state against the input Weak Subjectivity Checkpoint
// ws_state_epoch = compute_epoch_at_slot(ws_state.slot) // assert ws_state.latest_block_header.state_root == ws_checkpoint.root
// current_epoch = compute_epoch_at_slot(get_current_slot(store)) // assert compute_epoch_at_slot(ws_state.slot) == ws_checkpoint.epoch
// return current_epoch <= ws_state_epoch + ws_period //
// ws_period = compute_weak_subjectivity_period(ws_state)
// ws_state_epoch = compute_epoch_at_slot(ws_state.slot)
// current_epoch = compute_epoch_at_slot(get_current_slot(store))
// return current_epoch <= ws_state_epoch + ws_period
func IsWithinWeakSubjectivityPeriod( func IsWithinWeakSubjectivityPeriod(
ctx context.Context, currentEpoch types.Epoch, wsState state.ReadOnlyBeaconState, wsStateRoot [fieldparams.RootLength]byte, wsEpoch types.Epoch, cfg *params.BeaconChainConfig) (bool, error) { ctx context.Context, currentEpoch types.Epoch, wsState state.ReadOnlyBeaconState, wsStateRoot [fieldparams.RootLength]byte, wsEpoch types.Epoch, cfg *params.BeaconChainConfig) (bool, error) {
// Make sure that incoming objects are not nil. // Make sure that incoming objects are not nil.

View File

@ -10,13 +10,14 @@ import (
// Domain returns the domain version for BLS private key to sign and verify. // Domain returns the domain version for BLS private key to sign and verify.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_domain(state: BeaconState, domain_type: DomainType, epoch: Epoch=None) -> Domain: //
// """ // def get_domain(state: BeaconState, domain_type: DomainType, epoch: Epoch=None) -> Domain:
// Return the signature domain (fork version concatenated with domain type) of a message. // """
// """ // Return the signature domain (fork version concatenated with domain type) of a message.
// epoch = get_current_epoch(state) if epoch is None else epoch // """
// fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version // epoch = get_current_epoch(state) if epoch is None else epoch
// return compute_domain(domain_type, fork_version, state.genesis_validators_root) // fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
// return compute_domain(domain_type, fork_version, state.genesis_validators_root)
func Domain(fork *eth.Fork, epoch types.Epoch, domainType [bls.DomainByteLength]byte, genesisRoot []byte) ([]byte, error) { func Domain(fork *eth.Fork, epoch types.Epoch, domainType [bls.DomainByteLength]byte, genesisRoot []byte) ([]byte, error) {
if fork == nil { if fork == nil {
return []byte{}, errors.New("nil fork or domain type") return []byte{}, errors.New("nil fork or domain type")

View File

@ -37,14 +37,15 @@ func ComputeDomainAndSign(st state.ReadOnlyBeaconState, epoch types.Epoch, obj f
// ComputeSigningRoot computes the root of the object by calculating the hash tree root of the signing data with the given domain. // ComputeSigningRoot computes the root of the object by calculating the hash tree root of the signing data with the given domain.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def compute_signing_root(ssz_object: SSZObject, domain: Domain) -> Root: //
// """ // def compute_signing_root(ssz_object: SSZObject, domain: Domain) -> Root:
// Return the signing root for the corresponding signing data. // """
// """ // Return the signing root for the corresponding signing data.
// return hash_tree_root(SigningData( // """
// object_root=hash_tree_root(ssz_object), // return hash_tree_root(SigningData(
// domain=domain, // object_root=hash_tree_root(ssz_object),
// )) // domain=domain,
// ))
func ComputeSigningRoot(object fssz.HashRoot, domain []byte) ([32]byte, error) { func ComputeSigningRoot(object fssz.HashRoot, domain []byte) ([32]byte, error) {
return signingData(object.HashTreeRoot, domain) return signingData(object.HashTreeRoot, domain)
} }
@ -160,15 +161,16 @@ func BlockSignatureBatch(pub, signature, domain []byte, rootFunc func() ([32]byt
// array as the fork version. // array as the fork version.
// //
// def compute_domain(domain_type: DomainType, fork_version: Version=None, genesis_validators_root: Root=None) -> Domain: // def compute_domain(domain_type: DomainType, fork_version: Version=None, genesis_validators_root: Root=None) -> Domain:
// """ //
// Return the domain for the ``domain_type`` and ``fork_version``. // """
// """ // Return the domain for the ``domain_type`` and ``fork_version``.
// if fork_version is None: // """
// fork_version = GENESIS_FORK_VERSION // if fork_version is None:
// if genesis_validators_root is None: // fork_version = GENESIS_FORK_VERSION
// genesis_validators_root = Root() # all bytes zero by default // if genesis_validators_root is None:
// fork_data_root = compute_fork_data_root(fork_version, genesis_validators_root) // genesis_validators_root = Root() # all bytes zero by default
// return Domain(domain_type + fork_data_root[:28]) // fork_data_root = compute_fork_data_root(fork_version, genesis_validators_root)
// return Domain(domain_type + fork_data_root[:28])
func ComputeDomain(domainType [DomainByteLength]byte, forkVersion, genesisValidatorsRoot []byte) ([]byte, error) { func ComputeDomain(domainType [DomainByteLength]byte, forkVersion, genesisValidatorsRoot []byte) ([]byte, error) {
if forkVersion == nil { if forkVersion == nil {
forkVersion = params.BeaconConfig().GenesisForkVersion forkVersion = params.BeaconConfig().GenesisForkVersion
@ -195,19 +197,20 @@ func domain(domainType [DomainByteLength]byte, forkDataRoot []byte) []byte {
return b return b
} }
// this returns the 32byte fork data root for the ``current_version`` and ``genesis_validators_root``. // this returns the 32byte fork data root for the “current_version“ and “genesis_validators_root“.
// This is used primarily in signature domains to avoid collisions across forks/chains. // This is used primarily in signature domains to avoid collisions across forks/chains.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def compute_fork_data_root(current_version: Version, genesis_validators_root: Root) -> Root: //
// """ // def compute_fork_data_root(current_version: Version, genesis_validators_root: Root) -> Root:
// Return the 32-byte fork data root for the ``current_version`` and ``genesis_validators_root``. // """
// This is used primarily in signature domains to avoid collisions across forks/chains. // Return the 32-byte fork data root for the ``current_version`` and ``genesis_validators_root``.
// """ // This is used primarily in signature domains to avoid collisions across forks/chains.
// return hash_tree_root(ForkData( // """
// current_version=current_version, // return hash_tree_root(ForkData(
// genesis_validators_root=genesis_validators_root, // current_version=current_version,
// )) // genesis_validators_root=genesis_validators_root,
// ))
func computeForkDataRoot(version, root []byte) ([32]byte, error) { func computeForkDataRoot(version, root []byte) ([32]byte, error) {
r, err := (&ethpb.ForkData{ r, err := (&ethpb.ForkData{
CurrentVersion: version, CurrentVersion: version,
@ -222,13 +225,14 @@ func computeForkDataRoot(version, root []byte) ([32]byte, error) {
// ComputeForkDigest returns the fork for the current version and genesis validators root // ComputeForkDigest returns the fork for the current version and genesis validators root
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def compute_fork_digest(current_version: Version, genesis_validators_root: Root) -> ForkDigest: //
// """ // def compute_fork_digest(current_version: Version, genesis_validators_root: Root) -> ForkDigest:
// Return the 4-byte fork digest for the ``current_version`` and ``genesis_validators_root``. // """
// This is a digest primarily used for domain separation on the p2p layer. // Return the 4-byte fork digest for the ``current_version`` and ``genesis_validators_root``.
// 4-bytes suffices for practical separation of forks/chains. // This is a digest primarily used for domain separation on the p2p layer.
// """ // 4-bytes suffices for practical separation of forks/chains.
// return ForkDigest(compute_fork_data_root(current_version, genesis_validators_root)[:4]) // """
// return ForkDigest(compute_fork_data_root(current_version, genesis_validators_root)[:4])
func ComputeForkDigest(version, genesisValidatorsRoot []byte) ([4]byte, error) { func ComputeForkDigest(version, genesisValidatorsRoot []byte) ([4]byte, error) {
dataRoot, err := computeForkDataRoot(version, genesisValidatorsRoot) dataRoot, err := computeForkDataRoot(version, genesisValidatorsRoot)
if err != nil { if err != nil {

View File

@ -12,11 +12,12 @@ import (
// the slot number stored in beacon state. // the slot number stored in beacon state.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_current_epoch(state: BeaconState) -> Epoch: //
// """ // def get_current_epoch(state: BeaconState) -> Epoch:
// Return the current epoch. // """
// """ // Return the current epoch.
// return compute_epoch_at_slot(state.slot) // """
// return compute_epoch_at_slot(state.slot)
func CurrentEpoch(state state.ReadOnlyBeaconState) types.Epoch { func CurrentEpoch(state state.ReadOnlyBeaconState) types.Epoch {
return slots.ToEpoch(state.Slot()) return slots.ToEpoch(state.Slot())
} }
@ -26,12 +27,13 @@ func CurrentEpoch(state state.ReadOnlyBeaconState) types.Epoch {
// underflow condition. // underflow condition.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_previous_epoch(state: BeaconState) -> Epoch: //
// """` // def get_previous_epoch(state: BeaconState) -> Epoch:
// Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``). // """`
// """ // Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``).
// current_epoch = get_current_epoch(state) // """
// return GENESIS_EPOCH if current_epoch == GENESIS_EPOCH else Epoch(current_epoch - 1) // current_epoch = get_current_epoch(state)
// return GENESIS_EPOCH if current_epoch == GENESIS_EPOCH else Epoch(current_epoch - 1)
func PrevEpoch(state state.ReadOnlyBeaconState) types.Epoch { func PrevEpoch(state state.ReadOnlyBeaconState) types.Epoch {
currentEpoch := CurrentEpoch(state) currentEpoch := CurrentEpoch(state)
if currentEpoch == 0 { if currentEpoch == 0 {
@ -83,7 +85,8 @@ func CanUpgradeToCapella(slot types.Slot) bool {
// The epoch can be processed at the end of the last slot of every epoch. // The epoch can be processed at the end of the last slot of every epoch.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// If (state.slot + 1) % SLOTS_PER_EPOCH == 0: //
// If (state.slot + 1) % SLOTS_PER_EPOCH == 0:
func CanProcessEpoch(state state.ReadOnlyBeaconState) bool { func CanProcessEpoch(state state.ReadOnlyBeaconState) bool {
return (state.Slot()+1)%params.BeaconConfig().SlotsPerEpoch == 0 return (state.Slot()+1)%params.BeaconConfig().SlotsPerEpoch == 0
} }

View File

@ -17,41 +17,43 @@ import (
// full deposits were made to the deposit contract and the ChainStart log gets emitted. // full deposits were made to the deposit contract and the ChainStart log gets emitted.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32,
// eth1_timestamp: uint64,
// deposits: Sequence[Deposit]) -> BeaconState:
// fork = Fork(
// previous_version=GENESIS_FORK_VERSION,
// current_version=GENESIS_FORK_VERSION,
// epoch=GENESIS_EPOCH,
// )
// state = BeaconState(
// genesis_time=eth1_timestamp + GENESIS_DELAY,
// fork=fork,
// eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
// latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
// randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy
// )
// //
// # Process deposits // def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32,
// leaves = list(map(lambda deposit: deposit.data, deposits)) // eth1_timestamp: uint64,
// for index, deposit in enumerate(deposits): // deposits: Sequence[Deposit]) -> BeaconState:
// deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1]) // fork = Fork(
// state.eth1_data.deposit_root = hash_tree_root(deposit_data_list) // previous_version=GENESIS_FORK_VERSION,
// process_deposit(state, deposit) // current_version=GENESIS_FORK_VERSION,
// epoch=GENESIS_EPOCH,
// )
// state = BeaconState(
// genesis_time=eth1_timestamp + GENESIS_DELAY,
// fork=fork,
// eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
// latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
// randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy
// )
// //
// # Process activations // # Process deposits
// for index, validator in enumerate(state.validators): // leaves = list(map(lambda deposit: deposit.data, deposits))
// balance = state.balances[index] // for index, deposit in enumerate(deposits):
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) // deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1])
// if validator.effective_balance == MAX_EFFECTIVE_BALANCE: // state.eth1_data.deposit_root = hash_tree_root(deposit_data_list)
// validator.activation_eligibility_epoch = GENESIS_EPOCH // process_deposit(state, deposit)
// validator.activation_epoch = GENESIS_EPOCH
// //
// # Set genesis validators root for domain separation and chain versioning // # Process activations
// state.genesis_validators_root = hash_tree_root(state.validators) // for index, validator in enumerate(state.validators):
// balance = state.balances[index]
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
// if validator.effective_balance == MAX_EFFECTIVE_BALANCE:
// 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)
//
// return state
// //
// return state
// This method differs from the spec so as to process deposits beforehand instead of the end of the function. // This method differs from the spec so as to process deposits beforehand instead of the end of the function.
func GenesisBeaconState(ctx context.Context, deposits []*ethpb.Deposit, genesisTime uint64, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) { func GenesisBeaconState(ctx context.Context, deposits []*ethpb.Deposit, genesisTime uint64, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {
st, err := EmptyGenesisState() st, err := EmptyGenesisState()
@ -211,12 +213,14 @@ func EmptyGenesisState() (state.BeaconState, error) {
// if the minimum genesis time arrived already. // if the minimum genesis time arrived already.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def is_valid_genesis_state(state: BeaconState) -> bool: //
// if state.genesis_time < MIN_GENESIS_TIME: // def is_valid_genesis_state(state: BeaconState) -> bool:
// return False // if state.genesis_time < MIN_GENESIS_TIME:
// if len(get_active_validator_indices(state, GENESIS_EPOCH)) < MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: // return False
// return False // if len(get_active_validator_indices(state, GENESIS_EPOCH)) < MIN_GENESIS_ACTIVE_VALIDATOR_COUNT:
// return True // return False
// return True
//
// This method has been modified from the spec to allow whole states not to be saved // This method has been modified from the spec to allow whole states not to be saved
// but instead only cache the relevant information. // but instead only cache the relevant information.
func IsValidGenesisState(chainStartDepositCount, currentTime uint64) bool { func IsValidGenesisState(chainStartDepositCount, currentTime uint64) bool {

View File

@ -33,18 +33,19 @@ import (
// See: ExecuteStateTransitionNoVerifyAnySig // See: ExecuteStateTransitionNoVerifyAnySig
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def state_transition(state: BeaconState, signed_block: SignedBeaconBlock, validate_result: bool=True) -> None: //
// block = signed_block.message // def state_transition(state: BeaconState, signed_block: SignedBeaconBlock, validate_result: bool=True) -> None:
// # Process slots (including those with no blocks) since block // block = signed_block.message
// process_slots(state, block.slot) // # Process slots (including those with no blocks) since block
// # Verify signature // process_slots(state, block.slot)
// if validate_result: // # Verify signature
// assert verify_block_signature(state, signed_block) // if validate_result:
// # Process block // assert verify_block_signature(state, signed_block)
// process_block(state, block) // # Process block
// # Verify state root // process_block(state, block)
// if validate_result: // # Verify state root
// assert block.state_root == hash_tree_root(state) // if validate_result:
// assert block.state_root == hash_tree_root(state)
func ExecuteStateTransition( func ExecuteStateTransition(
ctx context.Context, ctx context.Context,
state state.BeaconState, state state.BeaconState,
@ -80,16 +81,16 @@ func ExecuteStateTransition(
// It happens regardless if there's an incoming block or not. // It happens regardless if there's an incoming block or not.
// Spec pseudocode definition: // Spec pseudocode definition:
// //
// def process_slot(state: BeaconState) -> None: // def process_slot(state: BeaconState) -> None:
// # Cache state root // # Cache state root
// previous_state_root = hash_tree_root(state) // previous_state_root = hash_tree_root(state)
// state.state_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_state_root // state.state_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_state_root
// # Cache latest block header state root // # Cache latest block header state root
// if state.latest_block_header.state_root == Bytes32(): // if state.latest_block_header.state_root == Bytes32():
// state.latest_block_header.state_root = previous_state_root // state.latest_block_header.state_root = previous_state_root
// # Cache block root // # Cache block root
// previous_block_root = hash_tree_root(state.latest_block_header) // previous_block_root = hash_tree_root(state.latest_block_header)
// state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root // state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root
func ProcessSlot(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { func ProcessSlot(ctx context.Context, state state.BeaconState) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlot") ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlot")
defer span.End() defer span.End()
@ -177,14 +178,15 @@ func ProcessSlotsIfPossible(ctx context.Context, state state.BeaconState, target
// ProcessSlots process through skip slots and apply epoch transition when it's needed // ProcessSlots process through skip slots and apply epoch transition when it's needed
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_slots(state: BeaconState, slot: Slot) -> None: //
// assert state.slot < slot // def process_slots(state: BeaconState, slot: Slot) -> None:
// while state.slot < slot: // assert state.slot < slot
// process_slot(state) // while state.slot < slot:
// # Process epoch on the start slot of the next epoch // process_slot(state)
// if (state.slot + 1) % SLOTS_PER_EPOCH == 0: // # Process epoch on the start slot of the next epoch
// process_epoch(state) // if (state.slot + 1) % SLOTS_PER_EPOCH == 0:
// state.slot = Slot(state.slot + 1) // process_epoch(state)
// state.slot = Slot(state.slot + 1)
func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot) (state.BeaconState, error) { func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlots") ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlots")
defer span.End() defer span.End()

View File

@ -28,18 +28,19 @@ import (
// This method also modifies the passed in state. // This method also modifies the passed in state.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def state_transition(state: BeaconState, signed_block: SignedBeaconBlock, validate_result: bool=True) -> None: //
// block = signed_block.message // def state_transition(state: BeaconState, signed_block: SignedBeaconBlock, validate_result: bool=True) -> None:
// # Process slots (including those with no blocks) since block // block = signed_block.message
// process_slots(state, block.slot) // # Process slots (including those with no blocks) since block
// # Verify signature // process_slots(state, block.slot)
// if validate_result: // # Verify signature
// assert verify_block_signature(state, signed_block) // if validate_result:
// # Process block // assert verify_block_signature(state, signed_block)
// process_block(state, block) // # Process block
// # Verify state root // process_block(state, block)
// if validate_result: // # Verify state root
// assert block.state_root == hash_tree_root(state) // if validate_result:
// assert block.state_root == hash_tree_root(state)
func ExecuteStateTransitionNoVerifyAnySig( func ExecuteStateTransitionNoVerifyAnySig(
ctx context.Context, ctx context.Context,
st state.BeaconState, st state.BeaconState,
@ -94,18 +95,19 @@ func ExecuteStateTransitionNoVerifyAnySig(
// This is used for proposer to compute state root before proposing a new block, and this does not modify state. // This is used for proposer to compute state root before proposing a new block, and this does not modify state.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def state_transition(state: BeaconState, signed_block: SignedBeaconBlock, validate_result: bool=True) -> None: //
// block = signed_block.message // def state_transition(state: BeaconState, signed_block: SignedBeaconBlock, validate_result: bool=True) -> None:
// # Process slots (including those with no blocks) since block // block = signed_block.message
// process_slots(state, block.slot) // # Process slots (including those with no blocks) since block
// # Verify signature // process_slots(state, block.slot)
// if validate_result: // # Verify signature
// assert verify_block_signature(state, signed_block) // if validate_result:
// # Process block // assert verify_block_signature(state, signed_block)
// process_block(state, block) // # Process block
// # Verify state root // process_block(state, block)
// if validate_result: // # Verify state root
// assert block.state_root == hash_tree_root(state) // if validate_result:
// assert block.state_root == hash_tree_root(state)
func CalculateStateRoot( func CalculateStateRoot(
ctx context.Context, ctx context.Context,
state state.BeaconState, state state.BeaconState,
@ -151,11 +153,11 @@ func CalculateStateRoot(
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// //
// def process_block(state: BeaconState, block: BeaconBlock) -> None: // def process_block(state: BeaconState, block: BeaconBlock) -> None:
// process_block_header(state, block) // process_block_header(state, block)
// process_randao(state, block.body) // process_randao(state, block.body)
// process_eth1_data(state, block.body) // process_eth1_data(state, block.body)
// process_operations(state, block.body) // process_operations(state, block.body)
func ProcessBlockNoVerifyAnySig( func ProcessBlockNoVerifyAnySig(
ctx context.Context, ctx context.Context,
st state.BeaconState, st state.BeaconState,
@ -209,19 +211,19 @@ func ProcessBlockNoVerifyAnySig(
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// //
// def process_operations(state: BeaconState, body: BeaconBlockBody) -> None: // def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
// # Verify that outstanding deposits are processed up to the maximum number of deposits // # Verify that outstanding deposits are processed up to the maximum number of deposits
// assert len(body.deposits) == min(MAX_DEPOSITS, state.eth1_data.deposit_count - state.eth1_deposit_index) // assert len(body.deposits) == min(MAX_DEPOSITS, state.eth1_data.deposit_count - state.eth1_deposit_index)
// //
// def for_ops(operations: Sequence[Any], fn: Callable[[BeaconState, Any], None]) -> None: // def for_ops(operations: Sequence[Any], fn: Callable[[BeaconState, Any], None]) -> None:
// for operation in operations: // for operation in operations:
// fn(state, operation) // fn(state, operation)
// //
// for_ops(body.proposer_slashings, process_proposer_slashing) // for_ops(body.proposer_slashings, process_proposer_slashing)
// for_ops(body.attester_slashings, process_attester_slashing) // for_ops(body.attester_slashings, process_attester_slashing)
// for_ops(body.attestations, process_attestation) // for_ops(body.attestations, process_attestation)
// for_ops(body.deposits, process_deposit) // for_ops(body.deposits, process_deposit)
// for_ops(body.voluntary_exits, process_voluntary_exit) // for_ops(body.voluntary_exits, process_voluntary_exit)
func ProcessOperationsNoVerifyAttsSigs( func ProcessOperationsNoVerifyAttsSigs(
ctx context.Context, ctx context.Context,
state state.BeaconState, state state.BeaconState,
@ -260,13 +262,14 @@ func ProcessOperationsNoVerifyAttsSigs(
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def process_block(state: BeaconState, block: BeaconBlock) -> None: // def process_block(state: BeaconState, block: BeaconBlock) -> None:
// process_block_header(state, block) //
// if is_execution_enabled(state, block.body): // process_block_header(state, block)
// process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [New in Bellatrix] // if is_execution_enabled(state, block.body):
// process_randao(state, block.body) // process_execution_payload(state, block.body.execution_payload, EXECUTION_ENGINE) # [New in Bellatrix]
// process_eth1_data(state, block.body) // process_randao(state, block.body)
// process_operations(state, block.body) // process_eth1_data(state, block.body)
// process_sync_aggregate(state, block.body.sync_aggregate) // process_operations(state, block.body)
// process_sync_aggregate(state, block.body.sync_aggregate)
func ProcessBlockForStateRoot( func ProcessBlockForStateRoot(
ctx context.Context, ctx context.Context,
state state.BeaconState, state state.BeaconState,

View File

@ -22,25 +22,26 @@ import (
// validator with correct voluntary exit parameters. // validator with correct voluntary exit parameters.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None:
// """
// Initiate the exit of the validator with index ``index``.
// """
// # Return if validator already initiated exit
// validator = state.validators[index]
// if validator.exit_epoch != FAR_FUTURE_EPOCH:
// return
// //
// # Compute exit queue epoch // def initiate_validator_exit(state: BeaconState, index: ValidatorIndex) -> None:
// exit_epochs = [v.exit_epoch for v in state.validators if v.exit_epoch != FAR_FUTURE_EPOCH] // """
// exit_queue_epoch = max(exit_epochs + [compute_activation_exit_epoch(get_current_epoch(state))]) // Initiate the exit of the validator with index ``index``.
// exit_queue_churn = len([v for v in state.validators if v.exit_epoch == exit_queue_epoch]) // """
// if exit_queue_churn >= get_validator_churn_limit(state): // # Return if validator already initiated exit
// exit_queue_epoch += Epoch(1) // validator = state.validators[index]
// if validator.exit_epoch != FAR_FUTURE_EPOCH:
// return
// //
// # Set validator exit epoch and withdrawable epoch // # Compute exit queue epoch
// validator.exit_epoch = exit_queue_epoch // exit_epochs = [v.exit_epoch for v in state.validators if v.exit_epoch != FAR_FUTURE_EPOCH]
// validator.withdrawable_epoch = Epoch(validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY) // exit_queue_epoch = max(exit_epochs + [compute_activation_exit_epoch(get_current_epoch(state))])
// exit_queue_churn = len([v for v in state.validators if v.exit_epoch == exit_queue_epoch])
// if exit_queue_churn >= get_validator_churn_limit(state):
// exit_queue_epoch += Epoch(1)
//
// # Set validator exit epoch and withdrawable epoch
// validator.exit_epoch = exit_queue_epoch
// validator.withdrawable_epoch = Epoch(validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
func InitiateValidatorExit(ctx context.Context, s state.BeaconState, idx types.ValidatorIndex) (state.BeaconState, error) { func InitiateValidatorExit(ctx context.Context, s state.BeaconState, idx types.ValidatorIndex) (state.BeaconState, error) {
validator, err := s.ValidatorAtIndex(idx) validator, err := s.ValidatorAtIndex(idx)
if err != nil { if err != nil {
@ -114,28 +115,29 @@ func InitiateValidatorExit(ctx context.Context, s state.BeaconState, idx types.V
// the whistleblower's balance. // the whistleblower's balance.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def slash_validator(state: BeaconState,
// slashed_index: ValidatorIndex,
// whistleblower_index: ValidatorIndex=None) -> None:
// """
// Slash the validator with index ``slashed_index``.
// """
// epoch = get_current_epoch(state)
// initiate_validator_exit(state, slashed_index)
// validator = state.validators[slashed_index]
// validator.slashed = True
// validator.withdrawable_epoch = max(validator.withdrawable_epoch, Epoch(epoch + EPOCHS_PER_SLASHINGS_VECTOR))
// state.slashings[epoch % EPOCHS_PER_SLASHINGS_VECTOR] += validator.effective_balance
// decrease_balance(state, slashed_index, validator.effective_balance // MIN_SLASHING_PENALTY_QUOTIENT)
// //
// # Apply proposer and whistleblower rewards // def slash_validator(state: BeaconState,
// proposer_index = get_beacon_proposer_index(state) // slashed_index: ValidatorIndex,
// if whistleblower_index is None: // whistleblower_index: ValidatorIndex=None) -> None:
// whistleblower_index = proposer_index // """
// whistleblower_reward = Gwei(validator.effective_balance // WHISTLEBLOWER_REWARD_QUOTIENT) // Slash the validator with index ``slashed_index``.
// proposer_reward = Gwei(whistleblower_reward // PROPOSER_REWARD_QUOTIENT) // """
// increase_balance(state, proposer_index, proposer_reward) // epoch = get_current_epoch(state)
// increase_balance(state, whistleblower_index, Gwei(whistleblower_reward - proposer_reward)) // initiate_validator_exit(state, slashed_index)
// validator = state.validators[slashed_index]
// validator.slashed = True
// validator.withdrawable_epoch = max(validator.withdrawable_epoch, Epoch(epoch + EPOCHS_PER_SLASHINGS_VECTOR))
// state.slashings[epoch % EPOCHS_PER_SLASHINGS_VECTOR] += validator.effective_balance
// decrease_balance(state, slashed_index, validator.effective_balance // MIN_SLASHING_PENALTY_QUOTIENT)
//
// # Apply proposer and whistleblower rewards
// proposer_index = get_beacon_proposer_index(state)
// if whistleblower_index is None:
// whistleblower_index = proposer_index
// whistleblower_reward = Gwei(validator.effective_balance // WHISTLEBLOWER_REWARD_QUOTIENT)
// proposer_reward = Gwei(whistleblower_reward // PROPOSER_REWARD_QUOTIENT)
// increase_balance(state, proposer_index, proposer_reward)
// increase_balance(state, whistleblower_index, Gwei(whistleblower_reward - proposer_reward))
func SlashValidator( func SlashValidator(
ctx context.Context, ctx context.Context,
s state.BeaconState, s state.BeaconState,

View File

@ -3,15 +3,15 @@
// For example, one can specify a filter query for data by start epoch + end epoch + shard // For example, one can specify a filter query for data by start epoch + end epoch + shard
// for attestations, build a filter as follows, and respond to it accordingly: // for attestations, build a filter as follows, and respond to it accordingly:
// //
// f := filters.NewFilter().SetStartEpoch(3).SetEndEpoch(5) // f := filters.NewFilter().SetStartEpoch(3).SetEndEpoch(5)
// for k, v := range f.Filters() { // for k, v := range f.Filters() {
// switch k { // switch k {
// case filters.StartEpoch: // case filters.StartEpoch:
// // Verify data matches filter criteria... // // Verify data matches filter criteria...
// case filters.EndEpoch: // case filters.EndEpoch:
// // Verify data matches filter criteria... // // Verify data matches filter criteria...
// } // }
// } // }
package filters package filters
import types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" import types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"

View File

@ -76,7 +76,9 @@ func TestStore_IsFinalizedBlockGenesis(t *testing.T) {
// Example: // Example:
// 0 1 2 3 4 5 6 slot // 0 1 2 3 4 5 6 slot
// a <- b <-- d <- e <- f <- g roots // a <- b <-- d <- e <- f <- g roots
// ^- c //
// ^- c
//
// Imagine that epochs are 2 slots and that epoch 1, 2, and 3 are finalized. Checkpoint roots would // Imagine that epochs are 2 slots and that epoch 1, 2, and 3 are finalized. Checkpoint roots would
// be c, e, and g. In this scenario, c was a finalized checkpoint root but no block built upon it so // be c, e, and g. In this scenario, c was a finalized checkpoint root but no block built upon it so
// it should not be considered "final and canonical" in the view at slot 6. // it should not be considered "final and canonical" in the view at slot 6.

View File

@ -214,15 +214,16 @@ func (s *Service) ExchangeTransitionConfiguration(
// //
// Spec code: // Spec code:
// def get_pow_block_at_terminal_total_difficulty(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]: // def get_pow_block_at_terminal_total_difficulty(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]:
// # `pow_chain` abstractly represents all blocks in the PoW chain
// for block in pow_chain:
// parent = pow_chain[block.parent_hash]
// block_reached_ttd = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
// parent_reached_ttd = parent.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
// if block_reached_ttd and not parent_reached_ttd:
// return block
// //
// return None // # `pow_chain` abstractly represents all blocks in the PoW chain
// for block in pow_chain:
// parent = pow_chain[block.parent_hash]
// block_reached_ttd = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
// parent_reached_ttd = parent.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
// if block_reached_ttd and not parent_reached_ttd:
// return block
//
// return None
func (s *Service) GetTerminalBlockHash(ctx context.Context, transitionTime uint64) ([]byte, bool, error) { func (s *Service) GetTerminalBlockHash(ctx context.Context, transitionTime uint64) ([]byte, bool, error) {
ttd := new(big.Int) ttd := new(big.Int)
ttd.SetString(params.BeaconConfig().TerminalTotalDifficulty, 10) ttd.SetString(params.BeaconConfig().TerminalTotalDifficulty, 10)

View File

@ -15,20 +15,21 @@ import (
// This should only be called at the start of every slot interval. // This should only be called at the start of every slot interval.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// # Reset store.proposer_boost_root if this is a new slot
// if current_slot > previous_slot:
// store.proposer_boost_root = Root()
// //
// # Not a new epoch, return // # Reset store.proposer_boost_root if this is a new slot
// if not (current_slot > previous_slot and compute_slots_since_epoch_start(current_slot) == 0): // if current_slot > previous_slot:
// return // store.proposer_boost_root = Root()
// //
// # Update store.justified_checkpoint if a better checkpoint on the store.finalized_checkpoint chain // # Not a new epoch, return
// if store.best_justified_checkpoint.epoch > store.justified_checkpoint.epoch: // if not (current_slot > previous_slot and compute_slots_since_epoch_start(current_slot) == 0):
// finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch) // return
// ancestor_at_finalized_slot = get_ancestor(store, store.best_justified_checkpoint.root, finalized_slot) //
// if ancestor_at_finalized_slot == store.finalized_checkpoint.root: // # Update store.justified_checkpoint if a better checkpoint on the store.finalized_checkpoint chain
// store.justified_checkpoint = store.best_justified_checkpoint // if store.best_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
// finalized_slot = compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)
// ancestor_at_finalized_slot = get_ancestor(store, store.best_justified_checkpoint.root, finalized_slot)
// if ancestor_at_finalized_slot == store.finalized_checkpoint.root:
// store.justified_checkpoint = store.best_justified_checkpoint
func (f *ForkChoice) NewSlot(ctx context.Context, slot types.Slot) error { func (f *ForkChoice) NewSlot(ctx context.Context, slot types.Slot) error {
// Reset proposer boost root // Reset proposer boost root
if err := f.ResetBoostedProposerRoot(ctx); err != nil { if err := f.ResetBoostedProposerRoot(ctx); err != nil {

View File

@ -13,16 +13,15 @@ import (
// We test the algorithm to update a node from SYNCING to INVALID // We test the algorithm to update a node from SYNCING to INVALID
// We start with the same diagram as above: // We start with the same diagram as above:
// //
// E -- F // E -- F
// / // /
// C -- D // C -- D
// / \ // / \
// A -- B G -- H -- I // A -- B G -- H -- I
// \ \ // \ \
// J -- K -- L // J -- K -- L
// //
// And every block in the Fork choice is optimistic. // And every block in the Fork choice is optimistic.
//
func TestPruneInvalid(t *testing.T) { func TestPruneInvalid(t *testing.T) {
tests := []struct { tests := []struct {
root [32]byte // the root of the new INVALID block root [32]byte // the root of the new INVALID block
@ -286,12 +285,12 @@ func TestSetOptimisticToInvalid_CorrectChildren(t *testing.T) {
// Pow | Pos // Pow | Pos
// //
// CA -- A -- B -- C-----D // CA -- A -- B -- C-----D
// \ \--------------E // \ \--------------E
// \ // \
// ----------------------F -- G // ----------------------F -- G
// B is INVALID
// //
// B is INVALID
func TestSetOptimisticToInvalid_ForkAtMerge(t *testing.T) { func TestSetOptimisticToInvalid_ForkAtMerge(t *testing.T) {
ctx := context.Background() ctx := context.Background()
f := setup(1, 1) f := setup(1, 1)
@ -339,12 +338,12 @@ func TestSetOptimisticToInvalid_ForkAtMerge(t *testing.T) {
// Pow | Pos // Pow | Pos
// //
// CA -------- B -- C-----D // CA -------- B -- C-----D
// \ \--------------E // \ \--------------E
// \ // \
// --A -------------------------F -- G // --A -------------------------F -- G
// B is INVALID
// //
// B is INVALID
func TestSetOptimisticToInvalid_ForkAtMerge_bis(t *testing.T) { func TestSetOptimisticToInvalid_ForkAtMerge_bis(t *testing.T) {
ctx := context.Background() ctx := context.Background()
f := setup(1, 1) f := setup(1, 1)

View File

@ -215,8 +215,9 @@ func TestStore_Prune_ReturnEarly(t *testing.T) {
// This unit tests starts with a simple branch like this // This unit tests starts with a simple branch like this
// //
// - 1 // - 1
// / // /
//
// -- 0 -- 2 // -- 0 -- 2
// //
// And we finalize 1. As a result only 1 should survive // And we finalize 1. As a result only 1 should survive
@ -237,17 +238,15 @@ func TestStore_Prune_NoDanglingBranch(t *testing.T) {
} }
// This test starts with the following branching diagram // This test starts with the following branching diagram
/// We start with the following diagram // / We start with the following diagram
//
// E -- F
// /
// C -- D
// / \
// A -- B G -- H -- I
// \ \
// J -- K -- L
//
// //
// E -- F
// /
// C -- D
// / \
// A -- B G -- H -- I
// \ \
// J -- K -- L
func TestStore_tips(t *testing.T) { func TestStore_tips(t *testing.T) {
ctx := context.Background() ctx := context.Background()
f := setup(1, 1) f := setup(1, 1)

View File

@ -53,17 +53,18 @@ func TestStore_UpdateUnrealizedCheckpoints(t *testing.T) {
} }
// Epoch 2 | Epoch 3
// //
// Epoch 2 | Epoch 3 // |
// | // C |
// C | // / |
// / |
// A <-- B |
// \ |
// ---- D
// //
// B is the first block that justifies A. // A <-- B |
// //
// \ |
// ---- D
//
// B is the first block that justifies A.
func TestStore_LongFork(t *testing.T) { func TestStore_LongFork(t *testing.T) {
f := setup(1, 1) f := setup(1, 1)
ctx := context.Background() ctx := context.Background()
@ -104,18 +105,17 @@ func TestStore_LongFork(t *testing.T) {
require.Equal(t, [32]byte{'c'}, headRoot) require.Equal(t, [32]byte{'c'}, headRoot)
} }
// Epoch 1 Epoch 2 Epoch 3
// | |
// | |
// //
// A <-- B <-- C <-- D <-- E <-- F <-- G <-- H |
// //
// Epoch 1 Epoch 2 Epoch 3 // | \ |
// | | // | --------------- I
// | | // | |
// A <-- B <-- C <-- D <-- E <-- F <-- G <-- H |
// | \ |
// | --------------- I
// | |
//
// E justifies A. G justifies E.
// //
// E justifies A. G justifies E.
func TestStore_NoDeadLock(t *testing.T) { func TestStore_NoDeadLock(t *testing.T) {
f := setup(0, 0) f := setup(0, 0)
ctx := context.Background() ctx := context.Background()
@ -187,17 +187,16 @@ func TestStore_NoDeadLock(t *testing.T) {
require.Equal(t, types.Epoch(1), f.FinalizedCheckpoint().Epoch) require.Equal(t, types.Epoch(1), f.FinalizedCheckpoint().Epoch)
} }
// Epoch 1 | Epoch 2 // Epoch 1 | Epoch 2
// | // |
// -- D (late) // -- D (late)
// / | // / |
// A <- B <- C | // A <- B <- C |
// \ | // \ |
// -- -- -- E <- F <- G <- H // -- -- -- E <- F <- G <- H
// | // |
// //
// D justifies and comes late. // D justifies and comes late.
//
func TestStore_ForkNextEpoch(t *testing.T) { func TestStore_ForkNextEpoch(t *testing.T) {
resetCfg := features.InitWithReset(&features.Flags{ resetCfg := features.InitWithReset(&features.Flags{
EnableDefensivePull: true, EnableDefensivePull: true,

View File

@ -283,12 +283,13 @@ func (ns *Server) GetSyncStatus(ctx context.Context, _ *emptypb.Empty) (*ethpb.S
// GetHealth returns node health status in http status codes. Useful for load balancers. // GetHealth returns node health status in http status codes. Useful for load balancers.
// Response Usage: // Response Usage:
// "200": //
// description: Node is ready // "200":
// "206": // description: Node is ready
// description: Node is syncing but can serve incomplete data // "206":
// "503": // description: Node is syncing but can serve incomplete data
// description: Node not initialized or having issues // "503":
// description: Node not initialized or having issues
func (ns *Server) GetHealth(ctx context.Context, _ *emptypb.Empty) (*emptypb.Empty, error) { func (ns *Server) GetHealth(ctx context.Context, _ *emptypb.Empty) (*emptypb.Empty, error) {
ctx, span := trace.StartSpan(ctx, "node.GetHealth") ctx, span := trace.StartSpan(ctx, "node.GetHealth")
defer span.End() defer span.End()

View File

@ -20,16 +20,16 @@ import (
// eth1DataMajorityVote determines the appropriate eth1data for a block proposal using // eth1DataMajorityVote determines the appropriate eth1data for a block proposal using
// an algorithm called Voting with the Majority. The algorithm works as follows: // an algorithm called Voting with the Majority. The algorithm works as follows:
// - Determine the timestamp for the start slot for the eth1 voting period. // - Determine the timestamp for the start slot for the eth1 voting period.
// - Determine the earliest and latest timestamps that a valid block can have. // - Determine the earliest and latest timestamps that a valid block can have.
// - Determine the first block not before the earliest timestamp. This block is the lower bound. // - Determine the first block not before the earliest timestamp. This block is the lower bound.
// - Determine the last block not after the latest timestamp. This block is the upper bound. // - Determine the last block not after the latest timestamp. This block is the upper bound.
// - If the last block is too early, use current eth1data from the beacon state. // - If the last block is too early, use current eth1data from the beacon state.
// - Filter out votes on unknown blocks and blocks which are outside of the range determined by the lower and upper bounds. // - Filter out votes on unknown blocks and blocks which are outside of the range determined by the lower and upper bounds.
// - If no blocks are left after filtering votes, use eth1data from the latest valid block. // - If no blocks are left after filtering votes, use eth1data from the latest valid block.
// - Otherwise: // - Otherwise:
// - Determine the vote with the highest count. Prefer the vote with the highest eth1 block height in the event of a tie. // - Determine the vote with the highest count. Prefer the vote with the highest eth1 block height in the event of a tie.
// - This vote's block is the eth1 block to use for the block proposal. // - This vote's block is the eth1 block to use for the block proposal.
func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState state.BeaconState) (*ethpb.Eth1Data, error) { func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState state.BeaconState) (*ethpb.Eth1Data, error) {
ctx, cancel := context.WithTimeout(ctx, eth1dataTimeout) ctx, cancel := context.WithTimeout(ctx, eth1dataTimeout)
defer cancel() defer cancel()

View File

@ -186,14 +186,15 @@ func warnIfFeeRecipientDiffers(payload *enginev1.ExecutionPayload, feeRecipient
// //
// Spec code: // Spec code:
// def get_terminal_pow_block(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]: // def get_terminal_pow_block(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]:
// if TERMINAL_BLOCK_HASH != Hash32():
// # Terminal block hash override takes precedence over terminal total difficulty
// if TERMINAL_BLOCK_HASH in pow_chain:
// return pow_chain[TERMINAL_BLOCK_HASH]
// else:
// return None
// //
// return get_pow_block_at_terminal_total_difficulty(pow_chain) // if TERMINAL_BLOCK_HASH != Hash32():
// # Terminal block hash override takes precedence over terminal total difficulty
// if TERMINAL_BLOCK_HASH in pow_chain:
// return pow_chain[TERMINAL_BLOCK_HASH]
// else:
// return None
//
// return get_pow_block_at_terminal_total_difficulty(pow_chain)
func (vs *Server) getTerminalBlockHashIfExists(ctx context.Context, transitionTime uint64) ([]byte, bool, error) { func (vs *Server) getTerminalBlockHashIfExists(ctx context.Context, transitionTime uint64) ([]byte, bool, error) {
terminalBlockHash := params.BeaconConfig().TerminalBlockHash terminalBlockHash := params.BeaconConfig().TerminalBlockHash
// Terminal block hash override takes precedence over terminal total difficulty. // Terminal block hash override takes precedence over terminal total difficulty.
@ -214,10 +215,11 @@ func (vs *Server) getTerminalBlockHashIfExists(ctx context.Context, transitionTi
// activationEpochNotReached returns true if activation epoch has not been reach. // activationEpochNotReached returns true if activation epoch has not been reach.
// Which satisfy the following conditions in spec: // Which satisfy the following conditions in spec:
// is_terminal_block_hash_set = TERMINAL_BLOCK_HASH != Hash32() //
// is_activation_epoch_reached = get_current_epoch(state) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH // is_terminal_block_hash_set = TERMINAL_BLOCK_HASH != Hash32()
// if is_terminal_block_hash_set and not is_activation_epoch_reached: // is_activation_epoch_reached = get_current_epoch(state) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
// return True // if is_terminal_block_hash_set and not is_activation_epoch_reached:
// return True
func activationEpochNotReached(slot types.Slot) bool { func activationEpochNotReached(slot types.Slot) bool {
terminalBlockHashSet := bytesutil.ToBytes32(params.BeaconConfig().TerminalBlockHash.Bytes()) != [32]byte{} terminalBlockHashSet := bytesutil.ToBytes32(params.BeaconConfig().TerminalBlockHash.Bytes()) != [32]byte{}
if terminalBlockHashSet { if terminalBlockHashSet {

View File

@ -87,12 +87,12 @@ type StateProvider struct {
} }
// State returns the BeaconState for a given identifier. The identifier can be one of: // State returns the BeaconState for a given identifier. The identifier can be one of:
// - "head" (canonical head in node's view) // - "head" (canonical head in node's view)
// - "genesis" // - "genesis"
// - "finalized" // - "finalized"
// - "justified" // - "justified"
// - <slot> // - <slot>
// - <hex encoded state root with '0x' prefix> // - <hex encoded state root with '0x' prefix>
func (p *StateProvider) State(ctx context.Context, stateId []byte) (state.BeaconState, error) { func (p *StateProvider) State(ctx context.Context, stateId []byte) (state.BeaconState, error) {
var ( var (
s state.BeaconState s state.BeaconState
@ -141,12 +141,12 @@ func (p *StateProvider) State(ctx context.Context, stateId []byte) (state.Beacon
} }
// StateRoot returns a beacon state root for a given identifier. The identifier can be one of: // StateRoot returns a beacon state root for a given identifier. The identifier can be one of:
// - "head" (canonical head in node's view) // - "head" (canonical head in node's view)
// - "genesis" // - "genesis"
// - "finalized" // - "finalized"
// - "justified" // - "justified"
// - <slot> // - <slot>
// - <hex encoded state root with '0x' prefix> // - <hex encoded state root with '0x' prefix>
func (p *StateProvider) StateRoot(ctx context.Context, stateId []byte) (root []byte, err error) { func (p *StateProvider) StateRoot(ctx context.Context, stateId []byte) (root []byte, err error) {
stateIdString := strings.ToLower(string(stateId)) stateIdString := strings.ToLower(string(stateId))
switch stateIdString { switch stateIdString {

View File

@ -56,29 +56,29 @@ type Chunker interface {
// Under ideal network conditions, where every target epoch immediately follows its source, // Under ideal network conditions, where every target epoch immediately follows its source,
// min spans for a validator will look as follows: // min spans for a validator will look as follows:
// //
// min_spans = [2, 2, 2, ..., 2] // min_spans = [2, 2, 2, ..., 2]
// //
// Next, we can chunk this list of min spans into chunks of length C. For C = 2, for example: // Next, we can chunk this list of min spans into chunks of length C. For C = 2, for example:
// //
// chunk0 chunk1 chunkN // chunk0 chunk1 chunkN
// { } { } { } // { } { } { }
// chunked_min_spans = [[2, 2], [2, 2], ..., [2, 2]] // chunked_min_spans = [[2, 2], [2, 2], ..., [2, 2]]
// //
// Finally, we can store each chunk index for K validators into a single flat slice. For K = 3: // Finally, we can store each chunk index for K validators into a single flat slice. For K = 3:
// //
// val0 val1 val2 // val0 val1 val2
// { } { } { } // { } { } { }
// chunk_0_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]] // chunk_0_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]]
// //
// val0 val1 val2 // val0 val1 val2
// { } { } { } // { } { } { }
// chunk_1_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]] // chunk_1_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]]
// //
// ... // ...
// //
// val0 val1 val2 // val0 val1 val2
// { } { } { } // { } { } { }
// chunk_N_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]] // chunk_N_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]]
// //
// MinSpanChunksSlice represents the data structure above for a single chunk index. // MinSpanChunksSlice represents the data structure above for a single chunk index.
type MinSpanChunksSlice struct { type MinSpanChunksSlice struct {
@ -175,7 +175,7 @@ func (m *MaxSpanChunksSlice) Chunk() []uint16 {
// within the min span chunks slice. Recall that for an incoming attestation, B, and an // within the min span chunks slice. Recall that for an incoming attestation, B, and an
// existing attestation, A: // existing attestation, A:
// //
// B surrounds A if and only if B.target > min_spans[B.source] // B surrounds A if and only if B.target > min_spans[B.source]
// //
// That is, this condition is sufficient to check if an incoming attestation // That is, this condition is sufficient to check if an incoming attestation
// is surrounding a previous one. We also check if we indeed have an existing // is surrounding a previous one. We also check if we indeed have an existing
@ -222,7 +222,7 @@ func (m *MinSpanChunksSlice) CheckSlashable(
// within the max span chunks slice. Recall that for an incoming attestation, B, and an // within the max span chunks slice. Recall that for an incoming attestation, B, and an
// existing attestation, A: // existing attestation, A:
// //
// B surrounds A if and only if B.target < max_spans[B.source] // B surrounds A if and only if B.target < max_spans[B.source]
// //
// That is, this condition is sufficient to check if an incoming attestation // That is, this condition is sufficient to check if an incoming attestation
// is surrounded by a previous one. We also check if we indeed have an existing // is surrounded by a previous one. We also check if we indeed have an existing
@ -278,19 +278,19 @@ func (m *MaxSpanChunksSlice) CheckSlashable(
// Recall that a MinSpanChunksSlice struct represents a single slice for a chunk index // Recall that a MinSpanChunksSlice struct represents a single slice for a chunk index
// from the collection below: // from the collection below:
// //
// val0 val1 val2 // val0 val1 val2
// { } { } { } // { } { } { }
// chunk_0_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]] // chunk_0_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]]
// //
// val0 val1 val2 // val0 val1 val2
// { } { } { } // { } { } { }
// chunk_1_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]] // chunk_1_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]]
// //
// ... // ...
// //
// val0 val1 val2 // val0 val1 val2
// { } { } { } // { } { } { }
// chunk_N_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]] // chunk_N_for_validators_0_to_2 = [[2, 2], [2, 2], [2, 2]]
// //
// Let's take a look at how this update will look for a real set of min span chunk: // Let's take a look at how this update will look for a real set of min span chunk:
// For the purposes of a simple example, let's set H = 2, meaning a min span // For the purposes of a simple example, let's set H = 2, meaning a min span
@ -301,12 +301,11 @@ func (m *MaxSpanChunksSlice) CheckSlashable(
// 4 down to 3. First, we find out which chunk epoch 4 falls into, which is calculated as: // 4 down to 3. First, we find out which chunk epoch 4 falls into, which is calculated as:
// chunk_idx = (epoch % H) / C = (4 % 2) / 2 = 0 // chunk_idx = (epoch % H) / C = (4 % 2) / 2 = 0
// //
// // val0 val1 val2
// val0 val1 val2 // { } { } { }
// { } { } { } // chunk_0_for_validators_0_to_3 = [[2, 2], [2, 2], [2, 2]]
// chunk_0_for_validators_0_to_3 = [[2, 2], [2, 2], [2, 2]] // |
// | // |-> epoch 4 for validator 0
// |-> epoch 4 for validator 0
// //
// Next up, we proceed with the update process for validator index 0, starting at epoch 4 // Next up, we proceed with the update process for validator index 0, starting at epoch 4
// all the way down to epoch 2. We will need to go down the array as far as we can get. If the // all the way down to epoch 2. We will need to go down the array as far as we can get. If the
@ -452,18 +451,18 @@ func (_ *MaxSpanChunksSlice) StartEpoch(
// NextChunkStartEpoch given an epoch, determines the start epoch of the next chunk. For min // NextChunkStartEpoch given an epoch, determines the start epoch of the next chunk. For min
// span chunks, this will be the last epoch of chunk index = (current chunk - 1). For example: // span chunks, this will be the last epoch of chunk index = (current chunk - 1). For example:
// //
// chunk0 chunk1 chunk2 // chunk0 chunk1 chunk2
// | | | // | | |
// max_spans_val_i = [[-, -, -], [-, -, -], [-, -, -]] // max_spans_val_i = [[-, -, -], [-, -, -], [-, -, -]]
// //
// If C = chunkSize is 3 epochs per chunk, and we input start epoch of chunk 1 which is 3 then the next start // If C = chunkSize is 3 epochs per chunk, and we input start epoch of chunk 1 which is 3 then the next start
// epoch is the last epoch of chunk 0, which is epoch 2. This is computed as: // epoch is the last epoch of chunk 0, which is epoch 2. This is computed as:
// //
// last_epoch(chunkIndex(startEpoch)-1) // last_epoch(chunkIndex(startEpoch)-1)
// last_epoch(chunkIndex(3) - 1) // last_epoch(chunkIndex(3) - 1)
// last_epoch(1 - 1) // last_epoch(1 - 1)
// last_epoch(0) // last_epoch(0)
// 2 // 2
func (m *MinSpanChunksSlice) NextChunkStartEpoch(startEpoch types.Epoch) types.Epoch { func (m *MinSpanChunksSlice) NextChunkStartEpoch(startEpoch types.Epoch) types.Epoch {
prevChunkIdx := m.params.chunkIndex(startEpoch) prevChunkIdx := m.params.chunkIndex(startEpoch)
if prevChunkIdx > 0 { if prevChunkIdx > 0 {
@ -475,18 +474,18 @@ func (m *MinSpanChunksSlice) NextChunkStartEpoch(startEpoch types.Epoch) types.E
// NextChunkStartEpoch given an epoch, determines the start epoch of the next chunk. For max // NextChunkStartEpoch given an epoch, determines the start epoch of the next chunk. For max
// span chunks, this will be the start epoch of chunk index = (current chunk + 1). For example: // span chunks, this will be the start epoch of chunk index = (current chunk + 1). For example:
// //
// chunk0 chunk1 chunk2 // chunk0 chunk1 chunk2
// | | | // | | |
// max_spans_val_i = [[-, -, -], [-, -, -], [-, -, -]] // max_spans_val_i = [[-, -, -], [-, -, -], [-, -, -]]
// //
// If C = chunkSize is 3 epochs per chunk, and we input start epoch of chunk 1 which is 3. The next start // If C = chunkSize is 3 epochs per chunk, and we input start epoch of chunk 1 which is 3. The next start
// epoch is the start epoch of chunk 2, which is epoch 4. This is computed as: // epoch is the start epoch of chunk 2, which is epoch 4. This is computed as:
// //
// first_epoch(chunkIndex(startEpoch)+1) // first_epoch(chunkIndex(startEpoch)+1)
// first_epoch(chunkIndex(3)+1) // first_epoch(chunkIndex(3)+1)
// first_epoch(1 + 1) // first_epoch(1 + 1)
// first_epoch(2) // first_epoch(2)
// 4 // 4
func (m *MaxSpanChunksSlice) NextChunkStartEpoch(startEpoch types.Epoch) types.Epoch { func (m *MaxSpanChunksSlice) NextChunkStartEpoch(startEpoch types.Epoch) types.Epoch {
return m.params.firstEpoch(m.params.chunkIndex(startEpoch) + 1) return m.params.firstEpoch(m.params.chunkIndex(startEpoch) + 1)
} }

View File

@ -72,11 +72,11 @@ func (s *Service) checkSlashableAttestations(
// as the current epoch in time, we perform slashing detection. // as the current epoch in time, we perform slashing detection.
// The process is as follows given a list of attestations: // The process is as follows given a list of attestations:
// //
// 1. Check for attester double votes using the list of attestations. // 1. Check for attester double votes using the list of attestations.
// 2. Group the attestations by chunk index. // 2. Group the attestations by chunk index.
// 3. Update the min and max spans for those grouped attestations, check if any slashings are // 3. Update the min and max spans for those grouped attestations, check if any slashings are
// found in the process // found in the process
// 4. Update the latest written epoch for all validators involved to the current epoch. // 4. Update the latest written epoch for all validators involved to the current epoch.
// //
// This function performs a lot of critical actions and is split into smaller helpers for cleanliness. // This function performs a lot of critical actions and is split into smaller helpers for cleanliness.
func (s *Service) detectAllAttesterSlashings( func (s *Service) detectAllAttesterSlashings(
@ -239,13 +239,13 @@ func (s *Service) epochUpdateForValidator(
} }
// Updates spans and detects any slashable attester offenses along the way. // Updates spans and detects any slashable attester offenses along the way.
// 1. Determine the chunks we need to use for updating for the validator indices // 1. Determine the chunks we need to use for updating for the validator indices
// in a validator chunk index, then retrieve those chunks from the database. // in a validator chunk index, then retrieve those chunks from the database.
// 2. Using the chunks from step (1): // 2. Using the chunks from step (1):
// for every attestation by chunk index: // for every attestation by chunk index:
// for each validator in the attestation's attesting indices: // for each validator in the attestation's attesting indices:
// - Check if the attestation is slashable, if so return a slashing object. // - Check if the attestation is slashable, if so return a slashing object.
// 3. Save the updated chunks to disk. // 3. Save the updated chunks to disk.
func (s *Service) updateSpans( func (s *Service) updateSpans(
ctx context.Context, ctx context.Context,
updatedChunks map[uint64]Chunker, updatedChunks map[uint64]Chunker,

View File

@ -17,25 +17,25 @@
// with length = H where H is the amount of epochs worth of history // with length = H where H is the amount of epochs worth of history
// we want to persist for slashing detection. // we want to persist for slashing detection.
// //
// validator_1_min_span = [2, 2, 2, ..., 2] // validator_1_min_span = [2, 2, 2, ..., 2]
// validator_1_max_span = [0, 0, 0, ..., 0] // validator_1_max_span = [0, 0, 0, ..., 0]
// //
// Instead of always dealing with length H arrays, which can be prohibitively // Instead of always dealing with length H arrays, which can be prohibitively
// expensive to handle in memory, we split these arrays into chunks of length C. // expensive to handle in memory, we split these arrays into chunks of length C.
// For C = 3, for example, the 0th chunk of validator 1's min and max spans would look // For C = 3, for example, the 0th chunk of validator 1's min and max spans would look
// as follows: // as follows:
// //
// validator_1_min_span_chunk_0 = [2, 2, 2] // validator_1_min_span_chunk_0 = [2, 2, 2]
// validator_1_max_span_chunk_0 = [2, 2, 2] // validator_1_max_span_chunk_0 = [2, 2, 2]
// //
// Next, on disk, we take chunks for K validators, and store them as flat slices. // Next, on disk, we take chunks for K validators, and store them as flat slices.
// For example, if H = 3, C = 3, and K = 3, then we can store 3 validators' chunks as a flat // For example, if H = 3, C = 3, and K = 3, then we can store 3 validators' chunks as a flat
// slice as follows: // slice as follows:
// //
// val0 val1 val2 // val0 val1 val2
// | | | // | | |
// { } { } { } // { } { } { }
// [2, 2, 2, 2, 2, 2, 2, 2, 2] // [2, 2, 2, 2, 2, 2, 2, 2, 2]
// //
// This is known as 2D chunking, pioneered by the Sigma Prime team here: // This is known as 2D chunking, pioneered by the Sigma Prime team here:
// https://hackmd.io/@sproul/min-max-slasher. The parameters H, C, and K will be // https://hackmd.io/@sproul/min-max-slasher. The parameters H, C, and K will be

View File

@ -44,10 +44,9 @@ func DefaultParams() *Parameters {
// if we are keeping 6 epochs worth of data, and we have chunks of size 2, then epoch // if we are keeping 6 epochs worth of data, and we have chunks of size 2, then epoch
// 4 will fall into chunk index (4 % 6) / 2 = 2. // 4 will fall into chunk index (4 % 6) / 2 = 2.
// //
// span = [-, -, -, -, -, -] // span = [-, -, -, -, -, -]
// chunked = [[-, -], [-, -], [-, -]] // chunked = [[-, -], [-, -], [-, -]]
// |-> epoch 4, chunk idx 2 // |-> epoch 4, chunk idx 2
//
func (p *Parameters) chunkIndex(epoch types.Epoch) uint64 { func (p *Parameters) chunkIndex(epoch types.Epoch) uint64 {
return uint64(epoch.Mod(uint64(p.historyLength)).Div(p.chunkSize)) return uint64(epoch.Mod(uint64(p.historyLength)).Div(p.chunkSize))
} }
@ -63,12 +62,11 @@ func (p *Parameters) validatorChunkIndex(validatorIndex types.ValidatorIndex) ui
// For example, if we have chunks of length 3 and we ask to give us the // For example, if we have chunks of length 3 and we ask to give us the
// first epoch of chunk1, then: // first epoch of chunk1, then:
// //
// chunk0 chunk1 chunk2 // chunk0 chunk1 chunk2
// | | | // | | |
// [[-, -, -], [-, -, -], [-, -, -], ...] // [[-, -, -], [-, -, -], [-, -, -], ...]
// | // |
// -> first epoch of chunk 1 equals 3 // -> first epoch of chunk 1 equals 3
//
func (p *Parameters) firstEpoch(chunkIndex uint64) types.Epoch { func (p *Parameters) firstEpoch(chunkIndex uint64) types.Epoch {
return types.Epoch(chunkIndex * p.chunkSize) return types.Epoch(chunkIndex * p.chunkSize)
} }
@ -77,12 +75,11 @@ func (p *Parameters) firstEpoch(chunkIndex uint64) types.Epoch {
// For example, if we have chunks of length 3 and we ask to give us the // For example, if we have chunks of length 3 and we ask to give us the
// last epoch of chunk1, then: // last epoch of chunk1, then:
// //
// chunk0 chunk1 chunk2 // chunk0 chunk1 chunk2
// | | | // | | |
// [[-, -, -], [-, -, -], [-, -, -], ...] // [[-, -, -], [-, -, -], [-, -, -], ...]
// | // |
// -> last epoch of chunk 1 equals 5 // -> last epoch of chunk 1 equals 5
//
func (p *Parameters) lastEpoch(chunkIndex uint64) types.Epoch { func (p *Parameters) lastEpoch(chunkIndex uint64) types.Epoch {
return p.firstEpoch(chunkIndex).Add(p.chunkSize - 1) return p.firstEpoch(chunkIndex).Add(p.chunkSize - 1)
} }
@ -92,24 +89,23 @@ func (p *Parameters) lastEpoch(chunkIndex uint64) types.Epoch {
// chunk of size C. For example, if C = 3 and K = 3, the data we store // chunk of size C. For example, if C = 3 and K = 3, the data we store
// on disk is a flat slice as follows: // on disk is a flat slice as follows:
// //
// val0 val1 val2 // val0 val1 val2
// | | | // | | |
// { } { } { } // { } { } { }
// [-, -, -, -, -, -, -, -, -] // [-, -, -, -, -, -, -, -, -]
// //
// Then, figuring out the exact cell index for epoch 1 for validator 2 is computed // Then, figuring out the exact cell index for epoch 1 for validator 2 is computed
// with (validatorIndex % K)*C + (epoch % C), which gives us: // with (validatorIndex % K)*C + (epoch % C), which gives us:
// //
// (2 % 3)*3 + (1 % 3) = // (2 % 3)*3 + (1 % 3) =
// (2*3) + (1) = // (2*3) + (1) =
// 7 // 7
//
// val0 val1 val2
// | | |
// { } { } { }
// [-, -, -, -, -, -, -, -, -]
// |-> epoch 1 for val2
// //
// val0 val1 val2
// | | |
// { } { } { }
// [-, -, -, -, -, -, -, -, -]
// |-> epoch 1 for val2
func (p *Parameters) cellIndex(validatorIndex types.ValidatorIndex, epoch types.Epoch) uint64 { func (p *Parameters) cellIndex(validatorIndex types.ValidatorIndex, epoch types.Epoch) uint64 {
validatorChunkOffset := p.validatorOffset(validatorIndex) validatorChunkOffset := p.validatorOffset(validatorIndex)
chunkOffset := p.chunkOffset(epoch) chunkOffset := p.chunkOffset(epoch)
@ -134,17 +130,16 @@ func (p *Parameters) validatorOffset(validatorIndex types.ValidatorIndex) uint64
// If chunkSize C = 3 and validatorChunkSize K = 3, and historyLength H = 12, // If chunkSize C = 3 and validatorChunkSize K = 3, and historyLength H = 12,
// if we are looking for epoch 6 and validator 6, then // if we are looking for epoch 6 and validator 6, then
// //
// validatorChunkIndex = 6 / 3 = 2 // validatorChunkIndex = 6 / 3 = 2
// chunkIndex = (6 % historyLength) / 3 = (6 % 12) / 3 = 2 // chunkIndex = (6 % historyLength) / 3 = (6 % 12) / 3 = 2
// //
// Then we compute how many chunks there are per max span, known as the "width" // Then we compute how many chunks there are per max span, known as the "width"
// //
// width = H / C = 12 / 3 = 4 // width = H / C = 12 / 3 = 4
// //
// So every span has 4 chunks. Then, we have a disk key calculated by // So every span has 4 chunks. Then, we have a disk key calculated by
// //
// validatorChunkIndex * width + chunkIndex = 2*4 + 2 = 10 // validatorChunkIndex * width + chunkIndex = 2*4 + 2 = 10
//
func (p *Parameters) flatSliceID(validatorChunkIndex, chunkIndex uint64) []byte { func (p *Parameters) flatSliceID(validatorChunkIndex, chunkIndex uint64) []byte {
width := p.historyLength.Div(p.chunkSize) width := p.historyLength.Div(p.chunkSize)
return ssz.MarshalUint64(make([]byte, 0), uint64(width.Mul(validatorChunkIndex).Add(chunkIndex))) return ssz.MarshalUint64(make([]byte, 0), uint64(width.Mul(validatorChunkIndex).Add(chunkIndex)))

View File

@ -9,20 +9,20 @@
// allowing it to be used by other package-level functions that already hold a lock. // allowing it to be used by other package-level functions that already hold a lock.
// Hence the functions look something like this: // Hence the functions look something like this:
// //
// func (b *BeaconState) Foo() uint64 { // func (b *BeaconState) Foo() uint64 {
// // Read lock. // // Read lock.
// b.lock.RLock() // b.lock.RLock()
// defer b.lock.RUnlock() // defer b.lock.RUnlock()
// //
// // Internal getter. // // Internal getter.
// return b.foo() // return b.foo()
// } // }
// //
// func (b *BeaconState) foo() uint64 { // func (b *BeaconState) foo() uint64 {
// (...) // Some processing logic. // (...) // Some processing logic.
// //
// return b.foo // return b.foo
// } // }
// //
// Although it is technically possible to remove the short-circuit conditions // Although it is technically possible to remove the short-circuit conditions
// from the external function, that would require every read to obtain a lock // from the external function, that would require every read to obtain a lock

View File

@ -360,8 +360,9 @@ func TestLoadBlocks_BadStart(t *testing.T) {
// tree1 constructs the following tree: // tree1 constructs the following tree:
// B0 - B1 - - B3 -- B5 // B0 - B1 - - B3 -- B5
// \- B2 -- B4 -- B6 ----- B8 //
// \- B7 // \- B2 -- B4 -- B6 ----- B8
// \- B7
func tree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) { func tree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
b0 := util.NewBeaconBlock() b0 := util.NewBeaconBlock()
b0.Block.Slot = 0 b0.Block.Slot = 0
@ -449,10 +450,11 @@ func tree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte,
// tree2 constructs the following tree: // tree2 constructs the following tree:
// B0 - B1 // B0 - B1
// \- B2 //
// \- B2 // \- B2
// \- B2 // \- B2
// \- B2 -- B3 // \- B2
// \- B2 -- B3
func tree2(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) { func tree2(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
b0 := util.NewBeaconBlock() b0 := util.NewBeaconBlock()
b0.Block.Slot = 0 b0.Block.Slot = 0
@ -531,10 +533,11 @@ func tree2(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte,
// tree3 constructs the following tree: // tree3 constructs the following tree:
// B0 - B1 // B0 - B1
// \- B2 //
// \- B2 // \- B2
// \- B2 // \- B2
// \- B2 // \- B2
// \- B2
func tree3(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) { func tree3(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
b0 := util.NewBeaconBlock() b0 := util.NewBeaconBlock()
b0.Block.Slot = 0 b0.Block.Slot = 0
@ -607,10 +610,11 @@ func tree3(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte,
// tree4 constructs the following tree: // tree4 constructs the following tree:
// B0 // B0
// \- B2 //
// \- B2 // \- B2
// \- B2 // \- B2
// \- B2 // \- B2
// \- B2
func tree4(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) { func tree4(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
b0 := util.NewBeaconBlock() b0 := util.NewBeaconBlock()
b0.Block.Slot = 0 b0.Block.Slot = 0

View File

@ -31,9 +31,12 @@ import (
"github.com/prysmaticlabs/prysm/v3/testing/util" "github.com/prysmaticlabs/prysm/v3/testing/util"
) )
// /- b1 - b2 // /- b1 - b2
//
// b0 // b0
// \- b3 //
// \- b3
//
// Test b1 was missing then received and we can process b0 -> b1 -> b2 // Test b1 was missing then received and we can process b0 -> b1 -> b2
func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks1(t *testing.T) { func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks1(t *testing.T) {
db := dbtest.SetupDB(t) db := dbtest.SetupDB(t)
@ -348,9 +351,12 @@ func TestRegularSyncBeaconBlockSubscriber_DoNotReprocessBlock(t *testing.T) {
assert.Equal(t, 0, len(r.seenPendingBlocks), "Incorrect size for seen pending block") assert.Equal(t, 0, len(r.seenPendingBlocks), "Incorrect size for seen pending block")
} }
// /- b1 - b2 - b5 // /- b1 - b2 - b5
//
// b0 // b0
// \- b3 - b4 //
// \- b3 - b4
//
// Test b2 and b3 were missed, after receiving them we can process 2 chains. // Test b2 and b3 were missed, after receiving them we can process 2 chains.
func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks_2Chains(t *testing.T) { func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks_2Chains(t *testing.T) {
db := dbtest.SetupDB(t) db := dbtest.SetupDB(t)

View File

@ -3,19 +3,19 @@ Package features defines which features are enabled for runtime
in order to selectively enable certain features to maintain a stable runtime. in order to selectively enable certain features to maintain a stable runtime.
The process for implementing new features using this package is as follows: The process for implementing new features using this package is as follows:
1. Add a new CMD flag in flags.go, and place it in the proper list(s) var for its client. 1. Add a new CMD flag in flags.go, and place it in the proper list(s) var for its client.
2. Add a condition for the flag in the proper Configure function(s) below. 2. Add a condition for the flag in the proper Configure function(s) below.
3. Place any "new" behavior in the `if flagEnabled` statement. 3. Place any "new" behavior in the `if flagEnabled` statement.
4. Place any "previous" behavior in the `else` statement. 4. Place any "previous" behavior in the `else` statement.
5. Ensure any tests using the new feature fail if the flag isn't enabled. 5. Ensure any tests using the new feature fail if the flag isn't enabled.
5a. Use the following to enable your flag for tests: 5a. Use the following to enable your flag for tests:
cfg := &featureconfig.Flags{ cfg := &featureconfig.Flags{
VerifyAttestationSigs: true, VerifyAttestationSigs: true,
} }
resetCfg := featureconfig.InitWithReset(cfg) resetCfg := featureconfig.InitWithReset(cfg)
defer resetCfg() defer resetCfg()
6. Add the string for the flags that should be running within E2E to E2EValidatorFlags 6. Add the string for the flags that should be running within E2E to E2EValidatorFlags
and E2EBeaconChainFlags. and E2EBeaconChainFlags.
*/ */
package features package features

View File

@ -18,7 +18,6 @@ This means it is the exact mirror of a token bucket.
n := b.Add(1) n := b.Add(1)
// n == 0 // n == 0
A Collector is a convenient way to keep track of multiple LeakyBucket's. A Collector is a convenient way to keep track of multiple LeakyBucket's.
Buckets are associated with string keys for fast lookup. It can dynamically Buckets are associated with string keys for fast lookup. It can dynamically
add new buckets and automatically remove them as they become empty, freeing add new buckets and automatically remove them as they become empty, freeing

View File

@ -296,11 +296,12 @@ func SplitCommaSeparated(arr []string) []string {
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def get_split_offset(list_size: int, chunks: int, index: int) -> int: // def get_split_offset(list_size: int, chunks: int, index: int) -> int:
// """ //
// Returns a value such that for a list L, chunk count k and index i, // """
// split(L, k)[i] == L[get_split_offset(len(L), k, i): get_split_offset(len(L), k, i+1)] // Returns a value such that for a list L, chunk count k and index i,
// """ // split(L, k)[i] == L[get_split_offset(len(L), k, i): get_split_offset(len(L), k, i+1)]
// return (list_size * index) // chunks // """
// return (list_size * index) // chunks
func SplitOffset(listSize, chunks, index uint64) uint64 { func SplitOffset(listSize, chunks, index uint64) uint64 {
return (listSize * index) / chunks return (listSize * index) / chunks
} }

View File

@ -101,8 +101,9 @@ func (m *SparseMerkleTrie) Items() [][]byte {
} }
// HashTreeRoot of the Merkle trie as defined in the deposit contract. // HashTreeRoot of the Merkle trie as defined in the deposit contract.
// Spec Definition: //
// sha256(concat(node, self.to_little_endian_64(self.deposit_count), slice(zero_bytes32, start=0, len=24))) // Spec Definition:
// sha256(concat(node, self.to_little_endian_64(self.deposit_count), slice(zero_bytes32, start=0, len=24)))
func (m *SparseMerkleTrie) HashTreeRoot() ([32]byte, error) { func (m *SparseMerkleTrie) HashTreeRoot() ([32]byte, error) {
enc := [32]byte{} enc := [32]byte{}
depositCount := uint64(len(m.originalItems)) depositCount := uint64(len(m.originalItems))

View File

@ -16,13 +16,14 @@ import (
// signed by the deposit key. // signed by the deposit key.
// //
// Spec details about general deposit workflow: // Spec details about general deposit workflow:
// To submit a deposit:
// //
// - Pack the validator's initialization parameters into deposit_data, a Deposit_Data SSZ object. // To submit a deposit:
// - Let amount be the amount in Gwei to be deposited by the validator where MIN_DEPOSIT_AMOUNT <= amount <= MAX_EFFECTIVE_BALANCE. //
// - Set deposit_data.amount = amount. // - Pack the validator's initialization parameters into deposit_data, a Deposit_Data SSZ object.
// - Let signature be the result of bls_sign of the signing_root(deposit_data) with domain=compute_domain(DOMAIN_DEPOSIT). (Deposits are valid regardless of fork version, compute_domain will default to zeroes there). // - Let amount be the amount in Gwei to be deposited by the validator where MIN_DEPOSIT_AMOUNT <= amount <= MAX_EFFECTIVE_BALANCE.
// - Send a transaction on the Ethereum 1.0 chain to DEPOSIT_CONTRACT_ADDRESS executing `deposit(pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96])` along with a deposit of amount Gwei. // - Set deposit_data.amount = amount.
// - Let signature be the result of bls_sign of the signing_root(deposit_data) with domain=compute_domain(DOMAIN_DEPOSIT). (Deposits are valid regardless of fork version, compute_domain will default to zeroes there).
// - Send a transaction on the Ethereum 1.0 chain to DEPOSIT_CONTRACT_ADDRESS executing `deposit(pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96])` along with a deposit of amount Gwei.
// //
// See: https://github.com/ethereum/consensus-specs/blob/master/specs/validator/0_beacon-chain-validator.md#submit-deposit // See: https://github.com/ethereum/consensus-specs/blob/master/specs/validator/0_beacon-chain-validator.md#submit-deposit
func DepositInput(depositKey, withdrawalKey bls.SecretKey, amountInGwei uint64) (*ethpb.Deposit_Data, [32]byte, error) { func DepositInput(depositKey, withdrawalKey bls.SecretKey, amountInGwei uint64) (*ethpb.Deposit_Data, [32]byte, error) {
@ -68,8 +69,10 @@ func DepositInput(depositKey, withdrawalKey bls.SecretKey, amountInGwei uint64)
// address. // address.
// //
// The specification is as follows: // The specification is as follows:
// withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX_BYTE //
// withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:] // withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX_BYTE
// withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]
//
// where withdrawal_credentials is of type bytes32. // where withdrawal_credentials is of type bytes32.
func WithdrawalCredentialsHash(withdrawalKey bls.SecretKey) []byte { func WithdrawalCredentialsHash(withdrawalKey bls.SecretKey) []byte {
h := hash.Hash(withdrawalKey.PublicKey().Marshal()) h := hash.Hash(withdrawalKey.PublicKey().Marshal())

View File

@ -3,5 +3,4 @@
// verifying and aggregating BLS signatures used by Ethereum. // verifying and aggregating BLS signatures used by Ethereum.
// //
// This implementation uses the library written by Supranational, blst. // This implementation uses the library written by Supranational, blst.
//
package blst package blst

View File

@ -67,7 +67,8 @@ func IsZero(sKey []byte) bool {
// //
// In IETF draft BLS specification: // In IETF draft BLS specification:
// Sign(SK, message) -> signature: a signing algorithm that generates // Sign(SK, message) -> signature: a signing algorithm that generates
// a deterministic signature given a secret key SK and a message. //
// a deterministic signature given a secret key SK and a message.
// //
// In Ethereum proof of stake specification: // In Ethereum proof of stake specification:
// def Sign(SK: int, message: Bytes) -> BLSSignature // def Sign(SK: int, message: Bytes) -> BLSSignature

View File

@ -85,8 +85,9 @@ func MultipleSignaturesFromBytes(multiSigs [][]byte) ([]common.Signature, error)
// //
// In IETF draft BLS specification: // In IETF draft BLS specification:
// Verify(PK, message, signature) -> VALID or INVALID: a verification // Verify(PK, message, signature) -> VALID or INVALID: a verification
// algorithm that outputs VALID if signature is a valid signature of //
// message under public key PK, and INVALID otherwise. // algorithm that outputs VALID if signature is a valid signature of
// message under public key PK, and INVALID otherwise.
// //
// In the Ethereum proof of stake specification: // In the Ethereum proof of stake specification:
// def Verify(PK: BLSPubkey, message: Bytes, signature: BLSSignature) -> bool // def Verify(PK: BLSPubkey, message: Bytes, signature: BLSSignature) -> bool
@ -103,10 +104,11 @@ func (s *Signature) Verify(pubKey common.PublicKey, msg []byte) bool {
// //
// In IETF draft BLS specification: // In IETF draft BLS specification:
// AggregateVerify((PK_1, message_1), ..., (PK_n, message_n), // AggregateVerify((PK_1, message_1), ..., (PK_n, message_n),
// signature) -> VALID or INVALID: an aggregate verification //
// algorithm that outputs VALID if signature is a valid aggregated // signature) -> VALID or INVALID: an aggregate verification
// signature for a collection of public keys and messages, and // algorithm that outputs VALID if signature is a valid aggregated
// outputs INVALID otherwise. // signature for a collection of public keys and messages, and
// outputs INVALID otherwise.
// //
// In the Ethereum proof of stake specification: // In the Ethereum proof of stake specification:
// def AggregateVerify(pairs: Sequence[PK: BLSPubkey, message: Bytes], signature: BLSSignature) -> bool // def AggregateVerify(pairs: Sequence[PK: BLSPubkey, message: Bytes], signature: BLSSignature) -> bool
@ -134,9 +136,10 @@ func (s *Signature) AggregateVerify(pubKeys []common.PublicKey, msgs [][32]byte)
// //
// In IETF draft BLS specification: // In IETF draft BLS specification:
// FastAggregateVerify(PK_1, ..., PK_n, message, signature) -> VALID // FastAggregateVerify(PK_1, ..., PK_n, message, signature) -> VALID
// or INVALID: a verification algorithm for the aggregate of multiple //
// signatures on the same message. This function is faster than // or INVALID: a verification algorithm for the aggregate of multiple
// AggregateVerify. // signatures on the same message. This function is faster than
// AggregateVerify.
// //
// In the Ethereum proof of stake specification: // In the Ethereum proof of stake specification:
// def FastAggregateVerify(PKs: Sequence[BLSPubkey], message: Bytes, signature: BLSSignature) -> bool // def FastAggregateVerify(PKs: Sequence[BLSPubkey], message: Bytes, signature: BLSSignature) -> bool
@ -156,12 +159,13 @@ func (s *Signature) FastAggregateVerify(pubKeys []common.PublicKey, msg [32]byte
// //
// Spec code: // Spec code:
// def eth2_fast_aggregate_verify(pubkeys: Sequence[BLSPubkey], message: Bytes32, signature: BLSSignature) -> bool: // def eth2_fast_aggregate_verify(pubkeys: Sequence[BLSPubkey], message: Bytes32, signature: BLSSignature) -> bool:
// """ //
// Wrapper to ``bls.FastAggregateVerify`` accepting the ``G2_POINT_AT_INFINITY`` signature when ``pubkeys`` is empty. // """
// """ // Wrapper to ``bls.FastAggregateVerify`` accepting the ``G2_POINT_AT_INFINITY`` signature when ``pubkeys`` is empty.
// if len(pubkeys) == 0 and signature == G2_POINT_AT_INFINITY: // """
// return True // if len(pubkeys) == 0 and signature == G2_POINT_AT_INFINITY:
// return bls.FastAggregateVerify(pubkeys, message, signature) // return True
// return bls.FastAggregateVerify(pubkeys, message, signature)
func (s *Signature) Eth2FastAggregateVerify(pubKeys []common.PublicKey, msg [32]byte) bool { func (s *Signature) Eth2FastAggregateVerify(pubKeys []common.PublicKey, msg [32]byte) bool {
if len(pubKeys) == 0 && bytes.Equal(s.Marshal(), common.InfiniteSignature[:]) { if len(pubKeys) == 0 && bytes.Equal(s.Marshal(), common.InfiniteSignature[:]) {
return true return true

View File

@ -7,26 +7,26 @@ This limits the scope of code that needs to be hardened.
There are two modes, one for deterministic and another non-deterministic randomness: There are two modes, one for deterministic and another non-deterministic randomness:
1. If deterministic pseudo-random generator is enough, use: 1. If deterministic pseudo-random generator is enough, use:
import "github.com/prysmaticlabs/prysm/v3/crypto/rand" import "github.com/prysmaticlabs/prysm/v3/crypto/rand"
randGen := rand.NewDeterministicGenerator() randGen := rand.NewDeterministicGenerator()
randGen.Intn(32) // or any other func defined in math.rand API randGen.Intn(32) // or any other func defined in math.rand API
In this mode, only seed is generated using cryptographically secure source (crypto/rand). So, In this mode, only seed is generated using cryptographically secure source (crypto/rand). So,
once seed is obtained, and generator is seeded, the next generations are deterministic, thus fast. once seed is obtained, and generator is seeded, the next generations are deterministic, thus fast.
However given that we only seed this 63 bits from crypto/rand and use math/rand to generate the outputs, However given that we only seed this 63 bits from crypto/rand and use math/rand to generate the outputs,
this method is not cryptographically secure. This is directly stated in the math/rand package, this method is not cryptographically secure. This is directly stated in the math/rand package,
https://github.com/golang/go/blob/release-branch.go1.17/src/math/rand/rand.go#L15. For any security https://github.com/golang/go/blob/release-branch.go1.17/src/math/rand/rand.go#L15. For any security
sensitive work this particular generator is NOT to be used. sensitive work this particular generator is NOT to be used.
2. For cryptographically secure non-deterministic mode (CSPRNG), use: 2. For cryptographically secure non-deterministic mode (CSPRNG), use:
import "github.com/prysmaticlabs/prysm/v3/crypto/rand" import "github.com/prysmaticlabs/prysm/v3/crypto/rand"
randGen := rand.NewGenerator() randGen := rand.NewGenerator()
randGen.Intn(32) // or any other func defined in math.rand API randGen.Intn(32) // or any other func defined in math.rand API
Again, any of the functions from `math/rand` can be used, however, they all use custom source Again, any of the functions from `math/rand` can be used, however, they all use custom source
of randomness (crypto/rand), on every step. This makes randomness non-deterministic. However, of randomness (crypto/rand), on every step. This makes randomness non-deterministic. However,
you take a performance hit -- as it is an order of magnitude slower. you take a performance hit -- as it is an order of magnitude slower.
*/ */
package rand package rand

View File

@ -247,7 +247,7 @@ func deepValueBaseTypeEqual(v1, v2 reflect.Value) bool {
} }
} }
// DeepEqual reports whether two SSZ-able values x and y are ``deeply equal,'' defined as follows: // DeepEqual reports whether two SSZ-able values x and y are “deeply equal,” defined as follows:
// Two values of identical type are deeply equal if one of the following cases applies: // Two values of identical type are deeply equal if one of the following cases applies:
// //
// Values of distinct types are never deeply equal. // Values of distinct types are never deeply equal.

View File

@ -1,6 +1,6 @@
base: base:
language: go language: go
version: 1.18 version: 1.19
build_tags: build_tags:
- fuzz - fuzz
- develop - develop

2
go.mod
View File

@ -1,6 +1,6 @@
module github.com/prysmaticlabs/prysm/v3 module github.com/prysmaticlabs/prysm/v3
go 1.18 go 1.19
require ( require (
contrib.go.opencensus.io/exporter/jaeger v0.2.1 contrib.go.opencensus.io/exporter/jaeger v0.2.1

View File

@ -6,7 +6,7 @@ import (
"github.com/wercker/journalhook" "github.com/wercker/journalhook"
) )
//Enable enables the journald logrus hook // Enable enables the journald logrus hook
func Enable() error { func Enable() error {
journalhook.Enable() journalhook.Enable()
return nil return nil

View File

@ -186,8 +186,10 @@ func createDepositData(privKey bls.SecretKey, pubKey bls.PublicKey) (*ethpb.Depo
// address. // address.
// //
// The specification is as follows: // The specification is as follows:
// withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX_BYTE //
// withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:] // withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX_BYTE
// withdrawal_credentials[1:] == hash(withdrawal_pubkey)[1:]
//
// where withdrawal_credentials is of type bytes32. // where withdrawal_credentials is of type bytes32.
func withdrawalCredentialsHash(pubKey []byte) []byte { func withdrawalCredentialsHash(pubKey []byte) []byte {
h := hash.Hash(pubKey) h := hash.Hash(pubKey)

View File

@ -568,7 +568,6 @@ func (r *testRunner) executeProvidedEvaluators(currentEpoch uint64, conns []*grp
// Along with that we will also take a single lighthouse node and its validator offline. // Along with that we will also take a single lighthouse node and its validator offline.
// After 1 epoch we will then attempt to bring it online again. // After 1 epoch we will then attempt to bring it online again.
// //
//
// 2) Then we will start testing optimistic sync by engaging our engine proxy. // 2) Then we will start testing optimistic sync by engaging our engine proxy.
// After the proxy has been sending `SYNCING` responses to the beacon node, we // After the proxy has been sending `SYNCING` responses to the beacon node, we
// will test this with our optimistic sync evaluator to ensure everything works // will test this with our optimistic sync evaluator to ensure everything works

View File

@ -65,11 +65,12 @@ func AbsoluteValueSlotDifference(x, y types.Slot) uint64 {
// ToEpoch returns the epoch number of the input slot. // ToEpoch returns the epoch number of the input slot.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def compute_epoch_at_slot(slot: Slot) -> Epoch: //
// """ // def compute_epoch_at_slot(slot: Slot) -> Epoch:
// Return the epoch number at ``slot``. // """
// """ // Return the epoch number at ``slot``.
// return Epoch(slot // SLOTS_PER_EPOCH) // """
// return Epoch(slot // SLOTS_PER_EPOCH)
func ToEpoch(slot types.Slot) types.Epoch { func ToEpoch(slot types.Slot) types.Epoch {
return types.Epoch(slot.DivSlot(params.BeaconConfig().SlotsPerEpoch)) return types.Epoch(slot.DivSlot(params.BeaconConfig().SlotsPerEpoch))
} }
@ -78,11 +79,12 @@ func ToEpoch(slot types.Slot) types.Epoch {
// current epoch. // current epoch.
// //
// Spec pseudocode definition: // Spec pseudocode definition:
// def compute_start_slot_at_epoch(epoch: Epoch) -> Slot: //
// """ // def compute_start_slot_at_epoch(epoch: Epoch) -> Slot:
// Return the start slot of ``epoch``. // """
// """ // Return the start slot of ``epoch``.
// return Slot(epoch * SLOTS_PER_EPOCH) // """
// return Slot(epoch * SLOTS_PER_EPOCH)
func EpochStart(epoch types.Epoch) (types.Slot, error) { func EpochStart(epoch types.Epoch) (types.Slot, error) {
slot, err := params.BeaconConfig().SlotsPerEpoch.SafeMul(uint64(epoch)) slot, err := params.BeaconConfig().SlotsPerEpoch.SafeMul(uint64(epoch))
if err != nil { if err != nil {
@ -213,7 +215,8 @@ func PrevSlot(slot types.Slot) types.Slot {
// //
// Spec code: // Spec code:
// def compute_sync_committee_period(epoch: Epoch) -> uint64: // def compute_sync_committee_period(epoch: Epoch) -> uint64:
// return epoch // EPOCHS_PER_SYNC_COMMITTEE_PERIOD //
// return epoch // EPOCHS_PER_SYNC_COMMITTEE_PERIOD
func SyncCommitteePeriod(e types.Epoch) uint64 { func SyncCommitteePeriod(e types.Epoch) uint64 {
return uint64(e / params.BeaconConfig().EpochsPerSyncCommitteePeriod) return uint64(e / params.BeaconConfig().EpochsPerSyncCommitteePeriod)
} }

View File

@ -313,16 +313,16 @@ func namesForExcludeCheck(pass *analysis.Pass, call *ast.CallExpr) []string {
// //
// For example, say we have: // For example, say we have:
// //
// type Inner interface {Method()} // type Inner interface {Method()}
// type Middle interface {Inner} // type Middle interface {Inner}
// type Outer interface {Middle} // type Outer interface {Middle}
// type T struct {Outer} // type T struct {Outer}
// type U struct {T} // type U struct {T}
// type V struct {U} // type V struct {U}
// //
// And then the selector: // And then the selector:
// //
// V.Method // V.Method
// //
// We'll return [Outer, Middle, Inner] by first walking through the embedded structs // We'll return [Outer, Middle, Inner] by first walking through the embedded structs
// until we reach the Outer interface, then descending through the embedded interfaces // until we reach the Outer interface, then descending through the embedded interfaces

View File

@ -25,7 +25,8 @@ var Analyzer = &analysis.Analyzer{
// Recommended thresholds according to the 2008 presentation titled // Recommended thresholds according to the 2008 presentation titled
// "Software Quality Metrics to Identify Risk" by Thomas McCabe Jr. // "Software Quality Metrics to Identify Risk" by Thomas McCabe Jr.
// //
// 1 - 10 Simple procedure, little risk // 1 - 10 Simple procedure, little risk
//
// 11 - 20 More complex, moderate risk // 11 - 20 More complex, moderate risk
// 21 - 50 Complex, high risk // 21 - 50 Complex, high risk
// > 50 Untestable code, very high risk // > 50 Untestable code, very high risk

View File

@ -1,11 +1,11 @@
/** /*
* Block tree graph viz *
* - Block tree graph viz
* Given a DB, start slot and end slot. This tool computes the graphviz data *
* needed to construct the block tree in graphviz data format. Then one can paste - Given a DB, start slot and end slot. This tool computes the graphviz data
* the data in a Graph rendering engine (ie. http://www.webgraphviz.com/) to see the visual format. - needed to construct the block tree in graphviz data format. Then one can paste
- the data in a Graph rendering engine (ie. http://www.webgraphviz.com/) to see the visual format.
*/ */
package main package main
import ( import (

View File

@ -11,7 +11,8 @@ import (
// A basic tool to extract genesis.ssz from existing beaconchain.db. // A basic tool to extract genesis.ssz from existing beaconchain.db.
// ex: // ex:
// bazel run //tools/interop/export-genesis:export-genesis -- /tmp/data/beaconchaindata /tmp/genesis.ssz //
// bazel run //tools/interop/export-genesis:export-genesis -- /tmp/data/beaconchaindata /tmp/genesis.ssz
func main() { func main() {
if len(os.Args) < 3 { if len(os.Args) < 3 {
fmt.Println("Usage: ./main /path/to/datadir /path/to/output/genesis.ssz") fmt.Println("Usage: ./main /path/to/datadir /path/to/output/genesis.ssz")

View File

@ -1,4 +1,5 @@
/** /*
*
Tool for replaying http requests from a file of base64 encoded, line-delimited Tool for replaying http requests from a file of base64 encoded, line-delimited
Go http raw requests. Credits to https://gist.github.com/kasey/c9e663eae5baebbf8fbe548c2b1d961b. Go http raw requests. Credits to https://gist.github.com/kasey/c9e663eae5baebbf8fbe548c2b1d961b.
*/ */

View File

@ -247,8 +247,9 @@ func (v *validator) saveAttesterIndexToData(data *ethpb.AttestationData, index t
} }
// waitOneThirdOrValidBlock waits until (a) or (b) whichever comes first: // waitOneThirdOrValidBlock waits until (a) or (b) whichever comes first:
// (a) the validator has received a valid block that is the same slot as input slot //
// (b) one-third of the slot has transpired (SECONDS_PER_SLOT / 3 seconds after the start of slot) // (a) the validator has received a valid block that is the same slot as input slot
// (b) one-third of the slot has transpired (SECONDS_PER_SLOT / 3 seconds after the start of slot)
func (v *validator) waitOneThirdOrValidBlock(ctx context.Context, slot types.Slot) { func (v *validator) waitOneThirdOrValidBlock(ctx context.Context, slot types.Slot) {
ctx, span := trace.StartSpan(ctx, "validator.waitOneThirdOrValidBlock") ctx, span := trace.StartSpan(ctx, "validator.waitOneThirdOrValidBlock")
defer span.End() defer span.End()

View File

@ -14,46 +14,46 @@ the remote server.
Remote sign requests are defined by the following protobuf schema: Remote sign requests are defined by the following protobuf schema:
// SignRequest is a message type used by a keymanager // SignRequest is a message type used by a keymanager
// as part of Prysm's accounts implementation. // as part of Prysm's accounts implementation.
message SignRequest { message SignRequest {
// 48 byte public key corresponding to an associated private key // 48 byte public key corresponding to an associated private key
// being requested to sign data. // being requested to sign data.
bytes public_key = 1; bytes public_key = 1;
// Raw bytes signing root the client is requesting to sign. The client is // Raw bytes signing root the client is requesting to sign. The client is
// expected to determine these raw bytes from the appropriate BLS // expected to determine these raw bytes from the appropriate BLS
// signing domain as well as the signing root of the data structure // signing domain as well as the signing root of the data structure
// the bytes represent. // the bytes represent.
bytes signing_root = 2; bytes signing_root = 2;
} }
Remote signing responses will contain a BLS12-381 signature along with the Remote signing responses will contain a BLS12-381 signature along with the
status of the signing response from the remote server, signifying the status of the signing response from the remote server, signifying the
request either failed, was denied, or completed successfully. request either failed, was denied, or completed successfully.
message SignResponse { message SignResponse {
enum Status { enum Status {
UNKNOWN = 0; UNKNOWN = 0;
SUCCEEDED = 1; SUCCEEDED = 1;
DENIED = 2; DENIED = 2;
FAILED = 3; FAILED = 3;
} }
// BLS12-381 signature for the data specified in the request. // BLS12-381 signature for the data specified in the request.
bytes signature = 1; bytes signature = 1;
} }
The remote keymanager can be customized via a keymanageropts.json file The remote keymanager can be customized via a keymanageropts.json file
which requires the following schema: which requires the following schema:
{ {
"remote_address": "remoteserver.com:4000", // Remote gRPC server address. "remote_address": "remoteserver.com:4000", // Remote gRPC server address.
"remote_cert": { "remote_cert": {
"crt_path": "/home/eth2/certs/client.crt", // Client certificate path. "crt_path": "/home/eth2/certs/client.crt", // Client certificate path.
"ca_crt_path": "/home/eth2/certs/ca.crt", // Certificate authority cert path. "ca_crt_path": "/home/eth2/certs/ca.crt", // Certificate authority cert path.
"key_path": "/home/eth2/certs/client.key", // Client key path. "key_path": "/home/eth2/certs/client.key", // Client key path.
} }
} }
*/ */
package remote package remote

View File

@ -19,9 +19,9 @@ import (
// easy to migrate machines or Ethereum consensus clients. // easy to migrate machines or Ethereum consensus clients.
// //
// Steps: // Steps:
// 1. Call the function which exports the data from // 1. Call the function which exports the data from
// the validator's db into an EIP standard slashing protection format. // the validator's db into an EIP standard slashing protection format.
// 2. Format and send JSON in the response. // 2. Format and send JSON in the response.
func (s *Server) ExportSlashingProtection(ctx context.Context, _ *empty.Empty) (*pb.ExportSlashingProtectionResponse, error) { func (s *Server) ExportSlashingProtection(ctx context.Context, _ *empty.Empty) (*pb.ExportSlashingProtectionResponse, error) {
if s.valDB == nil { if s.valDB == nil {
return nil, errors.New("err finding validator database at path") return nil, errors.New("err finding validator database at path")

View File

@ -174,18 +174,19 @@ func validateMetadata(ctx context.Context, validatorDB db.Database, interchangeJ
// We create a map of pubKey -> []*SignedBlock. Then, for each public key we observe, // We create a map of pubKey -> []*SignedBlock. Then, for each public key we observe,
// we append to this map. This allows us to handle valid input JSON data such as: // we append to this map. This allows us to handle valid input JSON data such as:
// //
// "0x2932232930: { // "0x2932232930: {
// SignedBlocks: [Slot: 5, Slot: 6, Slot: 7], // SignedBlocks: [Slot: 5, Slot: 6, Slot: 7],
// }, // },
// "0x2932232930: { //
// SignedBlocks: [Slot: 5, Slot: 10, Slot: 11], // "0x2932232930: {
// } // SignedBlocks: [Slot: 5, Slot: 10, Slot: 11],
// }
// //
// Which should be properly parsed as: // Which should be properly parsed as:
// //
// "0x2932232930: { // "0x2932232930: {
// SignedBlocks: [Slot: 5, Slot: 5, Slot: 6, Slot: 7, Slot: 10, Slot: 11], // SignedBlocks: [Slot: 5, Slot: 5, Slot: 6, Slot: 7, Slot: 10, Slot: 11],
// } // }
func parseBlocksForUniquePublicKeys(data []*format.ProtectionData) (map[[fieldparams.BLSPubkeyLength]byte][]*format.SignedBlock, error) { func parseBlocksForUniquePublicKeys(data []*format.ProtectionData) (map[[fieldparams.BLSPubkeyLength]byte][]*format.SignedBlock, error) {
signedBlocksByPubKey := make(map[[fieldparams.BLSPubkeyLength]byte][]*format.SignedBlock) signedBlocksByPubKey := make(map[[fieldparams.BLSPubkeyLength]byte][]*format.SignedBlock)
for _, validatorData := range data { for _, validatorData := range data {
@ -206,18 +207,19 @@ func parseBlocksForUniquePublicKeys(data []*format.ProtectionData) (map[[fieldpa
// We create a map of pubKey -> []*SignedAttestation. Then, for each public key we observe, // We create a map of pubKey -> []*SignedAttestation. Then, for each public key we observe,
// we append to this map. This allows us to handle valid input JSON data such as: // we append to this map. This allows us to handle valid input JSON data such as:
// //
// "0x2932232930: { // "0x2932232930: {
// SignedAttestations: [{Source: 5, Target: 6}, {Source: 6, Target: 7}], // SignedAttestations: [{Source: 5, Target: 6}, {Source: 6, Target: 7}],
// }, // },
// "0x2932232930: { //
// SignedAttestations: [{Source: 5, Target: 6}], // "0x2932232930: {
// } // SignedAttestations: [{Source: 5, Target: 6}],
// }
// //
// Which should be properly parsed as: // Which should be properly parsed as:
// //
// "0x2932232930: { // "0x2932232930: {
// SignedAttestations: [{Source: 5, Target: 6}, {Source: 5, Target: 6}, {Source: 6, Target: 7}], // SignedAttestations: [{Source: 5, Target: 6}, {Source: 5, Target: 6}, {Source: 6, Target: 7}],
// } // }
func parseAttestationsForUniquePublicKeys(data []*format.ProtectionData) (map[[fieldparams.BLSPubkeyLength]byte][]*format.SignedAttestation, error) { func parseAttestationsForUniquePublicKeys(data []*format.ProtectionData) (map[[fieldparams.BLSPubkeyLength]byte][]*format.SignedAttestation, error) {
signedAttestationsByPubKey := make(map[[fieldparams.BLSPubkeyLength]byte][]*format.SignedAttestation) signedAttestationsByPubKey := make(map[[fieldparams.BLSPubkeyLength]byte][]*format.SignedAttestation)
for _, validatorData := range data { for _, validatorData := range data {