prysm-pulse/beacon-chain/db/kv/archived_point.go
2020-03-02 08:55:38 +01:00

102 lines
3.1 KiB
Go

package kv
import (
"context"
"github.com/boltdb/bolt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"go.opencensus.io/trace"
)
// SaveArchivedPointState saves an archived point state to the DB. This is used for cold state management.
// An archive point index is `slot / slots_per_archive_point`.
func (k *Store) SaveArchivedPointState(ctx context.Context, state *state.BeaconState, index uint64) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveArchivedPointState")
defer span.End()
if state == nil {
return errors.New("nil state")
}
enc, err := encode(state.InnerStateUnsafe())
if err != nil {
return err
}
return k.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(archivedIndexStateBucket)
return bucket.Put(uint64ToBytes(index), enc)
})
}
// SaveArchivedPointRoot saves an archived point root to the DB. This is used for cold state management.
func (k *Store) SaveArchivedPointRoot(ctx context.Context, blockRoot [32]byte, index uint64) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveArchivedPointRoot")
defer span.End()
return k.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(archivedIndexRootBucket)
return bucket.Put(uint64ToBytes(index), blockRoot[:])
})
}
// ArchivedPointState returns the state of an archived point from the DB.
// This is essential for cold state management and to restore a cold state.
func (k *Store) ArchivedPointState(ctx context.Context, index uint64) (*state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "BeaconDB.ArchivedPointState")
defer span.End()
var s *pb.BeaconState
err := k.db.View(func(tx *bolt.Tx) error {
bucket := tx.Bucket(archivedIndexStateBucket)
enc := bucket.Get(uint64ToBytes(index))
if enc == nil {
return nil
}
var err error
s, err = createState(enc)
return err
})
if err != nil {
return nil, err
}
if s == nil {
return nil, nil
}
return state.InitializeFromProtoUnsafe(s)
}
// ArchivedPointRoot returns the block root of an archived point from the DB.
// This is essential for cold state management and to restore a cold state.
func (k *Store) ArchivedPointRoot(ctx context.Context, index uint64) [32]byte {
ctx, span := trace.StartSpan(ctx, "BeaconDB.ArchivePointRoot")
defer span.End()
var blockRoot []byte
// #nosec G104. Always returns nil.
k.db.View(func(tx *bolt.Tx) error {
bucket := tx.Bucket(archivedIndexRootBucket)
blockRoot = bucket.Get(uint64ToBytes(index))
return nil
})
return bytesutil.ToBytes32(blockRoot)
}
// HasArchivedPoint returns true if an archived point exists in DB.
func (k *Store) HasArchivedPoint(ctx context.Context, index uint64) bool {
ctx, span := trace.StartSpan(ctx, "BeaconDB.HasArchivedPoint")
defer span.End()
var exists bool
// #nosec G104. Always returns nil.
k.db.View(func(tx *bolt.Tx) error {
iBucket := tx.Bucket(archivedIndexRootBucket)
sBucket := tx.Bucket(archivedIndexStateBucket)
exists = iBucket.Get(uint64ToBytes(index)) != nil &&
sBucket.Get(uint64ToBytes(index)) != nil
return nil
})
return exists
}