mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-07 10:12:19 +00:00
14b3181e67
* more spanner additions * implement iface * begin implement * wrapped up spanner functions * rem interface * added in necessary comments * comments on enums * begin adding tests * plug in surround vote detection * saved indexed db implementation * finally plugin slashing for historical data * Small fixes * add in all gazelle * save incoming new functions * resolve todo * fix broken test channel item * tests passing when fixing certain arguments and setups * Add comment and change unimplemented * find surround * added in gazelle * gazz * feedback from shay * fixed up naming * Update * Add tests for detectSurroundVotes * Remove logs * Fix slasher test * formatting * Remove unneeded condition * Test indices better * fixing broken build * pass tests * skip tests * imports * Update slasher/detection/attestations/attestations_test.go * Update slasher/beaconclient/historical_data_retrieval_test.go * Address comments * Rename function * Add comment for future optimization * Fix comment Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
103 lines
3.1 KiB
Go
103 lines
3.1 KiB
Go
package detection
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/pkg/errors"
|
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
|
"github.com/prysmaticlabs/prysm/slasher/detection/attestations/types"
|
|
)
|
|
|
|
func (ds *Service) detectAttesterSlashings(
|
|
ctx context.Context,
|
|
att *ethpb.IndexedAttestation,
|
|
) ([]*ethpb.AttesterSlashing, error) {
|
|
slashings := make([]*ethpb.AttesterSlashing, 0)
|
|
for i := 0; i < len(att.AttestingIndices); i++ {
|
|
valIdx := att.AttestingIndices[i]
|
|
surroundedAttSlashings, err := ds.detectSurroundVotes(ctx, valIdx, att)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not detect surround votes on attestation")
|
|
}
|
|
doubleAttSlashings, err := ds.detectDoubleVotes(ctx, att)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not detect double votes on attestation")
|
|
}
|
|
if len(surroundedAttSlashings) > 0 {
|
|
log.Infof("Found %d slashings for val idx %d", len(surroundedAttSlashings), valIdx)
|
|
}
|
|
newSlashings := append(surroundedAttSlashings, doubleAttSlashings...)
|
|
slashings = append(slashings, newSlashings...)
|
|
}
|
|
return slashings, nil
|
|
}
|
|
|
|
// detectDoubleVote --
|
|
// TODO(#4589): Implement.
|
|
func (ds *Service) detectDoubleVotes(
|
|
ctx context.Context,
|
|
att *ethpb.IndexedAttestation,
|
|
) ([]*ethpb.AttesterSlashing, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
// detectSurroundVotes cross references the passed in attestation with the requested validator's
|
|
// voting history in order to detect any possible surround votes.
|
|
func (ds *Service) detectSurroundVotes(
|
|
ctx context.Context,
|
|
validatorIdx uint64,
|
|
incomingAtt *ethpb.IndexedAttestation,
|
|
) ([]*ethpb.AttesterSlashing, error) {
|
|
res, err := ds.minMaxSpanDetector.DetectSlashingForValidator(
|
|
ctx,
|
|
validatorIdx,
|
|
incomingAtt.Data,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if res == nil {
|
|
return nil, nil
|
|
}
|
|
if res.Kind != types.SurroundVote {
|
|
return nil, nil
|
|
}
|
|
|
|
var slashings []*ethpb.AttesterSlashing
|
|
otherAtts, err := ds.slasherDB.IndexedAttestationsForEpoch(ctx, res.SlashableEpoch)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, att := range otherAtts {
|
|
if att.Data == nil {
|
|
continue
|
|
}
|
|
// If there are no shared indices, there is no validator to slash.
|
|
if len(sliceutil.IntersectionUint64(att.AttestingIndices, incomingAtt.AttestingIndices)) == 0 {
|
|
continue
|
|
}
|
|
|
|
if isSurrounding(incomingAtt, att) || isSurrounded(incomingAtt, att) {
|
|
slashings = append(slashings, ðpb.AttesterSlashing{
|
|
Attestation_1: att,
|
|
Attestation_2: incomingAtt,
|
|
})
|
|
}
|
|
}
|
|
if len(slashings) == 0 {
|
|
return nil, errors.New("unexpected false positive in surround vote detection")
|
|
}
|
|
return slashings, nil
|
|
}
|
|
|
|
func isSurrounding(incomingAtt *ethpb.IndexedAttestation, prevAtt *ethpb.IndexedAttestation) bool {
|
|
return incomingAtt.Data.Source.Epoch < prevAtt.Data.Source.Epoch &&
|
|
incomingAtt.Data.Target.Epoch > prevAtt.Data.Target.Epoch
|
|
}
|
|
|
|
func isSurrounded(incomingAtt *ethpb.IndexedAttestation, prevAtt *ethpb.IndexedAttestation) bool {
|
|
return incomingAtt.Data.Source.Epoch > prevAtt.Data.Source.Epoch &&
|
|
incomingAtt.Data.Target.Epoch < prevAtt.Data.Target.Epoch
|
|
}
|