You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
6.4 KiB

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>
7 months ago
  1. {{ sdpx }}
  2. /*
  3. Copyright 2021 0KIMS association.
  4. * `folding-schemes-solidity` added comment
  5. This file is a template built out of [snarkJS](https://github.com/iden3/snarkjs) groth16 verifier.
  6. See the original ejs template [here](https://github.com/iden3/snarkjs/blob/master/templates/verifier_groth16.sol.ejs)
  7. *
  8. snarkJS is a free software: you can redistribute it and/or modify it
  9. under the terms of the GNU General Public License as published by
  10. the Free Software Foundation, either version 3 of the License, or
  11. (at your option) any later version.
  12. snarkJS is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  14. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  15. License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. {{ pragma_version }}
  20. contract Groth16Verifier {
  21. // Scalar field size
  22. uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
  23. // Base field size
  24. uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
  25. // Verification Key data
  26. uint256 constant alphax = {{ vkey_alpha_g1.0[0] }};
  27. uint256 constant alphay = {{ vkey_alpha_g1.0[1] }};
  28. uint256 constant betax1 = {{ vkey_beta_g2.0[0][1] }};
  29. uint256 constant betax2 = {{ vkey_beta_g2.0[0][0] }};
  30. uint256 constant betay1 = {{ vkey_beta_g2.0[1][1] }};
  31. uint256 constant betay2 = {{ vkey_beta_g2.0[1][0] }};
  32. uint256 constant gammax1 = {{ vkey_gamma_g2.0[0][1] }};
  33. uint256 constant gammax2 = {{ vkey_gamma_g2.0[0][0] }};
  34. uint256 constant gammay1 = {{ vkey_gamma_g2.0[1][1] }};
  35. uint256 constant gammay2 = {{ vkey_gamma_g2.0[1][0] }};
  36. uint256 constant deltax1 = {{ vkey_delta_g2.0[0][1] }};
  37. uint256 constant deltax2 = {{ vkey_delta_g2.0[0][0] }};
  38. uint256 constant deltay1 = {{ vkey_delta_g2.0[1][1] }};
  39. uint256 constant deltay2 = {{ vkey_delta_g2.0[1][0] }};
  40. {% for (i, point) in gamma_abc_g1.iter().enumerate() %}
  41. uint256 constant IC{{i}}x = {{ point.0[0] }};
  42. uint256 constant IC{{i}}y = {{ point.0[1] }};
  43. {% endfor %}
  44. // Memory data
  45. uint16 constant pVk = 0;
  46. uint16 constant pPairing = 128;
  47. uint16 constant pLastMem = 896;
  48. 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) {
  49. assembly {
  50. function checkField(v) {
  51. if iszero(lt(v, q)) {
  52. mstore(0, 0)
  53. return(0, 0x20)
  54. }
  55. }
  56. // G1 function to multiply a G1 value(x,y) to value in an address
  57. function g1_mulAccC(pR, x, y, s) {
  58. let success
  59. let mIn := mload(0x40)
  60. mstore(mIn, x)
  61. mstore(add(mIn, 32), y)
  62. mstore(add(mIn, 64), s)
  63. success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
  64. if iszero(success) {
  65. mstore(0, 0)
  66. return(0, 0x20)
  67. }
  68. mstore(add(mIn, 64), mload(pR))
  69. mstore(add(mIn, 96), mload(add(pR, 32)))
  70. success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
  71. if iszero(success) {
  72. mstore(0, 0)
  73. return(0, 0x20)
  74. }
  75. }
  76. function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
  77. let _pPairing := add(pMem, pPairing)
  78. let _pVk := add(pMem, pVk)
  79. mstore(_pVk, IC0x)
  80. mstore(add(_pVk, 32), IC0y)
  81. // Compute the linear combination vk_x
  82. {% for (i, _) in gamma_abc_g1.iter().enumerate() %}
  83. {% if loop.first -%}
  84. {%- else -%}
  85. g1_mulAccC(_pVk, IC{{i}}x, IC{{i}}y, calldataload(add(pubSignals, {{(i-1)*32}})))
  86. {%- endif -%}
  87. {% endfor %}
  88. // -A
  89. mstore(_pPairing, calldataload(pA))
  90. mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
  91. // B
  92. mstore(add(_pPairing, 64), calldataload(pB))
  93. mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
  94. mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
  95. mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
  96. // alpha1
  97. mstore(add(_pPairing, 192), alphax)
  98. mstore(add(_pPairing, 224), alphay)
  99. // beta2
  100. mstore(add(_pPairing, 256), betax1)
  101. mstore(add(_pPairing, 288), betax2)
  102. mstore(add(_pPairing, 320), betay1)
  103. mstore(add(_pPairing, 352), betay2)
  104. // vk_x
  105. mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
  106. mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
  107. // gamma2
  108. mstore(add(_pPairing, 448), gammax1)
  109. mstore(add(_pPairing, 480), gammax2)
  110. mstore(add(_pPairing, 512), gammay1)
  111. mstore(add(_pPairing, 544), gammay2)
  112. // C
  113. mstore(add(_pPairing, 576), calldataload(pC))
  114. mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
  115. // delta2
  116. mstore(add(_pPairing, 640), deltax1)
  117. mstore(add(_pPairing, 672), deltax2)
  118. mstore(add(_pPairing, 704), deltay1)
  119. mstore(add(_pPairing, 736), deltay2)
  120. let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
  121. isOk := and(success, mload(_pPairing))
  122. }
  123. let pMem := mload(0x40)
  124. mstore(0x40, add(pMem, pLastMem))
  125. // Validate that all evaluations ∈ F
  126. {% for (i, _) in gamma_abc_g1.iter().enumerate() %}
  127. checkField(calldataload(add(_pubSignals, {{i*32}})))
  128. {% endfor %}
  129. // Validate all evaluations
  130. let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
  131. mstore(0, isValid)
  132. return(0, 0x20)
  133. }
  134. }
  135. }