Skip to content

Commit

Permalink
Fix reply block edge cases and tests (#4881)
Browse files Browse the repository at this point in the history
* Covered 2 edge cases and tests

* Consider process epoch
  • Loading branch information
terencechain committed Feb 17, 2020
1 parent b9c140c commit 9b2aa66
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 13 deletions.
3 changes: 3 additions & 0 deletions beacon-chain/stategen/BUILD.bazel
Expand Up @@ -23,11 +23,14 @@ go_test(
srcs = ["replay_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/db/testing:go_default_library",
"//beacon-chain/state:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
],
Expand Down
19 changes: 6 additions & 13 deletions beacon-chain/stategen/replay.go
Expand Up @@ -15,26 +15,19 @@ import (
func (s *State) replayBlocks(ctx context.Context, state *state.BeaconState, signed []*ethpb.SignedBeaconBlock, targetSlot uint64) (*state.BeaconState, error) {
var err error
// The input block list is sorted in decreasing slots order.
for i := len(signed) - 1; i >= 0; i-- {
// If there is skip slot.
for state.Slot() < signed[i].Block.Slot {
state, err = transition.ProcessSlot(ctx, state)
if len(signed) > 0 {
for i := len(signed) - 1; i >= 0; i-- {
state, err = transition.ExecuteStateTransitionNoVerifyAttSigs(ctx, state, signed[i])
if err != nil {
return nil, err
}
}
state, err = transition.ProcessBlockNoVerifyAttSigs(ctx, state, signed[i])
if err != nil {
return nil, err
}
}

// If there is skip slots at the end.
for state.Slot() < targetSlot {
state, err = transition.ProcessSlot(ctx, state)
if err != nil {
return nil, err
}
state, err = transition.ProcessSlots(ctx, state, targetSlot)
if err != nil {
return nil, err
}

return state, nil
Expand Down
75 changes: 75 additions & 0 deletions beacon-chain/stategen/replay_test.go
Expand Up @@ -7,13 +7,88 @@ import (

ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
)

func TestReplayBlocks_AllSkipSlots(t *testing.T) {
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)

beaconState, _ := testutil.DeterministicGenesisState(t, 32)
genesisBlock := blocks.NewGenesisBlock([]byte{})
bodyRoot, err := ssz.HashTreeRoot(genesisBlock.Block)
if err != nil {
t.Fatal(err)
}
beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: genesisBlock.Block.Slot,
ParentRoot: genesisBlock.Block.ParentRoot,
StateRoot: params.BeaconConfig().ZeroHash[:],
BodyRoot: bodyRoot[:],
})
beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))
cp := beaconState.CurrentJustifiedCheckpoint()
mockRoot := [32]byte{}
copy(mockRoot[:], "hello-world")
cp.Root = mockRoot[:]
beaconState.SetCurrentJustifiedCheckpoint(cp)
beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{})

service := New(db)
targetSlot := params.BeaconConfig().SlotsPerEpoch - 1
newState, err := service.replayBlocks(context.Background(), beaconState, []*ethpb.SignedBeaconBlock{}, targetSlot)
if err != nil {
t.Fatal(err)
}

if newState.Slot() != targetSlot {
t.Error("Did not advance slots")
}
}

func TestReplayBlocks_SameSlot(t *testing.T) {
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)

beaconState, _ := testutil.DeterministicGenesisState(t, 32)
genesisBlock := blocks.NewGenesisBlock([]byte{})
bodyRoot, err := ssz.HashTreeRoot(genesisBlock.Block)
if err != nil {
t.Fatal(err)
}
beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: genesisBlock.Block.Slot,
ParentRoot: genesisBlock.Block.ParentRoot,
StateRoot: params.BeaconConfig().ZeroHash[:],
BodyRoot: bodyRoot[:],
})
beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))
cp := beaconState.CurrentJustifiedCheckpoint()
mockRoot := [32]byte{}
copy(mockRoot[:], "hello-world")
cp.Root = mockRoot[:]
beaconState.SetCurrentJustifiedCheckpoint(cp)
beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{})

service := New(db)
targetSlot := beaconState.Slot()
newState, err := service.replayBlocks(context.Background(), beaconState, []*ethpb.SignedBeaconBlock{}, targetSlot)
if err != nil {
t.Fatal(err)
}

if newState.Slot() != targetSlot {
t.Error("Did not advance slots")
}
}

func TestLoadBlocks_FirstBranch(t *testing.T) {
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
Expand Down

0 comments on commit 9b2aa66

Please sign in to comment.