PoseidonGate's recursive evaluations were using a lot of gates, and the MDS layer was the main culprit.
The other issue is that `constant_layer_recursive` creates a bunch of `ArithmeticGate`s with unique constants. We could either change `ArithmeticGate` to support different constants per operation, or wire in constants from `ConstantGate`, and change `ConstantGate` to support several constants per gate.
This won't really help anything near term since we're still between 2^12 and 2^13, but could have some benefits later, depending on what recursion arities and security settings we end up using.
`PoseidonMdsGate` needs `2 * D * WIDTH = 48` routed wires, and the combination of adding a gate and increasing routed wires slows down the prover a bit. So for now, I kept it at 28 wires, and the old code path is still used.
With this approach, we don't need `Target::PublicInput`; any routable `Target` can be marked as a public input via `register_public_input`. The circuit itself hashes these targets, and routes the hash output to the first four wires of a `PublicInputGate`, which is placed at an arbitrary location in the circuit.
All gates have direct access to the purported hash of public inputs. We could think of them as accessing `PI_hash_i(x)` (as in Plonk), but these are now (four) constant functions, so they effectively have direct access to the hash itself.
`PublicInputGate` checks that its first four wires match this purported public input hash. The other gates ignore the hash.
Resolves#64.
* Draw challenge points from the extension field
* Now building
* Misc
* Default eval_unfiltered_base
* fmt
* A few field settings
* Add to Sage
* Display tweak
* eval_filtered_base
* Quartic in bench
* Missing methods
* Fix tests
* PR feedback
Over quartic field extension (for now). This would be used in our FRI recursive verifier later, for the consistency check.
To summarize the wires,
- `n` inputs for the `n` points to interpolate (don't need `4n` since they'll be in the subgroup of the base field)
- `4n` inputs for the `n` (extension field) values to interpolate
- `4` inputs for the point to evaluate the interpolant at (beta, which will be drawn from the extension field right?)
- `4` outputs for the interpolated value
- `4n` internal wires for the interpolant's coefficients
This definitely isn't the most optimal approach, e.g. we could route in a single "base" point and derive its neighboring points, but just wanted to keep it simple for now.
... and other minor refactoring.
`bench_recursion` will be the default bin run by `cargo run`; the otheres can be selected with the `--bin` flag.
We could probably delete some of the other binaries later. E.g. `field_search` might not be useful any more. `bench_fft` should maybe be converted to a benchmark (although there are some pros and cons, e.g. the bench framework has a minimum number of runs, and isn't helpful in testing multi-core performance).