Merge 2ae270a8079081cf7c924852f8f93ec918b93217 into 73b5ae2734050d64157afbc29d364345ff0ec211

This commit is contained in:
aimendj 2026-01-29 11:47:44 +00:00 committed by GitHub
commit a5919e93a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 698 additions and 0 deletions

View File

@ -0,0 +1,146 @@
import std/unittest
import groth16/bn128/fields
import groth16/fake_setup
import groth16/zkey_types
import groth16/files/r1cs
suite "fake setup":
const testWitnessCfg =
WitnessConfig( nWires: 5
, nPubOut: 1
, nPubIn: 1
, nPrivIn: 2
, nLabels: 0
)
const testConstraint1: Constraint = (
@[ (wireIdx: 0, value: oneFr) ] ,
@[ (wireIdx: 1, value: oneFr) ] ,
@[ (wireIdx: 2, value: oneFr) ]
)
const testConstraints: seq[Constraint] = @[ testConstraint1 ]
const testLabels: seq[int] = @[]
const testR1CS =
R1CS( r: primeR
, cfg: testWitnessCfg
, nConstr: testConstraints.len
, constraints: testConstraints
, wireToLabel: testLabels
)
test "create fake circuit setup - JensGroth":
let zkey = createFakeCircuitSetup( testR1CS, flavour=JensGroth )
check zkey.header.curve == "bn128"
check zkey.header.flavour == JensGroth
check zkey.header.nvars == testWitnessCfg.nWires
check zkey.header.npubs == testWitnessCfg.nPubOut + testWitnessCfg.nPubIn
test "create fake circuit setup - Snarkjs":
let zkey = createFakeCircuitSetup( testR1CS, flavour=Snarkjs )
check zkey.header.curve == "bn128"
check zkey.header.flavour == Snarkjs
check zkey.header.nvars == testWitnessCfg.nWires
check zkey.header.npubs == testWitnessCfg.nPubOut + testWitnessCfg.nPubIn
test "fake setup header consistency":
let zkey = createFakeCircuitSetup( testR1CS, flavour=Snarkjs )
let header = zkey.header
check header.domainSize == (1 shl header.logDomainSize)
check header.domainSize >= testR1CS.nConstr + header.npubs + 1
test "fake setup spec points":
let zkey = createFakeCircuitSetup( testR1CS, flavour=Snarkjs )
let spec = zkey.specPoints
check true
check true
test "fake setup verifier points":
let zkey = createFakeCircuitSetup( testR1CS, flavour=Snarkjs )
let vPoints = zkey.vPoints
let expectedLen = testWitnessCfg.nPubOut + testWitnessCfg.nPubIn + 1
check vPoints.pointsIC.len == expectedLen
test "fake setup prover points":
let zkey = createFakeCircuitSetup( testR1CS, flavour=Snarkjs )
let pPoints = zkey.pPoints
check pPoints.pointsA1.len == testWitnessCfg.nWires
check pPoints.pointsB1.len == testWitnessCfg.nWires
check pPoints.pointsB2.len == testWitnessCfg.nWires
check pPoints.pointsC1.len == testWitnessCfg.nWires - (testWitnessCfg.nPubOut + testWitnessCfg.nPubIn + 1)
check pPoints.pointsH1.len > 0
test "fake setup coefficients":
let zkey = createFakeCircuitSetup( testR1CS, flavour=Snarkjs )
check zkey.coeffs.len > 0
for coeff in zkey.coeffs:
check coeff.row >= 0
check coeff.col >= 0
check coeff.col < testWitnessCfg.nWires
test "random toxic waste":
let toxic1 = randomToxicWaste()
let toxic2 = randomToxicWaste()
check not isEqualFr(toxic1.alpha, toxic2.alpha) or
not isEqualFr(toxic1.beta, toxic2.beta) or
not isEqualFr(toxic1.gamma, toxic2.gamma) or
not isEqualFr(toxic1.delta, toxic2.delta) or
not isEqualFr(toxic1.tau, toxic2.tau)
test "R1CS to coefficients conversion":
let coeffs = r1csToCoeffs( testR1CS )
check coeffs.len > 0
var hasA = false
var hasB = false
for coeff in coeffs:
if coeff.matrix == MatrixA:
hasA = true
if coeff.matrix == MatrixB:
hasB = true
check hasA or hasB
test "R1CS to sparse matrices":
let matrices = r1csToSparseMatrices( testR1CS )
check matrices.A.len == testWitnessCfg.nWires
check matrices.B.len == testWitnessCfg.nWires
check matrices.C.len == testWitnessCfg.nWires
test "fake setup with different flavours produces different H points":
let zkey1 = createFakeCircuitSetup( testR1CS, flavour=JensGroth )
let zkey2 = createFakeCircuitSetup( testR1CS, flavour=Snarkjs )
check zkey1.pPoints.pointsH1.len == zkey2.pPoints.pointsH1.len
test "fake setup domain size":
let zkey = createFakeCircuitSetup( testR1CS, flavour=Snarkjs )
let domainSize = zkey.header.domainSize
check (domainSize and (domainSize - 1)) == 0
check domainSize >= testR1CS.nConstr + zkey.header.npubs + 1
test "fake setup consistency":
let zkey1 = createFakeCircuitSetup( testR1CS, flavour=Snarkjs )
let zkey2 = createFakeCircuitSetup( testR1CS, flavour=Snarkjs )
check zkey1.header.nvars == zkey2.header.nvars
check zkey1.header.npubs == zkey2.header.npubs
check zkey1.header.domainSize == zkey2.header.domainSize
check zkey1.pPoints.pointsA1.len == zkey2.pPoints.pointsA1.len

