prysm-pulse/testing/spectest/shared/common/forkchoice/runner.go
Potuz a27feb4cb2
Implement optimistic sync spectests (#11391)
* builder changes

* New valid status

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-09-15 05:42:20 +00:00

215 lines
7.7 KiB
Go

package forkchoice
import (
"fmt"
"path"
"testing"
"github.com/golang/snappy"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/v1"
v2 "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/v2"
v3 "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/v3"
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/testing/require"
"github.com/prysmaticlabs/prysm/v3/testing/spectest/utils"
"github.com/prysmaticlabs/prysm/v3/testing/util"
)
func init() {
transition.SkipSlotCache.Disable()
}
// Run executes "forkchoice" and "sync" test.
func Run(t *testing.T, config string, fork int) {
runTest(t, config, fork, "fork_choice")
runTest(t, config, fork, "sync")
}
func runTest(t *testing.T, config string, fork int, basePath string) {
require.NoError(t, utils.SetConfig(t, config))
testFolders, _ := utils.TestFolders(t, config, version.String(fork), basePath)
if testFolders == nil {
return
}
for _, folder := range testFolders {
folderPath := path.Join(basePath, folder.Name(), "pyspec_tests")
testFolders, testsFolderPath := utils.TestFolders(t, config, version.String(fork), folderPath)
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
preStepsFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "steps.yaml")
require.NoError(t, err)
var steps []Step
require.NoError(t, utils.UnmarshalYaml(preStepsFile, &steps))
preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "anchor_state.ssz_snappy")
require.NoError(t, err)
preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile)
require.NoError(t, err)
blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "anchor_block.ssz_snappy")
require.NoError(t, err)
blockSSZ, err := snappy.Decode(nil /* dst */, blockFile)
require.NoError(t, err)
var beaconState state.BeaconState
var beaconBlock interfaces.SignedBeaconBlock
switch fork {
case version.Phase0:
beaconState = unmarshalPhase0State(t, preBeaconStateSSZ)
beaconBlock = unmarshalPhase0Block(t, blockSSZ)
case version.Altair:
beaconState = unmarshalAltairState(t, preBeaconStateSSZ)
beaconBlock = unmarshalAltairBlock(t, blockSSZ)
case version.Bellatrix:
beaconState = unmarshalBellatrixState(t, preBeaconStateSSZ)
beaconBlock = unmarshalBellatrixBlock(t, blockSSZ)
default:
t.Fatalf("unknown fork version: %v", fork)
}
builder := NewBuilder(t, beaconState, beaconBlock)
for _, step := range steps {
if step.Tick != nil {
builder.Tick(t, int64(*step.Tick))
}
if step.Block != nil {
blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), fmt.Sprint(*step.Block, ".ssz_snappy"))
require.NoError(t, err)
blockSSZ, err := snappy.Decode(nil /* dst */, blockFile)
require.NoError(t, err)
var beaconBlock interfaces.SignedBeaconBlock
switch fork {
case version.Phase0:
beaconBlock = unmarshalSignedPhase0Block(t, blockSSZ)
case version.Altair:
beaconBlock = unmarshalSignedAltairBlock(t, blockSSZ)
case version.Bellatrix:
beaconBlock = unmarshalSignedBellatrixBlock(t, blockSSZ)
default:
t.Fatalf("unknown fork version: %v", fork)
}
if step.Valid != nil && !*step.Valid {
builder.InvalidBlock(t, beaconBlock)
} else {
builder.ValidBlock(t, beaconBlock)
}
}
if step.AttesterSlashing != nil {
slashingFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), fmt.Sprint(*step.AttesterSlashing, ".ssz_snappy"))
require.NoError(t, err)
slashingSSZ, err := snappy.Decode(nil /* dst */, slashingFile)
require.NoError(t, err)
slashing := &ethpb.AttesterSlashing{}
require.NoError(t, slashing.UnmarshalSSZ(slashingSSZ), "Failed to unmarshal")
builder.AttesterSlashing(slashing)
}
if step.Attestation != nil {
attFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), fmt.Sprint(*step.Attestation, ".ssz_snappy"))
require.NoError(t, err)
attSSZ, err := snappy.Decode(nil /* dst */, attFile)
require.NoError(t, err)
att := &ethpb.Attestation{}
require.NoError(t, att.UnmarshalSSZ(attSSZ), "Failed to unmarshal")
builder.Attestation(t, att)
}
if step.PayloadStatus != nil {
require.NoError(t, builder.SetPayloadStatus(step.PayloadStatus))
}
if step.PowBlock != nil {
powBlockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), fmt.Sprint(*step.PowBlock, ".ssz_snappy"))
require.NoError(t, err)
p, err := snappy.Decode(nil /* dst */, powBlockFile)
require.NoError(t, err)
pb := &ethpb.PowBlock{}
require.NoError(t, pb.UnmarshalSSZ(p), "Failed to unmarshal")
builder.PoWBlock(pb)
}
builder.Check(t, step.Check)
}
})
}
}
}
func unmarshalPhase0State(t *testing.T, raw []byte) state.BeaconState {
base := &ethpb.BeaconState{}
require.NoError(t, base.UnmarshalSSZ(raw))
st, err := v1.InitializeFromProto(base)
require.NoError(t, err)
return st
}
func unmarshalPhase0Block(t *testing.T, raw []byte) interfaces.SignedBeaconBlock {
base := &ethpb.BeaconBlock{}
require.NoError(t, base.UnmarshalSSZ(raw))
blk, err := blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlock{Block: base, Signature: make([]byte, fieldparams.BLSSignatureLength)})
require.NoError(t, err)
return blk
}
func unmarshalSignedPhase0Block(t *testing.T, raw []byte) interfaces.SignedBeaconBlock {
base := &ethpb.SignedBeaconBlock{}
require.NoError(t, base.UnmarshalSSZ(raw))
blk, err := blocks.NewSignedBeaconBlock(base)
require.NoError(t, err)
return blk
}
func unmarshalAltairState(t *testing.T, raw []byte) state.BeaconState {
base := &ethpb.BeaconStateAltair{}
require.NoError(t, base.UnmarshalSSZ(raw))
st, err := v2.InitializeFromProto(base)
require.NoError(t, err)
return st
}
func unmarshalAltairBlock(t *testing.T, raw []byte) interfaces.SignedBeaconBlock {
base := &ethpb.BeaconBlockAltair{}
require.NoError(t, base.UnmarshalSSZ(raw))
blk, err := blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlockAltair{Block: base, Signature: make([]byte, fieldparams.BLSSignatureLength)})
require.NoError(t, err)
return blk
}
func unmarshalSignedAltairBlock(t *testing.T, raw []byte) interfaces.SignedBeaconBlock {
base := &ethpb.SignedBeaconBlockAltair{}
require.NoError(t, base.UnmarshalSSZ(raw))
blk, err := blocks.NewSignedBeaconBlock(base)
require.NoError(t, err)
return blk
}
func unmarshalBellatrixState(t *testing.T, raw []byte) state.BeaconState {
base := &ethpb.BeaconStateBellatrix{}
require.NoError(t, base.UnmarshalSSZ(raw))
st, err := v3.InitializeFromProto(base)
require.NoError(t, err)
return st
}
func unmarshalBellatrixBlock(t *testing.T, raw []byte) interfaces.SignedBeaconBlock {
base := &ethpb.BeaconBlockBellatrix{}
require.NoError(t, base.UnmarshalSSZ(raw))
blk, err := blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlockBellatrix{Block: base, Signature: make([]byte, fieldparams.BLSSignatureLength)})
require.NoError(t, err)
return blk
}
func unmarshalSignedBellatrixBlock(t *testing.T, raw []byte) interfaces.SignedBeaconBlock {
base := &ethpb.SignedBeaconBlockBellatrix{}
require.NoError(t, base.UnmarshalSSZ(raw))
blk, err := blocks.NewSignedBeaconBlock(base)
require.NoError(t, err)
return blk
}