@@ -10,6 +10,8 @@ import (
1010 "math/big"
1111
1212 mathlib "github.com/IBM/mathlib"
13+ bls12381fr "github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
14+ bn254fr "github.com/consensys/gnark-crypto/ecc/bn254/fr"
1315 "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors"
1416 "github.com/hyperledger-labs/fabric-token-sdk/token/core/common/encoding/asn1"
1517 "github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/crypto/math"
@@ -276,14 +278,32 @@ func (rp *rangeProver) Prove() (*RangeProof, error) {
276278 if err != nil {
277279 return nil , errors .New ("Unable to obtain partial lagrange multipliers" )
278280 }
279- u := math .InnerProduct (aCoeffs , mu , rp .Curve )
281+ // Compute u = <aCoeffs, mu> — dispatch to native for supported curves.
282+ isBLS , isBN254 := math .DispatchCurve (rp .Curve )
283+ var u * mathlib.Zr
284+ if isBLS {
285+ u = nativeRPInnerProduct [bls12381fr.Element , * bls12381fr.Element ](aCoeffs , mu , rp .Curve )
286+ } else if isBN254 {
287+ u = nativeRPInnerProduct [bn254fr.Element , * bn254fr.Element ](aCoeffs , mu , rp .Curve )
288+ } else {
289+ u = math .InnerProduct (aCoeffs , mu , rp .Curve )
290+ }
280291
281292 tr .Absorb (u .Bytes ())
282293 gamma , err := tr .Squeeze ()
283294 if err != nil {
284295 return nil , errors .New ("Unable to obtain challenge gamma" )
285296 }
286297
298+ // Compute paddedSize for lf/wit (next power of 2 >= 2n+4).
299+ witSize := 2 * n + 4
300+ cspRounds := uint64 (0 )
301+ paddedSize := uint64 (1 )
302+ for paddedSize < witSize {
303+ paddedSize <<= 1
304+ cspRounds ++
305+ }
306+
287307 // Extended commitment: pCommExt = pComm + eta * VCommitment.
288308 pCommExt := pComm .Copy ()
289309 pCommExt .Add (rp .VCommitment .Mul (eta ))
@@ -299,53 +319,66 @@ func (rp *rangeProver) Prove() (*RangeProof, error) {
299319 gExt [2 * n + 2 ] = rp .VGenerators [0 ].Mul (eta )
300320 gExt [2 * n + 3 ] = rp .VGenerators [1 ].Mul (eta )
301321
302- // Build aggregated linear form lf = L1 + gamma*L2 + gamma^2*L3 over pExt.
303- //
304- // pExt layout [0..n]=aCoeffs [n+1..2n+1]=bCoeffs [2n+2]=v [2n+3]=r
305- //
306- // L1: eta*2^{i-1} at [1..n], -eta at [2n+2] → checks eta*(Σ a_i·2^{i-1} - v) = 0
307- // L2: mu[i] at [0..n] → checks a(c) = u
308- // L3: nu[k] at [n+1..2n+1] (k=0..n) → checks b(c) = u*(u-1)
309- gammaSquare := rp .Curve .ModMul (gamma , gamma , rp .Curve .GroupOrder )
310- lf := make ([]* mathlib.Zr , len (pExt ))
311- for i := range lf {
312- lf [i ] = math .Zero (rp .Curve )
313- }
314- // L1 contribution1s.
315- for i := uint64 (1 ); i <= n ; i ++ {
316- lf [i ] = rp .Curve .ModMul (eta , math .PowerOfTwo (rp .Curve , i - 1 ), rp .Curve .GroupOrder )
317- }
318- negEta := eta .Copy ()
319- negEta .Neg ()
320- lf [2 * n + 2 ] = negEta
321- // L2 contributions: add gamma*mu[i] at positions 0..n.
322- for i := uint64 (0 ); i <= n ; i ++ {
323- lf [i ] = rp .Curve .ModAddMul2 (
324- lf [i ], math .One (rp .Curve ),
325- gamma , mu [i ],
322+ // Build aggregated linear form, and compute lVal.
323+ // Dispatch to native gnark arithmetic for supported curves.
324+ var lf []* mathlib.Zr
325+ var lVal * mathlib.Zr
326+ if isBLS {
327+ lf , _ , lVal = nativeRPBuildLF [bls12381fr.Element , * bls12381fr.Element ](
328+ n , eta , gamma , mu , nu , aCoeffs , u , rp .Curve )
329+ } else if isBN254 {
330+ lf , _ , lVal = nativeRPBuildLF [bn254fr.Element , * bn254fr.Element ](
331+ n , eta , gamma , mu , nu , aCoeffs , u , rp .Curve )
332+ } else {
333+ gammaSquare := rp .Curve .ModMul (gamma , gamma , rp .Curve .GroupOrder )
334+ lf = make ([]* mathlib.Zr , len (pExt ))
335+ for i := range lf {
336+ lf [i ] = math .Zero (rp .Curve )
337+ }
338+ // L1 contribution1s.
339+ for i := uint64 (1 ); i <= n ; i ++ {
340+ lf [i ] = rp .Curve .ModMul (eta , math .PowerOfTwo (rp .Curve , i - 1 ), rp .Curve .GroupOrder )
341+ }
342+ negEta := eta .Copy ()
343+ negEta .Neg ()
344+ lf [2 * n + 2 ] = negEta
345+ // L2 contributions: add gamma*mu[i] at positions 0..n.
346+ for i := uint64 (0 ); i <= n ; i ++ {
347+ lf [i ] = rp .Curve .ModAddMul2 (
348+ lf [i ], math .One (rp .Curve ),
349+ gamma , mu [i ],
350+ rp .Curve .GroupOrder ,
351+ )
352+ }
353+ // L3 contributions: gamma^2*nu[k] at positions n+1..2n+1.
354+ for k := uint64 (0 ); k <= n ; k ++ {
355+ lf [n + 1 + k ] = rp .Curve .ModMul (gammaSquare , nu [k ], rp .Curve .GroupOrder )
356+ }
357+
358+ // Claimed value: lVal = gamma*u + gamma^2*u*(u-1) (L1(pExt)=0 for honest prover).
359+ uMinus1 := rp .Curve .ModSub (u , math .One (rp .Curve ), rp .Curve .GroupOrder )
360+ lVal = rp .Curve .ModAddMul2 (
361+ gamma , u ,
362+ gammaSquare , rp .Curve .ModMul (u , uMinus1 , rp .Curve .GroupOrder ),
326363 rp .Curve .GroupOrder ,
327364 )
328365 }
329- // L3 contributions: gamma^2*nu[k] at positions n+1..2n+1.
330- for k := uint64 (0 ); k <= n ; k ++ {
331- lf [n + 1 + k ] = rp .Curve .ModMul (gammaSquare , nu [k ], rp .Curve .GroupOrder )
332- }
333-
334- // Claimed value: lVal = gamma*u + gamma^2*u*(u-1) (L1(pExt)=0 for honest prover).
335- uMinus1 := rp .Curve .ModSub (u , math .One (rp .Curve ), rp .Curve .GroupOrder )
336- lVal := rp .Curve .ModAddMul2 (
337- gamma , u ,
338- gammaSquare , rp .Curve .ModMul (u , uMinus1 , rp .Curve .GroupOrder ),
339- rp .Curve .GroupOrder ,
340- )
341366
342367 // ZK blinding: random sBlind, commit it, evaluate L on it.
343368 sBlind := make ([]* mathlib.Zr , len (pExt ))
344369 for i := range sBlind {
345370 sBlind [i ] = rp .Curve .NewRandomZr (rand )
346371 }
347372 sComm := rp .Curve .MultiScalarMul (gExt , sBlind )
348- sVal := math .InnerProduct (lf , sBlind , rp .Curve )
373+ // Compute sVal = ⟨lf, sBlind⟩ — dispatch to native for supported curves.
374+ var sVal * mathlib.Zr
375+ if isBLS {
376+ sVal = nativeRPInnerProduct [bls12381fr.Element , * bls12381fr.Element ](lf , sBlind , rp .Curve )
377+ } else if isBN254 {
378+ sVal = nativeRPInnerProduct [bn254fr.Element , * bn254fr.Element ](lf , sBlind , rp .Curve )
379+ } else {
380+ sVal = math .InnerProduct (lf , sBlind , rp .Curve )
381+ }
349382 tr .Absorb (sComm .Bytes ())
350383 tr .Absorb (sVal .Bytes ())
351384
@@ -354,33 +387,34 @@ func (rp *rangeProver) Prove() (*RangeProof, error) {
354387 return nil , errors .New ("Unable to obtain challenge rho" )
355388 }
356389
357- // Blinded witness: wit = pExt + rho*sBlind so that
358- // MSM(gExt, wit) = pCommExt + rho*sComm
359- // L(wit) = lVal + rho*sVal
360- wit := make ([]* mathlib.Zr , len (pExt ))
361- for i := range pExt {
362- wit [i ] = rp .Curve .ModAddMul2 (
363- pExt [i ], math .One (rp .Curve ),
364- rho , sBlind [i ],
390+ // Compute wit and witVal — dispatch to native for supported curves.
391+ var wit []* mathlib.Zr
392+ var witVal * mathlib.Zr
393+ if isBLS {
394+ wit , witVal = nativeRPBlindWitness [bls12381fr.Element , * bls12381fr.Element ](
395+ sBlind , pExt , rho , lVal , sVal , rp .Curve )
396+ } else if isBN254 {
397+ wit , witVal = nativeRPBlindWitness [bn254fr.Element , * bn254fr.Element ](
398+ sBlind , pExt , rho , lVal , sVal , rp .Curve )
399+ } else {
400+ wit = make ([]* mathlib.Zr , len (pExt ))
401+ for i := range pExt {
402+ wit [i ] = rp .Curve .ModAddMul2 (
403+ pExt [i ], math .One (rp .Curve ),
404+ rho , sBlind [i ],
405+ rp .Curve .GroupOrder ,
406+ )
407+ }
408+ witVal = rp .Curve .ModAddMul2 (
409+ lVal , math .One (rp .Curve ),
410+ rho , sVal ,
365411 rp .Curve .GroupOrder ,
366412 )
367413 }
368414 witComm := pCommExt .Copy ()
369415 witComm .Add (sComm .Mul (rho ))
370- witVal := rp .Curve .ModAddMul2 (
371- lVal , math .One (rp .Curve ),
372- rho , sVal ,
373- rp .Curve .GroupOrder ,
374- )
375416
376417 // Pad witness / generators / linear form to the next power of 2 for CSP.
377- witSize := uint64 (len (wit ))
378- cspRounds := uint64 (0 )
379- paddedSize := uint64 (1 )
380- for paddedSize < witSize {
381- paddedSize <<= 1
382- cspRounds ++
383- }
384418 for uint64 (len (wit )) < paddedSize {
385419 wit = append (wit , math .Zero (rp .Curve ))
386420 gExt = append (gExt , rp .Curve .GenG1 )
0 commit comments