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  }