Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bounce attack tests #3993

Merged
merged 14 commits into from
Nov 14, 2019
3 changes: 2 additions & 1 deletion beacon-chain/blockchain/forkchoice/process_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,8 @@ func (s *Store) currentSlot() uint64 {

// updates justified check point in store if a better check point is known
func (s *Store) updateJustifiedCheckpoint() {
if helpers.SlotsSinceEpochStarts(s.currentSlot()) == 0 {
// Update at epoch boundary slot only
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

if !helpers.IsEpochStart(s.currentSlot()) {
return
}
if s.bestJustifiedCheckpt.Epoch > s.justifiedCheckpt.Epoch {
Expand Down
114 changes: 114 additions & 0 deletions beacon-chain/blockchain/forkchoice/process_block_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package forkchoice

import (
"bytes"
"context"
"reflect"
"strings"
"testing"
"time"

"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/go-ssz"
Expand Down Expand Up @@ -334,3 +336,115 @@ func TestRemoveStateSinceLastFinalized(t *testing.T) {
}
}
}

func TestShouldUpdateJustified_ReturnTrue(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
params.UseMinimalConfig()
defer params.UseMainnetConfig()

store := NewForkChoiceService(ctx, db)
store.genesisTime = uint64(time.Now().Unix())

update, err := store.shouldUpdateJustified(ctx, &ethpb.Checkpoint{})
if err != nil {
t.Fatal(err)
}
if !update {
t.Error("Should be able to update justified, received false")
}

lastJustifiedBlk := &ethpb.BeaconBlock{ParentRoot: []byte{'G'}}
lastJustifiedRoot, _ := ssz.SigningRoot(lastJustifiedBlk)
newJustifiedBlk := &ethpb.BeaconBlock{Slot: 1, ParentRoot: lastJustifiedRoot[:]}
newJustifiedRoot, _ := ssz.SigningRoot(newJustifiedBlk)
if err := store.db.SaveBlock(ctx, newJustifiedBlk); err != nil {
t.Fatal(err)
}
if err := store.db.SaveBlock(ctx, lastJustifiedBlk); err != nil {
t.Fatal(err)
}

diff := (params.BeaconConfig().SlotsPerEpoch - 1) * params.BeaconConfig().SecondsPerSlot
store.genesisTime = uint64(time.Now().Unix()) - diff
store.justifiedCheckpt = &ethpb.Checkpoint{Root: lastJustifiedRoot[:]}
update, err = store.shouldUpdateJustified(ctx, &ethpb.Checkpoint{Root: newJustifiedRoot[:]})
if err != nil {
t.Fatal(err)
}
if !update {
t.Error("Should be able to update justified, received false")
}
}

func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
params.UseMinimalConfig()
defer params.UseMainnetConfig()

store := NewForkChoiceService(ctx, db)

lastJustifiedBlk := &ethpb.BeaconBlock{ParentRoot: []byte{'G'}}
lastJustifiedRoot, _ := ssz.SigningRoot(lastJustifiedBlk)
newJustifiedBlk := &ethpb.BeaconBlock{ParentRoot: lastJustifiedRoot[:]}
newJustifiedRoot, _ := ssz.SigningRoot(newJustifiedBlk)
if err := store.db.SaveBlock(ctx, newJustifiedBlk); err != nil {
t.Fatal(err)
}
if err := store.db.SaveBlock(ctx, lastJustifiedBlk); err != nil {
t.Fatal(err)
}

diff := (params.BeaconConfig().SlotsPerEpoch - 1) * params.BeaconConfig().SecondsPerSlot
store.genesisTime = uint64(time.Now().Unix()) - diff
store.justifiedCheckpt = &ethpb.Checkpoint{Root: lastJustifiedRoot[:]}

update, err := store.shouldUpdateJustified(ctx, &ethpb.Checkpoint{Root: newJustifiedRoot[:]})
if err != nil {
t.Fatal(err)
}
if update {
t.Error("Should not be able to update justified, received true")
}
}

func TestUpdateJustifiedCheckpoint_Update(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
params.UseMinimalConfig()
defer params.UseMainnetConfig()

store := NewForkChoiceService(ctx, db)
store.genesisTime = uint64(time.Now().Unix())

store.justifiedCheckpt = &ethpb.Checkpoint{Root: []byte{'A'}}
store.bestJustifiedCheckpt = &ethpb.Checkpoint{Epoch: 1, Root: []byte{'B'}}
store.updateJustifiedCheckpoint()

if !bytes.Equal(store.justifiedCheckpt.Root, []byte{'B'}) {
t.Error("Justified check point root did not update")
}
}

func TestUpdateJustifiedCheckpoint_NoUpdate(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
params.UseMinimalConfig()
defer params.UseMainnetConfig()

store := NewForkChoiceService(ctx, db)
store.genesisTime = uint64(time.Now().Unix()) - params.BeaconConfig().SecondsPerSlot

store.justifiedCheckpt = &ethpb.Checkpoint{Root: []byte{'A'}}
store.bestJustifiedCheckpt = &ethpb.Checkpoint{Epoch: 1, Root: []byte{'B'}}
store.updateJustifiedCheckpoint()

if bytes.Equal(store.justifiedCheckpt.Root, []byte{'B'}) {
t.Error("Justified check point root was not suppose to update")
}
}
18 changes: 18 additions & 0 deletions beacon-chain/core/helpers/slot_epoch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,21 @@ func TestIsEpochEnd(t *testing.T) {
}
}
}

func TestSlotsSinceEpochStarts(t *testing.T) {
tests := []struct {
slots uint64
wantedSlots uint64
}{
{slots: 0, wantedSlots: 0},
{slots: 1, wantedSlots: 1},
{slots: params.BeaconConfig().SlotsPerEpoch - 1, wantedSlots: params.BeaconConfig().SlotsPerEpoch - 1},
{slots: params.BeaconConfig().SlotsPerEpoch + 1, wantedSlots: 1},
{slots: 10*params.BeaconConfig().SlotsPerEpoch + 2, wantedSlots: 2},
}
for _, tt := range tests {
if got := SlotsSinceEpochStarts(tt.slots); got != tt.wantedSlots {
t.Errorf("SlotsSinceEpochStarts() = %v, want %v", got, tt.wantedSlots)
}
}
}