Skip to content

Commit

Permalink
Merge branch 'fixForkData' of https://github.com/prysmaticlabs/geth-s…
Browse files Browse the repository at this point in the history
…harding into fixForkData
  • Loading branch information
nisdas committed May 27, 2020
2 parents 847a089 + 9733c3b commit e774b22
Show file tree
Hide file tree
Showing 149 changed files with 2,899 additions and 989 deletions.
27 changes: 27 additions & 0 deletions beacon-chain/blockchain/chain_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
Expand All @@ -21,6 +22,7 @@ type ChainInfoFetcher interface {
HeadFetcher
FinalizationFetcher
GenesisFetcher
CanonicalFetcher
}

// TimeFetcher retrieves the Eth2 data that's related to time.
Expand All @@ -44,13 +46,19 @@ type HeadFetcher interface {
HeadValidatorsIndices(epoch uint64) ([]uint64, error)
HeadSeed(epoch uint64) ([32]byte, error)
HeadGenesisValidatorRoot() [32]byte
ProtoArrayStore() *protoarray.Store
}

// ForkFetcher retrieves the current fork information of the Ethereum beacon chain.
type ForkFetcher interface {
CurrentFork() *pb.Fork
}

// CanonicalFetcher retrieves the current chain's canonical information.
type CanonicalFetcher interface {
IsCanonical(ctx context.Context, blockRoot [32]byte) (bool, error)
}

// FinalizationFetcher defines a common interface for methods in blockchain service which
// directly retrieves finalization and justification related data.
type FinalizationFetcher interface {
Expand Down Expand Up @@ -190,6 +198,11 @@ func (s *Service) HeadGenesisValidatorRoot() [32]byte {
return s.headGenesisValidatorRoot()
}

// ProtoArrayStore returns the proto array store object.
func (s *Service) ProtoArrayStore() *protoarray.Store {
return s.forkChoiceStore.Store()
}

// GenesisTime returns the genesis time of beacon chain.
func (s *Service) GenesisTime() time.Time {
return s.genesisTime
Expand Down Expand Up @@ -222,3 +235,17 @@ func (s *Service) Participation(epoch uint64) *precompute.Balance {

return s.epochParticipation[epoch]
}

// IsCanonical returns true if the input block root is part of the canonical chain.
func (s *Service) IsCanonical(ctx context.Context, blockRoot [32]byte) (bool, error) {
// If the block has been finalized, the block will always be part of the canonical chain.
if s.beaconDB.IsFinalizedBlock(ctx, blockRoot) {
return true, nil
}

// If the block has not been finalized, the block must be recent. Check recent canonical roots
// mapping which uses proto array fork choice.
s.recentCanonicalBlocksLock.RLock()
defer s.recentCanonicalBlocksLock.RUnlock()
return s.recentCanonicalBlocks[blockRoot], nil
}
30 changes: 30 additions & 0 deletions beacon-chain/blockchain/head.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
Expand Down Expand Up @@ -46,6 +47,10 @@ func (s *Service) updateHead(ctx context.Context, balances []uint64) error {
return err
}

if err := s.updateRecentCanonicalBlocks(ctx, headRoot); err != nil {
return err
}

// Save head to the local service cache.
return s.saveHead(ctx, headRoot)
}
Expand Down Expand Up @@ -254,3 +259,28 @@ func (s *Service) hasHeadState() bool {

return s.head != nil && s.head.state != nil
}

// This updates recent canonical block mapping. It uses input head root and retrieves
// all the canonical block roots that are ancestor of the input head block root.
func (s *Service) updateRecentCanonicalBlocks(ctx context.Context, headRoot [32]byte) error {
s.recentCanonicalBlocksLock.Lock()
defer s.recentCanonicalBlocksLock.Unlock()

s.recentCanonicalBlocks = make(map[[32]byte]bool)
s.recentCanonicalBlocks[headRoot] = true
nodes := s.forkChoiceStore.Nodes()
node := s.forkChoiceStore.Node(headRoot)
if node == nil {
return nil
}

for node.Parent != protoarray.NonExistentNode {
if ctx.Err() != nil {
return ctx.Err()
}
node = nodes[node.Parent]
s.recentCanonicalBlocks[node.Root] = true
}

return nil
}
59 changes: 59 additions & 0 deletions beacon-chain/blockchain/head_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,62 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
}
testutil.AssertLogsContain(t, hook, "Chain reorg occurred")
}

