start refactoring and deprecation round 1

This commit is contained in:
Preston Van Loon
2020-01-11 22:13:23 -08:00
parent 7992375a0e
commit 008f992993
8 changed files with 72 additions and 52 deletions

View File

@@ -29,11 +29,17 @@ type GenesisTimeFetcher interface {
// HeadFetcher defines a common interface for methods in blockchain service which
// directly retrieves head related data.
type HeadFetcher interface {
// Deprecated: Use beacondb.TODO.
HeadSlot() uint64
// Deprecated: Use beacondb.TODO.
HeadRoot() []byte
// Deprecated: Use beacondb.HeadBlock.
HeadBlock() *ethpb.SignedBeaconBlock
// Deprecated: Use beacondb.HeadState.
HeadState(ctx context.Context) (*pb.BeaconState, error)
// Deprecated: Use beacondb.TODO.
HeadValidatorsIndices(epoch uint64) ([]uint64, error)
// Deprecated: Use beacondb.TODO.
HeadSeed(epoch uint64) ([32]byte, error)
}
@@ -51,8 +57,12 @@ type ForkFetcher interface {
// FinalizationFetcher defines a common interface for methods in blockchain service which
// directly retrieves finalization and justification related data.
type FinalizationFetcher interface {
// Deprecated: Use beacondb.FinalizedCheckpoint.
FinalizedCheckpt() *ethpb.Checkpoint
// Deprecated: Use beacondb.CurrentJustifiedCheckpoint.
CurrentJustifiedCheckpt() *ethpb.Checkpoint
// Deprecated: Use beacondb.TODO.
// TODO: Write a beacondb method to return this value.
PreviousJustifiedCheckpt() *ethpb.Checkpoint
}
@@ -63,48 +73,50 @@ type ParticipationFetcher interface {
}
// FinalizedCheckpt returns the latest finalized checkpoint from head state.
// Deprecated: Use beacondb.FinalizedCheckpoint.
func (s *Service) FinalizedCheckpt() *ethpb.Checkpoint {
if s.headState == nil || s.headState.FinalizedCheckpoint == nil {
headState, err := s.beaconDB.HeadState(context.TODO())
if err != nil || headState == nil || headState.FinalizedCheckpoint == nil {
return &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
}
// If head state exists but there hasn't been a finalized check point,
// the check point's root should refer to genesis block root.
if bytes.Equal(s.headState.FinalizedCheckpoint.Root, params.BeaconConfig().ZeroHash[:]) {
if bytes.Equal(headState.FinalizedCheckpoint.Root, params.BeaconConfig().ZeroHash[:]) {
return &ethpb.Checkpoint{Root: s.genesisRoot[:]}
}
return s.headState.FinalizedCheckpoint
return headState.FinalizedCheckpoint
}
// CurrentJustifiedCheckpt returns the current justified checkpoint from head state.
// Deprecated: Use beacondb.JustifiedCheckpoint.
func (s *Service) CurrentJustifiedCheckpt() *ethpb.Checkpoint {
if s.headState == nil || s.headState.CurrentJustifiedCheckpoint == nil {
return &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
}
c, _ := s.beaconDB.JustifiedCheckpoint(context.TODO())
// If head state exists but there hasn't been a justified check point,
// the check point root should refer to genesis block root.
if bytes.Equal(s.headState.CurrentJustifiedCheckpoint.Root, params.BeaconConfig().ZeroHash[:]) {
if bytes.Equal(c.Root, params.BeaconConfig().ZeroHash[:]) {
return &ethpb.Checkpoint{Root: s.genesisRoot[:]}
}
return s.headState.CurrentJustifiedCheckpoint
return c
}
// PreviousJustifiedCheckpt returns the previous justified checkpoint from head state.
// TODO: This is a full state read that could be another method in the DB.
func (s *Service) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
if s.headState == nil || s.headState.PreviousJustifiedCheckpoint == nil {
headState, _ := s.HeadState(context.TODO())
if headState == nil || headState.PreviousJustifiedCheckpoint == nil {
return &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
}
// If head state exists but there hasn't been a justified check point,
// the check point root should refer to genesis block root.
if bytes.Equal(s.headState.PreviousJustifiedCheckpoint.Root, params.BeaconConfig().ZeroHash[:]) {
if bytes.Equal(headState.PreviousJustifiedCheckpoint.Root, params.BeaconConfig().ZeroHash[:]) {
return &ethpb.Checkpoint{Root: s.genesisRoot[:]}
}
return s.headState.PreviousJustifiedCheckpoint
return headState.PreviousJustifiedCheckpoint
}
// HeadSlot returns the slot of the head of the chain.
@@ -129,42 +141,41 @@ func (s *Service) HeadRoot() []byte {
}
// HeadBlock returns the head block of the chain.
// Deprecated: Use beacondb.HeadBlock.
func (s *Service) HeadBlock() *ethpb.SignedBeaconBlock {
s.headLock.RLock()
defer s.headLock.RUnlock()
return proto.Clone(s.headBlock).(*ethpb.SignedBeaconBlock)
hb, _ := s.beaconDB.HeadBlock(context.TODO())
return hb
}
// HeadState returns the head state of the chain.
// If the head state is nil from service struct,
// it will attempt to get from DB and error if nil again.
// Deprecated: Use beacondb.HeadState.
func (s *Service) HeadState(ctx context.Context) (*pb.BeaconState, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
if s.headState == nil {
return s.beaconDB.HeadState(ctx)
}
return proto.Clone(s.headState).(*pb.BeaconState), nil
return s.beaconDB.HeadState(ctx)
}
// HeadValidatorsIndices returns a list of active validator indices from the head view of a given epoch.
// TODO: This is a full state read. Maybe it can be reduced?
func (s *Service) HeadValidatorsIndices(epoch uint64) ([]uint64, error) {
if s.headState == nil {
headState, _ := s.HeadState(context.TODO())
if headState == nil {
return []uint64{}, nil
}
return helpers.ActiveValidatorIndices(s.headState, epoch)
return helpers.ActiveValidatorIndices(headState, epoch)
}
// HeadSeed returns the seed from the head view of a given epoch.
func (s *Service) HeadSeed(epoch uint64) ([32]byte, error) {
if s.headState == nil {
headState, err := s.beaconDB.HeadState(context.TODO())
if err != nil {
return [32]byte{}, err
}
if headState == nil {
return [32]byte{}, nil
}
return helpers.Seed(s.headState, epoch, params.BeaconConfig().DomainBeaconAttester)
return helpers.Seed(headState, epoch, params.BeaconConfig().DomainBeaconAttester)
}
// CanonicalRoot returns the canonical root of a given slot.
@@ -181,14 +192,16 @@ func (s *Service) GenesisTime() time.Time {
}
// CurrentFork retrieves the latest fork information of the beacon chain.
// TODO: Can this be improved? It is a full state read now just for the fork.
func (s *Service) CurrentFork() *pb.Fork {
if s.headState == nil {
headState, _ := s.beaconDB.HeadState(context.TODO())
if headState == nil {
return &pb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
}
}
return proto.Clone(s.headState.Fork).(*pb.Fork)
return proto.Clone(headState.Fork).(*pb.Fork)
}
// Participation returns the participation stats of a given epoch.

View File

@@ -26,6 +26,7 @@ import (
// ForkChoicer defines a common interface for methods useful for directly applying fork choice
// to beacon blocks to compute head.
type ForkChoicer interface {
// Deprecated: use beacondb.Head.
Head(ctx context.Context) ([]byte, error)
OnBlock(ctx context.Context, b *ethpb.SignedBeaconBlock) error
OnBlockInitialSyncStateTransition(ctx context.Context, b *ethpb.SignedBeaconBlock) error

View File

@@ -1,6 +1,8 @@
package blockchain
import (
"context"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
@@ -61,8 +63,13 @@ func (s *Service) reportSlotMetrics(currentSlot uint64) {
beaconSlot.Set(float64(currentSlot))
beaconHeadSlot.Set(float64(s.HeadSlot()))
beaconHeadRoot.Set(float64(bytesutil.ToLowInt64(s.HeadRoot())))
if s.headState != nil {
headFinalizedEpoch.Set(float64(s.headState.FinalizedCheckpoint.Epoch))
headFinalizedRoot.Set(float64(bytesutil.ToLowInt64(s.headState.FinalizedCheckpoint.Root)))
fc, err := s.beaconDB.FinalizedCheckpoint(context.TODO())
if err != nil {
log.WithError(err).Error("Failed to fetch finalized checkpoint from database.")
return
}
if fc != nil {
headFinalizedEpoch.Set(float64(fc.Epoch))
headFinalizedRoot.Set(float64(bytesutil.ToLowInt64(fc.Root)))
}
}

View File

@@ -47,7 +47,6 @@ type Service struct {
maxRoutines int64
headSlot uint64
headBlock *ethpb.SignedBeaconBlock
headState *pb.BeaconState
canonicalRoots map[uint64][]byte
headLock sync.RWMutex
stateNotifier statefeed.Notifier
@@ -252,12 +251,6 @@ func (s *Service) saveHead(ctx context.Context, signed *ethpb.SignedBeaconBlock,
}
s.headBlock = signed
headState, err := s.beaconDB.State(ctx, r)
if err != nil {
return errors.Wrap(err, "could not retrieve head state in DB")
}
s.headState = headState
log.WithFields(logrus.Fields{
"slot": signed.Block.Slot,
"headRoot": fmt.Sprintf("%#x", r),
@@ -278,12 +271,6 @@ func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock,
s.headBlock = b
headState, err := s.beaconDB.State(ctx, r)
if err != nil {
return errors.Wrap(err, "could not retrieve head state in DB")
}
s.headState = headState
log.WithFields(logrus.Fields{
"slot": b.Block.Slot,
"headRoot": fmt.Sprintf("%#x", r),
@@ -340,7 +327,6 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState *pb.BeaconSt
s.genesisRoot = genesisBlkRoot
s.headBlock = genesisBlk
s.headState = genesisState
s.canonicalRoots[genesisState.Slot] = genesisBlkRoot[:]
return nil
@@ -373,10 +359,6 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
// would be the genesis state and block.
return errors.New("no finalized epoch in the database")
}
s.headState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(finalized.Root))
if err != nil {
return errors.Wrap(err, "could not get finalized state from db")
}
s.headBlock, err = s.beaconDB.Block(ctx, bytesutil.ToBytes32(finalized.Root))
if err != nil {
return errors.Wrap(err, "could not get finalized block from db")

View File

@@ -12,6 +12,7 @@ import (
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
@@ -320,8 +321,14 @@ func (k *Store) SaveHeadBlockRoot(ctx context.Context, blockRoot [32]byte) error
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveHeadBlockRoot")
defer span.End()
return k.db.Update(func(tx *bolt.Tx) error {
if tx.Bucket(stateBucket).Get(blockRoot[:]) == nil {
if head := tx.Bucket(stateBucket).Get(blockRoot[:]); head == nil {
return errors.New("no state found with head block root")
} else {
h := &pb.BeaconState{}
if err := decode(head, h); err != nil {
return errors.Wrap(err, "could not unmarshal head state")
}
k.headState = h
}
bucket := tx.Bucket(blocksBucket)
return bucket.Put(headBlockRootKey, blockRoot[:])

View File

@@ -12,6 +12,7 @@ import (
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prysmaticlabs/prysm/beacon-chain/db/iface"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
)
var _ = iface.Database(&Store{})
@@ -36,6 +37,7 @@ type Store struct {
databasePath string
blockCache *ristretto.Cache
validatorIndexCache *ristretto.Cache
headState *pb.BeaconState
}
// NewKVStore initializes a new boltDB key-value store at the directory

View File

@@ -5,6 +5,7 @@ import (
"context"
"github.com/boltdb/bolt"
"github.com/gogo/protobuf/proto"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -35,6 +36,9 @@ func (k *Store) State(ctx context.Context, blockRoot [32]byte) (*pb.BeaconState,
func (k *Store) HeadState(ctx context.Context) (*pb.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "BeaconDB.HeadState")
defer span.End()
if k.headState != nil {
return proto.Clone(k.headState).(*pb.BeaconState), nil
}
var s *pb.BeaconState
err := k.db.View(func(tx *bolt.Tx) error {
// Retrieve head block's signing root from blocks bucket,

View File

@@ -72,6 +72,10 @@ func TestHeadState_CanSaveRetrieve(t *testing.T) {
if !reflect.DeepEqual(s, savedHeadS) {
t.Error("did not retrieve saved state")
}
if !reflect.DeepEqual(s, db.headState) {
t.Error("did not cache head state")
}
}
func TestGenesisState_CanSaveRetrieve(t *testing.T) {