Prover works with zkey (#711)
* rework backend to instantiate key at initialization * add groth16 convertes for solidity * prover taks num samples on construction * add zkey file * rework helpers * rename types * update tests * reworked test helpers * rename types * rework test * test all slots artifacts * bump to latest version
This commit is contained in:
parent
6b86601597
commit
9e13d2251a
|
@ -20,8 +20,11 @@ import ../../types
|
|||
import ../../../stores
|
||||
import ../../../merkletree
|
||||
import ../../../codextypes
|
||||
import ../../../contracts
|
||||
|
||||
export circomcompat
|
||||
import ./converters
|
||||
|
||||
export circomcompat, converters
|
||||
|
||||
type
|
||||
CircomCompat* = object
|
||||
|
@ -32,40 +35,24 @@ type
|
|||
numSamples : int # number of samples per slot
|
||||
r1csPath : string # path to the r1cs file
|
||||
wasmPath : string # path to the wasm file
|
||||
zKeyPath : string # path to the zkey file
|
||||
zkeyPath : string # path to the zkey file
|
||||
backendCfg : ptr CircomBn254Cfg
|
||||
|
||||
CircomG1* = G1
|
||||
CircomG2* = G2
|
||||
|
||||
CircomProof* = Proof
|
||||
CircomKey* = VerifyingKey
|
||||
CircomInputs* = Inputs
|
||||
vkp* : ptr CircomKey
|
||||
|
||||
proc release*(self: CircomCompat) =
|
||||
## Release the backend
|
||||
## Release the ctx
|
||||
##
|
||||
|
||||
if not isNil(self.backendCfg):
|
||||
self.backendCfg.unsafeAddr.releaseCfg()
|
||||
|
||||
proc getVerifyingKey*(
|
||||
self: CircomCompat): ?!ptr CircomKey =
|
||||
## Get the verifying key
|
||||
##
|
||||
|
||||
var
|
||||
cfg: ptr CircomBn254Cfg = self.backendCfg
|
||||
vkpPtr: ptr VerifyingKey = nil
|
||||
|
||||
if cfg.getVerifyingKey(vkpPtr.addr) != ERR_OK or vkpPtr == nil:
|
||||
return failure("Failed to get verifying key")
|
||||
|
||||
success vkpPtr
|
||||
if not isNil(self.vkp):
|
||||
self.vkp.unsafeAddr.release_key()
|
||||
|
||||
proc prove*[H](
|
||||
self: CircomCompat,
|
||||
input: ProofInput[H]): ?!CircomProof =
|
||||
## Encode buffers using a backend
|
||||
input: ProofInputs[H]): ?!CircomProof =
|
||||
## Encode buffers using a ctx
|
||||
##
|
||||
|
||||
# NOTE: All inputs are statically sized per circuit
|
||||
|
@ -86,43 +73,43 @@ proc prove*[H](
|
|||
|
||||
# TODO: All parameters should match circom's static parametter
|
||||
var
|
||||
backend: ptr CircomCompatCtx
|
||||
ctx: ptr CircomCompatCtx
|
||||
|
||||
defer:
|
||||
if backend != nil:
|
||||
backend.addr.releaseCircomCompat()
|
||||
if ctx != nil:
|
||||
ctx.addr.releaseCircomCompat()
|
||||
|
||||
if initCircomCompat(
|
||||
self.backendCfg,
|
||||
addr backend) != ERR_OK or backend == nil:
|
||||
raiseAssert("failed to initialize CircomCompat backend")
|
||||
addr ctx) != ERR_OK or ctx == nil:
|
||||
raiseAssert("failed to initialize CircomCompat ctx")
|
||||
|
||||
var
|
||||
entropy = input.entropy.toBytes
|
||||
dataSetRoot = input.datasetRoot.toBytes
|
||||
slotRoot = input.slotRoot.toBytes
|
||||
|
||||
if backend.pushInputU256Array(
|
||||
if ctx.pushInputU256Array(
|
||||
"entropy".cstring, entropy[0].addr, entropy.len.uint32) != ERR_OK:
|
||||
return failure("Failed to push entropy")
|
||||
|
||||
if backend.pushInputU256Array(
|
||||
if ctx.pushInputU256Array(
|
||||
"dataSetRoot".cstring, dataSetRoot[0].addr, dataSetRoot.len.uint32) != ERR_OK:
|
||||
return failure("Failed to push data set root")
|
||||
|
||||
if backend.pushInputU256Array(
|
||||
if ctx.pushInputU256Array(
|
||||
"slotRoot".cstring, slotRoot[0].addr, slotRoot.len.uint32) != ERR_OK:
|
||||
return failure("Failed to push data set root")
|
||||
|
||||
if backend.pushInputU32(
|
||||
if ctx.pushInputU32(
|
||||
"nCellsPerSlot".cstring, input.nCellsPerSlot.uint32) != ERR_OK:
|
||||
return failure("Failed to push nCellsPerSlot")
|
||||
|
||||
if backend.pushInputU32(
|
||||
if ctx.pushInputU32(
|
||||
"nSlotsPerDataSet".cstring, input.nSlotsPerDataSet.uint32) != ERR_OK:
|
||||
return failure("Failed to push nSlotsPerDataSet")
|
||||
|
||||
if backend.pushInputU32(
|
||||
if ctx.pushInputU32(
|
||||
"slotIndex".cstring, input.slotIndex.uint32) != ERR_OK:
|
||||
return failure("Failed to push slotIndex")
|
||||
|
||||
|
@ -132,7 +119,7 @@ proc prove*[H](
|
|||
slotProof.setLen(self.datasetDepth) # zero pad inputs to correct size
|
||||
|
||||
# arrays are always flattened
|
||||
if backend.pushInputU256Array(
|
||||
if ctx.pushInputU256Array(
|
||||
"slotProof".cstring,
|
||||
slotProof[0].addr,
|
||||
uint (slotProof[0].len * slotProof.len)) != ERR_OK:
|
||||
|
@ -144,14 +131,14 @@ proc prove*[H](
|
|||
data = s.cellData
|
||||
|
||||
merklePaths.setLen(self.slotDepth) # zero pad inputs to correct size
|
||||
if backend.pushInputU256Array(
|
||||
if ctx.pushInputU256Array(
|
||||
"merklePaths".cstring,
|
||||
merklePaths[0].addr,
|
||||
uint (merklePaths[0].len * merklePaths.len)) != ERR_OK:
|
||||
return failure("Failed to push merkle paths")
|
||||
|
||||
data.setLen(self.cellElms * 32) # zero pad inputs to correct size
|
||||
if backend.pushInputU256Array(
|
||||
if ctx.pushInputU256Array(
|
||||
"cellData".cstring,
|
||||
data[0].addr,
|
||||
data.len.uint) != ERR_OK:
|
||||
|
@ -163,7 +150,7 @@ proc prove*[H](
|
|||
let proof =
|
||||
try:
|
||||
if (
|
||||
let res = self.backendCfg.proveCircuit(backend, proofPtr.addr);
|
||||
let res = self.backendCfg.proveCircuit(ctx, proofPtr.addr);
|
||||
res != ERR_OK) or
|
||||
proofPtr == nil:
|
||||
return failure("Failed to prove - err code: " & $res)
|
||||
|
@ -175,55 +162,66 @@ proc prove*[H](
|
|||
|
||||
success proof
|
||||
|
||||
proc verify*(
|
||||
proc verify*[H](
|
||||
self: CircomCompat,
|
||||
proof: CircomProof,
|
||||
inputs: CircomInputs,
|
||||
vkp: CircomKey): ?!bool =
|
||||
## Verify a proof using a backend
|
||||
inputs: ProofInputs[H]): ?!bool =
|
||||
## Verify a proof using a ctx
|
||||
##
|
||||
|
||||
var
|
||||
proofPtr : ptr Proof = unsafeAddr proof
|
||||
inputsPtr: ptr Inputs = unsafeAddr inputs
|
||||
vpkPtr: ptr CircomKey = unsafeAddr vkp
|
||||
proofPtr = unsafeAddr proof
|
||||
inputs = inputs.toCircomInputs()
|
||||
|
||||
let res = verifyCircuit(proofPtr, inputsPtr, vpkPtr)
|
||||
try:
|
||||
let res = verifyCircuit(proofPtr, inputs.addr, self.vkp)
|
||||
if res == ERR_OK:
|
||||
success true
|
||||
elif res == ERR_FAILED_TO_VERIFY_PROOF:
|
||||
success false
|
||||
else:
|
||||
failure("Failed to verify proof - err code: " & $res)
|
||||
finally:
|
||||
inputs.releaseCircomInputs()
|
||||
|
||||
proc init*(
|
||||
_: type CircomCompat,
|
||||
r1csPath : string,
|
||||
wasmPath : string,
|
||||
zKeyPath : string = "",
|
||||
zkeyPath : string = "",
|
||||
slotDepth = DefaultMaxSlotDepth,
|
||||
datasetDepth = DefaultMaxDatasetDepth,
|
||||
blkDepth = DefaultBlockDepth,
|
||||
cellElms = DefaultCellElms,
|
||||
numSamples = DefaultSamplesNum): CircomCompat =
|
||||
## Create a new backend
|
||||
## Create a new ctx
|
||||
##
|
||||
|
||||
var cfg: ptr CircomBn254Cfg
|
||||
var zkey = if zkeyPath.len > 0: zkeyPath.cstring else: nil
|
||||
|
||||
if initCircomConfig(
|
||||
r1csPath.cstring,
|
||||
wasmPath.cstring,
|
||||
if zKeyPath.len > 0: zKeyPath.cstring else: nil,
|
||||
addr cfg) != ERR_OK or cfg == nil:
|
||||
zkey, cfg.addr) != ERR_OK or cfg == nil:
|
||||
if cfg != nil: cfg.addr.releaseCfg()
|
||||
raiseAssert("failed to initialize circom compat config")
|
||||
|
||||
var
|
||||
vkpPtr: ptr VerifyingKey = nil
|
||||
|
||||
if cfg.getVerifyingKey(vkpPtr.addr) != ERR_OK or vkpPtr == nil:
|
||||
if vkpPtr != nil: vkpPtr.addr.releaseKey()
|
||||
raiseAssert("Failed to get verifying key")
|
||||
|
||||
CircomCompat(
|
||||
r1csPath : r1csPath,
|
||||
wasmPath : wasmPath,
|
||||
zKeyPath : zKeyPath,
|
||||
backendCfg : cfg,
|
||||
zkeyPath : zkeyPath,
|
||||
slotDepth : slotDepth,
|
||||
datasetDepth: datasetDepth,
|
||||
blkDepth : blkDepth,
|
||||
cellElms : cellElms,
|
||||
numSamples : numSamples)
|
||||
numSamples : numSamples,
|
||||
backendCfg : cfg,
|
||||
vkp : vkpPtr)
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
## Nim-Codex
|
||||
## Copyright (c) 2024 Status Research & Development GmbH
|
||||
## Licensed under either of
|
||||
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||
## at your option.
|
||||
## This file may not be copied, modified, or distributed except according to
|
||||
## those terms.
|
||||
|
||||
{.push raises: [].}
|
||||
|
||||
import pkg/circomcompat
|
||||
|
||||
import ../../../contracts
|
||||
import ../../types
|
||||
import ../../../merkletree
|
||||
|
||||
type
|
||||
CircomG1* = G1
|
||||
CircomG2* = G2
|
||||
|
||||
CircomProof* = Proof
|
||||
CircomKey* = VerifyingKey
|
||||
CircomInputs* = Inputs
|
||||
|
||||
proc toCircomInputs*(inputs: ProofInputs[Poseidon2Hash]): CircomInputs =
|
||||
var
|
||||
slotIndex = inputs.slotIndex.toF.toBytes.toArray32
|
||||
datasetRoot = inputs.datasetRoot.toBytes.toArray32
|
||||
entropy = inputs.entropy.toBytes.toArray32
|
||||
|
||||
elms = [
|
||||
entropy,
|
||||
datasetRoot,
|
||||
slotIndex
|
||||
]
|
||||
|
||||
let inputsPtr = allocShared0(32 * elms.len)
|
||||
copyMem(inputsPtr, addr elms[0], elms.len * 32)
|
||||
|
||||
CircomInputs(
|
||||
elms: cast[ptr array[32, byte]](inputsPtr),
|
||||
len: elms.len.uint)
|
||||
|
||||
proc releaseCircomInputs*(inputs: var CircomInputs) =
|
||||
if not inputs.elms.isNil:
|
||||
deallocShared(inputs.elms)
|
||||
inputs.elms = nil
|
||||
|
||||
func toG1*(g: CircomG1): G1Point =
|
||||
G1Point(
|
||||
x: UInt256.fromBytesLE(g.x),
|
||||
y: UInt256.fromBytesLE(g.y))
|
||||
|
||||
func toG2*(g: CircomG2): G2Point =
|
||||
G2Point(
|
||||
x: [
|
||||
UInt256.fromBytesLE(g.x[0]),
|
||||
UInt256.fromBytesLE(g.x[1])
|
||||
],
|
||||
y: [
|
||||
UInt256.fromBytesLE(g.y[0]),
|
||||
UInt256.fromBytesLE(g.y[1])
|
||||
])
|
||||
|
||||
func toGroth16Proof*(proof: CircomProof): Groth16Proof =
|
||||
Groth16Proof(
|
||||
a: proof.a.toG1,
|
||||
b: proof.b.toG2,
|
||||
c: proof.c.toG1)
|
|
@ -30,25 +30,27 @@ import ../types
|
|||
|
||||
export backends
|
||||
|
||||
type
|
||||
AnyProof* = CircomProof
|
||||
AnyInputs* = CircomInputs
|
||||
AnyKeys* = CircomKey
|
||||
AnyHash* = Poseidon2Hash
|
||||
AnyBackend* = CircomCompat
|
||||
AnyBuilder* = Poseidon2Builder
|
||||
AnySampler* = Poseidon2Sampler
|
||||
logScope:
|
||||
topics = "codex prover"
|
||||
|
||||
type
|
||||
AnyBackend* = CircomCompat
|
||||
AnyProof* = CircomProof
|
||||
|
||||
AnySampler* = Poseidon2Sampler
|
||||
AnyBuilder* = Poseidon2Builder
|
||||
|
||||
AnyProofInputs* = ProofInputs[Poseidon2Hash]
|
||||
Prover* = ref object of RootObj
|
||||
backend: AnyBackend
|
||||
store: BlockStore
|
||||
nSamples: int
|
||||
|
||||
proc prove*(
|
||||
self: Prover,
|
||||
slotIdx: int,
|
||||
manifest: Manifest,
|
||||
challenge: ProofChallenge,
|
||||
nSamples = DefaultSamplesNum): Future[?!AnyProof] {.async.} =
|
||||
challenge: ProofChallenge): Future[?!(AnyProofInputs, AnyProof)] {.async.} =
|
||||
## Prove a statement using backend.
|
||||
## Returns a future that resolves to a proof.
|
||||
|
||||
|
@ -67,7 +69,7 @@ proc prove*(
|
|||
error "Unable to create data sampler", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
without proofInput =? await sampler.getProofInput(challenge, nSamples), err:
|
||||
without proofInput =? await sampler.getProofInput(challenge, self.nSamples), err:
|
||||
error "Unable to get proof input for slot", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
|
@ -76,23 +78,24 @@ proc prove*(
|
|||
error "Unable to prove slot", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
success proof
|
||||
success (proofInput, proof)
|
||||
|
||||
proc verify*(
|
||||
self: Prover,
|
||||
proof: AnyProof,
|
||||
inputs: AnyInputs,
|
||||
vpk: AnyKeys): Future[?!bool] {.async.} =
|
||||
inputs: AnyProofInputs): Future[?!bool] {.async.} =
|
||||
## Prove a statement using backend.
|
||||
## Returns a future that resolves to a proof.
|
||||
|
||||
self.backend.verify(proof, inputs, vpk)
|
||||
self.backend.verify(proof, inputs)
|
||||
|
||||
proc new*(
|
||||
_: type Prover,
|
||||
store: BlockStore,
|
||||
backend: AnyBackend): Prover =
|
||||
backend: AnyBackend,
|
||||
nSamples: int): Prover =
|
||||
|
||||
Prover(
|
||||
backend: backend,
|
||||
store: store)
|
||||
store: store,
|
||||
nSamples: nSamples)
|
||||
|
|
|
@ -91,7 +91,7 @@ proc getSample*[T, H](
|
|||
proc getProofInput*[T, H](
|
||||
self: DataSampler[T, H],
|
||||
entropy: ProofChallenge,
|
||||
nSamples: Natural): Future[?!ProofInput[H]] {.async.} =
|
||||
nSamples: Natural): Future[?!ProofInputs[H]] {.async.} =
|
||||
## Generate proofs as input to the proving circuit.
|
||||
##
|
||||
|
||||
|
@ -124,7 +124,7 @@ proc getProofInput*[T, H](
|
|||
(await self.getSample(cellIdx, slotTreeCid, slotRoot)).valueOr:
|
||||
return failure("Failed to get sample")
|
||||
|
||||
success ProofInput[H](
|
||||
success ProofInputs[H](
|
||||
entropy: entropy,
|
||||
datasetRoot: datasetRoot,
|
||||
slotProof: slotProof.path,
|
||||
|
|
|
@ -17,7 +17,7 @@ type
|
|||
datasetRoot*: H
|
||||
entropy*: H
|
||||
|
||||
ProofInput*[H] = object
|
||||
ProofInputs*[H] = object
|
||||
entropy*: H
|
||||
datasetRoot*: H
|
||||
slotIndex*: Natural
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -2,8 +2,10 @@
|
|||
import std/sequtils
|
||||
import std/sugar
|
||||
import std/strutils
|
||||
import std/options
|
||||
|
||||
import pkg/poseidon2
|
||||
import pkg/poseidon2/io
|
||||
import pkg/constantine/math/arithmetic
|
||||
import pkg/constantine/math/io/io_bigints
|
||||
import pkg/constantine/math/io/io_fields
|
||||
|
@ -15,7 +17,7 @@ import pkg/codex/utils/json
|
|||
|
||||
export types
|
||||
|
||||
func fromCircomData*[H](cellData: seq[byte]): seq[H] =
|
||||
func fromCircomData*(_: type Poseidon2Hash, cellData: seq[byte]): seq[Poseidon2Hash] =
|
||||
var
|
||||
pos = 0
|
||||
cellElms: seq[Bn254Fr]
|
||||
|
@ -30,43 +32,40 @@ func fromCircomData*[H](cellData: seq[byte]): seq[H] =
|
|||
|
||||
cellElms
|
||||
|
||||
func toPublicInputs*[H](input: ProofInput[H]): PublicInputs[H] =
|
||||
PublicInputs[H](
|
||||
slotIndex: input.slotIndex,
|
||||
datasetRoot: input.datasetRoot,
|
||||
entropy: input.entropy
|
||||
)
|
||||
|
||||
proc toCircomInputs*[H](inputs: PublicInputs[H]): CircomInputs =
|
||||
var
|
||||
slotIndex = inputs.slotIndex.toF.toBytes.toArray32
|
||||
datasetRoot = inputs.datasetRoot.toBytes.toArray32
|
||||
entropy = inputs.entropy.toBytes.toArray32
|
||||
|
||||
elms = [
|
||||
entropy,
|
||||
datasetRoot,
|
||||
slotIndex
|
||||
]
|
||||
|
||||
let inputsPtr = allocShared0(32 * elms.len)
|
||||
copyMem(inputsPtr, addr elms[0], elms.len * 32)
|
||||
|
||||
CircomInputs(
|
||||
elms: cast[ptr array[32, byte]](inputsPtr),
|
||||
len: elms.len.uint
|
||||
)
|
||||
|
||||
proc releaseNimInputs*(inputs: var CircomInputs) =
|
||||
if not inputs.elms.isNil:
|
||||
deallocShared(inputs.elms)
|
||||
inputs.elms = nil
|
||||
|
||||
func toJsonDecimal*(big: BigInt[254]): string =
|
||||
let s = big.toDecimal.strip( leading = true, trailing = false, chars = {'0'} )
|
||||
if s.len == 0: "0" else: s
|
||||
|
||||
func toJson*[H](input: ProofInput[H]): JsonNode =
|
||||
func toJson*(g1: CircomG1): JsonNode =
|
||||
%* {
|
||||
"x": Bn254Fr.fromBytes(g1.x).get.toBig.toJsonDecimal,
|
||||
"y": Bn254Fr.fromBytes(g1.y).get.toBig.toJsonDecimal
|
||||
}
|
||||
|
||||
func toJson*(g2: CircomG2): JsonNode =
|
||||
%* {
|
||||
"x": [
|
||||
Bn254Fr.fromBytes(g2.x[0]).get.toBig.toJsonDecimal,
|
||||
Bn254Fr.fromBytes(g2.x[1]).get.toBig.toJsonDecimal],
|
||||
"y": [
|
||||
Bn254Fr.fromBytes(g2.y[0]).get.toBig.toJsonDecimal,
|
||||
Bn254Fr.fromBytes(g2.y[1]).get.toBig.toJsonDecimal]
|
||||
}
|
||||
|
||||
proc toJson*(vpk: VerifyingKey): JsonNode =
|
||||
let
|
||||
ic = toSeq(cast[ptr UncheckedArray[CircomG1]](vpk.ic).toOpenArray(0, vpk.icLen.int - 1))
|
||||
|
||||
echo ic.len
|
||||
%* {
|
||||
"alpha1": vpk.alpha1.toJson,
|
||||
"beta2": vpk.beta2.toJson,
|
||||
"gamma2": vpk.gamma2.toJson,
|
||||
"delta2": vpk.delta2.toJson,
|
||||
"ic": ic.mapIt( it.toJson )
|
||||
}
|
||||
|
||||
func toJson*(input: ProofInputs[Poseidon2Hash]): JsonNode =
|
||||
var
|
||||
input = input
|
||||
|
||||
|
@ -79,14 +78,14 @@ func toJson*[H](input: ProofInput[H]): JsonNode =
|
|||
"slotRoot": input.slotRoot.toDecimal,
|
||||
"slotProof": input.slotProof.mapIt( it.toBig.toJsonDecimal ),
|
||||
"cellData": input.samples.mapIt(
|
||||
toSeq( it.cellData.elements(H) ).mapIt( it.toBig.toJsonDecimal )
|
||||
toSeq( it.cellData.elements(Poseidon2Hash) ).mapIt( it.toBig.toJsonDecimal )
|
||||
),
|
||||
"merklePaths": input.samples.mapIt(
|
||||
it.merklePaths.mapIt( it.toBig.toJsonDecimal )
|
||||
)
|
||||
}
|
||||
|
||||
func jsonToProofInput*[H](inputJson: JsonNode): ProofInput[H] =
|
||||
func jsonToProofInput*(_: type Poseidon2Hash, inputJson: JsonNode): ProofInputs[Poseidon2Hash] =
|
||||
let
|
||||
cellData =
|
||||
inputJson["cellData"].mapIt(
|
||||
|
@ -107,7 +106,7 @@ func jsonToProofInput*[H](inputJson: JsonNode): ProofInput[H] =
|
|||
block:
|
||||
var
|
||||
big: BigInt[254]
|
||||
hash: H
|
||||
hash: Poseidon2Hash
|
||||
assert bool(big.fromDecimal( it.getStr ))
|
||||
hash.fromBig( big )
|
||||
hash
|
||||
|
@ -118,7 +117,7 @@ func jsonToProofInput*[H](inputJson: JsonNode): ProofInput[H] =
|
|||
block:
|
||||
var
|
||||
big: BigInt[254]
|
||||
hash: H
|
||||
hash: Poseidon2Hash
|
||||
assert bool(big.fromDecimal( it.str ))
|
||||
hash.fromBig( big )
|
||||
hash
|
||||
|
@ -127,7 +126,7 @@ func jsonToProofInput*[H](inputJson: JsonNode): ProofInput[H] =
|
|||
datasetRoot = block:
|
||||
var
|
||||
big: BigInt[254]
|
||||
hash: H
|
||||
hash: Poseidon2Hash
|
||||
assert bool(big.fromDecimal( inputJson["dataSetRoot"].str ))
|
||||
hash.fromBig( big )
|
||||
hash
|
||||
|
@ -135,7 +134,7 @@ func jsonToProofInput*[H](inputJson: JsonNode): ProofInput[H] =
|
|||
slotRoot = block:
|
||||
var
|
||||
big: BigInt[254]
|
||||
hash: H
|
||||
hash: Poseidon2Hash
|
||||
assert bool(big.fromDecimal( inputJson["slotRoot"].str ))
|
||||
hash.fromBig( big )
|
||||
hash
|
||||
|
@ -143,7 +142,7 @@ func jsonToProofInput*[H](inputJson: JsonNode): ProofInput[H] =
|
|||
entropy = block:
|
||||
var
|
||||
big: BigInt[254]
|
||||
hash: H
|
||||
hash: Poseidon2Hash
|
||||
assert bool(big.fromDecimal( inputJson["entropy"].str ))
|
||||
hash.fromBig( big )
|
||||
hash
|
||||
|
@ -152,7 +151,7 @@ func jsonToProofInput*[H](inputJson: JsonNode): ProofInput[H] =
|
|||
nSlotsPerDataSet = inputJson["nSlotsPerDataSet"].getInt
|
||||
slotIndex = inputJson["slotIndex"].getInt
|
||||
|
||||
ProofInput[H](
|
||||
ProofInputs[Poseidon2Hash](
|
||||
entropy: entropy,
|
||||
slotIndex: slotIndex,
|
||||
datasetRoot: datasetRoot,
|
||||
|
@ -161,7 +160,7 @@ func jsonToProofInput*[H](inputJson: JsonNode): ProofInput[H] =
|
|||
nCellsPerSlot: nCellsPerSlot,
|
||||
nSlotsPerDataSet: nSlotsPerDataSet,
|
||||
samples: zip(cellData, merklePaths)
|
||||
.mapIt(Sample[H](
|
||||
.mapIt(Sample[Poseidon2Hash](
|
||||
cellData: it[0],
|
||||
merklePaths: it[1]
|
||||
))
|
||||
|
|
|
@ -3,8 +3,9 @@ import std/sequtils
|
|||
import std/sugar
|
||||
import std/options
|
||||
|
||||
import pkg/chronos
|
||||
import ../../../asynctest
|
||||
|
||||
import pkg/chronos
|
||||
import pkg/poseidon2
|
||||
import pkg/datastore
|
||||
|
||||
|
@ -16,10 +17,6 @@ import pkg/codex/codextypes
|
|||
import pkg/codex/manifest
|
||||
import pkg/codex/stores
|
||||
|
||||
import pkg/constantine/math/arithmetic
|
||||
import pkg/constantine/math/io/io_fields
|
||||
import pkg/constantine/math/io/io_bigints
|
||||
|
||||
import ./helpers
|
||||
import ../helpers
|
||||
|
||||
|
@ -27,56 +24,50 @@ suite "Test Circom Compat Backend - control inputs":
|
|||
let
|
||||
r1cs = "tests/circuits/fixtures/proof_main.r1cs"
|
||||
wasm = "tests/circuits/fixtures/proof_main.wasm"
|
||||
zkey = "tests/circuits/fixtures/proof_main.zkey"
|
||||
|
||||
var
|
||||
circom: CircomCompat
|
||||
verifyingKeyPtr: ptr CircomKey
|
||||
proofInput: ProofInput[Poseidon2Hash]
|
||||
publicInputs: CircomInputs
|
||||
proofInputs: ProofInputs[Poseidon2Hash]
|
||||
|
||||
setup:
|
||||
let
|
||||
inputData = readFile("tests/circuits/fixtures/input.json")
|
||||
inputJson = parseJson(inputData)
|
||||
|
||||
proofInput = jsonToProofInput[Poseidon2Hash](inputJson)
|
||||
publicInputs = toPublicInputs[Poseidon2Hash](proofInput).toCircomInputs
|
||||
|
||||
# circom = CircomCompat.init(r1cs, wasm, zkey)
|
||||
circom = CircomCompat.init(r1cs, wasm)
|
||||
verifyingKeyPtr = circom.getVerifyingKey().tryGet
|
||||
proofInputs = Poseidon2Hash.jsonToProofInput(inputJson)
|
||||
circom = CircomCompat.init(r1cs, wasm, zkey)
|
||||
|
||||
teardown:
|
||||
publicInputs.releaseNimInputs() # this is allocated by nim
|
||||
verifyingKeyPtr.addr.releaseKey() # this comes from the rust FFI
|
||||
circom.release() # this comes from the rust FFI
|
||||
|
||||
test "Should verify with correct inputs":
|
||||
let
|
||||
proof = circom.prove(proofInput).tryGet
|
||||
proof = circom.prove(proofInputs).tryGet
|
||||
|
||||
check circom.verify(proof, publicInputs, verifyingKeyPtr[]).tryGet
|
||||
check circom.verify(proof, proofInputs).tryGet
|
||||
|
||||
test "Should not verify with incorrect inputs":
|
||||
proofInput.slotIndex = 1 # change slot index
|
||||
proofInputs.slotIndex = 1 # change slot index
|
||||
|
||||
let
|
||||
proof = circom.prove(proofInput).tryGet
|
||||
proof = circom.prove(proofInputs).tryGet
|
||||
|
||||
check circom.verify(proof, publicInputs, verifyingKeyPtr[]).tryGet == false
|
||||
check circom.verify(proof, proofInputs).tryGet == false
|
||||
|
||||
suite "Test Circom Compat Backend":
|
||||
let
|
||||
slotId = 3
|
||||
samples = 5
|
||||
ecK = 2
|
||||
ecM = 2
|
||||
slotId = 3
|
||||
samples = 5
|
||||
numDatasetBlocks = 8
|
||||
blockSize = DefaultBlockSize
|
||||
cellSize = DefaultCellSize
|
||||
|
||||
r1cs = "tests/circuits/fixtures/proof_main.r1cs"
|
||||
wasm = "tests/circuits/fixtures/proof_main.wasm"
|
||||
zkey = "tests/circuits/fixtures/proof_main.zkey"
|
||||
|
||||
var
|
||||
store: BlockStore
|
||||
|
@ -84,9 +75,7 @@ suite "Test Circom Compat Backend":
|
|||
protected: Manifest
|
||||
verifiable: Manifest
|
||||
circom: CircomCompat
|
||||
verifyingKeyPtr: ptr CircomKey
|
||||
proofInput: ProofInput[Poseidon2Hash]
|
||||
publicInputs: CircomInputs
|
||||
proofInputs: ProofInputs[Poseidon2Hash]
|
||||
challenge: array[32, byte]
|
||||
builder: Poseidon2Builder
|
||||
sampler: Poseidon2Sampler
|
||||
|
@ -109,29 +98,24 @@ suite "Test Circom Compat Backend":
|
|||
builder = Poseidon2Builder.new(store, verifiable).tryGet
|
||||
sampler = Poseidon2Sampler.new(slotId, store, builder).tryGet
|
||||
|
||||
# circom = CircomCompat.init(r1cs, wasm, zkey)
|
||||
circom = CircomCompat.init(r1cs, wasm)
|
||||
verifyingKeyPtr = circom.getVerifyingKey().tryGet
|
||||
circom = CircomCompat.init(r1cs, wasm, zkey)
|
||||
challenge = 1234567.toF.toBytes.toArray32
|
||||
|
||||
proofInput = (await sampler.getProofInput(challenge, samples)).tryGet
|
||||
publicInputs = proofInput.toPublicInputs.toCircomInputs
|
||||
proofInputs = (await sampler.getProofInput(challenge, samples)).tryGet
|
||||
|
||||
teardown:
|
||||
publicInputs.releaseNimInputs() # this is allocated by nim
|
||||
verifyingKeyPtr.addr.releaseKey() # this comes from the rust FFI
|
||||
circom.release() # this comes from the rust FFI
|
||||
|
||||
test "Should verify with correct input":
|
||||
var
|
||||
proof = circom.prove(proofInput).tryGet
|
||||
proof = circom.prove(proofInputs).tryGet
|
||||
|
||||
check circom.verify(proof, publicInputs, verifyingKeyPtr[]).tryGet
|
||||
check circom.verify(proof, proofInputs).tryGet
|
||||
|
||||
test "Should not verify with incorrect input":
|
||||
proofInput.slotIndex = 1 # change slot index
|
||||
proofInputs.slotIndex = 1 # change slot index
|
||||
|
||||
let
|
||||
proof = circom.prove(proofInput).tryGet
|
||||
proof = circom.prove(proofInputs).tryGet
|
||||
|
||||
check circom.verify(proof, publicInputs, verifyingKeyPtr[]).tryGet == false
|
||||
check circom.verify(proof, proofInputs).tryGet == false
|
||||
|
|
|
@ -31,12 +31,12 @@ suite "Test Sampler - control samples":
|
|||
var
|
||||
inputData: string
|
||||
inputJson: JsonNode
|
||||
proofInput: ProofInput[Poseidon2Hash]
|
||||
proofInput: ProofInputs[Poseidon2Hash]
|
||||
|
||||
setup:
|
||||
inputData = readFile("tests/circuits/fixtures/input.json")
|
||||
inputJson = parseJson(inputData)
|
||||
proofInput = jsonToProofInput[Poseidon2Hash](inputJson)
|
||||
proofInput = Poseidon2Hash.jsonToProofInput(inputJson)
|
||||
|
||||
test "Should verify control samples":
|
||||
let
|
||||
|
@ -58,7 +58,7 @@ suite "Test Sampler - control samples":
|
|||
proofInput.nCellsPerSlot,
|
||||
sample.merklePaths[5..<9]).tryGet
|
||||
|
||||
cellData = fromCircomData[Poseidon2Hash](sample.cellData)
|
||||
cellData = Poseidon2Hash.fromCircomData(sample.cellData)
|
||||
cellLeaf = Poseidon2Hash.spongeDigest(cellData, rate = 2).tryGet
|
||||
slotLeaf = cellProof.reconstructRoot(cellLeaf).tryGet
|
||||
|
||||
|
@ -154,7 +154,7 @@ suite "Test Sampler":
|
|||
nSlotCells,
|
||||
sample.merklePaths[5..<sample.merklePaths.len]).tryGet
|
||||
|
||||
cellData = fromCircomData[Poseidon2Hash](sample.cellData)
|
||||
cellData = Poseidon2Hash.fromCircomData(sample.cellData)
|
||||
cellLeaf = Poseidon2Hash.spongeDigest(cellData, rate = 2).tryGet
|
||||
slotLeaf = cellProof.reconstructRoot(cellLeaf).tryGet
|
||||
|
||||
|
|
|
@ -34,12 +34,12 @@ asyncchecksuite "Test proof sampler utils":
|
|||
var
|
||||
inputData: string
|
||||
inputJson: JsonNode
|
||||
proofInput: ProofInput[Poseidon2Hash]
|
||||
proofInput: ProofInputs[Poseidon2Hash]
|
||||
|
||||
setup:
|
||||
inputData = readFile("tests/circuits/fixtures/input.json")
|
||||
inputJson = parseJson(inputData)
|
||||
proofInput = jsonToProofInput[Poseidon2Hash](inputJson)
|
||||
proofInput = Poseidon2Hash.jsonToProofInput(inputJson)
|
||||
|
||||
test "Extract low bits":
|
||||
proc extract(value: uint64, nBits: int): uint64 =
|
||||
|
|
|
@ -18,10 +18,6 @@ import pkg/codex/stores
|
|||
import pkg/poseidon2/io
|
||||
import pkg/codex/utils/poseidon2digest
|
||||
|
||||
import pkg/constantine/math/arithmetic
|
||||
import pkg/constantine/math/io/io_bigints
|
||||
import pkg/constantine/math/io/io_fields
|
||||
|
||||
import ./helpers
|
||||
import ../helpers
|
||||
import ./backends/helpers
|
||||
|
@ -30,11 +26,11 @@ suite "Test Prover":
|
|||
let
|
||||
slotId = 1
|
||||
samples = 5
|
||||
blockSize = DefaultBlockSize
|
||||
cellSize = DefaultCellSize
|
||||
ecK = 3
|
||||
ecM = 2
|
||||
numDatasetBlocks = 8
|
||||
blockSize = DefaultBlockSize
|
||||
cellSize = DefaultCellSize
|
||||
|
||||
var
|
||||
datasetBlocks: seq[bt.Block]
|
||||
|
@ -65,14 +61,9 @@ suite "Test Prover":
|
|||
wasm = "tests/circuits/fixtures/proof_main.wasm"
|
||||
|
||||
circomBackend = CircomCompat.init(r1cs, wasm)
|
||||
prover = Prover.new(store, circomBackend)
|
||||
prover = Prover.new(store, circomBackend, samples)
|
||||
challenge = 1234567.toF.toBytes.toArray32
|
||||
proof = (await prover.prove(1, verifiable, challenge, 5)).tryGet
|
||||
key = circomBackend.getVerifyingKey().tryGet
|
||||
builder = Poseidon2Builder.new(store, verifiable).tryGet
|
||||
sampler = Poseidon2Sampler.new(1, store, builder).tryGet
|
||||
proofInput = (await sampler.getProofInput(challenge, 5)).tryGet
|
||||
inputs = proofInput.toPublicInputs.toCircomInputs
|
||||
(inputs, proof) = (await prover.prove(1, verifiable, challenge)).tryGet
|
||||
|
||||
check:
|
||||
(await prover.verify(proof, inputs, key[])).tryGet == true
|
||||
(await prover.verify(proof, inputs)).tryGet == true
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import ./slots/testslotbuilder
|
||||
import ./slots/testsampler
|
||||
import ./slots/testconverters
|
||||
import ./slots/testbackends
|
||||
import ./slots/testprover
|
||||
|
||||
{.warning[UnusedImport]: off.}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit fa513b123e081c76ec0bb3237ad886d4830b8071
|
||||
Subproject commit e710e4c333f367353aaa1ee82a55a47326b63a65
|
Loading…
Reference in New Issue