mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-24 12:27:18 +00:00
Reject a block which its parent is not part of the finalized chain (#6549)
* Reject a block which its parent is not part of the finalized chain * Refactor verifyBlkDescendant to be public and omit the slot argument, which was only used for error messages * Merge branch 'refactor-verifyBlkDescendant-signature' into reject-bad-block * fix * impl in mock * impl in mock * gofmt * Merge refs/heads/master into refactor-verifyBlkDescendant-signature * Merge branch 'refactor-verifyBlkDescendant-signature' into reject-bad-block * fix test * add test * Merge branch 'refactor-verifyBlkDescendant-signature' into reject-bad-block * gofmt * Merge branch 'master' of github.com:prysmaticlabs/prysm into reject-bad-block * move up in the validation pipeline, @terencechain offline feedback * Merge refs/heads/master into reject-bad-block
This commit is contained in:
parent
c9ca5857f8
commit
1f35384578
@ -46,6 +46,7 @@ type ChainService struct {
|
||||
opNotifier opfeed.Notifier
|
||||
ValidAttestation bool
|
||||
ForkChoiceStore *protoarray.Store
|
||||
VerifyBlkDescendantErr error
|
||||
}
|
||||
|
||||
// StateNotifier mocks the same method in the chain service.
|
||||
@ -350,5 +351,5 @@ func (ms *ChainService) HeadGenesisValidatorRoot() [32]byte {
|
||||
|
||||
// VerifyBlkDescendant mocks VerifyBlkDescendant and always returns nil.
|
||||
func (ms *ChainService) VerifyBlkDescendant(ctx context.Context, root [32]byte) error {
|
||||
return nil
|
||||
return ms.VerifyBlkDescendantErr
|
||||
}
|
||||
|
@ -110,6 +110,11 @@ 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")
|
||||
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 {
|
||||
|
@ -3,6 +3,7 @@ package sync
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@ -632,3 +633,96 @@ func TestValidateBeaconBlockPubSub_FilterByFinalizedEpoch(t *testing.T) {
|
||||
r.validateBeaconBlockPubSub(context.Background(), "", m)
|
||||
testutil.AssertLogsDoNotContain(t, hook, "Block slot older/equal than last finalized epoch start slot, rejecting itt")
|
||||
}
|
||||
|
||||
func TestValidateBeaconBlockPubSub_ParentNotFinalizedDescendant(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
db, stateSummaryCache := dbtest.SetupDB(t)
|
||||
p := p2ptest.NewTestP2P(t)
|
||||
ctx := context.Background()
|
||||
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
||||
parentBlock := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ProposerIndex: 0,
|
||||
Slot: 0,
|
||||
},
|
||||
}
|
||||
if err := db.SaveBlock(ctx, parentBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bRoot, err := stateutil.BlockRoot(parentBlock.Block)
|
||||
if err := db.SaveState(ctx, beaconState, bRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.SaveStateSummary(ctx, &pb.StateSummary{
|
||||
Root: bRoot[:],
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
copied := beaconState.Copy()
|
||||
if err := copied.SetSlot(1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
proposerIdx, err := helpers.BeaconProposerIndex(copied)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
msg := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ProposerIndex: proposerIdx,
|
||||
Slot: 1,
|
||||
ParentRoot: bRoot[:],
|
||||
},
|
||||
}
|
||||
|
||||
domain, err := helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
signingRoot, err := helpers.ComputeSigningRoot(msg.Block, domain)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
blockSig := privKeys[proposerIdx].Sign(signingRoot[:]).Marshal()
|
||||
msg.Signature = blockSig[:]
|
||||
|
||||
c, err := lru.New(10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
stateGen := stategen.New(db, stateSummaryCache)
|
||||
chainService := &mock.ChainService{Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot), 0),
|
||||
State: beaconState,
|
||||
FinalizedCheckPoint: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
},
|
||||
VerifyBlkDescendantErr: errors.New("not part of finalized chain"),
|
||||
}
|
||||
r := &Service{
|
||||
db: db,
|
||||
p2p: p,
|
||||
initialSync: &mockSync.Sync{IsSyncing: false},
|
||||
chain: chainService,
|
||||
blockNotifier: chainService.BlockNotifier(),
|
||||
seenBlockCache: c,
|
||||
slotToPendingBlocks: make(map[uint64]*ethpb.SignedBeaconBlock),
|
||||
seenPendingBlocks: make(map[[32]byte]bool),
|
||||
stateSummaryCache: stateSummaryCache,
|
||||
stateGen: stateGen,
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
if _, err := p.Encoding().EncodeGossip(buf, msg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m := &pubsub.Message{
|
||||
Message: &pubsubpb.Message{
|
||||
Data: buf.Bytes(),
|
||||
TopicIDs: []string{
|
||||
p2p.GossipTypeMapping[reflect.TypeOf(msg)],
|
||||
},
|
||||
},
|
||||
}
|
||||
if res := r.validateBeaconBlockPubSub(ctx, "", m); res != pubsub.ValidationReject {
|
||||
t.Error("Wrong validation result returned")
|
||||
}
|
||||
testutil.AssertLogsContain(t, hook, "not part of finalized chain")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user