erigon-pulse/cmd/erigon-cl/forkchoice/utils.go
a 30430d585a
begin refactor of beacon state (#7433)
this first major move separates the transient beacon state cache from
the underlying tree.

leaf updates are enforced in the setters, which should make programming
easier.

all exported methods of the raw.BeaconState should be safe to call
(without disrupting internal state)

changes many functions to consume *raw.BeaconState in perparation for
interface


beyond refactor it also:

adds a pool for the leaves of the validator ssz hash 

adds a pool for the snappy writers
  
removed the parallel hash experiment (high memory use)
2023-05-04 15:18:42 +02:00

98 lines
3.7 KiB
Go

package forkchoice
import (
"fmt"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/transition"
"github.com/ledgerwatch/log/v3"
)
// Slot calculates the current slot number using the time and genesis slot.
func (f *ForkChoiceStore) Slot() uint64 {
return f.forkGraph.Config().GenesisSlot + ((f.time - f.forkGraph.GenesisTime()) / f.forkGraph.Config().SecondsPerSlot)
}
// updateCheckpoints updates the justified and finalized checkpoints if new checkpoints have higher epochs.
func (f *ForkChoiceStore) updateCheckpoints(justifiedCheckpoint, finalizedCheckpoint *cltypes.Checkpoint) {
if justifiedCheckpoint.Epoch > f.justifiedCheckpoint.Epoch {
f.justifiedCheckpoint = justifiedCheckpoint
}
if finalizedCheckpoint.Epoch > f.finalizedCheckpoint.Epoch {
f.finalizedCheckpoint = finalizedCheckpoint
}
}
// updateCheckpoints updates the justified and finalized checkpoints if new checkpoints have higher epochs.
func (f *ForkChoiceStore) updateUnrealizedCheckpoints(justifiedCheckpoint, finalizedCheckpoint *cltypes.Checkpoint) {
if justifiedCheckpoint.Epoch > f.unrealizedJustifiedCheckpoint.Epoch {
f.unrealizedJustifiedCheckpoint = justifiedCheckpoint
}
if finalizedCheckpoint.Epoch > f.unrealizedFinalizedCheckpoint.Epoch {
f.unrealizedFinalizedCheckpoint = finalizedCheckpoint
}
}
// computeEpochAtSlot calculates the epoch at a given slot number.
func (f *ForkChoiceStore) computeEpochAtSlot(slot uint64) uint64 {
return slot / f.forkGraph.Config().SlotsPerEpoch
}
// computeStartSlotAtEpoch calculates the starting slot of a given epoch.
func (f *ForkChoiceStore) computeStartSlotAtEpoch(epoch uint64) uint64 {
return epoch * f.forkGraph.Config().SlotsPerEpoch
}
// computeSlotsSinceEpochStart calculates the number of slots since the start of the epoch of a given slot.
func (f *ForkChoiceStore) computeSlotsSinceEpochStart(slot uint64) uint64 {
return slot - f.computeStartSlotAtEpoch(f.computeEpochAtSlot(slot))
}
// Ancestor returns the ancestor to the given root.
func (f *ForkChoiceStore) Ancestor(root libcommon.Hash, slot uint64) libcommon.Hash {
header, has := f.forkGraph.GetHeader(root)
if !has {
return libcommon.Hash{}
}
for header.Slot > slot {
root = header.ParentRoot
header, has = f.forkGraph.GetHeader(header.ParentRoot)
if !has {
return libcommon.Hash{}
}
}
return root
}
// getCheckpointState computes and caches checkpoint states.
func (f *ForkChoiceStore) getCheckpointState(checkpoint cltypes.Checkpoint) (*checkpointState, error) {
// check if it can be found in cache.
if state, ok := f.checkpointStates.Get(checkpoint); ok {
return state, nil
}
// If it is not in cache compute it and then put in cache.
baseState, err := f.forkGraph.GetState(checkpoint.Root, true)
if err != nil {
return nil, err
}
if baseState == nil {
return nil, fmt.Errorf("getCheckpointState: baseState not found in graph")
}
// By default use the no change encoding to signal that there is no future epoch here.
if baseState.Slot() < f.computeStartSlotAtEpoch(checkpoint.Epoch) {
log.Debug("Long checkpoint detected")
// If we require to change it then process the future epoch
if err := transition.ProcessSlots(baseState, f.computeStartSlotAtEpoch(checkpoint.Epoch)); err != nil {
return nil, err
}
}
mixes := baseState.RandaoMixes()
checkpointState := newCheckpointState(f.forkGraph.Config(), baseState.Validators(),
mixes[:], baseState.GenesisValidatorsRoot(), baseState.Fork(), baseState.GetTotalActiveBalance(), state.Epoch(baseState.BeaconState))
// Cache in memory what we are left with.
f.checkpointStates.Add(checkpoint, checkpointState)
return checkpointState, nil
}