mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 12:57:18 +00:00
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
This commit is contained in:
parent
835418d1e3
commit
4330839bc1
@ -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);
|
||||
|
@ -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] = ðpb.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,
|
||||
|
@ -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, ðpb.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
|
||||
}
|
||||
|
@ -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 := ðpb.IndexedAttestation{
|
||||
CustodyBit_0Indices: []uint64{0},
|
||||
CustodyBit_1Indices: []uint64{},
|
||||
Signature: []byte("sig2"),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 4*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
Index: 0,
|
||||
BeaconBlockRoot: []byte("block1"),
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Target: ðpb.Checkpoint{Epoch: 4},
|
||||
},
|
||||
}
|
||||
ia2 := ðpb.IndexedAttestation{
|
||||
CustodyBit_0Indices: []uint64{0},
|
||||
CustodyBit_1Indices: []uint64{},
|
||||
Signature: []byte("sig1"),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 4*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
Index: 0,
|
||||
BeaconBlockRoot: []byte("block2"),
|
||||
Source: ðpb.Checkpoint{Epoch: 2},
|
||||
Target: ðpb.Checkpoint{Epoch: 3},
|
||||
},
|
||||
}
|
||||
want := ðpb.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 := ðpb.IndexedAttestation{
|
||||
CustodyBit_0Indices: []uint64{0},
|
||||
CustodyBit_1Indices: []uint64{},
|
||||
Signature: []byte("sig2"),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 4*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
Index: 0,
|
||||
BeaconBlockRoot: []byte("block1"),
|
||||
Source: ðpb.Checkpoint{Epoch: 2},
|
||||
Target: ðpb.Checkpoint{Epoch: 3},
|
||||
},
|
||||
}
|
||||
ia2 := ðpb.IndexedAttestation{
|
||||
CustodyBit_0Indices: []uint64{0},
|
||||
CustodyBit_1Indices: []uint64{},
|
||||
Signature: []byte("sig1"),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 4*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
Index: 0,
|
||||
BeaconBlockRoot: []byte("block2"),
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Target: ðpb.Checkpoint{Epoch: 4},
|
||||
},
|
||||
}
|
||||
want := ðpb.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 := ðpb.IndexedAttestation{
|
||||
CustodyBit_0Indices: []uint64{0},
|
||||
CustodyBit_1Indices: []uint64{},
|
||||
Signature: []byte("sig2"),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 5*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
Index: 0,
|
||||
BeaconBlockRoot: []byte("block1"),
|
||||
Source: ðpb.Checkpoint{Epoch: 2},
|
||||
Target: ðpb.Checkpoint{Epoch: 4},
|
||||
},
|
||||
}
|
||||
ia2 := ðpb.IndexedAttestation{
|
||||
CustodyBit_0Indices: []uint64{0},
|
||||
CustodyBit_1Indices: []uint64{},
|
||||
Signature: []byte("sig1"),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 5*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
Index: 0,
|
||||
BeaconBlockRoot: []byte("block2"),
|
||||
Source: ðpb.Checkpoint{Epoch: 3},
|
||||
Target: ðpb.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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user