wire in circom backend (#698)
* wire in circom backend * should contain leafs * adding circom compad and circuits deps * update windows build * fix windows build * improve test names * move proving defaults to codextypes * remove unnedded inmports and move defaults to codextypes * capture error code on backend failure
This commit is contained in:
parent
825766eea0
commit
e23159b065
|
@ -45,6 +45,7 @@ runs:
|
|||
if: inputs.os == 'windows' && inputs.cpu == 'amd64'
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
path-type: inherit
|
||||
msystem: UCRT64
|
||||
install: >
|
||||
base-devel
|
||||
|
@ -52,11 +53,13 @@ runs:
|
|||
mingw-w64-ucrt-x86_64-toolchain
|
||||
mingw-w64-ucrt-x86_64-cmake
|
||||
mingw-w64-ucrt-x86_64-ntldd-git
|
||||
mingw-w64-ucrt-x86_64-rust
|
||||
|
||||
- name: MSYS2 (Windows i386)
|
||||
if: inputs.os == 'windows' && inputs.cpu == 'i386'
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
path-type: inherit
|
||||
msystem: MINGW32
|
||||
install: >
|
||||
base-devel
|
||||
|
@ -64,6 +67,7 @@ runs:
|
|||
mingw-w64-i686-toolchain
|
||||
mingw-w64-i686-cmake
|
||||
mingw-w64-i686-ntldd-git
|
||||
mingw-w64-i686-rust
|
||||
|
||||
- name: Derive environment variables
|
||||
shell: ${{ inputs.shell }} {0}
|
||||
|
|
|
@ -27,6 +27,7 @@ jobs:
|
|||
name: '${{ matrix.os }}-${{ matrix.cpu }}-${{ matrix.nim_version }}-${{ matrix.tests }}'
|
||||
runs-on: ${{ matrix.builder }}
|
||||
timeout-minutes: 80
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
|
|
|
@ -42,7 +42,6 @@ jobs:
|
|||
cache_nonce: ${{ needs.matrix.outputs.cache_nonce }}
|
||||
|
||||
coverage:
|
||||
continue-on-error: true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
|
|
|
@ -199,3 +199,13 @@
|
|||
[submodule "vendor/constantine"]
|
||||
path = vendor/constantine
|
||||
url = https://github.com/mratsim/constantine.git
|
||||
[submodule "vendor/nim-circom-compat"]
|
||||
path = vendor/nim-circom-compat
|
||||
url = https://github.com/codex-storage/nim-circom-compat.git
|
||||
ignore = untracked
|
||||
branch = master
|
||||
[submodule "vendor/codex-storage-proofs-circuits"]
|
||||
path = vendor/codex-storage-proofs-circuits
|
||||
url = https://github.com/codex-storage/codex-storage-proofs-circuits.git
|
||||
ignore = untracked
|
||||
branch = master
|
||||
|
|
|
@ -28,6 +28,13 @@ const
|
|||
DefaultBlockSize* = NBytes 1024*64
|
||||
DefaultCellSize* = NBytes 2048
|
||||
|
||||
# Proving defaults
|
||||
DefaultMaxSlotDepth* = 32
|
||||
DefaultMaxDatasetDepth* = 8
|
||||
DefaultBlockDepth* = 5
|
||||
DefaultCellElms* = 67
|
||||
DefaultSamplesNum* = 5
|
||||
|
||||
# hashes
|
||||
Sha256HashCodec* = multiCodec("sha2-256")
|
||||
Sha512HashCodec* = multiCodec("sha2-512")
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import ./slots/builder
|
||||
import ./slots/sampler
|
||||
import ./slots/proofs
|
||||
import ./slots/types
|
||||
|
||||
export builder, sampler
|
||||
export builder, sampler, proofs, types
|
||||
|
|
|
@ -78,11 +78,11 @@ func toVerifiableProof*(
|
|||
proof: CodexProof): ?!Poseidon2Proof =
|
||||
|
||||
let
|
||||
verifiableProof = Poseidon2Proof(
|
||||
index: proof.index,
|
||||
nleaves: proof.nleaves,
|
||||
path: proof.path.mapIt(
|
||||
nodes = proof.path.mapIt(
|
||||
? Poseidon2Hash.fromBytes(it.toArray32).toFailure
|
||||
))
|
||||
)
|
||||
|
||||
success verifiableProof
|
||||
Poseidon2Proof.init(
|
||||
index = proof.index,
|
||||
nleaves = proof.nleaves,
|
||||
nodes = nodes)
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
import ./proofs/backends
|
||||
import ./proofs/prover
|
||||
|
||||
export circomcompat, prover
|
|
@ -0,0 +1,3 @@
|
|||
import ./backends/circomcompat
|
||||
|
||||
export circomcompat
|
|
@ -0,0 +1,228 @@
|
|||
## 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 std/sequtils
|
||||
|
||||
import pkg/chronos
|
||||
import pkg/questionable/results
|
||||
import pkg/circomcompat
|
||||
import pkg/poseidon2/io
|
||||
|
||||
import ../../types
|
||||
import ../../../stores
|
||||
import ../../../merkletree
|
||||
import ../../../codextypes
|
||||
|
||||
export circomcompat
|
||||
|
||||
type
|
||||
CircomCompat* = object
|
||||
slotDepth : int # max depth of the slot tree
|
||||
datasetDepth : int # max depth of dataset tree
|
||||
blkDepth : int # depth of the block merkle tree (pow2 for now)
|
||||
cellElms : int # number of field elements per cell
|
||||
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
|
||||
backendCfg : ptr CircomBn254Cfg
|
||||
|
||||
CircomG1* = G1
|
||||
CircomG2* = G2
|
||||
|
||||
CircomProof* = Proof
|
||||
CircomKey* = VerifyingKey
|
||||
CircomInputs* = Inputs
|
||||
|
||||
proc release*(self: CircomCompat) =
|
||||
## Release the backend
|
||||
##
|
||||
|
||||
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
|
||||
|
||||
proc prove*[H](
|
||||
self: CircomCompat,
|
||||
input: ProofInput[H]): ?!CircomProof =
|
||||
## Encode buffers using a backend
|
||||
##
|
||||
|
||||
# NOTE: All inputs are statically sized per circuit
|
||||
# and adjusted accordingly right before being passed
|
||||
# to the circom ffi - `setLen` is used to adjust the
|
||||
# sequence length to the correct size which also 0 pads
|
||||
# to the correct length
|
||||
doAssert input.samples.len == self.numSamples,
|
||||
"Number of samples does not match"
|
||||
|
||||
doAssert input.slotProof.len <= self.datasetDepth,
|
||||
"Number of slot proofs does not match"
|
||||
|
||||
doAssert input.samples.allIt(
|
||||
block:
|
||||
(it.merklePaths.len <= self.slotDepth + self.blkDepth and
|
||||
it.cellData.len <= self.cellElms * 32)), "Merkle paths length does not match"
|
||||
|
||||
# TODO: All parameters should match circom's static parametter
|
||||
var
|
||||
backend: ptr CircomCompatCtx
|
||||
|
||||
if initCircomCompat(
|
||||
self.backendCfg,
|
||||
addr backend) != ERR_OK or backend == nil:
|
||||
raiseAssert("failed to initialize CircomCompat backend")
|
||||
|
||||
var
|
||||
entropy = input.entropy.toBytes
|
||||
dataSetRoot = input.datasetRoot.toBytes
|
||||
slotRoot = input.slotRoot.toBytes
|
||||
|
||||
if backend.pushInputU256Array(
|
||||
"entropy".cstring, entropy[0].addr, entropy.len.uint32) != ERR_OK:
|
||||
return failure("Failed to push entropy")
|
||||
|
||||
if backend.pushInputU256Array(
|
||||
"dataSetRoot".cstring, dataSetRoot[0].addr, dataSetRoot.len.uint32) != ERR_OK:
|
||||
return failure("Failed to push data set root")
|
||||
|
||||
if backend.pushInputU256Array(
|
||||
"slotRoot".cstring, slotRoot[0].addr, slotRoot.len.uint32) != ERR_OK:
|
||||
return failure("Failed to push data set root")
|
||||
|
||||
if backend.pushInputU32(
|
||||
"nCellsPerSlot".cstring, input.nCellsPerSlot.uint32) != ERR_OK:
|
||||
return failure("Failed to push nCellsPerSlot")
|
||||
|
||||
if backend.pushInputU32(
|
||||
"nSlotsPerDataSet".cstring, input.nSlotsPerDataSet.uint32) != ERR_OK:
|
||||
return failure("Failed to push nSlotsPerDataSet")
|
||||
|
||||
if backend.pushInputU32(
|
||||
"slotIndex".cstring, input.slotIndex.uint32) != ERR_OK:
|
||||
return failure("Failed to push slotIndex")
|
||||
|
||||
var
|
||||
slotProof = input.slotProof.mapIt( it.toBytes ).concat
|
||||
|
||||
slotProof.setLen(self.datasetDepth) # zero pad inputs to correct size
|
||||
|
||||
# arrays are always flattened
|
||||
if backend.pushInputU256Array(
|
||||
"slotProof".cstring,
|
||||
slotProof[0].addr,
|
||||
uint (slotProof[0].len * slotProof.len)) != ERR_OK:
|
||||
return failure("Failed to push slot proof")
|
||||
|
||||
for s in input.samples:
|
||||
var
|
||||
merklePaths = s.merklePaths.mapIt( it.toBytes )
|
||||
data = s.cellData
|
||||
|
||||
merklePaths.setLen(self.slotDepth) # zero pad inputs to correct size
|
||||
if backend.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(
|
||||
"cellData".cstring,
|
||||
data[0].addr,
|
||||
data.len.uint) != ERR_OK:
|
||||
return failure("Failed to push cell data")
|
||||
|
||||
var
|
||||
proofPtr: ptr Proof = nil
|
||||
|
||||
let proof =
|
||||
try:
|
||||
if (
|
||||
let res = self.backendCfg.proveCircuit(backend, proofPtr.addr);
|
||||
res != ERR_OK) or
|
||||
proofPtr == nil:
|
||||
return failure("Failed to prove - err code: " & $res)
|
||||
|
||||
proofPtr[]
|
||||
finally:
|
||||
if proofPtr != nil:
|
||||
proofPtr.addr.releaseProof()
|
||||
|
||||
if backend != nil:
|
||||
backend.addr.releaseCircomCompat()
|
||||
|
||||
success proof
|
||||
|
||||
proc verify*(
|
||||
self: CircomCompat,
|
||||
proof: CircomProof,
|
||||
inputs: CircomInputs,
|
||||
vkp: CircomKey): ?!bool =
|
||||
## Verify a proof using a backend
|
||||
##
|
||||
|
||||
var
|
||||
proofPtr : ptr Proof = unsafeAddr proof
|
||||
inputsPtr: ptr Inputs = unsafeAddr inputs
|
||||
vpkPtr: ptr CircomKey = unsafeAddr vkp
|
||||
|
||||
let res = verifyCircuit(proofPtr, inputsPtr, vpkPtr)
|
||||
if res == ERR_OK:
|
||||
success true
|
||||
elif res == ERR_FAILED_TO_VERIFY_PROOF:
|
||||
success false
|
||||
else:
|
||||
failure("Failed to verify proof - err code: " & $res)
|
||||
|
||||
proc init*(
|
||||
_: type CircomCompat,
|
||||
r1csPath : string,
|
||||
wasmPath : string,
|
||||
zKeyPath : string = "",
|
||||
slotDepth = DefaultMaxSlotDepth,
|
||||
datasetDepth = DefaultMaxDatasetDepth,
|
||||
blkDepth = DefaultBlockDepth,
|
||||
cellElms = DefaultCellElms,
|
||||
numSamples = DefaultSamplesNum): CircomCompat =
|
||||
## Create a new backend
|
||||
##
|
||||
|
||||
var cfg: ptr CircomBn254Cfg
|
||||
if initCircomConfig(
|
||||
r1csPath.cstring,
|
||||
wasmPath.cstring,
|
||||
if zKeyPath.len > 0: zKeyPath.cstring else: nil,
|
||||
addr cfg) != ERR_OK or cfg == nil:
|
||||
raiseAssert("failed to initialize circom compat config")
|
||||
|
||||
CircomCompat(
|
||||
r1csPath : r1csPath,
|
||||
wasmPath : wasmPath,
|
||||
zKeyPath : zKeyPath,
|
||||
backendCfg : cfg,
|
||||
slotDepth : slotDepth,
|
||||
datasetDepth: datasetDepth,
|
||||
blkDepth : blkDepth,
|
||||
cellElms : cellElms,
|
||||
numSamples : numSamples)
|
|
@ -0,0 +1,98 @@
|
|||
## 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.
|
||||
##
|
||||
|
||||
import pkg/chronos
|
||||
import pkg/chronicles
|
||||
import pkg/circomcompat
|
||||
import pkg/poseidon2
|
||||
import pkg/questionable/results
|
||||
|
||||
import pkg/libp2p/cid
|
||||
|
||||
import ../../manifest
|
||||
import ../../merkletree
|
||||
import ../../stores
|
||||
import ../../market
|
||||
import ../../utils/poseidon2digest
|
||||
|
||||
import ../builder
|
||||
import ../sampler
|
||||
|
||||
import ./backends
|
||||
import ../types
|
||||
|
||||
export backends
|
||||
|
||||
type
|
||||
AnyProof* = CircomProof
|
||||
AnyInputs* = CircomInputs
|
||||
AnyKeys* = CircomKey
|
||||
AnyHash* = Poseidon2Hash
|
||||
AnyBackend* = CircomCompat
|
||||
AnyBuilder* = Poseidon2Builder
|
||||
AnySampler* = Poseidon2Sampler
|
||||
|
||||
Prover* = ref object of RootObj
|
||||
backend: AnyBackend
|
||||
store: BlockStore
|
||||
|
||||
proc prove*(
|
||||
self: Prover,
|
||||
slotIdx: int,
|
||||
manifest: Manifest,
|
||||
challenge: ProofChallenge,
|
||||
nSamples = DefaultSamplesNum): Future[?!AnyProof] {.async.} =
|
||||
## Prove a statement using backend.
|
||||
## Returns a future that resolves to a proof.
|
||||
|
||||
logScope:
|
||||
cid = manifest.treeCid
|
||||
slot = slotIdx
|
||||
challenge = challenge
|
||||
|
||||
trace "Received proof challenge"
|
||||
|
||||
without builder =? AnyBuilder.new(self.store, manifest), err:
|
||||
error "Unable to create slots builder", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
without sampler =? AnySampler.new(slotIdx, self.store, builder), err:
|
||||
error "Unable to create data sampler", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
without proofInput =? await sampler.getProofInput(challenge, nSamples), err:
|
||||
error "Unable to get proof input for slot", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
# prove slot
|
||||
without proof =? self.backend.prove(proofInput), err:
|
||||
error "Unable to prove slot", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
success proof
|
||||
|
||||
proc verify*(
|
||||
self: Prover,
|
||||
proof: AnyProof,
|
||||
inputs: AnyInputs,
|
||||
vpk: AnyKeys): Future[?!bool] {.async.} =
|
||||
## Prove a statement using backend.
|
||||
## Returns a future that resolves to a proof.
|
||||
|
||||
self.backend.verify(proof, inputs, vpk)
|
||||
|
||||
proc new*(
|
||||
_: type Prover,
|
||||
store: BlockStore,
|
||||
backend: AnyBackend): Prover =
|
||||
|
||||
Prover(
|
||||
backend: backend,
|
||||
store: store)
|
|
@ -0,0 +1,4 @@
|
|||
pragma circom 2.0.0;
|
||||
include "sample_cells.circom";
|
||||
// SampleAndProven( maxDepth, maxLog2NSlots, blockTreeDepth, nFieldElemsPerCell, nSamples )
|
||||
component main {public [entropy,dataSetRoot,slotIndex]} = SampleAndProve(32, 8, 5, 67, 5);
|
Binary file not shown.
Binary file not shown.
|
@ -79,4 +79,5 @@ proc example*(_: type MerkleProof): MerkleProof =
|
|||
proc example*(_: type Poseidon2Proof): Poseidon2Proof =
|
||||
var example = MerkleProof[Poseidon2Hash, PoseidonKeysEnum]()
|
||||
example.index = 123
|
||||
example.path = @[1, 2, 3, 4].mapIt( it.toF )
|
||||
example
|
||||
|
|
|
@ -37,6 +37,31 @@ func toPublicInputs*[H](input: ProofInput[H]): PublicInputs[H] =
|
|||
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
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
|
||||
import std/sequtils
|
||||
import std/sugar
|
||||
import std/options
|
||||
|
||||
import pkg/chronos
|
||||
import ../../../asynctest
|
||||
import pkg/poseidon2
|
||||
import pkg/datastore
|
||||
|
||||
import pkg/codex/slots {.all.}
|
||||
import pkg/codex/slots/types {.all.}
|
||||
import pkg/codex/merkletree
|
||||
import pkg/codex/utils/json
|
||||
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
|
||||
|
||||
suite "Test Circom Compat Backend - control inputs":
|
||||
let
|
||||
r1cs = "tests/circuits/fixtures/proof_main.r1cs"
|
||||
wasm = "tests/circuits/fixtures/proof_main.wasm"
|
||||
|
||||
var
|
||||
circom: CircomCompat
|
||||
verifyingKeyPtr: ptr CircomKey
|
||||
proofInput: ProofInput[Poseidon2Hash]
|
||||
publicInputs: CircomInputs
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
check circom.verify(proof, publicInputs, verifyingKeyPtr[]).tryGet
|
||||
|
||||
test "Should not verify with incorrect inputs":
|
||||
proofInput.slotIndex = 1 # change slot index
|
||||
|
||||
let
|
||||
proof = circom.prove(proofInput).tryGet
|
||||
|
||||
check circom.verify(proof, publicInputs, verifyingKeyPtr[]).tryGet == false
|
||||
|
||||
suite "Test Circom Compat Backend":
|
||||
let
|
||||
slotId = 3
|
||||
samples = 5
|
||||
ecK = 2
|
||||
ecM = 2
|
||||
numDatasetBlocks = 8
|
||||
blockSize = DefaultBlockSize
|
||||
cellSize = DefaultCellSize
|
||||
|
||||
r1cs = "tests/circuits/fixtures/proof_main.r1cs"
|
||||
wasm = "tests/circuits/fixtures/proof_main.wasm"
|
||||
|
||||
var
|
||||
store: BlockStore
|
||||
manifest: Manifest
|
||||
protected: Manifest
|
||||
verifiable: Manifest
|
||||
circom: CircomCompat
|
||||
verifyingKeyPtr: ptr CircomKey
|
||||
proofInput: ProofInput[Poseidon2Hash]
|
||||
publicInputs: CircomInputs
|
||||
challenge: array[32, byte]
|
||||
builder: Poseidon2Builder
|
||||
sampler: Poseidon2Sampler
|
||||
|
||||
setup:
|
||||
let
|
||||
repoDs = SQLiteDatastore.new(Memory).tryGet()
|
||||
metaDs = SQLiteDatastore.new(Memory).tryGet()
|
||||
|
||||
store = RepoStore.new(repoDs, metaDs)
|
||||
|
||||
(manifest, protected, verifiable) =
|
||||
await createVerifiableManifest(
|
||||
store,
|
||||
numDatasetBlocks,
|
||||
ecK, ecM,
|
||||
blockSize,
|
||||
cellSize)
|
||||
|
||||
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
|
||||
challenge = 1234567.toF.toBytes.toArray32
|
||||
|
||||
proofInput = (await sampler.getProofInput(challenge, samples)).tryGet
|
||||
publicInputs = proofInput.toPublicInputs.toCircomInputs
|
||||
|
||||
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
|
||||
|
||||
check circom.verify(proof, publicInputs, verifyingKeyPtr[]).tryGet
|
||||
|
||||
test "Should not verify with incorrect input":
|
||||
proofInput.slotIndex = 1 # change slot index
|
||||
|
||||
let
|
||||
proof = circom.prove(proofInput).tryGet
|
||||
|
||||
check circom.verify(proof, publicInputs, verifyingKeyPtr[]).tryGet == false
|
|
@ -26,7 +26,7 @@ import ../backends/helpers
|
|||
import ../helpers
|
||||
import ../../helpers
|
||||
|
||||
suite "Test control samples":
|
||||
suite "Test Sampler - control samples":
|
||||
|
||||
var
|
||||
inputData: string
|
||||
|
@ -73,7 +73,7 @@ suite "Test control samples":
|
|||
|
||||
check datasetProof.verify(proofInput.slotRoot, proofInput.datasetRoot).tryGet
|
||||
|
||||
suite "Test sampler samples":
|
||||
suite "Test Sampler":
|
||||
|
||||
let
|
||||
slotIndex = 3
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import ./backends/testcircomcompat
|
||||
|
||||
{.warning[UnusedImport]: off.}
|
|
@ -0,0 +1,78 @@
|
|||
import std/sequtils
|
||||
import std/sugar
|
||||
import std/math
|
||||
|
||||
import ../../asynctest
|
||||
|
||||
import pkg/chronos
|
||||
import pkg/libp2p/cid
|
||||
import pkg/datastore
|
||||
|
||||
import pkg/codex/merkletree
|
||||
import pkg/codex/rng
|
||||
import pkg/codex/manifest
|
||||
import pkg/codex/chunker
|
||||
import pkg/codex/blocktype as bt
|
||||
import pkg/codex/slots
|
||||
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
|
||||
|
||||
suite "Test Prover":
|
||||
let
|
||||
slotId = 1
|
||||
samples = 5
|
||||
blockSize = DefaultBlockSize
|
||||
cellSize = DefaultCellSize
|
||||
ecK = 3
|
||||
ecM = 2
|
||||
numDatasetBlocks = 8
|
||||
|
||||
var
|
||||
datasetBlocks: seq[bt.Block]
|
||||
store: BlockStore
|
||||
manifest: Manifest
|
||||
protected: Manifest
|
||||
verifiable: Manifest
|
||||
sampler: Poseidon2Sampler
|
||||
|
||||
setup:
|
||||
let
|
||||
repoDs = SQLiteDatastore.new(Memory).tryGet()
|
||||
metaDs = SQLiteDatastore.new(Memory).tryGet()
|
||||
|
||||
store = RepoStore.new(repoDs, metaDs)
|
||||
|
||||
(manifest, protected, verifiable) =
|
||||
await createVerifiableManifest(
|
||||
store,
|
||||
numDatasetBlocks,
|
||||
ecK, ecM,
|
||||
blockSize,
|
||||
cellSize)
|
||||
|
||||
test "Should sample and prove a slot":
|
||||
let
|
||||
r1cs = "tests/circuits/fixtures/proof_main.r1cs"
|
||||
wasm = "tests/circuits/fixtures/proof_main.wasm"
|
||||
|
||||
circomBackend = CircomCompat.init(r1cs, wasm)
|
||||
prover = Prover.new(store, circomBackend)
|
||||
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
|
||||
|
||||
check:
|
||||
(await prover.verify(proof, inputs, key[])).tryGet == true
|
|
@ -0,0 +1 @@
|
|||
Subproject commit c03b43221d68e34bd5015a4e4ee1a0ad3299f8ef
|
|
@ -0,0 +1 @@
|
|||
Subproject commit fa513b123e081c76ec0bb3237ad886d4830b8071
|
Loading…
Reference in New Issue