mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-26 05:17:22 +00:00
de0143e036
* save origin block root before finalize * add test for SaveOrigin * goimports :( * signature to LoadGenesis changed in a diff PR Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: terence tsao <terence@prysmaticlabs.com> Co-authored-by: Radosław Kapka <rkapka@wp.pl>
105 lines
3.8 KiB
Go
105 lines
3.8 KiB
Go
package kv
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/pkg/errors"
|
|
types "github.com/prysmaticlabs/eth2-types"
|
|
"github.com/prysmaticlabs/prysm/config/params"
|
|
"github.com/prysmaticlabs/prysm/encoding/ssz/detect"
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/runtime/version"
|
|
)
|
|
|
|
// SaveOrigin loads an ssz serialized Block & BeaconState from an io.Reader
|
|
// (ex: an open file) prepares the database so that the beacon node can begin
|
|
// syncing, using the provided values as their point of origin. This is an alternative
|
|
// to syncing from genesis, and should only be run on an empty database.
|
|
func (s *Store) SaveOrigin(ctx context.Context, serState, serBlock []byte) error {
|
|
genesisRoot, err := s.GenesisBlockRoot(ctx)
|
|
if err != nil {
|
|
if errors.Is(err, ErrNotFoundGenesisBlockRoot) {
|
|
return errors.Wrap(err, "genesis block root not found: genesis must be provided for checkpoint sync")
|
|
}
|
|
return errors.Wrap(err, "genesis block root query error: checkpoint sync must verify genesis to proceed")
|
|
}
|
|
err = s.SaveBackfillBlockRoot(ctx, genesisRoot)
|
|
if err != nil {
|
|
return errors.Wrap(err, "unable to save genesis root as initial backfill starting point for checkpoint sync")
|
|
}
|
|
|
|
cf, err := detect.FromState(serState)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not sniff config+fork for origin state bytes")
|
|
}
|
|
_, ok := params.BeaconConfig().ForkVersionSchedule[cf.Version]
|
|
if !ok {
|
|
return fmt.Errorf("config mismatch, beacon node configured to connect to %s, detected state is for %s", params.BeaconConfig().ConfigName, cf.Config.ConfigName)
|
|
}
|
|
|
|
log.Infof("detected supported config for state & block version, config name=%s, fork name=%s", cf.Config.ConfigName, version.String(cf.Fork))
|
|
state, err := cf.UnmarshalBeaconState(serState)
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to initialize origin state w/ bytes + config+fork")
|
|
}
|
|
|
|
wblk, err := cf.UnmarshalBeaconBlock(serBlock)
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to initialize origin block w/ bytes + config+fork")
|
|
}
|
|
blk := wblk.Block()
|
|
|
|
// save block
|
|
blockRoot, err := blk.HashTreeRoot()
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not compute HashTreeRoot of checkpoint block")
|
|
}
|
|
log.Infof("saving checkpoint block to db, w/ root=%#x", blockRoot)
|
|
if err := s.SaveBlock(ctx, wblk); err != nil {
|
|
return errors.Wrap(err, "could not save checkpoint block")
|
|
}
|
|
|
|
// save state
|
|
log.Infof("calling SaveState w/ blockRoot=%x", blockRoot)
|
|
if err = s.SaveState(ctx, state, blockRoot); err != nil {
|
|
return errors.Wrap(err, "could not save state")
|
|
}
|
|
if err = s.SaveStateSummary(ctx, ðpb.StateSummary{
|
|
Slot: state.Slot(),
|
|
Root: blockRoot[:],
|
|
}); err != nil {
|
|
return errors.Wrap(err, "could not save state summary")
|
|
}
|
|
|
|
// mark block as head of chain, so that processing will pick up from this point
|
|
if err = s.SaveHeadBlockRoot(ctx, blockRoot); err != nil {
|
|
return errors.Wrap(err, "could not save head block root")
|
|
}
|
|
|
|
// save origin block root in a special key, to be used when the canonical
|
|
// origin (start of chain, ie alternative to genesis) block or state is needed
|
|
if err = s.SaveOriginCheckpointBlockRoot(ctx, blockRoot); err != nil {
|
|
return errors.Wrap(err, "could not save origin block root")
|
|
}
|
|
|
|
// rebuild the checkpoint from the block
|
|
// use it to mark the block as justified and finalized
|
|
slotEpoch, err := wblk.Block().Slot().SafeDivSlot(params.BeaconConfig().SlotsPerEpoch)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
chkpt := ðpb.Checkpoint{
|
|
Epoch: types.Epoch(slotEpoch),
|
|
Root: blockRoot[:],
|
|
}
|
|
if err = s.SaveJustifiedCheckpoint(ctx, chkpt); err != nil {
|
|
return errors.Wrap(err, "could not mark checkpoint sync block as justified")
|
|
}
|
|
if err = s.SaveFinalizedCheckpoint(ctx, chkpt); err != nil {
|
|
return errors.Wrap(err, "could not mark checkpoint sync block as finalized")
|
|
}
|
|
|
|
return nil
|
|
}
|