View File

@ -0,0 +1,117 @@
import std/unittest
import std/sequtils
import taskpools
import groth16/bn128/fields
import groth16/prover
import groth16/verifier
import groth16/fake_setup
import groth16/zkey_types
import groth16/files/r1cs
import groth16/files/witness
suite "prover and verifier":
const simpleWitnessCfg =
WitnessConfig( nWires: 8
, nPubOut: 1
, nPubIn: 1
, nPrivIn: 3
, nLabels: 0
)
const simpleEq1: Constraint = ( @[] , @[] , @[ (1,minusOneFr) , (2,oneFr) , (7,oneFr) ] )
const simpleEq2: Constraint = ( @[ (3,oneFr) ] , @[ (4,oneFr) ] , @[ (6,oneFr) ] )
const simpleEq3: Constraint = ( @[ (5,oneFr) ] , @[ (6,oneFr) ] , @[ (7,oneFr) ] )
const simpleConstraints: seq[Constraint] = @[ simpleEq1, simpleEq2, simpleEq3 ]
const simpleLabels: seq[int] = @[]
const simpleR1CS =
R1CS( r: primeR
, cfg: simpleWitnessCfg
, nConstr: simpleConstraints.len
, constraints: simpleConstraints
, wireToLabel: simpleLabels
)
let simpleWitnessValues = map( @[ 1, 2023, 1022, 7, 11, 13, 7*11, 7*11*13 ] , intToFr )
let simpleWitness =
Witness( curve: "bn128"
, r: primeR
, nvars: 8
, values: simpleWitnessValues
)
test "prove and verify - JensGroth flavour":
let zkey = createFakeCircuitSetup( simpleR1CS, flavour=JensGroth )
var pool = Taskpool.new()
let proof = generateProof( zkey, simpleWitness, pool )
let vkey = extractVKey( zkey )
let ok = verifyProof( vkey, proof )
pool.shutdown()
check ok
test "prove and verify - Snarkjs flavour":
let zkey = createFakeCircuitSetup( simpleR1CS, flavour=Snarkjs )
var pool = Taskpool.new()
let proof = generateProof( zkey, simpleWitness, pool )
let vkey = extractVKey( zkey )
let ok = verifyProof( vkey, proof )
pool.shutdown()
check ok
test "proof structure":
let zkey = createFakeCircuitSetup( simpleR1CS, flavour=Snarkjs )
var pool = Taskpool.new()
let proof = generateProof( zkey, simpleWitness, pool )
pool.shutdown()
check proof.curve == "bn128"
check proof.publicIO.len == simpleWitnessCfg.nPubOut + simpleWitnessCfg.nPubIn + 1
check true
test "verification key extraction":
let zkey = createFakeCircuitSetup( simpleR1CS, flavour=Snarkjs )
let vkey = extractVKey( zkey )
check vkey.curve == "bn128"
check vkey.vpoints.pointsIC.len == simpleWitnessCfg.nPubOut + simpleWitnessCfg.nPubIn + 1
test "proof structure consistency":
let zkey = createFakeCircuitSetup( simpleR1CS, flavour=Snarkjs )
var pool = Taskpool.new()
let proof1 = generateProof( zkey, simpleWitness, pool )
let proof2 = generateProof( zkey, simpleWitness, pool )
pool.shutdown()
check proof1.publicIO.len == proof2.publicIO.len
check proof1.curve == proof2.curve
check proof1.curve == "bn128"
test "multiple proofs with same setup":
let zkey = createFakeCircuitSetup( simpleR1CS, flavour=Snarkjs )
let vkey = extractVKey( zkey )
var pool = Taskpool.new()
for i in 1..5:
let proof = generateProof( zkey, simpleWitness, pool )
let ok = verifyProof( vkey, proof )
check ok
pool.shutdown()
test "proof with different witness but same public IO":
let altWitnessValues = map( @[ 1, 2023, 1022, 7, 11, 13, 7*11, 7*11*13 ] , intToFr )
let altWitness = Witness( curve: "bn128", r: primeR, nvars: 8, values: altWitnessValues )
let zkey = createFakeCircuitSetup( simpleR1CS, flavour=Snarkjs )
var pool = Taskpool.new()
let proof = generateProof( zkey, altWitness, pool )
let vkey = extractVKey( zkey )
let ok = verifyProof( vkey, proof )
pool.shutdown()
check ok

