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 }