⚠️ This repo has NOT been audited and is NOT intended for a production environment yet.
Solidity verifier generator for halo2
proof with KZG polynomial commitment scheme on BN254.
For audited solidity verifier generator and proof aggregation toolkits, please refer to snark-verifier
.
let generator = SolidityGenerator::new(¶ms, &vk, Bdfg21, num_instances);
let (verifier_solidity, vk_solidity) = generator.render_separately().unwrap();
Check examples/separately.rs
for more details.
let generator = SolidityGenerator::new(¶ms, &vk, Bdfg21, num_instances);
let verifier_solidity = generator.render().unwrap();
let calldata = encode_calldata(vk_address, &proof, &instances);
Note that function selector is already included.
- It only allows circuit with exact 1 instance column and no rotated query to this instance column.
- Currently even the
configure
is same, the selector compression might lead to different configuration when selector assignments are different. To avoid this, please usekeygen_vk_custom
withcompress_selectors: false
to do key generation without selector compression. - Now it only supports BDFG21 batch open scheme (aka SHPLONK), GWC19 is not yet implemented.
The Keccak256Transcript
behaves exactly same as the EvmTranscript
in snark-verifier
.
The current solidity verifier generator within snark-verifier
faces a couple of issues:
- The generator receives only unoptimized, low-level operations, such as add or mul. As a result, it currently unrolls all assembly codes, making it susceptible to exceeding the contract size limit, even with a moderately sized circuit.
- The existing solution involves complex abstractions and APIs for consumers.
This repository is a ground-up rebuild, addressing these concerns while maintaining a focus on code size and readability. Remarkably, the gas cost is comparable, if not slightly lower, than the one generated by snark-verifier
.
The previous render_separately
solidity verifier, although granted some degree of reusability, was still dependent on a given circuit's configuation despite being independent of the verifying key. We wanted to reengineer the separate verifier to be completely independent of the circuit configuration, allowing for a single verifier to be used across multiple circuits.
In the process we created two new types of contracts--Halo2VerifierReusable
and Halo2VerifierArtifact
-- that replaced the previous Halo2Verifier
and Halo2VerifierKey
contracts generated by the render_seperately
compilation respectively.
The Halo2VerifierArtifact
extends the original Halo2VerifierKey
by encoding all of the circuit configuration data that was hardcoded in the original separate Halo2Verifier
into memory. The Halo2VerifierReusable
then loads this configuration data dynamicaly from the Halo2VerifierArtifact
at runtime, decodes it and executes the verification computation in a functionally identical manner to the conjoined version.
For large circuits, this reduces deployment costs by 77 percent enabling the deployment of circuits that were previously infeasible due to the contract size limit, requiring an aggregation to get below the limit.
The template is heavily inspired by Aztec's BaseUltraVerifier.sol
.
Note that we have extended the verifier to include the ability to verify mvlookup / logup lookups. This is hidden behind the mvlookup
feature flag.