140
tests/groth16/testR1CS.nim Normal file
View File

@ -0,0 +1,140 @@
import std/unittest
import groth16/bn128/fields
import groth16/files/r1cs
suite "R1CS operations":
test "R1CS creation":
let cfg = WitnessConfig(
nWires: 8,
nPubOut: 1,
nPubIn: 1,
nPrivIn: 3,
nLabels: 0
)
let constraint1: Constraint = (
A: @[(wireIdx: 1, value: minusOneFr), (wireIdx: 2, value: oneFr), (wireIdx: 7, value: oneFr)],
B: @[],
C: @[]
)
let constraint2: Constraint = (
A: @[(wireIdx: 3, value: oneFr)],
B: @[(wireIdx: 4, value: oneFr)],
C: @[(wireIdx: 6, value: oneFr)]
)
let constraints = @[constraint1, constraint2]
let r1cs = R1CS(
r: primeR,
cfg: cfg,
nConstr: constraints.len,
constraints: constraints,
wireToLabel: @[]
)
check r1cs.cfg.nWires == 8
check r1cs.nConstr == 2
check r1cs.constraints.len == 2
test "R1CS constraint structure":
let constraint: Constraint = (
A: @[(wireIdx: 0, value: oneFr), (wireIdx: 1, value: intToFr(2))],
B: @[(wireIdx: 2, value: intToFr(3))],
C: @[(wireIdx: 3, value: intToFr(4))]
)
check constraint.A.len == 2
check constraint.B.len == 1
check constraint.C.len == 1
check isEqualFr(constraint.A[0].value, oneFr)
check isEqualFr(constraint.A[1].value, intToFr(2))
test "R1CS witness config":
let cfg = WitnessConfig(
nWires: 10,
nPubOut: 2,
nPubIn: 3,
nPrivIn: 4,
nLabels: 1
)
check cfg.nWires == 10
check cfg.nPubOut == 2
check cfg.nPubIn == 3
check cfg.nPrivIn == 4
check cfg.nLabels == 1
test "R1CS term creation":
let term1: Term = (wireIdx: 5, value: intToFr(42))
let term2: Term = (wireIdx: 3, value: minusOneFr)
check term1.wireIdx == 5
check isEqualFr(term1.value, intToFr(42))
check term2.wireIdx == 3
check isEqualFr(term2.value, minusOneFr)
test "R1CS linear combination":
let linComb: LinComb = @[
(wireIdx: 0, value: oneFr),
(wireIdx: 1, value: intToFr(2)),
(wireIdx: 2, value: intToFr(3))
]
check linComb.len == 3
check linComb[0].wireIdx == 0
check isEqualFr(linComb[1].value, intToFr(2))
test "R1CS constraint evaluation":
let x = intToFr(5)
let y = intToFr(7)
let expected = x * y
let constraint: Constraint = (
A: @[(wireIdx: 0, value: x)],
B: @[(wireIdx: 1, value: y)],
C: @[(wireIdx: 2, value: expected)]
)
let product = constraint.A[0].value * constraint.B[0].value
check isEqualFr(product, constraint.C[0].value)
test "R1CS empty constraint":
let emptyConstraint: Constraint = (
A: @[],
B: @[],
C: @[]
)
check emptyConstraint.A.len == 0
check emptyConstraint.B.len == 0
check emptyConstraint.C.len == 0
test "R1CS multiple constraints":
let constraints = @[
(A: @[(wireIdx: 0, value: oneFr)], B: @[(wireIdx: 1, value: oneFr)], C: @[(wireIdx: 2, value: oneFr)]),
(A: @[(wireIdx: 2, value: oneFr)], B: @[(wireIdx: 3, value: oneFr)], C: @[(wireIdx: 4, value: oneFr)]),
(A: @[(wireIdx: 4, value: oneFr)], B: @[(wireIdx: 5, value: oneFr)], C: @[(wireIdx: 6, value: oneFr)])
]
check constraints.len == 3
for i, constraint in constraints:
check constraint.A.len > 0 or constraint.B.len > 0 or constraint.C.len > 0
test "R1CS wire to label mapping":
let wireToLabel = @[0, 1, 2, 3, 4]
let r1cs = R1CS(
r: primeR,
cfg: WitnessConfig(nWires: 5, nPubOut: 0, nPubIn: 0, nPrivIn: 0, nLabels: 0),
nConstr: 0,
constraints: @[],
wireToLabel: wireToLabel
)
check r1cs.wireToLabel.len == 5
check r1cs.wireToLabel[0] == 0
check r1cs.wireToLabel[4] == 4

