mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 23:18:15 -05:00
Changes to E2E for Optimized Slasher (#9698)
* remaining slasher e2e changes * testing gaz * slash e2e * deepsource * gaz * viz * revert wait group changes * comment * lock around reset cache * add slashing reason * revert changes * is sync Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: prestonvanloon <preston@prysmaticlabs.com>
This commit is contained in:
@@ -131,6 +131,7 @@ func (p *Pool) InsertAttesterSlashing(
|
||||
|
||||
slashedVal := slice.IntersectionUint64(slashing.Attestation_1.AttestingIndices, slashing.Attestation_2.AttestingIndices)
|
||||
cantSlash := make([]uint64, 0, len(slashedVal))
|
||||
slashingReason := ""
|
||||
for _, val := range slashedVal {
|
||||
// Has this validator index been included recently?
|
||||
ok, err := p.validatorSlashingPreconditionCheck(state, types.ValidatorIndex(val))
|
||||
@@ -140,6 +141,7 @@ func (p *Pool) InsertAttesterSlashing(
|
||||
// If the validator has already exited, has already been slashed, or if its index
|
||||
// has been recently included in the pool of slashings, skip including this indice.
|
||||
if !ok {
|
||||
slashingReason = "validator already exited/slashed or already recently included in slashings pool"
|
||||
cantSlash = append(cantSlash, val)
|
||||
continue
|
||||
}
|
||||
@@ -150,6 +152,7 @@ func (p *Pool) InsertAttesterSlashing(
|
||||
return uint64(p.pendingAttesterSlashing[i].validatorToSlash) >= val
|
||||
})
|
||||
if found != len(p.pendingAttesterSlashing) && uint64(p.pendingAttesterSlashing[found].validatorToSlash) == val {
|
||||
slashingReason = "validator already exist in list of pending slashings, no need to attempt to slash again"
|
||||
cantSlash = append(cantSlash, val)
|
||||
continue
|
||||
}
|
||||
@@ -166,7 +169,11 @@ func (p *Pool) InsertAttesterSlashing(
|
||||
numPendingAttesterSlashings.Set(float64(len(p.pendingAttesterSlashing)))
|
||||
}
|
||||
if len(cantSlash) == len(slashedVal) {
|
||||
return fmt.Errorf("could not slash any of %d validators in submitted slashing", len(slashedVal))
|
||||
return fmt.Errorf(
|
||||
"could not slash any of %d validators in submitted slashing: %s",
|
||||
len(slashedVal),
|
||||
slashingReason,
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ go_test(
|
||||
"endtoend_test.go",
|
||||
"minimal_e2e_test.go",
|
||||
"minimal_slashing_e2e_test.go",
|
||||
"slasher_simulator_e2e_test.go",
|
||||
],
|
||||
args = ["-test.v"],
|
||||
data = [
|
||||
@@ -28,8 +29,13 @@ go_test(
|
||||
"requires-network",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/db/testing:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/endtoend/components:go_default_library",
|
||||
@@ -38,9 +44,12 @@ go_test(
|
||||
"//testing/endtoend/params:go_default_library",
|
||||
"//testing/endtoend/types:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/slasher/simulator:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_golang_x_sync//errgroup:go_default_library",
|
||||
|
||||
@@ -140,7 +140,6 @@ func (r *testRunner) run() {
|
||||
requiredComponents := []e2etypes.ComponentRunner{
|
||||
tracingSink, eth1Node, bootNode, beaconNodes, validatorNodes,
|
||||
}
|
||||
|
||||
ctxAllNodesReady, cancel := context.WithTimeout(ctx, allNodesStartTimeout)
|
||||
defer cancel()
|
||||
if err := helpers.ComponentsStarted(ctxAllNodesReady, requiredComponents); err != nil {
|
||||
@@ -148,7 +147,7 @@ func (r *testRunner) run() {
|
||||
}
|
||||
|
||||
// Since defer unwraps in LIFO order, parent context will be closed only after logs are written.
|
||||
defer helpers.LogOutput(t, config)
|
||||
defer helpers.LogOutput(t)
|
||||
if config.UsePprof {
|
||||
defer func() {
|
||||
log.Info("Writing output pprof files")
|
||||
@@ -228,26 +227,23 @@ func (r *testRunner) runEvaluators(conns []*grpc.ClientConn, tickingStartTime ti
|
||||
ticker := helpers.NewEpochTicker(tickingStartTime, secondsPerEpoch)
|
||||
for currentEpoch := range ticker.C() {
|
||||
wg := new(sync.WaitGroup)
|
||||
for _, ev := range config.Evaluators {
|
||||
for _, eval := range config.Evaluators {
|
||||
// Fix reference to evaluator as it will be running
|
||||
// in a separate goroutine.
|
||||
evaluator := ev
|
||||
evaluator := eval
|
||||
// Only run if the policy says so.
|
||||
if !evaluator.Policy(types.Epoch(currentEpoch)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Add evaluator to our waitgroup.
|
||||
wg.Add(1)
|
||||
|
||||
go t.Run(fmt.Sprintf(evaluator.Name, currentEpoch), func(t *testing.T) {
|
||||
err := evaluator.Evaluation(conns...)
|
||||
assert.NoError(t, err, "Evaluation failed for epoch %d: %v", currentEpoch, err)
|
||||
wg.Done()
|
||||
})
|
||||
}
|
||||
// Wait for all evaluators to finish their evaluation for the epoch.
|
||||
wg.Wait()
|
||||
|
||||
if t.Failed() || currentEpoch >= config.EpochsToRun-1 {
|
||||
ticker.Done()
|
||||
if t.Failed() {
|
||||
@@ -319,7 +315,6 @@ func (r *testRunner) testBeaconChainSync(ctx context.Context, g *errgroup.Group,
|
||||
assert.NoError(t, evaluator.Evaluation(conns...), "Evaluation failed for sync node")
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethtypes "github.com/prysmaticlabs/eth2-types"
|
||||
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/endtoend/policies"
|
||||
"github.com/prysmaticlabs/prysm/testing/endtoend/types"
|
||||
@@ -14,10 +15,12 @@ import (
|
||||
|
||||
// FinalizationOccurs is an evaluator to make sure finalization is performing as it should.
|
||||
// Requires to be run after at least 4 epochs have passed.
|
||||
var FinalizationOccurs = types.Evaluator{
|
||||
Name: "finalizes_at_epoch_%d",
|
||||
Policy: policies.AfterNthEpoch(3),
|
||||
Evaluation: finalizationOccurs,
|
||||
var FinalizationOccurs = func(epoch ethtypes.Epoch) types.Evaluator {
|
||||
return types.Evaluator{
|
||||
Name: "finalizes_at_epoch_%d",
|
||||
Policy: policies.AfterNthEpoch(epoch),
|
||||
Evaluation: finalizationOccurs,
|
||||
}
|
||||
}
|
||||
|
||||
func finalizationOccurs(conns ...*grpc.ClientConn) error {
|
||||
|
||||
@@ -39,7 +39,7 @@ var HealthzCheck = e2etypes.Evaluator{
|
||||
|
||||
// FinishedSyncing returns whether the beacon node with the given rpc port has finished syncing.
|
||||
var FinishedSyncing = e2etypes.Evaluator{
|
||||
Name: "finished_syncing",
|
||||
Name: "finished_syncing_%d",
|
||||
Policy: policies.AllEpochs,
|
||||
Evaluation: finishedSyncing,
|
||||
}
|
||||
@@ -47,7 +47,7 @@ var FinishedSyncing = e2etypes.Evaluator{
|
||||
// AllNodesHaveSameHead ensures all nodes have the same head epoch. Checks finality and justification as well.
|
||||
// Not checking head block root as it may change irregularly for the validator connected nodes.
|
||||
var AllNodesHaveSameHead = e2etypes.Evaluator{
|
||||
Name: "all_nodes_have_same_head",
|
||||
Name: "all_nodes_have_same_head_%d",
|
||||
Policy: policies.AllEpochs,
|
||||
Evaluation: allNodesHaveSameHead,
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/container/slice"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
e2e "github.com/prysmaticlabs/prysm/testing/endtoend/params"
|
||||
"github.com/prysmaticlabs/prysm/testing/endtoend/policies"
|
||||
e2eTypes "github.com/prysmaticlabs/prysm/testing/endtoend/types"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
@@ -19,32 +20,40 @@ import (
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// InjectDoubleVote broadcasts a double vote into the beacon node pool for the slasher to detect.
|
||||
var InjectDoubleVote = e2eTypes.Evaluator{
|
||||
Name: "inject_double_vote_%d",
|
||||
Policy: policies.OnEpoch(1),
|
||||
Evaluation: insertDoubleAttestationIntoPool,
|
||||
// InjectDoubleVoteOnEpoch broadcasts a double vote into the beacon node pool for the slasher to detect.
|
||||
var InjectDoubleVoteOnEpoch = func(n types.Epoch) e2eTypes.Evaluator {
|
||||
return e2eTypes.Evaluator{
|
||||
Name: "inject_double_vote_%d",
|
||||
Policy: policies.OnEpoch(n),
|
||||
Evaluation: insertDoubleAttestationIntoPool,
|
||||
}
|
||||
}
|
||||
|
||||
// ProposeDoubleBlock broadcasts a double block to the beacon node for the slasher to detect.
|
||||
var ProposeDoubleBlock = e2eTypes.Evaluator{
|
||||
Name: "propose_double_block_%d",
|
||||
Policy: policies.OnEpoch(1),
|
||||
Evaluation: proposeDoubleBlock,
|
||||
// InjectDoubleBlockOnEpoch proposes a double block to the beacon node for the slasher to detect.
|
||||
var InjectDoubleBlockOnEpoch = func(n types.Epoch) e2eTypes.Evaluator {
|
||||
return e2eTypes.Evaluator{
|
||||
Name: "inject_double_block_%d",
|
||||
Policy: policies.OnEpoch(n),
|
||||
Evaluation: proposeDoubleBlock,
|
||||
}
|
||||
}
|
||||
|
||||
// ValidatorsSlashed ensures the expected amount of validators are slashed.
|
||||
var ValidatorsSlashed = e2eTypes.Evaluator{
|
||||
Name: "validators_slashed_epoch_%d",
|
||||
Policy: policies.AfterNthEpoch(1),
|
||||
Evaluation: validatorsSlashed,
|
||||
// ValidatorsSlashedAfterEpoch ensures the expected amount of validators are slashed.
|
||||
var ValidatorsSlashedAfterEpoch = func(n types.Epoch) e2eTypes.Evaluator {
|
||||
return e2eTypes.Evaluator{
|
||||
Name: "validators_slashed_epoch_%d",
|
||||
Policy: policies.AfterNthEpoch(n),
|
||||
Evaluation: validatorsSlashed,
|
||||
}
|
||||
}
|
||||
|
||||
// SlashedValidatorsLoseBalance checks if the validators slashed lose the right balance.
|
||||
var SlashedValidatorsLoseBalance = e2eTypes.Evaluator{
|
||||
Name: "slashed_validators_lose_valance_epoch_%d",
|
||||
Policy: policies.AfterNthEpoch(1),
|
||||
Evaluation: validatorsLoseBalance,
|
||||
// SlashedValidatorsLoseBalanceAfterEpoch checks if the validators slashed lose the right balance.
|
||||
var SlashedValidatorsLoseBalanceAfterEpoch = func(n types.Epoch) e2eTypes.Evaluator {
|
||||
return e2eTypes.Evaluator{
|
||||
Name: "slashed_validators_lose_valance_epoch_%d",
|
||||
Policy: policies.AfterNthEpoch(n),
|
||||
Evaluation: validatorsLoseBalance,
|
||||
}
|
||||
}
|
||||
|
||||
var slashedIndices []uint64
|
||||
@@ -193,7 +202,6 @@ func proposeDoubleBlock(conns ...*grpc.ClientConn) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get chain head")
|
||||
}
|
||||
|
||||
_, privKeys, err := util.DeterministicDepositsAndKeys(params.BeaconConfig().MinGenesisActiveValidatorCount)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -218,10 +226,23 @@ func proposeDoubleBlock(conns ...*grpc.ClientConn) error {
|
||||
}
|
||||
}
|
||||
|
||||
validatorNum := int(params.BeaconConfig().MinGenesisActiveValidatorCount)
|
||||
beaconNodeNum := e2e.TestParams.BeaconNodeCount
|
||||
if validatorNum%beaconNodeNum != 0 {
|
||||
return errors.New("validator count is not easily divisible by beacon node count")
|
||||
}
|
||||
validatorsPerNode := validatorNum / beaconNodeNum
|
||||
|
||||
// If the proposer index is in the second validator client, we connect to
|
||||
// the corresponding beacon node instead.
|
||||
if proposerIndex >= types.ValidatorIndex(uint64(validatorsPerNode)) {
|
||||
valClient = eth.NewBeaconNodeValidatorClient(conns[1])
|
||||
}
|
||||
|
||||
hashLen := 32
|
||||
blk := ð.BeaconBlock{
|
||||
Slot: chainHead.HeadSlot - 1,
|
||||
ParentRoot: bytesutil.PadTo([]byte("bad parent root"), hashLen),
|
||||
Slot: chainHead.HeadSlot + 1,
|
||||
ParentRoot: chainHead.HeadBlockRoot,
|
||||
StateRoot: bytesutil.PadTo([]byte("bad state root"), hashLen),
|
||||
ProposerIndex: proposerIndex,
|
||||
Body: ð.BeaconBlockBody{
|
||||
@@ -260,8 +281,7 @@ func proposeDoubleBlock(conns ...*grpc.ClientConn) error {
|
||||
|
||||
// We only broadcast to conns[0] here since we can trust that at least 1 node will be online.
|
||||
// Only broadcasting the attestation to one node also helps test slashing propagation.
|
||||
client := eth.NewBeaconNodeValidatorClient(conns[0])
|
||||
if _, err = client.ProposeBlock(ctx, signedBlk); err == nil {
|
||||
if _, err = valClient.ProposeBlock(ctx, signedBlk); err == nil {
|
||||
return errors.New("expected block to fail processing")
|
||||
}
|
||||
slashedIndices = append(slashedIndices, uint64(proposerIndex))
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethtypes "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -27,10 +28,12 @@ var ValidatorsAreActive = types.Evaluator{
|
||||
}
|
||||
|
||||
// ValidatorsParticipating ensures the expected amount of validators are active.
|
||||
var ValidatorsParticipating = types.Evaluator{
|
||||
Name: "validators_participating_epoch_%d",
|
||||
Policy: policies.AfterNthEpoch(2),
|
||||
Evaluation: validatorsParticipating,
|
||||
var ValidatorsParticipatingAtEpoch = func(epoch ethtypes.Epoch) types.Evaluator {
|
||||
return types.Evaluator{
|
||||
Name: "validators_participating_epoch_%d",
|
||||
Policy: policies.AfterNthEpoch(epoch),
|
||||
Evaluation: validatorsParticipating,
|
||||
}
|
||||
}
|
||||
|
||||
// ValidatorSyncParticipation ensures the expected amount of sync committee participants
|
||||
|
||||
@@ -109,7 +109,7 @@ random:
|
||||
}
|
||||
|
||||
// LogOutput logs the output of all log files made.
|
||||
func LogOutput(t *testing.T, config *e2etypes.E2EConfig) {
|
||||
func LogOutput(t *testing.T) {
|
||||
// Log out errors from beacon chain nodes.
|
||||
for i := 0; i < e2e.TestParams.BeaconNodeCount; i++ {
|
||||
beaconLogFile, err := os.Open(path.Join(e2e.TestParams.LogPath, fmt.Sprintf(e2e.BeaconNodeLogFileName, i)))
|
||||
@@ -123,15 +123,8 @@ func LogOutput(t *testing.T, config *e2etypes.E2EConfig) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
LogErrorOutput(t, validatorLogFile, "validator client", i)
|
||||
|
||||
if config.TestSlasher {
|
||||
slasherLogFile, err := os.Open(path.Join(e2e.TestParams.LogPath, fmt.Sprintf(e2e.SlasherLogFileName, i)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
LogErrorOutput(t, slasherLogFile, "slasher client", i)
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Ending time: %s\n", time.Now().String())
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ func e2eMinimal(t *testing.T, usePrysmSh bool) {
|
||||
ev.HealthzCheck,
|
||||
ev.MetricsCheck,
|
||||
ev.ValidatorsAreActive,
|
||||
ev.ValidatorsParticipating,
|
||||
ev.FinalizationOccurs,
|
||||
ev.ValidatorsParticipatingAtEpoch(2),
|
||||
ev.FinalizationOccurs(3),
|
||||
ev.ProcessesDepositsInBlocks,
|
||||
ev.VerifyBlockGraffiti,
|
||||
ev.ActivatesDepositedValidators,
|
||||
@@ -60,6 +60,8 @@ func e2eMinimal(t *testing.T, usePrysmSh bool) {
|
||||
ev.ForkTransition,
|
||||
ev.APIMiddlewareVerifyIntegrity,
|
||||
ev.APIGatewayV1Alpha1VerifyIntegrity,
|
||||
ev.FinishedSyncing,
|
||||
ev.AllNodesHaveSameHead,
|
||||
}
|
||||
// TODO(#9166): remove this block once v2 changes are live.
|
||||
if !usePrysmSh {
|
||||
@@ -78,7 +80,6 @@ func e2eMinimal(t *testing.T, usePrysmSh bool) {
|
||||
EpochsToRun: uint64(epochsToRun),
|
||||
TestSync: true,
|
||||
TestDeposits: true,
|
||||
TestSlasher: false,
|
||||
UsePrysmShValidator: usePrysmSh,
|
||||
UsePprof: !longRunning,
|
||||
TracingSinkEndpoint: tracingEndpoint,
|
||||
|
||||
@@ -10,26 +10,25 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
func TestEndToEnd_Slashing_MinimalConfig(t *testing.T) {
|
||||
t.Skip("To be replaced with the new slasher implementation")
|
||||
|
||||
func TestEndToEnd_Slasher_MinimalConfig(t *testing.T) {
|
||||
params.UseE2EConfig()
|
||||
require.NoError(t, e2eParams.Init(e2eParams.StandardBeaconCount))
|
||||
|
||||
testConfig := &types.E2EConfig{
|
||||
BeaconFlags: []string{},
|
||||
BeaconFlags: []string{
|
||||
"--slasher",
|
||||
},
|
||||
ValidatorFlags: []string{},
|
||||
EpochsToRun: 4,
|
||||
TestSync: false,
|
||||
TestSlasher: true,
|
||||
TestDeposits: false,
|
||||
Evaluators: []types.Evaluator{
|
||||
ev.PeersConnect,
|
||||
ev.HealthzCheck,
|
||||
ev.ValidatorsSlashed,
|
||||
ev.SlashedValidatorsLoseBalance,
|
||||
ev.InjectDoubleVote,
|
||||
ev.ProposeDoubleBlock,
|
||||
ev.ValidatorsSlashedAfterEpoch(4),
|
||||
ev.SlashedValidatorsLoseBalanceAfterEpoch(4),
|
||||
ev.InjectDoubleVoteOnEpoch(2),
|
||||
ev.InjectDoubleBlockOnEpoch(2),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@ type params struct {
|
||||
BeaconNodeMetricsPort int
|
||||
ValidatorMetricsPort int
|
||||
ValidatorGatewayPort int
|
||||
SlasherRPCPort int
|
||||
SlasherMetricsPort int
|
||||
}
|
||||
|
||||
// TestParams is the globally accessible var for getting config elements.
|
||||
@@ -42,9 +40,6 @@ var TracingRequestSinkFileName = "tracing-http-requests.log.gz"
|
||||
// BeaconNodeLogFileName is the file name used for the beacon chain node logs.
|
||||
var BeaconNodeLogFileName = "beacon-%d.log"
|
||||
|
||||
// SlasherLogFileName is the file name used for the slasher client logs.
|
||||
var SlasherLogFileName = "slasher-%d.log"
|
||||
|
||||
// ValidatorLogFileName is the file name used for the validator client logs.
|
||||
var ValidatorLogFileName = "vals-%d.log"
|
||||
|
||||
@@ -82,8 +77,6 @@ func Init(beaconNodeCount int) error {
|
||||
BeaconNodeMetricsPort: 5100 + testIndex*100,
|
||||
ValidatorMetricsPort: 6100 + testIndex*100,
|
||||
ValidatorGatewayPort: 7150 + testIndex*100,
|
||||
SlasherRPCPort: 7100 + testIndex*100,
|
||||
SlasherMetricsPort: 8100 + testIndex*100,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
78
testing/endtoend/slasher_simulator_e2e_test.go
Normal file
78
testing/endtoend/slasher_simulator_e2e_test.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package endtoend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/crypto/bls"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
slashersimulator "github.com/prysmaticlabs/prysm/testing/slasher/simulator"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func TestEndToEnd_SlasherSimulator(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
ctx := context.Background()
|
||||
|
||||
// Run for 10 epochs if not in long-running to confirm long-running has no issues.
|
||||
simulatorParams := slashersimulator.DefaultParams()
|
||||
var err error
|
||||
epochStr, longRunning := os.LookupEnv("E2E_EPOCHS")
|
||||
if longRunning {
|
||||
epochsToRun, err := strconv.Atoi(epochStr)
|
||||
require.NoError(t, err)
|
||||
simulatorParams.NumEpochs = uint64(epochsToRun)
|
||||
}
|
||||
|
||||
slasherDB := dbtest.SetupSlasherDB(t)
|
||||
beaconState, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
|
||||
// We setup validators in the beacon state along with their
|
||||
// private keys used to generate valid signatures in generated objects.
|
||||
validators := make([]*ethpb.Validator, simulatorParams.NumValidators)
|
||||
privKeys := make(map[types.ValidatorIndex]bls.SecretKey)
|
||||
for valIdx := range validators {
|
||||
privKey, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
privKeys[types.ValidatorIndex(valIdx)] = privKey
|
||||
validators[valIdx] = ðpb.Validator{
|
||||
PublicKey: privKey.PublicKey().Marshal(),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
}
|
||||
}
|
||||
err = beaconState.SetValidators(validators)
|
||||
require.NoError(t, err)
|
||||
|
||||
mockChain := &mock.ChainService{State: beaconState}
|
||||
gen := stategen.NewMockService()
|
||||
gen.AddStateForRoot(beaconState, [32]byte{})
|
||||
|
||||
sim, err := slashersimulator.New(ctx, &slashersimulator.ServiceConfig{
|
||||
Params: simulatorParams,
|
||||
Database: slasherDB,
|
||||
StateNotifier: &mock.MockStateNotifier{},
|
||||
HeadStateFetcher: mockChain,
|
||||
AttestationStateFetcher: mockChain,
|
||||
StateGen: gen,
|
||||
PrivateKeysByValidatorIndex: privKeys,
|
||||
SlashingsPool: &slashings.PoolMock{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
sim.Start()
|
||||
err = sim.Stop()
|
||||
require.NoError(t, err)
|
||||
require.LogsDoNotContain(t, hook, "ERROR")
|
||||
require.LogsDoNotContain(t, hook, "Did not detect")
|
||||
require.LogsContain(t, hook, "Correctly detected simulated proposer slashing")
|
||||
require.LogsContain(t, hook, "Correctly detected simulated attester slashing")
|
||||
}
|
||||
@@ -15,7 +15,6 @@ type E2EConfig struct {
|
||||
UsePrysmShValidator bool
|
||||
UsePprof bool
|
||||
TestDeposits bool
|
||||
TestSlasher bool
|
||||
EpochsToRun uint64
|
||||
TracingSinkEndpoint string
|
||||
Evaluators []Evaluator
|
||||
|
||||
@@ -10,7 +10,7 @@ go_library(
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/testing/slasher/simulator",
|
||||
visibility = [
|
||||
"//endtoend:__subpackages__",
|
||||
"//testing/endtoend:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//async/event:go_default_library",
|
||||
|
||||
@@ -247,7 +247,6 @@ func DeterministicEth1Data(size int) (*ethpb.Eth1Data, error) {
|
||||
|
||||
// DeterministicGenesisState returns a genesis state made using the deterministic deposits.
|
||||
func DeterministicGenesisState(t testing.TB, numValidators uint64) (state.BeaconState, []bls.SecretKey) {
|
||||
resetCache()
|
||||
deposits, privKeys, err := DeterministicDepositsAndKeys(numValidators)
|
||||
if err != nil {
|
||||
t.Fatal(errors.Wrapf(err, "failed to get %d deposits", numValidators))
|
||||
@@ -290,6 +289,8 @@ func DepositTrieFromDeposits(deposits []*ethpb.Deposit) (*trie.SparseMerkleTrie,
|
||||
|
||||
// resetCache clears out the old trie, private keys and deposits.
|
||||
func resetCache() {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
t = nil
|
||||
privKeys = []bls.SecretKey{}
|
||||
cachedDeposits = []*ethpb.Deposit{}
|
||||
|
||||
Reference in New Issue
Block a user