Skip to content

Commit a918073

Browse files
committed
Add initial BatchUncompress function
1 parent 6e0190c commit a918073

File tree

4 files changed

+291
-0
lines changed

4 files changed

+291
-0
lines changed

bindings/go/blst.go

+118
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,65 @@ func (p1 *P1Affine) Uncompress(in []byte) *P1Affine {
14091409
}
14101410
return p1
14111411
}
1412+
1413+
func (dummy *P1Affine) BatchUncompress(in [][]byte) []*P1Affine {
1414+
// Allocate space for all of the resulting points. Later we'll save pointers
1415+
// and return those so that the result could be used in other functions,
1416+
// such as MultipleAggregateVerify.
1417+
n := len(in)
1418+
points := make([]P1Affine, n)
1419+
pointsPtrs := make([]*P1Affine, n)
1420+
1421+
numCores := runtime.GOMAXPROCS(0)
1422+
numThreads := maxProcs
1423+
if numThreads > numCores {
1424+
numThreads = numCores
1425+
}
1426+
if numThreads > n {
1427+
numThreads = n
1428+
}
1429+
// Each thread will determine next message to process by atomically
1430+
// incrementing curItem, process corresponding point, and
1431+
// repeat until n is exceeded. Each thread will send a result (true for
1432+
// success, false for failure) into the channel when complete.
1433+
resCh := make(chan bool, numThreads)
1434+
valid := int32(1)
1435+
curItem := uint32(0)
1436+
for tid := 0; tid < numThreads; tid++ {
1437+
go func() {
1438+
for atomic.LoadInt32(&valid) > 0 {
1439+
// Get a work item
1440+
work := atomic.AddUint32(&curItem, 1) - 1
1441+
if work >= uint32(n) {
1442+
break
1443+
}
1444+
if points[work].Uncompress(in[work]) == nil {
1445+
atomic.StoreInt32(&valid, 0)
1446+
break
1447+
}
1448+
pointsPtrs[work] = &points[work]
1449+
}
1450+
if atomic.LoadInt32(&valid) > 0 {
1451+
resCh <- true
1452+
} else {
1453+
resCh <- false
1454+
}
1455+
}()
1456+
}
1457+
1458+
// Collect the threads
1459+
result := true
1460+
for i := 0; i < numThreads; i++ {
1461+
if !<-resCh {
1462+
result = false
1463+
}
1464+
}
1465+
if atomic.LoadInt32(&valid) == 0 || result == false {
1466+
return nil
1467+
}
1468+
return pointsPtrs
1469+
}
1470+
14121471
func (p1 *P1) Serialize() []byte {
14131472
var out [BLST_P1_SERIALIZE_BYTES]byte
14141473
C.blst_p1_serialize((*C.byte)(&out[0]), p1)
@@ -1552,6 +1611,65 @@ func (p2 *P2Affine) Uncompress(in []byte) *P2Affine {
15521611
}
15531612
return p2
15541613
}
1614+
1615+
func (dummy *P2Affine) BatchUncompress(in [][]byte) []*P2Affine {
1616+
// Allocate space for all of the resulting points. Later we'll save pointers
1617+
// and return those so that the result could be used in other functions,
1618+
// such as MultipleAggregateVerify.
1619+
n := len(in)
1620+
points := make([]P2Affine, n)
1621+
pointsPtrs := make([]*P2Affine, n)
1622+
1623+
numCores := runtime.GOMAXPROCS(0)
1624+
numThreads := maxProcs
1625+
if numThreads > numCores {
1626+
numThreads = numCores
1627+
}
1628+
if numThreads > n {
1629+
numThreads = n
1630+
}
1631+
// Each thread will determine next message to process by atomically
1632+
// incrementing curItem, process corresponding point, and
1633+
// repeat until n is exceeded. Each thread will send a result (true for
1634+
// success, false for failure) into the channel when complete.
1635+
resCh := make(chan bool, numThreads)
1636+
valid := int32(1)
1637+
curItem := uint32(0)
1638+
for tid := 0; tid < numThreads; tid++ {
1639+
go func() {
1640+
for atomic.LoadInt32(&valid) > 0 {
1641+
// Get a work item
1642+
work := atomic.AddUint32(&curItem, 1) - 1
1643+
if work >= uint32(n) {
1644+
break
1645+
}
1646+
if points[work].Uncompress(in[work]) == nil {
1647+
atomic.StoreInt32(&valid, 0)
1648+
break
1649+
}
1650+
pointsPtrs[work] = &points[work]
1651+
}
1652+
if atomic.LoadInt32(&valid) > 0 {
1653+
resCh <- true
1654+
} else {
1655+
resCh <- false
1656+
}
1657+
}()
1658+
}
1659+
1660+
// Collect the threads
1661+
result := true
1662+
for i := 0; i < numThreads; i++ {
1663+
if !<-resCh {
1664+
result = false
1665+
}
1666+
}
1667+
if atomic.LoadInt32(&valid) == 0 || result == false {
1668+
return nil
1669+
}
1670+
return pointsPtrs
1671+
}
1672+
15551673
func (p2 *P2) Serialize() []byte {
15561674
var out [BLST_P2_SERIALIZE_BYTES]byte
15571675
C.blst_p2_serialize((*C.byte)(&out[0]), p2)

bindings/go/blst_minpk_test.go

+57
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,28 @@ func TestSignMultipleVerifyAggregateMinPk(t *testing.T) {
330330
}
331331
}
332332

