mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-23 11:57:18 +00:00
d17996f8b0
* Update V3 from V4 * Fix build v3 -> v4 * Update ssz * Update beacon_chain.pb.go * Fix formatter import * Update update-mockgen.sh comment to v4 * Fix conflicts. Pass build and tests * Fix test
99 lines
3.6 KiB
Go
99 lines
3.6 KiB
Go
package client
|
||
|
||
import (
|
||
"context"
|
||
"encoding/hex"
|
||
"fmt"
|
||
|
||
"github.com/pkg/errors"
|
||
"github.com/prysmaticlabs/prysm/v4/config/features"
|
||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||
"github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/slashings"
|
||
"github.com/prysmaticlabs/prysm/v4/validator/db/kv"
|
||
"go.opencensus.io/trace"
|
||
)
|
||
|
||
var failedAttLocalProtectionErr = "attempted to make slashable attestation, rejected by local slashing protection"
|
||
var failedPostAttSignExternalErr = "attempted to make slashable attestation, rejected by external slasher service"
|
||
|
||
// Checks if an attestation is slashable by comparing it with the attesting
|
||
// history for the given public key in our DB. If it is not, we then update the history
|
||
// with new values and save it to the database.
|
||
func (v *validator) slashableAttestationCheck(
|
||
ctx context.Context,
|
||
indexedAtt *ethpb.IndexedAttestation,
|
||
pubKey [fieldparams.BLSPubkeyLength]byte,
|
||
signingRoot [32]byte,
|
||
) error {
|
||
ctx, span := trace.StartSpan(ctx, "validator.postAttSignUpdate")
|
||
defer span.End()
|
||
|
||
// Based on EIP3076, validator should refuse to sign any attestation with source epoch less
|
||
// than the minimum source epoch present in that signer’s attestations.
|
||
lowestSourceEpoch, exists, err := v.db.LowestSignedSourceEpoch(ctx, pubKey)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if exists && indexedAtt.Data.Source.Epoch < lowestSourceEpoch {
|
||
return fmt.Errorf(
|
||
"could not sign attestation lower than lowest source epoch in db, %d < %d",
|
||
indexedAtt.Data.Source.Epoch,
|
||
lowestSourceEpoch,
|
||
)
|
||
}
|
||
existingSigningRoot, err := v.db.SigningRootAtTargetEpoch(ctx, pubKey, indexedAtt.Data.Target.Epoch)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
signingRootsDiffer := slashings.SigningRootsDiffer(existingSigningRoot, signingRoot)
|
||
|
||
// Based on EIP3076, validator should refuse to sign any attestation with target epoch less
|
||
// than or equal to the minimum target epoch present in that signer’s attestations.
|
||
lowestTargetEpoch, exists, err := v.db.LowestSignedTargetEpoch(ctx, pubKey)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if signingRootsDiffer && exists && indexedAtt.Data.Target.Epoch <= lowestTargetEpoch {
|
||
return fmt.Errorf(
|
||
"could not sign attestation lower than or equal to lowest target epoch in db, %d <= %d",
|
||
indexedAtt.Data.Target.Epoch,
|
||
lowestTargetEpoch,
|
||
)
|
||
}
|
||
fmtKey := "0x" + hex.EncodeToString(pubKey[:])
|
||
slashingKind, err := v.db.CheckSlashableAttestation(ctx, pubKey, signingRoot, indexedAtt)
|
||
if err != nil {
|
||
if v.emitAccountMetrics {
|
||
ValidatorAttestFailVec.WithLabelValues(fmtKey).Inc()
|
||
}
|
||
switch slashingKind {
|
||
case kv.DoubleVote:
|
||
log.Warn("Attestation is slashable as it is a double vote")
|
||
case kv.SurroundingVote:
|
||
log.Warn("Attestation is slashable as it is surrounding a previous attestation")
|
||
case kv.SurroundedVote:
|
||
log.Warn("Attestation is slashable as it is surrounded by a previous attestation")
|
||
}
|
||
return errors.Wrap(err, failedAttLocalProtectionErr)
|
||
}
|
||
|
||
if err := v.db.SaveAttestationForPubKey(ctx, pubKey, signingRoot, indexedAtt); err != nil {
|
||
return errors.Wrap(err, "could not save attestation history for validator public key")
|
||
}
|
||
|
||
if features.Get().RemoteSlasherProtection {
|
||
slashing, err := v.slashingProtectionClient.IsSlashableAttestation(ctx, indexedAtt)
|
||
if err != nil {
|
||
return errors.Wrap(err, "could not check if attestation is slashable")
|
||
}
|
||
if slashing != nil && len(slashing.AttesterSlashings) > 0 {
|
||
if v.emitAccountMetrics {
|
||
ValidatorAttestFailVecSlasher.WithLabelValues(fmtKey).Inc()
|
||
}
|
||
return errors.New(failedPostAttSignExternalErr)
|
||
}
|
||
}
|
||
return nil
|
||
}
|