Add solidity groth16, kzg10 and final decider verifiers in a dedicated workspace (#70)
* change: Refactor structure into workspace
* chore: Add empty readme
* change: Transform repo into workspace
* add: Create folding-verifier-solidity crate
* add: Include askama.toml for `sol` extension escaper
* add: Jordi's old Groth16 verifier .sol template and adapt it
* tmp: create simple template struct to test
* Update FoldingSchemes trait, fit Nova+CycleFold
- update lib.rs's `FoldingScheme` trait interface
- fit Nova+CycleFold into the `FoldingScheme` trait
- refactor `src/nova/*`
* chore: add serialization assets for testing
Now we include an `assets` folder with a serialized proof & vk for tests
* Add `examples` dir, with Nova's `FoldingScheme` example
* polishing
* expose poseidon_test_config outside tests
* change: Refactor structure into workspace
* chore: Add empty readme
* change: Transform repo into workspace
* add: Create folding-verifier-solidity crate
* add: Include askama.toml for `sol` extension escaper
* add: Jordi's old Groth16 verifier .sol template and adapt it
* tmp: create simple template struct to test
* feat: templating kzg working
* chore: add emv and revm
* feat: start evm file
* chore: add ark-poly-commit
* chore: move `commitment` to `folding-schemes`
* chore: update `.gitignore` to ignore generated contracts
* chore: update template with bn254 lib on it (avoids import), update for loop to account for whitespaces
* refactor: update template with no lib
* feat: add evm deploy code, compile and create kzg verifier
* chore: update `Cargo.toml` to have `folding-schemes` available with verifiers
* feat: start kzg prove and verify with sol
* chore: compute crs from kzg prover
* feat: evm kzg verification passing
* tmp
* change: Swap order of G2 coordinates within the template
* Update way to serialize proof with correct order
* chore: update `Cargo.toml`
* chore: add revm
* chore: add `save_solidity`
* refactor: verifiers in dedicated mod
* refactor: have dedicated `utils` module
* chore: expose modules
* chore: update verifier for kzg
* chore: rename templates
* fix: look for binary using also name of contract
* refactor: generate groth16 proof for sha256 pre-image, generate groth16 template with verifying key
* chore: template renaming
* fix: switch circuit for circuit that simply adds
* feat: generates test data on the fly
* feat: update to latest groth16 verifier
* refactor: rename folder, update `.gitignore`
* chore: update `Cargo.toml`
* chore: update templates extension to indicate that they are templates
* chore: rename templates, both files and structs
* fix: template inheritance working
* feat: template spdx and pragma statements
* feat: decider verifier compiles, update test for kzg10 and groth16 templates
* feat: parameterize which size of the crs should be stored on the contract
* chore: add comment on how the groth16 and kzg10 proofs will be linked together
* chore: cargo clippy run
* chore: cargo clippy tests
* chore: cargo fmt
* refactor: remove unused lifetime parameter
* chore: end merge
* chore: move examples to `folding-schemes` workspace
* get latest main changes
* fix: temp fix clippy warnings, will remove lints once not used in tests only
* fix: cargo clippy lint added on `code_size`
* fix: update path to test circuit and add step for installing solc
* chore: remove `save_solidity` steps
* fix: the borrowed expression implements the required traits
* chore: update `Cargo.toml`
* chore: remove extra `[patch.crates-io]`
* fix: update to patch at the workspace level and add comment explaining this
* refactor: correct `staticcall` with valid input/output sizes and change return syntax for pairing
* refactor: expose modules and remove `dead_code` calls
* chore: update `README.md`, add additional comments on `kzg10` template and update `groth16` template comments
* chore: be clearer on attributions on `kzg10`
---------
Co-authored-by: CPerezz <c.perezbaro@gmail.com>
Co-authored-by: arnaucube <root@arnaucube.com> 9 months ago |
|
{{ sdpx }} /*
Copyright 2021 0KIMS association.
* `folding-schemes-solidity` added comment This file is a template built out of [snarkJS](https://github.com/iden3/snarkjs) groth16 verifier.
See the original ejs template [here](https://github.com/iden3/snarkjs/blob/master/templates/verifier_groth16.sol.ejs)
*
snarkJS is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
snarkJS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
*/
{{ pragma_version }}
contract Groth16Verifier { // Scalar field size
uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Base field size
uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
// Verification Key data
uint256 constant alphax = {{ vkey_alpha_g1.0[0] }}; uint256 constant alphay = {{ vkey_alpha_g1.0[1] }}; uint256 constant betax1 = {{ vkey_beta_g2.0[0][1] }}; uint256 constant betax2 = {{ vkey_beta_g2.0[0][0] }}; uint256 constant betay1 = {{ vkey_beta_g2.0[1][1] }}; uint256 constant betay2 = {{ vkey_beta_g2.0[1][0] }}; uint256 constant gammax1 = {{ vkey_gamma_g2.0[0][1] }}; uint256 constant gammax2 = {{ vkey_gamma_g2.0[0][0] }}; uint256 constant gammay1 = {{ vkey_gamma_g2.0[1][1] }}; uint256 constant gammay2 = {{ vkey_gamma_g2.0[1][0] }}; uint256 constant deltax1 = {{ vkey_delta_g2.0[0][1] }}; uint256 constant deltax2 = {{ vkey_delta_g2.0[0][0] }}; uint256 constant deltay1 = {{ vkey_delta_g2.0[1][1] }}; uint256 constant deltay2 = {{ vkey_delta_g2.0[1][0] }};
{% for (i, point) in gamma_abc_g1.iter().enumerate() %} uint256 constant IC{{i}}x = {{ point.0[0] }}; uint256 constant IC{{i}}y = {{ point.0[1] }}; {% endfor %} // Memory data
uint16 constant pVk = 0; uint16 constant pPairing = 128;
uint16 constant pLastMem = 896;
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[{{ gamma_abc_len - 1 }}] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, q)) { mstore(0, 0) return(0, 0x20) } } // G1 function to multiply a G1 value(x,y) to value in an address
function g1_mulAccC(pR, x, y, s) { let success let mIn := mload(0x40) mstore(mIn, x) mstore(add(mIn, 32), y) mstore(add(mIn, 64), s)
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
if iszero(success) { mstore(0, 0) return(0, 0x20) }
mstore(add(mIn, 64), mload(pR)) mstore(add(mIn, 96), mload(add(pR, 32)))
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
if iszero(success) { mstore(0, 0) return(0, 0x20) } }
function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk { let _pPairing := add(pMem, pPairing) let _pVk := add(pMem, pVk)
mstore(_pVk, IC0x) mstore(add(_pVk, 32), IC0y)
// Compute the linear combination vk_x
{% for (i, _) in gamma_abc_g1.iter().enumerate() %} {% if loop.first -%} {%- else -%} g1_mulAccC(_pVk, IC{{i}}x, IC{{i}}y, calldataload(add(pubSignals, {{(i-1)*32}}))) {%- endif -%} {% endfor %}
// -A
mstore(_pPairing, calldataload(pA)) mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
// B
mstore(add(_pPairing, 64), calldataload(pB)) mstore(add(_pPairing, 96), calldataload(add(pB, 32))) mstore(add(_pPairing, 128), calldataload(add(pB, 64))) mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
// alpha1
mstore(add(_pPairing, 192), alphax) mstore(add(_pPairing, 224), alphay)
// beta2
mstore(add(_pPairing, 256), betax1) mstore(add(_pPairing, 288), betax2) mstore(add(_pPairing, 320), betay1) mstore(add(_pPairing, 352), betay2)
// vk_x
mstore(add(_pPairing, 384), mload(add(pMem, pVk))) mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
// gamma2
mstore(add(_pPairing, 448), gammax1) mstore(add(_pPairing, 480), gammax2) mstore(add(_pPairing, 512), gammay1) mstore(add(_pPairing, 544), gammay2)
// C
mstore(add(_pPairing, 576), calldataload(pC)) mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
// delta2
mstore(add(_pPairing, 640), deltax1) mstore(add(_pPairing, 672), deltax2) mstore(add(_pPairing, 704), deltay1) mstore(add(_pPairing, 736), deltay2)
let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
isOk := and(success, mload(_pPairing)) }
let pMem := mload(0x40) mstore(0x40, add(pMem, pLastMem))
// Validate that all evaluations ∈ F
{% for (i, _) in gamma_abc_g1.iter().enumerate() %} checkField(calldataload(add(_pubSignals, {{i*32}}))) {% endfor %}
// Validate all evaluations
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
mstore(0, isValid) return(0, 0x20) } } }
|