333+
func TestBatchUncompressMinPk(t *testing.T) {
334+
size := 128
335+
var points []*P2Affine
336+
var compPoints [][]byte
337+
338+
for i := 0; i < size; i++ {
339+
msg := Message(fmt.Sprintf("blst is a blast!! %d", i))
340+
p2 := HashToG2(msg, dstMinPk).ToAffine()
341+
points = append(points, p2)
342+
compPoints = append(compPoints, p2.Compress())
343+
}
344+
uncompPoints := new(SignatureMinPk).BatchUncompress(compPoints)
345+
if uncompPoints == nil {
346+
t.Errorf("BatchUncompress returned nil size %d", size)
347+
}
348+
for i := 0; i < size; i++ {
349+
if !points[i].Equals(uncompPoints[i]) {
350+
t.Errorf("Uncompressed point does not equal initial point %d", i)
351+
}
352+
}
353+
}
354+
333355
func BenchmarkCoreSignMinPk(b *testing.B) {
334356
var ikm = [...]byte{
335357
0x93, 0xad, 0x7e, 0x65, 0xde, 0xad, 0x05, 0x2a,
@@ -499,3 +521,38 @@ func generateBatchTestDataUncompressedMinPk(size int) (sks []*SecretKey,
499521
agsig = agProj.ToAffine()
500522
return
501523
}
524+
525+
func BenchmarkBatchUncompressMinPk(b *testing.B) {
526+
size := 128
527+
var points []*P2Affine
528+
var compPoints [][]byte
529+
530+
for i := 0; i < size; i++ {
531+
msg := Message(fmt.Sprintf("blst is a blast!! %d", i))
532+
p2 := HashToG2(msg, dstMinPk).ToAffine()
533+
points = append(points, p2)
534+
compPoints = append(compPoints, p2.Compress())
535+
}
536+
b.Run("Single", func(b *testing.B) {
537+
b.ResetTimer()
538+
b.ReportAllocs()
539+
var tmp SignatureMinPk
540+
for i := 0; i < b.N; i++ {
541+
for j := 0; j < size; j++ {
542+
if tmp.Uncompress(compPoints[j]) == nil {
543+
b.Fatal("could not uncompress point")
544+
}
545+
}
546+
}
547+
})
548+
b.Run("Batch", func(b *testing.B) {
549+
b.ResetTimer()
550+
b.ReportAllocs()
551+
var tmp SignatureMinPk
552+
for i := 0; i < b.N; i++ {
553+
if tmp.BatchUncompress(compPoints) == nil {
554+
b.Fatal("could not batch uncompress points")
555+
}
556+
}
557+
})
558+
}

bindings/go/blst_minsig_test.go

+57
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,28 @@ func TestSignMultipleVerifyAggregateMinSig(t *testing.T) {
334334
}
335335
}
336336

337+
func TestBatchUncompressMinSig(t *testing.T) {
338+
size := 128
339+
var points []*P1Affine
340+
var compPoints [][]byte
341+
342+
for i := 0; i < size; i++ {
343+
msg := Message(fmt.Sprintf("blst is a blast!! %d", i))
344+
p1 := HashToG1(msg, dstMinSig).ToAffine()
345+
points = append(points, p1)
346+
compPoints = append(compPoints, p1.Compress())
347+
}
348+
uncompPoints := new(SignatureMinSig).BatchUncompress(compPoints)
349+
if uncompPoints == nil {
350+
t.Errorf("BatchUncompress returned nil size %d", size)
351+
}
352+
for i := 0; i < size; i++ {
353+
if !points[i].Equals(uncompPoints[i]) {
354+
t.Errorf("Uncompressed point does not equal initial point %d", i)
355+
}
356+
}
357+
}
358+
337359
func BenchmarkCoreSignMinSig(b *testing.B) {
338360
var ikm = [...]byte{
339361
0x93, 0xad, 0x7e, 0x65, 0xde, 0xad, 0x05, 0x2a,
@@ -503,3 +525,38 @@ func generateBatchTestDataUncompressedMinSig(size int) (sks []*SecretKey,
503525
agsig = agProj.ToAffine()
504526
return
505527
}
528+
529+
func BenchmarkBatchUncompressMinSig(b *testing.B) {
530+
size := 128
531+
var points []*P1Affine
532+
var compPoints [][]byte
533+
534+
for i := 0; i < size; i++ {
535+
msg := Message(fmt.Sprintf("blst is a blast!! %d", i))
536+
p1 := HashToG1(msg, dstMinSig).ToAffine()
537+
points = append(points, p1)
538+
compPoints = append(compPoints, p1.Compress())
539+
}
540+
b.Run("Single", func(b *testing.B) {
541+
b.ResetTimer()
542+
b.ReportAllocs()
543+
var tmp SignatureMinSig
544+
for i := 0; i < b.N; i++ {
545+
for j := 0; j < size; j++ {
546+
if tmp.Uncompress(compPoints[j]) == nil {
547+
b.Fatal("could not uncompress point")
548+
}
549+
}
550+
}
551+
})
552+
b.Run("Batch", func(b *testing.B) {
553+
b.ResetTimer()
554+
b.ReportAllocs()
555+
var tmp SignatureMinSig
556+
for i := 0; i < b.N; i++ {
557+
if tmp.BatchUncompress(compPoints) == nil {
558+
b.Fatal("could not batch uncompress points")
559+
}
560+
}
561+
})
562+
}

bindings/go/blst_px.tgo

+59
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,65 @@ func (p1 *P1Affine) Uncompress(in []byte) *P1Affine {
5858
}
5959
return p1
6060
}
61+
62+
func (dummy *P1Affine) BatchUncompress(in [][]byte) []*P1Affine {
63+
// Allocate space for all of the resulting points. Later we'll save pointers
64+
// and return those so that the result could be used in other functions,
65+
// such as MultipleAggregateVerify.
66+
n := len(in)
67+
points := make([]P1Affine, n)
68+
pointsPtrs := make([]*P1Affine, n)
69+
70+
numCores := runtime.GOMAXPROCS(0)
71+
numThreads := maxProcs
72+
if numThreads > numCores {
73+
numThreads = numCores
74+
}
75+
if numThreads > n {
76+
numThreads = n
77+
}
78+
// Each thread will determine next message to process by atomically
79+
// incrementing curItem, process corresponding point, and
80+
// repeat until n is exceeded. Each thread will send a result (true for
81+
// success, false for failure) into the channel when complete.
82+
resCh := make(chan bool, numThreads)
83+
valid := int32(1)
84+
curItem := uint32(0)
85+
for tid := 0; tid < numThreads; tid++ {
86+
go func() {
87+
for atomic.LoadInt32(&valid) > 0 {
88+
// Get a work item
89+
work := atomic.AddUint32(&curItem, 1) - 1
90+
if work >= uint32(n) {
91+
break
92+
}
93+
if points[work].Uncompress(in[work]) == nil {
94+
atomic.StoreInt32(&valid, 0)
95+
break
96+
}
97+
pointsPtrs[work] = &points[work]
98+
}
99+
if atomic.LoadInt32(&valid) > 0 {
100+
resCh <- true
101+
} else {
102+
resCh <- false
103+
}
104+
}()
105+
}
106+
107+
// Collect the threads
108+
result := true
109+
for i := 0; i < numThreads; i++ {
110+
if ! <-resCh {
111+
result = false
112+
}
113+
}
114+
if atomic.LoadInt32(&valid) == 0 || result == false {
115+
return nil
116+
}
117+
return pointsPtrs
118+
}
119+
61120
func (p1 *P1) Serialize() []byte {
62121
var out [BLST_P1_SERIALIZE_BYTES]byte
63122
C.blst_p1_serialize((*C.byte)(&out[0]), p1)

0 commit comments

Comments
 (0)