mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-31 23:41:22 +00:00
798bbbdc82
* coldstart flags for validator * WIP beacon node flags * wip beacon chain, flag fix in validator, arg fix in validator * checkpoint * Added interop service * working on mock chainstart * save the state lol * fix tests * Save genesis validators * gaz * fix validator help flags * WaitForChainStart actually waits for genesis time * cold start fixes * cache * change back * allow for genesis state too * remove logs * increase mmap size * dont process if head doesn't exist * add 10ms tolerance * enable libp2p debug at debug, fix pubsub * works with checkpt * initialize justified and finalized in db * Removed preloadStatePath from blockchain service * Clean up * Write to disk for now post state * revert b466dd536f8eadbdae2264a545a755370223d917 * Builds * Only RPC test fails now * use minimal config, no demo config * clean up branch * Lint * resolve lint * more lint fixes * lint * fix viz * Fixing RPC test * skip before epoch 2 * RPC time out * Fixed ordering * rename * remove some dbg statements * ensure index is correct * fix some panics * getting closer * fix tests * Fix private key * Fixed RPC test * Fixed beacon chain build for docker * Add interop.go to validator go_image * Fixed docker build * handle errors * skip test, skip disconnecting peers * Fixed docker build * tolerance for attestation processing * revert copy * clearer err message parse * fix launching from dep contract
577 lines
20 KiB
Go
577 lines
20 KiB
Go
// Package state implements the whole state transition
|
|
// function which consists of per slot, per-epoch transitions.
|
|
// It also bootstraps the genesis beacon state for slot 0.
|
|
package state
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/gogo/protobuf/proto"
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/go-ssz"
|
|
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
|
e "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/state/interop"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
|
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
"go.opencensus.io/trace"
|
|
)
|
|
|
|
// ExecuteStateTransition defines the procedure for a state transition function.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def state_transition(state: BeaconState, block: BeaconBlock, validate_state_root: bool=False) -> BeaconState:
|
|
// # Process slots (including those with no blocks) since block
|
|
// process_slots(state, block.slot)
|
|
// # Process block
|
|
// process_block(state, block)
|
|
// # Validate state root (`validate_state_root == True` in production)
|
|
// if validate_state_root:
|
|
// assert block.state_root == hash_tree_root(state)
|
|
// # Return post-state
|
|
// return state
|
|
func ExecuteStateTransition(
|
|
ctx context.Context,
|
|
state *pb.BeaconState,
|
|
block *ethpb.BeaconBlock,
|
|
) (*pb.BeaconState, error) {
|
|
if ctx.Err() != nil {
|
|
return nil, ctx.Err()
|
|
}
|
|
helpers.ClearStartShardCache()
|
|
b.ClearEth1DataVoteCache()
|
|
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.ExecuteStateTransition")
|
|
defer span.End()
|
|
var err error
|
|
// Execute per slots transition.
|
|
state, err = ProcessSlots(ctx, state, block.Slot)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process slot")
|
|
}
|
|
|
|
// Execute per block transition.
|
|
if block != nil {
|
|
state, err = ProcessBlock(ctx, state, block)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block")
|
|
}
|
|
}
|
|
|
|
interop.WriteStateToDisk(state)
|
|
|
|
postStateRoot, err := ssz.HashTreeRoot(state)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not tree hash processed state")
|
|
}
|
|
if !bytes.Equal(postStateRoot[:], block.StateRoot) {
|
|
return nil, fmt.Errorf("validate state root failed, wanted: %#x, received: %#x",
|
|
postStateRoot[:], block.StateRoot)
|
|
}
|
|
|
|
return state, nil
|
|
}
|
|
|
|
// ExecuteStateTransitionNoVerify defines the procedure for a state transition function.
|
|
// This does not validate state root, The use case of such is for state root calculation, the proposer
|
|
// should first run state transition on an unsigned block containing a stub for the state root and signature.
|
|
// This does not modify state.
|
|
//
|
|
// WARNING: This method does not validate state root and proposer signature. This is used for proposer to compute
|
|
// state root before proposing a new block, and this does not modify state.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def state_transition(state: BeaconState, block: BeaconBlock, validate_state_root: bool=False) -> BeaconState:
|
|
// # Process slots (including those with no blocks) since block
|
|
// process_slots(state, block.slot)
|
|
// # Process block
|
|
// process_block(state, block)
|
|
// # Return post-state
|
|
// return state
|
|
func ExecuteStateTransitionNoVerify(
|
|
ctx context.Context,
|
|
state *pb.BeaconState,
|
|
block *ethpb.BeaconBlock,
|
|
) (*pb.BeaconState, error) {
|
|
if ctx.Err() != nil {
|
|
return nil, ctx.Err()
|
|
}
|
|
|
|
stateCopy := proto.Clone(state).(*pb.BeaconState)
|
|
helpers.ClearStartShardCache()
|
|
b.ClearEth1DataVoteCache()
|
|
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.ExecuteStateTransition")
|
|
defer span.End()
|
|
var err error
|
|
|
|
// Execute per slots transition.
|
|
stateCopy, err = ProcessSlots(ctx, stateCopy, block.Slot)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process slot")
|
|
}
|
|
|
|
// Execute per block transition.
|
|
if block != nil {
|
|
stateCopy, err = processBlockNoVerify(ctx, stateCopy, block)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block")
|
|
}
|
|
}
|
|
|
|
return stateCopy, nil
|
|
}
|
|
|
|
// ProcessSlot happens every slot and focuses on the slot counter and block roots record updates.
|
|
// It happens regardless if there's an incoming block or not.
|
|
// Spec pseudocode definition:
|
|
//
|
|
// def process_slot(state: BeaconState) -> None:
|
|
// # Cache state root
|
|
// previous_state_root = hash_tree_root(state)
|
|
// state.state_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_state_root
|
|
//
|
|
// # Cache latest block header state root
|
|
// if state.latest_block_header.state_root == Bytes32():
|
|
// state.latest_block_header.state_root = previous_state_root
|
|
//
|
|
// # Cache block root
|
|
// previous_block_root = signing_root(state.latest_block_header)
|
|
// state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root
|
|
func ProcessSlot(ctx context.Context, state *pb.BeaconState) (*pb.BeaconState, error) {
|
|
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessSlot")
|
|
defer span.End()
|
|
span.AddAttributes(trace.Int64Attribute("slot", int64(state.Slot)))
|
|
|
|
prevStateRoot, err := ssz.HashTreeRoot(state)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not tree hash prev state root")
|
|
}
|
|
state.StateRoots[state.Slot%params.BeaconConfig().SlotsPerHistoricalRoot] = prevStateRoot[:]
|
|
|
|
zeroHash := params.BeaconConfig().ZeroHash
|
|
// Cache latest block header state root.
|
|
if bytes.Equal(state.LatestBlockHeader.StateRoot, zeroHash[:]) {
|
|
state.LatestBlockHeader.StateRoot = prevStateRoot[:]
|
|
}
|
|
prevBlockRoot, err := ssz.SigningRoot(state.LatestBlockHeader)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not determine prev block root")
|
|
}
|
|
// Cache the block root.
|
|
state.BlockRoots[state.Slot%params.BeaconConfig().SlotsPerHistoricalRoot] = prevBlockRoot[:]
|
|
return state, nil
|
|
}
|
|
|
|
// ProcessSlots process through skip skips and apply epoch transition when it's needed
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def process_slots(state: BeaconState, slot: Slot) -> None:
|
|
// assert state.slot <= slot
|
|
// while state.slot < slot:
|
|
// process_slot(state)
|
|
// # Process epoch on the first slot of the next epoch
|
|
// if (state.slot + 1) % SLOTS_PER_EPOCH == 0:
|
|
// process_epoch(state)
|
|
// state.slot += 1
|
|
// ]
|
|
func ProcessSlots(ctx context.Context, state *pb.BeaconState, slot uint64) (*pb.BeaconState, error) {
|
|
if state.Slot > slot {
|
|
return nil, fmt.Errorf("expected state.slot %d < slot %d", state.Slot, slot)
|
|
}
|
|
for state.Slot < slot {
|
|
if ctx.Err() != nil {
|
|
return nil, ctx.Err()
|
|
}
|
|
state, err := ProcessSlot(ctx, state)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process slot")
|
|
}
|
|
if CanProcessEpoch(state) {
|
|
state, err = ProcessEpoch(ctx, state)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process epoch")
|
|
}
|
|
}
|
|
state.Slot++
|
|
}
|
|
return state, nil
|
|
}
|
|
|
|
// ProcessBlock creates a new, modified beacon state by applying block operation
|
|
// transformations as defined in the Ethereum Serenity specification, including processing proposer slashings,
|
|
// processing block attestations, and more.
|
|
//
|
|
// Spec pseudocode definition:
|
|
//
|
|
// def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
|
// process_block_header(state, block)
|
|
// process_randao(state, block.body)
|
|
// process_eth1_data(state, block.body)
|
|
// process_operations(state, block.body)
|
|
func ProcessBlock(
|
|
ctx context.Context,
|
|
state *pb.BeaconState,
|
|
block *ethpb.BeaconBlock,
|
|
) (*pb.BeaconState, error) {
|
|
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessBlock")
|
|
defer span.End()
|
|
|
|
state, err := b.ProcessBlockHeader(state, block)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block header")
|
|
}
|
|
|
|
state, err = b.ProcessRandao(state, block.Body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not verify and process randao")
|
|
}
|
|
|
|
state, err = b.ProcessEth1DataInBlock(state, block)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process eth1 data")
|
|
}
|
|
|
|
state, err = ProcessOperations(ctx, state, block.Body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block operation")
|
|
}
|
|
|
|
return state, nil
|
|
}
|
|
|
|
// processBlockNoVerify creates a new, modified beacon state by applying block operation
|
|
// transformations as defined in the Ethereum Serenity specification. It does not validate
|
|
// block signature.
|
|
//
|
|
//
|
|
// WARNING: This method does not verify proposer signature. This is used for proposer to compute state root
|
|
// using a unsigned block.
|
|
//
|
|
// Spec pseudocode definition:
|
|
//
|
|
// def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
|
// process_block_header(state, block)
|
|
// process_randao(state, block.body)
|
|
// process_eth1_data(state, block.body)
|
|
// process_operations(state, block.body)
|
|
func processBlockNoVerify(
|
|
ctx context.Context,
|
|
state *pb.BeaconState,
|
|
block *ethpb.BeaconBlock,
|
|
) (*pb.BeaconState, error) {
|
|
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessBlock")
|
|
defer span.End()
|
|
|
|
state, err := b.ProcessBlockHeaderNoVerify(state, block)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block header")
|
|
}
|
|
|
|
state, err = b.ProcessRandao(state, block.Body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not verify and process randao")
|
|
}
|
|
|
|
state, err = b.ProcessEth1DataInBlock(state, block)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process eth1 data")
|
|
}
|
|
|
|
state, err = processOperationsNoVerify(ctx, state, block.Body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block operation")
|
|
}
|
|
|
|
return state, nil
|
|
}
|
|
|
|
// ProcessOperations processes the operations in the beacon block and updates beacon state
|
|
// with the operations in block.
|
|
//
|
|
// Spec pseudocode definition:
|
|
//
|
|
// def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
|
|
// # 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)
|
|
// # Verify that there are no duplicate transfers
|
|
// assert len(body.transfers) == len(set(body.transfers))
|
|
//
|
|
// all_operations = (
|
|
// (body.proposer_slashings, process_proposer_slashing),
|
|
// (body.attester_slashings, process_attester_slashing),
|
|
// (body.attestations, process_attestation),
|
|
// (body.deposits, process_deposit),
|
|
// (body.voluntary_exits, process_voluntary_exit),
|
|
// (body.transfers, process_transfer),
|
|
// ) # type: Sequence[Tuple[List, Callable]]
|
|
// for operations, function in all_operations:
|
|
// for operation in operations:
|
|
// function(state, operation)
|
|
func ProcessOperations(
|
|
ctx context.Context,
|
|
state *pb.BeaconState,
|
|
body *ethpb.BeaconBlockBody) (*pb.BeaconState, error) {
|
|
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessOperations")
|
|
defer span.End()
|
|
|
|
if err := verifyOperationLengths(state, body); err != nil {
|
|
return nil, errors.Wrap(err, "could not verify operation lengths")
|
|
}
|
|
|
|
// Verify that there are no duplicate transfers
|
|
transferSet := make(map[[32]byte]bool)
|
|
for _, transfer := range body.Transfers {
|
|
h, err := hashutil.HashProto(transfer)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not hash transfer")
|
|
}
|
|
if transferSet[h] {
|
|
return nil, fmt.Errorf("duplicate transfer: %v", transfer)
|
|
}
|
|
transferSet[h] = true
|
|
}
|
|
|
|
state, err := b.ProcessProposerSlashings(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block proposer slashings")
|
|
}
|
|
state, err = b.ProcessAttesterSlashings(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block attester slashings")
|
|
}
|
|
state, err = b.ProcessAttestations(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block attestations")
|
|
}
|
|
state, err = b.ProcessDeposits(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block validator deposits")
|
|
}
|
|
state, err = b.ProcessVoluntaryExits(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process validator exits")
|
|
}
|
|
state, err = b.ProcessTransfers(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block transfers")
|
|
}
|
|
|
|
return state, nil
|
|
}
|
|
|
|
// processOperationsNoVerify processes the operations in the beacon block and updates beacon state
|
|
// with the operations in block. It does not validate the attestation signature
|
|
//
|
|
// WARNING: This method does not verify attestation signature. This is used for proposer to compute state root
|
|
// using a unsigned block.
|
|
//
|
|
// Spec pseudocode definition:
|
|
//
|
|
// def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
|
|
// # 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)
|
|
// # Verify that there are no duplicate transfers
|
|
// assert len(body.transfers) == len(set(body.transfers))
|
|
//
|
|
// all_operations = (
|
|
// (body.proposer_slashings, process_proposer_slashing),
|
|
// (body.attester_slashings, process_attester_slashing),
|
|
// (body.attestations, process_attestation),
|
|
// (body.deposits, process_deposit),
|
|
// (body.voluntary_exits, process_voluntary_exit),
|
|
// (body.transfers, process_transfer),
|
|
// ) # type: Sequence[Tuple[List, Callable]]
|
|
// for operations, function in all_operations:
|
|
// for operation in operations:
|
|
// function(state, operation)
|
|
func processOperationsNoVerify(
|
|
ctx context.Context,
|
|
state *pb.BeaconState,
|
|
body *ethpb.BeaconBlockBody) (*pb.BeaconState, error) {
|
|
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessOperations")
|
|
defer span.End()
|
|
|
|
if err := verifyOperationLengths(state, body); err != nil {
|
|
return nil, errors.Wrap(err, "could not verify operation lengths")
|
|
}
|
|
|
|
// Verify that there are no duplicate transfers
|
|
transferSet := make(map[[32]byte]bool)
|
|
for _, transfer := range body.Transfers {
|
|
h, err := hashutil.HashProto(transfer)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not hash transfer")
|
|
}
|
|
if transferSet[h] {
|
|
return nil, fmt.Errorf("duplicate transfer: %v", transfer)
|
|
}
|
|
transferSet[h] = true
|
|
}
|
|
|
|
state, err := b.ProcessProposerSlashings(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block proposer slashings")
|
|
}
|
|
state, err = b.ProcessAttesterSlashings(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block attester slashings")
|
|
}
|
|
state, err = b.ProcessAttestationsNoVerify(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block attestations")
|
|
}
|
|
state, err = b.ProcessDeposits(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block validator deposits")
|
|
}
|
|
state, err = b.ProcessVoluntaryExits(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process validator exits")
|
|
}
|
|
state, err = b.ProcessTransfers(state, body)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process block transfers")
|
|
}
|
|
|
|
return state, nil
|
|
}
|
|
|
|
func verifyOperationLengths(state *pb.BeaconState, body *ethpb.BeaconBlockBody) error {
|
|
if uint64(len(body.ProposerSlashings)) > params.BeaconConfig().MaxProposerSlashings {
|
|
return fmt.Errorf(
|
|
"number of proposer slashings (%d) in block body exceeds allowed threshold of %d",
|
|
len(body.ProposerSlashings),
|
|
params.BeaconConfig().MaxProposerSlashings,
|
|
)
|
|
}
|
|
|
|
if uint64(len(body.AttesterSlashings)) > params.BeaconConfig().MaxAttesterSlashings {
|
|
return fmt.Errorf(
|
|
"number of attester slashings (%d) in block body exceeds allowed threshold of %d",
|
|
len(body.AttesterSlashings),
|
|
params.BeaconConfig().MaxAttesterSlashings,
|
|
)
|
|
}
|
|
|
|
if uint64(len(body.Attestations)) > params.BeaconConfig().MaxAttestations {
|
|
return fmt.Errorf(
|
|
"number of attestations (%d) in block body exceeds allowed threshold of %d",
|
|
len(body.Attestations),
|
|
params.BeaconConfig().MaxAttestations,
|
|
)
|
|
}
|
|
|
|
if uint64(len(body.VoluntaryExits)) > params.BeaconConfig().MaxVoluntaryExits {
|
|
return fmt.Errorf(
|
|
"number of voluntary exits (%d) in block body exceeds allowed threshold of %d",
|
|
len(body.VoluntaryExits),
|
|
params.BeaconConfig().MaxVoluntaryExits,
|
|
)
|
|
}
|
|
|
|
if uint64(len(body.Transfers)) > params.BeaconConfig().MaxTransfers {
|
|
return fmt.Errorf(
|
|
"number of transfers (%d) in block body exceeds allowed threshold of %d",
|
|
len(body.Transfers),
|
|
params.BeaconConfig().MaxTransfers,
|
|
)
|
|
}
|
|
|
|
if state.Eth1DepositIndex > state.Eth1Data.DepositCount {
|
|
return fmt.Errorf("expected state.deposit_index %d <= eth1data.deposit_count %d", state.Eth1DepositIndex, state.Eth1Data.DepositCount)
|
|
}
|
|
maxDeposits := mathutil.Min(params.BeaconConfig().MaxDeposits, state.Eth1Data.DepositCount-state.Eth1DepositIndex)
|
|
// Verify outstanding deposits are processed up to max number of deposits
|
|
if len(body.Deposits) != int(maxDeposits) {
|
|
return fmt.Errorf("incorrect outstanding deposits in block body, wanted: %d, got: %d",
|
|
maxDeposits, len(body.Deposits))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CanProcessEpoch checks the eligibility to process epoch.
|
|
// The epoch can be processed at the end of the last slot of every epoch
|
|
//
|
|
// Spec pseudocode definition:
|
|
// If (state.slot + 1) % SLOTS_PER_EPOCH == 0:
|
|
func CanProcessEpoch(state *pb.BeaconState) bool {
|
|
return (state.Slot+1)%params.BeaconConfig().SlotsPerEpoch == 0
|
|
}
|
|
|
|
// ProcessEpoch describes the per epoch operations that are performed on the
|
|
// beacon state. It focuses on the validator registry, adjusting balances, and finalizing slots.
|
|
//
|
|
// Spec pseudocode definition:
|
|
//
|
|
// def process_epoch(state: BeaconState) -> None:
|
|
// process_justification_and_finalization(state)
|
|
// process_crosslinks(state)
|
|
// process_rewards_and_penalties(state)
|
|
// process_registry_updates(state)
|
|
// # @process_reveal_deadlines
|
|
// # @process_challenge_deadlines
|
|
// process_slashings(state)
|
|
// process_final_updates(state)
|
|
// # @after_process_final_updates
|
|
func ProcessEpoch(ctx context.Context, state *pb.BeaconState) (*pb.BeaconState, error) {
|
|
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessEpoch")
|
|
defer span.End()
|
|
span.AddAttributes(trace.Int64Attribute("epoch", int64(helpers.SlotToEpoch(state.Slot))))
|
|
|
|
prevEpochAtts, err := e.MatchAttestations(state, helpers.PrevEpoch(state))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not get target atts prev epoch %d: %v",
|
|
helpers.PrevEpoch(state), err)
|
|
}
|
|
currentEpochAtts, err := e.MatchAttestations(state, helpers.CurrentEpoch(state))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not get target atts current epoch %d: %v",
|
|
helpers.CurrentEpoch(state), err)
|
|
}
|
|
prevEpochAttestedBalance, err := e.AttestingBalance(state, prevEpochAtts.Target)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not get attesting balance prev epoch")
|
|
}
|
|
currentEpochAttestedBalance, err := e.AttestingBalance(state, currentEpochAtts.Target)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not get attesting balance current epoch")
|
|
}
|
|
|
|
state, err = e.ProcessJustificationAndFinalization(state, prevEpochAttestedBalance, currentEpochAttestedBalance)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process justification")
|
|
}
|
|
|
|
state, err = e.ProcessCrosslinks(state)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process crosslink")
|
|
}
|
|
|
|
state, err = e.ProcessRewardsAndPenalties(state)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process rewards and penalties")
|
|
}
|
|
|
|
state, err = e.ProcessRegistryUpdates(state)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process registry updates")
|
|
}
|
|
|
|
state, err = e.ProcessSlashings(state)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process slashings")
|
|
}
|
|
|
|
state, err = e.ProcessFinalUpdates(state)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process final updates")
|
|
}
|
|
return state, nil
|
|
}
|