@@ -50,14 +50,20 @@ import (
5050)
5151
5252// BatchVerifier enqueues signatures to be validated in batch.
53- type BatchVerifier struct {
53+ type BatchVerifier interface {
54+ EnqueueSignature (sigVerifier SignatureVerifier , message Hashable , sig Signature )
55+ GetNumberOfEnqueuedSignatures () int
56+ Verify () error
57+ VerifyWithFeedback () (failed []bool , err error )
58+ }
59+
60+ type cgoBatchVerifier struct {
5461 messages []Hashable // contains a slice of messages to be hashed. Each message is varible length
5562 publicKeys []SignatureVerifier // contains a slice of public keys. Each individual public key is 32 bytes.
5663 signatures []Signature // contains a slice of signatures keys. Each individual signature is 64 bytes.
64+ useSingle bool
5765}
5866
59- const minBatchVerifierAlloc = 16
60-
6167// Batch verifications errors
6268var (
6369 ErrBatchHasFailedSigs = errors .New ("At least one signature didn't pass verification" )
@@ -69,27 +75,31 @@ func ed25519_randombytes_unsafe(p unsafe.Pointer, len C.size_t) {
6975 RandBytes (randBuf )
7076}
7177
72- // MakeBatchVerifier creates a BatchVerifier instance.
73- func MakeBatchVerifier () * BatchVerifier {
78+ const minBatchVerifierAlloc = 16
79+ const useSingleVerifierDefault = true
80+
81+ // MakeBatchVerifier creates a BatchVerifier instance with the provided options.
82+ func MakeBatchVerifier () BatchVerifier {
7483 return MakeBatchVerifierWithHint (minBatchVerifierAlloc )
7584}
7685
77- // MakeBatchVerifierWithHint creates a BatchVerifier instance. This function pre-allocates
86+ // MakeBatchVerifierWithHint creates a cgoBatchVerifier instance. This function pre-allocates
7887// amount of free space to enqueue signatures without expanding
79- func MakeBatchVerifierWithHint (hint int ) * BatchVerifier {
88+ func MakeBatchVerifierWithHint (hint int ) BatchVerifier {
8089 // preallocate enough storage for the expected usage. We will reallocate as needed.
8190 if hint < minBatchVerifierAlloc {
8291 hint = minBatchVerifierAlloc
8392 }
84- return & BatchVerifier {
93+ return & cgoBatchVerifier {
8594 messages : make ([]Hashable , 0 , hint ),
8695 publicKeys : make ([]SignatureVerifier , 0 , hint ),
8796 signatures : make ([]Signature , 0 , hint ),
97+ useSingle : useSingleVerifierDefault ,
8898 }
8999}
90100
91101// EnqueueSignature enqueues a signature to be enqueued
92- func (b * BatchVerifier ) EnqueueSignature (sigVerifier SignatureVerifier , message Hashable , sig Signature ) {
102+ func (b * cgoBatchVerifier ) EnqueueSignature (sigVerifier SignatureVerifier , message Hashable , sig Signature ) {
93103 // do we need to reallocate ?
94104 if len (b .messages ) == cap (b .messages ) {
95105 b .expand ()
@@ -99,7 +109,7 @@ func (b *BatchVerifier) EnqueueSignature(sigVerifier SignatureVerifier, message
99109 b .signatures = append (b .signatures , sig )
100110}
101111
102- func (b * BatchVerifier ) expand () {
112+ func (b * cgoBatchVerifier ) expand () {
103113 messages := make ([]Hashable , len (b .messages ), len (b .messages )* 2 )
104114 publicKeys := make ([]SignatureVerifier , len (b .publicKeys ), len (b .publicKeys )* 2 )
105115 signatures := make ([]Signature , len (b .signatures ), len (b .signatures )* 2 )
@@ -112,12 +122,12 @@ func (b *BatchVerifier) expand() {
112122}
113123
114124// GetNumberOfEnqueuedSignatures returns the number of signatures currently enqueued into the BatchVerifier
115- func (b * BatchVerifier ) GetNumberOfEnqueuedSignatures () int {
125+ func (b * cgoBatchVerifier ) GetNumberOfEnqueuedSignatures () int {
116126 return len (b .messages )
117127}
118128
119129// Verify verifies that all the signatures are valid. in that case nil is returned
120- func (b * BatchVerifier ) Verify () error {
130+ func (b * cgoBatchVerifier ) Verify () error {
121131 _ , err := b .VerifyWithFeedback ()
122132 return err
123133}
@@ -126,11 +136,15 @@ func (b *BatchVerifier) Verify() error {
126136// if all sigs are valid, nil will be returned for err (failed will have all false)
127137// if some signatures are invalid, true will be set in failed at the corresponding indexes, and
128138// ErrBatchVerificationFailed for err
129- func (b * BatchVerifier ) VerifyWithFeedback () (failed []bool , err error ) {
139+ func (b * cgoBatchVerifier ) VerifyWithFeedback () (failed []bool , err error ) {
130140 if len (b .messages ) == 0 {
131141 return nil , nil
132142 }
133143
144+ if b .useSingle {
145+ return b .singleVerify ()
146+ }
147+
134148 const estimatedMessageSize = 64
135149 msgLengths := make ([]uint64 , 0 , len (b .messages ))
136150 var messages = make ([]byte , 0 , len (b .messages )* estimatedMessageSize )
@@ -141,17 +155,33 @@ func (b *BatchVerifier) VerifyWithFeedback() (failed []bool, err error) {
141155 msgLengths = append (msgLengths , uint64 (len (messages )- lenWas ))
142156 lenWas = len (messages )
143157 }
144- allValid , failed := batchVerificationImpl (messages , msgLengths , b .publicKeys , b .signatures )
158+ allValid , failed := cgoBatchVerificationImpl (messages , msgLengths , b .publicKeys , b .signatures )
145159 if allValid {
146160 return failed , nil
147161 }
148162 return failed , ErrBatchHasFailedSigs
149163}
150164
151- // batchVerificationImpl invokes the ed25519 batch verification algorithm.
165+ func (b * cgoBatchVerifier ) singleVerify () (failed []bool , err error ) {
166+ failed = make ([]bool , len (b .messages ))
167+ var containsFailed bool
168+
169+ for i := range b .messages {
170+ failed [i ] = ! ed25519Verify (ed25519PublicKey (b .publicKeys [i ]), HashRep (b .messages [i ]), ed25519Signature (b .signatures [i ]))
171+ if failed [i ] {
172+ containsFailed = true
173+ }
174+ }
175+ if containsFailed {
176+ return failed , ErrBatchHasFailedSigs
177+ }
178+ return failed , nil
179+ }
180+
181+ // cgoBatchVerificationImpl invokes the ed25519 batch verification algorithm.
152182// it returns true if all the signatures were authentically signed by the owners
153183// otherwise, returns false, and sets the indexes of the failed sigs in failed
154- func batchVerificationImpl (messages []byte , msgLengths []uint64 , publicKeys []SignatureVerifier , signatures []Signature ) (allSigsValid bool , failed []bool ) {
184+ func cgoBatchVerificationImpl (messages []byte , msgLengths []uint64 , publicKeys []SignatureVerifier , signatures []Signature ) (allSigsValid bool , failed []bool ) {
155185
156186 numberOfSignatures := len (msgLengths )
157187 valid := make ([]C.int , numberOfSignatures )
0 commit comments