mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-09 11:11:20 +00:00
ee5d75732d
* Add pkg crypto * Update go.yml Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
109 lines
3.7 KiB
Go
109 lines
3.7 KiB
Go
package attestations
|
|
|
|
import (
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/config/features"
|
|
"github.com/prysmaticlabs/prysm/crypto/bls"
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/shared/aggregation"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
const (
|
|
// NaiveAggregation is an aggregation strategy without any optimizations.
|
|
NaiveAggregation AttestationAggregationStrategy = "naive"
|
|
|
|
// MaxCoverAggregation is a strategy based on Maximum Coverage greedy algorithm.
|
|
MaxCoverAggregation AttestationAggregationStrategy = "max_cover"
|
|
|
|
// OptMaxCoverAggregation is a strategy based on Maximum Coverage greedy algorithm.
|
|
// This new variant is optimized and relies on Bitlist64 (once fully tested, `max_cover`
|
|
// strategy will be replaced with this one).
|
|
OptMaxCoverAggregation AttestationAggregationStrategy = "opt_max_cover"
|
|
)
|
|
|
|
// AttestationAggregationStrategy defines attestation aggregation strategy.
|
|
type AttestationAggregationStrategy string
|
|
|
|
// attList represents list of attestations, defined for easier en masse operations (filtering, sorting).
|
|
type attList []*ethpb.Attestation
|
|
|
|
// BLS aggregate signature aliases for testing / benchmark substitution. These methods are
|
|
// significantly more expensive than the inner logic of AggregateAttestations so they must be
|
|
// substituted for benchmarks which analyze AggregateAttestations.
|
|
var aggregateSignatures = bls.AggregateSignatures
|
|
var signatureFromBytes = bls.SignatureFromBytes
|
|
|
|
var _ = logrus.WithField("prefix", "aggregation.attestations")
|
|
|
|
// ErrInvalidAttestationCount is returned when insufficient number
|
|
// of attestations is provided for aggregation.
|
|
var ErrInvalidAttestationCount = errors.New("invalid number of attestations")
|
|
|
|
// Aggregate aggregates attestations. The minimal number of attestations is returned.
|
|
// Aggregation occurs in-place i.e. contents of input array will be modified. Should you need to
|
|
// preserve input attestations, clone them before aggregating:
|
|
//
|
|
// clonedAtts := make([]*ethpb.Attestation, len(atts))
|
|
// for i, a := range atts {
|
|
// clonedAtts[i] = stateTrie.CopyAttestation(a)
|
|
// }
|
|
// aggregatedAtts, err := attaggregation.Aggregate(clonedAtts)
|
|
func Aggregate(atts []*ethpb.Attestation) ([]*ethpb.Attestation, error) {
|
|
strategy := AttestationAggregationStrategy(features.Get().AttestationAggregationStrategy)
|
|
switch strategy {
|
|
case "", NaiveAggregation:
|
|
return NaiveAttestationAggregation(atts)
|
|
case MaxCoverAggregation:
|
|
return MaxCoverAttestationAggregation(atts)
|
|
case OptMaxCoverAggregation:
|
|
return optMaxCoverAttestationAggregation(atts)
|
|
default:
|
|
return nil, errors.Wrapf(aggregation.ErrInvalidStrategy, "%q", strategy)
|
|
}
|
|
}
|
|
|
|
// AggregatePair aggregates pair of attestations a1 and a2 together.
|
|
func AggregatePair(a1, a2 *ethpb.Attestation) (*ethpb.Attestation, error) {
|
|
o, err := a1.AggregationBits.Overlaps(a2.AggregationBits)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if o {
|
|
return nil, aggregation.ErrBitsOverlap
|
|
}
|
|
|
|
baseAtt := ethpb.CopyAttestation(a1)
|
|
newAtt := ethpb.CopyAttestation(a2)
|
|
if newAtt.AggregationBits.Count() > baseAtt.AggregationBits.Count() {
|
|
baseAtt, newAtt = newAtt, baseAtt
|
|
}
|
|
|
|
c, err := baseAtt.AggregationBits.Contains(newAtt.AggregationBits)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if c {
|
|
return baseAtt, nil
|
|
}
|
|
|
|
newBits, err := baseAtt.AggregationBits.Or(newAtt.AggregationBits)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
newSig, err := signatureFromBytes(newAtt.Signature)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
baseSig, err := signatureFromBytes(baseAtt.Signature)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
aggregatedSig := aggregateSignatures([]bls.Signature{baseSig, newSig})
|
|
baseAtt.Signature = aggregatedSig.Marshal()
|
|
baseAtt.AggregationBits = newBits
|
|
|
|
return baseAtt, nil
|
|
}
|