mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 07:58:22 -05:00
Add Doppelganger E2E (#9239)
* add current fixes * fix prev release * Update endtoend/endtoend_test.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update endtoend/endtoend_test.go Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * Update endtoend/endtoend_test.go Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * review comments for radek and raul Co-authored-by: Radosław Kapka <rkapka@wp.pl> Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
@@ -35,6 +35,9 @@ const (
|
||||
// allNodesStartTimeout defines period after which nodes are considered
|
||||
// stalled (safety measure for nodes stuck at startup, shouldn't normally happen).
|
||||
allNodesStartTimeout = 5 * time.Minute
|
||||
|
||||
// errGeneralCode is used to represent the string value for all general process errors.
|
||||
errGeneralCode = "exit status 1"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -181,7 +184,10 @@ func (r *testRunner) run() {
|
||||
if !config.TestSync {
|
||||
return nil
|
||||
}
|
||||
return r.testBeaconChainSync(ctx, g, conns, tickingStartTime, bootNode.ENR())
|
||||
if err := r.testBeaconChainSync(ctx, g, conns, tickingStartTime, bootNode.ENR()); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.testDoppelGangerProtection(ctx)
|
||||
})
|
||||
|
||||
if err := g.Wait(); err != nil && !errors.Is(err, context.Canceled) {
|
||||
@@ -296,3 +302,43 @@ func (r *testRunner) testBeaconChainSync(ctx context.Context, g *errgroup.Group,
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *testRunner) testDoppelGangerProtection(ctx context.Context) error {
|
||||
// Exit if we are running from the previous release.
|
||||
if r.config.UsePrysmShValidator {
|
||||
return nil
|
||||
}
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
// Follow same parameters as older validators.
|
||||
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
|
||||
valIndex := beaconNodeNum + 1
|
||||
|
||||
// Replicate starting up validator client 0 to test doppleganger protection.
|
||||
valNode := components.NewValidatorNode(r.config, validatorsPerNode, valIndex, validatorsPerNode*0)
|
||||
g.Go(func() error {
|
||||
return valNode.Start(ctx)
|
||||
})
|
||||
if err := helpers.ComponentsStarted(ctx, []e2etypes.ComponentRunner{valNode}); err != nil {
|
||||
return fmt.Errorf("validator not ready: %w", err)
|
||||
}
|
||||
logFile, err := os.Create(path.Join(e2e.TestParams.LogPath, fmt.Sprintf(e2e.ValidatorLogFileName, valIndex)))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to open log file: %v", err)
|
||||
}
|
||||
r.t.Run("doppelganger found", func(t *testing.T) {
|
||||
assert.NoError(t, helpers.WaitForTextInFile(logFile, "Duplicate instances exists in the network for validator keys"), "Failed to carry out doppelganger check correctly")
|
||||
})
|
||||
if r.t.Failed() {
|
||||
return errors.New("doppelganger was unable to be found")
|
||||
}
|
||||
// Expect an abrupt exit for the validator client.
|
||||
if err := g.Wait(); err == nil || !strings.Contains(err.Error(), errGeneralCode) {
|
||||
return fmt.Errorf("wanted an error of %s but received %v", errGeneralCode, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -387,7 +387,8 @@ func (v *validator) CheckDoppelGanger(ctx context.Context) error {
|
||||
}
|
||||
req := ðpb.DoppelGangerRequest{ValidatorRequests: []*ethpb.DoppelGangerRequest_ValidatorRequest{}}
|
||||
for _, pkey := range pubkeys {
|
||||
attRec, err := v.db.AttestationHistoryForPubKey(ctx, pkey)
|
||||
copiedKey := pkey
|
||||
attRec, err := v.db.AttestationHistoryForPubKey(ctx, copiedKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -396,14 +397,14 @@ func (v *validator) CheckDoppelGanger(ctx context.Context) error {
|
||||
// value for the request epoch and root.
|
||||
req.ValidatorRequests = append(req.ValidatorRequests,
|
||||
ðpb.DoppelGangerRequest_ValidatorRequest{
|
||||
PublicKey: pkey[:],
|
||||
PublicKey: copiedKey[:],
|
||||
Epoch: 0,
|
||||
SignedRoot: make([]byte, 32),
|
||||
})
|
||||
continue
|
||||
}
|
||||
r := retrieveLatestRecord(attRec)
|
||||
if pkey != r.PubKey {
|
||||
if copiedKey != r.PubKey {
|
||||
return errors.New("attestation record mismatched public key")
|
||||
}
|
||||
req.ValidatorRequests = append(req.ValidatorRequests,
|
||||
@@ -429,7 +430,9 @@ func buildDuplicateError(respones []*ethpb.DoppelGangerResponse_ValidatorRespons
|
||||
duplicates := make([][]byte, 0)
|
||||
for _, valRes := range respones {
|
||||
if valRes.DuplicateExists {
|
||||
duplicates = append(duplicates, valRes.PublicKey)
|
||||
copiedKey := [48]byte{}
|
||||
copy(copiedKey[:], valRes.PublicKey)
|
||||
duplicates = append(duplicates, copiedKey[:])
|
||||
}
|
||||
}
|
||||
if len(duplicates) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user