github.com/prysmaticlabs/prysm@v1.4.4/shared/aggregation/sync_contribution/naive.go (about) 1 package sync_contribution 2 3 import ( 4 v2 "github.com/prysmaticlabs/prysm/proto/prysm/v2" 5 "github.com/prysmaticlabs/prysm/shared/aggregation" 6 "github.com/prysmaticlabs/prysm/shared/bls" 7 "github.com/prysmaticlabs/prysm/shared/copyutil" 8 ) 9 10 // naiveSyncContributionAggregation aggregates naively, without any complex algorithms or optimizations. 11 // Note: this is currently a naive implementation to the order of O(mn^2). 12 func naiveSyncContributionAggregation(contributions []*v2.SyncCommitteeContribution) ([]*v2.SyncCommitteeContribution, error) { 13 if len(contributions) <= 1 { 14 return contributions, nil 15 } 16 17 // Naive aggregation. O(n^2) time. 18 for i, a := range contributions { 19 if i >= len(contributions) { 20 break 21 } 22 for j := i + 1; j < len(contributions); j++ { 23 b := contributions[j] 24 if o, err := a.AggregationBits.Overlaps(b.AggregationBits); err != nil { 25 return nil, err 26 } else if !o { 27 var err error 28 a, err = aggregate(a, b) 29 if err != nil { 30 return nil, err 31 } 32 // Delete b 33 contributions = append(contributions[:j], contributions[j+1:]...) 34 j-- 35 contributions[i] = a 36 } 37 } 38 } 39 40 // Naive deduplication of identical contributions. O(n^2) time. 41 for i, a := range contributions { 42 for j := i + 1; j < len(contributions); j++ { 43 b := contributions[j] 44 45 if a.AggregationBits.Len() != b.AggregationBits.Len() { 46 continue 47 } 48 49 if c, err := a.AggregationBits.Contains(b.AggregationBits); err != nil { 50 return nil, err 51 } else if c { 52 // If b is fully contained in a, then b can be removed. 53 contributions = append(contributions[:j], contributions[j+1:]...) 54 j-- 55 } else if c, err := b.AggregationBits.Contains(a.AggregationBits); err != nil { 56 return nil, err 57 } else if c { 58 // if a is fully contained in b, then a can be removed. 59 contributions = append(contributions[:i], contributions[i+1:]...) 60 break // Stop the inner loop, advance a. 61 } 62 } 63 } 64 65 return contributions, nil 66 } 67 68 // aggregates pair of sync contributions c1 and c2 together. 69 func aggregate(c1, c2 *v2.SyncCommitteeContribution) (*v2.SyncCommitteeContribution, error) { 70 if o, err := c1.AggregationBits.Overlaps(c2.AggregationBits); err != nil { 71 return nil, err 72 } else if o { 73 return nil, aggregation.ErrBitsOverlap 74 } 75 76 baseContribution := copyutil.CopySyncCommitteeContribution(c1) 77 newContribution := copyutil.CopySyncCommitteeContribution(c2) 78 if newContribution.AggregationBits.Count() > baseContribution.AggregationBits.Count() { 79 baseContribution, newContribution = newContribution, baseContribution 80 } 81 82 if c, err := baseContribution.AggregationBits.Contains(newContribution.AggregationBits); err != nil { 83 return nil, err 84 } else if c { 85 return baseContribution, nil 86 } 87 88 newBits, err := baseContribution.AggregationBits.Or(newContribution.AggregationBits) 89 if err != nil { 90 return nil, err 91 } 92 newSig, err := bls.SignatureFromBytes(newContribution.Signature) 93 if err != nil { 94 return nil, err 95 } 96 baseSig, err := bls.SignatureFromBytes(baseContribution.Signature) 97 if err != nil { 98 return nil, err 99 } 100 101 aggregatedSig := bls.AggregateSignatures([]bls.Signature{baseSig, newSig}) 102 baseContribution.Signature = aggregatedSig.Marshal() 103 baseContribution.AggregationBits = newBits 104 105 return baseContribution, nil 106 }