mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-23 11:57:18 +00:00
Add detection package for slashing detection functions (#4861)
* Move detection to its own package * Fix renames * More fixes * Revert "Fix renames" This reverts commit 3200f89a1b81bbffffdbd1bdca0fad73e0e8bc17. * Fix * Fix renames again * Fix another rename * Fix comment * unused * add comment * gazelle * Add spans * Unexport helper functions Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
parent
214121b0ab
commit
6b40fa01ec
33
slasher/detection/BUILD.bazel
Normal file
33
slasher/detection/BUILD.bazel
Normal file
@ -0,0 +1,33 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["attestations.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/slasher/detection",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//proto/slashing:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"attestation_test.go",
|
||||
"attestations_bench_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//proto/slashing:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//slasher/db/testing:go_default_library",
|
||||
"//slasher/flags:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_urfave_cli//:go_default_library",
|
||||
],
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package rpc
|
||||
package detection
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -201,25 +201,22 @@ func TestServer_UpdateMaxEpochSpan(t *testing.T) {
|
||||
defer testDB.TeardownSlasherDB(t, db)
|
||||
ctx := context.Background()
|
||||
|
||||
slasherServer := &Server{
|
||||
SlasherDB: db,
|
||||
}
|
||||
for _, tt := range spanTestsMax {
|
||||
spanMap, err := slasherServer.SlasherDB.ValidatorSpansMap(ctx, tt.validatorIdx)
|
||||
spanMap, err := db.ValidatorSpansMap(ctx, tt.validatorIdx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, spanMap, err := slasherServer.DetectAndUpdateMaxEpochSpan(ctx, tt.sourceEpoch, tt.targetEpoch, tt.validatorIdx, spanMap)
|
||||
st, spanMap, err := detectAndUpdateMaxEpochSpan(ctx, tt.sourceEpoch, tt.targetEpoch, spanMap)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to update span: %v", err)
|
||||
}
|
||||
if err := slasherServer.SlasherDB.SaveValidatorSpansMap(ctx, tt.validatorIdx, spanMap); err != nil {
|
||||
if err := db.SaveValidatorSpansMap(ctx, tt.validatorIdx, spanMap); err != nil {
|
||||
t.Fatalf("Couldnt save span map for validator id: %d", tt.validatorIdx)
|
||||
}
|
||||
if st != tt.slashingTargetEpoch {
|
||||
t.Fatalf("Expected slashing target: %d got: %d", tt.slashingTargetEpoch, st)
|
||||
}
|
||||
sm, err := slasherServer.SlasherDB.ValidatorSpansMap(ctx, tt.validatorIdx)
|
||||
sm, err := db.ValidatorSpansMap(ctx, tt.validatorIdx)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to retrieve span: %v", err)
|
||||
}
|
||||
@ -236,25 +233,23 @@ func TestServer_UpdateMinEpochSpan(t *testing.T) {
|
||||
db := testDB.SetupSlasherDB(t, c)
|
||||
defer testDB.TeardownSlasherDB(t, db)
|
||||
ctx := context.Background()
|
||||
slasherServer := &Server{
|
||||
SlasherDB: db,
|
||||
}
|
||||
|
||||
for _, tt := range spanTestsMin {
|
||||
spanMap, err := slasherServer.SlasherDB.ValidatorSpansMap(ctx, tt.validatorIdx)
|
||||
spanMap, err := db.ValidatorSpansMap(ctx, tt.validatorIdx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, spanMap, err := slasherServer.DetectAndUpdateMinEpochSpan(ctx, tt.sourceEpoch, tt.targetEpoch, tt.validatorIdx, spanMap)
|
||||
st, spanMap, err := detectAndUpdateMinEpochSpan(ctx, tt.sourceEpoch, tt.targetEpoch, spanMap)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to update span: %v", err)
|
||||
}
|
||||
if err := slasherServer.SlasherDB.SaveValidatorSpansMap(ctx, tt.validatorIdx, spanMap); err != nil {
|
||||
if err := db.SaveValidatorSpansMap(ctx, tt.validatorIdx, spanMap); err != nil {
|
||||
t.Fatalf("Couldnt save span map for validator id: %d", tt.validatorIdx)
|
||||
}
|
||||
if st != tt.slashingTargetEpoch {
|
||||
t.Fatalf("Expected slashing target: %d got: %d", tt.slashingTargetEpoch, st)
|
||||
}
|
||||
sm, err := slasherServer.SlasherDB.ValidatorSpansMap(ctx, tt.validatorIdx)
|
||||
sm, err := db.ValidatorSpansMap(ctx, tt.validatorIdx)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to retrieve span: %v", err)
|
||||
}
|
||||
@ -271,11 +266,8 @@ func TestServer_FailToUpdate(t *testing.T) {
|
||||
db := testDB.SetupSlasherDB(t, c)
|
||||
defer testDB.TeardownSlasherDB(t, db)
|
||||
ctx := context.Background()
|
||||
slasherServer := &Server{
|
||||
SlasherDB: db,
|
||||
}
|
||||
|
||||
spanTestsFail := spanMapTestStruct{
|
||||
validatorIdx: 0,
|
||||
sourceEpoch: 0,
|
||||
slashingTargetEpoch: 0,
|
||||
targetEpoch: params.BeaconConfig().WeakSubjectivityPeriod + 1,
|
||||
@ -286,14 +278,14 @@ func TestServer_FailToUpdate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
spanMap, err := slasherServer.SlasherDB.ValidatorSpansMap(ctx, spanTestsFail.validatorIdx)
|
||||
spanMap, err := db.ValidatorSpansMap(ctx, spanTestsFail.validatorIdx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, _, err := slasherServer.DetectAndUpdateMinEpochSpan(ctx, spanTestsFail.sourceEpoch, spanTestsFail.targetEpoch, spanTestsFail.validatorIdx, spanMap); err == nil {
|
||||
if _, _, err := detectAndUpdateMinEpochSpan(ctx, spanTestsFail.sourceEpoch, spanTestsFail.targetEpoch, spanMap); err == nil {
|
||||
t.Fatalf("Update should not support diff greater then weak subjectivity period: %v ", params.BeaconConfig().WeakSubjectivityPeriod)
|
||||
}
|
||||
if _, _, err := slasherServer.DetectAndUpdateMaxEpochSpan(ctx, spanTestsFail.sourceEpoch, spanTestsFail.targetEpoch, spanTestsFail.validatorIdx, spanMap); err == nil {
|
||||
if _, _, err := detectAndUpdateMaxEpochSpan(ctx, spanTestsFail.sourceEpoch, spanTestsFail.targetEpoch, spanMap); err == nil {
|
||||
t.Fatalf("Update should not support diff greater then weak subjectivity period: %v ", params.BeaconConfig().WeakSubjectivityPeriod)
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
package rpc
|
||||
package detection
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
slashpb "github.com/prysmaticlabs/prysm/proto/slashing"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// Detector is a function type used to implement the slashable surrounding/surrounded
|
||||
@ -13,52 +16,62 @@ import (
|
||||
type detectFn = func(attestationEpochSpan uint64, recorderEpochSpan *slashpb.MinMaxEpochSpan, sourceEpoch uint64) uint64
|
||||
|
||||
// detectMax is a function for maxDetector used to detect surrounding attestations.
|
||||
func detectMax(
|
||||
attestationEpochSpan uint64,
|
||||
recorderEpochSpan *slashpb.MinMaxEpochSpan,
|
||||
attestationSourceEpoch uint64,
|
||||
) uint64 {
|
||||
func detectMax(attEpochSpan uint64, recorderEpochSpan *slashpb.MinMaxEpochSpan, attSourceEpoch uint64) uint64 {
|
||||
maxSpan := uint64(recorderEpochSpan.MaxEpochSpan)
|
||||
if maxSpan > attestationEpochSpan {
|
||||
return maxSpan + attestationSourceEpoch
|
||||
if maxSpan > attEpochSpan {
|
||||
return maxSpan + attSourceEpoch
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// detectMin is a function for minDetecter used to detect surrounded attestations.
|
||||
func detectMin(
|
||||
attestationEpochSpan uint64,
|
||||
recorderEpochSpan *slashpb.MinMaxEpochSpan,
|
||||
attestationSourceEpoch uint64,
|
||||
) uint64 {
|
||||
// detectMin is a function for minDetector used to detect surrounded attestations.
|
||||
func detectMin(attEpochSpan uint64, recorderEpochSpan *slashpb.MinMaxEpochSpan, attSourceEpoch uint64) uint64 {
|
||||
minSpan := uint64(recorderEpochSpan.MinEpochSpan)
|
||||
if minSpan > 0 && minSpan < attestationEpochSpan {
|
||||
return minSpan + attestationSourceEpoch
|
||||
if minSpan > 0 && minSpan < attEpochSpan {
|
||||
return minSpan + attSourceEpoch
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// DetectAndUpdateMaxEpochSpan is used to detect and update the max span of an incoming attestation.
|
||||
// DetectAndUpdateSpans runs detection and updating for both min and max epoch spans, this is used for
|
||||
// attestation slashing detection.
|
||||
// Detailed here: https://github.com/protolambda/eth2-surround/blob/master/README.md#min-max-surround
|
||||
func DetectAndUpdateSpans(
|
||||
ctx context.Context,
|
||||
att *ethpb.IndexedAttestation,
|
||||
spanMap *slashpb.EpochSpanMap,
|
||||
) (*slashpb.EpochSpanMap, uint64, uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Detection.DetectAndUpdateSpans")
|
||||
defer span.End()
|
||||
minTargetEpoch, spanMap, err := detectAndUpdateMinEpochSpan(ctx, att.Data.Source.Epoch, att.Data.Target.Epoch, spanMap)
|
||||
if err != nil {
|
||||
return nil, 0, 0, errors.Wrap(err, "failed to update min spans")
|
||||
}
|
||||
maxTargetEpoch, spanMap, err := detectAndUpdateMaxEpochSpan(ctx, att.Data.Source.Epoch, att.Data.Target.Epoch, spanMap)
|
||||
if err != nil {
|
||||
return nil, 0, 0, errors.Wrap(err, "failed to update max spans")
|
||||
}
|
||||
return spanMap, minTargetEpoch, maxTargetEpoch, nil
|
||||
}
|
||||
|
||||
// detectAndUpdateMaxEpochSpan is used to detect and update the max span of an incoming attestation.
|
||||
// This is used for detecting surrounding votes.
|
||||
// The max span is the span between the current attestation's source epoch and the furthest attestation's
|
||||
// target epoch that has a lower (earlier) source epoch.
|
||||
// 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(
|
||||
func detectAndUpdateMaxEpochSpan(
|
||||
ctx context.Context,
|
||||
source uint64,
|
||||
target uint64,
|
||||
validatorIdx uint64,
|
||||
spanMap *slashpb.EpochSpanMap,
|
||||
) (uint64, *slashpb.EpochSpanMap, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Detection.detectAndUpdateMaxEpochSpan")
|
||||
defer span.End()
|
||||
if target < source {
|
||||
return 0, nil, fmt.Errorf(
|
||||
"target: %d < source: %d ",
|
||||
target,
|
||||
source,
|
||||
)
|
||||
return 0, nil, fmt.Errorf("target: %d < source: %d ", target, source)
|
||||
}
|
||||
targetEpoch, span, spanMap, err := ss.detectSlashingByEpochSpan(source, target, spanMap, detectMax)
|
||||
targetEpoch, minMaxSpan, spanMap, err := detectSlashingByEpochSpan(ctx, source, target, spanMap, detectMax)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
@ -67,7 +80,7 @@ func (ss *Server) DetectAndUpdateMaxEpochSpan(
|
||||
}
|
||||
|
||||
for i := uint64(1); i < target-source; i++ {
|
||||
val := uint32(span - i)
|
||||
val := uint32(minMaxSpan - i)
|
||||
if _, ok := spanMap.EpochSpanMap[source+i]; !ok {
|
||||
spanMap.EpochSpanMap[source+i] = &slashpb.MinMaxEpochSpan{}
|
||||
}
|
||||
@ -77,26 +90,24 @@ func (ss *Server) DetectAndUpdateMaxEpochSpan(
|
||||
break
|
||||
}
|
||||
}
|
||||
if err := ss.SlasherDB.SaveValidatorSpansMap(ctx, validatorIdx, spanMap); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return 0, spanMap, nil
|
||||
}
|
||||
|
||||
// DetectAndUpdateMinEpochSpan is used to detect surrounded votes and update the min epoch span
|
||||
// detectAndUpdateMinEpochSpan is used to detect surrounded votes and update the min epoch span
|
||||
// of an incoming attestation.
|
||||
// The min span is the span between the current attestations target epoch and the
|
||||
// closest attestation's target distance.
|
||||
//
|
||||
// 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(
|
||||
func detectAndUpdateMinEpochSpan(
|
||||
ctx context.Context,
|
||||
source uint64,
|
||||
target uint64,
|
||||
validatorIdx uint64,
|
||||
spanMap *slashpb.EpochSpanMap,
|
||||
) (uint64, *slashpb.EpochSpanMap, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Detection.detectAndUpdateMinEpochSpan")
|
||||
defer span.End()
|
||||
if target < source {
|
||||
return 0, nil, fmt.Errorf(
|
||||
"target: %d < source: %d ",
|
||||
@ -104,7 +115,7 @@ func (ss *Server) DetectAndUpdateMinEpochSpan(
|
||||
source,
|
||||
)
|
||||
}
|
||||
targetEpoch, _, spanMap, err := ss.detectSlashingByEpochSpan(source, target, spanMap, detectMin)
|
||||
targetEpoch, _, spanMap, err := detectSlashingByEpochSpan(ctx, source, target, spanMap, detectMin)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
@ -133,21 +144,25 @@ func (ss *Server) DetectAndUpdateMinEpochSpan(
|
||||
// in the db by checking either the closest attestation target or the furthest
|
||||
// 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,
|
||||
func detectSlashingByEpochSpan(
|
||||
ctx context.Context,
|
||||
source uint64,
|
||||
target uint64,
|
||||
spanMap *slashpb.EpochSpanMap,
|
||||
detector detectFn,
|
||||
) (uint64, uint64, *slashpb.EpochSpanMap, error) {
|
||||
span := target - source
|
||||
if span > params.BeaconConfig().WeakSubjectivityPeriod {
|
||||
return 0, span, nil, fmt.Errorf("target: %d - source: %d > weakSubjectivityPeriod",
|
||||
ctx, span := trace.StartSpan(ctx, "Detection.detectSlashingByEpochSpan")
|
||||
defer span.End()
|
||||
minMaxSpan := target - source
|
||||
if minMaxSpan > params.BeaconConfig().WeakSubjectivityPeriod {
|
||||
return 0, minMaxSpan, nil, fmt.Errorf(
|
||||
"target: %d - source: %d > weakSubjectivityPeriod",
|
||||
params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
span,
|
||||
minMaxSpan,
|
||||
)
|
||||
}
|
||||
if _, ok := spanMap.EpochSpanMap[source]; ok {
|
||||
return detector(span, spanMap.EpochSpanMap[source], source), span, spanMap, nil
|
||||
return detector(minMaxSpan, spanMap.EpochSpanMap[source], source), minMaxSpan, spanMap, nil
|
||||
}
|
||||
return 0, span, spanMap, nil
|
||||
return 0, minMaxSpan, spanMap, nil
|
||||
}
|
101
slasher/detection/attestations_bench_test.go
Normal file
101
slasher/detection/attestations_bench_test.go
Normal file
@ -0,0 +1,101 @@
|
||||
package detection
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
testDB "github.com/prysmaticlabs/prysm/slasher/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/slasher/flags"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
func BenchmarkMinSpan(b *testing.B) {
|
||||
diffs := []uint64{2, 10, 100, 1000, 10000, 53999}
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(flags.UseSpanCacheFlag.Name, true, "enable span map cache")
|
||||
db := testDB.SetupSlasherDB(b, cli.NewContext(app, set, nil))
|
||||
defer testDB.TeardownSlasherDB(b, db)
|
||||
ctx := context.Background()
|
||||
|
||||
for _, diff := range diffs {
|
||||
b.Run(fmt.Sprintf("MinSpan_diff_%d", diff), func(ib *testing.B) {
|
||||
for i := uint64(0); i < uint64(ib.N); i++ {
|
||||
spanMap, err := db.ValidatorSpansMap(ctx, i%10)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, _, err = detectAndUpdateMinEpochSpan(ctx, i, i+diff, spanMap)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMaxSpan(b *testing.B) {
|
||||
diffs := []uint64{2, 10, 100, 1000, 10000, 53999}
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(flags.UseSpanCacheFlag.Name, true, "enable span map cache")
|
||||
db := testDB.SetupSlasherDB(b, cli.NewContext(app, set, nil))
|
||||
defer testDB.TeardownSlasherDB(b, db)
|
||||
ctx := context.Background()
|
||||
|
||||
for _, diff := range diffs {
|
||||
b.Run(fmt.Sprintf("MaxSpan_diff_%d", diff), func(ib *testing.B) {
|
||||
for i := uint64(0); i < uint64(ib.N); i++ {
|
||||
spanMap, err := db.ValidatorSpansMap(ctx, i%10)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, _, err = detectAndUpdateMaxEpochSpan(ctx, diff, diff+i, spanMap)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDetectSpan(b *testing.B) {
|
||||
diffs := []uint64{2, 10, 100, 1000, 10000, 53999}
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(flags.UseSpanCacheFlag.Name, true, "enable span map cache")
|
||||
db := testDB.SetupSlasherDB(b, cli.NewContext(app, set, nil))
|
||||
defer testDB.TeardownSlasherDB(b, db)
|
||||
ctx := context.Background()
|
||||
|
||||
for _, diff := range diffs {
|
||||
b.Run(fmt.Sprintf("Detect_MaxSpan_diff_%d", diff), func(ib *testing.B) {
|
||||
for i := uint64(0); i < uint64(ib.N); i++ {
|
||||
spanMap, err := db.ValidatorSpansMap(ctx, i%10)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, _, _, err = detectSlashingByEpochSpan(ctx, i, i+diff, spanMap, detectMax)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
for _, diff := range diffs {
|
||||
b.Run(fmt.Sprintf("Detect_MinSpan_diff_%d", diff), func(ib *testing.B) {
|
||||
for i := uint64(0); i < uint64(ib.N); i++ {
|
||||
spanMap, err := db.ValidatorSpansMap(ctx, i%10)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, _, _, err = detectSlashingByEpochSpan(ctx, i, i+diff, spanMap, detectMin)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -2,19 +2,16 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"detect_update_min_max_span.go",
|
||||
"server.go",
|
||||
],
|
||||
srcs = ["server.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/slasher/rpc",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//proto/slashing:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//slasher/db/kv:go_default_library",
|
||||
"//slasher/db/types:go_default_library",
|
||||
"//slasher/detection:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
@ -24,11 +21,7 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"detect_update_min_max_span_test.go",
|
||||
"server_test.go",
|
||||
"slashing_bench_test.go",
|
||||
],
|
||||
srcs = ["server_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//proto/slashing:go_default_library",
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/slasher/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/slasher/db/types"
|
||||
"github.com/prysmaticlabs/prysm/slasher/detection"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -110,13 +111,7 @@ func (ss *Server) UpdateSpanMaps(ctx context.Context, req *ethpb.IndexedAttestat
|
||||
wg.Done()
|
||||
return
|
||||
}
|
||||
_, spanMap, err = ss.DetectAndUpdateMinEpochSpan(ctx, req.Data.Source.Epoch, req.Data.Target.Epoch, i, spanMap)
|
||||
if err != nil {
|
||||
er <- err
|
||||
wg.Done()
|
||||
return
|
||||
}
|
||||
_, spanMap, err = ss.DetectAndUpdateMaxEpochSpan(ctx, req.Data.Source.Epoch, req.Data.Target.Epoch, i, spanMap)
|
||||
spanMap, _, _, err = detection.DetectAndUpdateSpans(ctx, req, spanMap)
|
||||
if err != nil {
|
||||
er <- err
|
||||
wg.Done()
|
||||
@ -193,13 +188,9 @@ func (ss *Server) DetectSurroundVotes(ctx context.Context, validatorIdx uint64,
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get validator spans map")
|
||||
}
|
||||
minTargetEpoch, spanMap, err := ss.DetectAndUpdateMinEpochSpan(ctx, req.Data.Source.Epoch, req.Data.Target.Epoch, validatorIdx, spanMap)
|
||||
spanMap, minTargetEpoch, maxTargetEpoch, err := detection.DetectAndUpdateSpans(ctx, req, spanMap)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to update min spans")
|
||||
}
|
||||
maxTargetEpoch, spanMap, err := ss.DetectAndUpdateMaxEpochSpan(ctx, req.Data.Source.Epoch, req.Data.Target.Epoch, validatorIdx, spanMap)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to update max spans")
|
||||
return nil, errors.Wrap(err, "failed to update spans")
|
||||
}
|
||||
if err := ss.SlasherDB.SaveValidatorSpansMap(ctx, validatorIdx, spanMap); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to save validator spans map")
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
testDB "github.com/prysmaticlabs/prysm/slasher/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/slasher/db/types"
|
||||
"github.com/prysmaticlabs/prysm/slasher/flags"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
@ -698,5 +699,44 @@ func TestServer_Store_100_Attestations(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
t.Logf("DB size is: %d", s)
|
||||
|
||||
}
|
||||
|
||||
func BenchmarkCheckAttestations(b *testing.B) {
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(flags.UseSpanCacheFlag.Name, true, "enable span map cache")
|
||||
ctx := cli.NewContext(app, set, nil)
|
||||
db := testDB.SetupSlasherDB(b, ctx)
|
||||
defer testDB.TeardownSlasherDB(b, db)
|
||||
context := context.Background()
|
||||
|
||||
slasherServer := &Server{
|
||||
ctx: context,
|
||||
SlasherDB: db,
|
||||
}
|
||||
var cb []uint64
|
||||
for i := uint64(0); i < 100; i++ {
|
||||
cb = append(cb, i)
|
||||
}
|
||||
ia1 := ðpb.IndexedAttestation{
|
||||
AttestingIndices: cb,
|
||||
Signature: make([]byte, 96),
|
||||
Data: ðpb.AttestationData{
|
||||
CommitteeIndex: 0,
|
||||
BeaconBlockRoot: make([]byte, 32),
|
||||
Source: ðpb.Checkpoint{Epoch: 2},
|
||||
Target: ðpb.Checkpoint{Epoch: 4},
|
||||
},
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := uint64(0); i < uint64(b.N); i++ {
|
||||
ia1.Data.Target.Epoch = i + 1
|
||||
ia1.Data.Source.Epoch = i
|
||||
ia1.Data.Slot = (i + 1) * params.BeaconConfig().SlotsPerEpoch
|
||||
root := []byte(strconv.Itoa(int(i)))
|
||||
ia1.Data.BeaconBlockRoot = append(root, ia1.Data.BeaconBlockRoot[len(root):]...)
|
||||
if _, err := slasherServer.IsSlashableAttestation(context, ia1); err != nil {
|
||||
b.Errorf("Could not call RPC method: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,160 +0,0 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
testDB "github.com/prysmaticlabs/prysm/slasher/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/slasher/flags"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var appFlags = []cli.Flag{
|
||||
flags.CertFlag,
|
||||
flags.RPCPort,
|
||||
flags.KeyFlag,
|
||||
flags.UseSpanCacheFlag,
|
||||
}
|
||||
|
||||
func BenchmarkMinSpan(b *testing.B) {
|
||||
diffs := []uint64{2, 10, 100, 1000, 10000, 53999}
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(flags.UseSpanCacheFlag.Name, true, "enable span map cache")
|
||||
db := testDB.SetupSlasherDB(b, cli.NewContext(app, set, nil))
|
||||
defer testDB.TeardownSlasherDB(b, db)
|
||||
ctx := context.Background()
|
||||
|
||||
slasherServer := &Server{
|
||||
SlasherDB: db,
|
||||
}
|
||||
for _, diff := range diffs {
|
||||
b.Run(fmt.Sprintf("MinSpan_diff_%d", diff), func(ib *testing.B) {
|
||||
for i := uint64(0); i < uint64(ib.N); i++ {
|
||||
spanMap, err := slasherServer.SlasherDB.ValidatorSpansMap(ctx, i%10)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, _, err = slasherServer.DetectAndUpdateMinEpochSpan(ctx, i, i+diff, i%10, spanMap)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMaxSpan(b *testing.B) {
|
||||
diffs := []uint64{2, 10, 100, 1000, 10000, 53999}
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(flags.UseSpanCacheFlag.Name, true, "enable span map cache")
|
||||
db := testDB.SetupSlasherDB(b, cli.NewContext(app, set, nil))
|
||||
defer testDB.TeardownSlasherDB(b, db)
|
||||
ctx := context.Background()
|
||||
|
||||
slasherServer := &Server{
|
||||
SlasherDB: db,
|
||||
}
|
||||
for _, diff := range diffs {
|
||||
b.Run(fmt.Sprintf("MaxSpan_diff_%d", diff), func(ib *testing.B) {
|
||||
for i := uint64(0); i < uint64(ib.N); i++ {
|
||||
spanMap, err := slasherServer.SlasherDB.ValidatorSpansMap(ctx, i%10)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, _, err = slasherServer.DetectAndUpdateMaxEpochSpan(ctx, diff, diff+i, i%10, spanMap)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDetectSpan(b *testing.B) {
|
||||
diffs := []uint64{2, 10, 100, 1000, 10000, 53999}
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(flags.UseSpanCacheFlag.Name, true, "enable span map cache")
|
||||
db := testDB.SetupSlasherDB(b, cli.NewContext(app, set, nil))
|
||||
defer testDB.TeardownSlasherDB(b, db)
|
||||
ctx := context.Background()
|
||||
|
||||
slasherServer := &Server{
|
||||
SlasherDB: db,
|
||||
}
|
||||
for _, diff := range diffs {
|
||||
b.Run(fmt.Sprintf("Detect_MaxSpan_diff_%d", diff), func(ib *testing.B) {
|
||||
for i := uint64(0); i < uint64(ib.N); i++ {
|
||||
spanMap, err := slasherServer.SlasherDB.ValidatorSpansMap(ctx, i%10)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, _, _, err = slasherServer.detectSlashingByEpochSpan(i, i+diff, spanMap, detectMax)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
for _, diff := range diffs {
|
||||
b.Run(fmt.Sprintf("Detect_MinSpan_diff_%d", diff), func(ib *testing.B) {
|
||||
for i := uint64(0); i < uint64(ib.N); i++ {
|
||||
spanMap, err := slasherServer.SlasherDB.ValidatorSpansMap(ctx, i%10)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_, _, _, err = slasherServer.detectSlashingByEpochSpan(i, i+diff, spanMap, detectMin)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCheckAttestations(b *testing.B) {
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(flags.UseSpanCacheFlag.Name, true, "enable span map cache")
|
||||
ctx := cli.NewContext(app, set, nil)
|
||||
db := testDB.SetupSlasherDB(b, ctx)
|
||||
defer testDB.TeardownSlasherDB(b, db)
|
||||
context := context.Background()
|
||||
slasherServer := &Server{
|
||||
ctx: context,
|
||||
SlasherDB: db,
|
||||
}
|
||||
var cb []uint64
|
||||
for i := uint64(0); i < 100; i++ {
|
||||
cb = append(cb, i)
|
||||
}
|
||||
ia1 := ðpb.IndexedAttestation{
|
||||
AttestingIndices: cb,
|
||||
Signature: make([]byte, 96),
|
||||
Data: ðpb.AttestationData{
|
||||
CommitteeIndex: 0,
|
||||
BeaconBlockRoot: make([]byte, 32),
|
||||
Source: ðpb.Checkpoint{Epoch: 2},
|
||||
Target: ðpb.Checkpoint{Epoch: 4},
|
||||
},
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := uint64(0); i < uint64(b.N); i++ {
|
||||
ia1.Data.Target.Epoch = i + 1
|
||||
ia1.Data.Source.Epoch = i
|
||||
ia1.Data.Slot = (i + 1) * params.BeaconConfig().SlotsPerEpoch
|
||||
root := []byte(strconv.Itoa(int(i)))
|
||||
ia1.Data.BeaconBlockRoot = append(root, ia1.Data.BeaconBlockRoot[len(root):]...)
|
||||
if _, err := slasherServer.IsSlashableAttestation(context, ia1); err != nil {
|
||||
b.Errorf("Could not call RPC method: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -68,7 +68,7 @@ func TestStop_CancelsContext(t *testing.T) {
|
||||
|
||||
select {
|
||||
case <-time.After(1 * time.Second):
|
||||
t.Error("ctx not canceled within 1s")
|
||||
t.Error("Context not canceled within 1s")
|
||||
case <-vs.ctx.Done():
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user