2020-03-14 16:31:21 +00:00
|
|
|
package stategen
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
2020-08-27 22:29:59 +00:00
|
|
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
2020-03-14 16:31:21 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
2020-08-27 22:29:59 +00:00
|
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
2020-07-28 18:35:17 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
2020-08-03 18:34:54 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
2020-03-14 16:31:21 +00:00
|
|
|
"go.opencensus.io/trace"
|
|
|
|
)
|
|
|
|
|
2020-08-27 22:29:59 +00:00
|
|
|
// SaveState saves the state in the cache and/or DB.
|
2020-03-14 16:31:21 +00:00
|
|
|
func (s *State) SaveState(ctx context.Context, root [32]byte, state *state.BeaconState) error {
|
|
|
|
ctx, span := trace.StartSpan(ctx, "stateGen.SaveState")
|
|
|
|
defer span.End()
|
|
|
|
|
2020-08-27 22:29:59 +00:00
|
|
|
return s.saveStateByRoot(ctx, root, state)
|
2020-03-14 16:31:21 +00:00
|
|
|
}
|
2020-07-28 18:35:17 +00:00
|
|
|
|
|
|
|
// ForceCheckpoint initiates a cold state save of the given state. This method does not update the
|
|
|
|
// "last archived state" but simply saves the specified state from the root argument into the DB.
|
|
|
|
func (s *State) ForceCheckpoint(ctx context.Context, root []byte) error {
|
|
|
|
ctx, span := trace.StartSpan(ctx, "stateGen.ForceCheckpoint")
|
|
|
|
defer span.End()
|
|
|
|
|
|
|
|
root32 := bytesutil.ToBytes32(root)
|
2020-08-03 18:34:54 +00:00
|
|
|
// Before the first finalized check point, the finalized root is zero hash.
|
|
|
|
// Return early if there hasn't been a finalized check point.
|
|
|
|
if root32 == params.BeaconConfig().ZeroHash {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-08-27 22:29:59 +00:00
|
|
|
fs, err := s.loadStateByRoot(ctx, root32)
|
2020-07-28 18:35:17 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-10-09 23:39:23 +00:00
|
|
|
return s.beaconDB.SaveState(ctx, fs, root32)
|
2020-07-28 18:35:17 +00:00
|
|
|
}
|
2020-08-27 22:29:59 +00:00
|
|
|
|
|
|
|
// SaveStateSummary saves the relevant state summary for a block and its corresponding state slot in the
|
|
|
|
// state summary cache.
|
|
|
|
func (s *State) SaveStateSummary(ctx context.Context, blk *ethpb.SignedBeaconBlock, blockRoot [32]byte) {
|
|
|
|
// Save State summary
|
|
|
|
s.stateSummaryCache.Put(blockRoot, &pb.StateSummary{
|
|
|
|
Slot: blk.Block.Slot,
|
|
|
|
Root: blockRoot[:],
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// This saves a post beacon state. On the epoch boundary,
|
|
|
|
// it saves a full state. On an intermediate slot, it saves a back pointer to the
|
|
|
|
// nearest epoch boundary state.
|
|
|
|
func (s *State) saveStateByRoot(ctx context.Context, blockRoot [32]byte, state *state.BeaconState) error {
|
|
|
|
ctx, span := trace.StartSpan(ctx, "stateGen.saveStateByRoot")
|
|
|
|
defer span.End()
|
|
|
|
|
|
|
|
// If the hot state is already in cache, one can be sure the state was processed and in the DB.
|
|
|
|
if s.hotStateCache.Has(blockRoot) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only on an epoch boundary slot, saves epoch boundary state in epoch boundary root state cache.
|
|
|
|
if helpers.IsEpochStart(state.Slot()) {
|
|
|
|
if err := s.epochBoundaryStateCache.put(blockRoot, state); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// On an intermediate slots, save the hot state summary.
|
|
|
|
s.stateSummaryCache.Put(blockRoot, &pb.StateSummary{
|
|
|
|
Slot: state.Slot(),
|
|
|
|
Root: blockRoot[:],
|
|
|
|
})
|
|
|
|
|
|
|
|
// Store the copied state in the hot state cache.
|
|
|
|
s.hotStateCache.Put(blockRoot, state)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|