mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 07:58:22 -05:00
Validate beacon block in pending queue (#7847)
This commit is contained in:
@@ -125,12 +125,21 @@ func (s *Service) processPendingBlocks(ctx context.Context) error {
|
||||
span.End()
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.validateBeaconBlock(ctx, b, blkRoot); err != nil {
|
||||
log.Debugf("Could not validate block from slot %d: %v", b.Block.Slot, err)
|
||||
s.setBadBlock(ctx, blkRoot)
|
||||
traceutil.AnnotateError(span, err)
|
||||
}
|
||||
|
||||
if err := s.chain.ReceiveBlock(ctx, b, blkRoot); err != nil {
|
||||
log.Debugf("Could not process block from slot %d: %v", b.Block.Slot, err)
|
||||
s.setBadBlock(ctx, blkRoot)
|
||||
traceutil.AnnotateError(span, err)
|
||||
}
|
||||
|
||||
s.setSeenBlockIndexSlot(b.Block.Slot, b.Block.ProposerIndex)
|
||||
|
||||
// Broadcasting the block again once a node is able to process it.
|
||||
if err := s.p2p.Broadcast(ctx, b); err != nil {
|
||||
log.WithError(err).Debug("Failed to broadcast block")
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
// \- b3
|
||||
// Test b1 was missing then received and we can process b0 -> b1 -> b2
|
||||
func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks1(t *testing.T) {
|
||||
db, _ := dbtest.SetupDB(t)
|
||||
db, stateSummaryCache := dbtest.SetupDB(t)
|
||||
|
||||
p1 := p2ptest.NewTestP2P(t)
|
||||
r := &Service{
|
||||
@@ -41,6 +41,7 @@ func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks1(t *testing.T) {
|
||||
},
|
||||
slotToPendingBlocks: make(map[uint64][]*ethpb.SignedBeaconBlock),
|
||||
seenPendingBlocks: make(map[[32]byte]bool),
|
||||
stateSummaryCache: stateSummaryCache,
|
||||
}
|
||||
err := r.initCaches()
|
||||
require.NoError(t, err)
|
||||
@@ -134,7 +135,7 @@ func TestRegularSync_InsertDuplicateBlocks(t *testing.T) {
|
||||
// \- b3 - b4
|
||||
// Test b2 and b3 were missed, after receiving them we can process 2 chains.
|
||||
func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks_2Chains(t *testing.T) {
|
||||
db, _ := dbtest.SetupDB(t)
|
||||
db, stateSummaryCache := dbtest.SetupDB(t)
|
||||
p1 := p2ptest.NewTestP2P(t)
|
||||
p2 := p2ptest.NewTestP2P(t)
|
||||
p1.Connect(p2)
|
||||
@@ -166,6 +167,7 @@ func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks_2Chains(t *testin
|
||||
},
|
||||
slotToPendingBlocks: make(map[uint64][]*ethpb.SignedBeaconBlock),
|
||||
seenPendingBlocks: make(map[[32]byte]bool),
|
||||
stateSummaryCache: stateSummaryCache,
|
||||
}
|
||||
err := r.initCaches()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -2,6 +2,7 @@ package sync
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
@@ -118,43 +119,8 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
|
||||
if err := s.chain.VerifyBlkDescendant(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot)); err != nil {
|
||||
log.WithError(err).Warn("Rejecting block")
|
||||
s.setBadBlock(ctx, blockRoot)
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
|
||||
hasStateSummaryDB := s.db.HasStateSummary(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
hasStateSummaryCache := s.stateSummaryCache.Has(bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if !hasStateSummaryDB && !hasStateSummaryCache {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("No access to parent state")
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
parentState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not get parent state")
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
|
||||
if err := blocks.VerifyBlockSignature(parentState, blk); err != nil {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not verify block signature")
|
||||
s.setBadBlock(ctx, blockRoot)
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
|
||||
parentState, err = state.ProcessSlots(ctx, parentState, blk.Block.Slot)
|
||||
if err != nil {
|
||||
log.Errorf("Could not advance slot to calculate proposer index: %v", err)
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
idx, err := helpers.BeaconProposerIndex(parentState)
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not get proposer index using parent state")
|
||||
return pubsub.ValidationIgnore
|
||||
}
|
||||
if blk.Block.ProposerIndex != idx {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Incorrect proposer index")
|
||||
s.setBadBlock(ctx, blockRoot)
|
||||
if err := s.validateBeaconBlock(ctx, blk, blockRoot); err != nil {
|
||||
log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not validate beacon block")
|
||||
return pubsub.ValidationReject
|
||||
}
|
||||
|
||||
@@ -162,6 +128,46 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
|
||||
return pubsub.ValidationAccept
|
||||
}
|
||||
|
||||
func (s *Service) validateBeaconBlock(ctx context.Context, blk *ethpb.SignedBeaconBlock, blockRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "sync.validateBeaconBlock")
|
||||
defer span.End()
|
||||
|
||||
if err := s.chain.VerifyBlkDescendant(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot)); err != nil {
|
||||
s.setBadBlock(ctx, blockRoot)
|
||||
return err
|
||||
}
|
||||
|
||||
hasStateSummaryDB := s.db.HasStateSummary(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
hasStateSummaryCache := s.stateSummaryCache.Has(bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if !hasStateSummaryDB && !hasStateSummaryCache {
|
||||
return errors.New("no access to parent state")
|
||||
}
|
||||
parentState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := blocks.VerifyBlockSignature(parentState, blk); err != nil {
|
||||
s.setBadBlock(ctx, blockRoot)
|
||||
return err
|
||||
}
|
||||
|
||||
parentState, err = state.ProcessSlots(ctx, parentState, blk.Block.Slot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
idx, err := helpers.BeaconProposerIndex(parentState)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if blk.Block.ProposerIndex != idx {
|
||||
s.setBadBlock(ctx, blockRoot)
|
||||
return errors.New("incorrect proposer index")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns true if the block is not the first block proposed for the proposer for the slot.
|
||||
func (s *Service) hasSeenBlockIndexSlot(slot, proposerIdx uint64) bool {
|
||||
s.seenBlockLock.RLock()
|
||||
|
||||
Reference in New Issue
Block a user