wip rework backend

This commit is contained in:
Dmitriy Ryajov 2024-01-26 19:53:11 -06:00
parent 0d3b18cb5e
commit b0e5058d45
No known key found for this signature in database
GPG Key ID: DA8C680CE7C657A4
2 changed files with 102 additions and 79 deletions

View File

@ -17,49 +17,70 @@ import pkg/circomcompat
import ../../../stores import ../../../stores
import ../../types import ../../types
import ../../../merkletree
export circomcompat export circomcompat
type type
CircomCompat*[H, P] = ref object of RootObj CircomCompat* = object
r1csPath : string r1csPath : string
wasmPath : string wasmPath : string
zKeyPath : string zKeyPath : string
backend : ptr CircomCompatCtx backendCfg : ptr CircomBn254Cfg
proc release*[H, P](self: CircomCompat[H, P]) = CircomProof* = object
proof*: Proof
backend: ptr CircomCompatCtx
cfg: ptr CircomBn254Cfg
proc release*(self: CircomCompat) =
## Release the backend ## Release the backend
## ##
self.backend.addr.releaseCircomCompat() self.backendCfg.unsafeAddr.releaseCfg()
proc prove*[H, P]( proc release*(proof: CircomProof) =
self: CircomCompat[H, P], ## Release the backend context
input: ProofInput[H]): Future[?!P] {.async.} = ##
proof.backend.unsafeAddr.release_circom_compat()
doAssert(proof.backend == nil)
proc prove*(
self: CircomCompat,
input: ProofInput[Poseidon2Hash]): ?!CircomProof =
## Encode buffers using a backend ## Encode buffers using a backend
## ##
var
backend: ptr CircomCompatCtx
if initCircomCompat(
self.backendCfg,
addr backend) != ERR_OK or backend == nil:
raiseAssert("failed to initialize CircomCompat backend")
var var
entropy = input.entropy.toBytes entropy = input.entropy.toBytes
verifyRoot = input.verifyRoot.toBytes verifyRoot = input.verifyRoot.toBytes
if self.backend.pushInputU256Array( if backend.pushInputU256Array(
"entropy".cstring, entropy.addr, entropy.len.uint32) != ERR_OK: "entropy".cstring, entropy.addr, entropy.len.uint32) != ERR_OK:
return failure("Failed to push entropy") return failure("Failed to push entropy")
if self.backend.pushInputU256Array( if backend.pushInputU256Array(
"dataSetRoot".cstring, verifyRoot.addr, verifyRoot.len.uint32) != ERR_OK: "dataSetRoot".cstring, verifyRoot.addr, verifyRoot.len.uint32) != ERR_OK:
return failure("Failed to push data set root") return failure("Failed to push data set root")
if self.backend.pushInputU32( if backend.pushInputU32(
"nCellsPerSlot".cstring, input.numCells.uint32) != ERR_OK: "nCellsPerSlot".cstring, input.numCells.uint32) != ERR_OK:
return failure("Failed to push nCellsPerSlot") return failure("Failed to push nCellsPerSlot")
if self.backend.pushInputU32( if backend.pushInputU32(
"nSlotsPerDataSet".cstring, input.numSlots.uint32) != ERR_OK: "nSlotsPerDataSet".cstring, input.numSlots.uint32) != ERR_OK:
return failure("Failed to push nSlotsPerDataSet") return failure("Failed to push nSlotsPerDataSet")
if self.backend.pushInputU32( if backend.pushInputU32(
"slotIndex".cstring, input.slotIndex.uint32) != ERR_OK: "slotIndex".cstring, input.slotIndex.uint32) != ERR_OK:
return failure("Failed to push slotIndex") return failure("Failed to push slotIndex")
@ -67,7 +88,7 @@ proc prove*[H, P](
slotProof = input.verifyProof.mapIt( it.toBytes ).concat slotProof = input.verifyProof.mapIt( it.toBytes ).concat
# arrays are always flattened # arrays are always flattened
if self.backend.pushInputU256Array( if backend.pushInputU256Array(
"slotProof".cstring, "slotProof".cstring,
slotProof.addr, slotProof.addr,
uint input.verifyProof.len) != ERR_OK: uint input.verifyProof.len) != ERR_OK:
@ -78,13 +99,13 @@ proc prove*[H, P](
merklePaths = s.merkleProof.mapIt( it.toBytes ).concat merklePaths = s.merkleProof.mapIt( it.toBytes ).concat
data = s.data data = s.data
if self.backend.pushInputU256Array( if backend.pushInputU256Array(
"merklePaths".cstring, "merklePaths".cstring,
merklePaths[0].addr, merklePaths[0].addr,
uint merklePaths.len) != ERR_OK: uint merklePaths.len) != ERR_OK:
return failure("Failed to push merkle paths") return failure("Failed to push merkle paths")
if self.backend.pushInputU256Array( if backend.pushInputU256Array(
"cellData".cstring, "cellData".cstring,
data[0].addr, data[0].addr,
uint data.len) != ERR_OK: uint data.len) != ERR_OK:
@ -93,10 +114,9 @@ proc prove*[H, P](
var var
proofPtr: ptr Proof = nil proofPtr: ptr Proof = nil
let let proof =
proof =
try: try:
if self.backend.proveCircuit(proofPtr.addr) != ERR_OK or if self.backendCfg.proveCircuit(backend, proofPtr.addr) != ERR_OK or
proofPtr == nil: proofPtr == nil:
return failure("Failed to prove") return failure("Failed to prove")
@ -105,9 +125,12 @@ proc prove*[H, P](
if proofPtr != nil: if proofPtr != nil:
release_proof(proofPtr.addr) release_proof(proofPtr.addr)
success proof success CircomProof(
proof: proof,
cfg: self.backendCfg,
backend: backend)
proc verify*[H, P](self: CircomCompat[H, P], proof: P): Future[?!bool] {.async.} = proc verify*(proof: CircomProof): ?!bool =
## Verify a proof using a backend ## Verify a proof using a backend
## ##
@ -115,16 +138,16 @@ proc verify*[H, P](self: CircomCompat[H, P], proof: P): Future[?!bool] {.async.}
inputsPtr: ptr Inputs = nil inputsPtr: ptr Inputs = nil
vkPtr: ptr VerifyingKey = nil vkPtr: ptr VerifyingKey = nil
if (let res = self.backend.getVerifyingKey(vkPtr.addr); res != ERR_OK) or if (let res = proof.cfg.getVerifyingKey(vkPtr.addr); res != ERR_OK) or
vkPtr == nil: vkPtr == nil:
return failure("Failed to get verifying key - err code: " & $res) return failure("Failed to get verifying key - err code: " & $res)
if (let res = self.backend.getPubInputs(inputsPtr.addr); res != ERR_OK) or if (let res = proof.backend.getPubInputs(inputsPtr.addr); res != ERR_OK) or
inputsPtr == nil: inputsPtr == nil:
return failure("Failed to get public inputs - err code: " & $res) return failure("Failed to get public inputs - err code: " & $res)
try: try:
let res = verifyCircuit(proof.unsafeAddr, inputsPtr, vkPtr) let res = verifyCircuit(proof.proof.unsafeAddr, inputsPtr, vkPtr)
if res == ERR_OK: if res == ERR_OK:
success true success true
elif res == ERR_FAILED_TO_VERIFY_PROOF: elif res == ERR_FAILED_TO_VERIFY_PROOF:
@ -139,24 +162,24 @@ proc verify*[H, P](self: CircomCompat[H, P], proof: P): Future[?!bool] {.async.}
if vkPtr != nil: if vkPtr != nil:
releaseKey(vkPtr.addr) releaseKey(vkPtr.addr)
proc new*[H, P]( proc init*(
_: type CircomCompat[H, P], _: type CircomCompat,
r1csPath: string, r1csPath: string,
wasmPath: string, wasmPath: string,
zKeyPath: string = ""): CircomCompat[H, P] = zKeyPath: string = ""): CircomCompat =
## Create a new backend ## Create a new backend
## ##
var backend: ptr CircomCompatCtx var cfg: ptr CircomBn254Cfg
if initCircomCompat( if initCircomConfig(
r1csPath.cstring, r1csPath.cstring,
wasmPath.cstring, wasmPath.cstring,
if zKeyPath.len > 0: zKeyPath.cstring else: nil, if zKeyPath.len > 0: zKeyPath.cstring else: nil,
addr backend) != ERR_OK or backend == nil: addr cfg) != ERR_OK or cfg == nil:
raiseAssert("failed to initialize CircomCompat backend") raiseAssert("failed to initialize circom compat config")
CircomCompat[H, P]( CircomCompat(
r1csPath: r1csPath, r1csPath: r1csPath,
wasmPath: wasmPath, wasmPath: wasmPath,
zKeyPath: zKeyPath, zKeyPath: zKeyPath,
backend: backend) backendCfg: cfg)

View File

@ -1,46 +1,46 @@
## Nim-Codex # ## Nim-Codex
## Copyright (c) 2024 Status Research & Development GmbH # ## Copyright (c) 2024 Status Research & Development GmbH
## Licensed under either of # ## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) # ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT)) # ## * MIT license ([LICENSE-MIT](LICENSE-MIT))
## at your option. # ## at your option.
## This file may not be copied, modified, or distributed except according to # ## This file may not be copied, modified, or distributed except according to
## those terms. # ## those terms.
## # ##
import pkg/chronos # import pkg/chronos
import pkg/circomcompat # import pkg/circomcompat
import pkg/poseidon2 # import pkg/poseidon2
import pkg/questionable/results # import pkg/questionable/results
import ../../merkletree # import ../../merkletree
import ./backends # import ./backends
import ../types # import ../types
type # type
Prover*[HashT, ProofT, BackendT] = ref object of RootObj # Prover*[HashT, ProofT, BackendT] = ref object of RootObj
backend: BackendT # backend: BackendT
AnyProof* = Proof # AnyProof* = Proof
AnyHash* = Poseidon2Hash # AnyHash* = Poseidon2Hash
AnyProverBacked* = CircomCompat[AnyHash, AnyProof] # AnyProverBacked* = CircomCompat
AnyProver* = Prover[AnyHash, AnyProof, AnyProverBacked] # AnyProver* = Prover[AnyHash, AnyProof, AnyProverBacked]
proc prove*( # proc prove*(
self: AnyProver, # self: AnyProver,
input: ProofInput[AnyHash]): Future[?!AnyProof] {.async.} = # input: ProofInput[AnyHash]): Future[?!AnyProof] {.async.} =
## Prove a statement using backend. # ## Prove a statement using backend.
## Returns a future that resolves to a proof. # ## Returns a future that resolves to a proof.
## TODO: implement # ## TODO: implement
await self.backend.prove(input) # # discard self.backend.prove(input)
proc verify*( # proc verify*(
self: AnyProver, # self: AnyProver,
proof: AnyProof): Future[?!bool] {.async.} = # proof: AnyProof): Future[?!bool] {.async.} =
## Prove a statement using backend. # ## Prove a statement using backend.
## Returns a future that resolves to a proof. # ## Returns a future that resolves to a proof.
## TODO: implement # ## TODO: implement
await self.backend.verify(proof) # # discard self.backend.verify(proof)