github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/blockchain/process_attestation.go (about) 1 package blockchain 2 3 import ( 4 "context" 5 6 "github.com/pkg/errors" 7 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 8 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 9 "github.com/prysmaticlabs/prysm/shared/attestationutil" 10 "github.com/prysmaticlabs/prysm/shared/bytesutil" 11 "github.com/prysmaticlabs/prysm/shared/copyutil" 12 "github.com/prysmaticlabs/prysm/shared/params" 13 "github.com/prysmaticlabs/prysm/shared/timeutils" 14 "go.opencensus.io/trace" 15 ) 16 17 // onAttestation is called whenever an attestation is received, verifies the attestation is valid and saves 18 // it to the DB. As a stateless function, this does not hold nor delay attestation based on the spec descriptions. 19 // The delay is handled by the caller in `processAttestations`. 20 // 21 // Spec pseudocode definition: 22 // def on_attestation(store: Store, attestation: Attestation) -> None: 23 // """ 24 // Run ``on_attestation`` upon receiving a new ``attestation`` from either within a block or directly on the wire. 25 // 26 // An ``attestation`` that is asserted as invalid may be valid at a later time, 27 // consider scheduling it for later processing in such case. 28 // """ 29 // validate_on_attestation(store, attestation) 30 // store_target_checkpoint_state(store, attestation.data.target) 31 // 32 // # Get state at the `target` to fully validate attestation 33 // target_state = store.checkpoint_states[attestation.data.target] 34 // indexed_attestation = get_indexed_attestation(target_state, attestation) 35 // assert is_valid_indexed_attestation(target_state, indexed_attestation) 36 // 37 // # Update latest messages for attesting indices 38 // update_latest_messages(store, indexed_attestation.attesting_indices, attestation) 39 func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) error { 40 ctx, span := trace.StartSpan(ctx, "blockChain.onAttestation") 41 defer span.End() 42 43 if err := helpers.ValidateNilAttestation(a); err != nil { 44 return err 45 } 46 if err := helpers.ValidateSlotTargetEpoch(a.Data); err != nil { 47 return err 48 } 49 tgt := copyutil.CopyCheckpoint(a.Data.Target) 50 51 // Note that target root check is ignored here because it was performed in sync's validation pipeline: 52 // validate_aggregate_proof.go and validate_beacon_attestation.go 53 // If missing target root were to fail in this method, it would have just failed in `getAttPreState`. 54 55 // Retrieve attestation's data beacon block pre state. Advance pre state to latest epoch if necessary and 56 // save it to the cache. 57 baseState, err := s.getAttPreState(ctx, tgt) 58 if err != nil { 59 return err 60 } 61 62 genesisTime := baseState.GenesisTime() 63 64 // Verify attestation target is from current epoch or previous epoch. 65 if err := s.verifyAttTargetEpoch(ctx, genesisTime, uint64(timeutils.Now().Unix()), tgt); err != nil { 66 return err 67 } 68 69 // Verify attestation beacon block is known and not from the future. 70 if err := s.verifyBeaconBlock(ctx, a.Data); err != nil { 71 return errors.Wrap(err, "could not verify attestation beacon block") 72 } 73 74 // Note that LMG GHOST and FFG consistency check is ignored because it was performed in sync's validation pipeline: 75 // validate_aggregate_proof.go and validate_beacon_attestation.go 76 77 // Verify attestations can only affect the fork choice of subsequent slots. 78 if err := helpers.VerifySlotTime(genesisTime, a.Data.Slot+1, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil { 79 return err 80 } 81 82 // Use the target state to verify attesting indices are valid. 83 committee, err := helpers.BeaconCommitteeFromState(baseState, a.Data.Slot, a.Data.CommitteeIndex) 84 if err != nil { 85 return err 86 } 87 indexedAtt, err := attestationutil.ConvertToIndexed(ctx, a, committee) 88 if err != nil { 89 return err 90 } 91 if err := attestationutil.IsValidAttestationIndices(ctx, indexedAtt); err != nil { 92 return err 93 } 94 95 // Note that signature verification is ignored here because it was performed in sync's validation pipeline: 96 // validate_aggregate_proof.go and validate_beacon_attestation.go 97 // We assume trusted attestation in this function has verified signature. 98 99 // Update forkchoice store with the new attestation for updating weight. 100 s.cfg.ForkChoiceStore.ProcessAttestation(ctx, indexedAtt.AttestingIndices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch) 101 102 return nil 103 }