github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/sync/validate_attester_slashing.go (about) 1 package sync 2 3 import ( 4 "context" 5 6 "github.com/libp2p/go-libp2p-core/peer" 7 pubsub "github.com/libp2p/go-libp2p-pubsub" 8 "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" 9 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 10 "github.com/prysmaticlabs/prysm/shared/sliceutil" 11 "github.com/prysmaticlabs/prysm/shared/traceutil" 12 "go.opencensus.io/trace" 13 ) 14 15 // Clients who receive an attester slashing on this topic MUST validate the conditions within VerifyAttesterSlashing before 16 // forwarding it across the network. 17 func (s *Service) validateAttesterSlashing(ctx context.Context, pid peer.ID, msg *pubsub.Message) pubsub.ValidationResult { 18 // Validation runs on publish (not just subscriptions), so we should approve any message from 19 // ourselves. 20 if pid == s.cfg.P2P.PeerID() { 21 return pubsub.ValidationAccept 22 } 23 24 // The head state will be too far away to validate any slashing. 25 if s.cfg.InitialSync.Syncing() { 26 return pubsub.ValidationIgnore 27 } 28 29 ctx, span := trace.StartSpan(ctx, "sync.validateAttesterSlashing") 30 defer span.End() 31 32 m, err := s.decodePubsubMessage(msg) 33 if err != nil { 34 log.WithError(err).Debug("Could not decode message") 35 traceutil.AnnotateError(span, err) 36 return pubsub.ValidationReject 37 } 38 slashing, ok := m.(*ethpb.AttesterSlashing) 39 if !ok { 40 return pubsub.ValidationReject 41 } 42 43 if slashing == nil || slashing.Attestation_1 == nil || slashing.Attestation_2 == nil { 44 return pubsub.ValidationReject 45 } 46 if s.hasSeenAttesterSlashingIndices(slashing.Attestation_1.AttestingIndices, slashing.Attestation_2.AttestingIndices) { 47 return pubsub.ValidationIgnore 48 } 49 50 headState, err := s.cfg.Chain.HeadState(ctx) 51 if err != nil { 52 return pubsub.ValidationIgnore 53 } 54 if err := blocks.VerifyAttesterSlashing(ctx, headState, slashing); err != nil { 55 return pubsub.ValidationReject 56 } 57 58 msg.ValidatorData = slashing // Used in downstream subscriber 59 return pubsub.ValidationAccept 60 } 61 62 // Returns true if the node has already received a valid attester slashing with the attesting indices. 63 func (s *Service) hasSeenAttesterSlashingIndices(indices1, indices2 []uint64) bool { 64 slashableIndices := sliceutil.IntersectionUint64(indices1, indices2) 65 66 s.seenAttesterSlashingLock.RLock() 67 defer s.seenAttesterSlashingLock.RUnlock() 68 69 // Return false if any of the slashing index has not been seen before. (i.e. not in cache) 70 for _, index := range slashableIndices { 71 if !s.seenAttesterSlashingCache[index] { 72 return false 73 } 74 } 75 76 return true 77 } 78 79 // Set attester slashing indices in attester slashing cache. 80 func (s *Service) setAttesterSlashingIndicesSeen(indices1, indices2 []uint64) { 81 slashableIndices := sliceutil.IntersectionUint64(indices1, indices2) 82 83 s.seenAttesterSlashingLock.Lock() 84 defer s.seenAttesterSlashingLock.Unlock() 85 86 for _, index := range slashableIndices { 87 s.seenAttesterSlashingCache[index] = true 88 } 89 }