mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-01 15:57:39 +00:00
365 lines
10 KiB
Go
365 lines
10 KiB
Go
package attestation
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
|
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func init() {
|
|
logrus.SetLevel(logrus.DebugLevel)
|
|
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
|
EnableCommitteesCache: false,
|
|
})
|
|
}
|
|
|
|
func TestUpdateLatestAttestation_UpdatesLatest(t *testing.T) {
|
|
beaconDB := internal.SetupDB(t)
|
|
defer internal.TeardownDB(t, beaconDB)
|
|
ctx := context.Background()
|
|
|
|
var validators []*pb.Validator
|
|
for i := 0; i < 64; i++ {
|
|
validators = append(validators, &pb.Validator{
|
|
Pubkey: []byte{byte(i)},
|
|
ActivationEpoch: 0,
|
|
ExitEpoch: 10,
|
|
})
|
|
}
|
|
|
|
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
|
ValidatorRegistry: validators,
|
|
}); err != nil {
|
|
t.Fatalf("could not save state: %v", err)
|
|
}
|
|
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
|
|
|
attestation := &pb.Attestation{
|
|
AggregationBitfield: []byte{0x80},
|
|
Data: &pb.AttestationData{
|
|
Slot: 1,
|
|
Shard: 1,
|
|
},
|
|
}
|
|
|
|
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
|
|
t.Fatalf("could not update latest attestation: %v", err)
|
|
}
|
|
pubkey := bytesutil.ToBytes48([]byte{byte(35)})
|
|
if service.store.m[pubkey].Data.Slot !=
|
|
attestation.Data.Slot {
|
|
t.Errorf("Incorrect slot stored, wanted: %d, got: %d",
|
|
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
|
|
}
|
|
|
|
attestation.Data.Slot = 36
|
|
attestation.Data.Shard = 36
|
|
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
|
|
t.Fatalf("could not update latest attestation: %v", err)
|
|
}
|
|
if service.store.m[pubkey].Data.Slot !=
|
|
attestation.Data.Slot {
|
|
t.Errorf("Incorrect slot stored, wanted: %d, got: %d",
|
|
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
|
|
}
|
|
}
|
|
|
|
func TestAttestationPool_UpdatesAttestationPool(t *testing.T) {
|
|
beaconDB := internal.SetupDB(t)
|
|
defer internal.TeardownDB(t, beaconDB)
|
|
ctx := context.Background()
|
|
|
|
var validators []*pb.Validator
|
|
for i := 0; i < 64; i++ {
|
|
validators = append(validators, &pb.Validator{
|
|
Pubkey: []byte{byte(i)},
|
|
ActivationEpoch: 0,
|
|
ExitEpoch: 10,
|
|
})
|
|
}
|
|
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
|
ValidatorRegistry: validators,
|
|
}); err != nil {
|
|
t.Fatalf("could not save state: %v", err)
|
|
}
|
|
|
|
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
|
attestation := &pb.Attestation{
|
|
AggregationBitfield: []byte{0x80},
|
|
Data: &pb.AttestationData{
|
|
Slot: 1,
|
|
Shard: 1,
|
|
},
|
|
}
|
|
|
|
if err := service.handleAttestation(context.Background(), attestation); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestLatestAttestation_ReturnsLatestAttestation(t *testing.T) {
|
|
beaconDB := internal.SetupDB(t)
|
|
defer internal.TeardownDB(t, beaconDB)
|
|
ctx := context.Background()
|
|
|
|
pubKey := []byte{'A'}
|
|
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
|
ValidatorRegistry: []*pb.Validator{{Pubkey: pubKey}},
|
|
}); err != nil {
|
|
t.Fatalf("could not save state: %v", err)
|
|
}
|
|
|
|
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
|
pubKey48 := bytesutil.ToBytes48(pubKey)
|
|
attestation := &pb.Attestation{AggregationBitfield: []byte{'B'}}
|
|
service.store.m[pubKey48] = attestation
|
|
|
|
latestAttestation, err := service.LatestAttestation(ctx, 0)
|
|
if err != nil {
|
|
t.Fatalf("Could not get latest attestation: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(attestation, latestAttestation) {
|
|
t.Errorf("Wanted: %v, got: %v", attestation, latestAttestation)
|
|
}
|
|
}
|
|
|
|
func TestLatestAttestation_InvalidIndex(t *testing.T) {
|
|
beaconDB := internal.SetupDB(t)
|
|
defer internal.TeardownDB(t, beaconDB)
|
|
ctx := context.Background()
|
|
|
|
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
|
ValidatorRegistry: []*pb.Validator{},
|
|
}); err != nil {
|
|
t.Fatalf("could not save state: %v", err)
|
|
}
|
|
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
|
|
|
index := uint64(0)
|
|
want := fmt.Sprintf("invalid validator index %d", index)
|
|
if _, err := service.LatestAttestation(ctx, index); !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Wanted error to contain %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestLatestAttestation_NoAttestation(t *testing.T) {
|
|
beaconDB := internal.SetupDB(t)
|
|
defer internal.TeardownDB(t, beaconDB)
|
|
ctx := context.Background()
|
|
|
|
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
|
ValidatorRegistry: []*pb.Validator{{}},
|
|
}); err != nil {
|
|
t.Fatalf("could not save state: %v", err)
|
|
}
|
|
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
|
|
|
index := 0
|
|
a, err := service.LatestAttestation(ctx, uint64(index))
|
|
if err != nil {
|
|
t.Fatalf("could not run latest attestation: %v", err)
|
|
}
|
|
if a != nil {
|
|
t.Errorf("Wanted attesstation %v, received %v", nil, a)
|
|
}
|
|
}
|
|
|
|
func TestLatestAttestationTarget_CantGetAttestation(t *testing.T) {
|
|
beaconDB := internal.SetupDB(t)
|
|
defer internal.TeardownDB(t, beaconDB)
|
|
ctx := context.Background()
|
|
|
|
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
|
ValidatorRegistry: []*pb.Validator{{}},
|
|
}); err != nil {
|
|
t.Fatalf("could not save state: %v", err)
|
|
}
|
|
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
|
|
|
index := uint64(100)
|
|
want := fmt.Sprintf("could not get attestation: invalid validator index %d", index)
|
|
if _, err := service.LatestAttestationTarget(ctx, index); !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Wanted error to contain %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestLatestAttestationTarget_ReturnsLatestAttestedBlock(t *testing.T) {
|
|
beaconDB := internal.SetupDB(t)
|
|
defer internal.TeardownDB(t, beaconDB)
|
|
ctx := context.Background()
|
|
|
|
pubKey := []byte{'A'}
|
|
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
|
ValidatorRegistry: []*pb.Validator{{Pubkey: pubKey}},
|
|
}); err != nil {
|
|
t.Fatalf("could not save state: %v", err)
|
|
}
|
|
|
|
block := &pb.BeaconBlock{Slot: 999}
|
|
if err := beaconDB.SaveBlock(block); err != nil {
|
|
t.Fatalf("could not save block: %v", err)
|
|
}
|
|
blockRoot, err := hashutil.HashBeaconBlock(block)
|
|
if err != nil {
|
|
log.Fatalf("could not hash block: %v", err)
|
|
}
|
|
|
|
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
|
|
|
attestation := &pb.Attestation{
|
|
Data: &pb.AttestationData{
|
|
BeaconBlockRootHash32: blockRoot[:],
|
|
}}
|
|
pubKey48 := bytesutil.ToBytes48(pubKey)
|
|
service.store.m[pubKey48] = attestation
|
|
|
|
latestAttestedBlock, err := service.LatestAttestationTarget(ctx, 0)
|
|
if err != nil {
|
|
t.Fatalf("Could not get latest attestation: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(block, latestAttestedBlock) {
|
|
t.Errorf("Wanted: %v, got: %v", block, latestAttestedBlock)
|
|
}
|
|
}
|
|
|
|
func TestUpdateLatestAttestation_CacheEnabledAndMiss(t *testing.T) {
|
|
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
|
EnableCommitteesCache: true,
|
|
})
|
|
|
|
beaconDB := internal.SetupDB(t)
|
|
defer internal.TeardownDB(t, beaconDB)
|
|
ctx := context.Background()
|
|
|
|
var validators []*pb.Validator
|
|
for i := 0; i < 64; i++ {
|
|
validators = append(validators, &pb.Validator{
|
|
Pubkey: []byte{byte(i)},
|
|
ActivationEpoch: 0,
|
|
ExitEpoch: 10,
|
|
})
|
|
}
|
|
|
|
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
|
ValidatorRegistry: validators,
|
|
}); err != nil {
|
|
t.Fatalf("could not save state: %v", err)
|
|
}
|
|
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
|
|
|
attestation := &pb.Attestation{
|
|
AggregationBitfield: []byte{0x80},
|
|
Data: &pb.AttestationData{
|
|
Slot: 1,
|
|
Shard: 1,
|
|
},
|
|
}
|
|
|
|
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
|
|
t.Fatalf("could not update latest attestation: %v", err)
|
|
}
|
|
pubkey := bytesutil.ToBytes48([]byte{byte(35)})
|
|
if service.store.m[pubkey].Data.Slot !=
|
|
attestation.Data.Slot {
|
|
t.Errorf("Incorrect slot stored, wanted: %d, got: %d",
|
|
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
|
|
}
|
|
|
|
attestation.Data.Slot = 36
|
|
attestation.Data.Shard = 36
|
|
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
|
|
t.Fatalf("could not update latest attestation: %v", err)
|
|
}
|
|
if service.store.m[pubkey].Data.Slot !=
|
|
attestation.Data.Slot {
|
|
t.Errorf("Incorrect slot stored, wanted: %d, got: %d",
|
|
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
|
|
}
|
|
|
|
// Verify the committee for attestation's data slot was cached.
|
|
fetchedCommittees, err := committeeCache.CommitteesInfoBySlot(attestation.Data.Slot)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
wantedCommittee := []uint64{20}
|
|
if !reflect.DeepEqual(wantedCommittee, fetchedCommittees.Committees[0].Committee) {
|
|
t.Errorf(
|
|
"Result indices was an unexpected value. Wanted %d, got %d",
|
|
wantedCommittee,
|
|
fetchedCommittees.Committees[0].Committee,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestUpdateLatestAttestation_CacheEnabledAndHit(t *testing.T) {
|
|
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
|
EnableCommitteesCache: true,
|
|
})
|
|
|
|
var validators []*pb.Validator
|
|
for i := 0; i < 64; i++ {
|
|
validators = append(validators, &pb.Validator{
|
|
Pubkey: []byte{byte(i)},
|
|
ActivationEpoch: 0,
|
|
ExitEpoch: 10,
|
|
})
|
|
}
|
|
|
|
beaconDB := internal.SetupDB(t)
|
|
defer internal.TeardownDB(t, beaconDB)
|
|
ctx := context.Background()
|
|
|
|
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
|
ValidatorRegistry: validators,
|
|
}); err != nil {
|
|
t.Fatalf("could not save state: %v", err)
|
|
}
|
|
|
|
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
|
|
|
slot := uint64(2)
|
|
shard := uint64(3)
|
|
index := uint64(4)
|
|
attestation := &pb.Attestation{
|
|
AggregationBitfield: []byte{0x80},
|
|
Data: &pb.AttestationData{
|
|
Slot: slot,
|
|
Shard: shard,
|
|
},
|
|
}
|
|
|
|
csInSlot := &cache.CommitteesInSlot{
|
|
Slot: slot,
|
|
Committees: []*cache.CommitteeInfo{
|
|
{Shard: shard, Committee: []uint64{index, 999}},
|
|
}}
|
|
|
|
if err := committeeCache.AddCommittees(csInSlot); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
|
|
t.Fatalf("could not update latest attestation: %v", err)
|
|
}
|
|
pubkey := bytesutil.ToBytes48([]byte{byte(index)})
|
|
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
|
|
t.Fatalf("could not update latest attestation: %v", err)
|
|
}
|
|
|
|
if service.store.m[pubkey].Data.Slot !=
|
|
attestation.Data.Slot {
|
|
t.Errorf("Incorrect slot stored, wanted: %d, got: %d",
|
|
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
|
|
}
|
|
}
|