func TestUpdateRecentCanonicalBlocks_CanUpdateWithoutParent(t *testing.T) {
db := testDB.SetupDB(t)
service := setupBeaconChain(t, db)

r := [32]byte{'a'}
if err := service.updateRecentCanonicalBlocks(context.Background(), r); err != nil {
t.Fatal(err)
}
canonical, err := service.IsCanonical(context.Background(), r)
if err != nil {
t.Fatal(err)
}
if !canonical {
t.Error("Block should be canonical")
}
}

func TestUpdateRecentCanonicalBlocks_CanUpdateWithParent(t *testing.T) {
db := testDB.SetupDB(t)
service := setupBeaconChain(t, db)
oldHead := [32]byte{'a'}
if err := service.forkChoiceStore.ProcessBlock(context.Background(), 1, oldHead, [32]byte{'g'}, [32]byte{}, 0, 0); err != nil {
t.Fatal(err)
}
currentHead := [32]byte{'b'}
if err := service.forkChoiceStore.ProcessBlock(context.Background(), 3, currentHead, oldHead, [32]byte{}, 0, 0); err != nil {
t.Fatal(err)
}
forkedRoot := [32]byte{'c'}
if err := service.forkChoiceStore.ProcessBlock(context.Background(), 2, forkedRoot, oldHead, [32]byte{}, 0, 0); err != nil {
t.Fatal(err)
}

if err := service.updateRecentCanonicalBlocks(context.Background(), currentHead); err != nil {
t.Fatal(err)
}
canonical, err := service.IsCanonical(context.Background(), currentHead)
if err != nil {
t.Fatal(err)
}
if !canonical {
t.Error("Block should be canonical")
}
canonical, err = service.IsCanonical(context.Background(), oldHead)
if err != nil {
t.Fatal(err)
}
if !canonical {
t.Error("Block should be canonical")
}
canonical, err = service.IsCanonical(context.Background(), forkedRoot)
if err != nil {
t.Fatal(err)
}
if canonical {
t.Error("Block should not be canonical")
}
}
109 changes: 56 additions & 53 deletions beacon-chain/blockchain/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,40 +43,42 @@ import (
// Service represents a service that handles the internal
// logic of managing the full PoS beacon chain.
type Service struct {
ctx context.Context
cancel context.CancelFunc
beaconDB db.HeadAccessDatabase
depositCache *depositcache.DepositCache
chainStartFetcher powchain.ChainStartFetcher
attPool attestations.Pool
slashingPool *slashings.Pool
exitPool *voluntaryexits.Pool
genesisTime time.Time
p2p p2p.Broadcaster
maxRoutines int64
head *head
headLock sync.RWMutex
stateNotifier statefeed.Notifier
genesisRoot [32]byte
epochParticipation map[uint64]*precompute.Balance
epochParticipationLock sync.RWMutex
forkChoiceStore f.ForkChoicer
justifiedCheckpt *ethpb.Checkpoint
prevJustifiedCheckpt *ethpb.Checkpoint
bestJustifiedCheckpt *ethpb.Checkpoint
finalizedCheckpt *ethpb.Checkpoint
prevFinalizedCheckpt *ethpb.Checkpoint
nextEpochBoundarySlot uint64
voteLock sync.RWMutex
initSyncState map[[32]byte]*stateTrie.BeaconState
boundaryRoots [][32]byte
initSyncStateLock sync.RWMutex
checkpointState *cache.CheckpointStateCache
checkpointStateLock sync.Mutex
stateGen *stategen.State
opsService *attestations.Service
initSyncBlocks map[[32]byte]*ethpb.SignedBeaconBlock
initSyncBlocksLock sync.RWMutex
ctx context.Context
cancel context.CancelFunc
beaconDB db.HeadAccessDatabase
depositCache *depositcache.DepositCache
chainStartFetcher powchain.ChainStartFetcher
attPool attestations.Pool
slashingPool *slashings.Pool
exitPool *voluntaryexits.Pool
genesisTime time.Time
p2p p2p.Broadcaster
maxRoutines int64
head *head
headLock sync.RWMutex
stateNotifier statefeed.Notifier
genesisRoot [32]byte
epochParticipation map[uint64]*precompute.Balance
epochParticipationLock sync.RWMutex
forkChoiceStore f.ForkChoicer
justifiedCheckpt *ethpb.Checkpoint
prevJustifiedCheckpt *ethpb.Checkpoint
bestJustifiedCheckpt *ethpb.Checkpoint
finalizedCheckpt *ethpb.Checkpoint
prevFinalizedCheckpt *ethpb.Checkpoint
nextEpochBoundarySlot uint64
voteLock sync.RWMutex
initSyncState map[[32]byte]*stateTrie.BeaconState
boundaryRoots [][32]byte
initSyncStateLock sync.RWMutex
checkpointState *cache.CheckpointStateCache
checkpointStateLock sync.Mutex
stateGen *stategen.State
opsService *attestations.Service
initSyncBlocks map[[32]byte]*ethpb.SignedBeaconBlock
initSyncBlocksLock sync.RWMutex
recentCanonicalBlocks map[[32]byte]bool
recentCanonicalBlocksLock sync.RWMutex
}

// Config options for the service.
Expand All @@ -101,25 +103,26 @@ type Config struct {
func NewService(ctx context.Context, cfg *Config) (*Service, error) {
ctx, cancel := context.WithCancel(ctx)
return &Service{
ctx: ctx,
cancel: cancel,
beaconDB: cfg.BeaconDB,
depositCache: cfg.DepositCache,
chainStartFetcher: cfg.ChainStartFetcher,
attPool: cfg.AttPool,
exitPool: cfg.ExitPool,
slashingPool: cfg.SlashingPool,
p2p: cfg.P2p,
maxRoutines: cfg.MaxRoutines,
stateNotifier: cfg.StateNotifier,
epochParticipation: make(map[uint64]*precompute.Balance),
forkChoiceStore: cfg.ForkChoiceStore,
initSyncState: make(map[[32]byte]*stateTrie.BeaconState),
boundaryRoots: [][32]byte{},
checkpointState: cache.NewCheckpointStateCache(),
opsService: cfg.OpsService,
stateGen: cfg.StateGen,
initSyncBlocks: make(map[[32]byte]*ethpb.SignedBeaconBlock),
ctx: ctx,
cancel: cancel,
beaconDB: cfg.BeaconDB,
depositCache: cfg.DepositCache,
chainStartFetcher: cfg.ChainStartFetcher,
attPool: cfg.AttPool,
exitPool: cfg.ExitPool,
slashingPool: cfg.SlashingPool,
p2p: cfg.P2p,
maxRoutines: cfg.MaxRoutines,
stateNotifier: cfg.StateNotifier,
epochParticipation: make(map[uint64]*precompute.Balance),
forkChoiceStore: cfg.ForkChoiceStore,
initSyncState: make(map[[32]byte]*stateTrie.BeaconState),
boundaryRoots: [][32]byte{},
checkpointState: cache.NewCheckpointStateCache(),
opsService: cfg.OpsService,
stateGen: cfg.StateGen,
initSyncBlocks: make(map[[32]byte]*ethpb.SignedBeaconBlock),
recentCanonicalBlocks: make(map[[32]byte]bool),
}, nil
}

Expand Down
1 change: 1 addition & 0 deletions beacon-chain/blockchain/testing/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ go_library(
"//beacon-chain/core/feed/state:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/forkchoice/protoarray:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
Expand Down
7 changes: 7 additions & 0 deletions beacon-chain/blockchain/testing/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
Expand All @@ -41,6 +42,7 @@ type ChainService struct {
blockNotifier blockfeed.Notifier
opNotifier opfeed.Notifier
ValidAttestation bool
ForkChoiceStore *protoarray.Store
}

// StateNotifier mocks the same method in the chain service.
Expand Down Expand Up @@ -220,6 +222,11 @@ func (ms *ChainService) HeadSeed(epoch uint64) ([32]byte, error) {
return helpers.Seed(ms.State, epoch, params.BeaconConfig().DomainBeaconAttester)
}

// ProtoArrayStore mocks the same method in the chain service.
func (ms *ChainService) ProtoArrayStore() *protoarray.Store {
return ms.ForkChoiceStore
}

// GenesisTime mocks the same method in the chain service.
func (ms *ChainService) GenesisTime() time.Time {
return ms.Genesis
Expand Down
4 changes: 2 additions & 2 deletions beacon-chain/core/blocks/block_operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, pub []byte, signature
if err != nil {
return errors.Wrap(err, "could not get container root")
}
if !sig.Verify(ctrRoot[:], publicKey) {
if !sig.Verify(publicKey, ctrRoot[:]) {
return helpers.ErrSigFailedToVerify
}
return nil
Expand All @@ -75,7 +75,7 @@ func verifySignature(signedData []byte, pub []byte, signature []byte, domain []b
if err != nil {
return errors.Wrap(err, "could not hash container")
}
if !sig.Verify(root[:], publicKey) {
if !sig.Verify(publicKey, root[:]) {
return helpers.ErrSigFailedToVerify
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/core/helpers/attestation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ func TestSlotSignature_Verify(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !sig.Verify(msg[:], pub) {
if !sig.Verify(pub, msg[:]) {
t.Error("Could not verify slot signature")
}
}
Expand Down
6 changes: 3 additions & 3 deletions beacon-chain/core/helpers/signing_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func VerifySigningRoot(obj interface{}, pub []byte, signature []byte, domain []b
if err != nil {
return errors.Wrap(err, "could not compute signing root")
}
if !sig.Verify(root[:], publicKey) {
if !sig.Verify(publicKey, root[:]) {
return ErrSigFailedToVerify
}
return nil
Expand All @@ -97,7 +97,7 @@ func VerifyBlockSigningRoot(blk *ethpb.BeaconBlock, pub []byte, signature []byte
if err != nil {
return errors.Wrap(err, "could not compute signing root")
}
if !sig.Verify(root[:], publicKey) {
if !sig.Verify(publicKey, root[:]) {
return ErrSigFailedToVerify
}
return nil
Expand All @@ -119,7 +119,7 @@ func VerifyBlockHeaderSigningRoot(blkHdr *ethpb.BeaconBlockHeader, pub []byte, s
if err != nil {
return errors.Wrap(err, "could not compute signing root")
}
if !sig.Verify(root[:], publicKey) {
if !sig.Verify(publicKey, root[:]) {
return ErrSigFailedToVerify
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion beacon-chain/flags/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ var (
SlasherProviderFlag = &cli.StringFlag{
Name: "slasher-provider",
Usage: "A slasher provider string endpoint. Can either be an grpc server endpoint.",
Value: "127.0.0.1:5000",
Value: "127.0.0.1:4002",
}
// SlotsPerArchivedPoint specifies the number of slots between the archived points, to save beacon state in the cold
// section of DB.
Expand Down

0 comments on commit e774b22

Please sign in to comment.