Skip to content

Commit cec5433

Browse files
authored
perf(zkatdlog): add UnboundedExecutor and WorkerPoolExecutor with constructor injection (#1497)
Signed-off-by: Ankit Basu <ankitbasu14@gmail.com>
1 parent 784bfc3 commit cec5433

14 files changed

Lines changed: 426 additions & 167 deletions

File tree

token/core/zkatdlog/nogh/v1/crypto/rp/bulletproof/ipa.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/hyperledger-labs/fabric-token-sdk/token/core/common/encoding/asn1"
1313
"github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/crypto/common"
1414
"github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/crypto/math"
15-
"github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/crypto/rp"
15+
rp "github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/crypto/rp/executor"
1616
)
1717

1818
// IPA contains the proof for the inner product argument.
@@ -111,9 +111,14 @@ type ipaProver struct {
111111
NumberOfRounds uint64
112112
// Curve is the mathematical curve.
113113
Curve *mathlib.Curve
114+
// Provider creates a fresh Executor for each Prove call.
115+
// If nil, DefaultProvider (SerialProvider) is used.
116+
Provider rp.ExecutorProvider
114117
}
115118

116119
// NewIPAProver returns a new ipaProver instance.
120+
// exec controls how generator reduction is parallelised; pass nil
121+
// to use SerialExecutor (equivalent to the previous behaviour).
117122
func NewIPAProver(
118123
innerProduct *mathlib.Zr,
119124
leftVector, rightVector []*mathlib.Zr,
@@ -122,7 +127,12 @@ func NewIPAProver(
122127
Commitment *mathlib.G1,
123128
rounds uint64,
124129
c *mathlib.Curve,
130+
provider rp.ExecutorProvider,
125131
) *ipaProver {
132+
if provider == nil {
133+
provider = rp.DefaultProvider
134+
}
135+
126136
return &ipaProver{
127137
InnerProduct: innerProduct,
128138
rightVector: rightVector,
@@ -133,6 +143,7 @@ func NewIPAProver(
133143
NumberOfRounds: rounds,
134144
Commitment: Commitment,
135145
Q: Q,
146+
Provider: provider,
136147
}
137148
}
138149

@@ -206,7 +217,7 @@ func (p *ipaProver) reduce(X, com *mathlib.G1) (*mathlib.Zr, *mathlib.Zr, []*mat
206217
xInv.InvModOrder()
207218

208219
// reduce the generators by 1/2, as a function of the old generators and x and 1/x
209-
leftGen, rightGen = reduceGenerators(leftGen, rightGen, x, xInv)
220+
leftGen, rightGen = reduceGenerators(leftGen, rightGen, x, xInv, p.Provider)
210221

211222
// reduce the vectors by 1/2, a function of the old vectors and x and 1/x
212223
left, right = reduceVectors(left, right, x, xInv, p.Curve)
@@ -241,17 +252,27 @@ type ipaVerifier struct {
241252
NumberOfRounds uint64
242253
// Curve is the mathematical curve.
243254
Curve *mathlib.Curve
255+
// Provider creates a fresh Executor for each Prove call.
256+
// If nil, DefaultProvider (SerialProvider) is used.
257+
Provider rp.ExecutorProvider
244258
}
245259

246260
// NewIPAVerifier returns an ipaVerifier instance.
261+
// exec controls how generator reduction is parallelised; pass nil
262+
// to use SerialExecutor (equivalent to the previous behaviour).
247263
func NewIPAVerifier(
248264
innerProduct *mathlib.Zr,
249265
Q *mathlib.G1,
250266
leftGens, rightGens []*mathlib.G1,
251267
Commitment *mathlib.G1,
252268
rounds uint64,
253269
c *mathlib.Curve,
270+
provider rp.ExecutorProvider,
254271
) *ipaVerifier {
272+
if provider == nil {
273+
provider = rp.DefaultProvider
274+
}
275+
255276
return &ipaVerifier{
256277
InnerProduct: innerProduct,
257278
RightGenerators: rightGens,
@@ -260,6 +281,7 @@ func NewIPAVerifier(
260281
NumberOfRounds: rounds,
261282
Commitment: Commitment,
262283
Q: Q,
284+
Provider: provider,
263285
}
264286
}
265287

@@ -384,22 +406,21 @@ func reduceVectors(left, right []*mathlib.Zr, x, xInv *mathlib.Zr, c *mathlib.Cu
384406

385407
// reduceGenerators reduces the number of generators passed in the parameters by 1/2,
386408
// as a function of the old generators, x and 1/x
387-
func reduceGenerators(leftGen, rightGen []*mathlib.G1, x, xInv *mathlib.Zr) ([]*mathlib.G1, []*mathlib.G1) {
409+
func reduceGenerators(leftGen, rightGen []*mathlib.G1, x, xInv *mathlib.Zr, provider rp.ExecutorProvider) ([]*mathlib.G1, []*mathlib.G1) {
388410
l := len(leftGen) / 2
389411
// Use the Executor abstraction so that the execution strategy can be
390412
// swapped without changing this function. SerialExecutor runs each task
391413
// immediately with no locks or goroutine overhead.
392-
executor := rp.NewSerialExecutor()
393-
414+
exec := provider.New()
394415
for i := range l {
395-
executor.Submit(func() {
416+
exec.Submit(func() {
396417
// G_i = G_i^{x_inv} * G_{i+l}^x
397418
leftGen[i].Mul2InPlace(xInv, leftGen[i+l], x)
398419
// H_i = H_i^x * H_{i+l}^{x_inv}
399420
rightGen[i].Mul2InPlace(x, rightGen[i+l], xInv)
400421
})
401422
}
402-
executor.Wait()
423+
exec.Wait()
403424

404425
return leftGen[:l], rightGen[:l]
405426
}

token/core/zkatdlog/nogh/v1/crypto/rp/bulletproof/ipa_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ func TestIPAProofVerify(t *testing.T) {
8383
setup.com,
8484
setup.nr,
8585
setup.curve,
86+
nil,
8687
)
8788
proof, err := prover.Prove()
8889
require.NoError(t, err)
@@ -96,6 +97,7 @@ func TestIPAProofVerify(t *testing.T) {
9697
setup.com,
9798
setup.nr,
9899
setup.curve,
100+
nil,
99101
)
100102
err = verifier.Verify(proof)
101103
require.NoError(t, err)
@@ -126,6 +128,7 @@ func BenchmarkIPAProver(b *testing.B) {
126128
setup.com,
127129
setup.nr,
128130
setup.curve,
131+
nil,
129132
)
130133
proof, err := prover.Prove()
131134
require.NoError(b, err)
@@ -154,6 +157,7 @@ func TestParallelIPAProver(t *testing.T) {
154157
setup.com,
155158
setup.nr,
156159
setup.curve,
160+
nil,
157161
)
158162
_, err := prover.Prove()
159163

token/core/zkatdlog/nogh/v1/crypto/rp/bulletproof/rangecorrectness.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
math "github.com/IBM/mathlib"
1111
"github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors"
1212
"github.com/hyperledger-labs/fabric-token-sdk/token/core/common/encoding/asn1"
13-
"github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/crypto/rp"
13+
rp "github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/crypto/rp/executor"
1414
)
1515

1616
// RangeCorrectness contains a set of range proofs for multiple commitments.
@@ -85,9 +85,14 @@ type RangeCorrectnessProver struct {
8585
Q *math.G1
8686
// Curve is the mathematical curve.
8787
Curve *math.Curve
88+
// Provider creates a fresh Executor for each Prove call.
89+
// If nil, DefaultProvider (SerialProvider) is used.
90+
Provider rp.ExecutorProvider
8891
}
8992

90-
// NewRangeCorrectnessProver returns a new RangeCorrectnessProver instance.
93+
// NewRangeCorrectnessProver returns a new RangeCorrectnessProver.
94+
// exec controls how independent range proofs are executed; pass nil
95+
// to use SerialExecutor (equivalent to the previous behaviour).
9196
func NewRangeCorrectnessProver(
9297
coms []*math.G1,
9398
values []uint64,
@@ -96,7 +101,12 @@ func NewRangeCorrectnessProver(
96101
P, Q *math.G1,
97102
bitLength, rounds uint64,
98103
c *math.Curve,
104+
provider rp.ExecutorProvider,
99105
) *RangeCorrectnessProver {
106+
if provider == nil {
107+
provider = rp.DefaultProvider
108+
}
109+
100110
return &RangeCorrectnessProver{
101111
Commitments: coms,
102112
Values: values,
@@ -109,6 +119,7 @@ func NewRangeCorrectnessProver(
109119
BitLength: bitLength,
110120
NumberOfRounds: rounds,
111121
Curve: c,
122+
Provider: provider,
112123
}
113124
}
114125

@@ -120,8 +131,8 @@ func (p *RangeCorrectnessProver) Prove() (*RangeCorrectness, error) {
120131
Proofs: make([]*RangeProof, n),
121132
}
122133

123-
// SerialExecutor runs tasks immediately with no overhead
124-
executor := rp.NewSerialExecutor()
134+
// Executor controls execution strategy (serial or parallel)
135+
executor := p.Provider.New()
125136
errs := make([]error, n)
126137

127138
for i := range n {
@@ -138,6 +149,7 @@ func (p *RangeCorrectnessProver) Prove() (*RangeCorrectness, error) {
138149
p.NumberOfRounds,
139150
p.BitLength,
140151
p.Curve,
152+
p.Provider,
141153
)
142154
rc.Proofs[i], errs[i] = bp.Prove()
143155
})
@@ -174,15 +186,25 @@ type RangeCorrectnessVerifier struct {
174186
Q *math.G1
175187
// Curve is the mathematical curve.
176188
Curve *math.Curve
189+
// Provider creates a fresh Executor for each Prove call.
190+
// If nil, DefaultProvider (SerialProvider) is used.
191+
Provider rp.ExecutorProvider
177192
}
178193

179-
// NewRangeCorrectnessVerifier returns a new RangeCorrectnessVerifier instance.
194+
// NewRangeCorrectnessVerifier returns a new RangeCorrectnessVerifier.
195+
// exec controls how independent range proofs are verified; pass nil
196+
// to use SerialExecutor (equivalent to the previous behaviour).
180197
func NewRangeCorrectnessVerifier(
181198
pedersenParameters, leftGenerators, rightGenerators []*math.G1,
182199
P, Q *math.G1,
183200
bitLength, rounds uint64,
184201
curve *math.Curve,
202+
provider rp.ExecutorProvider,
185203
) *RangeCorrectnessVerifier {
204+
if provider == nil {
205+
provider = rp.DefaultProvider
206+
}
207+
186208
return &RangeCorrectnessVerifier{
187209
PedersenParameters: pedersenParameters,
188210
LeftGenerators: leftGenerators,
@@ -192,6 +214,7 @@ func NewRangeCorrectnessVerifier(
192214
BitLength: bitLength,
193215
NumberOfRounds: rounds,
194216
Curve: curve,
217+
Provider: provider,
195218
}
196219
}
197220

@@ -202,7 +225,7 @@ func (v *RangeCorrectnessVerifier) Verify(rc *RangeCorrectness) error {
202225
}
203226

204227
n := len(rc.Proofs)
205-
executor := rp.NewSerialExecutor()
228+
executor := v.Provider.New()
206229
errs := make([]error, n)
207230

208231
for i := range n {
@@ -223,6 +246,7 @@ func (v *RangeCorrectnessVerifier) Verify(rc *RangeCorrectness) error {
223246
v.NumberOfRounds,
224247
v.BitLength,
225248
v.Curve,
249+
v.Provider,
226250
)
227251

228252
errs[i] = bv.Verify(rc.Proofs[i])

token/core/zkatdlog/nogh/v1/crypto/rp/bulletproof/rangecorrectness_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func TestRangeCorrectness(t *testing.T) {
5151
bitLength,
5252
rounds,
5353
curve,
54+
nil,
5455
)
5556

5657
rc, err := prover.Prove()
@@ -80,6 +81,7 @@ func TestRangeCorrectness(t *testing.T) {
8081
bitLength,
8182
rounds,
8283
curve,
84+
nil,
8385
)
8486
// We need to manually set commitments because NewRangeCorrectnessVerifier doesn't take them
8587
verifier.Commitments = commitments

token/core/zkatdlog/nogh/v1/crypto/rp/bulletproof/rp.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/hyperledger-labs/fabric-token-sdk/token/core/common/encoding/asn1"
1313
"github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/crypto/common"
1414
math2 "github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/crypto/math"
15+
rp "github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/crypto/rp/executor"
1516
)
1617

1718
// RangeProofData contains the elements of a Bulletproof-style range proof.
@@ -199,6 +200,9 @@ type rangeProver struct {
199200
BitLength uint64
200201
// Curve is the mathematical curve.
201202
Curve *math.Curve
203+
// Provider creates a fresh Executor for each Prove call.
204+
// If nil, DefaultProvider (SerialProvider) is used.
205+
Provider rp.ExecutorProvider
202206
}
203207

204208
// NewRangeProver returns a rangeProver based on the passed arguments
@@ -212,6 +216,7 @@ func NewRangeProver(
212216
P, Q *math.G1,
213217
numberOfRounds, bitLength uint64,
214218
curve *math.Curve,
219+
provider rp.ExecutorProvider,
215220
) *rangeProver {
216221
return &rangeProver{
217222
Commitment: com,
@@ -225,6 +230,7 @@ func NewRangeProver(
225230
NumberOfRounds: numberOfRounds,
226231
BitLength: bitLength,
227232
Curve: curve,
233+
Provider: provider,
228234
}
229235
}
230236

@@ -263,6 +269,7 @@ func (p *rangeProver) Prove() (*RangeProof, error) {
263269
com,
264270
p.NumberOfRounds,
265271
p.Curve,
272+
p.Provider,
266273
)
267274
rp.IPA, err = ipp.Prove()
268275
if err != nil {
@@ -442,6 +449,9 @@ type rangeVerifier struct {
442449
BitLength uint64
443450
// Curve is the mathematical curve.
444451
Curve *math.Curve
452+
// Provider creates a fresh Executor for each Prove call.
453+
// If nil, DefaultProvider (SerialProvider) is used.
454+
Provider rp.ExecutorProvider
445455
}
446456

447457
// NewRangeVerifier returns a rangeVerifier based on the passed arguments
@@ -453,6 +463,7 @@ func NewRangeVerifier(
453463
P, Q *math.G1,
454464
numberOfRounds, bitLength uint64,
455465
curve *math.Curve,
466+
provider rp.ExecutorProvider,
456467
) *rangeVerifier {
457468
return &rangeVerifier{
458469
Commitment: com,
@@ -464,6 +475,7 @@ func NewRangeVerifier(
464475
NumberOfRounds: numberOfRounds,
465476
BitLength: bitLength,
466477
Curve: curve,
478+
Provider: provider,
467479
}
468480
}
469481

@@ -619,6 +631,7 @@ func (v *rangeVerifier) verifyIPA(rp *RangeProof, x *math.Zr, yPow []*math.Zr, z
619631
com,
620632
v.NumberOfRounds,
621633
v.Curve,
634+
v.Provider,
622635
)
623636

624637
return ipv.Verify(rp.IPA)

token/core/zkatdlog/nogh/v1/crypto/rp/bulletproof/rp_internal_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func TestRangeProofDeserializeError(t *testing.T) {
196196

197197
func TestRangeVerifier_VerifyError(t *testing.T) {
198198
curve := math.Curves[math.BN254]
199-
verifier := NewRangeVerifier(curve.GenG1, []*math.G1{curve.GenG1}, nil, nil, curve.GenG1, curve.GenG1, 1, 1, curve)
199+
verifier := NewRangeVerifier(curve.GenG1, []*math.G1{curve.GenG1}, nil, nil, curve.GenG1, curve.GenG1, 1, 1, curve, nil)
200200

201201
proof := &RangeProof{
202202
Data: &RangeProofData{},

0 commit comments

Comments
 (0)