mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 04:47:18 +00:00
Part 9 of update fork choice - HeadBlock and HeadState getters (#3279)
* Headblock and headstate getters * Moved mutex around
This commit is contained in:
parent
0d64f7b80e
commit
c47598514c
@ -3,6 +3,7 @@ package blockchain
|
||||
import (
|
||||
"time"
|
||||
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
|
||||
)
|
||||
|
||||
@ -20,6 +21,8 @@ type ChainInfoRetriever interface {
|
||||
type HeadRetriever interface {
|
||||
HeadSlot() uint64
|
||||
HeadRoot() []byte
|
||||
HeadBlock() *ethpb.BeaconBlock
|
||||
HeadState() *pb.BeaconState
|
||||
}
|
||||
|
||||
// CanonicalRetriever defines a common interface for methods in blockchain service which
|
||||
@ -52,6 +55,16 @@ func (c *ChainService) HeadRoot() []byte {
|
||||
return c.canonicalRoots[c.headSlot]
|
||||
}
|
||||
|
||||
// HeadBlock returns the head block of the chain.
|
||||
func (c *ChainService) HeadBlock() *ethpb.BeaconBlock {
|
||||
return c.headBlock
|
||||
}
|
||||
|
||||
// HeadState returns the head state of the chain.
|
||||
func (c *ChainService) HeadState() *pb.BeaconState {
|
||||
return c.headState
|
||||
}
|
||||
|
||||
// CanonicalRoot returns the canonical root of a given slot.
|
||||
func (c *ChainService) CanonicalRoot(slot uint64) []byte {
|
||||
c.canonicalRootsLock.RLock()
|
||||
|
@ -3,11 +3,13 @@ package blockchain
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
|
||||
)
|
||||
|
||||
// Ensure ChainService implements chain info interface.
|
||||
@ -47,11 +49,28 @@ func TestHeadRoot_CanRetrieve(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeadBlock_CanRetrieve(t *testing.T) {
|
||||
b := ðpb.BeaconBlock{Slot: 1}
|
||||
c := &ChainService{headBlock: b}
|
||||
if !reflect.DeepEqual(b, c.HeadBlock()) {
|
||||
t.Error("incorrect head block received")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeadState_CanRetrieve(t *testing.T) {
|
||||
s := &pb.BeaconState{Slot: 2}
|
||||
c := &ChainService{headState: s}
|
||||
if !reflect.DeepEqual(s, c.HeadState()) {
|
||||
t.Error("incorrect head state received")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanonicalRoot_CanRetrieve(t *testing.T) {
|
||||
c := &ChainService{canonicalRoots: make(map[uint64][]byte)}
|
||||
slot := uint64(123)
|
||||
c.canonicalRoots[slot] = []byte{'B'}
|
||||
if !bytes.Equal([]byte{'B'}, c.CanonicalRoot(slot)) {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,6 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -140,61 +137,3 @@ func (c *ChainService) CleanupBlockOperations(ctx context.Context, block *ethpb.
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// saveValidatorIdx saves the validators public key to index mapping in DB, these
|
||||
// validators were activated from current epoch. After it saves, current epoch key
|
||||
// is deleted from ActivatedValidators mapping.
|
||||
func (c *ChainService) saveValidatorIdx(ctx context.Context, state *pb.BeaconState) error {
|
||||
nextEpoch := helpers.CurrentEpoch(state) + 1
|
||||
activatedValidators := validators.ActivatedValFromEpoch(nextEpoch)
|
||||
var idxNotInState []uint64
|
||||
for _, idx := range activatedValidators {
|
||||
// If for some reason the activated validator indices is not in state,
|
||||
// we skip them and save them to process for next epoch.
|
||||
if int(idx) >= len(state.Validators) {
|
||||
idxNotInState = append(idxNotInState, idx)
|
||||
continue
|
||||
}
|
||||
pubKey := state.Validators[idx].PublicKey
|
||||
if err := c.beaconDB.SaveValidatorIndex(ctx, bytesutil.ToBytes48(pubKey), idx); err != nil {
|
||||
return errors.Wrap(err, "could not save validator index")
|
||||
}
|
||||
}
|
||||
// Since we are processing next epoch, save the can't processed validator indices
|
||||
// to the epoch after that.
|
||||
validators.InsertActivatedIndices(nextEpoch+1, idxNotInState)
|
||||
validators.DeleteActivatedVal(helpers.CurrentEpoch(state))
|
||||
return nil
|
||||
}
|
||||
|
||||
// deleteValidatorIdx deletes the validators public key to index mapping in DB, the
|
||||
// validators were exited from current epoch. After it deletes, current epoch key
|
||||
// is deleted from ExitedValidators mapping.
|
||||
func (c *ChainService) deleteValidatorIdx(ctx context.Context, state *pb.BeaconState) error {
|
||||
exitedValidators := validators.ExitedValFromEpoch(helpers.CurrentEpoch(state) + 1)
|
||||
for _, idx := range exitedValidators {
|
||||
pubKey := state.Validators[idx].PublicKey
|
||||
if err := c.beaconDB.DeleteValidatorIndex(ctx, bytesutil.ToBytes48(pubKey)); err != nil {
|
||||
return errors.Wrap(err, "could not delete validator index")
|
||||
}
|
||||
}
|
||||
validators.DeleteExitedVal(helpers.CurrentEpoch(state))
|
||||
return nil
|
||||
}
|
||||
|
||||
// This gets called to update canonical root mapping.
|
||||
func (c *ChainService) saveHead(ctx context.Context, b *ethpb.BeaconBlock, r [32]byte) error {
|
||||
c.canonicalRootsLock.Lock()
|
||||
defer c.canonicalRootsLock.Unlock()
|
||||
c.headSlot = b.Slot
|
||||
c.canonicalRoots[b.Slot] = r[:]
|
||||
if err := c.beaconDB.SaveHeadBlockRoot(ctx, r); err != nil {
|
||||
return errors.Wrap(err, "could not save head root in DB")
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"slots": b.Slot,
|
||||
"root": hex.EncodeToString(r[:]),
|
||||
}).Info("Saved head info")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
@ -13,12 +14,16 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain/forkchoice"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
@ -46,10 +51,12 @@ type ChainService struct {
|
||||
genesisTime time.Time
|
||||
stateInitializedFeed *event.Feed
|
||||
p2p p2p.Broadcaster
|
||||
canonicalRoots map[uint64][]byte
|
||||
canonicalRootsLock sync.RWMutex
|
||||
maxRoutines int64
|
||||
headSlot uint64
|
||||
headBlock *ethpb.BeaconBlock
|
||||
headState *pb.BeaconState
|
||||
canonicalRoots map[uint64][]byte
|
||||
canonicalRootsLock sync.RWMutex
|
||||
}
|
||||
|
||||
// Config options for the service.
|
||||
@ -166,3 +173,72 @@ func (c *ChainService) Status() error {
|
||||
func (c *ChainService) StateInitializedFeed() *event.Feed {
|
||||
return c.stateInitializedFeed
|
||||
}
|
||||
|
||||
// saveValidatorIdx saves the validators public key to index mapping in DB, these
|
||||
// validators were activated from current epoch. After it saves, current epoch key
|
||||
// is deleted from ActivatedValidators mapping.
|
||||
func (c *ChainService) saveValidatorIdx(ctx context.Context, state *pb.BeaconState) error {
|
||||
nextEpoch := helpers.CurrentEpoch(state) + 1
|
||||
activatedValidators := validators.ActivatedValFromEpoch(nextEpoch)
|
||||
var idxNotInState []uint64
|
||||
for _, idx := range activatedValidators {
|
||||
// If for some reason the activated validator indices is not in state,
|
||||
// we skip them and save them to process for next epoch.
|
||||
if int(idx) >= len(state.Validators) {
|
||||
idxNotInState = append(idxNotInState, idx)
|
||||
continue
|
||||
}
|
||||
pubKey := state.Validators[idx].PublicKey
|
||||
if err := c.beaconDB.SaveValidatorIndex(ctx, bytesutil.ToBytes48(pubKey), idx); err != nil {
|
||||
return errors.Wrap(err, "could not save validator index")
|
||||
}
|
||||
}
|
||||
// Since we are processing next epoch, save the can't processed validator indices
|
||||
// to the epoch after that.
|
||||
validators.InsertActivatedIndices(nextEpoch+1, idxNotInState)
|
||||
validators.DeleteActivatedVal(helpers.CurrentEpoch(state))
|
||||
return nil
|
||||
}
|
||||
|
||||
// deleteValidatorIdx deletes the validators public key to index mapping in DB, the
|
||||
// validators were exited from current epoch. After it deletes, current epoch key
|
||||
// is deleted from ExitedValidators mapping.
|
||||
func (c *ChainService) deleteValidatorIdx(ctx context.Context, state *pb.BeaconState) error {
|
||||
exitedValidators := validators.ExitedValFromEpoch(helpers.CurrentEpoch(state) + 1)
|
||||
for _, idx := range exitedValidators {
|
||||
pubKey := state.Validators[idx].PublicKey
|
||||
if err := c.beaconDB.DeleteValidatorIndex(ctx, bytesutil.ToBytes48(pubKey)); err != nil {
|
||||
return errors.Wrap(err, "could not delete validator index")
|
||||
}
|
||||
}
|
||||
validators.DeleteExitedVal(helpers.CurrentEpoch(state))
|
||||
return nil
|
||||
}
|
||||
|
||||
// This gets called to update canonical root mapping.
|
||||
func (c *ChainService) saveHead(ctx context.Context, b *ethpb.BeaconBlock, r [32]byte) error {
|
||||
|
||||
c.headSlot = b.Slot
|
||||
|
||||
c.canonicalRootsLock.Lock()
|
||||
c.canonicalRoots[b.Slot] = r[:]
|
||||
defer c.canonicalRootsLock.Unlock()
|
||||
|
||||
if err := c.beaconDB.SaveHeadBlockRoot(ctx, r); err != nil {
|
||||
return errors.Wrap(err, "could not save head root in DB")
|
||||
}
|
||||
c.headBlock = b
|
||||
|
||||
s, err := c.beaconDB.State(ctx, r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
c.headState = s
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"slots": b.Slot,
|
||||
"root": hex.EncodeToString(r[:]),
|
||||
}).Info("Saved head info")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user