github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/core/epoch/precompute/attestation.go (about)

     1  package precompute
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  
     7  	"github.com/pkg/errors"
     8  	types "github.com/prysmaticlabs/eth2-types"
     9  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    10  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
    11  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    12  	"github.com/prysmaticlabs/prysm/shared/attestationutil"
    13  	"github.com/prysmaticlabs/prysm/shared/params"
    14  	"github.com/prysmaticlabs/prysm/shared/traceutil"
    15  	"go.opencensus.io/trace"
    16  )
    17  
    18  // ProcessAttestations process the attestations in state and update individual validator's pre computes,
    19  // it also tracks and updates epoch attesting balances.
    20  func ProcessAttestations(
    21  	ctx context.Context,
    22  	state iface.ReadOnlyBeaconState,
    23  	vp []*Validator,
    24  	pBal *Balance,
    25  ) ([]*Validator, *Balance, error) {
    26  	ctx, span := trace.StartSpan(ctx, "precomputeEpoch.ProcessAttestations")
    27  	defer span.End()
    28  
    29  	v := &Validator{}
    30  	var err error
    31  
    32  	prevAtt, err := state.PreviousEpochAttestations()
    33  	if err != nil {
    34  		return nil, nil, err
    35  	}
    36  	curAtt, err := state.CurrentEpochAttestations()
    37  	if err != nil {
    38  		return nil, nil, err
    39  	}
    40  	for _, a := range append(prevAtt, curAtt...) {
    41  		if a.InclusionDelay == 0 {
    42  			return nil, nil, errors.New("attestation with inclusion delay of 0")
    43  		}
    44  		v.IsCurrentEpochAttester, v.IsCurrentEpochTargetAttester, err = AttestedCurrentEpoch(state, a)
    45  		if err != nil {
    46  			traceutil.AnnotateError(span, err)
    47  			return nil, nil, errors.Wrap(err, "could not check validator attested current epoch")
    48  		}
    49  		v.IsPrevEpochAttester, v.IsPrevEpochTargetAttester, v.IsPrevEpochHeadAttester, err = AttestedPrevEpoch(state, a)
    50  		if err != nil {
    51  			traceutil.AnnotateError(span, err)
    52  			return nil, nil, errors.Wrap(err, "could not check validator attested previous epoch")
    53  		}
    54  
    55  		committee, err := helpers.BeaconCommitteeFromState(state, a.Data.Slot, a.Data.CommitteeIndex)
    56  		if err != nil {
    57  			return nil, nil, err
    58  		}
    59  		indices, err := attestationutil.AttestingIndices(a.AggregationBits, committee)
    60  		if err != nil {
    61  			return nil, nil, err
    62  		}
    63  		vp = UpdateValidator(vp, v, indices, a, a.Data.Slot)
    64  	}
    65  
    66  	pBal = UpdateBalance(vp, pBal)
    67  
    68  	return vp, pBal, nil
    69  }
    70  
    71  // AttestedCurrentEpoch returns true if attestation `a` attested once in current epoch and/or epoch boundary block.
    72  func AttestedCurrentEpoch(s iface.ReadOnlyBeaconState, a *pb.PendingAttestation) (bool, bool, error) {
    73  	currentEpoch := helpers.CurrentEpoch(s)
    74  	var votedCurrentEpoch, votedTarget bool
    75  	// Did validator vote current epoch.
    76  	if a.Data.Target.Epoch == currentEpoch {
    77  		votedCurrentEpoch = true
    78  		same, err := SameTarget(s, a, currentEpoch)
    79  		if err != nil {
    80  			return false, false, err
    81  		}
    82  		if same {
    83  			votedTarget = true
    84  		}
    85  	}
    86  	return votedCurrentEpoch, votedTarget, nil
    87  }
    88  
    89  // AttestedPrevEpoch returns true if attestation `a` attested once in previous epoch and epoch boundary block and/or the same head.
    90  func AttestedPrevEpoch(s iface.ReadOnlyBeaconState, a *pb.PendingAttestation) (bool, bool, bool, error) {
    91  	prevEpoch := helpers.PrevEpoch(s)
    92  	var votedPrevEpoch, votedTarget, votedHead bool
    93  	// Did validator vote previous epoch.
    94  	if a.Data.Target.Epoch == prevEpoch {
    95  		votedPrevEpoch = true
    96  		same, err := SameTarget(s, a, prevEpoch)
    97  		if err != nil {
    98  			return false, false, false, errors.Wrap(err, "could not check same target")
    99  		}
   100  		if same {
   101  			votedTarget = true
   102  		}
   103  
   104  		if votedTarget {
   105  			same, err = SameHead(s, a)
   106  			if err != nil {
   107  				return false, false, false, errors.Wrap(err, "could not check same head")
   108  			}
   109  			if same {
   110  				votedHead = true
   111  			}
   112  		}
   113  	}
   114  	return votedPrevEpoch, votedTarget, votedHead, nil
   115  }
   116  
   117  // SameTarget returns true if attestation `a` attested to the same target block in state.
   118  func SameTarget(state iface.ReadOnlyBeaconState, a *pb.PendingAttestation, e types.Epoch) (bool, error) {
   119  	r, err := helpers.BlockRoot(state, e)
   120  	if err != nil {
   121  		return false, err
   122  	}
   123  	if bytes.Equal(a.Data.Target.Root, r) {
   124  		return true, nil
   125  	}
   126  	return false, nil
   127  }
   128  
   129  // SameHead returns true if attestation `a` attested to the same block by attestation slot in state.
   130  func SameHead(state iface.ReadOnlyBeaconState, a *pb.PendingAttestation) (bool, error) {
   131  	r, err := helpers.BlockRootAtSlot(state, a.Data.Slot)
   132  	if err != nil {
   133  		return false, err
   134  	}
   135  	if bytes.Equal(a.Data.BeaconBlockRoot, r) {
   136  		return true, nil
   137  	}
   138  	return false, nil
   139  }
   140  
   141  // UpdateValidator updates pre computed validator store.
   142  func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *pb.PendingAttestation, aSlot types.Slot) []*Validator {
   143  	inclusionSlot := aSlot + a.InclusionDelay
   144  
   145  	for _, i := range indices {
   146  		if record.IsCurrentEpochAttester {
   147  			vp[i].IsCurrentEpochAttester = true
   148  		}
   149  		if record.IsCurrentEpochTargetAttester {
   150  			vp[i].IsCurrentEpochTargetAttester = true
   151  		}
   152  		if record.IsPrevEpochAttester {
   153  			vp[i].IsPrevEpochAttester = true
   154  			// Update attestation inclusion info if inclusion slot is lower than before
   155  			if inclusionSlot < vp[i].InclusionSlot {
   156  				vp[i].InclusionSlot = aSlot + a.InclusionDelay
   157  				vp[i].InclusionDistance = a.InclusionDelay
   158  				vp[i].ProposerIndex = a.ProposerIndex
   159  			}
   160  		}
   161  		if record.IsPrevEpochTargetAttester {
   162  			vp[i].IsPrevEpochTargetAttester = true
   163  		}
   164  		if record.IsPrevEpochHeadAttester {
   165  			vp[i].IsPrevEpochHeadAttester = true
   166  		}
   167  	}
   168  	return vp
   169  }
   170  
   171  // UpdateBalance updates pre computed balance store.
   172  func UpdateBalance(vp []*Validator, bBal *Balance) *Balance {
   173  	for _, v := range vp {
   174  		if !v.IsSlashed {
   175  			if v.IsCurrentEpochAttester {
   176  				bBal.CurrentEpochAttested += v.CurrentEpochEffectiveBalance
   177  			}
   178  			if v.IsCurrentEpochTargetAttester {
   179  				bBal.CurrentEpochTargetAttested += v.CurrentEpochEffectiveBalance
   180  			}
   181  			if v.IsPrevEpochAttester {
   182  				bBal.PrevEpochAttested += v.CurrentEpochEffectiveBalance
   183  			}
   184  			if v.IsPrevEpochTargetAttester {
   185  				bBal.PrevEpochTargetAttested += v.CurrentEpochEffectiveBalance
   186  			}
   187  			if v.IsPrevEpochHeadAttester {
   188  				bBal.PrevEpochHeadAttested += v.CurrentEpochEffectiveBalance
   189  			}
   190  		}
   191  	}
   192  
   193  	return EnsureBalancesLowerBound(bBal)
   194  }
   195  
   196  // EnsureBalancesLowerBound ensures all the balances such as active current epoch, active previous epoch and more
   197  // have EffectiveBalanceIncrement(1 eth) as a lower bound.
   198  func EnsureBalancesLowerBound(bBal *Balance) *Balance {
   199  	ebi := params.BeaconConfig().EffectiveBalanceIncrement
   200  	if ebi > bBal.ActiveCurrentEpoch {
   201  		bBal.ActiveCurrentEpoch = ebi
   202  	}
   203  	if ebi > bBal.ActivePrevEpoch {
   204  		bBal.ActivePrevEpoch = ebi
   205  	}
   206  	if ebi > bBal.CurrentEpochAttested {
   207  		bBal.CurrentEpochAttested = ebi
   208  	}
   209  	if ebi > bBal.CurrentEpochTargetAttested {
   210  		bBal.CurrentEpochTargetAttested = ebi
   211  	}
   212  	if ebi > bBal.PrevEpochAttested {
   213  		bBal.PrevEpochAttested = ebi
   214  	}
   215  	if ebi > bBal.PrevEpochTargetAttested {
   216  		bBal.PrevEpochTargetAttested = ebi
   217  	}
   218  	if ebi > bBal.PrevEpochHeadAttested {
   219  		bBal.PrevEpochHeadAttested = ebi
   220  	}
   221  	return bBal
   222  }