View File

@ -0,0 +1,203 @@
import std/unittest
import taskpools
import groth16/bn128
import groth16/prover
import groth16/verifier
import groth16/fake_setup
import groth16/zkey_types
import groth16/files/r1cs
import groth16/files/witness
import groth16/math/poly
import groth16/math/domain
import groth16/math/ntt
suite "regression tests":
test "edge case - single constraint circuit":
const cfg = WitnessConfig( nWires: 3, nPubOut: 0, nPubIn: 1, nPrivIn: 1, nLabels: 0 )
const constraint: Constraint = (
@[ (wireIdx: 0, value: oneFr) ] ,
@[ (wireIdx: 1, value: oneFr) ] ,
@[ (wireIdx: 2, value: oneFr) ]
)
const r1cs = R1CS( r: primeR, cfg: cfg, nConstr: 1, constraints: @[constraint], wireToLabel: @[] )
let witness = Witness( curve: "bn128", r: primeR, nvars: 3, values: @[oneFr, intToFr(2), intToFr(2)] )
let zkey = createFakeCircuitSetup( r1cs, flavour=Snarkjs )
var pool = Taskpool.new()
let proof = generateProof( zkey, witness, pool )
let vkey = extractVKey( zkey )
let ok = verifyProof( vkey, proof )
pool.shutdown()
check ok
test "edge case - empty public inputs":
const cfg = WitnessConfig( nWires: 4, nPubOut: 0, nPubIn: 0, nPrivIn: 2, nLabels: 0 )
const constraint: Constraint = (
@[ (wireIdx: 1, value: oneFr) ] ,
@[ (wireIdx: 2, value: oneFr) ] ,
@[ (wireIdx: 3, value: oneFr) ]
)
const r1cs = R1CS( r: primeR, cfg: cfg, nConstr: 1, constraints: @[constraint], wireToLabel: @[] )
let witness = Witness( curve: "bn128", r: primeR, nvars: 4, values: @[oneFr, intToFr(2), intToFr(2), intToFr(4)] )
let zkey = createFakeCircuitSetup( r1cs, flavour=Snarkjs )
var pool = Taskpool.new()
let proof = generateProof( zkey, witness, pool )
let vkey = extractVKey( zkey )
let ok = verifyProof( vkey, proof )
pool.shutdown()
check ok
test "edge case - large number of constraints":
let cfg = WitnessConfig( nWires: 10, nPubOut: 1, nPubIn: 1, nPrivIn: 7, nLabels: 0 )
var constraints: seq[Constraint] = @[]
for i in 0..<20:
constraints.add((
@[ (wireIdx: i mod 10, value: oneFr) ],
@[ (wireIdx: (i+1) mod 10, value: oneFr) ],
@[ (wireIdx: (i+2) mod 10, value: oneFr) ]
))
let witnessValues = @[oneFr, oneFr, oneFr, oneFr, oneFr, oneFr, oneFr, oneFr, oneFr, oneFr]
let r1cs = R1CS( r: primeR, cfg: cfg, nConstr: constraints.len, constraints: constraints, wireToLabel: @[] )
let witness = Witness( curve: "bn128", r: primeR, nvars: 10, values: witnessValues )
let zkey = createFakeCircuitSetup( r1cs, flavour=Snarkjs )
var pool = Taskpool.new()
let proof = generateProof( zkey, witness, pool )
let vkey = extractVKey( zkey )
let ok = verifyProof( vkey, proof )
pool.shutdown()
check ok
test "edge case - polynomial with leading zeros":
let P = Poly(coeffs: @[intToFr(1), intToFr(2), zeroFr, zeroFr])
check polyDegree(P) == 1
check not polyIsZero(P)
test "edge case - domain size 2":
let D = createDomain(2)
check D.domainSize == 2
check D.logDomainSize == 1
let points = enumerateDomain(D)
check points.len == 2
check isEqualFr(points[0], oneFr)
check isEqualFr(points[1], D.domainGen)
test "edge case - very large domain":
let D = createDomain(1024)
check D.domainSize == 1024
check D.logDomainSize == 10
let points = enumerateDomain(D)
check points.len == 1024
let wrapAround = points[1023] * D.domainGen
check isEqualFr(wrapAround, oneFr)
test "edge case - field element at prime boundary":
let minusOne = minusOneFr
let one = oneFr
let sum = minusOne + one
check isZeroFr(sum)
test "edge case - batch inversion with single element":
let xs = @[intToFr(5)]
let ys = batchInverseFr(xs)
check ys.len == 1
check isEqualFr(xs[0] * ys[0], oneFr)
test "edge case - batch inversion with zero element":
let xs = @[intToFr(1), intToFr(2), intToFr(3)]
let ys = batchInverseFr(xs)
for i in 0..<xs.len:
check isEqualFr(xs[i] * ys[i], oneFr)
test "regression - polynomial multiplication identity":
let P = Poly(coeffs: @[intToFr(1), intToFr(2), intToFr(3)])
let onePoly = Poly(coeffs: @[oneFr])
let result = P * onePoly
check polyIsEqual(result, P)
test "regression - polynomial addition zero":
let P = Poly(coeffs: @[intToFr(1), intToFr(2)])
let zeroPoly = Poly(coeffs: @[zeroFr])
let result = P + zeroPoly
check polyIsEqual(result, P)
test "regression - NTT round trip with two elements":
let D = createDomain(2)
let input = @[intToFr(1), intToFr(2)]
let forward = forwardNTT(input, D)
let inverse = inverseNTT(forward, D)
check input.len == inverse.len
check isEqualFr(input[0], inverse[0])
check isEqualFr(input[1], inverse[1])
test "regression - vanishing polynomial at domain points":
let N = 8
let Z = vanishingPoly(N)
let D = createDomain(N)
let points = enumerateDomain(D)
for point in points:
let eval = polyEvalAt(Z, point)
check isZeroFr(eval)
test "regression - Lagrange basis at domain points":
let N = 4
let D = createDomain(N)
let points = enumerateDomain(D)
for k in 0..<N:
let Lk = lagrangePoly(D, k)
for i in 0..<N:
let eval = polyEvalAt(Lk, points[i])
if i == k:
check isEqualFr(eval, oneFr)
else:
check isZeroFr(eval)
test "regression - proof generation with minimal circuit":
const cfg = WitnessConfig( nWires: 2, nPubOut: 0, nPubIn: 0, nPrivIn: 1, nLabels: 0 )
const constraint: Constraint = (
@[ (wireIdx: 0, value: oneFr) ] ,
@[ (wireIdx: 1, value: oneFr) ] ,
@[ (wireIdx: 1, value: oneFr) ]
)
const r1cs = R1CS( r: primeR, cfg: cfg, nConstr: 1, constraints: @[constraint], wireToLabel: @[] )
let witness = Witness( curve: "bn128", r: primeR, nvars: 2, values: @[oneFr, oneFr] )
let zkey = createFakeCircuitSetup( r1cs, flavour=Snarkjs )
var pool = Taskpool.new()
let proof = generateProof( zkey, witness, pool )
let vkey = extractVKey( zkey )
let ok = verifyProof( vkey, proof )
pool.shutdown()
check ok
test "regression - multiple proof generations don't interfere":
const cfg = WitnessConfig( nWires: 3, nPubOut: 0, nPubIn: 1, nPrivIn: 1, nLabels: 0 )
const constraint: Constraint = (
@[ (wireIdx: 0, value: oneFr) ] ,
@[ (wireIdx: 1, value: oneFr) ] ,
@[ (wireIdx: 2, value: oneFr) ]
)
const r1cs = R1CS( r: primeR, cfg: cfg, nConstr: 1, constraints: @[constraint], wireToLabel: @[] )
let witness = Witness( curve: "bn128", r: primeR, nvars: 3, values: @[oneFr, intToFr(2), intToFr(2)] )
let zkey = createFakeCircuitSetup( r1cs, flavour=Snarkjs )
let vkey = extractVKey( zkey )
var pool = Taskpool.new()
for i in 1..10:
let proof = generateProof( zkey, witness, pool )
let ok = verifyProof( vkey, proof )
check ok
pool.shutdown()

