Prevent invalid pending attestations (#1994)

* prevent invalid pending attestations

* no past block

* regress test

* +1

* fix lint

* fix buld

* revert unrelated

* passing tests, still need regression tst
This commit is contained in:
Preston Van Loon 2019-03-19 12:25:34 -04:00 committed by GitHub
parent f801bfedcf
commit f44c7082d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 3 deletions

View File

@ -80,6 +80,23 @@ func (ps *ProposerServer) PendingAttestations(ctx context.Context, req *pb.Pendi
return nil, fmt.Errorf("could not retrieve pending attestations from operations service: %v", err)
}
head, err := ps.beaconDB.ChainHead()
if err != nil {
return nil, fmt.Errorf("failed to retrieve chain head: %v", err)
}
blockRoot, err := hashutil.HashBeaconBlock(head)
if err != nil {
return nil, fmt.Errorf("could not hash beacon block: %v", err)
}
for beaconState.Slot < req.ProposalBlockSlot {
beaconState, err = state.ExecuteStateTransition(
ctx, beaconState, nil /* block */, blockRoot, &state.TransitionConfig{},
)
if err != nil {
return nil, fmt.Errorf("could not execute head transition: %v", err)
}
}
// Use the optional proposal block slot parameter as the current slot for
// determining the validity window for attestations.
currentSlot := req.ProposalBlockSlot
@ -88,12 +105,21 @@ func (ps *ProposerServer) PendingAttestations(ctx context.Context, req *pb.Pendi
}
// Remove any attestation from the list if their slot is before the start of
// the previous epoch. This should be handled in the operationService cleanup
// method, but we should filter here in case it wasn't yet processed.
// the previous epoch or does not match the current state previous justified
// epoch. This should be handled in the operationService cleanup but we
// should filter here in case it wasn't yet processed.
boundary := currentSlot - params.BeaconConfig().SlotsPerEpoch
attsWithinBoundary := make([]*pbp2p.Attestation, 0, len(atts))
for _, att := range atts {
if att.Data.Slot > boundary {
var expectedJustifedEpoch uint64
if helpers.SlotToEpoch(att.Data.Slot+1) >= helpers.SlotToEpoch(currentSlot) {
expectedJustifedEpoch = beaconState.JustifiedEpoch
} else {
expectedJustifedEpoch = beaconState.PreviousJustifiedEpoch
}
if att.Data.Slot > boundary && att.Data.JustifiedEpoch == expectedJustifedEpoch {
attsWithinBoundary = append(attsWithinBoundary, att)
}
}

View File

@ -142,6 +142,19 @@ func TestPendingAttestations_FiltersWithinInclusionDelay(t *testing.T) {
if err := db.SaveState(beaconState); err != nil {
t.Fatal(err)
}
blk := &pbp2p.BeaconBlock{
Slot: beaconState.Slot,
}
if err := db.SaveBlock(blk); err != nil {
t.Fatalf("failed to save block %v")
}
if err := db.UpdateChainHead(blk, beaconState); err != nil {
t.Fatalf("couldnt update chainhead: %v")
}
res, err := proposerServer.PendingAttestations(context.Background(), &pb.PendingAttestationsRequest{
FilterReadyForInclusion: true,
})
@ -188,6 +201,19 @@ func TestPendingAttestations_FiltersExpiredAttestations(t *testing.T) {
if err := db.SaveState(beaconState); err != nil {
t.Fatal(err)
}
blk := &pbp2p.BeaconBlock{
Slot: beaconState.Slot,
}
if err := db.SaveBlock(blk); err != nil {
t.Fatalf("failed to save block %v")
}
if err := db.UpdateChainHead(blk, beaconState); err != nil {
t.Fatalf("couldnt update chainhead: %v")
}
res, err := proposerServer.PendingAttestations(
context.Background(),
&pb.PendingAttestationsRequest{
@ -219,6 +245,19 @@ func TestPendingAttestations_OK(t *testing.T) {
if err := db.SaveState(beaconState); err != nil {
t.Fatal(err)
}
blk := &pbp2p.BeaconBlock{
Slot: beaconState.Slot,
}
if err := db.SaveBlock(blk); err != nil {
t.Fatalf("failed to save block %v")
}
if err := db.UpdateChainHead(blk, beaconState); err != nil {
t.Fatalf("couldnt update chainhead: %v")
}
res, err := proposerServer.PendingAttestations(context.Background(), &pb.PendingAttestationsRequest{})
if err != nil {
t.Fatalf("Unexpected error fetching pending attestations: %v", err)