Circom witness generators

The original idea behind this small project was to take the "computation graph" files generated by circom-witnesscalc, and either interprets or compiles 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.

The biggest one is that it doesn't support any kind of dynamic computation (which should be obvious from the fact that it produces a static graph). But even if one uses only static computations, there are further very annoying things which just don't work.

However at the end this is still a useful thing.

Implementation status

Compiler (in Haskell):

  • parsing the graph file
  • parsing json input
  • naive interpreter
  • exporting the witness
  • constantine backend
  • zikkurat backend
  • arkworks backend

Nim witness generator (to be used with nim-groth16)

  • parsing the graph file
  • parsing json input
  • generating the witness
  • proper error handling

Testing & correctness

I haven't yet done any proper testing, apart from "works for our purposes".

Circuit optimizations

NOTE: you have to run circom with the --O2 options, otherwise the witness format will be most probably incompatible with the the one generated by circom-witnesscalc.

Graph file format

circom-witnesscalc produces binary files encoding a computation graph.

This has the following format:

  • 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

Node format:

  • varint length prefix
  • 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...)
Description
Circom witness generation experiments
Readme
Languages
Haskell 53.6%
Nim 46.4%