github.com/prysmaticlabs/prysm@v1.4.4/validator/client/attest_protect.go (about)

     1  package client
     2  
     3  import (
     4  	"context"
     5  	"encoding/hex"
     6  	"fmt"
     7  
     8  	"github.com/pkg/errors"
     9  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    10  	"github.com/prysmaticlabs/prysm/shared/featureconfig"
    11  	"github.com/prysmaticlabs/prysm/shared/slashutil"
    12  	"github.com/prysmaticlabs/prysm/validator/db/kv"
    13  	"go.opencensus.io/trace"
    14  )
    15  
    16  var failedAttLocalProtectionErr = "attempted to make slashable attestation, rejected by local slashing protection"
    17  var failedPostAttSignExternalErr = "attempted to make slashable attestation, rejected by external slasher service"
    18  
    19  // Checks if an attestation is slashable by comparing it with the attesting
    20  // history for the given public key in our DB. If it is not, we then update the history
    21  // with new values and save it to the database.
    22  func (v *validator) slashableAttestationCheck(
    23  	ctx context.Context,
    24  	indexedAtt *ethpb.IndexedAttestation,
    25  	pubKey [48]byte,
    26  	signingRoot [32]byte,
    27  ) error {
    28  	ctx, span := trace.StartSpan(ctx, "validator.postAttSignUpdate")
    29  	defer span.End()
    30  
    31  	// Based on EIP3076, validator should refuse to sign any attestation with source epoch less
    32  	// than the minimum source epoch present in that signer’s attestations.
    33  	lowestSourceEpoch, exists, err := v.db.LowestSignedSourceEpoch(ctx, pubKey)
    34  	if err != nil {
    35  		return err
    36  	}
    37  	if exists && indexedAtt.Data.Source.Epoch < lowestSourceEpoch {
    38  		return fmt.Errorf(
    39  			"could not sign attestation lower than lowest source epoch in db, %d < %d",
    40  			indexedAtt.Data.Source.Epoch,
    41  			lowestSourceEpoch,
    42  		)
    43  	}
    44  	existingSigningRoot, err := v.db.SigningRootAtTargetEpoch(ctx, pubKey, indexedAtt.Data.Target.Epoch)
    45  	if err != nil {
    46  		return err
    47  	}
    48  	signingRootsDiffer := slashutil.SigningRootsDiffer(existingSigningRoot, signingRoot)
    49  
    50  	// Based on EIP3076, validator should refuse to sign any attestation with target epoch less
    51  	// than or equal to the minimum target epoch present in that signer’s attestations.
    52  	lowestTargetEpoch, exists, err := v.db.LowestSignedTargetEpoch(ctx, pubKey)
    53  	if err != nil {
    54  		return err
    55  	}
    56  	if signingRootsDiffer && exists && indexedAtt.Data.Target.Epoch <= lowestTargetEpoch {
    57  		return fmt.Errorf(
    58  			"could not sign attestation lower than or equal to lowest target epoch in db, %d <= %d",
    59  			indexedAtt.Data.Target.Epoch,
    60  			lowestTargetEpoch,
    61  		)
    62  	}
    63  	fmtKey := "0x" + hex.EncodeToString(pubKey[:])
    64  	slashingKind, err := v.db.CheckSlashableAttestation(ctx, pubKey, signingRoot, indexedAtt)
    65  	if err != nil {
    66  		if v.emitAccountMetrics {
    67  			ValidatorAttestFailVec.WithLabelValues(fmtKey).Inc()
    68  		}
    69  		switch slashingKind {
    70  		case kv.DoubleVote:
    71  			log.Warn("Attestation is slashable as it is a double vote")
    72  		case kv.SurroundingVote:
    73  			log.Warn("Attestation is slashable as it is surrounding a previous attestation")
    74  		case kv.SurroundedVote:
    75  			log.Warn("Attestation is slashable as it is surrounded by a previous attestation")
    76  		}
    77  		return errors.Wrap(err, failedAttLocalProtectionErr)
    78  	}
    79  
    80  	if err := v.db.SaveAttestationForPubKey(ctx, pubKey, signingRoot, indexedAtt); err != nil {
    81  		return errors.Wrap(err, "could not save attestation history for validator public key")
    82  	}
    83  
    84  	if featureconfig.Get().SlasherProtection && v.protector != nil {
    85  		if !v.protector.CommitAttestation(ctx, indexedAtt) {
    86  			if v.emitAccountMetrics {
    87  				ValidatorAttestFailVecSlasher.WithLabelValues(fmtKey).Inc()
    88  			}
    89  			return errors.New(failedPostAttSignExternalErr)
    90  		}
    91  	}
    92  	return nil
    93  }