diff --git a/README.md b/README.md index eceeae4..66e2a0f 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ Circom witness generators ------------------------- The original idea behind this small project was to take the "computation graph" -files generated by [`circom-witnesscalc`](https://github.com/iden3/circom-witnesscalc), -and either interprets or compiles them to various algebra backends. +files generated by [`circom-witnesscalc`](https://github.com/iden3/circom-witnesscalc), +and either interpret or compile them to various algebra backends. While this is quite straightforward in principle, and seems to work on particular examples, it turns out that `circom-witnesscalc` itself has some serious limitations. @@ -30,8 +30,9 @@ Compiler (in Haskell): Nim witness generator (to be used with [`nim-groth16`](https://github.com/codex-storage/nim-groth16)) - [x] parsing the graph file -- [ ] parsing json input +- [x] parsing json input - [ ] generating the witness +- [ ] exporting the witness - [ ] proper error handling ### Testing & correctness @@ -50,18 +51,18 @@ by `circom-witnesscalc`. This has the following format: -- magic header: "wtns.graph.001" (14 bytes) +- magic header: `"wtns.graph.001"` (14 bytes) - number of nodes (8 bytes little endian) -- list of nodes, in protobuf serialized format. Each prefixed by a `varint` length -- `GraphMetaData`, in protobuf -- 8 bytes offset (yes, _at the very end_...), pointing to the start of `GraphMetaData` +- list of nodes, in protobuf serialized format. Each one is prefixed by a `varint` length +- after that, `GraphMetaData`, encoded with protobuf +- finally, 8 bytes little-endian offset (yes, _at the very end_...), pointing to the start of `GraphMetaData` Node format: - varint length prefix -- protobuf tag-byte (lower 3 bits are `0x02`, upper bits are node type 1..5) +- protobuf tag-byte (lower 3 bits are `0x02`, upper bits are node type `1..5`) - varint length - several record fields - - protobuf tag-byte (lower 3 bits are 0x00, upper bits are field index 1,2,3,4) - - value is varint word32, except for ConstantNode when it's a little-endian bytes - (wrapped a few times, because protobuf is being protobuf...) + - protobuf tag-byte (lower 3 bits are `0x00`, upper bits are field index `1,2,3,4`) + - value is varint word32, except for `ConstantNode` when it's a sequence of little-endian bytes, + encoding a field element (wrapped a few times, because protobuf is being protobuf...) diff --git a/nim/circom_witnessgen/input_json.nim b/nim/circom_witnessgen/input_json.nim new file mode 100644 index 0000000..97763cf --- /dev/null +++ b/nim/circom_witnessgen/input_json.nim @@ -0,0 +1,39 @@ + +import std/sequtils +import std/json +import std/tables + +import ./field + +#------------------------------------------------------------------------------- + +type + Inputs* = Table[string, seq[F]] + +proc printInputs*(inputs: Inputs) = + for key, list in pairs(inputs): + echo key + for y in list: + echo " - " & fToDecimal(y) + +proc flattenNode(node: JsonNode): seq[F] = + case node.kind: + of JString: return @[decimalToF(node.str)] + of JInt: return @[int64ToF(node.num)] + of JArray: return node.elems.map(flattenNode).concat() + else: assert( false, "parseInputJSON: expecting a number or a list (of numbers)" ) + +proc parseInputJSON*(json: JsonNode): Inputs = + doAssert json.kind == JObject + var stuff: Inputs + for key, node in pairs(json.fields): + stuff[key] = flattenNode(node) + return stuff + +proc loadInputJSON*(fpath: string): Inputs = + let text = readFile(fpath) + let json = parseJson(text) + return parseInputJSON(json) + +#------------------------------------------------------------------------------- + diff --git a/nim/main.nim b/nim/main.nim index 23db1a0..7e5aa7f 100644 --- a/nim/main.nim +++ b/nim/main.nim @@ -1,9 +1,16 @@ import circom_witnessgen/graph import circom_witnessgen/load +import circom_witnessgen/input_json + +const graph_file: string = "../tmp/graph4.bin" +const input_file: string = "../tmp/input4.json" when isMainModule: - let fn = "/Users/bkomuves/zk/codex/circom-witnessgen-compiler/tmp/graph2.bin" - echo "loading in " & fn - let g = loadGraph(fn) - echo $g + echo "\nloading in " & input_file + let inp = loadInputJSON(input_file) + printInputs(inp) + + echo "\nloading in " & graph_file + let gr = loadGraph(graph_file) + # echo $gr