Skip to content

Commit

Permalink
Block Processing Sanity Spec Tests (#2817)
Browse files Browse the repository at this point in the history
* update PrevEpoch

* add new changes

* shift to blocks package

* add more changes

* new changes

* updated pb with size tags

* add new changes

* fix errors

* uncomment code

* more changes

* add new changes

* rename and lint

* gaz

* more changes

* proccess slot SigningRoot instead of HashTreeRoot

* ensure yaml generated structs work

* block sanity all passing

* minimal and mainnet all pass

* remove commented code

* fix one test

* fix all tests

* fix again

* no state comparison

* matching spec

* change target viz

* comments gazelle

* clear caches before test cases

* latest attempts

* clean up test format

* remove debugging log, remove yaml

* unskip attestation

* remove skip, check post state, diff state diffs

* handle err

* add bug fixes

* fixed one more bug

* fixed churn limit bug

* change hashProto to HashTreeRoot

* all tests pass :)

* fix all tests

* gaz

* add regression tests

* fix test bug
  • Loading branch information
Nishant Das authored Jun 29, 2019
1 parent 816d14f commit c5a4778
Show file tree
Hide file tree
Showing 24 changed files with 365 additions and 36 deletions.
8 changes: 7 additions & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ go_repository(

go_repository(
name = "com_github_prysmaticlabs_go_ssz",
commit = "a2c7c20ea4b9f5ddfdc3122924822a8033e1db9d",
commit = "65835a5f002109998995206338ca888e41503525",
importpath = "github.com/prysmaticlabs/go-ssz",
)

Expand Down Expand Up @@ -1096,3 +1096,9 @@ go_repository(
commit = "4a0ed625a78b6858dc8d3a55fb7728968b712122",
importpath = "github.com/koron/go-ssdp",
)

go_repository(
name = "in_gopkg_d4l3k_messagediff_v1",
commit = "29f32d820d112dbd66e58492a6ffb7cc3106312b",
importpath = "gopkg.in/d4l3k/messagediff.v1",
)
1 change: 1 addition & 0 deletions beacon-chain/blockchain/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ go_library(
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
],
Expand Down
4 changes: 2 additions & 2 deletions beacon-chain/blockchain/block_processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"

"github.com/prysmaticlabs/go-ssz"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
Expand All @@ -15,7 +16,6 @@ import (
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
Expand Down Expand Up @@ -114,7 +114,7 @@ func (c *ChainService) ReceiveBlock(ctx context.Context, block *pb.BeaconBlock)

// Check state root
if featureconfig.FeatureConfig().EnableCheckBlockStateRoot {
stateRoot, err := hashutil.HashProto(beaconState)
stateRoot, err := ssz.HashTreeRoot(beaconState)
if err != nil {
return nil, fmt.Errorf("could not hash beacon state: %v", err)
}
Expand Down
5 changes: 3 additions & 2 deletions beacon-chain/blockchain/block_processing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ func initBlockStateRoot(t *testing.T, block *pb.BeaconBlock, chainService *Chain
t.Fatalf("could not apply block state transition: %v", err)
}

stateRoot, err := hashutil.HashProto(computedState)
stateRoot, err := ssz.HashTreeRoot(computedState)
if err != nil {
t.Fatalf("could not tree hash state: %v", err)
}

block.StateRoot = stateRoot[:]
t.Logf("state root after block: %#x", stateRoot)
}
Expand Down Expand Up @@ -365,7 +366,7 @@ func TestReceiveBlock_CheckBlockStateRoot_GoodState(t *testing.T) {
}

beaconState.Slot++
parentRoot, err := blockutil.BlockSigningRoot(genesis)
parentRoot, err := blockutil.BlockSigningRoot(genesisBlock)
if err != nil {
t.Fatal(err)
}
Expand Down
8 changes: 6 additions & 2 deletions beacon-chain/core/blocks/block_operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,22 +108,26 @@ func ProcessBlockHeader(
if err != nil {
return nil, err
}

if !bytes.Equal(block.ParentRoot, parentRoot[:]) {
return nil, fmt.Errorf(
"parent root %#x does not match the latest block header signing root in state %#x",
block.ParentRoot, parentRoot)
}

bodyRoot, err := ssz.HashTreeRoot(block.Body)
if err != nil {
return nil, err
}
emptySig := make([]byte, 96)
beaconState.LatestBlockHeader = &pb.BeaconBlockHeader{
Slot: block.Slot,
ParentRoot: block.ParentRoot,
StateRoot: params.BeaconConfig().ZeroHash[:],
BodyRoot: bodyRoot[:],
Signature: emptySig,
}

// Verify proposer is not slashed
// Verify proposer is not slashed.
idx, err := helpers.BeaconProposerIndex(beaconState)
if err != nil {
return nil, err
Expand Down
4 changes: 4 additions & 0 deletions beacon-chain/core/blocks/block_operations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,15 @@ func TestProcessBlockHeader_OK(t *testing.T) {
if err != nil {
t.Fatalf("Failed to process block header got: %v", err)
}
var zeroHash [32]byte
var zeroSig [96]byte
nsh := newState.LatestBlockHeader
expected := &pb.BeaconBlockHeader{
Slot: block.Slot,
ParentRoot: latestBlockSignedRoot[:],
BodyRoot: bodyRoot[:],
StateRoot: zeroHash[:],
Signature: zeroSig[:],
}
if !proto.Equal(nsh, expected) {
t.Errorf("Expected %v, received %vk9k", expected, nsh)
Expand Down
32 changes: 32 additions & 0 deletions beacon-chain/core/blocks/spectest/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "go_default_library",
srcs = [
"blocks_mainnet.yaml.go",
"blocks_minimal.yaml.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks/spectest",
visibility = ["//beacon-chain:__subpackages__"],
deps = ["//proto/beacon/p2p/v1:go_default_library"],
)

go_test(
name = "go_default_test",
srcs = ["block_processing_test.go"],
data = [
"@eth2_spec_tests//:test_data",
],
embed = [":go_default_library"],
tags = ["spectest"],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//shared/params/spectest:go_default_library",
"@com_github_ghodss_yaml//:go_default_library",
"@com_github_golang_protobuf//proto:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],
)
66 changes: 66 additions & 0 deletions beacon-chain/core/blocks/spectest/block_processing_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package spectest

import (
"context"
"io/ioutil"
"testing"

"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/golang/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"gopkg.in/d4l3k/messagediff.v1"
)

func TestBlockProcessingMinimalYaml(t *testing.T) {
runBlockProcessingTest(t, "sanity_blocks_minimal.yaml")
}

func TestBlockProcessingMainnetYaml(t *testing.T) {
runBlockProcessingTest(t, "sanity_blocks_mainnet.yaml")
}

func runBlockProcessingTest(t *testing.T, filename string) {
filepath, err := bazel.Runfile("/eth2_spec_tests/tests/sanity/blocks/" + filename)
if err != nil {
t.Fatal(err)
}
file, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatalf("Could not load file %v", err)
}

s := &BlocksMainnet{}
if err := yaml.Unmarshal(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}

if err := spectest.SetConfig(s.Config); err != nil {
t.Fatalf("Could not set config: %v", err)
}

for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
ctx := context.Background()
helpers.ClearAllCaches()
blocks.ClearEth1DataVoteCache()

stateConfig := state.DefaultConfig()
s := tt.Pre // Pre-state
for _, b := range tt.Blocks {
if tt.Pre, err = state.ExecuteStateTransition(ctx, tt.Pre, b, stateConfig); err != nil {
t.Fatalf("Transition failed with block at slot %d: %v", b.Slot, err)
}
}

if !proto.Equal(s, tt.Post) {
diff, _ := messagediff.PrettyDiff(s, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
})
}
}
22 changes: 22 additions & 0 deletions beacon-chain/core/blocks/spectest/blocks_mainnet.yaml.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions beacon-chain/core/blocks/spectest/blocks_minimal.yaml.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion beacon-chain/core/epoch/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ go_library(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/mathutil:go_default_library",
"//shared/params:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
Expand Down
13 changes: 8 additions & 5 deletions beacon-chain/core/epoch/epoch_processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
Expand Down Expand Up @@ -354,6 +353,7 @@ func ProcessRewardsAndPenalties(state *pb.BeaconState) (*pb.BeaconState, error)
// validator.activation_epoch = get_delayed_activation_exit_epoch(get_current_epoch(state))
func ProcessRegistryUpdates(state *pb.BeaconState) (*pb.BeaconState, error) {
currentEpoch := helpers.CurrentEpoch(state)
var err error
for idx, validator := range state.ValidatorRegistry {
// Process the validators for activation eligibility.
eligibleToActivate := validator.ActivationEligibilityEpoch == params.BeaconConfig().FarFutureEpoch
Expand All @@ -365,7 +365,10 @@ func ProcessRegistryUpdates(state *pb.BeaconState) (*pb.BeaconState, error) {
isActive := helpers.IsActiveValidator(validator, currentEpoch)
belowEjectionBalance := validator.EffectiveBalance <= params.BeaconConfig().EjectionBalance
if isActive && belowEjectionBalance {
state = validators.ExitValidator(state, uint64(idx))
state, err = validators.InitiateValidatorExit(state, uint64(idx))
if err != nil {
return nil, err
}
}
}

Expand Down Expand Up @@ -495,7 +498,7 @@ func ProcessFinalUpdates(state *pb.BeaconState) (*pb.BeaconState, error) {
nextEpoch := currentEpoch + 1

// Reset ETH1 data votes.
if (state.Slot+1)%params.BeaconConfig().SlotsPerHistoricalRoot == 0 {
if (state.Slot+1)%params.BeaconConfig().SlotsPerEth1VotingPeriod == 0 {
state.Eth1DataVotes = nil
}

Expand Down Expand Up @@ -549,7 +552,7 @@ func ProcessFinalUpdates(state *pb.BeaconState) (*pb.BeaconState, error) {
BlockRoots: state.LatestBlockRoots,
StateRoots: state.LatestStateRoots,
}
batchRoot, err := hashutil.HashProto(historicalBatch)
batchRoot, err := ssz.HashTreeRoot(historicalBatch)
if err != nil {
return nil, fmt.Errorf("could not hash historical batch: %v", err)
}
Expand All @@ -558,7 +561,7 @@ func ProcessFinalUpdates(state *pb.BeaconState) (*pb.BeaconState, error) {

// Rotate current and previous epoch attestations.
state.PreviousEpochAttestations = state.CurrentEpochAttestations
state.CurrentEpochAttestations = nil
state.CurrentEpochAttestations = make([]*pb.PendingAttestation, 0, 0)

return state, nil
}
Expand Down
4 changes: 4 additions & 0 deletions beacon-chain/core/epoch/epoch_processing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,10 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
if len(newS.HistoricalRoots) != 1 {
t.Errorf("wanted slashed balance %d, got %d", 1, len(newS.HistoricalRoots[ce]))
}

if newS.CurrentEpochAttestations == nil {
t.Error("nil value stored in current epoch attestations instead of empty slice")
}
}

func TestCrosslinkDelta_NoOneAttested(t *testing.T) {
Expand Down
5 changes: 4 additions & 1 deletion beacon-chain/core/helpers/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ func BlockRootAtSlot(state *pb.BeaconState, slot uint64) ([]byte, error) {
state.Slot,
)
}
return state.LatestBlockRoots[slot%params.BeaconConfig().SlotsPerHistoricalRoot], nil
rootWanted := state.LatestBlockRoots[slot%params.BeaconConfig().SlotsPerHistoricalRoot]
blkRoot := make([]byte, len(rootWanted))
copy(blkRoot, rootWanted)
return blkRoot, nil
}

// BlockRoot returns the block root stored in the BeaconState for epoch start slot.
Expand Down
4 changes: 3 additions & 1 deletion beacon-chain/core/helpers/cache.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package helpers

import "github.com/prysmaticlabs/prysm/beacon-chain/cache"
import (
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
)

// ClearShuffledValidatorCache clears the shuffled indices cache from scratch.
func ClearShuffledValidatorCache() {
Expand Down
10 changes: 8 additions & 2 deletions beacon-chain/core/helpers/randao.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ func GenerateSeed(state *pb.BeaconState, epoch uint64) ([32]byte, error) {
// """
// return state.latest_active_index_roots[epoch % LATEST_ACTIVE_INDEX_ROOTS_LENGTH]
func ActiveIndexRoot(state *pb.BeaconState, epoch uint64) []byte {
return state.LatestActiveIndexRoots[epoch%params.BeaconConfig().LatestActiveIndexRootsLength]
newRootLength := len(state.LatestActiveIndexRoots[epoch%params.BeaconConfig().LatestActiveIndexRootsLength])
newRoot := make([]byte, newRootLength)
copy(newRoot, state.LatestActiveIndexRoots[epoch%params.BeaconConfig().LatestActiveIndexRootsLength])
return newRoot
}

// RandaoMix returns the randao mix (xor'ed seed)
Expand All @@ -85,7 +88,10 @@ func ActiveIndexRoot(state *pb.BeaconState, epoch uint64) []byte {
// """
// return state.latest_randao_mixes[epoch % LATEST_RANDAO_MIXES_LENGTH]
func RandaoMix(state *pb.BeaconState, epoch uint64) []byte {
return state.LatestRandaoMixes[epoch%params.BeaconConfig().LatestRandaoMixesLength]
newMixLength := len(state.LatestRandaoMixes[epoch%params.BeaconConfig().LatestRandaoMixesLength])
newMix := make([]byte, newMixLength)
copy(newMix, state.LatestRandaoMixes[epoch%params.BeaconConfig().LatestRandaoMixesLength])
return newMix
}

// CreateRandaoReveal generates a epoch signature using the beacon proposer priv key.
Expand Down
Loading

0 comments on commit c5a4778

Please sign in to comment.