mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 23:48:06 -05:00
Split out forkchoice setup from service start (#14997)
This commit is contained in:
@@ -26,6 +26,7 @@ go_library(
|
|||||||
"receive_blob.go",
|
"receive_blob.go",
|
||||||
"receive_block.go",
|
"receive_block.go",
|
||||||
"service.go",
|
"service.go",
|
||||||
|
"setup_forchoice.go",
|
||||||
"tracked_proposer.go",
|
"tracked_proposer.go",
|
||||||
"weak_subjectivity_checks.go",
|
"weak_subjectivity_checks.go",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -2039,7 +2039,7 @@ func TestNoViableHead_Reboot(t *testing.T) {
|
|||||||
require.Equal(t, genesisRoot, bytesutil.ToBytes32(headRoot))
|
require.Equal(t, genesisRoot, bytesutil.ToBytes32(headRoot))
|
||||||
optimistic, err := service.IsOptimistic(ctx)
|
optimistic, err := service.IsOptimistic(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, false, optimistic)
|
require.Equal(t, true, optimistic)
|
||||||
|
|
||||||
// Check that the node's justified checkpoint does not agree with the
|
// Check that the node's justified checkpoint does not agree with the
|
||||||
// last valid state's justified checkpoint
|
// last valid state's justified checkpoint
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
package blockchain
|
package blockchain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -23,7 +22,6 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem"
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem"
|
||||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/execution"
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/execution"
|
||||||
f "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice"
|
f "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice"
|
||||||
forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types"
|
|
||||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations"
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations"
|
||||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/blstoexec"
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/blstoexec"
|
||||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/slashings"
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/slashings"
|
||||||
@@ -32,7 +30,6 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/startup"
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/startup"
|
||||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen"
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen"
|
||||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
|
||||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||||
@@ -269,69 +266,18 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.originBlockRoot = originRoot
|
s.originBlockRoot = originRoot
|
||||||
|
st, err := s.cfg.StateGen.Resume(s.ctx, s.cfg.FinalizedStateAtStartUp)
|
||||||
if err := s.initializeHeadFromDB(s.ctx); err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not set up chain info")
|
return errors.Wrap(err, "could not get finalized state from db")
|
||||||
}
|
}
|
||||||
spawnCountdownIfPreGenesis(s.ctx, s.genesisTime, s.cfg.BeaconDB)
|
spawnCountdownIfPreGenesis(s.ctx, s.genesisTime, s.cfg.BeaconDB)
|
||||||
|
if err := s.setupForkchoice(st); err != nil {
|
||||||
justified, err := s.cfg.BeaconDB.JustifiedCheckpoint(s.ctx)
|
return errors.Wrap(err, "could not set up forkchoice")
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "could not get justified checkpoint")
|
|
||||||
}
|
|
||||||
if justified == nil {
|
|
||||||
return errNilJustifiedCheckpoint
|
|
||||||
}
|
|
||||||
finalized, err := s.cfg.BeaconDB.FinalizedCheckpoint(s.ctx)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "could not get finalized checkpoint")
|
|
||||||
}
|
|
||||||
if finalized == nil {
|
|
||||||
return errNilFinalizedCheckpoint
|
|
||||||
}
|
|
||||||
|
|
||||||
fRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
|
||||||
s.cfg.ForkChoiceStore.Lock()
|
|
||||||
defer s.cfg.ForkChoiceStore.Unlock()
|
|
||||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(s.ctx, &forkchoicetypes.Checkpoint{Epoch: justified.Epoch,
|
|
||||||
Root: bytesutil.ToBytes32(justified.Root)}); err != nil {
|
|
||||||
return errors.Wrap(err, "could not update forkchoice's justified checkpoint")
|
|
||||||
}
|
|
||||||
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: finalized.Epoch,
|
|
||||||
Root: bytesutil.ToBytes32(finalized.Root)}); err != nil {
|
|
||||||
return errors.Wrap(err, "could not update forkchoice's finalized checkpoint")
|
|
||||||
}
|
|
||||||
s.cfg.ForkChoiceStore.SetGenesisTime(uint64(s.genesisTime.Unix()))
|
|
||||||
|
|
||||||
st, err := s.cfg.StateGen.StateByRoot(s.ctx, fRoot)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "could not get finalized checkpoint state")
|
|
||||||
}
|
|
||||||
finalizedBlock, err := s.cfg.BeaconDB.Block(s.ctx, fRoot)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "could not get finalized checkpoint block")
|
|
||||||
}
|
|
||||||
roblock, err := blocks.NewROBlockWithRoot(finalizedBlock, fRoot)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.cfg.ForkChoiceStore.InsertNode(s.ctx, st, roblock); err != nil {
|
|
||||||
return errors.Wrap(err, "could not insert finalized block to forkchoice")
|
|
||||||
}
|
|
||||||
if !features.Get().EnableStartOptimistic {
|
|
||||||
lastValidatedCheckpoint, err := s.cfg.BeaconDB.LastValidatedCheckpoint(s.ctx)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "could not get last validated checkpoint")
|
|
||||||
}
|
|
||||||
if bytes.Equal(finalized.Root, lastValidatedCheckpoint.Root) {
|
|
||||||
if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(s.ctx, fRoot); err != nil {
|
|
||||||
return errors.Wrap(err, "could not set finalized block as validated")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// not attempting to save initial sync blocks here, because there shouldn't be any until
|
// not attempting to save initial sync blocks here, because there shouldn't be any until
|
||||||
// after the statefeed.Initialized event is fired (below)
|
// after the statefeed.Initialized event is fired (below)
|
||||||
if err := s.wsVerifier.VerifyWeakSubjectivity(s.ctx, finalized.Epoch); err != nil {
|
cp := s.FinalizedCheckpt()
|
||||||
|
if err := s.wsVerifier.VerifyWeakSubjectivity(s.ctx, cp.Epoch); err != nil {
|
||||||
// Exit run time if the node failed to verify weak subjectivity checkpoint.
|
// Exit run time if the node failed to verify weak subjectivity checkpoint.
|
||||||
return errors.Wrap(err, "could not verify initial checkpoint provided for chain sync")
|
return errors.Wrap(err, "could not verify initial checkpoint provided for chain sync")
|
||||||
}
|
}
|
||||||
@@ -340,7 +286,6 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error {
|
|||||||
if err := s.clockSetter.SetClock(startup.NewClock(s.genesisTime, vr)); err != nil {
|
if err := s.clockSetter.SetClock(startup.NewClock(s.genesisTime, vr)); err != nil {
|
||||||
return errors.Wrap(err, "failed to initialize blockchain service")
|
return errors.Wrap(err, "failed to initialize blockchain service")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,23 +318,10 @@ func (s *Service) originRootFromSavedState(ctx context.Context) ([32]byte, error
|
|||||||
// initializeHeadFromDB uses the finalized checkpoint and head block found in the database to set the current head.
|
// initializeHeadFromDB uses the finalized checkpoint and head block found in the database to set the current head.
|
||||||
// Note that this may block until stategen replays blocks between the finalized and head blocks
|
// Note that this may block until stategen replays blocks between the finalized and head blocks
|
||||||
// if the head sync flag was specified and the gap between the finalized and head blocks is at least 128 epochs long.
|
// if the head sync flag was specified and the gap between the finalized and head blocks is at least 128 epochs long.
|
||||||
func (s *Service) initializeHeadFromDB(ctx context.Context) error {
|
func (s *Service) initializeHeadFromDB(ctx context.Context, finalizedState state.BeaconState) error {
|
||||||
finalized, err := s.cfg.BeaconDB.FinalizedCheckpoint(ctx)
|
cp := s.FinalizedCheckpt()
|
||||||
if err != nil {
|
fRoot := [32]byte(cp.Root)
|
||||||
return errors.Wrap(err, "could not get finalized checkpoint from db")
|
finalizedRoot := s.ensureRootNotZeros(fRoot)
|
||||||
}
|
|
||||||
if finalized == nil {
|
|
||||||
// This should never happen. At chain start, the finalized checkpoint
|
|
||||||
// would be the genesis state and block.
|
|
||||||
return errors.New("no finalized epoch in the database")
|
|
||||||
}
|
|
||||||
finalizedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
|
||||||
var finalizedState state.BeaconState
|
|
||||||
|
|
||||||
finalizedState, err = s.cfg.StateGen.Resume(ctx, s.cfg.FinalizedStateAtStartUp)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "could not get finalized state from db")
|
|
||||||
}
|
|
||||||
|
|
||||||
if finalizedState == nil || finalizedState.IsNil() {
|
if finalizedState == nil || finalizedState.IsNil() {
|
||||||
return errors.New("finalized state can't be nil")
|
return errors.New("finalized state can't be nil")
|
||||||
|
|||||||
84
beacon-chain/blockchain/setup_forchoice.go
Normal file
84
beacon-chain/blockchain/setup_forchoice.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package blockchain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types"
|
||||||
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||||
|
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||||
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||||
|
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Service) setupForkchoice(st state.BeaconState) error {
|
||||||
|
if err := s.setupForkchoiceCheckpoints(); err != nil {
|
||||||
|
return errors.Wrap(err, "could not set up forkchoice checkpoints")
|
||||||
|
}
|
||||||
|
if err := s.setupForkchoiceRoot(st); err != nil {
|
||||||
|
return errors.Wrap(err, "could not set up forkchoice root")
|
||||||
|
}
|
||||||
|
if err := s.initializeHeadFromDB(s.ctx, st); err != nil {
|
||||||
|
return errors.Wrap(err, "could not initialize head from db")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) setupForkchoiceRoot(st state.BeaconState) error {
|
||||||
|
cp := s.FinalizedCheckpt()
|
||||||
|
fRoot := s.ensureRootNotZeros([32]byte(cp.Root))
|
||||||
|
finalizedBlock, err := s.cfg.BeaconDB.Block(s.ctx, fRoot)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not get finalized checkpoint block")
|
||||||
|
}
|
||||||
|
roblock, err := blocks.NewROBlockWithRoot(finalizedBlock, fRoot)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.cfg.ForkChoiceStore.InsertNode(s.ctx, st, roblock); err != nil {
|
||||||
|
return errors.Wrap(err, "could not insert finalized block to forkchoice")
|
||||||
|
}
|
||||||
|
if !features.Get().EnableStartOptimistic {
|
||||||
|
lastValidatedCheckpoint, err := s.cfg.BeaconDB.LastValidatedCheckpoint(s.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not get last validated checkpoint")
|
||||||
|
}
|
||||||
|
if bytes.Equal(fRoot[:], lastValidatedCheckpoint.Root) {
|
||||||
|
if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(s.ctx, fRoot); err != nil {
|
||||||
|
return errors.Wrap(err, "could not set finalized block as validated")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) setupForkchoiceCheckpoints() error {
|
||||||
|
justified, err := s.cfg.BeaconDB.JustifiedCheckpoint(s.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not get justified checkpoint")
|
||||||
|
}
|
||||||
|
if justified == nil {
|
||||||
|
return errNilJustifiedCheckpoint
|
||||||
|
}
|
||||||
|
finalized, err := s.cfg.BeaconDB.FinalizedCheckpoint(s.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not get finalized checkpoint")
|
||||||
|
}
|
||||||
|
if finalized == nil {
|
||||||
|
return errNilFinalizedCheckpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
fRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
||||||
|
s.cfg.ForkChoiceStore.Lock()
|
||||||
|
defer s.cfg.ForkChoiceStore.Unlock()
|
||||||
|
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(s.ctx, &forkchoicetypes.Checkpoint{Epoch: justified.Epoch,
|
||||||
|
Root: bytesutil.ToBytes32(justified.Root)}); err != nil {
|
||||||
|
return errors.Wrap(err, "could not update forkchoice's justified checkpoint")
|
||||||
|
}
|
||||||
|
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: finalized.Epoch,
|
||||||
|
Root: fRoot}); err != nil {
|
||||||
|
return errors.Wrap(err, "could not update forkchoice's finalized checkpoint")
|
||||||
|
}
|
||||||
|
s.cfg.ForkChoiceStore.SetGenesisTime(uint64(s.genesisTime.Unix()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
3
changelog/potuz_forkchoice_startup.md
Normal file
3
changelog/potuz_forkchoice_startup.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
### Ignored
|
||||||
|
|
||||||
|
- Split out forkchoice startup from the main service startup.
|
||||||
Reference in New Issue
Block a user