2019-10-17 00:48:26 +00:00
|
|
|
package precompute
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
2021-09-30 19:00:14 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
2021-07-23 16:11:21 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
2021-09-21 19:59:25 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/config/params"
|
2022-04-29 14:32:11 +00:00
|
|
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
2021-09-14 20:59:51 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
2021-07-29 21:45:17 +00:00
|
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
2021-09-20 16:17:03 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
2021-11-03 21:50:41 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/runtime/version"
|
2019-10-17 00:48:26 +00:00
|
|
|
"go.opencensus.io/trace"
|
|
|
|
)
|
|
|
|
|
|
|
|
// ProcessAttestations process the attestations in state and update individual validator's pre computes,
|
|
|
|
// it also tracks and updates epoch attesting balances.
|
|
|
|
func ProcessAttestations(
|
|
|
|
ctx context.Context,
|
2021-07-23 16:11:21 +00:00
|
|
|
state state.ReadOnlyBeaconState,
|
2019-10-17 00:48:26 +00:00
|
|
|
vp []*Validator,
|
2020-05-01 19:43:04 +00:00
|
|
|
pBal *Balance,
|
2020-01-31 20:57:01 +00:00
|
|
|
) ([]*Validator, *Balance, error) {
|
2019-10-17 00:48:26 +00:00
|
|
|
ctx, span := trace.StartSpan(ctx, "precomputeEpoch.ProcessAttestations")
|
|
|
|
defer span.End()
|
|
|
|
|
|
|
|
v := &Validator{}
|
|
|
|
var err error
|
2019-12-19 23:40:51 +00:00
|
|
|
|
2021-03-26 18:15:03 +00:00
|
|
|
prevAtt, err := state.PreviousEpochAttestations()
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
curAtt, err := state.CurrentEpochAttestations()
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
for _, a := range append(prevAtt, curAtt...) {
|
2020-07-19 16:38:45 +00:00
|
|
|
if a.InclusionDelay == 0 {
|
|
|
|
return nil, nil, errors.New("attestation with inclusion delay of 0")
|
|
|
|
}
|
2019-10-18 08:38:47 +00:00
|
|
|
v.IsCurrentEpochAttester, v.IsCurrentEpochTargetAttester, err = AttestedCurrentEpoch(state, a)
|
2019-10-17 00:48:26 +00:00
|
|
|
if err != nil {
|
2021-09-14 20:59:51 +00:00
|
|
|
tracing.AnnotateError(span, err)
|
2019-10-17 00:48:26 +00:00
|
|
|
return nil, nil, errors.Wrap(err, "could not check validator attested current epoch")
|
|
|
|
}
|
2019-10-18 08:38:47 +00:00
|
|
|
v.IsPrevEpochAttester, v.IsPrevEpochTargetAttester, v.IsPrevEpochHeadAttester, err = AttestedPrevEpoch(state, a)
|
2019-10-17 00:48:26 +00:00
|
|
|
if err != nil {
|
2021-09-14 20:59:51 +00:00
|
|
|
tracing.AnnotateError(span, err)
|
2019-10-17 00:48:26 +00:00
|
|
|
return nil, nil, errors.Wrap(err, "could not check validator attested previous epoch")
|
|
|
|
}
|
|
|
|
|
2021-09-26 15:27:57 +00:00
|
|
|
committee, err := helpers.BeaconCommitteeFromState(ctx, state, a.Data.Slot, a.Data.CommitteeIndex)
|
2019-12-15 05:02:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
2021-09-20 16:17:03 +00:00
|
|
|
indices, err := attestation.AttestingIndices(a.AggregationBits, committee)
|
2021-01-20 03:00:52 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
2019-11-11 22:03:44 +00:00
|
|
|
vp = UpdateValidator(vp, v, indices, a, a.Data.Slot)
|
2019-10-17 00:48:26 +00:00
|
|
|
}
|
|
|
|
|
2021-11-03 21:50:41 +00:00
|
|
|
pBal = UpdateBalance(vp, pBal, state.Version())
|
2019-10-17 00:48:26 +00:00
|
|
|
|
2020-05-01 19:43:04 +00:00
|
|
|
return vp, pBal, nil
|
2019-10-17 00:48:26 +00:00
|
|
|
}
|
|
|
|
|
2019-10-18 08:38:47 +00:00
|
|
|
// AttestedCurrentEpoch returns true if attestation `a` attested once in current epoch and/or epoch boundary block.
|
2021-07-29 21:45:17 +00:00
|
|
|
func AttestedCurrentEpoch(s state.ReadOnlyBeaconState, a *ethpb.PendingAttestation) (bool, bool, error) {
|
2021-09-30 19:00:14 +00:00
|
|
|
currentEpoch := time.CurrentEpoch(s)
|
2019-10-17 00:48:26 +00:00
|
|
|
var votedCurrentEpoch, votedTarget bool
|
|
|
|
// Did validator vote current epoch.
|
|
|
|
if a.Data.Target.Epoch == currentEpoch {
|
|
|
|
votedCurrentEpoch = true
|
2019-10-18 08:38:47 +00:00
|
|
|
same, err := SameTarget(s, a, currentEpoch)
|
2019-10-17 00:48:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, false, err
|
|
|
|
}
|
|
|
|
if same {
|
|
|
|
votedTarget = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return votedCurrentEpoch, votedTarget, nil
|
|
|
|
}
|
|
|
|
|
2019-10-18 08:38:47 +00:00
|
|
|
// AttestedPrevEpoch returns true if attestation `a` attested once in previous epoch and epoch boundary block and/or the same head.
|
2021-07-29 21:45:17 +00:00
|
|
|
func AttestedPrevEpoch(s state.ReadOnlyBeaconState, a *ethpb.PendingAttestation) (bool, bool, bool, error) {
|
2021-09-30 19:00:14 +00:00
|
|
|
prevEpoch := time.PrevEpoch(s)
|
2019-10-17 00:48:26 +00:00
|
|
|
var votedPrevEpoch, votedTarget, votedHead bool
|
|
|
|
// Did validator vote previous epoch.
|
|
|
|
if a.Data.Target.Epoch == prevEpoch {
|
|
|
|
votedPrevEpoch = true
|
2019-10-18 08:38:47 +00:00
|
|
|
same, err := SameTarget(s, a, prevEpoch)
|
2019-10-17 00:48:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, false, false, errors.Wrap(err, "could not check same target")
|
|
|
|
}
|
|
|
|
if same {
|
|
|
|
votedTarget = true
|
|
|
|
}
|
|
|
|
|
2020-06-09 22:40:48 +00:00
|
|
|
if votedTarget {
|
|
|
|
same, err = SameHead(s, a)
|
|
|
|
if err != nil {
|
|
|
|
return false, false, false, errors.Wrap(err, "could not check same head")
|
|
|
|
}
|
|
|
|
if same {
|
|
|
|
votedHead = true
|
|
|
|
}
|
2019-10-17 00:48:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return votedPrevEpoch, votedTarget, votedHead, nil
|
|
|
|
}
|
|
|
|
|
2019-10-18 08:38:47 +00:00
|
|
|
// SameTarget returns true if attestation `a` attested to the same target block in state.
|
2021-07-29 21:45:17 +00:00
|
|
|
func SameTarget(state state.ReadOnlyBeaconState, a *ethpb.PendingAttestation, e types.Epoch) (bool, error) {
|
2019-10-17 00:48:26 +00:00
|
|
|
r, err := helpers.BlockRoot(state, e)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
if bytes.Equal(a.Data.Target.Root, r) {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
2019-10-18 08:38:47 +00:00
|
|
|
// SameHead returns true if attestation `a` attested to the same block by attestation slot in state.
|
2021-07-29 21:45:17 +00:00
|
|
|
func SameHead(state state.ReadOnlyBeaconState, a *ethpb.PendingAttestation) (bool, error) {
|
2019-11-11 22:03:44 +00:00
|
|
|
r, err := helpers.BlockRootAtSlot(state, a.Data.Slot)
|
2019-10-17 00:48:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
if bytes.Equal(a.Data.BeaconBlockRoot, r) {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
2019-10-18 08:38:47 +00:00
|
|
|
// UpdateValidator updates pre computed validator store.
|
2021-07-29 21:45:17 +00:00
|
|
|
func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *ethpb.PendingAttestation, aSlot types.Slot) []*Validator {
|
2019-10-19 04:47:54 +00:00
|
|
|
inclusionSlot := aSlot + a.InclusionDelay
|
|
|
|
|
2019-10-17 00:48:26 +00:00
|
|
|
for _, i := range indices {
|
|
|
|
if record.IsCurrentEpochAttester {
|
|
|
|
vp[i].IsCurrentEpochAttester = true
|
|
|
|
}
|
|
|
|
if record.IsCurrentEpochTargetAttester {
|
|
|
|
vp[i].IsCurrentEpochTargetAttester = true
|
|
|
|
}
|
|
|
|
if record.IsPrevEpochAttester {
|
|
|
|
vp[i].IsPrevEpochAttester = true
|
2019-10-29 05:39:16 +00:00
|
|
|
// Update attestation inclusion info if inclusion slot is lower than before
|
|
|
|
if inclusionSlot < vp[i].InclusionSlot {
|
|
|
|
vp[i].InclusionSlot = aSlot + a.InclusionDelay
|
|
|
|
vp[i].InclusionDistance = a.InclusionDelay
|
|
|
|
vp[i].ProposerIndex = a.ProposerIndex
|
|
|
|
}
|
2019-10-17 00:48:26 +00:00
|
|
|
}
|
|
|
|
if record.IsPrevEpochTargetAttester {
|
|
|
|
vp[i].IsPrevEpochTargetAttester = true
|
|
|
|
}
|
|
|
|
if record.IsPrevEpochHeadAttester {
|
|
|
|
vp[i].IsPrevEpochHeadAttester = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return vp
|
|
|
|
}
|
|
|
|
|
2019-10-18 08:38:47 +00:00
|
|
|
// UpdateBalance updates pre computed balance store.
|
2021-11-03 21:50:41 +00:00
|
|
|
func UpdateBalance(vp []*Validator, bBal *Balance, stateVersion int) *Balance {
|
2019-10-17 00:48:26 +00:00
|
|
|
for _, v := range vp {
|
|
|
|
if !v.IsSlashed {
|
|
|
|
if v.IsCurrentEpochAttester {
|
2020-05-01 19:43:04 +00:00
|
|
|
bBal.CurrentEpochAttested += v.CurrentEpochEffectiveBalance
|
2019-10-17 00:48:26 +00:00
|
|
|
}
|
|
|
|
if v.IsCurrentEpochTargetAttester {
|
2020-05-01 19:43:04 +00:00
|
|
|
bBal.CurrentEpochTargetAttested += v.CurrentEpochEffectiveBalance
|
2019-10-17 00:48:26 +00:00
|
|
|
}
|
2021-11-03 21:50:41 +00:00
|
|
|
if stateVersion == version.Phase0 && v.IsPrevEpochAttester {
|
|
|
|
bBal.PrevEpochAttested += v.CurrentEpochEffectiveBalance
|
|
|
|
}
|
2022-01-10 16:47:30 +00:00
|
|
|
if (stateVersion == version.Altair || stateVersion == version.Bellatrix) && v.IsPrevEpochSourceAttester {
|
2020-05-01 19:43:04 +00:00
|
|
|
bBal.PrevEpochAttested += v.CurrentEpochEffectiveBalance
|
2019-10-17 00:48:26 +00:00
|
|
|
}
|
|
|
|
if v.IsPrevEpochTargetAttester {
|
2020-05-01 19:43:04 +00:00
|
|
|
bBal.PrevEpochTargetAttested += v.CurrentEpochEffectiveBalance
|
2019-10-17 00:48:26 +00:00
|
|
|
}
|
|
|
|
if v.IsPrevEpochHeadAttester {
|
2020-05-01 19:43:04 +00:00
|
|
|
bBal.PrevEpochHeadAttested += v.CurrentEpochEffectiveBalance
|
2019-10-17 00:48:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-09 22:40:48 +00:00
|
|
|
|
|
|
|
return EnsureBalancesLowerBound(bBal)
|
|
|
|
}
|
|
|
|
|
|
|
|
// EnsureBalancesLowerBound ensures all the balances such as active current epoch, active previous epoch and more
|
|
|
|
// have EffectiveBalanceIncrement(1 eth) as a lower bound.
|
|
|
|
func EnsureBalancesLowerBound(bBal *Balance) *Balance {
|
|
|
|
ebi := params.BeaconConfig().EffectiveBalanceIncrement
|
|
|
|
if ebi > bBal.ActiveCurrentEpoch {
|
|
|
|
bBal.ActiveCurrentEpoch = ebi
|
|
|
|
}
|
|
|
|
if ebi > bBal.ActivePrevEpoch {
|
|
|
|
bBal.ActivePrevEpoch = ebi
|
|
|
|
}
|
|
|
|
if ebi > bBal.CurrentEpochAttested {
|
|
|
|
bBal.CurrentEpochAttested = ebi
|
|
|
|
}
|
|
|
|
if ebi > bBal.CurrentEpochTargetAttested {
|
|
|
|
bBal.CurrentEpochTargetAttested = ebi
|
|
|
|
}
|
|
|
|
if ebi > bBal.PrevEpochAttested {
|
|
|
|
bBal.PrevEpochAttested = ebi
|
|
|
|
}
|
|
|
|
if ebi > bBal.PrevEpochTargetAttested {
|
|
|
|
bBal.PrevEpochTargetAttested = ebi
|
|
|
|
}
|
|
|
|
if ebi > bBal.PrevEpochHeadAttested {
|
|
|
|
bBal.PrevEpochHeadAttested = ebi
|
|
|
|
}
|
2020-05-01 19:43:04 +00:00
|
|
|
return bBal
|
2019-10-17 00:48:26 +00:00
|
|
|
}
|