View File

@ -0,0 +1,87 @@
import std/unittest
import std/sequtils
import constantine/named/properties_fields
import groth16/bn128
import groth16/bn128/fields
import groth16/files/witness
suite "witness operations":
test "witness creation":
let values = @[oneFr, intToFr(2), intToFr(3), intToFr(4)]
let witness = makeWitnessBN254(values)
check witness.curve == "bn128"
check witness.nvars == 4
check witness.values.len == 4
check isEqualFr(witness.values[0], oneFr)
check isEqualFr(witness.values[1], intToFr(2))
test "witness structure":
let values = map(toSeq(1..10), intToFr)
let witness = makeWitnessBN254(values)
check witness.nvars == 10
check witness.values.len == 10
check true
test "witness with zero values":
let values = @[zeroFr, zeroFr, zeroFr]
let witness = makeWitnessBN254(values)
check witness.nvars == 3
check witness.values.len == 3
check isZeroFr(witness.values[0])
check isZeroFr(witness.values[1])
check isZeroFr(witness.values[2])
test "witness with large values":
let values = @[intToFr(1000000), intToFr(999999), intToFr(123456)]
let witness = makeWitnessBN254(values)
check witness.nvars == 3
check isEqualFr(witness.values[0], intToFr(1000000))
test "witness single value":
let values = @[oneFr]
let witness = makeWitnessBN254(values)
check witness.nvars == 1
check witness.values.len == 1
check isEqualFr(witness.values[0], oneFr)
test "witness empty (should fail or handle gracefully)":
let values: seq[Fr[BN254_Snarks]] = @[]
let witness = makeWitnessBN254(values)
check witness.nvars == 0
check witness.values.len == 0
test "witness field consistency":
let values = @[oneFr, intToFr(5), intToFr(10)]
let witness = makeWitnessBN254(values)
# All values should be valid field elements
check witness.values.len == 3
check isEqualFr(witness.values[0], oneFr)
check isEqualFr(witness.values[1], intToFr(5))
check isEqualFr(witness.values[2], intToFr(10))
test "witness ordering":
let publicOut = intToFr(100)
let publicIn = intToFr(200)
let privateIn = intToFr(300)
let secret = intToFr(400)
let values = @[oneFr, publicOut, publicIn, privateIn, secret]
let witness = makeWitnessBN254(values)
check witness.nvars == 5
check isEqualFr(witness.values[0], oneFr)
check isEqualFr(witness.values[1], publicOut)
check isEqualFr(witness.values[2], publicIn)
check isEqualFr(witness.values[3], privateIn)
check isEqualFr(witness.values[4], secret)

View File

@ -1,3 +1,8 @@
import ./groth16/testProver
import ./groth16/testR1CS
import ./groth16/testWitness
import ./groth16/testProverVerifier
import ./groth16/testFakeSetup
import ./groth16/testRegression