mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-17 23:38:46 +00:00
90 lines
3.1 KiB
Go
90 lines
3.1 KiB
Go
|
package kv
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
|
||
|
"github.com/pkg/errors"
|
||
|
types "github.com/prysmaticlabs/eth2-types"
|
||
|
statev2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
|
||
|
"github.com/prysmaticlabs/prysm/config/params"
|
||
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||
|
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||
|
)
|
||
|
|
||
|
// 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, stateReader, blockReader io.Reader) error {
|
||
|
// unmarshal both block and state before trying to save anything
|
||
|
// so that we fail early if there is any issue with the ssz data
|
||
|
blk := ðpb.SignedBeaconBlockAltair{}
|
||
|
bb, err := ioutil.ReadAll(blockReader)
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "error reading block given to SaveOrigin")
|
||
|
}
|
||
|
if err := blk.UnmarshalSSZ(bb); err != nil {
|
||
|
return errors.Wrap(err, "could not unmarshal checkpoint block")
|
||
|
}
|
||
|
wblk, err := wrapper.WrappedAltairSignedBeaconBlock(blk)
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "could not wrap checkpoint block")
|
||
|
}
|
||
|
bs, err := statev2.InitializeFromSSZReader(stateReader)
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "could not initialize checkpoint state from reader")
|
||
|
}
|
||
|
|
||
|
// save block
|
||
|
if err := s.SaveBlock(ctx, wblk); err != nil {
|
||
|
return errors.Wrap(err, "could not save checkpoint block")
|
||
|
}
|
||
|
blockRoot, err := blk.Block.HashTreeRoot()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "could not compute HashTreeRoot of checkpoint block")
|
||
|
}
|
||
|
|
||
|
// save state
|
||
|
if err = s.SaveState(ctx, bs, blockRoot); err != nil {
|
||
|
return errors.Wrap(err, "could not save state")
|
||
|
}
|
||
|
if err = s.SaveStateSummary(ctx, ðpb.StateSummary{
|
||
|
Slot: bs.Slot(),
|
||
|
Root: blockRoot[:],
|
||
|
}); err != nil {
|
||
|
return errors.Wrap(err, "could not save state summary")
|
||
|
}
|
||
|
|
||
|
// save origin block root in special key, to be used when the canonical
|
||
|
// origin (start of chain, ie alternative to genesis) block or state is needed
|
||
|
if err = s.SaveOriginBlockRoot(ctx, blockRoot); err != nil {
|
||
|
return errors.Wrap(err, "could not save origin block root")
|
||
|
}
|
||
|
|
||
|
// 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")
|
||
|
}
|
||
|
|
||
|
// rebuild the checkpoint from the block
|
||
|
// use it to mark the block as justified and finalized
|
||
|
slotEpoch, err := blk.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
|
||
|
}
|