prysm-pulse/beacon-chain/rpc/validator/proposer_utils.go
2021-01-19 13:21:32 +00:00

96 lines
2.9 KiB
Go

package validator
import (
"context"
"sort"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/params"
)
type proposerAtts []*ethpb.Attestation
// filter separates attestation list into two groups: valid and invalid attestations.
// The first group passes the all the required checks for attestation to be considered for proposing.
// And attestations from the second group should be deleted.
func (a proposerAtts) filter(ctx context.Context, state *stateTrie.BeaconState) (proposerAtts, proposerAtts) {
validAtts := make([]*ethpb.Attestation, 0, len(a))
invalidAtts := make([]*ethpb.Attestation, 0, len(a))
for _, att := range a {
if _, err := blocks.ProcessAttestationNoVerifySignature(ctx, state, att); err == nil {
validAtts = append(validAtts, att)
continue
}
invalidAtts = append(invalidAtts, att)
}
return validAtts, invalidAtts
}
// sortByProfitability orders attestations by highest slot and by highest aggregation bit count.
func (a proposerAtts) sortByProfitability() proposerAtts {
if len(a) < 2 {
return a
}
sort.Slice(a, func(i, j int) bool {
if a[i].Data.Slot == a[j].Data.Slot {
return a[i].AggregationBits.Count() > a[j].AggregationBits.Count()
}
return a[i].Data.Slot > a[j].Data.Slot
})
return a
}
// limitToMaxAttestations limits attestations to maximum attestations per block.
func (a proposerAtts) limitToMaxAttestations() proposerAtts {
if uint64(len(a)) > params.BeaconConfig().MaxAttestations {
return a[:params.BeaconConfig().MaxAttestations]
}
return a
}
// dedup removes duplicate attestations (ones with the same bits set on).
// Important: not only exact duplicates are removed, but proper subsets are removed too
// (their known bits are redundant and are already contained in their supersets).
func (a proposerAtts) dedup() proposerAtts {
if len(a) < 2 {
return a
}
attsByDataRoot := make(map[[32]byte][]*ethpb.Attestation, len(a))
for _, att := range a {
attDataRoot, err := att.Data.HashTreeRoot()
if err != nil {
continue
}
attsByDataRoot[attDataRoot] = append(attsByDataRoot[attDataRoot], att)
}
uniqAtts := make([]*ethpb.Attestation, 0, len(a))
for _, atts := range attsByDataRoot {
for i := 0; i < len(atts); i++ {
a := atts[i]
for j := i + 1; j < len(atts); j++ {
b := atts[j]
if a.AggregationBits.Contains(b.AggregationBits) {
// a contains b, b is redundant.
atts[j] = atts[len(atts)-1]
atts[len(atts)-1] = nil
atts = atts[:len(atts)-1]
j--
} else if b.AggregationBits.Contains(a.AggregationBits) {
// b contains a, a is redundant.
atts[i] = atts[len(atts)-1]
atts[len(atts)-1] = nil
atts = atts[:len(atts)-1]
i--
break
}
}
}
uniqAtts = append(uniqAtts, atts...)
}
return uniqAtts
}