erigon-pulse/cl/phase1/forkchoice/utils.go
a 4d35e776da
[caplin] abstract transition (#7661)
start of abstracting the transition layer. 

incremental movements.
2023-06-11 23:50:02 +02:00

104 lines
4.0 KiB
Go

package forkchoice
import (
"fmt"
"github.com/ledgerwatch/erigon/cl/transition"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/cltypes/solid"
"github.com/ledgerwatch/erigon/cl/phase1/core/state"
"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 solid.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 solid.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 solid.Checkpoint) (*checkpointState, error) {
// check if it can be found in cache.
if state, ok := f.checkpointStates.Get(checkpointComparable(checkpoint)); ok {
return state, nil
}
// If it is not in cache compute it and then put in cache.
baseState, _, err := f.forkGraph.GetState(checkpoint.BlockRoot(), 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.DefaultMachine.ProcessSlots(baseState, f.computeStartSlotAtEpoch(checkpoint.Epoch())); err != nil {
return nil, err
}
}
mixes := baseState.RandaoMixes()
// TODO: make this copy smarter when validators is a smarter struct
validators := make([]solid.Validator, baseState.ValidatorLength())
baseState.ForEachValidator(func(v solid.Validator, idx, total int) bool {
validators[idx] = v
return true
})
checkpointState := newCheckpointState(f.forkGraph.Config(), validators,
mixes, baseState.GenesisValidatorsRoot(), baseState.Fork(), baseState.GetTotalActiveBalance(), state.Epoch(baseState.BeaconState))
// Cache in memory what we are left with.
f.checkpointStates.Add(checkpointComparable(checkpoint), checkpointState)
return checkpointState, nil
}