Compare commits

...

3 Commits

Author SHA1 Message Date
Nishant Das
a264a097cc Update Pending Queue (#4066)
* update queue

* fix test

* put this all in validate method

* remove ancestors too

* not needed

* terence's review

* period

* preston's review
2019-11-21 21:24:50 +08:00
shayzluf
4330839bc1 Add surround check to endpoint (#4065)
* first version of the watchtower api

* service files

* Begin work on grpc server

* More changes to server

* REnames and mock setup

* working test

* merge

* double propose detection test

* nishant review

* todo change

* gaz

* fix service

* gaz

* remove unused import

* gaz

* resolve circular dependency

* resolve circular dependency 2nd try

* remove package

* fix package

* fix test

* added tests

* gaz

* remove status check

* gaz

* remove context

* remove context

* change var name

* moved to rpc dir

* gaz

* remove server code

* gaz

* slasher server

* visibility change

* pb

* service update

* gaz

* slasher grpc server

* making it work

* setup db and start

* gaz

* service flags fixes

* grpc service running

* go imports

* remove new initializer

* gaz

* remove feature flags

* change back SetupSlasherDB

* fix SetupSlasherDB calls

* define err

* fix bad merge

* fix test

* fix imports

* fix imports

* fix imports

* add cancel

* comment stop

* fix cancel issue

* remove unneeded code

* bring back bad merge that removed TODO

* remove use of epoch as am input

* fixed slasher to be runable again

* wait for channel close

* gaz

* small test

* flags fix

* fix flag order

* double vote detection

* remove source epoch from indexed attestation indices

* change server method to receive indexed attestation

* start implementation

* double vote detection

* proto

* pb

* fir comment

* add surround detection and retrieval to endpoint

* nishant review

* import fix

* fix miss order

* fix detection 0 case
added tests

* terence review
2019-11-21 12:41:23 +05:30
terence tsao
835418d1e3 Fix UpdateCommitteeCache slot (#4074) 2019-11-20 21:29:43 -08:00
21 changed files with 377 additions and 39 deletions

View File

@@ -296,7 +296,7 @@ func UpdateCommitteeCache(state *pb.BeaconState) error {
if err != nil {
return err
}
count, err := CommitteeCountAtSlot(state, epoch*params.BeaconConfig().SlotsPerEpoch)
count, err := CommitteeCountAtSlot(state, StartSlot(epoch))
if err != nil {
return err
}

View File

@@ -6,7 +6,9 @@ import (
"sort"
"time"
"github.com/pkg/errors"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/sync/peerstatus"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -39,6 +41,9 @@ func (r *RegularSync) processPendingBlocks(ctx context.Context) error {
defer span.End()
pids := peerstatus.Keys()
if err := r.validatePendingSlots(); err != nil {
return errors.Wrap(err, "could not validate pending slots")
}
slots := r.sortedPendingSlots()
span.AddAttributes(
@@ -109,6 +114,42 @@ func (r *RegularSync) sortedPendingSlots() []int {
slots = append(slots, int(s))
}
sort.Ints(slots)
return slots
}
// validatePendingSlots validates the pending blocks
// by their slot. If they are before the current finalized
// checkpoint, these blocks are removed from the queue.
func (r *RegularSync) validatePendingSlots() error {
r.pendingQueueLock.RLock()
defer r.pendingQueueLock.RUnlock()
oldBlockRoots := make(map[[32]byte]bool)
finalizedEpoch := r.chain.FinalizedCheckpt().Epoch
for s, b := range r.slotToPendingBlocks {
epoch := helpers.SlotToEpoch(s)
// remove all descendant blocks of old blocks
if oldBlockRoots[bytesutil.ToBytes32(b.ParentRoot)] {
root, err := ssz.SigningRoot(b)
if err != nil {
return err
}
oldBlockRoots[root] = true
delete(r.slotToPendingBlocks, s)
delete(r.seenPendingBlocks, root)
continue
}
// don't process old blocks
if finalizedEpoch > 0 && epoch <= finalizedEpoch {
blkRoot, err := ssz.SigningRoot(b)
if err != nil {
return err
}
oldBlockRoots[blkRoot] = true
delete(r.slotToPendingBlocks, s)
delete(r.seenPendingBlocks, blkRoot)
}
}
oldBlockRoots = nil
return nil
}

View File

@@ -30,8 +30,12 @@ func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks1(t *testing.T) {
defer dbtest.TeardownDB(t, db)
r := &RegularSync{
db: db,
chain: &mock.ChainService{},
db: db,
chain: &mock.ChainService{
FinalizedCheckPoint: &ethpb.Checkpoint{
Epoch: 0,
},
},
slotToPendingBlocks: make(map[uint64]*ethpb.BeaconBlock),
seenPendingBlocks: make(map[[32]byte]bool),
}
@@ -114,11 +118,14 @@ func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks2(t *testing.T) {
})
r := &RegularSync{
p2p: p1,
db: db,
chain: &mock.ChainService{},
slotToPendingBlocks: make(map[uint64]*ethpb.BeaconBlock),
seenPendingBlocks: make(map[[32]byte]bool),
p2p: p1,
db: db,
chain: &mock.ChainService{
FinalizedCheckPoint: &ethpb.Checkpoint{
Epoch: 0,
},
}, slotToPendingBlocks: make(map[uint64]*ethpb.BeaconBlock),
seenPendingBlocks: make(map[[32]byte]bool),
}
peerstatus.Set(p2.PeerID(), &pb.Status{})
@@ -192,3 +199,66 @@ func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks2(t *testing.T) {
t.Errorf("Incorrect size for seen pending block: got %d", len(r.seenPendingBlocks))
}
}
func TestRegularSyncBeaconBlockSubscriber_PruneOldPendingBlocks(t *testing.T) {
db := dbtest.SetupDB(t)
defer dbtest.TeardownDB(t, db)
p1 := p2ptest.NewTestP2P(t)
p2 := p2ptest.NewTestP2P(t)
p1.Connect(p2)
if len(p1.Host.Network().Peers()) != 1 {
t.Error("Expected peers to be connected")
}
r := &RegularSync{
p2p: p1,
db: db,
chain: &mock.ChainService{
FinalizedCheckPoint: &ethpb.Checkpoint{
Epoch: 1,
},
}, slotToPendingBlocks: make(map[uint64]*ethpb.BeaconBlock),
seenPendingBlocks: make(map[[32]byte]bool),
}
peerstatus.Set(p2.PeerID(), &pb.Status{})
b0 := &ethpb.BeaconBlock{}
if err := r.db.SaveBlock(context.Background(), b0); err != nil {
t.Fatal(err)
}
b0Root, _ := ssz.SigningRoot(b0)
b1 := &ethpb.BeaconBlock{Slot: 1, ParentRoot: b0Root[:]}
if err := r.db.SaveBlock(context.Background(), b1); err != nil {
t.Fatal(err)
}
b1Root, _ := ssz.SigningRoot(b1)
// Incomplete block links
b2 := &ethpb.BeaconBlock{Slot: 2, ParentRoot: b1Root[:]}
b2Root, _ := ssz.SigningRoot(b2)
b5 := &ethpb.BeaconBlock{Slot: 5, ParentRoot: b2Root[:]}
b5Root, _ := ssz.SigningRoot(b5)
b3 := &ethpb.BeaconBlock{Slot: 3, ParentRoot: b0Root[:]}
b3Root, _ := ssz.SigningRoot(b3)
b4 := &ethpb.BeaconBlock{Slot: 4, ParentRoot: b3Root[:]}
b4Root, _ := ssz.SigningRoot(b4)
r.slotToPendingBlocks[b2.Slot] = b2
r.seenPendingBlocks[b2Root] = true
r.slotToPendingBlocks[b3.Slot] = b3
r.seenPendingBlocks[b3Root] = true
r.slotToPendingBlocks[b4.Slot] = b4
r.seenPendingBlocks[b4Root] = true
r.slotToPendingBlocks[b5.Slot] = b5
r.seenPendingBlocks[b5Root] = true
if err := r.processPendingBlocks(context.Background()); err != nil {
t.Fatal(err)
}
if len(r.slotToPendingBlocks) != 0 {
t.Errorf("Incorrect size for slot to pending blocks cache: got %d", len(r.slotToPendingBlocks))
}
if len(r.seenPendingBlocks) != 0 {
t.Errorf("Incorrect size for seen pending block: got %d", len(r.seenPendingBlocks))
}
}

View File

@@ -5,12 +5,13 @@ package db
import (
fmt "fmt"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
v1alpha1 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,9 +5,10 @@ package db
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
proto "github.com/gogo/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,10 +5,11 @@ package ethereum_beacon_p2p_v1
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,12 +5,13 @@ package ethereum_beacon_p2p_v1
import (
fmt "fmt"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
v1alpha1 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -7,13 +7,14 @@ import (
context "context"
encoding_binary "encoding/binary"
fmt "fmt"
io "io"
math "math"
proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
v1alpha1 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,7 +5,6 @@ package ethereum.beacon.rpc.v1;
import "google/protobuf/empty.proto";
import "proto/eth/v1alpha1/beacon_block.proto";
import "proto/eth/v1alpha1/attestation.proto";
import "google/api/annotations.proto";
service AttesterService {
rpc RequestAttestation(AttestationRequest) returns (ethereum.eth.v1alpha1.AttestationData);

View File

@@ -6,6 +6,8 @@ package ethereum_beacon_rpc_v1
import (
context "context"
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
empty "github.com/golang/protobuf/ptypes/empty"
v1alpha1 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
@@ -13,7 +15,6 @@ import (
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,10 +5,11 @@ package eth
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,11 +5,12 @@ package eth
import (
fmt "fmt"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,10 +5,11 @@ package eth
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -6,13 +6,14 @@ package eth
import (
context "context"
fmt "fmt"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -6,12 +6,13 @@ package eth
import (
context "context"
fmt "fmt"
io "io"
math "math"
proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -6,11 +6,12 @@ package eth
import (
context "context"
fmt "fmt"
io "io"
math "math"
proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
grpc "google.golang.org/grpc"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -7,13 +7,14 @@ import (
context "context"
encoding_binary "encoding/binary"
fmt "fmt"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,9 +5,10 @@ package ethereum_sharding_p2p_v1
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
proto "github.com/gogo/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -32,7 +32,8 @@ func detectMin(attestationEpochSpan uint64,
attestationSourceEpoch uint64) uint64 {
minSpan := uint64(recorderEpochSpan.MinEpochSpan)
if minSpan < attestationEpochSpan {
if minSpan > 0 && minSpan < attestationEpochSpan {
return minSpan + attestationSourceEpoch
}
return 0
@@ -45,6 +46,13 @@ func detectMin(attestationEpochSpan uint64,
// Logic for this detection method was designed by https://github.com/protolambda
// Detailed here: https://github.com/protolambda/eth2-surround/blob/master/README.md#min-max-surround
func (ss *Server) DetectAndUpdateMaxEpochSpan(ctx context.Context, source uint64, target uint64, validatorIdx uint64) (uint64, error) {
if target < source {
return 0, fmt.Errorf(
"target: %d < source: %d ",
target,
source,
)
}
targetEpoch, span, spanMap, err := ss.detectSlashingByEpochSpan(source, target, validatorIdx, detectMax)
if err != nil {
return 0, err
@@ -53,7 +61,7 @@ func (ss *Server) DetectAndUpdateMaxEpochSpan(ctx context.Context, source uint64
return targetEpoch, nil
}
for i := uint64(1); i < target-source; i++ {
val := uint32(span - i - 1)
val := uint32(span - i)
if _, ok := spanMap.EpochSpanMap[source+i]; !ok {
spanMap.EpochSpanMap[source+i] = &ethpb.MinMaxEpochSpan{}
}
@@ -77,6 +85,13 @@ func (ss *Server) DetectAndUpdateMaxEpochSpan(ctx context.Context, source uint64
// Logic is following the detection method designed by https://github.com/protolambda
// Detailed here: https://github.com/protolambda/eth2-surround/blob/master/README.md#min-max-surround
func (ss *Server) DetectAndUpdateMinEpochSpan(ctx context.Context, source uint64, target uint64, validatorIdx uint64) (uint64, error) {
if target < source {
return 0, fmt.Errorf(
"target: %d < source: %d ",
target,
source,
)
}
targetEpoch, _, spanMap, err := ss.detectSlashingByEpochSpan(source, target, validatorIdx, detectMin)
if err != nil {
return 0, err
@@ -109,7 +124,7 @@ func (ss *Server) DetectAndUpdateMinEpochSpan(ctx context.Context, source uint64
// attestation target. This method receives a detector function in order to be used
// for both surrounding and surrounded vote cases.
func (ss *Server) detectSlashingByEpochSpan(source, target, validatorIdx uint64, detector detectFn) (uint64, uint64, *ethpb.EpochSpanMap, error) {
span := target - source + 1
span := target - source
if span > params.BeaconConfig().WeakSubjectivityPeriod {
return 0, span, nil, fmt.Errorf("target: %d - source: %d > weakSubjectivityPeriod",
params.BeaconConfig().WeakSubjectivityPeriod,

View File

@@ -45,7 +45,18 @@ func (ss *Server) IsSlashableAttestation(ctx context.Context, req *ethpb.Indexed
}
}
//TODO(#3133): add surround detection
for _, idx := range indices {
atts, err := ss.DetectSurroundVotes(ctx, req.Data.Source.Epoch, req.Data.Target.Epoch, idx)
if err != nil {
return nil, err
}
for _, ia := range atts {
atsSlashinngRes.AttesterSlashing = append(atsSlashinngRes.AttesterSlashing, &ethpb.AttesterSlashing{
Attestation_1: req,
Attestation_2: ia,
})
}
}
return atsSlashinngRes, nil
}
@@ -87,3 +98,40 @@ func (ss *Server) SlashableAttestations(req *types.Empty, server ethpb.Slasher_S
//TODO(3133): implement stream provider for newly discovered listening to slashable attestation.
return status.Error(codes.Unimplemented, "not implemented")
}
// DetectSurroundVotes is a method used to return the attestation that were detected
// by min max surround detection method.
func (ss *Server) DetectSurroundVotes(ctx context.Context, source uint64, target uint64, validatorIdx uint64) ([]*ethpb.IndexedAttestation, error) {
minTargetEpoch, err := ss.DetectAndUpdateMinEpochSpan(ctx, source, target, validatorIdx)
if err != nil {
return nil, err
}
maxTargetEpoch, err := ss.DetectAndUpdateMaxEpochSpan(ctx, source, target, validatorIdx)
if err != nil {
return nil, err
}
var idxAtts []*ethpb.IndexedAttestation
if minTargetEpoch > 0 {
attestations, err := ss.SlasherDB.IndexedAttestation(minTargetEpoch, validatorIdx)
if err != nil {
return nil, err
}
for _, ia := range attestations {
if ia.Data.Source.Epoch > source && ia.Data.Target.Epoch < target {
idxAtts = append(idxAtts, ia)
}
}
}
if maxTargetEpoch > 0 {
attestations, err := ss.SlasherDB.IndexedAttestation(maxTargetEpoch, validatorIdx)
if err != nil {
return nil, err
}
for _, ia := range attestations {
if ia.Data.Source.Epoch < source && ia.Data.Target.Epoch > target {
idxAtts = append(idxAtts, ia)
}
}
}
return idxAtts, nil
}

View File

@@ -418,3 +418,154 @@ func TestServer_DontSlashSameAttestationData(t *testing.T) {
t.Errorf("Should not return slashaing proof for same data: %v", sr)
}
}
func TestServer_SlashSurroundedAttestation(t *testing.T) {
dbs := db.SetupSlasherDB(t)
defer db.TeardownSlasherDB(t, dbs)
ctx := context.Background()
slasherServer := &Server{
ctx: ctx,
SlasherDB: dbs,
}
ia1 := &ethpb.IndexedAttestation{
CustodyBit_0Indices: []uint64{0},
CustodyBit_1Indices: []uint64{},
Signature: []byte("sig2"),
Data: &ethpb.AttestationData{
Slot: 4*params.BeaconConfig().SlotsPerEpoch + 1,
Index: 0,
BeaconBlockRoot: []byte("block1"),
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 4},
},
}
ia2 := &ethpb.IndexedAttestation{
CustodyBit_0Indices: []uint64{0},
CustodyBit_1Indices: []uint64{},
Signature: []byte("sig1"),
Data: &ethpb.AttestationData{
Slot: 4*params.BeaconConfig().SlotsPerEpoch + 1,
Index: 0,
BeaconBlockRoot: []byte("block2"),
Source: &ethpb.Checkpoint{Epoch: 2},
Target: &ethpb.Checkpoint{Epoch: 3},
},
}
want := &ethpb.AttesterSlashing{
Attestation_1: ia2,
Attestation_2: ia1,
}
if _, err := slasherServer.IsSlashableAttestation(ctx, ia1); err != nil {
t.Errorf("Could not call RPC method: %v", err)
}
sr, err := slasherServer.IsSlashableAttestation(ctx, ia2)
if err != nil {
t.Errorf("Could not call RPC method: %v", err)
}
if len(sr.AttesterSlashing) != 1 {
t.Fatalf("Should return 1 slashaing proof: %v", sr.AttesterSlashing)
}
if !proto.Equal(sr.AttesterSlashing[0], want) {
t.Errorf("Wanted slashing proof: %v got: %v", want, sr.AttesterSlashing[0])
}
}
func TestServer_SlashSurroundAttestation(t *testing.T) {
dbs := db.SetupSlasherDB(t)
defer db.TeardownSlasherDB(t, dbs)
ctx := context.Background()
slasherServer := &Server{
ctx: ctx,
SlasherDB: dbs,
}
ia1 := &ethpb.IndexedAttestation{
CustodyBit_0Indices: []uint64{0},
CustodyBit_1Indices: []uint64{},
Signature: []byte("sig2"),
Data: &ethpb.AttestationData{
Slot: 4*params.BeaconConfig().SlotsPerEpoch + 1,
Index: 0,
BeaconBlockRoot: []byte("block1"),
Source: &ethpb.Checkpoint{Epoch: 2},
Target: &ethpb.Checkpoint{Epoch: 3},
},
}
ia2 := &ethpb.IndexedAttestation{
CustodyBit_0Indices: []uint64{0},
CustodyBit_1Indices: []uint64{},
Signature: []byte("sig1"),
Data: &ethpb.AttestationData{
Slot: 4*params.BeaconConfig().SlotsPerEpoch + 1,
Index: 0,
BeaconBlockRoot: []byte("block2"),
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 4},
},
}
want := &ethpb.AttesterSlashing{
Attestation_1: ia2,
Attestation_2: ia1,
}
if _, err := slasherServer.IsSlashableAttestation(ctx, ia1); err != nil {
t.Errorf("Could not call RPC method: %v", err)
}
sr, err := slasherServer.IsSlashableAttestation(ctx, ia2)
if err != nil {
t.Errorf("Could not call RPC method: %v", err)
}
if len(sr.AttesterSlashing) != 1 {
t.Fatalf("Should return 1 slashaing proof: %v", sr.AttesterSlashing)
}
if !proto.Equal(sr.AttesterSlashing[0], want) {
t.Errorf("Wanted slashing proof: %v got: %v", want, sr.AttesterSlashing[0])
}
}
func TestServer_DontSlashValidAttestations(t *testing.T) {
dbs := db.SetupSlasherDB(t)
defer db.TeardownSlasherDB(t, dbs)
ctx := context.Background()
slasherServer := &Server{
ctx: ctx,
SlasherDB: dbs,
}
ia1 := &ethpb.IndexedAttestation{
CustodyBit_0Indices: []uint64{0},
CustodyBit_1Indices: []uint64{},
Signature: []byte("sig2"),
Data: &ethpb.AttestationData{
Slot: 5*params.BeaconConfig().SlotsPerEpoch + 1,
Index: 0,
BeaconBlockRoot: []byte("block1"),
Source: &ethpb.Checkpoint{Epoch: 2},
Target: &ethpb.Checkpoint{Epoch: 4},
},
}
ia2 := &ethpb.IndexedAttestation{
CustodyBit_0Indices: []uint64{0},
CustodyBit_1Indices: []uint64{},
Signature: []byte("sig1"),
Data: &ethpb.AttestationData{
Slot: 5*params.BeaconConfig().SlotsPerEpoch + 1,
Index: 0,
BeaconBlockRoot: []byte("block2"),
Source: &ethpb.Checkpoint{Epoch: 3},
Target: &ethpb.Checkpoint{Epoch: 5},
},
}
if _, err := slasherServer.IsSlashableAttestation(ctx, ia1); err != nil {
t.Errorf("Could not call RPC method: %v", err)
}
sr, err := slasherServer.IsSlashableAttestation(ctx, ia2)
if err != nil {
t.Errorf("Could not call RPC method: %v", err)
}
if len(sr.AttesterSlashing) != 0 {
t.Errorf("Should not return slashaing proof for same data: %v", sr)
}
}