github.com/amazechain/amc@v0.1.3/common/crypto/bls/signature_batch.go (about) 1 package bls 2 3 import "github.com/pkg/errors" 4 5 // SignatureBatch refers to the defined set of 6 // signatures and its respective public keys and 7 // messages required to verify it. 8 type SignatureBatch struct { 9 Signatures [][]byte 10 PublicKeys []PublicKey 11 Messages [][32]byte 12 } 13 14 // NewSet constructs an empty signature batch object. 15 func NewSet() *SignatureBatch { 16 return &SignatureBatch{ 17 Signatures: [][]byte{}, 18 PublicKeys: []PublicKey{}, 19 Messages: [][32]byte{}, 20 } 21 } 22 23 // Join merges the provided signature batch to out current one. 24 func (s *SignatureBatch) Join(set *SignatureBatch) *SignatureBatch { 25 s.Signatures = append(s.Signatures, set.Signatures...) 26 s.PublicKeys = append(s.PublicKeys, set.PublicKeys...) 27 s.Messages = append(s.Messages, set.Messages...) 28 return s 29 } 30 31 // Verify the current signature batch using the batch verify algorithm. 32 func (s *SignatureBatch) Verify() (bool, error) { 33 return VerifyMultipleSignatures(s.Signatures, s.Messages, s.PublicKeys) 34 } 35 36 // Copy the attached signature batch and return it 37 // to the caller. 38 func (s *SignatureBatch) Copy() *SignatureBatch { 39 signatures := make([][]byte, len(s.Signatures)) 40 pubkeys := make([]PublicKey, len(s.PublicKeys)) 41 messages := make([][32]byte, len(s.Messages)) 42 for i := range s.Signatures { 43 sig := make([]byte, len(s.Signatures[i])) 44 copy(sig, s.Signatures[i]) 45 signatures[i] = sig 46 } 47 for i := range s.PublicKeys { 48 pubkeys[i] = s.PublicKeys[i].Copy() 49 } 50 for i := range s.Messages { 51 copy(messages[i][:], s.Messages[i][:]) 52 } 53 return &SignatureBatch{ 54 Signatures: signatures, 55 PublicKeys: pubkeys, 56 Messages: messages, 57 } 58 } 59 60 // RemoveDuplicates removes duplicate signature sets from the signature batch. 61 func (s *SignatureBatch) RemoveDuplicates() (int, *SignatureBatch, error) { 62 if len(s.Signatures) == 0 || len(s.PublicKeys) == 0 || len(s.Messages) == 0 { 63 return 0, s, nil 64 } 65 if len(s.Signatures) != len(s.PublicKeys) || len(s.Signatures) != len(s.Messages) { 66 return 0, s, errors.Errorf("mismatch number of signatures, publickeys and messages in signature batch. "+ 67 "Signatures %d, Public Keys %d , Messages %d", s.Signatures, s.PublicKeys, s.Messages) 68 } 69 sigMap := make(map[string]int) 70 duplicateSet := make(map[int]bool) 71 for i := 0; i < len(s.Signatures); i++ { 72 if sigIdx, ok := sigMap[string(s.Signatures[i])]; ok { 73 if s.PublicKeys[sigIdx].Equals(s.PublicKeys[i]) && 74 s.Messages[sigIdx] == s.Messages[i] { 75 duplicateSet[i] = true 76 continue 77 } 78 } 79 sigMap[string(s.Signatures[i])] = i 80 } 81 82 sigs := s.Signatures[:0] 83 pubs := s.PublicKeys[:0] 84 msgs := s.Messages[:0] 85 86 for i := 0; i < len(s.Signatures); i++ { 87 if duplicateSet[i] { 88 continue 89 } 90 sigs = append(sigs, s.Signatures[i]) 91 pubs = append(pubs, s.PublicKeys[i]) 92 msgs = append(msgs, s.Messages[i]) 93 } 94 95 s.Signatures = sigs 96 s.PublicKeys = pubs 97 s.Messages = msgs 98 99 return len(duplicateSet), s, nil 100 } 101 102 // AggregateBatch aggregates common messages in the provided batch to 103 // reduce the number of pairings required when we finally verify the 104 // whole batch. 105 func (s *SignatureBatch) AggregateBatch() (*SignatureBatch, error) { 106 if len(s.Signatures) == 0 || len(s.PublicKeys) == 0 || len(s.Messages) == 0 { 107 return s, nil 108 } 109 if len(s.Signatures) != len(s.PublicKeys) || len(s.Signatures) != len(s.Messages) { 110 return s, errors.Errorf("mismatch number of signatures, publickeys and messages in signature batch. "+ 111 "Signatures %d, Public Keys %d , Messages %d", s.Signatures, s.PublicKeys, s.Messages) 112 } 113 msgMap := make(map[[32]byte]*SignatureBatch) 114 115 for i := 0; i < len(s.Messages); i++ { 116 currMsg := s.Messages[i] 117 currBatch, ok := msgMap[currMsg] 118 if ok { 119 currBatch.Signatures = append(currBatch.Signatures, s.Signatures[i]) 120 currBatch.Messages = append(currBatch.Messages, s.Messages[i]) 121 currBatch.PublicKeys = append(currBatch.PublicKeys, s.PublicKeys[i]) 122 continue 123 } 124 currBatch = &SignatureBatch{ 125 Signatures: [][]byte{s.Signatures[i]}, 126 Messages: [][32]byte{s.Messages[i]}, 127 PublicKeys: []PublicKey{s.PublicKeys[i]}, 128 } 129 msgMap[currMsg] = currBatch 130 } 131 newSt := NewSet() 132 for rt, b := range msgMap { 133 if len(b.PublicKeys) > 1 { 134 aggPub := AggregateMultiplePubkeys(b.PublicKeys) 135 aggSig, err := AggregateCompressedSignatures(b.Signatures) 136 if err != nil { 137 return nil, err 138 } 139 copiedRt := rt 140 b.PublicKeys = []PublicKey{aggPub} 141 b.Signatures = [][]byte{aggSig.Marshal()} 142 b.Messages = [][32]byte{copiedRt} 143 } 144 newObj := *b 145 newSt = newSt.Join(&newObj) 146 } 147 return newSt, nil 148 }