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:
Ivan Martinez 2020-02-14 09:46:55 -07:00 committed by GitHub
parent 214121b0ab
commit 6b40fa01ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 253 additions and 248 deletions

View 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",
],
)

View File

@ -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)
}

View File

@ -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
}

View 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)
}
}
})
}
}

View File

@ -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",

View File

@ -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")

View File

@ -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 := &ethpb.IndexedAttestation{
AttestingIndices: cb,
Signature: make([]byte, 96),
Data: &ethpb.AttestationData{
CommitteeIndex: 0,
BeaconBlockRoot: make([]byte, 32),
Source: &ethpb.Checkpoint{Epoch: 2},
Target: &ethpb.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)
}
}
}

View File

@ -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 := &ethpb.IndexedAttestation{
AttestingIndices: cb,
Signature: make([]byte, 96),
Data: &ethpb.AttestationData{
CommitteeIndex: 0,
BeaconBlockRoot: make([]byte, 32),
Source: &ethpb.Checkpoint{Epoch: 2},
Target: &ethpb.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)
}
}
}

View File

@ -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():
}
}