Update to spec v0.8.3 (#3355)

* Ignore latest messages in fork choice prior to latest justified

* Make sure Compact Committee Roots isn't changed by process_final_updates

* WIP add attestation bitfields length to match committee length

* Begin work on updating spec tests to 0.8.2

* WIP set up for new spec test structure

* Fix slashings

* Get mainnet tests mostly passing for attestations and attester slashings

* Fix process attestation test

* Undo change

* Complete spec tests for all operations
Still need sanity block tests

* Fix BLS sigs

* Reduce amount of reused code in core/blocks/spectests/

* Fix tests

* Update block sanity tests to 0.8.2

* Update epoch spec tests to 0.8.2

* Clean up all tests and fix shuffling/epoch tests

* WIP update bls tests to 0.8.2

* WIP update bls tests to 0.8.3

* Finish BLS spectest update to 0.8.3

* Fix shuffling spec tests

* Fix more tests

* Update proto ssz spec tests to 0.8.3

* Attempt to fix PrevEpochFFGDataMismatches test

* Goimports

* Fix documentation

* fix test

* Use custom general spec tests

* Reduce code footprint

* Remove unneeded minimal skip

* Fix for comments

* Fix for comments

* Fix test

* Small fixes

* Cleanup block spec tests a bit

* Undo change

* fix validator

* Fix validator tests

* Run gazelle

* Fix error output for epoch spec tests
This commit is contained in:
Ivan Martinez
2019-09-08 15:41:52 -04:00
committed by Preston Van Loon
parent d94522510f
commit 5e939378d0
103 changed files with 1671 additions and 2412 deletions

View File

@@ -14,3 +14,6 @@ run --host_force_python=PY2
# is required within the sandbox. This flag is no longer experimental after 0.29.0.
# Network sandboxing only works on linux.
--experimental_sandbox_default_allow_network=false
# Use minimal protobufs at runtime
run --define ssz=minimal

View File

@@ -146,18 +146,52 @@ http_archive(
)
http_archive(
name = "eth2_spec_tests",
name = "eth2_spec_tests_general",
build_file_content = """
filegroup(
name = "test_data",
srcs = glob([
"**/*.ssz",
"**/*.yaml",
]),
visibility = ["//visibility:public"],
)
""",
sha256 = "a531804ac35d2398d37cfa755a686280d8cb3a9649e993e3cf89640f06191d5e",
url = "https://github.com/prysmaticlabs/eth2.0-spec-tests/releases/download/v0.8.1/base64_encoded_archive.tar.gz",
sha256 = "386335fc3b055fad37088bd821929ff684bc00bb1a74e044e4b377ebd6e88fce",
# File names are normally too long, see: https://github.com/ethereum/eth2.0-spec-tests/issues/15
url = "https://prysmaticlabs.com/uploads/v0.8.3_general_spectests.tar.gz",
)
http_archive(
name = "eth2_spec_tests_minimal",
build_file_content = """
filegroup(
name = "test_data",
srcs = glob([
"**/*.ssz",
"**/*.yaml",
]),
visibility = ["//visibility:public"],
)
""",
sha256 = "7ab89a364796e3f8a9af84750c241e9c9e2170a34c1a4e160fdfa2cee5b03fb7",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.8.3/minimal.tar.gz",
)
http_archive(
name = "eth2_spec_tests_mainnet",
build_file_content = """
filegroup(
name = "test_data",
srcs = glob([
"**/*.ssz",
"**/*.yaml",
]),
visibility = ["//visibility:public"],
)
""",
sha256 = "6274e3b77f393faf7b17cef10e93244c16316d3b7ae9c6b844501b12f432a7c3",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.8.3/mainnet.tar.gz",
)
http_archive(

View File

@@ -92,8 +92,12 @@ func (s *Store) GenesisStore(
// Spec pseudocode definition:
// def get_ancestor(store: Store, root: Hash, slot: Slot) -> Hash:
// block = store.blocks[root]
// assert block.slot >= slot
// return root if block.slot == slot else get_ancestor(store, block.parent_root, slot)
// if block.slot > slot:
// return get_ancestor(store, block.parent_root, slot)
// elif block.slot == slot:
// return root
// else:
// return Bytes32() # root is older than queried slot: no results.
func (s *Store) ancestor(ctx context.Context, root []byte, slot uint64) ([]byte, error) {
ctx, span := trace.StartSpan(ctx, "forkchoice.ancestor")
defer span.End()

View File

@@ -525,9 +525,15 @@ func ProcessAttestationsNoVerify(
// Process ``Attestation`` operation.
// """
// data = attestation.data
// assert data.crosslink.shard < SHARD_COUNT
// assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
//
// attestation_slot = get_attestation_data_slot(state, data)
// assert attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation_slot + SLOTS_PER_EPOCH
//
// committee = get_crosslink_committee(state, data.target.epoch, data.crosslink.shard)
// assert len(attestation.aggregation_bits) == len(attestation.custody_bits) == len(committee)
//
// pending_attestation = PendingAttestation(
// data=data,
// aggregation_bitfield=attestation.aggregation_bitfield,
@@ -535,23 +541,23 @@ func ProcessAttestationsNoVerify(
// proposer_index=get_beacon_proposer_index(state),
// )
//
// assert data.target_epoch in (get_previous_epoch(state), get_current_epoch(state))
// if data.target_epoch == get_current_epoch(state):
// ffg_data = (state.current_justified_epoch, state.current_justified_root, get_current_epoch(state))
// parent_crosslink = state.current_crosslinks[data.crosslink.shard]
// state.current_epoch_attestations.append(pending_attestation)
// assert data.source == state.current_justified_checkpoint
// parent_crosslink = state.current_crosslinks[data.crosslink.shard]
// state.current_epoch_attestations.append(pending_attestation)
// else:
// ffg_data = (state.previous_justified_epoch, state.previous_justified_root, get_previous_epoch(state))
// parent_crosslink = state.previous_crosslinks[data.crosslink.shard]
// state.previous_epoch_attestations.append(pending_attestation)
// assert data.source == state.previous_justified_checkpoint
// parent_crosslink = state.previous_crosslinks[data.crosslink.shard]
// state.previous_epoch_attestations.append(pending_attestation)
//
// # Check FFG data, crosslink data, and signature
// assert ffg_data == (data.source_epoch, data.source_root, data.target_epoch)
// assert data.crosslink.start_epoch == parent_crosslink.end_epoch
// assert data.crosslink.end_epoch == min(data.target_epoch, parent_crosslink.end_epoch + MAX_EPOCHS_PER_CROSSLINK)
// # Check crosslink against expected parent crosslink
// assert data.crosslink.parent_root == hash_tree_root(parent_crosslink)
// assert data.crosslink.start_epoch == parent_crosslink.end_epoch
// assert data.crosslink.end_epoch == min(data.target.epoch, parent_crosslink.end_epoch + MAX_EPOCHS_PER_CROSSLINK)
// assert data.crosslink.data_root == Bytes32() # [to be removed in phase 1]
// validate_indexed_attestation(state, convert_to_indexed(state, attestation))
//
// # Check signature
// assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
func ProcessAttestation(beaconState *pb.BeaconState, att *ethpb.Attestation) (*pb.BeaconState, error) {
beaconState, err := ProcessAttestationNoVerify(beaconState, att)
if err != nil {
@@ -564,6 +570,24 @@ func ProcessAttestation(beaconState *pb.BeaconState, att *ethpb.Attestation) (*p
// method is used to validate attestations whose signatures have already been verified.
func ProcessAttestationNoVerify(beaconState *pb.BeaconState, att *ethpb.Attestation) (*pb.BeaconState, error) {
data := att.Data
if data.Crosslink.Shard > params.BeaconConfig().ShardCount {
return nil, fmt.Errorf(
"expected crosslink shard %d to be less than SHARD_COUNT %d",
data.Crosslink.Shard,
params.BeaconConfig().ShardCount,
)
}
if data.Target.Epoch != helpers.PrevEpoch(beaconState) && data.Target.Epoch != helpers.CurrentEpoch(beaconState) {
return nil, fmt.Errorf(
"expected target epoch (%d) to be the previous epoch (%d) or the current epoch (%d)",
data.Target.Epoch,
helpers.PrevEpoch(beaconState),
helpers.CurrentEpoch(beaconState),
)
}
attestationSlot, err := helpers.AttestationDataSlot(beaconState, data)
if err != nil {
return nil, errors.Wrap(err, "could not get attestation slot")
@@ -586,6 +610,11 @@ func ProcessAttestationNoVerify(beaconState *pb.BeaconState, att *ethpb.Attestat
params.BeaconConfig().SlotsPerEpoch,
)
}
if err := helpers.VerifyAttestationBitfieldLengths(beaconState, att); err != nil {
return nil, errors.Wrap(err, "could not verify attestation bitfields")
}
proposerIndex, err := helpers.BeaconProposerIndex(beaconState)
if err != nil {
return nil, err
@@ -597,15 +626,6 @@ func ProcessAttestationNoVerify(beaconState *pb.BeaconState, att *ethpb.Attestat
ProposerIndex: proposerIndex,
}
if !(data.Target.Epoch == helpers.PrevEpoch(beaconState) || data.Target.Epoch == helpers.CurrentEpoch(beaconState)) {
return nil, fmt.Errorf(
"expected target epoch %d == %d or %d",
data.Target.Epoch,
helpers.PrevEpoch(beaconState),
helpers.CurrentEpoch(beaconState),
)
}
var ffgSourceEpoch uint64
var ffgSourceRoot []byte
var ffgTargetEpoch uint64
@@ -664,6 +684,7 @@ func ProcessAttestationNoVerify(beaconState *pb.BeaconState, att *ethpb.Attestat
data.Crosslink.ParentRoot,
)
}
// To be removed in Phase 1
if !bytes.Equal(data.Crosslink.DataRoot, params.BeaconConfig().ZeroHash[:]) {
return nil, fmt.Errorf("expected data root %#x == ZERO_HASH", data.Crosslink.DataRoot)

View File

@@ -906,20 +906,20 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
helpers.ClearActiveCountCache()
helpers.ClearStartShardCache()
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
},
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
}
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
Attestations: []*ethpb.Attestation{att},
},
}
deposits, _ := testutil.SetupInitialDeposits(t, 100)
@@ -929,10 +929,17 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
}
helpers.ClearAllCaches()
beaconState.Slot += params.BeaconConfig().SlotsPerEpoch*4 + params.BeaconConfig().MinAttestationInclusionDelay
beaconState.PreviousCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
},
}
beaconState.PreviousJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.PreviousEpochAttestations = []*pb.PendingAttestation{}
want := fmt.Sprintf(
"expected target epoch %d == %d or %d",
attestations[0].Data.Target.Epoch,
"expected target epoch (%d) to be the previous epoch (%d) or the current epoch (%d)",
att.Data.Target.Epoch,
helpers.PrevEpoch(beaconState),
helpers.CurrentEpoch(beaconState),
)
@@ -944,15 +951,20 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
helpers.ClearAllCaches()
aggBits := bitfield.NewBitlist(1)
custodyBits := bitfield.NewBitlist(1)
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Source: &ethpb.Checkpoint{Epoch: 1},
Crosslink: &ethpb.Crosslink{
Shard: 0,
Shard: 0,
StartEpoch: 0,
},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
},
}
block := &ethpb.BeaconBlock{
@@ -999,15 +1011,26 @@ func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
helpers.ClearAllCaches()
deposits, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
if err != nil {
t.Fatal(err)
}
aggBits := bitfield.NewBitlist(1)
aggBits.SetBitAt(0, true)
custodyBits := bitfield.NewBitlist(1)
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 1},
Crosslink: &ethpb.Crosslink{
Shard: 0,
},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
},
}
block := &ethpb.BeaconBlock{
@@ -1015,12 +1038,8 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
Attestations: attestations,
},
}
deposits, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
if err != nil {
t.Fatal(err)
}
helpers.ClearAllCaches()
beaconState.Slot += params.BeaconConfig().SlotsPerEpoch + params.BeaconConfig().MinAttestationInclusionDelay
beaconState.PreviousCrosslinks = []*ethpb.Crosslink{
{
@@ -1038,13 +1057,15 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
if _, err := blocks.ProcessAttestations(beaconState, block.Body); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
helpers.ClearAllCaches()
block.Body.Attestations[0].Data.Source.Epoch = helpers.PrevEpoch(beaconState)
block.Body.Attestations[0].Data.Target.Epoch = helpers.CurrentEpoch(beaconState)
block.Body.Attestations[0].Data.Source.Root = []byte{}
want = fmt.Sprintf(
"expected source root %#x, received %#x",
beaconState.PreviousJustifiedCheckpoint.Root,
beaconState.CurrentJustifiedCheckpoint.Root,
attestations[0].Data.Source.Root,
)
if _, err := blocks.ProcessAttestations(beaconState, block.Body); !strings.Contains(err.Error(), want) {
@@ -1055,6 +1076,9 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
func TestProcessAttestations_CrosslinkMismatches(t *testing.T) {
helpers.ClearAllCaches()
aggBits := bitfield.NewBitlist(1)
aggBits.SetBitAt(0, true)
custodyBits := bitfield.NewBitlist(1)
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
@@ -1064,6 +1088,8 @@ func TestProcessAttestations_CrosslinkMismatches(t *testing.T) {
Shard: 0,
},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
},
}
block := &ethpb.BeaconBlock{
@@ -1108,14 +1134,16 @@ func TestProcessAttestations_CrosslinkMismatches(t *testing.T) {
}
}
func TestProcessAttestations_OK(t *testing.T) {
func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
helpers.ClearAllCaches()
deposits, privKeys := testutil.SetupInitialDeposits(t, 100)
deposits, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
if err != nil {
t.Fatal(err)
}
aggBits := bitfield.NewBitlist(2)
custodyBits := bitfield.NewBitlist(2)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
@@ -1125,30 +1153,10 @@ func TestProcessAttestations_OK(t *testing.T) {
StartEpoch: 0,
},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
CustodyBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0x01},
AggregationBits: aggBits,
CustodyBits: custodyBits,
}
attestingIndices, err := helpers.AttestingIndices(beaconState, att.Data, att.AggregationBits)
if err != nil {
t.Error(err)
}
domain := helpers.Domain(beaconState, 0, params.BeaconConfig().DomainAttestation)
sigs := make([]*bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
dataAndCustodyBit := &pb.AttestationDataAndCustodyBit{
Data: att.Data,
CustodyBit: false,
}
hashTreeRoot, err := ssz.HashTreeRoot(dataAndCustodyBit)
if err != nil {
t.Error(err)
}
sig := privKeys[indice].Sign(hashTreeRoot[:], domain)
sigs[i] = sig
}
att.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{att},
@@ -1172,6 +1180,80 @@ func TestProcessAttestations_OK(t *testing.T) {
block.Body.Attestations[0].Data.Crosslink.ParentRoot = encoded[:]
block.Body.Attestations[0].Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
expected := "failed to verify aggregation bitfield: wanted participants bitfield length 1, got: 2"
_, err = blocks.ProcessAttestations(beaconState, block.Body)
if !strings.Contains(err.Error(), expected) {
t.Errorf("Expected error checking aggregation and custody bit length, received: %v", err)
}
}
func TestProcessAttestations_OK(t *testing.T) {
helpers.ClearAllCaches()
deposits, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
if err != nil {
t.Fatal(err)
}
aggBits := bitfield.NewBitlist(1)
aggBits.SetBitAt(0, true)
custodyBits := bitfield.NewBitlist(1)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
}
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: 0,
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
att.Data.Crosslink.ParentRoot = encoded[:]
att.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
attestingIndices, err := helpers.AttestingIndices(beaconState, att.Data, att.AggregationBits)
if err != nil {
t.Error(err)
}
dataAndCustodyBit := &pb.AttestationDataAndCustodyBit{
Data: att.Data,
CustodyBit: false,
}
hashTreeRoot, err := ssz.HashTreeRoot(dataAndCustodyBit)
if err != nil {
t.Error(err)
}
domain := helpers.Domain(beaconState, 0, params.BeaconConfig().DomainAttestation)
sigs := make([]*bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
sig := privKeys[indice].Sign(hashTreeRoot[:], domain)
sigs[i] = sig
}
att.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{att},
},
}
beaconState.Slot += params.BeaconConfig().MinAttestationInclusionDelay
if _, err := blocks.ProcessAttestations(beaconState, block.Body); err != nil {
t.Errorf("Unexpected error: %v", err)
}
@@ -1186,6 +1268,9 @@ func TestProcessAttestationsNoVerify_OK(t *testing.T) {
t.Fatal(err)
}
aggBits := bitfield.NewBitlist(1)
aggBits.SetBitAt(1, true)
custodyBits := bitfield.NewBitlist(1)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
@@ -1195,8 +1280,8 @@ func TestProcessAttestationsNoVerify_OK(t *testing.T) {
StartEpoch: 0,
},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
CustodyBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0x01},
AggregationBits: aggBits,
CustodyBits: custodyBits,
}
zeroSig := [96]byte{}

