mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-03 17:44:29 +00:00
4d35e776da
start of abstracting the transition layer. incremental movements.
104 lines
4.0 KiB
Go
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
|
|
}
|