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 }