circom-witnessgen/README.md
2025-03-14 12:29:39 +01:00

2.1 KiB

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 small examples, it turns out that circom-witnesscalc itself is completely broken, in the sense that it doesn't seem to be able to handle nontrivial circuits using any kind of meaningful metaprogramming (that being the only thing which makes circom borderline useful).

And this doesn't look fixable without something like a full rewrite of circom-witnesscalc (?).

Implementation status

Compiler (in Haskell):

  • parsing the graph file
  • naive interpreter
  • constantine backend
  • zikkurat backend
  • arkworks backend

Nim witness generator:

  • parsing the graph file
  • 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...)