diff --git a/beacon-chain/archiver/service.go b/beacon-chain/archiver/service.go index 0328100e8..8b122adb2 100644 --- a/beacon-chain/archiver/service.go +++ b/beacon-chain/archiver/service.go @@ -24,7 +24,7 @@ var log = logrus.WithField("prefix", "archiver") type Service struct { ctx context.Context cancel context.CancelFunc - beaconDB db.Database + beaconDB db.NoHeadAccessDatabase headFetcher blockchain.HeadFetcher participationFetcher blockchain.ParticipationFetcher stateNotifier statefeed.Notifier @@ -33,7 +33,7 @@ type Service struct { // Config options for the archiver service. type Config struct { - BeaconDB db.Database + BeaconDB db.NoHeadAccessDatabase HeadFetcher blockchain.HeadFetcher ParticipationFetcher blockchain.ParticipationFetcher StateNotifier statefeed.Notifier diff --git a/beacon-chain/blockchain/chain_info.go b/beacon-chain/blockchain/chain_info.go index 5f26c4d89..994c06899 100644 --- a/beacon-chain/blockchain/chain_info.go +++ b/beacon-chain/blockchain/chain_info.go @@ -17,7 +17,6 @@ import ( // directly retrieves chain info related data. type ChainInfoFetcher interface { HeadFetcher - CanonicalRootFetcher FinalizationFetcher } @@ -37,12 +36,6 @@ type HeadFetcher interface { HeadSeed(epoch uint64) ([32]byte, error) } -// CanonicalRootFetcher defines a common interface for methods in blockchain service which -// directly retrieves canonical roots related data. -type CanonicalRootFetcher interface { - CanonicalRoot(slot uint64) []byte -} - // ForkFetcher retrieves the current fork information of the Ethereum beacon chain. type ForkFetcher interface { CurrentFork() *pb.Fork @@ -167,14 +160,6 @@ func (s *Service) HeadSeed(epoch uint64) ([32]byte, error) { return helpers.Seed(s.headState, epoch, params.BeaconConfig().DomainBeaconAttester) } -// CanonicalRoot returns the canonical root of a given slot. -func (s *Service) CanonicalRoot(slot uint64) []byte { - s.headLock.RLock() - defer s.headLock.RUnlock() - - return s.canonicalRoots[slot] -} - // GenesisTime returns the genesis time of beacon chain. func (s *Service) GenesisTime() time.Time { return s.genesisTime diff --git a/beacon-chain/blockchain/chain_info_test.go b/beacon-chain/blockchain/chain_info_test.go index 1557eedc7..d88e48ec3 100644 --- a/beacon-chain/blockchain/chain_info_test.go +++ b/beacon-chain/blockchain/chain_info_test.go @@ -172,13 +172,3 @@ func TestCurrentFork_CanRetrieve(t *testing.T) { t.Error("Recieved incorrect fork version") } } - -func TestCanonicalRoot_CanRetrieve(t *testing.T) { - c := &Service{canonicalRoots: make(map[uint64][]byte)} - slot := uint64(123) - r := []byte{'B'} - c.canonicalRoots[slot] = r - if !bytes.Equal(r, c.CanonicalRoot(slot)) { - t.Errorf("Wanted head root: %v, got: %d", []byte{'A'}, c.CanonicalRoot(slot)) - } -} diff --git a/beacon-chain/blockchain/forkchoice/service.go b/beacon-chain/blockchain/forkchoice/service.go index 2c7ea8494..ef3f8013a 100644 --- a/beacon-chain/blockchain/forkchoice/service.go +++ b/beacon-chain/blockchain/forkchoice/service.go @@ -39,7 +39,7 @@ type ForkChoicer interface { type Store struct { ctx context.Context cancel context.CancelFunc - db db.Database + db db.HeadAccessDatabase justifiedCheckpt *ethpb.Checkpoint finalizedCheckpt *ethpb.Checkpoint prevFinalizedCheckpt *ethpb.Checkpoint @@ -58,7 +58,7 @@ type Store struct { // NewForkChoiceService instantiates a new service instance that will // be registered into a running beacon node. -func NewForkChoiceService(ctx context.Context, db db.Database) *Store { +func NewForkChoiceService(ctx context.Context, db db.HeadAccessDatabase) *Store { ctx, cancel := context.WithCancel(ctx) return &Store{ ctx: ctx, diff --git a/beacon-chain/blockchain/service.go b/beacon-chain/blockchain/service.go index 9e43ffa53..a753b7b34 100644 --- a/beacon-chain/blockchain/service.go +++ b/beacon-chain/blockchain/service.go @@ -10,6 +10,7 @@ import ( "sync" "time" + "github.com/gogo/protobuf/proto" "github.com/pkg/errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/go-ssz" @@ -37,7 +38,7 @@ import ( type Service struct { ctx context.Context cancel context.CancelFunc - beaconDB db.Database + beaconDB db.HeadAccessDatabase depositCache *depositcache.DepositCache chainStartFetcher powchain.ChainStartFetcher attPool attestations.Pool @@ -60,7 +61,7 @@ type Service struct { type Config struct { BeaconBlockBuf int ChainStartFetcher powchain.ChainStartFetcher - BeaconDB db.Database + BeaconDB db.HeadAccessDatabase DepositCache *depositcache.DepositCache AttPool attestations.Pool P2p p2p.Broadcaster @@ -248,7 +249,7 @@ func (s *Service) saveHead(ctx context.Context, signed *ethpb.SignedBeaconBlock, if err := s.beaconDB.SaveHeadBlockRoot(ctx, r); err != nil { return errors.Wrap(err, "could not save head root in DB") } - s.headBlock = signed + s.headBlock = proto.Clone(signed).(*ethpb.SignedBeaconBlock) headState, err := s.beaconDB.State(ctx, r) if err != nil { @@ -274,7 +275,7 @@ func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock, s.canonicalRoots[b.Block.Slot] = r[:] - s.headBlock = b + s.headBlock = proto.Clone(b).(*ethpb.SignedBeaconBlock) headState, err := s.beaconDB.State(ctx, r) if err != nil { diff --git a/beacon-chain/blockchain/service_test.go b/beacon-chain/blockchain/service_test.go index 623c3a201..638b51329 100644 --- a/beacon-chain/blockchain/service_test.go +++ b/beacon-chain/blockchain/service_test.go @@ -270,7 +270,7 @@ func TestChainService_InitializeBeaconChain(t *testing.T) { if bc.HeadBlock() == nil { t.Error("Head state can't be nil after initialize beacon chain") } - if bc.CanonicalRoot(0) == nil { + if bc.canonicalRoots[0] == nil { t.Error("Canonical root for slot 0 can't be nil after initialize beacon chain") } } diff --git a/beacon-chain/db/alias.go b/beacon-chain/db/alias.go index 90eaf0b6a..2b0c334fc 100644 --- a/beacon-chain/db/alias.go +++ b/beacon-chain/db/alias.go @@ -2,6 +2,23 @@ package db import "github.com/prysmaticlabs/prysm/beacon-chain/db/iface" -// Database defines the necessary methods for Prysm's eth2 backend which may -// be implemented by any key-value or relational database in practice. +// ReadOnlyDatabase exposes Prysm's eth2 data backend for read access only, no information about +// head info. For head info, use github.com/prysmaticlabs/prysm/blockchain.HeadFetcher. +type ReadOnlyDatabase = iface.ReadOnlyDatabase + +// NoHeadAccessDatabase exposes Prysm's eth2 data backend for read/write access, no information +// about head info. For head info, use github.com/prysmaticlabs/prysm/blockchain.HeadFetcher. +type NoHeadAccessDatabase = iface.NoHeadAccessDatabase + +// HeadAccessDatabase exposes Prysm's eth2 backend for read/write access with information about +// chain head information. This interface should be used sparingly as the HeadFetcher is the source +// of truth around chain head information while this interface serves as persistent storage for the +// head fetcher. +// +// See github.com/prysmaticlabs/prysm/blockchain.HeadFetcher +type HeadAccessDatabase = iface.HeadAccessDatabase + +// Database defines the necessary methods for Prysm's eth2 backend which may be implemented by any +// key-value or relational database in practice. This is the full database interface which should +// not be used often. Prefer a more restrictive interface in this package. type Database = iface.Database diff --git a/beacon-chain/db/iface/interface.go b/beacon-chain/db/iface/interface.go index 0df9e67f0..3ac6dfe95 100644 --- a/beacon-chain/db/iface/interface.go +++ b/beacon-chain/db/iface/interface.go @@ -13,82 +13,112 @@ import ( ethereum_beacon_p2p_v1 "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" ) -// Database defines the necessary methods for Prysm's eth2 backend which may -// be implemented by any key-value or relational database in practice. -type Database interface { - io.Closer - DatabasePath() string - ClearDB() error - // Backup and restore methods - Backup(ctx context.Context) error +// ReadOnlyDatabase -- See github.com/prysmaticlabs/prysm/beacon-chain/db.ReadOnlyDatabase +type ReadOnlyDatabase interface { // Attestation related methods. AttestationsByDataRoot(ctx context.Context, attDataRoot [32]byte) ([]*eth.Attestation, error) Attestations(ctx context.Context, f *filters.QueryFilter) ([]*eth.Attestation, error) HasAttestation(ctx context.Context, attDataRoot [32]byte) bool + // Block related methods. + Block(ctx context.Context, blockRoot [32]byte) (*eth.SignedBeaconBlock, error) + Blocks(ctx context.Context, f *filters.QueryFilter) ([]*eth.SignedBeaconBlock, error) + BlockRoots(ctx context.Context, f *filters.QueryFilter) ([][32]byte, error) + HasBlock(ctx context.Context, blockRoot [32]byte) bool + GenesisBlock(ctx context.Context) (*ethpb.SignedBeaconBlock, error) + IsFinalizedBlock(ctx context.Context, blockRoot [32]byte) bool + // Validator related methods. + ValidatorIndex(ctx context.Context, publicKey []byte) (uint64, bool, error) + HasValidatorIndex(ctx context.Context, publicKey []byte) bool + // State related methods. + State(ctx context.Context, blockRoot [32]byte) (*ethereum_beacon_p2p_v1.BeaconState, error) + GenesisState(ctx context.Context) (*ethereum_beacon_p2p_v1.BeaconState, error) + HasState(ctx context.Context, blockRoot [32]byte) bool + // Slashing operations. + ProposerSlashing(ctx context.Context, slashingRoot [32]byte) (*eth.ProposerSlashing, error) + AttesterSlashing(ctx context.Context, slashingRoot [32]byte) (*eth.AttesterSlashing, error) + HasProposerSlashing(ctx context.Context, slashingRoot [32]byte) bool + HasAttesterSlashing(ctx context.Context, slashingRoot [32]byte) bool + // Block operations. + VoluntaryExit(ctx context.Context, exitRoot [32]byte) (*eth.VoluntaryExit, error) + HasVoluntaryExit(ctx context.Context, exitRoot [32]byte) bool + // Checkpoint operations. + JustifiedCheckpoint(ctx context.Context) (*eth.Checkpoint, error) + FinalizedCheckpoint(ctx context.Context) (*eth.Checkpoint, error) + // Archival data handlers for storing/retrieving historical beacon node information. + ArchivedActiveValidatorChanges(ctx context.Context, epoch uint64) (*ethereum_beacon_p2p_v1.ArchivedActiveSetChanges, error) + ArchivedCommitteeInfo(ctx context.Context, epoch uint64) (*ethereum_beacon_p2p_v1.ArchivedCommitteeInfo, error) + ArchivedBalances(ctx context.Context, epoch uint64) ([]uint64, error) + ArchivedValidatorParticipation(ctx context.Context, epoch uint64) (*eth.ValidatorParticipation, error) + // Deposit contract related handlers. + DepositContractAddress(ctx context.Context) ([]byte, error) + // Powchain operations. + PowchainData(ctx context.Context) (*db.ETH1ChainData, error) +} + +// NoHeadAccessDatabase -- See github.com/prysmaticlabs/prysm/beacon-chain/db.NoHeadAccessDatabase +type NoHeadAccessDatabase interface { + ReadOnlyDatabase + + // Attestation related methods. DeleteAttestation(ctx context.Context, attDataRoot [32]byte) error DeleteAttestations(ctx context.Context, attDataRoots [][32]byte) error SaveAttestation(ctx context.Context, att *eth.Attestation) error SaveAttestations(ctx context.Context, atts []*eth.Attestation) error // Block related methods. - Block(ctx context.Context, blockRoot [32]byte) (*eth.SignedBeaconBlock, error) - HeadBlock(ctx context.Context) (*eth.SignedBeaconBlock, error) - Blocks(ctx context.Context, f *filters.QueryFilter) ([]*eth.SignedBeaconBlock, error) - BlockRoots(ctx context.Context, f *filters.QueryFilter) ([][32]byte, error) - HasBlock(ctx context.Context, blockRoot [32]byte) bool DeleteBlock(ctx context.Context, blockRoot [32]byte) error DeleteBlocks(ctx context.Context, blockRoots [][32]byte) error SaveBlock(ctx context.Context, block *eth.SignedBeaconBlock) error SaveBlocks(ctx context.Context, blocks []*eth.SignedBeaconBlock) error - SaveHeadBlockRoot(ctx context.Context, blockRoot [32]byte) error - GenesisBlock(ctx context.Context) (*ethpb.SignedBeaconBlock, error) SaveGenesisBlockRoot(ctx context.Context, blockRoot [32]byte) error - IsFinalizedBlock(ctx context.Context, blockRoot [32]byte) bool // Validator related methods. - ValidatorIndex(ctx context.Context, publicKey []byte) (uint64, bool, error) - HasValidatorIndex(ctx context.Context, publicKey []byte) bool DeleteValidatorIndex(ctx context.Context, publicKey []byte) error SaveValidatorIndex(ctx context.Context, publicKey []byte, validatorIdx uint64) error SaveValidatorIndices(ctx context.Context, publicKeys [][]byte, validatorIndices []uint64) error // State related methods. - State(ctx context.Context, blockRoot [32]byte) (*ethereum_beacon_p2p_v1.BeaconState, error) - HeadState(ctx context.Context) (*ethereum_beacon_p2p_v1.BeaconState, error) - GenesisState(ctx context.Context) (*ethereum_beacon_p2p_v1.BeaconState, error) SaveState(ctx context.Context, state *ethereum_beacon_p2p_v1.BeaconState, blockRoot [32]byte) error DeleteState(ctx context.Context, blockRoot [32]byte) error DeleteStates(ctx context.Context, blockRoots [][32]byte) error - HasState(ctx context.Context, blockRoot [32]byte) bool // Slashing operations. - ProposerSlashing(ctx context.Context, slashingRoot [32]byte) (*eth.ProposerSlashing, error) - AttesterSlashing(ctx context.Context, slashingRoot [32]byte) (*eth.AttesterSlashing, error) SaveProposerSlashing(ctx context.Context, slashing *eth.ProposerSlashing) error SaveAttesterSlashing(ctx context.Context, slashing *eth.AttesterSlashing) error - HasProposerSlashing(ctx context.Context, slashingRoot [32]byte) bool - HasAttesterSlashing(ctx context.Context, slashingRoot [32]byte) bool DeleteProposerSlashing(ctx context.Context, slashingRoot [32]byte) error DeleteAttesterSlashing(ctx context.Context, slashingRoot [32]byte) error // Block operations. - VoluntaryExit(ctx context.Context, exitRoot [32]byte) (*eth.VoluntaryExit, error) SaveVoluntaryExit(ctx context.Context, exit *eth.VoluntaryExit) error - HasVoluntaryExit(ctx context.Context, exitRoot [32]byte) bool DeleteVoluntaryExit(ctx context.Context, exitRoot [32]byte) error // Checkpoint operations. - JustifiedCheckpoint(ctx context.Context) (*eth.Checkpoint, error) - FinalizedCheckpoint(ctx context.Context) (*eth.Checkpoint, error) SaveJustifiedCheckpoint(ctx context.Context, checkpoint *eth.Checkpoint) error SaveFinalizedCheckpoint(ctx context.Context, checkpoint *eth.Checkpoint) error // Archival data handlers for storing/retrieving historical beacon node information. - ArchivedActiveValidatorChanges(ctx context.Context, epoch uint64) (*ethereum_beacon_p2p_v1.ArchivedActiveSetChanges, error) SaveArchivedActiveValidatorChanges(ctx context.Context, epoch uint64, changes *ethereum_beacon_p2p_v1.ArchivedActiveSetChanges) error - ArchivedCommitteeInfo(ctx context.Context, epoch uint64) (*ethereum_beacon_p2p_v1.ArchivedCommitteeInfo, error) SaveArchivedCommitteeInfo(ctx context.Context, epoch uint64, info *ethereum_beacon_p2p_v1.ArchivedCommitteeInfo) error - ArchivedBalances(ctx context.Context, epoch uint64) ([]uint64, error) SaveArchivedBalances(ctx context.Context, epoch uint64, balances []uint64) error - ArchivedValidatorParticipation(ctx context.Context, epoch uint64) (*eth.ValidatorParticipation, error) SaveArchivedValidatorParticipation(ctx context.Context, epoch uint64, part *eth.ValidatorParticipation) error // Deposit contract related handlers. - DepositContractAddress(ctx context.Context) ([]byte, error) SaveDepositContractAddress(ctx context.Context, addr common.Address) error - //Powchain operations - PowchainData(ctx context.Context) (*db.ETH1ChainData, error) + // Powchain operations. SavePowchainData(ctx context.Context, data *db.ETH1ChainData) error } + +// HeadAccessDatabase -- See github.com/prysmaticlabs/prysm/beacon-chain/db.HeadAccessDatabase +type HeadAccessDatabase interface { + NoHeadAccessDatabase + + // Block related methods. + HeadBlock(ctx context.Context) (*eth.SignedBeaconBlock, error) + SaveHeadBlockRoot(ctx context.Context, blockRoot [32]byte) error + // State related methods. + HeadState(ctx context.Context) (*ethereum_beacon_p2p_v1.BeaconState, error) +} + +// Database -- See github.com/prysmaticlabs/prysm/beacon-chain/db.Database +type Database interface { + io.Closer + HeadAccessDatabase + + DatabasePath() string + ClearDB() error + + // Backup and restore methods + Backup(ctx context.Context) error +} diff --git a/beacon-chain/interop-cold-start/service.go b/beacon-chain/interop-cold-start/service.go index f86cce451..ab0b2ab96 100644 --- a/beacon-chain/interop-cold-start/service.go +++ b/beacon-chain/interop-cold-start/service.go @@ -29,7 +29,7 @@ type Service struct { cancel context.CancelFunc genesisTime uint64 numValidators uint64 - beaconDB db.Database + beaconDB db.HeadAccessDatabase powchain powchain.Service depositCache *depositcache.DepositCache genesisPath string @@ -40,7 +40,7 @@ type Service struct { type Config struct { GenesisTime uint64 NumValidators uint64 - BeaconDB db.Database + BeaconDB db.HeadAccessDatabase DepositCache *depositcache.DepositCache GenesisPath string } diff --git a/beacon-chain/powchain/service.go b/beacon-chain/powchain/service.go index 3489bedf9..841ef92d2 100644 --- a/beacon-chain/powchain/service.go +++ b/beacon-chain/powchain/service.go @@ -131,7 +131,7 @@ type Service struct { depositRoot []byte depositTrie *trieutil.SparseMerkleTrie chainStartData *protodb.ChainStartData - beaconDB db.Database + beaconDB db.HeadAccessDatabase // Circular dep if using HeadFetcher. depositCache *depositcache.DepositCache lastReceivedMerkleIndex int64 // Keeps track of the last received index to prevent log spam. isRunning bool @@ -147,7 +147,7 @@ type Web3ServiceConfig struct { ETH1Endpoint string HTTPEndPoint string DepositContract common.Address - BeaconDB db.Database + BeaconDB db.HeadAccessDatabase DepositCache *depositcache.DepositCache StateNotifier statefeed.Notifier } diff --git a/beacon-chain/rpc/aggregator/server.go b/beacon-chain/rpc/aggregator/server.go index cce61a2c4..f377acc71 100644 --- a/beacon-chain/rpc/aggregator/server.go +++ b/beacon-chain/rpc/aggregator/server.go @@ -25,7 +25,7 @@ func init() { // Server defines a server implementation of the gRPC aggregator service. type Server struct { - BeaconDB db.Database + BeaconDB db.ReadOnlyDatabase HeadFetcher blockchain.HeadFetcher SyncChecker sync.Checker AttPool attestations.Pool diff --git a/beacon-chain/rpc/aggregator/server_test.go b/beacon-chain/rpc/aggregator/server_test.go index 6c13c0537..06b8df0fa 100644 --- a/beacon-chain/rpc/aggregator/server_test.go +++ b/beacon-chain/rpc/aggregator/server_test.go @@ -99,7 +99,7 @@ func TestSubmitAggregateAndProof_IsAggregator(t *testing.T) { sig := priv.Sign([]byte{'A'}, 0) pubKey := pubKey(1) req := &pb.AggregationRequest{CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey} - if err := aggregatorServer.BeaconDB.SaveValidatorIndex(ctx, pubKey, 100); err != nil { + if err := db.SaveValidatorIndex(ctx, pubKey, 100); err != nil { t.Fatal(err) } @@ -137,7 +137,7 @@ func TestSubmitAggregateAndProof_AggregateOk(t *testing.T) { sig := priv.Sign([]byte{'B'}, 0) pubKey := pubKey(2) req := &pb.AggregationRequest{CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey} - if err := aggregatorServer.BeaconDB.SaveValidatorIndex(ctx, pubKey, 100); err != nil { + if err := db.SaveValidatorIndex(ctx, pubKey, 100); err != nil { t.Fatal(err) } @@ -190,7 +190,7 @@ func TestSubmitAggregateAndProof_AggregateNotOk(t *testing.T) { sig := priv.Sign([]byte{'B'}, 0) pubKey := pubKey(2) req := &pb.AggregationRequest{CommitteeIndex: 1, SlotSignature: sig.Marshal(), PublicKey: pubKey} - if err := aggregatorServer.BeaconDB.SaveValidatorIndex(ctx, pubKey, 100); err != nil { + if err := db.SaveValidatorIndex(ctx, pubKey, 100); err != nil { t.Fatal(err) } diff --git a/beacon-chain/rpc/beacon/server.go b/beacon-chain/rpc/beacon/server.go index fbbcafef9..91e368ea5 100644 --- a/beacon-chain/rpc/beacon/server.go +++ b/beacon-chain/rpc/beacon/server.go @@ -18,7 +18,7 @@ import ( // providing RPC endpoints to access data relevant to the Ethereum 2.0 phase 0 // beacon chain. type Server struct { - BeaconDB db.Database + BeaconDB db.ReadOnlyDatabase Ctx context.Context ChainStartFetcher powchain.ChainStartFetcher HeadFetcher blockchain.HeadFetcher diff --git a/beacon-chain/rpc/node/server.go b/beacon-chain/rpc/node/server.go index b8d3f4eb4..1fe12ea18 100644 --- a/beacon-chain/rpc/node/server.go +++ b/beacon-chain/rpc/node/server.go @@ -24,7 +24,7 @@ import ( type Server struct { SyncChecker sync.Checker Server *grpc.Server - BeaconDB db.Database + BeaconDB db.ReadOnlyDatabase PeersFetcher p2p.PeersProvider GenesisTimeFetcher blockchain.GenesisTimeFetcher } diff --git a/beacon-chain/rpc/service.go b/beacon-chain/rpc/service.go index d17c34f13..978978efa 100644 --- a/beacon-chain/rpc/service.go +++ b/beacon-chain/rpc/service.go @@ -52,7 +52,7 @@ func init() { type Service struct { ctx context.Context cancel context.CancelFunc - beaconDB db.Database + beaconDB db.ReadOnlyDatabase headFetcher blockchain.HeadFetcher forkFetcher blockchain.ForkFetcher finalizationFetcher blockchain.FinalizationFetcher @@ -91,7 +91,7 @@ type Config struct { Port string CertFlag string KeyFlag string - BeaconDB db.Database + BeaconDB db.ReadOnlyDatabase HeadFetcher blockchain.HeadFetcher ForkFetcher blockchain.ForkFetcher FinalizationFetcher blockchain.FinalizationFetcher diff --git a/beacon-chain/rpc/validator/attester.go b/beacon-chain/rpc/validator/attester.go index 5a6e09ca7..643ce337f 100644 --- a/beacon-chain/rpc/validator/attester.go +++ b/beacon-chain/rpc/validator/attester.go @@ -56,18 +56,11 @@ func (vs *Server) GetAttestationData(ctx context.Context, req *ethpb.Attestation } }() - headState, err := vs.BeaconDB.HeadState(ctx) + headState, err := vs.HeadFetcher.HeadState(ctx) if err != nil { return nil, status.Errorf(codes.Internal, "Could not retrieve head state: %v", err) } - headBlock, err := vs.BeaconDB.HeadBlock(ctx) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not retrieve head block: %v", err) - } - headRoot, err := ssz.HashTreeRoot(headBlock.Block) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not hash head block: %v", err) - } + headRoot := vs.HeadFetcher.HeadRoot() if helpers.CurrentEpoch(headState) < helpers.SlotToEpoch(req.Slot) { headState, err = state.ProcessSlots(ctx, headState, req.Slot) diff --git a/beacon-chain/rpc/validator/attester_test.go b/beacon-chain/rpc/validator/attester_test.go index 09a451d92..cedb00f57 100644 --- a/beacon-chain/rpc/validator/attester_test.go +++ b/beacon-chain/rpc/validator/attester_test.go @@ -158,13 +158,13 @@ func TestGetAttestationData_OK(t *testing.T) { AttestationCache: cache.NewAttestationCache(), HeadFetcher: &mock.ChainService{State: beaconState, Root: blockRoot[:]}, } - if err := attesterServer.BeaconDB.SaveState(ctx, beaconState, blockRoot); err != nil { + if err := db.SaveState(ctx, beaconState, blockRoot); err != nil { t.Fatal(err) } - if err := attesterServer.BeaconDB.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: block}); err != nil { + if err := db.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: block}); err != nil { t.Fatal(err) } - if err := attesterServer.BeaconDB.SaveHeadBlockRoot(ctx, blockRoot); err != nil { + if err := db.SaveHeadBlockRoot(ctx, blockRoot); err != nil { t.Fatal(err) } @@ -263,13 +263,13 @@ func TestAttestationDataAtSlot_handlesFarAwayJustifiedEpoch(t *testing.T) { HeadFetcher: &mock.ChainService{State: beaconState, Root: blockRoot[:]}, SyncChecker: &mockSync.Sync{IsSyncing: false}, } - if err := attesterServer.BeaconDB.SaveState(ctx, beaconState, blockRoot); err != nil { + if err := db.SaveState(ctx, beaconState, blockRoot); err != nil { t.Fatal(err) } - if err := attesterServer.BeaconDB.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: block}); err != nil { + if err := db.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: block}); err != nil { t.Fatal(err) } - if err := attesterServer.BeaconDB.SaveHeadBlockRoot(ctx, blockRoot); err != nil { + if err := db.SaveHeadBlockRoot(ctx, blockRoot); err != nil { t.Fatal(err) } diff --git a/beacon-chain/rpc/validator/proposer.go b/beacon-chain/rpc/validator/proposer.go index 2706a04ec..dd7ee5d7e 100644 --- a/beacon-chain/rpc/validator/proposer.go +++ b/beacon-chain/rpc/validator/proposer.go @@ -36,15 +36,7 @@ func (vs *Server) GetBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb } // Retrieve the parent block as the current head of the canonical chain. - parent, err := vs.BeaconDB.HeadBlock(ctx) - if err != nil { - return nil, err - } - - parentRoot, err := ssz.HashTreeRoot(parent.Block) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not get parent block signing root: %v", err) - } + parentRoot := vs.HeadFetcher.HeadRoot() eth1Data, err := vs.eth1Data(ctx, req.Slot) if err != nil { @@ -340,7 +332,7 @@ func (vs *Server) filterAttestationsForBlockInclusion(ctx context.Context, slot validAtts := make([]*ethpb.Attestation, 0, len(atts)) inValidAtts := make([]*ethpb.Attestation, 0, len(atts)) - bState, err := vs.BeaconDB.HeadState(ctx) + bState, err := vs.HeadFetcher.HeadState(ctx) if err != nil { return nil, errors.New("could not head state from DB") } diff --git a/beacon-chain/rpc/validator/proposer_test.go b/beacon-chain/rpc/validator/proposer_test.go index 259f512d7..54024be6d 100644 --- a/beacon-chain/rpc/validator/proposer_test.go +++ b/beacon-chain/rpc/validator/proposer_test.go @@ -68,7 +68,7 @@ func TestProposeBlock_OK(t *testing.T) { Body: ðpb.BeaconBlockBody{}, }, } - if err := proposerServer.BeaconDB.SaveBlock(ctx, req); err != nil { + if err := db.SaveBlock(ctx, req); err != nil { t.Fatal(err) } if _, err := proposerServer.ProposeBlock(context.Background(), req); err != nil { @@ -1026,8 +1026,9 @@ func TestFilterAttestation_OK(t *testing.T) { } proposerServer := &Server{ - BeaconDB: db, - AttPool: attestations.NewPool(), + BeaconDB: db, + AttPool: attestations.NewPool(), + HeadFetcher: &mock.ChainService{State: state, Root: genesisRoot[:]}, } atts := make([]*ethpb.Attestation, 10) diff --git a/beacon-chain/rpc/validator/server.go b/beacon-chain/rpc/validator/server.go index 61e885c98..a3161df34 100644 --- a/beacon-chain/rpc/validator/server.go +++ b/beacon-chain/rpc/validator/server.go @@ -37,7 +37,7 @@ func init() { // and more. type Server struct { Ctx context.Context - BeaconDB db.Database + BeaconDB db.ReadOnlyDatabase AttestationCache *cache.AttestationCache HeadFetcher blockchain.HeadFetcher ForkFetcher blockchain.ForkFetcher @@ -161,7 +161,7 @@ func (vs *Server) CanonicalHead(ctx context.Context, req *ptypes.Empty) (*ethpb. // subscribes to an event stream triggered by the powchain service whenever the ChainStart log does // occur in the Deposit Contract on ETH 1.0. func (vs *Server) WaitForChainStart(req *ptypes.Empty, stream ethpb.BeaconNodeValidator_WaitForChainStartServer) error { - head, err := vs.BeaconDB.HeadState(context.Background()) + head, err := vs.HeadFetcher.HeadState(context.Background()) if err != nil { return status.Errorf(codes.Internal, "Could not retrieve head state: %v", err) } diff --git a/beacon-chain/rpc/validator/server_test.go b/beacon-chain/rpc/validator/server_test.go index df4a96661..b89c8021c 100644 --- a/beacon-chain/rpc/validator/server_test.go +++ b/beacon-chain/rpc/validator/server_test.go @@ -228,6 +228,7 @@ func TestWaitForChainStart_ContextClosed(t *testing.T) { }, StateNotifier: chainService.StateNotifier(), BeaconDB: db, + HeadFetcher: chainService, } exitRoutine := make(chan bool) @@ -256,7 +257,7 @@ func TestWaitForChainStart_AlreadyStarted(t *testing.T) { t.Fatal(err) } - chainService := &mockChain.ChainService{} + chainService := &mockChain.ChainService{State: &pbp2p.BeaconState{Slot: 3}} Server := &Server{ Ctx: context.Background(), ChainStartFetcher: &mockPOW.POWChain{ @@ -264,6 +265,7 @@ func TestWaitForChainStart_AlreadyStarted(t *testing.T) { }, BeaconDB: db, StateNotifier: chainService.StateNotifier(), + HeadFetcher: chainService, } ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -292,6 +294,7 @@ func TestWaitForChainStart_NotStartedThenLogFired(t *testing.T) { }, BeaconDB: db, StateNotifier: chainService.StateNotifier(), + HeadFetcher: chainService, } exitRoutine := make(chan bool) ctrl := gomock.NewController(t) diff --git a/beacon-chain/sync/initial-sync/service.go b/beacon-chain/sync/initial-sync/service.go index 96acb040b..9567257bc 100644 --- a/beacon-chain/sync/initial-sync/service.go +++ b/beacon-chain/sync/initial-sync/service.go @@ -32,7 +32,7 @@ const ( // Config to set up the initial sync service. type Config struct { P2P p2p.P2P - DB db.Database + DB db.ReadOnlyDatabase Chain blockchainService StateNotifier statefeed.Notifier } @@ -42,7 +42,7 @@ type Service struct { ctx context.Context chain blockchainService p2p p2p.P2P - db db.Database + db db.ReadOnlyDatabase synced bool chainStarted bool stateNotifier statefeed.Notifier diff --git a/beacon-chain/sync/service.go b/beacon-chain/sync/service.go index 58e0272a7..27eb96cb6 100644 --- a/beacon-chain/sync/service.go +++ b/beacon-chain/sync/service.go @@ -19,7 +19,7 @@ var _ = shared.Service(&Service{}) // Config to set up the regular sync service. type Config struct { P2P p2p.P2P - DB db.Database + DB db.NoHeadAccessDatabase AttPool attestations.Pool Chain blockchainService InitialSync Checker @@ -64,7 +64,7 @@ type Service struct { ctx context.Context cancel context.CancelFunc p2p p2p.P2P - db db.Database + db db.NoHeadAccessDatabase attPool attestations.Pool chain blockchainService slotToPendingBlocks map[uint64]*ethpb.SignedBeaconBlock