View File

@@ -2,19 +2,9 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
testonly = True,
srcs = [
"attestation_test.yaml.go",
"block_operations.yaml.go",
"blocks_mainnet.yaml.go",
"blocks_minimal.yaml.go",
],
srcs = ["block_processing_test.yaml.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks/spectest",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
],
)
test_suite(
@@ -34,7 +24,7 @@ go_test(
exclude = ["*_minimal_test.go"],
),
data = glob(["*.yaml"]) + [
"@eth2_spec_tests//:test_data",
"@eth2_spec_tests_mainnet//:test_data",
],
embed = [":go_default_library"],
shard_count = 4,
@@ -44,10 +34,12 @@ go_test(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/core/state/stateutils:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//shared/params/spectest:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],
@@ -61,7 +53,7 @@ go_test(
exclude = ["*_mainnet_test.go"],
),
data = glob(["*.yaml"]) + [
"@eth2_spec_tests//:test_data",
"@eth2_spec_tests_minimal//:test_data",
],
embed = [":go_default_library"],
tags = ["spectest"],
@@ -70,10 +62,12 @@ go_test(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/core/state/stateutils:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//shared/params/spectest:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],

View File

@@ -5,5 +5,5 @@ import (
)
func TestAttestationMainnet(t *testing.T) {
runAttestationTest(t, "attestation_mainnet.yaml")
runAttestationTest(t, "mainnet")
}

View File

@@ -5,5 +5,5 @@ import (
)
func TestAttestationMinimal(t *testing.T) {
runAttestationTest(t, "attestation_minimal.yaml")
runAttestationTest(t, "minimal")
}

View File

@@ -1,78 +1,36 @@
package spectest
import (
"io/ioutil"
"reflect"
"path"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
func runAttestationTest(t *testing.T, filename string) {
filepath, err := bazel.Runfile("tests/operations/attestation/" + filename)
if err != nil {
t.Fatal(err)
}
file, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &AttestationTest{}
if err := testutil.UnmarshalYaml(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
func runAttestationTest(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(test.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
body := &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{
tt.Attestation,
},
}
post, err := blocks.ProcessAttestations(tt.Pre, body)
if !reflect.ValueOf(tt.Post).IsValid() {
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if err == nil {
t.Fatal("did not fail when expected")
}
return
}
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
t.Logf("Expected failure; failure reason = %v", err)
return
} else if err != nil {
testFolders, testsFolderPath := testutil.TestFolders(t, config, "operations/attestation/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
attestationFile, err := testutil.BazelFileBytes(folderPath, "attestation.ssz")
if err != nil {
t.Fatal(err)
}
if !proto.Equal(post, tt.Post) {
diff, _ := messagediff.PrettyDiff(post, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
att := &ethpb.Attestation{}
if err := ssz.Unmarshal(attestationFile, att); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
body := &ethpb.BeaconBlockBody{Attestations: []*ethpb.Attestation{att}}
testutil.RunBlockOperationTest(t, folderPath, body, blocks.ProcessAttestations)
})
}
}

View File

@@ -1,26 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: attestation_minimal.yaml
package spectest
import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
)
type AttestationTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
Attestation *ethpb.Attestation `json:"attestation"`
Post *pb.BeaconState `json:"post"`
BlsSetting uint64 `json:"bls_setting,omitempty"`
} `json:"test_cases"`
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestAttesterSlashingMainnet(t *testing.T) {
filepath, err := bazel.Runfile(attesterSlashingPrefix + "attester_slashing_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runAttesterSlashingTest(t, filepath)
runAttesterSlashingTest(t, "mainnet")
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestAttesterSlashingMinimal(t *testing.T) {
filepath, err := bazel.Runfile(attesterSlashingPrefix + "attester_slashing_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runAttesterSlashingTest(t, filepath)
runAttesterSlashingTest(t, "minimal")
}

View File

@@ -1,63 +1,36 @@
package spectest
import (
"io/ioutil"
"path"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
const attesterSlashingPrefix = "tests/operations/attester_slashing/"
func runAttesterSlashingTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
test := &BlockOperationTest{}
if err := testutil.UnmarshalYaml(file, test); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
func runAttesterSlashingTest(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(test.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
body := &ethpb.BeaconBlockBody{AttesterSlashings: []*ethpb.AttesterSlashing{tt.AttesterSlashing}}
postState, err := blocks.ProcessAttesterSlashings(tt.Pre, body)
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
return
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "operations/attester_slashing/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
attSlashingFile, err := testutil.BazelFileBytes(folderPath, "attester_slashing.ssz")
if err != nil {
t.Fatal(err)
}
if !proto.Equal(postState, tt.Post) {
diff, _ := messagediff.PrettyDiff(postState, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
attSlashing := &ethpb.AttesterSlashing{}
if err := ssz.Unmarshal(attSlashingFile, attSlashing); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
body := &ethpb.BeaconBlockBody{AttesterSlashings: []*ethpb.AttesterSlashing{attSlashing}}
testutil.RunBlockOperationTest(t, folderPath, body, blocks.ProcessAttesterSlashings)
})
}
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestBlockHeaderMainnet(t *testing.T) {
filepath, err := bazel.Runfile(blkHeaderPrefix + "block_header_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runBlockHeaderTest(t, filepath)
runBlockHeaderTest(t, "mainnet")
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestBlockHeaderMinimal(t *testing.T) {
filepath, err := bazel.Runfile(blkHeaderPrefix + "block_header_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runBlockHeaderTest(t, filepath)
runBlockHeaderTest(t, "minimal")
}

View File

@@ -2,63 +2,87 @@ package spectest
import (
"io/ioutil"
"path"
"strings"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
const blkHeaderPrefix = "tests/operations/block_header/"
// Block header test is actually a full block processing test. Not sure why it
// was named "block_header". The note in the test format readme says "Note that
// block_header is not strictly an operation (and is a full Block), but
// processed in the same manner, and hence included here."
func runBlockHeaderTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &BlockOperationTest{}
if err := testutil.UnmarshalYaml(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
func runBlockHeaderTest(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(test.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
testFolders, testsFolderPath := testutil.TestFolders(t, config, "operations/block_header/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
helpers.ClearAllCaches()
post, err := blocks.ProcessBlockHeader(tt.Pre, tt.Block)
if tt.Post == nil {
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if err == nil {
t.Fatal("did not fail when expected")
}
return
}
blockFile, err := testutil.BazelFileBytes(testsFolderPath, folder.Name(), "block.ssz")
if err != nil {
t.Fatal(err)
}
block := &ethpb.BeaconBlock{}
if err := ssz.Unmarshal(blockFile, block); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
if !proto.Equal(post, tt.Post) {
diff, _ := messagediff.PrettyDiff(post, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
preBeaconStateFile, err := testutil.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz")
if err != nil {
t.Fatal(err)
}
preBeaconState := &pb.BeaconState{}
if err := ssz.Unmarshal(preBeaconStateFile, preBeaconState); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
// If the post.ssz is not present, it means the test should fail on our end.
postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz"))
postSSZExists := true
if err != nil && strings.Contains(err.Error(), "could not locate file") {
postSSZExists = false
} else if err != nil {
t.Fatal(err)
}
beaconState, err := blocks.ProcessBlockHeader(preBeaconState, block)
if postSSZExists {
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
postBeaconStateFile, err := ioutil.ReadFile(postSSZFilepath)
if err != nil {
t.Fatal(err)
}
postBeaconState := &pb.BeaconState{}
if err := ssz.Unmarshal(postBeaconStateFile, postBeaconState); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
if !proto.Equal(beaconState, postBeaconState) {
diff, _ := messagediff.PrettyDiff(beaconState, postBeaconState)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
} else {
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if err == nil {
t.Fatal("Did not fail when expected")
}
t.Logf("Expected failure; failure reason = %v", err)
return
}
})
}

View File

@@ -1,31 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: voluntary_exit_minimal.yaml
package spectest
import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
)
type BlockOperationTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
BlsSetting uint64 `json:"bls_setting,omitempty"`
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
VoluntaryExit *ethpb.VoluntaryExit `json:"voluntary_exit"`
ProposerSlashing *ethpb.ProposerSlashing `json:"proposer_slashing"`
AttesterSlashing *ethpb.AttesterSlashing `json:"attester_slashing"`
Deposit *ethpb.Deposit `json:"deposit"`
Transfer *ethpb.Transfer `json:"transfer"`
Block *ethpb.BeaconBlock `json:"block"`
Post *pb.BeaconState `json:"post"`
} `json:"test_cases"`
}

View File

@@ -5,5 +5,5 @@ import (
)
func TestBlockProcessingMainnetYaml(t *testing.T) {
runBlockProcessingTest(t, "sanity_blocks_mainnet.yaml")
runBlockProcessingTest(t, "mainnet")
}

View File

@@ -5,7 +5,5 @@ import (
)
func TestBlockProcessingMinimalYaml(t *testing.T) {
t.Skip("This test suite requires --define ssz=minimal to be provided and there isn't a great way to do that without breaking //... See https://github.com/prysmaticlabs/prysm/issues/3066")
runBlockProcessingTest(t, "sanity_blocks_minimal.yaml")
runBlockProcessingTest(t, "minimal")
}

View File

@@ -2,67 +2,103 @@ package spectest
import (
"context"
"fmt"
"io/ioutil"
"path"
"strings"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
func runBlockProcessingTest(t *testing.T, filename string) {
filepath, err := bazel.Runfile("tests/sanity/blocks/" + filename)
if err != nil {
func runBlockProcessingTest(t *testing.T, config string) {
if err := spectest.SetConfig(config); 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 := testutil.UnmarshalYaml(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)
}
if len(s.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
ctx := context.Background()
testFolders, testsFolderPath := testutil.TestFolders(t, config, "sanity/blocks/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
helpers.ClearAllCaches()
blocks.ClearEth1DataVoteCache()
s := tt.Pre
for _, b := range tt.Blocks {
tt.Pre, err = state.ExecuteStateTransition(ctx, tt.Pre, b)
if tt.Post == nil {
if err == nil {
t.Fatal("Transition did not fail despite being invalid")
}
continue
}
if err != nil {
t.Fatalf("Transition failed with block at slot %d: %v", b.Slot, err)
}
preBeaconStateFile, err := testutil.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz")
if err != nil {
t.Fatal(err)
}
if tt.Post != nil {
if !proto.Equal(s, tt.Post) {
diff, _ := messagediff.PrettyDiff(s, tt.Post)
beaconState := &pb.BeaconState{}
if err := ssz.Unmarshal(preBeaconStateFile, beaconState); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
file, err := testutil.BazelFileBytes(testsFolderPath, folder.Name(), "meta.yaml")
if err != nil {
t.Fatal(err)
}
metaYaml := &SanityConfig{}
if err := testutil.UnmarshalYaml(file, metaYaml); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
var transitionError error
for i := 0; i < metaYaml.BlocksCount; i++ {
filename := fmt.Sprintf("blocks_%d.ssz", i)
blockFile, err := testutil.BazelFileBytes(testsFolderPath, folder.Name(), filename)
if err != nil {
t.Fatal(err)
}
block := &ethpb.BeaconBlock{}
if err := ssz.Unmarshal(blockFile, block); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
beaconState, transitionError = state.ExecuteStateTransition(context.Background(), beaconState, block)
}
// If the post.ssz is not present, it means the test should fail on our end.
postSSZFilepath, readError := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz"))
postSSZExists := true
if readError != nil && strings.Contains(readError.Error(), "could not locate file") {
postSSZExists = false
} else if readError != nil {
t.Fatal(readError)
}
if postSSZExists {
if transitionError != nil {
t.Fatalf("Unexpected error: %v", transitionError)
}
postBeaconStateFile, err := ioutil.ReadFile(postSSZFilepath)
if err != nil {
t.Fatal(err)
}
postBeaconState := &pb.BeaconState{}
if err := ssz.Unmarshal(postBeaconStateFile, postBeaconState); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
if !proto.Equal(beaconState, postBeaconState) {
diff, _ := messagediff.PrettyDiff(beaconState, postBeaconState)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
} else {
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if transitionError == nil {
t.Fatal("Did not fail when expected")
}
t.Logf("Expected failure; failure reason = %v", transitionError)
return
}
})
}

View File

@@ -0,0 +1,6 @@
package spectest
// SanityConfig --
type SanityConfig struct {
BlocksCount int `json:"blocks_count"`
}

View File

@@ -1,25 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: sanity_blocks_mainnet.yaml
package spectest
import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
)
type BlocksMainnet struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
Blocks []*ethpb.BeaconBlock `json:"blocks"`
Post *pb.BeaconState `json:"post"`
} `json:"test_cases"`
}

View File

@@ -1,25 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: sanity_blocks_minimal.yaml
package spectest
import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
)
type BlocksMinimal struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
Blocks []*ethpb.BeaconBlock `json:"blocks"`
Post *pb.BeaconState `json:"post"`
} `json:"test_cases"`
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestDepositMainnetYaml(t *testing.T) {
filepath, err := bazel.Runfile(depositPrefix + "deposit_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runDepositTest(t, filepath)
runDepositTest(t, "mainnet")
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestDepositMinimalYaml(t *testing.T) {
filepath, err := bazel.Runfile(depositPrefix + "deposit_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runDepositTest(t, filepath)
runDepositTest(t, "minimal")
}

View File

@@ -1,58 +1,36 @@
package spectest
import (
"io/ioutil"
"reflect"
"path"
"testing"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state/stateutils"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
const depositPrefix = "tests/operations/deposit/"
func runDepositTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
test := &BlockOperationTest{}
if err := testutil.UnmarshalYaml(file, test); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
func runDepositTest(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(test.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range test.TestCases {
helpers.ClearAllCaches()
t.Run(tt.Description, func(t *testing.T) {
valMap := stateutils.ValidatorIndexMap(tt.Pre)
post, err := blocks.ProcessDeposit(tt.Pre, tt.Deposit, valMap)
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
return
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "operations/deposit/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
depositFile, err := testutil.BazelFileBytes(folderPath, "deposit.ssz")
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(post, tt.Post) {
t.Error("Post state does not match expected")
deposit := &ethpb.Deposit{}
if err := ssz.Unmarshal(depositFile, deposit); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
body := &ethpb.BeaconBlockBody{Deposits: []*ethpb.Deposit{deposit}}
testutil.RunBlockOperationTest(t, folderPath, body, blocks.ProcessDeposits)
})
}
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestProposerSlashingMainnet(t *testing.T) {
filepath, err := bazel.Runfile(proposerSlashingPrefix + "proposer_slashing_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runProposerSlashingTest(t, filepath)
runProposerSlashingTest(t, "mainnet")
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestProposerSlashingMinimal(t *testing.T) {
filepath, err := bazel.Runfile(proposerSlashingPrefix + "proposer_slashing_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runProposerSlashingTest(t, filepath)
runProposerSlashingTest(t, "minimal")
}

View File

@@ -1,63 +1,36 @@
package spectest
import (
"io/ioutil"
"path"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
const proposerSlashingPrefix = "tests/operations/proposer_slashing/"
func runProposerSlashingTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
test := &BlockOperationTest{}
if err := testutil.UnmarshalYaml(file, test); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
func runProposerSlashingTest(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(test.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
body := &ethpb.BeaconBlockBody{ProposerSlashings: []*ethpb.ProposerSlashing{tt.ProposerSlashing}}
postState, err := blocks.ProcessProposerSlashings(tt.Pre, body)
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
return
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "operations/proposer_slashing/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
proposerSlashingFile, err := testutil.BazelFileBytes(folderPath, "proposer_slashing.ssz")
if err != nil {
t.Fatal(err)
}
if !proto.Equal(postState, tt.Post) {
diff, _ := messagediff.PrettyDiff(postState, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
proposerSlashing := &ethpb.ProposerSlashing{}
if err := ssz.Unmarshal(proposerSlashingFile, proposerSlashing); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
body := &ethpb.BeaconBlockBody{ProposerSlashings: []*ethpb.ProposerSlashing{proposerSlashing}}
testutil.RunBlockOperationTest(t, folderPath, body, blocks.ProcessProposerSlashings)
})
}
}

View File

@@ -1,16 +0,0 @@
package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestTransferMainnet(t *testing.T) {
t.Skip("Transfer tests are disabled. See https://github.com/ethereum/eth2.0-specs/pull/1238#issuecomment-507054595")
filepath, err := bazel.Runfile(transferPrefix + "transfer_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runTransferTest(t, filepath)
}

View File

@@ -1,16 +0,0 @@
package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestTransferMinimal(t *testing.T) {
t.Skip("Transfer tests are disabled. See https://github.com/ethereum/eth2.0-specs/pull/1238#issuecomment-507054595")
filepath, err := bazel.Runfile(transferPrefix + "transfer_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runTransferTest(t, filepath)
}

View File

@@ -1,63 +0,0 @@
package spectest
import (
"io/ioutil"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
const transferPrefix = "tests/operations/transfer/"
func runTransferTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
test := &BlockOperationTest{}
if err := testutil.UnmarshalYaml(file, test); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
t.Fatal(err)
}
if len(test.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
body := &ethpb.BeaconBlockBody{Transfers: []*ethpb.Transfer{tt.Transfer}}
postState, err := blocks.ProcessTransfers(tt.Pre, body)
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
return
}
if err != nil {
t.Fatal(err)
}
if !proto.Equal(postState, tt.Post) {
diff, _ := messagediff.PrettyDiff(postState, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
})
}
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestVoluntaryExitMainnet(t *testing.T) {
filepath, err := bazel.Runfile(exitPrefix + "voluntary_exit_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runVoluntaryExitTest(t, filepath)
runVoluntaryExitTest(t, "mainnet")
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestVoluntaryExitMinimal(t *testing.T) {
filepath, err := bazel.Runfile(exitPrefix + "voluntary_exit_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runVoluntaryExitTest(t, filepath)
runVoluntaryExitTest(t, "minimal")
}

View File

@@ -1,63 +1,36 @@
package spectest
import (
"io/ioutil"
"path"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
const exitPrefix = "tests/operations/voluntary_exit/"
func runVoluntaryExitTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
test := &BlockOperationTest{}
if err := testutil.UnmarshalYaml(file, test); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
func runVoluntaryExitTest(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(test.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
body := &ethpb.BeaconBlockBody{VoluntaryExits: []*ethpb.VoluntaryExit{tt.VoluntaryExit}}
postState, err := blocks.ProcessVoluntaryExits(tt.Pre, body)
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
return
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "operations/voluntary_exit/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
exitFile, err := testutil.BazelFileBytes(folderPath, "voluntary_exit.ssz")
if err != nil {
t.Fatal(err)
}
if !proto.Equal(postState, tt.Post) {
diff, _ := messagediff.PrettyDiff(postState, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
voluntaryExit := &ethpb.VoluntaryExit{}
if err := ssz.Unmarshal(exitFile, voluntaryExit); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
body := &ethpb.BeaconBlockBody{VoluntaryExits: []*ethpb.VoluntaryExit{voluntaryExit}}
testutil.RunBlockOperationTest(t, folderPath, body, blocks.ProcessVoluntaryExits)
})
}
}

View File

@@ -46,7 +46,7 @@ type MatchedAttestations struct {
// def get_matching_head_attestations(state: BeaconState, epoch: Epoch) -> List[PendingAttestation]:
// return [
// a for a in get_matching_source_attestations(state, epoch)
// if a.data.beacon_block_root == get_block_root_at_slot(state, a.data.slot)
// if a.data.beacon_block_root == get_block_root_at_slot(state, get_attestation_data_slot(state, a.data))
// ]
func MatchAttestations(state *pb.BeaconState, epoch uint64) (*MatchedAttestations, error) {
currentEpoch := helpers.CurrentEpoch(state)
@@ -443,8 +443,6 @@ func ProcessSlashings(state *pb.BeaconState) (*pb.BeaconState, error) {
// HALF_INCREMENT = EFFECTIVE_BALANCE_INCREMENT // 2
// if balance < validator.effective_balance or validator.effective_balance + 3 * HALF_INCREMENT < balance:
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
// # Update start shard
// state.start_shard = Shard((state.start_shard + get_shard_delta(state, current_epoch)) % SHARD_COUNT)
// # Set active index root
// index_epoch = Epoch(next_epoch + ACTIVATION_EXIT_DELAY)
// index_root_position = index_epoch % EPOCHS_PER_HISTORICAL_VECTOR
@@ -461,6 +459,8 @@ func ProcessSlashings(state *pb.BeaconState) (*pb.BeaconState, error) {
// if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
// historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots)
// state.historical_roots.append(hash_tree_root(historical_batch))
// # Update start shard
// state.start_shard = Shard((state.start_shard + get_shard_delta(state, current_epoch)) % SHARD_COUNT)
// # Rotate current/previous epoch attestations
// state.previous_epoch_attestations = state.current_epoch_attestations
// state.current_epoch_attestations = []
@@ -485,14 +485,6 @@ func ProcessFinalUpdates(state *pb.BeaconState) (*pb.BeaconState, error) {
}
}
// Update start shard.
delta, err := helpers.ShardDelta(state, currentEpoch)
if err != nil {
return nil, errors.Wrap(err, "could not get shard delta")
}
state.StartShard = (state.StartShard + delta) %
params.BeaconConfig().ShardCount
// Set active index root.
// index_epoch = Epoch(next_epoch + ACTIVATION_EXIT_DELAY)
// index_root_position = index_epoch % EPOCHS_PER_HISTORICAL_VECTOR
@@ -540,6 +532,13 @@ func ProcessFinalUpdates(state *pb.BeaconState) (*pb.BeaconState, error) {
state.HistoricalRoots = append(state.HistoricalRoots, batchRoot[:])
}
// Update start shard.
delta, err := helpers.ShardDelta(state, currentEpoch)
if err != nil {
return nil, errors.Wrap(err, "could not get shard delta")
}
state.StartShard = (state.StartShard + delta) % params.BeaconConfig().ShardCount
// Rotate current and previous epoch attestations.
state.PreviousEpochAttestations = state.CurrentEpochAttestations
state.CurrentEpochAttestations = []*pb.PendingAttestation{}

View File

@@ -1,12 +1,4 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["epoch_processing_test.yaml.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/spectest",
visibility = ["//beacon-chain:__subpackages__"],
deps = ["//proto/beacon/p2p/v1:go_default_library"],
)
load("@io_bazel_rules_go//go:def.bzl", "go_test")
test_suite(
name = "go_default_test",
@@ -25,9 +17,8 @@ go_test(
exclude = ["*_minimal_test.go"],
),
data = [
"@eth2_spec_tests//:test_data",
"@eth2_spec_tests_mainnet//:test_data",
],
embed = [":go_default_library"],
shard_count = 4,
tags = [
"spectest",
@@ -39,6 +30,7 @@ go_test(
"//shared/params/spectest:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],
@@ -52,9 +44,8 @@ go_test(
exclude = ["*_mainnet_test.go"],
),
data = [
"@eth2_spec_tests//:test_data",
"@eth2_spec_tests_minimal//:test_data",
],
embed = [":go_default_library"],
tags = [
"spectest",
],

View File

@@ -2,16 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
)
func TestCrosslinksProcessingMainnet(t *testing.T) {
helpers.ClearAllCaches()
filepath, err := bazel.Runfile(crosslinkPrefix + "crosslinks_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runCrosslinkProcessingTests(t, filepath)
runCrosslinkProcessingTests(t, "mainnet")
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestCrosslinksProcessingMinimal(t *testing.T) {
filepath, err := bazel.Runfile(crosslinkPrefix + "crosslinks_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runCrosslinkProcessingTests(t, filepath)
runCrosslinkProcessingTests(t, "minimal")
}

View File

@@ -1,47 +1,33 @@
package spectest
import (
"io/ioutil"
"reflect"
"path"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
const crosslinkPrefix = "tests/epoch_processing/crosslinks/"
func runCrosslinkProcessingTests(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &EpochProcessingTest{}
if err := testutil.UnmarshalYaml(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
func runCrosslinkProcessingTests(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(s.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
postState, err := epoch.ProcessCrosslinks(tt.Pre)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(postState, tt.Post) {
t.Error("Did not get expected state")
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "epoch_processing/crosslinks/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
testutil.RunEpochOperationTest(t, folderPath, processCrosslinksWrapper)
})
}
}
func processCrosslinksWrapper(t *testing.T, state *pb.BeaconState) (*pb.BeaconState, error) {
state, err := epoch.ProcessCrosslinks(state)
if err != nil {
t.Fatalf("could not process crosslinks: %v", err)
}
return state, nil
}

View File

@@ -1,19 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
package spectest
import pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
type EpochProcessingTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
Post *pb.BeaconState `json:"post"`
} `json:"test_cases"`
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestFinalUpdatesMainnet(t *testing.T) {
filepath, err := bazel.Runfile(finalUpdatesPrefix + "final_updates_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runFinalUpdatesTests(t, filepath)
runFinalUpdatesTests(t, "mainnet")
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestFinalUpdatesMinimal(t *testing.T) {
filepath, err := bazel.Runfile(finalUpdatesPrefix + "final_updates_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runFinalUpdatesTests(t, filepath)
runFinalUpdatesTests(t, "minimal")
}

View File

@@ -1,54 +1,33 @@
package spectest
import (
"io/ioutil"
"reflect"
"path"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
const finalUpdatesPrefix = "tests/epoch_processing/final_updates/"
func runFinalUpdatesTests(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &EpochProcessingTest{}
if err := testutil.UnmarshalYaml(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
func runFinalUpdatesTests(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(s.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
var postState *pb.BeaconState
postState, err = epoch.ProcessFinalUpdates(tt.Pre)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(postState, tt.Post) {
t.Error("Did not get expected state")
diff, _ := messagediff.PrettyDiff(tt.Post, postState)
t.Log(diff)
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "epoch_processing/final_updates/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
testutil.RunEpochOperationTest(t, folderPath, processFinalUpdatesWrapper)
})
}
}
func processFinalUpdatesWrapper(t *testing.T, state *pb.BeaconState) (*pb.BeaconState, error) {
state, err := epoch.ProcessFinalUpdates(state)
if err != nil {
t.Fatalf("could not process final updates: %v", err)
}
return state, nil
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestJustificationAndFinalizationMainnet(t *testing.T) {
filepath, err := bazel.Runfile(justificationAndFinalizationPrefix + "justification_and_finalization_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runJustificationAndFinalizationTests(t, filepath)
runJustificationAndFinalizationTests(t, "mainnet")
}

View File

@@ -2,15 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestJustificationAndFinalizationMinimal(t *testing.T) {
t.Skip("This test suite requires --define ssz=minimal to be provided and there isn't a great way to do that without breaking //... See https://github.com/prysmaticlabs/prysm/issues/3066")
filepath, err := bazel.Runfile(justificationAndFinalizationPrefix + "justification_and_finalization_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runJustificationAndFinalizationTests(t, filepath)
runJustificationAndFinalizationTests(t, "minimal")
}

View File

@@ -1,102 +1,55 @@
package spectest
import (
"fmt"
"io/ioutil"
"reflect"
"path"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
const justificationAndFinalizationPrefix = "tests/epoch_processing/justification_and_finalization/"
func runJustificationAndFinalizationTests(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
testPath := "epoch_processing/justification_and_finalization/pyspec_tests"
testFolders, testsFolderPath := testutil.TestFolders(t, config, testPath)
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
testutil.RunEpochOperationTest(t, folderPath, processJustificationAndFinalizationWrapper)
})
}
}
// This is a subset of state.ProcessEpoch. The spec test defines input data for
// `justification_and_finalization` only.
func processJustificationAndFinalizationWrapper(state *pb.BeaconState) (*pb.BeaconState, error) {
helpers.ClearAllCaches()
// This process mutates the state, so we'll make a copy in order to print debug before/after.
state = proto.Clone(state).(*pb.BeaconState)
func processJustificationAndFinalizationWrapper(t *testing.T, state *pb.BeaconState) (*pb.BeaconState, error) {
prevEpochAtts, err := epoch.MatchAttestations(state, helpers.PrevEpoch(state))
if err != nil {
return nil, fmt.Errorf("could not get target atts prev epoch %d: %v",
helpers.PrevEpoch(state), err)
t.Fatalf("could not get target atts prev epoch %d: %v", helpers.PrevEpoch(state), err)
}
currentEpochAtts, err := epoch.MatchAttestations(state, helpers.CurrentEpoch(state))
if err != nil {
return nil, fmt.Errorf("could not get target atts current epoch %d: %v",
helpers.CurrentEpoch(state), err)
t.Fatalf("could not get target atts current epoch %d: %v", helpers.CurrentEpoch(state), err)
}
prevEpochAttestedBalance, err := epoch.AttestingBalance(state, prevEpochAtts.Target)
if err != nil {
return nil, fmt.Errorf("could not get attesting balance prev epoch: %v", err)
t.Fatalf("could not get attesting balance prev epoch: %v", err)
}
currentEpochAttestedBalance, err := epoch.AttestingBalance(state, currentEpochAtts.Target)
if err != nil {
return nil, fmt.Errorf("could not get attesting balance current epoch: %v", err)
t.Fatalf("could not get attesting balance current epoch: %v", err)
}
state, err = epoch.ProcessJustificationAndFinalization(state, prevEpochAttestedBalance, currentEpochAttestedBalance)
if err != nil {
return nil, fmt.Errorf("could not process justification: %v", err)
t.Fatalf("could not process justification: %v", err)
}
return state, nil
}
func runJustificationAndFinalizationTests(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &EpochProcessingTest{}
if err := testutil.UnmarshalYaml(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
t.Fatal(err)
}
if len(s.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
preState := &pb.BeaconState{}
if err := testutil.ConvertToPb(tt.Pre, preState); err != nil {
t.Fatal(err)
}
postState, err := processJustificationAndFinalizationWrapper(preState)
if err != nil {
t.Fatal(err)
}
expectedPostState := &pb.BeaconState{}
if err := testutil.ConvertToPb(tt.Post, expectedPostState); err != nil {
t.Fatal(err)
}
if postState.JustificationBits[0] != expectedPostState.JustificationBits[0] {
t.Errorf("Justification bits mismatch. PreState.JustificationBits=%v. PostState.JustificationBits=%v. Expected=%v", preState.JustificationBits, postState.JustificationBits, expectedPostState.JustificationBits)
}
if !reflect.DeepEqual(postState, expectedPostState) {
diff, _ := messagediff.PrettyDiff(postState, expectedPostState)
t.Log(diff)
t.Error("Did not get expected state")
}
})
}
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestRegistryProcessingMainnet(t *testing.T) {
filepath, err := bazel.Runfile(registryUpdatesPrefix + "registry_updates_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runRegisteryProcessingTests(t, filepath)
func TestRegistryUpdatesMainnet(t *testing.T) {
runRegistryUpdatesTests(t, "mainnet")
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestRegistryProcessingMinimal(t *testing.T) {
filepath, err := bazel.Runfile(registryUpdatesPrefix + "registry_updates_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runRegisteryProcessingTests(t, filepath)
func TestRegistryUpdatesMinimal(t *testing.T) {
runRegistryUpdatesTests(t, "minimal")
}

View File

@@ -1,46 +1,33 @@
package spectest
import (
"io/ioutil"
"reflect"
"path"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
const registryUpdatesPrefix = "tests/epoch_processing/registry_updates/"
func runRegisteryProcessingTests(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &EpochProcessingTest{}
if err := testutil.UnmarshalYaml(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
func runRegistryUpdatesTests(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(s.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
postState, err := epoch.ProcessRegistryUpdates(tt.Pre)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(postState, tt.Post) {
t.Error("Did not get expected state")
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "epoch_processing/registry_updates/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
testutil.RunEpochOperationTest(t, folderPath, processRegistryUpdatesWrapper)
})
}
}
func processRegistryUpdatesWrapper(t *testing.T, state *pb.BeaconState) (*pb.BeaconState, error) {
state, err := epoch.ProcessRegistryUpdates(state)
if err != nil {
t.Fatalf("could not process registry updates: %v", err)
}
return state, nil
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestSlashingsMainnet(t *testing.T) {
filepath, err := bazel.Runfile(slashingsPrefix + "slashings_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runSlashingsTests(t, filepath)
runSlashingsTests(t, "mainnet")
}

View File

@@ -2,14 +2,8 @@ package spectest
import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
func TestSlashingsMinimal(t *testing.T) {
filepath, err := bazel.Runfile(slashingsPrefix + "slashings_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runSlashingsTests(t, filepath)
runSlashingsTests(t, "minimal")
}

View File

@@ -1,48 +1,33 @@
package spectest
import (
"io/ioutil"
"reflect"
"path"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
const slashingsPrefix = "tests/epoch_processing/slashings/"
func runSlashingsTests(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &EpochProcessingTest{}
if err := testutil.UnmarshalYaml(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
func runSlashingsTests(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(s.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
postState, err := epoch.ProcessSlashings(tt.Pre)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(postState, tt.Post) {
t.Error("Did not get expected state")
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "epoch_processing/slashings/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
testutil.RunEpochOperationTest(t, folderPath, processSlashingsWrapper)
})
}
}
func processSlashingsWrapper(t *testing.T, state *pb.BeaconState) (*pb.BeaconState, error) {
state, err := epoch.ProcessSlashings(state)
if err != nil {
t.Fatalf("could not process slashings: %v", err)
}
return state, nil
}

View File

@@ -17,7 +17,7 @@ import (
// assert slot < state.slot <= slot + SLOTS_PER_HISTORICAL_ROOT
// return state.block_roots[slot % SLOTS_PER_HISTORICAL_ROOT]
func BlockRootAtSlot(state *pb.BeaconState, slot uint64) ([]byte, error) {
if !(slot < state.Slot && state.Slot <= slot+params.BeaconConfig().SlotsPerHistoricalRoot) {
if slot >= state.Slot || state.Slot > slot+params.BeaconConfig().SlotsPerHistoricalRoot {
return []byte{}, errors.New("slot out of bounds")
}
return state.BlockRoots[slot%params.BeaconConfig().SlotsPerHistoricalRoot], nil

View File

@@ -175,6 +175,17 @@ func AttestingIndices(state *pb.BeaconState, data *ethpb.AttestationData, bf bit
return indices, nil
}
// VerifyBitfieldLength verifies that a bitfield length matches the given committee size.
func VerifyBitfieldLength(bf bitfield.Bitfield, committeeSize uint64) error {
if bf.Len() != committeeSize {
return fmt.Errorf(
"wanted participants bitfield length %d, got: %d",
committeeSize,
bf.Len())
}
return nil
}
// CommitteeAssignment is used to query committee assignment from
// current and previous epoch.
//
@@ -346,6 +357,27 @@ func StartShard(state *pb.BeaconState, epoch uint64) (uint64, error) {
return startShard, nil
}
// VerifyAttestationBitfieldLengths verifies that an attestations aggregation and custody bitfields are
// a valid length matching the size of the committee.
func VerifyAttestationBitfieldLengths(bState *pb.BeaconState, att *ethpb.Attestation) error {
committee, err := CrosslinkCommittee(bState, att.Data.Target.Epoch, att.Data.Crosslink.Shard)
if err != nil {
return errors.Wrap(err, "could not retrieve crosslink committees")
}
if committee == nil {
return errors.New("no committee exist for shard in the attestation")
}
if err := VerifyBitfieldLength(att.AggregationBits, uint64(len(committee))); err != nil {
return errors.Wrap(err, "failed to verify aggregation bitfield")
}
if err := VerifyBitfieldLength(att.CustodyBits, uint64(len(committee))); err != nil {
return errors.Wrap(err, "failed to verify custody bitfield")
}
return nil
}
// CompactCommitteesRoot returns the index root of a given epoch.
//
// Spec pseudocode definition:

View File

@@ -3,6 +3,7 @@ package helpers
import (
"fmt"
"reflect"
"strings"
"testing"
"github.com/prysmaticlabs/go-bitfield"
@@ -318,6 +319,20 @@ func TestAttestationParticipants_EmptyBitfield(t *testing.T) {
}
}
func TestVerifyBitfieldLength_OK(t *testing.T) {
bf := bitfield.Bitlist{0xFF, 0x01}
committeeSize := uint64(8)
if err := VerifyBitfieldLength(bf, committeeSize); err != nil {
t.Errorf("bitfield is not validated when it was supposed to be: %v", err)
}
bf = bitfield.Bitlist{0xFF, 0x07}
committeeSize = 10
if err := VerifyBitfieldLength(bf, committeeSize); err != nil {
t.Errorf("bitfield is not validated when it was supposed to be: %v", err)
}
}
func TestCommitteeAssignment_CanRetrieve(t *testing.T) {
// Initialize test with 128 validators, each slot and each shard gets 2 validators.
validators := make([]*ethpb.Validator, 2*params.BeaconConfig().SlotsPerEpoch)
@@ -572,6 +587,139 @@ func TestEpochStartShard_MixedActivationValidators(t *testing.T) {
}
}
func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
validators := make([]*ethpb.Validator, 2*params.BeaconConfig().SlotsPerEpoch)
activeRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
activeRoots[i] = []byte{'A'}
}
state := &pb.BeaconState{
Validators: validators,
ActiveIndexRoots: activeRoots,
RandaoMixes: activeRoots,
}
tests := []struct {
attestation *ethpb.Attestation
stateSlot uint64
invalidCustodyBits bool
verificationFailure bool
}{
{
attestation: &ethpb.Attestation{
AggregationBits: bitfield.Bitlist{0x05},
CustodyBits: bitfield.Bitlist{0x05},
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 5,
},
Target: &ethpb.Checkpoint{},
},
},
stateSlot: 5,
},
{
attestation: &ethpb.Attestation{
AggregationBits: bitfield.Bitlist{0x06},
CustodyBits: bitfield.Bitlist{0x06},
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 10,
},
Target: &ethpb.Checkpoint{},
},
},
stateSlot: 10,
},
{
attestation: &ethpb.Attestation{
AggregationBits: bitfield.Bitlist{0x06},
CustodyBits: bitfield.Bitlist{0x06},
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 20,
},
Target: &ethpb.Checkpoint{},
},
},
stateSlot: 20,
},
{
attestation: &ethpb.Attestation{
AggregationBits: bitfield.Bitlist{0x06},
CustodyBits: bitfield.Bitlist{0x10},
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 20,
},
Target: &ethpb.Checkpoint{},
},
},
stateSlot: 20,
verificationFailure: true,
invalidCustodyBits: true,
},
{
attestation: &ethpb.Attestation{
AggregationBits: bitfield.Bitlist{0xFF, 0xC0, 0x01},
CustodyBits: bitfield.Bitlist{0xFF, 0xC0, 0x01},
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 5,
},
Target: &ethpb.Checkpoint{},
},
},
stateSlot: 5,
verificationFailure: true,
},
{
attestation: &ethpb.Attestation{
AggregationBits: bitfield.Bitlist{0xFF, 0x01},
CustodyBits: bitfield.Bitlist{0xFF, 0x01},
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 20,
},
Target: &ethpb.Checkpoint{},
},
},
stateSlot: 20,
verificationFailure: true,
},
}
for i, tt := range tests {
ClearAllCaches()
state.Slot = tt.stateSlot
err := VerifyAttestationBitfieldLengths(state, tt.attestation)
if tt.verificationFailure {
if tt.invalidCustodyBits {
if !strings.Contains(err.Error(), "custody bitfield") {
t.Errorf("%d expected custody bits to fail: %v", i, err)
}
}
if err == nil {
t.Error("verification succeeded when it was supposed to fail")
}
continue
}
if err != nil {
t.Errorf("%d Failed to verify bitfield: %v", i, err)
continue
}
}
}
func TestCompactCommitteesRoot_OK(t *testing.T) {
ClearAllCaches()
// Create 10 committees

View File

@@ -12,15 +12,16 @@ go_test(
size = "small",
srcs = ["shuffle_yaml_test.go"],
data = [
"@eth2_spec_tests//:test_data",
"@eth2_spec_tests_mainnet//:test_data",
"@eth2_spec_tests_minimal//:test_data",
],
embed = [":go_default_library"],
tags = ["spectest"],
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//shared/params/spectest:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_go_yaml_yaml//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],
)

View File

@@ -1,20 +1,8 @@
package spectest
// ShuffleTest --
type ShuffleTest struct {
Title string `yaml:"title"`
Summary string `yaml:"summary"`
ForksTimeline string `yaml:"forks_timeline"`
Forks []string `yaml:"forks"`
Config string `yaml:"config"`
Runner string `yaml:"runner"`
Handler string `yaml:"handler"`
TestCases []*ShuffleTestCase `yaml:"test_cases"`
}
// ShuffleTestCase --
type ShuffleTestCase struct {
Seed string `yaml:"seed"`
Count uint64 `yaml:"count"`
Shuffled []uint64 `yaml:"shuffled"`
Seed string `yaml:"seed"`
Count uint64 `yaml:"count"`
Mapping []uint64 `yaml:"mapping"`
}

View File

@@ -1,68 +1,56 @@
package spectest
import (
"encoding/base64"
"encoding/hex"
"fmt"
"io/ioutil"
"path"
"reflect"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ethereum/go-ethereum/common"
"github.com/go-yaml/yaml"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
const shufflePrefix = "tests/shuffling/core/"
func TestShufflingMinimal(t *testing.T) {
helpers.ClearAllCaches()
filepath, err := bazel.Runfile(shufflePrefix + "shuffling_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runShuffleTests(t, filepath)
runShuffleTests(t, "minimal")
}
func TestShufflingMainnet(t *testing.T) {
helpers.ClearAllCaches()
filepath, err := bazel.Runfile(shufflePrefix + "shuffling_full.yaml")
if err != nil {
t.Fatal(err)
}
runShuffleTests(t, filepath)
runShuffleTests(t, "mainnet")
}
func runShuffleTests(t *testing.T, filepath string) {
file, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatalf("could not read YAML tests directory: %v", err)
}
shuffleTest := &ShuffleTest{}
if err := yaml.Unmarshal(file, shuffleTest); err != nil {
t.Fatalf("could not unmarshal YAML file into test struct: %v", err)
}
if err := spectest.SetConfig(shuffleTest.Config); err != nil {
func runShuffleTests(t *testing.T, config string) {
helpers.ClearAllCaches()
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
t.Logf("Title: %v", shuffleTest.Title)
t.Logf("Summary: %v", shuffleTest.Summary)
t.Logf("Fork: %v", shuffleTest.Forks)
t.Logf("Config: %v", shuffleTest.Config)
for _, testCase := range shuffleTest.TestCases {
if err := runShuffleTest(testCase); err != nil {
t.Fatalf("shuffle test failed: %v", err)
}
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "shuffling/core/shuffle")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
testCaseFile, err := testutil.BazelFileBytes(path.Join(testsFolderPath, folder.Name(), "mapping.yaml"))
if err != nil {
t.Fatalf("could not read YAML tests directory: %v", err)
}
testCase := &ShuffleTestCase{}
if err := yaml.Unmarshal(testCaseFile, testCase); err != nil {
t.Fatalf("could not unmarshal YAML file into test struct: %v", err)
}
if err := runShuffleTest(testCase); err != nil {
t.Fatalf("shuffle test failed: %v", err)
}
})
}
}
// RunShuffleTest uses validator set specified from a YAML file, runs the validator shuffle
// algorithm, then compare the output with the expected output from the YAML file.
func runShuffleTest(testCase *ShuffleTestCase) error {
baseSeed, err := base64.StdEncoding.DecodeString(testCase.Seed)
baseSeed, err := hex.DecodeString(testCase.Seed[2:])
if err != nil {
return err
}
@@ -80,8 +68,8 @@ func runShuffleTest(testCase *ShuffleTestCase) error {
}
shuffledList[i] = si
}
if !reflect.DeepEqual(shuffledList, testCase.Shuffled) {
return fmt.Errorf("shuffle result error: expected %v, actual %v", testCase.Shuffled, shuffledList)
if !reflect.DeepEqual(shuffledList, testCase.Mapping) {
return fmt.Errorf("shuffle result error: expected %v, actual %v", testCase.Mapping, shuffledList)
}
return nil
}

View File

@@ -1,19 +1,4 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"genesis_initialization.yaml.go",
"genesis_validity.yaml.go",
"sanity_slots_test.yaml.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/state/spectest",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
],
)
load("@io_bazel_rules_go//go:def.bzl", "go_test")
test_suite(
name = "go_default_test",
@@ -32,14 +17,14 @@ go_test(
exclude = ["*_minimal_test.go"],
),
data = [
"@eth2_spec_tests//:test_data",
"@eth2_spec_tests_mainnet//:test_data",
],
embed = [":go_default_library"],
shard_count = 2,
tags = ["spectest"],
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//shared/params:go_default_library",
"//shared/params/spectest:go_default_library",
@@ -59,13 +44,13 @@ go_test(
exclude = ["*_mainnet_test.go"],
),
data = [
"@eth2_spec_tests//:test_data",
"@eth2_spec_tests_minimal//:test_data",
],
embed = [":go_default_library"],
tags = ["spectest"],
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//shared/params:go_default_library",
"//shared/params/spectest:go_default_library",

View File

@@ -1,26 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: genesis_initialization_minimal.yaml
package spectest
import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
)
type GenesisInitializationTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Eth1BlockHash []byte `json:"eth1_block_hash"`
Eth1Timestamp uint64 `json:"eth1_timestamp"`
Deposits []*ethpb.Deposit `json:"deposits"`
State *pb.BeaconState `json:"state"`
} `json:"test_cases"`
}

View File

@@ -1,70 +0,0 @@
package spectest
import (
"io/ioutil"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestGenesisInitializationMinimal(t *testing.T) {
t.Skip("This test suite requires --define ssz=minimal to be provided and there isn't a great way to do that without breaking //... See https://github.com/prysmaticlabs/prysm/issues/3066")
filepath, err := bazel.Runfile("tests/genesis/initialization/genesis_initialization_minimal.yaml")
if err != nil {
t.Fatal(err)
}
file, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &GenesisInitializationTest{}
if err := testutil.UnmarshalYaml(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
t.Fatal(err)
}
if len(s.TestCases) == 0 {
t.Fatal("No tests!")
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
deposits := tt.Deposits
dataLeaves := make([]*ethpb.Deposit_Data, len(deposits))
for i := range deposits {
dataLeaves[i] = deposits[i].Data
}
depositRoot, err := ssz.HashTreeRootWithCapacity(dataLeaves, 1<<params.BeaconConfig().DepositContractTreeDepth)
if err != nil {
t.Fatal(err)
}
eth1Data := &ethpb.Eth1Data{
DepositRoot: depositRoot[:],
DepositCount: uint64(len(deposits)),
BlockHash: tt.Eth1BlockHash,
}
genesisState, err := state.GenesisBeaconState(deposits, tt.Eth1Timestamp, eth1Data)
if err != nil {
t.Fatal(err)
}
if !proto.Equal(genesisState, tt.State) {
t.Error("States are not equal")
}
})
}
}

View File

@@ -1,21 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: genesis_initialization_minimal.yaml
package spectest
import pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
type GenesisValidityTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Genesis *pb.BeaconState `json:"genesis"`
IsValid bool `json:"is_valid"`
} `json:"test_cases"`
}

View File

@@ -1,53 +0,0 @@
package spectest
import (
"io/ioutil"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestGenesisValidityMinimal(t *testing.T) {
filepath, err := bazel.Runfile("tests/genesis/validity/genesis_validity_minimal.yaml")
if err != nil {
t.Fatal(err)
}
file, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &GenesisValidityTest{}
if err := testutil.UnmarshalYaml(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
t.Fatal(err)
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
genesisState := tt.Genesis
validatorCount, err := helpers.ActiveValidatorCount(genesisState, 0)
if err != nil {
t.Fatalf("Could not get active validator count: %v", err)
}
isValid := state.IsValidGenesisState(validatorCount, genesisState.GenesisTime)
if isValid != tt.IsValid {
t.Fatalf(
"Genesis state does not have expected validity. Expected to be valid: %d, %d. %t %t",
tt.Genesis.GenesisTime,
validatorCount,
isValid,
tt.IsValid,
)
}
})
}
}

View File

@@ -1,22 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: sanity_slots_minimal.yaml
package spectest
import pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
type SanitySlotsTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
Slots uint64 `json:"slots"`
Post *pb.BeaconState `json:"post"`
} `json:"test_cases"`
}

View File

@@ -5,5 +5,5 @@ import (
)
func TestSlotProcessingMainnet(t *testing.T) {
runSlotProcessingTests(t, "sanity_slots_mainnet.yaml")
runSlotProcessingTests(t, "mainnet")
}

View File

@@ -5,6 +5,5 @@ import (
)
func TestSlotProcessingMinimal(t *testing.T) {
t.Skip("This test suite requires --define ssz=minimal to be provided and there isn't a great way to do that without breaking //... See https://github.com/prysmaticlabs/prysm/issues/3066")
runSlotProcessingTests(t, "sanity_slots_minimal.yaml")
runSlotProcessingTests(t, "minimal")
}

View File

@@ -2,53 +2,65 @@ package spectest
import (
"context"
"io/ioutil"
"strconv"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
const slotProcessingPrefix = "tests/sanity/slots/"
func runSlotProcessingTests(t *testing.T, filename string) {
filepath, err := bazel.Runfile(slotProcessingPrefix + filename)
if err != nil {
t.Fatal(err)
}
file, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &SanitySlotsTest{}
if err := testutil.UnmarshalYaml(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
func runSlotProcessingTests(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
if len(s.TestCases) == 0 {
t.Fatal("No tests!")
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "sanity/slots/pyspec_tests")
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
postState, err := state.ProcessSlots(context.Background(), tt.Pre, tt.Pre.Slot+tt.Slots)
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
helpers.ClearAllCaches()
preBeaconStateFile, err := testutil.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz")
if err != nil {
t.Fatal(err)
}
beaconState := &pb.BeaconState{}
if err := ssz.Unmarshal(preBeaconStateFile, beaconState); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
file, err := testutil.BazelFileBytes(testsFolderPath, folder.Name(), "slots.yaml")
if err != nil {
t.Fatal(err)
}
fileStr := string(file)
slotsCount, err := strconv.Atoi(fileStr[:len(fileStr)-5])
if err != nil {
t.Fatal(err)
}
if !proto.Equal(postState, tt.Post) {
diff, _ := messagediff.PrettyDiff(postState, tt.Post)
postBeaconStateFile, err := testutil.BazelFileBytes(testsFolderPath, folder.Name(), "post.ssz")
if err != nil {
t.Fatal(err)
}
postBeaconState := &pb.BeaconState{}
if err := ssz.Unmarshal(postBeaconStateFile, postBeaconState); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
postState, err := state.ProcessSlots(context.Background(), beaconState, beaconState.Slot+uint64(slotsCount))
if err != nil {
t.Fatal(err)
}
if !proto.Equal(postState, postBeaconState) {
diff, _ := messagediff.PrettyDiff(beaconState, postBeaconState)
t.Log(diff)
_ = diff
t.Fatal("Post state does not match expected")
}
})

View File

@@ -453,6 +453,19 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
BodyRoot: bodyRoot[:],
}
beaconState.Slashings = make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: helpers.SlotToEpoch(beaconState.Slot),
DataRoot: []byte{1},
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
proposerSlashIdx := uint64(3)
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
@@ -553,11 +566,10 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
blockRoots = append(blockRoots, []byte{byte(i)})
}
beaconState.BlockRoots = blockRoots
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
DataRoot: []byte{1},
},
}
aggBits := bitfield.NewBitlist(1)
aggBits.SetBitAt(1, true)
custodyBits := bitfield.NewBitlist(1)
blockAtt := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: helpers.SlotToEpoch(beaconState.Slot)},
@@ -566,27 +578,29 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
Root: []byte("hello-world"),
},
Crosslink: &ethpb.Crosslink{
Shard: 0,
EndEpoch: 64,
Shard: 0,
EndEpoch: 64,
DataRoot: params.BeaconConfig().ZeroHash[:],
ParentRoot: encoded[:],
},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
CustodyBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0x01},
AggregationBits: aggBits,
CustodyBits: custodyBits,
}
attestingIndices, err := helpers.AttestingIndices(beaconState, blockAtt.Data, blockAtt.AggregationBits)
if err != nil {
t.Error(err)
}
dataAndCustodyBit = &pb.AttestationDataAndCustodyBit{
Data: blockAtt.Data,
CustodyBit: false,
}
hashTreeRoot, err = ssz.HashTreeRoot(dataAndCustodyBit)
if err != nil {
t.Error(err)
}
sigs := make([]*bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
dataAndCustodyBit := &pb.AttestationDataAndCustodyBit{
Data: blockAtt.Data,
CustodyBit: false,
}
hashTreeRoot, err := ssz.HashTreeRoot(dataAndCustodyBit)
if err != nil {
t.Error(err)
}
sig := privKeys[indice].Sign(hashTreeRoot[:], domain)
sigs[i] = sig
}
@@ -607,18 +621,6 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
if err != nil {
t.Fatal(err)
}
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: helpers.SlotToEpoch(beaconState.Slot),
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
randaoReveal, err := testutil.CreateRandaoReveal(beaconState, currentEpoch, privKeys)
if err != nil {
@@ -639,8 +641,6 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
},
},
}
block.Body.Attestations[0].Data.Crosslink.ParentRoot = encoded[:]
block.Body.Attestations[0].Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
block, err = testutil.SignBlock(beaconState, block, privKeys)
if err != nil {

View File

@@ -196,6 +196,20 @@ func TestPendingAttestations_FiltersWithinInclusionDelay(t *testing.T) {
t.Fatal(err)
}
currentEpoch := helpers.CurrentEpoch(beaconState)
activeCount, err := helpers.ActiveValidatorCount(beaconState, currentEpoch)
if err != nil {
t.Error(err)
}
committeeCount, err := helpers.CommitteeCount(beaconState, currentEpoch)
if err != nil {
t.Error(err)
}
aggBits := bitfield.NewBitlist(activeCount / committeeCount)
for i := uint64(0); i < aggBits.Len(); i++ {
aggBits.SetBitAt(i, true)
}
custodyBits := bitfield.NewBitlist(activeCount / committeeCount)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
@@ -205,15 +219,22 @@ func TestPendingAttestations_FiltersWithinInclusionDelay(t *testing.T) {
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
CustodyBits: []byte{0x00, 0x00, 0x00, 0x00},
AggregationBits: aggBits,
CustodyBits: custodyBits,
}
attestingIndices, err := helpers.AttestingIndices(beaconState, att.Data, att.AggregationBits)
if err != nil {
t.Error(err)
}
currentEpoch := helpers.CurrentEpoch(beaconState)
dataAndCustodyBit := &pbp2p.AttestationDataAndCustodyBit{
Data: att.Data,
CustodyBit: false,
}
hashTreeRoot, err := ssz.HashTreeRoot(dataAndCustodyBit)
if err != nil {
t.Error(err)
}
domain := helpers.Domain(beaconState, currentEpoch, params.BeaconConfig().DomainAttestation)
sigs := make([]*bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
@@ -221,14 +242,6 @@ func TestPendingAttestations_FiltersWithinInclusionDelay(t *testing.T) {
if err != nil {
t.Error(err)
}
dataAndCustodyBit := &pbp2p.AttestationDataAndCustodyBit{
Data: att.Data,
CustodyBit: false,
}
hashTreeRoot, err := ssz.HashTreeRoot(dataAndCustodyBit)
if err != nil {
t.Error(err)
}
beaconState.Validators[indice].PublicKey = priv.PublicKey().Marshal()[:]
sigs[i] = priv.Sign(hashTreeRoot[:], domain)
}
@@ -310,14 +323,30 @@ func TestPendingAttestations_FiltersExpiredAttestations(t *testing.T) {
LatestBlockHeader: &ethpb.BeaconBlockHeader{StateRoot: []byte{}},
}
currentEpoch := helpers.CurrentEpoch(beaconState)
activeCount, err := helpers.ActiveValidatorCount(beaconState, currentEpoch)
if err != nil {
t.Error(err)
}
committeeCount, err := helpers.CommitteeCount(beaconState, currentEpoch)
if err != nil {
t.Error(err)
}
aggBits := bitfield.NewBitlist(activeCount / committeeCount)
for i := uint64(0); i < aggBits.Len(); i++ {
aggBits.SetBitAt(i, true)
}
custodyBits := bitfield.NewBitlist(activeCount / committeeCount)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{EndEpoch: 10, DataRoot: params.BeaconConfig().ZeroHash[:], ParentRoot: encoded[:]},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
AggregationBits: aggBits,
CustodyBits: custodyBits,
}
attestingIndices, err := helpers.AttestingIndices(beaconState, att.Data, att.AggregationBits)
if err != nil {
t.Error(err)
@@ -349,38 +378,60 @@ func TestPendingAttestations_FiltersExpiredAttestations(t *testing.T) {
opService := &mockOperationService{
pendingAttestations: []*ethpb.Attestation{
//Expired attestations
{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
}},
{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
}},
{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
}},
{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
}},
{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
}},
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
},
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
},
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
},
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
},
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
},
AggregationBits: aggBits,
CustodyBits: custodyBits},
// Non-expired attestation with incorrect justified epoch
{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch - 1},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
}},
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 10},
Source: &ethpb.Checkpoint{Epoch: expectedEpoch - 1},
Crosslink: &ethpb.Crosslink{DataRoot: params.BeaconConfig().ZeroHash[:]},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
},
// Non-expired attestations with correct justified epoch
att,
att2,
@@ -421,7 +472,8 @@ func TestPendingAttestations_FiltersExpiredAttestations(t *testing.T) {
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{EndEpoch: 10, DataRoot: params.BeaconConfig().ZeroHash[:], ParentRoot: encoded[:]},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
AggregationBits: aggBits,
CustodyBits: custodyBits,
Signature: aggregateSig,
},
{
@@ -430,7 +482,8 @@ func TestPendingAttestations_FiltersExpiredAttestations(t *testing.T) {
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{EndEpoch: 10, DataRoot: params.BeaconConfig().ZeroHash[:], ParentRoot: encoded[:]},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
AggregationBits: aggBits,
CustodyBits: custodyBits,
Signature: aggregateSig,
},
{
@@ -439,7 +492,8 @@ func TestPendingAttestations_FiltersExpiredAttestations(t *testing.T) {
Source: &ethpb.Checkpoint{Epoch: expectedEpoch},
Crosslink: &ethpb.Crosslink{EndEpoch: 10, DataRoot: params.BeaconConfig().ZeroHash[:], ParentRoot: encoded[:]},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
AggregationBits: aggBits,
CustodyBits: custodyBits,
Signature: aggregateSig,
},
}

View File

@@ -35,10 +35,12 @@ go_test(
size = "small",
srcs = [
"ssz_regression_test.go",
"ssz_static_test.go",
"tags_test.go",
],
data = [
"@eth2_spec_tests//:test_data",
"@eth2_spec_tests_mainnet//:test_data",
"@eth2_spec_tests_minimal//:test_data",
],
embed = [":go_default_library"],
tags = ["spectest"],
@@ -46,6 +48,7 @@ go_test(
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/params/spectest:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_ghodss_yaml//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
@@ -58,16 +61,18 @@ go_test(
name = "go_minimal_test",
size = "small",
srcs = [
"ssz_minimal_compatibility_test.go",
"ssz_static_minimal_test.go",
"ssz_static_test.go",
],
data = [
"@eth2_spec_tests//:test_data",
"@eth2_spec_tests_minimal//:test_data",
],
tags = ["spectest"],
deps = [
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/params/spectest:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_ghodss_yaml//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
@@ -80,16 +85,18 @@ go_test(
name = "go_mainnet_test",
size = "small",
srcs = [
"ssz_mainnet_compatibility_test.go",
"ssz_static_mainnet_test.go",
"ssz_static_test.go",
],
data = [
"@eth2_spec_tests//:test_data",
"@eth2_spec_tests_mainnet//:test_data",
],
tags = ["spectest"],
deps = [
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/params/spectest:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_ghodss_yaml//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",

View File

@@ -1,354 +0,0 @@
package testing
import (
"bytes"
"io/ioutil"
"path"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/go-ssz"
sszspectest "github.com/prysmaticlabs/go-ssz/spectests"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestYamlStatic_Mainnet(t *testing.T) {
topPath := "tests/ssz_static/core/"
yamlFileNames := []string{
"ssz_mainnet_random.yaml",
}
for _, f := range yamlFileNames {
fullPath := path.Join(topPath, f)
filepath, err := bazel.Runfile(fullPath)
if err != nil {
t.Fatal(err)
}
file, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &sszspectest.SszMainnetTest{}
if err := yaml.Unmarshal(file, s); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
runTestCasesMainnet(t, s)
}
}
func runTestCasesMainnet(t *testing.T, s *sszspectest.SszMainnetTest) {
for _, testCase := range s.TestCases {
if !testutil.IsEmpty(testCase.Attestation.Value) {
p := &ethpb.Attestation{}
if err := testutil.ConvertToPb(testCase.Attestation.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Attestation.Root) {
t.Errorf("Expected attestation root %#x, received %#x", testCase.Attestation.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Attestation.SigningRoot) {
t.Errorf("Expected attestation signing root data %#x, received %#x", testCase.AttestationData.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.AttestationData.Value) {
p := &ethpb.AttestationData{}
if err := testutil.ConvertToPb(testCase.AttestationData.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.AttestationData.Root) {
t.Errorf("Expected attestation data %#x, received %#x", testCase.AttestationData.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.AttestationDataAndCustodyBit.Value) {
p := &pb.AttestationDataAndCustodyBit{}
if err := testutil.ConvertToPb(testCase.AttestationDataAndCustodyBit.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.AttestationDataAndCustodyBit.Root) {
t.Errorf("Expected attestation data and custody bit %#x, received %#x", testCase.AttestationDataAndCustodyBit.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.AttesterSlashing.Value) {
p := &ethpb.AttesterSlashing{}
if err := testutil.ConvertToPb(testCase.AttesterSlashing.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.AttesterSlashing.Root) {
t.Errorf("Expected attester slashing bit %#x, received %#x", testCase.AttesterSlashing.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.BeaconBlock.Value) {
p := &ethpb.BeaconBlock{}
if err := testutil.ConvertToPb(testCase.BeaconBlock.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconBlock.Root) {
t.Errorf("Expected beacon block root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconBlock.SigningRoot) {
t.Errorf("Expected beacon block signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.BeaconBlockBody.Value) {
p := &ethpb.BeaconBlockBody{}
if err := testutil.ConvertToPb(testCase.BeaconBlockBody.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconBlockBody.Root) {
t.Errorf("Expected beacon block body %#x, received %#x", testCase.BeaconBlockBody.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.BeaconBlockHeader.Value) {
p := &ethpb.BeaconBlockHeader{}
if err := testutil.ConvertToPb(testCase.BeaconBlockHeader.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconBlockHeader.Root) {
t.Errorf("Expected beacon block header root %#x, received %#x", testCase.BeaconBlockHeader.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconBlockHeader.SigningRoot) {
t.Errorf("Expected beacon block header signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.BeaconState.Value) {
p := &pb.BeaconState{}
if err := testutil.ConvertToPb(testCase.BeaconState.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconState.Root) {
t.Errorf("Expected beacon state %#x, received %#x", testCase.BeaconState.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Crosslink.Value) {
c := &ethpb.Crosslink{}
if err := testutil.ConvertToPb(testCase.Crosslink.Value, c); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(c)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Crosslink.Root) {
t.Errorf("Expected crosslink %#x, received %#x", testCase.Crosslink.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Deposit.Value) {
p := &ethpb.Deposit{}
if err := testutil.ConvertToPb(testCase.Deposit.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Deposit.Root) {
t.Errorf("Expected deposit root %#x, received %#x", testCase.Deposit.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.DepositData.Value) {
p := &ethpb.Deposit_Data{}
if err := testutil.ConvertToPb(testCase.DepositData.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.DepositData.Root) {
t.Errorf("Expected deposit data root %#x, received %#x", testCase.DepositData.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.DepositData.SigningRoot) {
t.Errorf("Expected deposit data signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Eth1Data.Value) {
p := &ethpb.Eth1Data{}
if err := testutil.ConvertToPb(testCase.Eth1Data.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Eth1Data.Root) {
t.Errorf("Expected pb data %#x, received %#x", testCase.Eth1Data.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Fork.Value) {
p := &pb.Fork{}
if err := testutil.ConvertToPb(testCase.Fork.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Fork.Root) {
t.Errorf("Expected fork %#x, received %#x", testCase.Fork.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.HistoricalBatch.Value) {
p := &pb.HistoricalBatch{}
if err := testutil.ConvertToPb(testCase.HistoricalBatch.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.HistoricalBatch.Root) {
t.Errorf("Expected historical batch %#x, received %#x", testCase.HistoricalBatch.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.IndexedAttestation.Value) {
p := &ethpb.IndexedAttestation{}
if err := testutil.ConvertToPb(testCase.IndexedAttestation.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.IndexedAttestation.Root) {
t.Errorf("Expected indexed attestation root %#x, received %#x", testCase.IndexedAttestation.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.IndexedAttestation.SigningRoot) {
t.Errorf("Expected indexed attestation signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.PendingAttestation.Value) {
p := &pb.PendingAttestation{}
if err := testutil.ConvertToPb(testCase.PendingAttestation.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.PendingAttestation.Root) {
t.Errorf("Expected pending attestation %#x, received %#x", testCase.PendingAttestation.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.ProposerSlashing.Value) {
p := &ethpb.ProposerSlashing{}
if err := testutil.ConvertToPb(testCase.ProposerSlashing.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.ProposerSlashing.Root) {
t.Errorf("Expected proposer slashing %#x, received %#x", testCase.ProposerSlashing.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Transfer.Value) {
p := &ethpb.Transfer{}
if err := testutil.ConvertToPb(testCase.Transfer.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Transfer.Root) {
t.Errorf("Expected transfer root %#x, received %#x", testCase.Transfer.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Transfer.SigningRoot) {
t.Errorf("Expected transfer signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Validator.Value) {
p := &ethpb.Validator{}
if err := testutil.ConvertToPb(testCase.Validator.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Validator.Root) {
t.Errorf("Expected validator %#x, received %#x", testCase.Validator.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.VoluntaryExit.Value) {
p := &ethpb.VoluntaryExit{}
if err := testutil.ConvertToPb(testCase.VoluntaryExit.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.VoluntaryExit.Root) {
t.Errorf("Expected voluntary exit root %#x, received %#x", testCase.VoluntaryExit.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.VoluntaryExit.SigningRoot) {
t.Errorf("Expected voluntary exit signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
}
}

View File

@@ -1,356 +0,0 @@
package testing
import (
"bytes"
"io/ioutil"
"path"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/go-ssz"
sszspectest "github.com/prysmaticlabs/go-ssz/spectests"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestYamlStatic_Minimal(t *testing.T) {
t.Skip("This test suite requires --define ssz=minimal to be provided and there isn't a great way to do that without breaking //...")
topPath := "tests/ssz_static/core/"
yamlFileNames := []string{
"ssz_minimal_random.yaml",
}
for _, f := range yamlFileNames {
fullPath := path.Join(topPath, f)
filepath, err := bazel.Runfile(fullPath)
if err != nil {
t.Fatal(err)
}
file, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &sszspectest.SszMinimalTest{}
if err := yaml.Unmarshal(file, s); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
runTestCasesMinimal(t, s)
}
}
func runTestCasesMinimal(t *testing.T, s *sszspectest.SszMinimalTest) {
for _, testCase := range s.TestCases {
if !testutil.IsEmpty(testCase.Attestation.Value) {
p := &ethpb.Attestation{}
if err := testutil.ConvertToPb(testCase.Attestation.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Attestation.Root) {
t.Errorf("Expected attestation root %#x, received %#x", testCase.Attestation.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Attestation.SigningRoot) {
t.Errorf("Expected attestation signing root data %#x, received %#x", testCase.AttestationData.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.AttestationData.Value) {
p := &ethpb.AttestationData{}
if err := testutil.ConvertToPb(testCase.AttestationData.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.AttestationData.Root) {
t.Errorf("Expected attestation data %#x, received %#x", testCase.AttestationData.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.AttestationDataAndCustodyBit.Value) {
p := &pb.AttestationDataAndCustodyBit{}
if err := testutil.ConvertToPb(testCase.AttestationDataAndCustodyBit.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.AttestationDataAndCustodyBit.Root) {
t.Errorf("Expected attestation data and custody bit %#x, received %#x", testCase.AttestationDataAndCustodyBit.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.AttesterSlashing.Value) {
p := &ethpb.AttesterSlashing{}
if err := testutil.ConvertToPb(testCase.AttesterSlashing.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.AttesterSlashing.Root) {
t.Errorf("Expected attester slashing bit %#x, received %#x", testCase.AttesterSlashing.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.BeaconBlock.Value) {
p := &ethpb.BeaconBlock{}
if err := testutil.ConvertToPb(testCase.BeaconBlock.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconBlock.Root) {
t.Errorf("Expected beacon block root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconBlock.SigningRoot) {
t.Errorf("Expected beacon block signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.BeaconBlockBody.Value) {
p := &ethpb.BeaconBlockBody{}
if err := testutil.ConvertToPb(testCase.BeaconBlockBody.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconBlockBody.Root) {
t.Errorf("Expected beacon block body %#x, received %#x", testCase.BeaconBlockBody.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.BeaconBlockHeader.Value) {
p := &ethpb.BeaconBlockHeader{}
if err := testutil.ConvertToPb(testCase.BeaconBlockHeader.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconBlockHeader.Root) {
t.Errorf("Expected beacon block header root %#x, received %#x", testCase.BeaconBlockHeader.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconBlockHeader.SigningRoot) {
t.Errorf("Expected beacon block header signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.BeaconState.Value) {
p := &pb.BeaconState{}
if err := testutil.ConvertToPb(testCase.BeaconState.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.BeaconState.Root) {
t.Errorf("Expected beacon state %#x, received %#x", testCase.BeaconState.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Crosslink.Value) {
c := &ethpb.Crosslink{}
if err := testutil.ConvertToPb(testCase.Crosslink.Value, c); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(c)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Crosslink.Root) {
t.Errorf("Expected crosslink %#x, received %#x", testCase.Crosslink.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Deposit.Value) {
p := &ethpb.Deposit{}
if err := testutil.ConvertToPb(testCase.Deposit.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Deposit.Root) {
t.Errorf("Expected deposit root %#x, received %#x", testCase.Deposit.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.DepositData.Value) {
p := &ethpb.Deposit_Data{}
if err := testutil.ConvertToPb(testCase.DepositData.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.DepositData.Root) {
t.Errorf("Expected deposit data root %#x, received %#x", testCase.DepositData.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.DepositData.SigningRoot) {
t.Errorf("Expected deposit data signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Eth1Data.Value) {
p := &ethpb.Eth1Data{}
if err := testutil.ConvertToPb(testCase.Eth1Data.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Eth1Data.Root) {
t.Errorf("Expected pb data %#x, received %#x", testCase.Eth1Data.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Fork.Value) {
p := &pb.Fork{}
if err := testutil.ConvertToPb(testCase.Fork.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Fork.Root) {
t.Errorf("Expected fork %#x, received %#x", testCase.Fork.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.HistoricalBatch.Value) {
p := &pb.HistoricalBatch{}
if err := testutil.ConvertToPb(testCase.HistoricalBatch.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.HistoricalBatch.Root) {
t.Errorf("Expected historical batch %#x, received %#x", testCase.HistoricalBatch.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.IndexedAttestation.Value) {
p := &ethpb.IndexedAttestation{}
if err := testutil.ConvertToPb(testCase.IndexedAttestation.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.IndexedAttestation.Root) {
t.Errorf("Expected indexed attestation root %#x, received %#x", testCase.IndexedAttestation.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.IndexedAttestation.SigningRoot) {
t.Errorf("Expected indexed attestation signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.PendingAttestation.Value) {
p := &pb.PendingAttestation{}
if err := testutil.ConvertToPb(testCase.PendingAttestation.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.PendingAttestation.Root) {
t.Errorf("Expected pending attestation %#x, received %#x", testCase.PendingAttestation.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.ProposerSlashing.Value) {
p := &ethpb.ProposerSlashing{}
if err := testutil.ConvertToPb(testCase.ProposerSlashing.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.ProposerSlashing.Root) {
t.Errorf("Expected proposer slashing %#x, received %#x", testCase.ProposerSlashing.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Transfer.Value) {
p := &ethpb.Transfer{}
if err := testutil.ConvertToPb(testCase.Transfer.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Transfer.Root) {
t.Errorf("Expected transfer root %#x, received %#x", testCase.Transfer.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Transfer.SigningRoot) {
t.Errorf("Expected transfer signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.Validator.Value) {
p := &ethpb.Validator{}
if err := testutil.ConvertToPb(testCase.Validator.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.Validator.Root) {
t.Errorf("Expected validator %#x, received %#x", testCase.Validator.Root, root[:])
}
}
if !testutil.IsEmpty(testCase.VoluntaryExit.Value) {
p := &ethpb.VoluntaryExit{}
if err := testutil.ConvertToPb(testCase.VoluntaryExit.Value, p); err != nil {
t.Fatal(err)
}
root, err := ssz.HashTreeRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.VoluntaryExit.Root) {
t.Errorf("Expected voluntary exit root %#x, received %#x", testCase.VoluntaryExit.Root, root[:])
}
root, err = ssz.SigningRoot(p)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], testCase.VoluntaryExit.SigningRoot) {
t.Errorf("Expected voluntary exit signing root %#x, received %#x", testCase.BeaconBlock.Root, root[:])
}
}
}
}

View File

@@ -0,0 +1,9 @@
package testing
import (
"testing"
)
func TestSZZStatic_Mainnet(t *testing.T) {
runSSZStaticTests(t, "mainnet")
}

View File

@@ -0,0 +1,9 @@
package testing
import (
"testing"
)
func TestSSZStatic_Minimal(t *testing.T) {
runSSZStaticTests(t, "minimal")
}

View File

@@ -0,0 +1,144 @@
package testing
import (
"bytes"
"encoding/hex"
"errors"
"path"
"testing"
"github.com/prysmaticlabs/go-ssz"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
// SSZRoots --
type SSZRoots struct {
Root string `json:"root"`
SigningRoot string `json:"signing_root"`
}
func runSSZStaticTests(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
testFolders, _ := testutil.TestFolders(t, config, "ssz_static")
for _, folder := range testFolders {
innerPath := path.Join("ssz_static", folder.Name(), "ssz_random")
innerTestFolders, innerTestsFolderPath := testutil.TestFolders(t, config, innerPath)
for _, innerFolder := range innerTestFolders {
t.Run(path.Join(folder.Name(), innerFolder.Name()), func(t *testing.T) {
serializedBytes, err := testutil.BazelFileBytes(innerTestsFolderPath, innerFolder.Name(), "serialized.ssz")
if err != nil {
t.Fatal(err)
}
object, err := UnmarshalledSSZ(serializedBytes, folder.Name())
if err != nil {
t.Fatalf("Could not unmarshall serialized SSZ: %v", err)
}
rootsYamlFile, err := testutil.BazelFileBytes(innerTestsFolderPath, innerFolder.Name(), "roots.yaml")
if err != nil {
t.Fatal(err)
}
rootsYaml := &SSZRoots{}
if err := testutil.UnmarshalYaml(rootsYamlFile, rootsYaml); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
root, err := ssz.HashTreeRoot(object)
if err != nil {
t.Fatal(err)
}
rootBytes, err := hex.DecodeString(rootsYaml.Root[2:])
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(root[:], rootBytes) {
t.Fatalf(
"Did not receive expected hash tree root, received: %#x, expected: %#x",
root[:],
rootBytes,
)
}
if rootsYaml.SigningRoot == "" {
return
}
signingRoot, err := ssz.SigningRoot(object)
if err != nil {
t.Fatal(err)
}
signingRootBytes, err := hex.DecodeString(rootsYaml.SigningRoot[2:])
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(signingRoot[:], signingRootBytes) {
t.Fatalf(
"Did not receive expected signing root, received: %#x, expected: %#x",
signingRoot[:],
signingRootBytes,
)
}
})
}
}
}
func UnmarshalledSSZ(serializedBytes []byte, folderName string) (interface{}, error) {
var obj interface{}
switch folderName {
case "Attestation":
obj = &ethpb.Attestation{}
case "AttestationData":
obj = &ethpb.AttestationData{}
case "AttestationDataAndCustodyBit":
obj = &pb.AttestationDataAndCustodyBit{}
case "AttesterSlashing":
obj = &ethpb.AttesterSlashing{}
case "BeaconBlock":
obj = &ethpb.BeaconBlock{}
case "BeaconBlockBody":
obj = &ethpb.BeaconBlockBody{}
case "BeaconBlockHeader":
obj = &ethpb.BeaconBlockHeader{}
case "BeaconState":
obj = &pb.BeaconState{}
case "Checkpoint":
obj = &ethpb.Checkpoint{}
case "CompactCommittee":
obj = &pb.CompactCommittee{}
case "Crosslink":
obj = &ethpb.Crosslink{}
case "Deposit":
obj = &ethpb.Deposit{}
case "DepositData":
obj = &ethpb.Deposit_Data{}
case "Eth1Data":
obj = &ethpb.Eth1Data{}
case "Fork":
obj = &pb.Fork{}
case "HistoricalBatch":
obj = &pb.HistoricalBatch{}
case "IndexedAttestation":
obj = &ethpb.IndexedAttestation{}
case "PendingAttestation":
obj = &pb.PendingAttestation{}
case "ProposerSlashing":
obj = &ethpb.ProposerSlashing{}
case "Transfer":
obj = &ethpb.Transfer{}
case "Validator":
obj = &ethpb.Validator{}
case "VoluntaryExit":
obj = &ethpb.VoluntaryExit{}
default:
return nil, errors.New("type not found")
}
err := ssz.Unmarshal(serializedBytes, obj)
return obj, err
}

View File

@@ -74,7 +74,7 @@ func (s *SecretKey) PublicKey() *PublicKey {
// Sign a message using a secret key - in a beacon/validator client,
func (s *SecretKey) Sign(msg []byte, domain uint64) *Signature {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, domain)
binary.LittleEndian.PutUint64(b, domain)
sig := g1.SignWithDomain(bytesutil.ToBytes32(msg), s.val, bytesutil.ToBytes8(b))
return &Signature{val: sig}
}
@@ -101,7 +101,7 @@ func (p *PublicKey) Aggregate(p2 *PublicKey) *PublicKey {
// Verify a bls signature given a public key, a message, and a domain.
func (s *Signature) Verify(msg []byte, pub *PublicKey, domain uint64) bool {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, domain)
binary.LittleEndian.PutUint64(b, domain)
return g1.VerifyWithDomain(bytesutil.ToBytes32(msg), pub.val, s.val, bytesutil.ToBytes8(b))
}
@@ -117,7 +117,7 @@ func (s *Signature) VerifyAggregate(pubKeys []*PublicKey, msg [][32]byte, domain
keys = append(keys, v.val)
}
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, domain)
binary.LittleEndian.PutUint64(b, domain)
return s.val.VerifyAggregateWithDomain(keys, msg, bytesutil.ToBytes8(b))
}
@@ -133,7 +133,7 @@ func (s *Signature) VerifyAggregateCommon(pubKeys []*PublicKey, msg []byte, doma
keys = append(keys, v.val)
}
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, domain)
binary.LittleEndian.PutUint64(b, domain)
return s.val.VerifyAggregateCommonWithDomain(keys, bytesutil.ToBytes32(msg), bytesutil.ToBytes8(b))
}

View File

@@ -6,10 +6,10 @@ go_library(
srcs = [
"aggregate_pubkeys_test.yaml.go",
"aggregate_sigs_test.yaml.go",
"g2_compressed_test.yaml.go",
"g2_uncompressed_test.yaml.go",
"msg_hash_compressed_test.yaml.go",
"msg_hash_uncompressed_test.yaml.go",
"priv_to_pub_test.yaml.go",
"sign_message_test.yaml.go",
"sign_msg_test.yaml.go",
],
importpath = "github.com/prysmaticlabs/prysm/shared/bls/spectest",
visibility = ["//visibility:public"],
@@ -21,20 +21,21 @@ go_test(
srcs = [
"aggregate_pubkeys_test.go",
"aggregate_sigs_test.go",
"g2_compressed_test.go",
"g2_uncompressed_test.go",
"helper_test.go",
"msg_hash_compressed_test.go",
"msg_hash_uncompressed_test.go",
"priv_to_pub_test.go",
"sign_message_test.go",
"sign_msg_test.go",
],
data = [
"@eth2_spec_tests_general//:test_data",
],
data = ["@eth2_spec_tests//:test_data"],
embed = [":go_default_library"],
tags = ["spectest"],
deps = [
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_ghodss_yaml//:go_default_library",
"@com_github_phoreproject_bls//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],
)

View File

@@ -2,15 +2,17 @@ package spectest
import (
"bytes"
"fmt"
"encoding/hex"
"testing"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/prysm/shared/bls"
)
func TestAggregatePubkeysYaml(t *testing.T) {
file, err := loadBlsYaml("aggregate_pubkeys/aggregate_pubkeys.yaml")
file, err := testutil.BazelFileBytes("tests/general/phase0/bls/aggregate_pubkeys/small/agg_pub_keys/data.yaml")
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
@@ -20,24 +22,32 @@ func TestAggregatePubkeysYaml(t *testing.T) {
t.Fatalf("Failed to unmarshal: %v", err)
}
for i, tt := range test.TestCases {
t.Run(fmt.Sprintf("Test %d", i), func(t *testing.T) {
pk, err := bls.PublicKeyFromBytes(tt.Input[0])
if err != nil {
t.Fatal(err)
}
for _, pk2 := range tt.Input[1:] {
p, err := bls.PublicKeyFromBytes(pk2)
if err != nil {
t.Fatal(err)
}
pk.Aggregate(p)
}
pubBytes, err := hex.DecodeString(test.Input[0][2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
pk, err := bls.PublicKeyFromBytes(pubBytes)
if err != nil {
t.Fatal(err)
}
for _, pk2 := range test.Input[1:] {
pubBytes2, err := hex.DecodeString(pk2[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
p, err := bls.PublicKeyFromBytes(pubBytes2)
if err != nil {
t.Fatal(err)
}
pk.Aggregate(p)
}
if !bytes.Equal(tt.Output, pk.Marshal()) {
t.Fatal("Output does not equal marshaled aggregated public " +
"key bytes")
}
})
outputBytes, err := hex.DecodeString(test.Output[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
if !bytes.Equal(outputBytes, pk.Marshal()) {
t.Fatal("Output does not equal marshaled aggregated public " +
"key bytes")
}
}

View File

@@ -4,15 +4,6 @@
package spectest
type AggregatePubkeysTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Input [][]byte `json:"input"`
Output []byte `json:"output" ssz:"size=48"`
} `json:"test_cases"`
Input []string `json:"input"`
Output string `json:"output" ssz:"size=48"`
}

View File

@@ -2,37 +2,49 @@ package spectest
import (
"bytes"
"fmt"
"encoding/hex"
"path"
"testing"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestAggregateSignaturesYaml(t *testing.T) {
file, err := loadBlsYaml("aggregate_sigs/aggregate_sigs.yaml")
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
testFolders, testFolderPath := testutil.TestFolders(t, "general", "bls/aggregate_sigs/small")
test := &AggregateSigsTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
file, err := testutil.BazelFileBytes(path.Join(testFolderPath, folder.Name(), "data.yaml"))
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &AggregateSigsTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
for i, tt := range test.TestCases {
t.Run(fmt.Sprintf("Test %d", i), func(t *testing.T) {
var sigs []*bls.Signature
for _, s := range tt.Input {
sig, err := bls.SignatureFromBytes(s)
for _, s := range test.Input {
sigBytes, err := hex.DecodeString(s[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
sig, err := bls.SignatureFromBytes(sigBytes)
if err != nil {
t.Fatalf("Unable to unmarshal signature from bytes: %v", err)
}
sigs = append(sigs, sig)
}
sig := bls.AggregateSignatures(sigs)
if !bytes.Equal(tt.Output, sig.Marshal()) {
outputBytes, err := hex.DecodeString(test.Output[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
if !bytes.Equal(outputBytes, sig.Marshal()) {
t.Fatal("Output does not equal marshaled aggregated sig bytes")
}
})

View File

@@ -4,15 +4,6 @@
package spectest
type AggregateSigsTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Input [][]byte `json:"input"`
Output []byte `json:"output" ssz:"size=96"`
} `json:"test_cases"`
Input []string `json:"input"`
Output string `json:"output" ssz:"size=96"`
}

View File

@@ -1,50 +0,0 @@
package spectest
import (
"bytes"
"encoding/binary"
"fmt"
"testing"
"github.com/ghodss/yaml"
"github.com/phoreproject/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
)
// Note: This actually tests the underlying library as we don't have a need for
// HashG2Compressed in our local BLS API.
func TestG2CompressedHash(t *testing.T) {
file, err := loadBlsYaml("msg_hash_g2_compressed/g2_compressed.yaml")
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &G2CompressedTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
for i, tt := range test.TestCases {
t.Run(fmt.Sprintf("Test %d", i), func(t *testing.T) {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, tt.Input.Domain)
projective := bls.HashG2WithDomain(
bytesutil.ToBytes32(tt.Input.Message),
bytesutil.ToBytes8(b),
)
hash := bls.CompressG2(projective.ToAffine())
var buf []byte
for _, slice := range tt.Output {
buf = append(buf, slice...)
}
if !bytes.Equal(buf, hash[:]) {
t.Logf("Domain=%d", tt.Input.Domain)
t.Fatalf("Hash does not match the expected output. "+
"Expected %#x but received %#x", buf, hash)
}
t.Logf("Success. Domain=%d", tt.Input.Domain)
})
}
}

View File

@@ -1,21 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: g2_compressed.yaml
package spectest
type G2CompressedTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Input struct {
Message []byte `json:"message" ssz:"size=32"`
Domain uint64 `json:"domain"`
} `json:"input"`
Output [][]byte `json:"output"`
} `json:"test_cases"`
}

View File

@@ -1,53 +0,0 @@
package spectest
import (
"bytes"
"encoding/binary"
"fmt"
"testing"
"github.com/ghodss/yaml"
"github.com/phoreproject/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
)
// Note: This actually tests the underlying library as we don't have a need for
// HashG2Uncompressed in our local BLS API.
func TestG2UncompressedHash(t *testing.T) {
t.Skip("The python uncompressed method does not match the go uncompressed method and this isn't very important")
file, err := loadBlsYaml("msg_hash_g2_uncompressed/g2_uncompressed.yaml")
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &G2UncompressedTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
for i, tt := range test.TestCases {
t.Run(fmt.Sprintf("Test %d", i), func(t *testing.T) {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, tt.Input.Domain)
projective := bls.HashG2WithDomain(
bytesutil.ToBytes32(tt.Input.Message),
bytesutil.ToBytes8(b),
)
hash := projective.ToAffine().SerializeBytes()
var buf []byte
for _, slice := range tt.Output {
for _, innerSlice := range slice {
buf = append(buf, innerSlice...)
}
}
if !bytes.Equal(buf, hash[:]) {
t.Logf("Domain=%d", tt.Input.Domain)
t.Fatalf("Hash does not match the expected output. "+
"Expected %#x but received %#x", buf, hash)
}
t.Logf("Success. Domain=%d", tt.Input.Domain)
})
}
}

View File

@@ -1,21 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: g2_uncompressed.yaml
package spectest
type G2UncompressedTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Input struct {
Message []byte `json:"message" ssz:"size=32"`
Domain uint64 `json:"domain"`
} `json:"input"`
Output [][][]byte `json:"output"`
} `json:"test_cases"`
}

View File

@@ -1,21 +0,0 @@
package spectest
import (
"io/ioutil"
"github.com/bazelbuild/rules_go/go/tools/bazel"
)
const prefix = "tests/bls/"
// Load BLS yaml from spec test bls directory. The file parameter should be in
// the format of the path starting at the bls directory.
// Example: aggregate_pubkeys/aggregate_pubkeys.yaml where the full path would
// be tests/bls/aggregate_pubkeys/aggregate_pubkeys.yaml.
func loadBlsYaml(file string) ([]byte, error) {
filepath, err := bazel.Runfile(prefix + file)
if err != nil {
return []byte{}, err
}
return ioutil.ReadFile(filepath)
}

View File

@@ -0,0 +1,61 @@
package spectest
import (
"bytes"
"encoding/hex"
"path"
"testing"
"github.com/ghodss/yaml"
"github.com/phoreproject/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
// Note: This actually tests the underlying library as we don't have a need for
// HashG2Compressed in our local BLS API.
func TestMsgHashCompressed(t *testing.T) {
testFolders, testFolderPath := testutil.TestFolders(t, "general", "bls/msg_hash_compressed/small")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
file, err := testutil.BazelFileBytes(path.Join(testFolderPath, folder.Name(), "data.yaml"))
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &MsgHashCompressedTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
msgBytes, err := hex.DecodeString(test.Input.Message[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
domain, err := hex.DecodeString(test.Input.Domain[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
projective := bls.HashG2WithDomain(
bytesutil.ToBytes32(msgBytes),
bytesutil.ToBytes8(domain),
)
hash := bls.CompressG2(projective.ToAffine())
var buf []byte
for _, innerString := range test.Output {
slice, err := hex.DecodeString(innerString[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
buf = append(buf, slice...)
}
if !bytes.Equal(buf, hash[:]) {
t.Logf("Domain=%d", domain)
t.Fatalf("Hash does not match the expected output. "+
"Expected %#x but received %#x", buf, hash)
}
t.Logf("Success. Domain=%d", domain)
})
}
}

View File

@@ -0,0 +1,12 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: g2_compressed.yaml
package spectest
type MsgHashCompressedTest struct {
Input struct {
Message string `json:"message"`
Domain string `json:"domain"`
} `json:"input"`
Output []string `json:"output"`
}

View File

@@ -0,0 +1,65 @@
package spectest
import (
"bytes"
"encoding/hex"
"path"
"testing"
"github.com/ghodss/yaml"
"github.com/phoreproject/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
// Note: This actually tests the underlying library as we don't have a need for
// HashG2Uncompressed in our local BLS API.
func TestMsgHashUncompressed(t *testing.T) {
t.Skip("The python uncompressed method does not match the go uncompressed method and this isn't very important")
testFolders, testFolderPath := testutil.TestFolders(t, "general", "bls/msg_hash_uncompressed/small")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
file, err := testutil.BazelFileBytes(path.Join(testFolderPath, folder.Name(), "data.yaml"))
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &MsgHashUncompressedTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
domain, err := hex.DecodeString(test.Input.Domain[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
msgBytes, err := hex.DecodeString(test.Input.Message[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
projective := bls.HashG2WithDomain(
bytesutil.ToBytes32(msgBytes),
bytesutil.ToBytes8(domain),
)
hash := projective.ToAffine().SerializeBytes()
var buf []byte
for _, outputStrings := range test.Output {
for _, innerString := range outputStrings {
slice, err := hex.DecodeString(innerString[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
buf = append(buf, slice...)
}
}
if !bytes.Equal(buf, hash[:]) {
t.Logf("Domain=%d", domain)
t.Logf("Message=%#x", msgBytes)
t.Fatalf("Hash does not match the expected output. "+
"Expected %#x but received %#x", buf, hash)
}
t.Logf("Success. Domain=%d", domain)
})
}
}

View File

@@ -0,0 +1,12 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: g2_uncompressed.yaml
package spectest
type MsgHashUncompressedTest struct {
Input struct {
Message string `json:"message"`
Domain string `json:"domain"`
} `json:"input"`
Output [][]string `json:"output"`
}

View File

@@ -2,31 +2,43 @@ package spectest
import (
"bytes"
"fmt"
"encoding/hex"
"path"
"testing"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestPrivToPubYaml(t *testing.T) {
file, err := loadBlsYaml("priv_to_pub/priv_to_pub.yaml")
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
testFolders, testFolderPath := testutil.TestFolders(t, "general", "bls/priv_to_pub/small")
test := &PrivToPubTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
file, err := testutil.BazelFileBytes(path.Join(testFolderPath, folder.Name(), "data.yaml"))
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &PrivToPubTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
for i, tt := range test.TestCases {
t.Run(fmt.Sprintf("Test %d", i), func(t *testing.T) {
sk, err := bls.SecretKeyFromBytes(tt.Input)
pkBytes, err := hex.DecodeString(test.Input[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
sk, err := bls.SecretKeyFromBytes(pkBytes)
if err != nil {
t.Fatalf("Cannot unmarshal input to secret key: %v", err)
}
if !bytes.Equal(tt.Output, sk.PublicKey().Marshal()) {
outputBytes, err := hex.DecodeString(test.Output[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
if !bytes.Equal(outputBytes, sk.PublicKey().Marshal()) {
t.Fatal("Output does not marshaled public key bytes")
}
})

View File

@@ -4,15 +4,6 @@
package spectest
type PrivToPubTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Input []byte `json:"input" ssz:"size=32"`
Output []byte `json:"output" ssz:"size=48"`
} `json:"test_cases"`
Input string `json:"input"`
Output string `json:"output"`
}

View File

@@ -1,39 +0,0 @@
package spectest
import (
"bytes"
"fmt"
"testing"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/prysm/shared/bls"
)
func TestSignMessageYaml(t *testing.T) {
file, err := loadBlsYaml("sign_msg/sign_msg.yaml")
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &SignMessageTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
for i, tt := range test.TestCases {
t.Run(fmt.Sprintf("Test %d", i), func(t *testing.T) {
sk, err := bls.SecretKeyFromBytes(tt.Input.Privkey)
if err != nil {
t.Fatalf("Cannot unmarshal input to secret key: %v", err)
}
sig := sk.Sign(tt.Input.Message, tt.Input.Domain)
if !bytes.Equal(tt.Output, sig.Marshal()) {
t.Logf("Domain=%d", tt.Input.Domain)
t.Fatalf("Signature does not match the expected output. "+
"Expected %#x but received %#x", tt.Output, sig.Marshal())
}
t.Logf("Success. Domain=%d", tt.Input.Domain)
})
}
}

View File

@@ -1,22 +0,0 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: sign_msg.yaml
package spectest
type SignMessageTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Input struct {
Privkey []byte `json:"privkey" ssz:"size=32"`
Message []byte `json:"message" ssz:"size=32"`
Domain uint64 `json:"domain"`
} `json:"input"`
Output []byte `json:"output" ssz:"size=96"`
} `json:"test_cases"`
}

View File

@@ -0,0 +1,61 @@
package spectest
import (
"bytes"
"encoding/binary"
"encoding/hex"
"path"
"testing"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestSignMessageYaml(t *testing.T) {
testFolders, testFolderPath := testutil.TestFolders(t, "general", "bls/sign_msg/small")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
file, err := testutil.BazelFileBytes(path.Join(testFolderPath, folder.Name(), "data.yaml"))
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &SignMsgTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
pkBytes, err := hex.DecodeString(test.Input.Privkey[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
sk, err := bls.SecretKeyFromBytes(pkBytes)
if err != nil {
t.Fatalf("Cannot unmarshal input to secret key: %v", err)
}
msgBytes, err := hex.DecodeString(test.Input.Message[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
domain, err := hex.DecodeString(test.Input.Domain[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
num := binary.LittleEndian.Uint64(domain)
sig := sk.Sign(msgBytes, num)
outputBytes, err := hex.DecodeString(test.Output[2:])
if err != nil {
t.Fatalf("Cannot decode string to bytes: %v", err)
}
if !bytes.Equal(outputBytes, sig.Marshal()) {
t.Logf("Domain=%d", domain)
t.Fatalf("Signature does not match the expected output. "+
"Expected %#x but received %#x", outputBytes, sig.Marshal())
}
t.Logf("Success. Domain=%d", domain)
})
}
}

View File

@@ -0,0 +1,13 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: sign_msg.yaml
package spectest
type SignMsgTest struct {
Input struct {
Privkey string `json:"privkey"`
Message string `json:"message"`
Domain string `json:"domain"`
} `json:"input"`
Output string `json:"output"`
}

View File

@@ -241,55 +241,70 @@ func DemoBeaconConfig() *BeaconChainConfig {
// MinimalSpecConfig retrieves the minimal config used in spec tests.
func MinimalSpecConfig() *BeaconChainConfig {
minimalConfig := *defaultBeaconConfig
// Misc
minimalConfig.ShardCount = 8
minimalConfig.TargetCommitteeSize = 4
minimalConfig.MaxValidatorsPerCommittee = 4096
minimalConfig.MinPerEpochChurnLimit = 4
minimalConfig.ChurnLimitQuotient = 65536
minimalConfig.BaseRewardsPerEpoch = 5
minimalConfig.ShuffleRoundCount = 10
minimalConfig.MinGenesisActiveValidatorCount = 64
minimalConfig.DepositContractTreeDepth = 32
minimalConfig.MinGenesisTime = 1578009600
// Gwei values
minimalConfig.MinDepositAmount = 1e9
minimalConfig.MaxEffectiveBalance = 32e9
minimalConfig.EjectionBalance = 16e9
minimalConfig.EffectiveBalanceIncrement = 1e9
minimalConfig.FarFutureEpoch = 1<<64 - 1
// Initial values
minimalConfig.BLSWithdrawalPrefixByte = byte(0)
// Time parameters
minimalConfig.SecondsPerSlot = 6
minimalConfig.MinAttestationInclusionDelay = 1
minimalConfig.SlotsPerEpoch = 8
minimalConfig.MinSeedLookahead = 1
minimalConfig.ActivationExitDelay = 4
minimalConfig.SlotsPerEth1VotingPeriod = 16
minimalConfig.HistoricalRootsLimit = 64
minimalConfig.SlotsPerHistoricalRoot = 64
minimalConfig.MinValidatorWithdrawabilityDelay = 256
minimalConfig.PersistentCommitteePeriod = 2048
minimalConfig.MaxEpochsPerCrosslink = 4
minimalConfig.MinEpochsToInactivityPenalty = 4
// State vector lengths
minimalConfig.EpochsPerHistoricalVector = 64
minimalConfig.EpochsPerSlashingsVector = 64
minimalConfig.HistoricalRootsLimit = 16777216
minimalConfig.ValidatorRegistryLimit = 1099511627776
// Reward and penalty quotients
minimalConfig.BaseRewardFactor = 64
minimalConfig.WhistleBlowerRewardQuotient = 512
minimalConfig.ProposerRewardQuotient = 8
minimalConfig.InactivityPenaltyQuotient = 33554432
minimalConfig.MinSlashingPenaltyQuotient = 32
minimalConfig.BaseRewardsPerEpoch = 5
// Max operations per block
minimalConfig.MaxProposerSlashings = 16
minimalConfig.MaxAttesterSlashings = 1
minimalConfig.MaxAttestations = 128
minimalConfig.MaxDeposits = 16
minimalConfig.MaxVoluntaryExits = 16
minimalConfig.MaxTransfers = 0
// Signature domains
minimalConfig.DomainBeaconProposer = bytesutil.Bytes4(0)
minimalConfig.DomainRandao = bytesutil.Bytes4(1)
minimalConfig.DomainAttestation = bytesutil.Bytes4(2)
minimalConfig.DomainDeposit = bytesutil.Bytes4(3)
minimalConfig.DomainVoluntaryExit = bytesutil.Bytes4(4)
minimalConfig.DomainTransfer = bytesutil.Bytes4(5)
minimalConfig.MinGenesisTime = 1578009600
minimalConfig.DepositContractTreeDepth = 32
minimalConfig.FarFutureEpoch = 1<<64 - 1
return &minimalConfig
}

View File

@@ -10,6 +10,7 @@ go_library(
"json_to_pb_converter.go",
"log.go",
"random_bytes.go",
"spectest.go",
"tempdir.go",
"wait_timeout.go",
],
@@ -28,6 +29,8 @@ go_library(
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],
)

171
shared/testutil/spectest.go Normal file
View File

@@ -0,0 +1,171 @@
package testutil
import (
"io/ioutil"
"os"
"path"
"strings"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"gopkg.in/d4l3k/messagediff.v1"
)
type blockOperation func(*pb.BeaconState, *ethpb.BeaconBlockBody) (*pb.BeaconState, error)
type epochOperation func(*testing.T, *pb.BeaconState) (*pb.BeaconState, error)
// TestFolders sets the proper config and returns the result of ReadDir
// on the passed in eth2-spec-tests directory along with its path.
func TestFolders(t *testing.T, config string, folderPath string) ([]os.FileInfo, string) {
if config == "minimal" {
t.Skip("This test suite requires --define ssz=minimal to be provided and there isn't a great way to do that without breaking //... See https://github.com/prysmaticlabs/prysm/issues/3066")
}
testsFolderPath := path.Join("tests", config, "phase0", folderPath)
filepath, err := bazel.Runfile(testsFolderPath)
if err != nil {
t.Fatal(err)
}
testFolders, err := ioutil.ReadDir(filepath)
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
return testFolders, testsFolderPath
}
// BazelFileBytes returns the byte array of the bazel file path given.
func BazelFileBytes(filePaths ...string) ([]byte, error) {
filepath, err := bazel.Runfile(path.Join(filePaths...))
if err != nil {
return nil, err
}
fileBytes, err := ioutil.ReadFile(filepath)
if err != nil {
return nil, err
}
return fileBytes, nil
}
// RunBlockOperationTest takes in the prestate and the beacon block body, processes it through the
// passed in block operation function and checks the post state with the expected post state.
func RunBlockOperationTest(
t *testing.T,
folderPath string,
body *ethpb.BeaconBlockBody,
operationFn blockOperation,
) {
helpers.ClearAllCaches()
preBeaconStateFile, err := BazelFileBytes(path.Join(folderPath, "pre.ssz"))
if err != nil {
t.Fatal(err)
}
preState := &pb.BeaconState{}
if err := ssz.Unmarshal(preBeaconStateFile, preState); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
// If the post.ssz is not present, it means the test should fail on our end.
postSSZFilepath, err := bazel.Runfile(path.Join(folderPath, "post.ssz"))
postSSZExists := true
if err != nil && strings.Contains(err.Error(), "could not locate file") {
postSSZExists = false
} else if err != nil {
t.Fatal(err)
}
beaconState, err := operationFn(preState, body)
if postSSZExists {
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
postBeaconStateFile, err := ioutil.ReadFile(postSSZFilepath)
if err != nil {
t.Fatal(err)
}
postBeaconState := &pb.BeaconState{}
if err := ssz.Unmarshal(postBeaconStateFile, postBeaconState); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
if !proto.Equal(beaconState, postBeaconState) {
diff, _ := messagediff.PrettyDiff(beaconState, postBeaconState)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
} else {
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if err == nil {
t.Fatal("Did not fail when expected")
}
t.Logf("Expected failure; failure reason = %v", err)
return
}
}
// RunEpochOperationTest takes in the prestate and processes it through the
// passed in epoch operation function and checks the post state with the expected post state.
func RunEpochOperationTest(
t *testing.T,
testFolderPath string,
operationFn epochOperation,
) {
helpers.ClearAllCaches()
preBeaconStateFile, err := BazelFileBytes(path.Join(testFolderPath, "pre.ssz"))
if err != nil {
t.Fatal(err)
}
preBeaconState := &pb.BeaconState{}
if err := ssz.Unmarshal(preBeaconStateFile, preBeaconState); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
// If the post.ssz is not present, it means the test should fail on our end.
postSSZFilepath, err := bazel.Runfile(path.Join(testFolderPath, "post.ssz"))
postSSZExists := true
if err != nil && strings.Contains(err.Error(), "could not locate file") {
postSSZExists = false
} else if err != nil {
t.Fatal(err)
}
beaconState, err := operationFn(t, preBeaconState)
if postSSZExists {
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
postBeaconStateFile, err := ioutil.ReadFile(postSSZFilepath)
if err != nil {
t.Fatal(err)
}
postBeaconState := &pb.BeaconState{}
if err := ssz.Unmarshal(postBeaconStateFile, postBeaconState); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
if !proto.Equal(beaconState, postBeaconState) {
diff, _ := messagediff.PrettyDiff(beaconState, postBeaconState)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
} else {
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if err == nil {
t.Fatal("Did not fail when expected")
}
t.Logf("Expected failure; failure reason = %v", err)
return
}
}

Some files were not shown because too many files have changed in this diff Show More