mirror of
https://github.com/logos-storage/nim-groth16.git
synced 2026-07-21 07:59:32 +00:00
optimize the preprocessing by using the subgroup structure for the second IFFT-s in the convolution
This commit is contained in:
parent
ed363001e4
commit
1f35ef18d2
@ -154,6 +154,67 @@ proc groupConvolveWithWVecBar*( D: Domain, gs: seq[G1] ): seq[G1] =
|
||||
inplaceScalarMulByFFTofWVecBar( gsHat )
|
||||
return inverseGroupFFT( gsHat , D)
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
# only computes the result on a subgroup
|
||||
proc fieldConvolveWithWVecBarOnSubgroup*( sg: Subgroup, xs: seq[F] ): seq[F] =
|
||||
|
||||
let N = xs.len
|
||||
assert( N == sg.bigDomain.domainSize )
|
||||
let D = sg.bigDomain
|
||||
let K = sg.smallDomain.domainSize
|
||||
let ell = N div K
|
||||
|
||||
let fN = intToFr( N )
|
||||
let invN = invFr( fN )
|
||||
let fell : F = intToFr(ell)
|
||||
let invN_per_fell : F = invN / fell
|
||||
|
||||
let xsHat = forwardNTT( xs , D )
|
||||
var ysHat : seq[F] = newSeq[F]( K )
|
||||
|
||||
let c0 = divBy2Fr(oneFr - fN) * invN_per_fell
|
||||
for k in 0..<K:
|
||||
var sum: F = zeroFr
|
||||
for i in 0..<ell:
|
||||
let kk = k + K*i
|
||||
let kk_rev = (if kk==0: 0 else: N-kk)
|
||||
let u = c0 + intToFr(kk_rev) * invN_per_fell
|
||||
sum += u * xsHat[kk]
|
||||
ysHat[k] = sum
|
||||
|
||||
return inverseNTT( ysHat , sg.smallDomain )
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
proc groupConvolveWithWVecOnSubgroup*( sg: Subgroup, pts: seq[G1] ): seq[G1] =
|
||||
|
||||
let N = pts.len
|
||||
assert( N == sg.bigDomain.domainSize )
|
||||
let D = sg.bigDomain
|
||||
let K = sg.smallDomain.domainSize
|
||||
let ell = N div K
|
||||
|
||||
let fN = intToFr( N )
|
||||
let invN = invFr( fN )
|
||||
let fell : F = intToFr(ell)
|
||||
let invN_per_fell : F = invN / fell
|
||||
|
||||
var ptsHat = forwardGroupFFT( pts , D )
|
||||
|
||||
var small : seq[G1] = newSeq[G1]( K )
|
||||
var miniPts : seq[G1] = newSeq[G1]( ell )
|
||||
var miniCfs : seq[F] = newSeq[F] ( ell )
|
||||
let c0 = divBy2Fr(oneFr - fN) * invN_per_fell
|
||||
for k in 0..<K:
|
||||
for i in 0..<ell:
|
||||
let kk = k + K*i
|
||||
miniCfs[i] = c0 + intToFr(kk) * invN_per_fell
|
||||
miniPts[i] = ptsHat[kk]
|
||||
small[k] = msmConstantineG1( miniCfs , miniPts )
|
||||
|
||||
return inverseGroupFFT( small , sg.smallDomain )
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# computes the vectors A*z, B*z (but skips C*z)
|
||||
|
||||
@ -9,8 +9,8 @@ import std/options
|
||||
|
||||
import taskpools
|
||||
|
||||
import constantine/math/arithmetic
|
||||
import constantine/named/properties_fields
|
||||
#import constantine/math/arithmetic
|
||||
#import constantine/named/properties_fields
|
||||
|
||||
import groth16/bn128
|
||||
import groth16/bn128/arrays
|
||||
@ -20,9 +20,9 @@ import groth16/zkey_types
|
||||
import groth16/files/witness
|
||||
|
||||
import groth16/math/domain
|
||||
import groth16/math/ntt
|
||||
import groth16/math/poly
|
||||
import groth16/math/convolution
|
||||
#import groth16/math/poly
|
||||
#import groth16/math/ntt
|
||||
|
||||
import groth16/prover/types
|
||||
import groth16/prover/shared
|
||||
@ -30,7 +30,6 @@ import groth16/partial/finish
|
||||
|
||||
import groth16/dynamic/shared
|
||||
import groth16/dynamic/v1/types
|
||||
import groth16/dynamic/v1/setup
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -10,12 +10,10 @@
|
||||
# this is V1, the version closest to the Dynark paper
|
||||
#
|
||||
|
||||
import std/options
|
||||
|
||||
import taskpools
|
||||
|
||||
import constantine/math/arithmetic
|
||||
import constantine/named/properties_fields
|
||||
#import constantine/named/properties_fields
|
||||
|
||||
import groth16/bn128
|
||||
import groth16/bn128/arrays
|
||||
@ -24,7 +22,6 @@ import groth16/misc
|
||||
import groth16/zkey_types
|
||||
|
||||
import groth16/math/domain
|
||||
import groth16/math/convolution
|
||||
import groth16/math/poly
|
||||
|
||||
import groth16/partial/precalc
|
||||
@ -32,7 +29,6 @@ import groth16/partial/precalc
|
||||
import groth16/dynamic/shared
|
||||
import groth16/dynamic/v1/types
|
||||
import groth16/dynamic/v1/setup
|
||||
import groth16/dynamic/v1/finish
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
import taskpools
|
||||
|
||||
import groth16/bn128
|
||||
import groth16/bn128/arrays
|
||||
import groth16/misc
|
||||
#import groth16/bn128/arrays
|
||||
|
||||
import groth16/math/domain
|
||||
import groth16/math/group_fft
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#import constantine/named/properties_fields
|
||||
|
||||
import groth16/bn128
|
||||
import groth16/math/domain
|
||||
#import groth16/math/domain
|
||||
#import groth16/math/ntt
|
||||
#import groth16/math/poly
|
||||
|
||||
|
||||
@ -26,22 +26,70 @@ import groth16/partial/precalc
|
||||
|
||||
import groth16/dynamic/shared
|
||||
import groth16/dynamic/permute
|
||||
import groth16/dynamic/v2/types as v2types
|
||||
# import groth16/dynamic/v2/types as v2types
|
||||
import groth16/dynamic/v2/preprocess
|
||||
import groth16/dynamic/v3/types
|
||||
import groth16/dynamic/v3/setup
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
func convert_preprocess_V2_to_V3( v2: DynaPreprocessV2 ): DynaPreprocessV3 =
|
||||
return DynaPreprocessV3( unified: v2.unified )
|
||||
func projectionElementsV3*(setup: DynaSetupV3, As: seq[F] ): seq[G1] =
|
||||
let sg = setup.imageSubgroup
|
||||
let D = sg.bigDomain
|
||||
let N = D.domainSize
|
||||
let K = sg.smallDomain.domainSize
|
||||
let ell = N div K
|
||||
|
||||
func convert_setup_V3_to_V2( v3: DynaSetupV3 ): DynaSetupV2 =
|
||||
let fakePhi: seq[G1] = newSeq[G1]()
|
||||
return DynaSetupV2( weightVec : v3.weightVec ,
|
||||
pointsDeltaLZ : v3.pointsDeltaLZ ,
|
||||
wConvDeltaLZ : v3.wConvDeltaLZ ,
|
||||
diagPhiPoints : fakePhi )
|
||||
var Us: seq[G1] = newSeq[G1]( K )
|
||||
|
||||
let fldN : F = intToFr( N )
|
||||
let sumW : F = sumOfWVec( N )
|
||||
|
||||
let WBarStarA : seq[F] = fieldConvolveWithWVecBarOnSubgroup( sg , As )
|
||||
let ALstarW : seq[G1] = groupConvolveWithWVecOnSubgroup( sg , pointwiseScaleG1( As , setup.pointsDeltaLZ ) )
|
||||
|
||||
# 2*d scalar multiplications + the group convolution above
|
||||
for k in 0..<K:
|
||||
|
||||
let ellk = ell*k
|
||||
let cf : F = WBarStarA[k] - As[ellk] * sumW
|
||||
Us[k] = ALstarW[k] - (As[ellk] ** setup.wConvDeltaLZ[ellk]) + (cf ** setup.pointsDeltaLZ[ellk])
|
||||
|
||||
return Us
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
proc dynaPreprocessV3*(zkey: ZKey, setup: DynaSetupV3, partialAB: PartialAB, partial_mask: seq[bool], zdeltaMask: seq[bool] ): DynaPreprocessV3 =
|
||||
let sg = setup.imageSubgroup
|
||||
let D = sg.bigDomain
|
||||
let K = sg.smallDomain.domainSize
|
||||
let N = D.domainSize
|
||||
let ell = N div K
|
||||
|
||||
var projA_mini: seq[G1]
|
||||
var projB_mini: seq[G1]
|
||||
withMeasureTime(true," + the \"projection\" points U_k, V_k"):
|
||||
projA_mini = projectionElementsV3( setup , partialAB.valuesAz )
|
||||
projB_mini = projectionElementsV3( setup , partialAB.valuesBz )
|
||||
|
||||
let m = countTrues(zdeltaMask)
|
||||
var Xs: seq[G1] = newSeq[G1]( m )
|
||||
|
||||
let points_C1 = compactifyPointsC1( zkey, partial_mask )
|
||||
|
||||
withMeasureTime(true," + the \"unified\" points X_j"):
|
||||
|
||||
let matABC = zkeyToSparseMatrices(zkey)
|
||||
let colsA = selectTrues( zdeltaMask , matABC.A.columns )
|
||||
let colsB = selectTrues( zdeltaMask , matABC.B.columns )
|
||||
|
||||
for j in 0..<m:
|
||||
var h : G1 = points_C1[j]
|
||||
for (k,a) in colsA[j].pairs: h += (a ** projB_mini[k div ell])
|
||||
for (k,b) in colsB[j].pairs: h += (b ** projA_mini[k div ell])
|
||||
Xs[j] = h
|
||||
|
||||
return DynaPreprocessV3( unified: Xs )
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@ -84,15 +132,14 @@ proc dynaPreProofV3*(zkey: ZKey, setup: DynaSetupV3, partialWitness: PartialWitn
|
||||
|
||||
partialProof.partial_pi_c += nonlin
|
||||
|
||||
var preprocessV3 : DynaPreprocessV3
|
||||
var preprocess : DynaPreprocessV3
|
||||
withMeasureTime(printTimings,"precomputing the \"projection\" and then the unified points"):
|
||||
let setupV2 = convert_setup_V3_to_V2( setup )
|
||||
preprocessV3 = convert_preprocess_V2_to_V3( dynaPreprocessV2( zkey, setupV2, partialAB, partialMask, zdeltaMask ))
|
||||
preprocess = dynaPreprocessV3( zkey, setup, partialAB, partialMask, zdeltaMask )
|
||||
|
||||
return DynaPreProofV3( partialProof : partialProof ,
|
||||
deltaImages : deltaImages ,
|
||||
dynaSetup : setup ,
|
||||
dynaPreprocess : preprocessV3 )
|
||||
dynaPreprocess : preprocess )
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -32,12 +32,86 @@ func groupConvolution*(xs: seq[F], gs: seq[G1]): seq[G1] =
|
||||
assert( N == gs.len )
|
||||
let D = createDomain( N )
|
||||
|
||||
let us = forwardNTT(xs, D)
|
||||
let hs = forwardGroupFFT(gs, D)
|
||||
let us = forwardNTT(xs, D)
|
||||
let hs = forwardGroupFFT(gs, D)
|
||||
let rs = pointwiseScaleG1(us, hs)
|
||||
|
||||
return inverseGroupFFT(rs, D)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
func fieldConvolutionOnSubgroup*(sg: Subgroup, xs: seq[F], ys: seq[F]): seq[F] =
|
||||
let N = xs.len
|
||||
assert( N == ys.len )
|
||||
assert( N == sg.bigDomain.domainSize )
|
||||
let D = sg.bigDomain
|
||||
let K = sg.smallDomain.domainSize
|
||||
let ell = N div K
|
||||
let fell : F = intToFr(ell)
|
||||
let invfell : F = invFr(fell)
|
||||
|
||||
let us = forwardNTT(xs, D)
|
||||
let vs = forwardNTT(ys, D)
|
||||
|
||||
var ws: seq[F] = newSeq[F]( K )
|
||||
for k in 0..<K:
|
||||
var sum: F = zeroFr
|
||||
for i in 0..<ell:
|
||||
sum += us[k + i*K] * vs[k + i*K]
|
||||
ws[k] = sum * invfell
|
||||
|
||||
return inverseNTT(ws, sg.smallDomain)
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
# only computes the result in a subgroup
|
||||
func groupConvolutionOnSubgroup*(sg: Subgroup, xs: seq[F], gs: seq[G1]): seq[G1] =
|
||||
let N = xs.len
|
||||
assert( N == gs.len )
|
||||
assert( N == sg.bigDomain.domainSize )
|
||||
let D = sg.bigDomain
|
||||
let K = sg.smallDomain.domainSize
|
||||
let ell = N div K
|
||||
let fell : F = intToFr(ell)
|
||||
let invfell : F = invFr(fell)
|
||||
|
||||
let us = forwardNTT(xs, D)
|
||||
let hs = forwardGroupFFT(gs, D)
|
||||
|
||||
var rs : seq[G1] = newSeq[G1]( K )
|
||||
var miniPts : seq[G1] = newSeq[G1]( ell )
|
||||
var miniCfs : seq[F] = newSeq[F] ( ell )
|
||||
for k in 0..<K:
|
||||
for i in 0..<ell:
|
||||
miniCfs[i] = us[k + K*i] * invfell
|
||||
miniPts[i] = hs[k + K*i]
|
||||
rs[k] = msmConstantineG1( miniCfs , miniPts )
|
||||
|
||||
return inverseGroupFFT(rs, sg.smallDomain)
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
proc testFieldConvolutionOnSubgroup*(N: int, K: int): bool =
|
||||
let sg = createSubgroup( createDomain(N) , K )
|
||||
|
||||
let xs = randFrSeq(N)
|
||||
let ys = randFrSeq(N)
|
||||
|
||||
let target = selectOnSubgroup( sg , fieldConvolution(xs, ys) )
|
||||
let smart = fieldConvolutionOnSubgroup( sg, xs, ys )
|
||||
return isEqualFrSeq(target , smart)
|
||||
|
||||
|
||||
proc testGroupConvolutionOnSubgroup*(N: int, K: int): bool =
|
||||
let sg = createSubgroup( createDomain(N) , K )
|
||||
|
||||
let xs = randFrSeq(N)
|
||||
let ps = randG1Seq(N)
|
||||
|
||||
let target = selectOnSubgroup( sg , groupConvolution(xs, ps) )
|
||||
let smart = groupConvolutionOnSubgroup( sg, xs, ps )
|
||||
return isEqualG1Seq(target , smart)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# naive reference implementations for testing
|
||||
|
||||
|
||||
@ -17,9 +17,9 @@ import groth16/math/convolution
|
||||
|
||||
import groth16/dynamic/types
|
||||
import groth16/dynamic/shared
|
||||
import groth16/dynamic/setup
|
||||
import groth16/dynamic/preprocess
|
||||
import groth16/dynamic/finish
|
||||
import groth16/dynamic/v1/preprocess
|
||||
#import groth16/dynamic/v1/setup
|
||||
#import groth16/dynamic/v1/finish
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@ -30,7 +30,9 @@ func ones(N : int): seq[F] = constSeq(N, oneFr)
|
||||
suite "dynamic proof (Dynark) tests":
|
||||
|
||||
let N : int = 128
|
||||
let D = createDomain( N )
|
||||
let K : int = 32
|
||||
let D = createDomain( N )
|
||||
let sg = createSubgroup( D , K )
|
||||
let tau : F = randFr()
|
||||
let delta : F = randFr()
|
||||
|
||||
@ -75,6 +77,12 @@ suite "dynamic proof (Dynark) tests":
|
||||
let rhs = fieldConvolution( xs , calculateWVecBar(D) )
|
||||
check isEqualFrSeq( lhs , rhs )
|
||||
|
||||
test "field convolution with WvecBar on a subgroup":
|
||||
let xs = randFrSeq( N )
|
||||
let lhs = fieldConvolveWithWVecBarOnSubgroup( sg , xs )
|
||||
let rhs = selectOnSubgroup( sg , fieldConvolution( xs , calculateWVecBar(D) ) )
|
||||
check isEqualFrSeq( lhs , rhs )
|
||||
|
||||
test "group convolution with Wvec":
|
||||
let gs = randG1Seq( N )
|
||||
let lhs = groupConvolveWithWVec( D , gs )
|
||||
@ -87,6 +95,12 @@ suite "dynamic proof (Dynark) tests":
|
||||
let rhs = groupConvolution( calculateWVecBar(D) , gs )
|
||||
check isEqualG1Seq( lhs , rhs )
|
||||
|
||||
test "group convolution with Wvec on a subgroup":
|
||||
let gs = randG1Seq( N )
|
||||
let lhs = groupConvolveWithWVecOnSubgroup( sg , gs )
|
||||
let rhs = selectOnSubgroup( sg , groupConvolution( calculateWVec(D) , gs ) )
|
||||
check isEqualG1Seq( lhs , rhs )
|
||||
|
||||
test "expansion of the product of Lagrange polynomials":
|
||||
var ok = true
|
||||
for i in 0..<N:
|
||||
|
||||
@ -84,4 +84,10 @@ suite "convolution checks":
|
||||
test "FFT group convolutions vs. slow reference":
|
||||
check isEqualG1Seq( groupConvolution(xs,gs) , naiveGroupConvolution(xs,gs) )
|
||||
|
||||
test "FFT field convolution evaluated on a subgroup":
|
||||
check testFieldConvolutionOnSubgroup( 32 , 8 )
|
||||
|
||||
test "FFT group convolution evaluated on a subgroup":
|
||||
check testGroupConvolutionOnSubgroup( 128 , 16 )
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user