@enclave-e3/contracts 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json +3 -3
  2. package/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/artifacts.d.ts +3 -3
  3. package/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/ITransparentUpgradeableProxy.json +1 -1
  4. package/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json +3 -3
  5. package/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/artifacts.d.ts +4 -4
  6. package/artifacts/build-info/{solc-0_8_28-c77ac33099bb85c15f46d194dd2b735e036cb799.json → solc-0_8_28-e60a5d7c133605edcf61acdd5ba43ab44ee0928e.json} +27 -12
  7. package/artifacts/build-info/solc-0_8_28-e60a5d7c133605edcf61acdd5ba43ab44ee0928e.output.json +1 -0
  8. package/artifacts/contracts/E3RefundManager.sol/E3RefundManager.json +684 -0
  9. package/artifacts/contracts/E3RefundManager.sol/artifacts.d.ts +27 -0
  10. package/artifacts/contracts/Enclave.sol/Enclave.json +530 -182
  11. package/artifacts/contracts/Enclave.sol/artifacts.d.ts +4 -4
  12. package/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json +14 -1
  13. package/artifacts/contracts/interfaces/IBondingRegistry.sol/artifacts.d.ts +2 -2
  14. package/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json +55 -5
  15. package/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/artifacts.d.ts +2 -2
  16. package/artifacts/contracts/interfaces/IComputeProvider.sol/IComputeProvider.json +1 -1
  17. package/artifacts/contracts/interfaces/IComputeProvider.sol/artifacts.d.ts +1 -1
  18. package/artifacts/contracts/interfaces/IDecryptionVerifier.sol/IDecryptionVerifier.json +1 -1
  19. package/artifacts/contracts/interfaces/IDecryptionVerifier.sol/artifacts.d.ts +1 -1
  20. package/artifacts/contracts/interfaces/IE3Program.sol/IE3Program.json +19 -24
  21. package/artifacts/contracts/interfaces/IE3Program.sol/artifacts.d.ts +2 -2
  22. package/artifacts/contracts/interfaces/IE3RefundManager.sol/IE3RefundManager.json +470 -0
  23. package/artifacts/contracts/interfaces/IE3RefundManager.sol/artifacts.d.ts +27 -0
  24. package/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json +383 -128
  25. package/artifacts/contracts/interfaces/IEnclave.sol/artifacts.d.ts +2 -2
  26. package/artifacts/contracts/interfaces/ISlashVerifier.sol/ISlashVerifier.json +1 -1
  27. package/artifacts/contracts/interfaces/ISlashVerifier.sol/artifacts.d.ts +1 -1
  28. package/artifacts/contracts/interfaces/ISlashingManager.sol/ISlashingManager.json +1 -1
  29. package/artifacts/contracts/interfaces/ISlashingManager.sol/artifacts.d.ts +1 -1
  30. package/artifacts/contracts/lib/ExitQueueLib.sol/ExitQueueLib.json +1 -1
  31. package/artifacts/contracts/lib/ExitQueueLib.sol/artifacts.d.ts +1 -1
  32. package/artifacts/contracts/registry/BondingRegistry.sol/BondingRegistry.json +16 -3
  33. package/artifacts/contracts/registry/BondingRegistry.sol/artifacts.d.ts +4 -4
  34. package/artifacts/contracts/registry/CiphernodeRegistryOwnable.sol/CiphernodeRegistryOwnable.json +91 -25
  35. package/artifacts/contracts/registry/CiphernodeRegistryOwnable.sol/artifacts.d.ts +6 -6
  36. package/artifacts/contracts/slashing/SlashingManager.sol/SlashingManager.json +3 -3
  37. package/artifacts/contracts/slashing/SlashingManager.sol/artifacts.d.ts +3 -3
  38. package/artifacts/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistry.json +57 -7
  39. package/artifacts/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistryEmptyKey.json +57 -7
  40. package/artifacts/contracts/test/MockCiphernodeRegistry.sol/artifacts.d.ts +8 -8
  41. package/artifacts/contracts/test/MockComputeProvider.sol/MockComputeProvider.json +3 -3
  42. package/artifacts/contracts/test/MockComputeProvider.sol/artifacts.d.ts +3 -3
  43. package/artifacts/contracts/test/MockDecryptionVerifier.sol/MockDecryptionVerifier.json +1 -1
  44. package/artifacts/contracts/test/MockDecryptionVerifier.sol/artifacts.d.ts +1 -1
  45. package/artifacts/contracts/test/MockE3Program.sol/MockE3Program.json +21 -26
  46. package/artifacts/contracts/test/MockE3Program.sol/artifacts.d.ts +4 -4
  47. package/artifacts/contracts/test/MockSlashingVerifier.sol/MockSlashingVerifier.json +1 -1
  48. package/artifacts/contracts/test/MockSlashingVerifier.sol/artifacts.d.ts +1 -1
  49. package/artifacts/contracts/test/MockStableToken.sol/MockUSDC.json +3 -3
  50. package/artifacts/contracts/test/MockStableToken.sol/artifacts.d.ts +3 -3
  51. package/artifacts/contracts/token/EnclaveTicketToken.sol/EnclaveTicketToken.json +14 -22
  52. package/artifacts/contracts/token/EnclaveTicketToken.sol/artifacts.d.ts +4 -4
  53. package/artifacts/contracts/token/EnclaveToken.sol/EnclaveToken.json +10 -10
  54. package/artifacts/contracts/token/EnclaveToken.sol/artifacts.d.ts +4 -4
  55. package/artifacts/contracts/verifier/DkgPkVerifier.sol/BaseZKHonkVerifier.json +89 -0
  56. package/artifacts/contracts/verifier/DkgPkVerifier.sol/CommitmentSchemeLib.json +13 -0
  57. package/artifacts/contracts/verifier/DkgPkVerifier.sol/DkgPkVerifier.json +186 -0
  58. package/artifacts/contracts/verifier/DkgPkVerifier.sol/FrLib.json +13 -0
  59. package/artifacts/contracts/verifier/DkgPkVerifier.sol/Honk.json +13 -0
  60. package/artifacts/contracts/verifier/DkgPkVerifier.sol/HonkVerificationKey.json +13 -0
  61. package/artifacts/contracts/verifier/DkgPkVerifier.sol/IVerifier.json +38 -0
  62. package/artifacts/contracts/verifier/DkgPkVerifier.sol/RelationsLib.json +13 -0
  63. package/artifacts/contracts/verifier/DkgPkVerifier.sol/ZKTranscriptLib.json +400 -0
  64. package/artifacts/contracts/verifier/DkgPkVerifier.sol/artifacts.d.ts +155 -0
  65. package/artifacts/poseidon-solidity/PoseidonT3.sol/PoseidonT3.json +1 -1
  66. package/artifacts/poseidon-solidity/PoseidonT3.sol/artifacts.d.ts +1 -1
  67. package/contracts/E3RefundManager.sol +365 -0
  68. package/contracts/Enclave.sol +426 -119
  69. package/contracts/interfaces/IBondingRegistry.sol +6 -0
  70. package/contracts/interfaces/ICiphernodeRegistry.sol +29 -7
  71. package/contracts/interfaces/IE3.sol +2 -6
  72. package/contracts/interfaces/IE3Program.sol +3 -7
  73. package/contracts/interfaces/IE3RefundManager.sol +150 -0
  74. package/contracts/interfaces/IEnclave.sol +186 -64
  75. package/contracts/registry/BondingRegistry.sol +9 -0
  76. package/contracts/registry/CiphernodeRegistryOwnable.sol +89 -42
  77. package/contracts/test/MockCiphernodeRegistry.sol +20 -6
  78. package/contracts/test/MockE3Program.sol +3 -8
  79. package/contracts/verifier/DkgPkVerifier.sol +3140 -0
  80. package/dist/hardhat.config.d.ts.map +1 -1
  81. package/dist/hardhat.config.js +4 -4
  82. package/dist/ignition/modules/dkgPkVerifier.d.ts +3 -0
  83. package/dist/ignition/modules/dkgPkVerifier.d.ts.map +1 -0
  84. package/dist/ignition/modules/dkgPkVerifier.js +10 -0
  85. package/dist/ignition/modules/e3RefundManager.d.ts +3 -0
  86. package/dist/ignition/modules/e3RefundManager.d.ts.map +1 -0
  87. package/dist/ignition/modules/e3RefundManager.js +23 -0
  88. package/dist/ignition/modules/enclave.d.ts.map +1 -1
  89. package/dist/ignition/modules/enclave.js +10 -0
  90. package/dist/scripts/deployAndSave/e3RefundManager.d.ts +20 -0
  91. package/dist/scripts/deployAndSave/e3RefundManager.d.ts.map +1 -0
  92. package/dist/scripts/deployAndSave/e3RefundManager.js +55 -0
  93. package/dist/scripts/deployAndSave/enclave.d.ts +13 -1
  94. package/dist/scripts/deployAndSave/enclave.d.ts.map +1 -1
  95. package/dist/scripts/deployAndSave/enclave.js +8 -1
  96. package/dist/scripts/deployAndSave/verifiers.d.ts +29 -0
  97. package/dist/scripts/deployAndSave/verifiers.d.ts.map +1 -0
  98. package/dist/scripts/deployAndSave/verifiers.js +109 -0
  99. package/dist/scripts/deployEnclave.d.ts.map +1 -1
  100. package/dist/scripts/deployEnclave.js +36 -0
  101. package/dist/scripts/deployVerifiers.d.ts +2 -0
  102. package/dist/scripts/deployVerifiers.d.ts.map +1 -0
  103. package/dist/scripts/deployVerifiers.js +33 -0
  104. package/dist/scripts/index.d.ts +1 -0
  105. package/dist/scripts/index.d.ts.map +1 -1
  106. package/dist/scripts/index.js +1 -0
  107. package/dist/tasks/enclave.d.ts +0 -2
  108. package/dist/tasks/enclave.d.ts.map +1 -1
  109. package/dist/tasks/enclave.js +8 -72
  110. package/dist/tasks/program.d.ts +2 -0
  111. package/dist/tasks/program.d.ts.map +1 -0
  112. package/dist/tasks/program.js +55 -0
  113. package/dist/test/E3Lifecycle/E3Integration.spec.d.ts +2 -0
  114. package/dist/test/E3Lifecycle/E3Integration.spec.d.ts.map +1 -0
  115. package/dist/test/E3Lifecycle/E3Integration.spec.js +757 -0
  116. package/dist/test/Enclave.spec.js +83 -406
  117. package/dist/test/Registry/CiphernodeRegistryOwnable.spec.js +133 -59
  118. package/dist/types/contracts/E3RefundManager.d.ts +379 -0
  119. package/dist/types/contracts/E3RefundManager.d.ts.map +1 -0
  120. package/dist/types/contracts/E3RefundManager.js +24 -0
  121. package/dist/types/contracts/Enclave.d.ts +325 -73
  122. package/dist/types/contracts/Enclave.d.ts.map +1 -1
  123. package/dist/types/contracts/Enclave.js +27 -3
  124. package/dist/types/contracts/index.d.ts +3 -0
  125. package/dist/types/contracts/index.d.ts.map +1 -1
  126. package/dist/types/contracts/interfaces/IBondingRegistry.d.ts +11 -1
  127. package/dist/types/contracts/interfaces/IBondingRegistry.d.ts.map +1 -1
  128. package/dist/types/contracts/interfaces/ICiphernodeRegistry.d.ts +35 -7
  129. package/dist/types/contracts/interfaces/ICiphernodeRegistry.d.ts.map +1 -1
  130. package/dist/types/contracts/interfaces/ICiphernodeRegistry.js +4 -0
  131. package/dist/types/contracts/interfaces/IE3Program.d.ts +16 -18
  132. package/dist/types/contracts/interfaces/IE3Program.d.ts.map +1 -1
  133. package/dist/types/contracts/interfaces/IE3RefundManager.d.ts +238 -0
  134. package/dist/types/contracts/interfaces/IE3RefundManager.d.ts.map +1 -0
  135. package/dist/types/contracts/interfaces/IE3RefundManager.js +16 -0
  136. package/dist/types/contracts/interfaces/IEnclave.d.ts +290 -62
  137. package/dist/types/contracts/interfaces/IEnclave.d.ts.map +1 -1
  138. package/dist/types/contracts/interfaces/IEnclave.js +27 -3
  139. package/dist/types/contracts/interfaces/index.d.ts +1 -0
  140. package/dist/types/contracts/interfaces/index.d.ts.map +1 -1
  141. package/dist/types/contracts/registry/BondingRegistry.d.ts +11 -1
  142. package/dist/types/contracts/registry/BondingRegistry.d.ts.map +1 -1
  143. package/dist/types/contracts/registry/CiphernodeRegistryOwnable.d.ts +35 -7
  144. package/dist/types/contracts/registry/CiphernodeRegistryOwnable.d.ts.map +1 -1
  145. package/dist/types/contracts/registry/CiphernodeRegistryOwnable.js +4 -0
  146. package/dist/types/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistry.d.ts +35 -7
  147. package/dist/types/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistry.d.ts.map +1 -1
  148. package/dist/types/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistry.js +4 -0
  149. package/dist/types/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistryEmptyKey.d.ts +35 -7
  150. package/dist/types/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistryEmptyKey.d.ts.map +1 -1
  151. package/dist/types/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistryEmptyKey.js +4 -0
  152. package/dist/types/contracts/test/MockE3Program.d.ts +16 -18
  153. package/dist/types/contracts/test/MockE3Program.d.ts.map +1 -1
  154. package/dist/types/contracts/verifier/DkgPkVerifier.sol/BaseZKHonkVerifier.d.ts +36 -0
  155. package/dist/types/contracts/verifier/DkgPkVerifier.sol/BaseZKHonkVerifier.d.ts.map +1 -0
  156. package/dist/types/contracts/verifier/DkgPkVerifier.sol/BaseZKHonkVerifier.js +1 -0
  157. package/dist/types/contracts/verifier/DkgPkVerifier.sol/DkgPkVerifier.d.ts +36 -0
  158. package/dist/types/contracts/verifier/DkgPkVerifier.sol/DkgPkVerifier.d.ts.map +1 -0
  159. package/dist/types/contracts/verifier/DkgPkVerifier.sol/DkgPkVerifier.js +1 -0
  160. package/dist/types/contracts/verifier/DkgPkVerifier.sol/IVerifier.d.ts +36 -0
  161. package/dist/types/contracts/verifier/DkgPkVerifier.sol/IVerifier.d.ts.map +1 -0
  162. package/dist/types/contracts/verifier/DkgPkVerifier.sol/IVerifier.js +1 -0
  163. package/dist/types/contracts/verifier/DkgPkVerifier.sol/ZKTranscriptLib.d.ts +138 -0
  164. package/dist/types/contracts/verifier/DkgPkVerifier.sol/ZKTranscriptLib.d.ts.map +1 -0
  165. package/dist/types/contracts/verifier/DkgPkVerifier.sol/ZKTranscriptLib.js +1 -0
  166. package/dist/types/contracts/verifier/DkgPkVerifier.sol/index.d.ts +5 -0
  167. package/dist/types/contracts/verifier/DkgPkVerifier.sol/index.d.ts.map +1 -0
  168. package/dist/types/contracts/verifier/DkgPkVerifier.sol/index.js +1 -0
  169. package/dist/types/contracts/verifier/index.d.ts +3 -0
  170. package/dist/types/contracts/verifier/index.d.ts.map +1 -0
  171. package/dist/types/contracts/verifier/index.js +1 -0
  172. package/dist/types/factories/@openzeppelin/contracts/proxy/transparent/ProxyAdmin__factory.d.ts +1 -1
  173. package/dist/types/factories/@openzeppelin/contracts/proxy/transparent/ProxyAdmin__factory.d.ts.map +1 -1
  174. package/dist/types/factories/@openzeppelin/contracts/proxy/transparent/ProxyAdmin__factory.js +1 -1
  175. package/dist/types/factories/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy__factory.d.ts +1 -1
  176. package/dist/types/factories/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy__factory.d.ts.map +1 -1
  177. package/dist/types/factories/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy__factory.js +1 -1
  178. package/dist/types/factories/contracts/E3RefundManager__factory.d.ts +540 -0
  179. package/dist/types/factories/contracts/E3RefundManager__factory.d.ts.map +1 -0
  180. package/dist/types/factories/contracts/E3RefundManager__factory.js +706 -0
  181. package/dist/types/factories/contracts/Enclave__factory.d.ts +412 -143
  182. package/dist/types/factories/contracts/Enclave__factory.d.ts.map +1 -1
  183. package/dist/types/factories/contracts/Enclave__factory.js +528 -180
  184. package/dist/types/factories/contracts/index.d.ts +2 -0
  185. package/dist/types/factories/contracts/index.d.ts.map +1 -1
  186. package/dist/types/factories/contracts/index.js +2 -0
  187. package/dist/types/factories/contracts/interfaces/IBondingRegistry__factory.d.ts +10 -0
  188. package/dist/types/factories/contracts/interfaces/IBondingRegistry__factory.d.ts.map +1 -1
  189. package/dist/types/factories/contracts/interfaces/IBondingRegistry__factory.js +13 -0
  190. package/dist/types/factories/contracts/interfaces/ICiphernodeRegistry__factory.d.ts +42 -4
  191. package/dist/types/factories/contracts/interfaces/ICiphernodeRegistry__factory.d.ts.map +1 -1
  192. package/dist/types/factories/contracts/interfaces/ICiphernodeRegistry__factory.js +54 -4
  193. package/dist/types/factories/contracts/interfaces/IE3Program__factory.d.ts +14 -18
  194. package/dist/types/factories/contracts/interfaces/IE3Program__factory.d.ts.map +1 -1
  195. package/dist/types/factories/contracts/interfaces/IE3Program__factory.js +18 -23
  196. package/dist/types/factories/contracts/interfaces/IE3RefundManager__factory.d.ts +358 -0
  197. package/dist/types/factories/contracts/interfaces/IE3RefundManager__factory.d.ts.map +1 -0
  198. package/dist/types/factories/contracts/interfaces/IE3RefundManager__factory.js +471 -0
  199. package/dist/types/factories/contracts/interfaces/IEnclave__factory.d.ts +303 -103
  200. package/dist/types/factories/contracts/interfaces/IEnclave__factory.d.ts.map +1 -1
  201. package/dist/types/factories/contracts/interfaces/IEnclave__factory.js +382 -127
  202. package/dist/types/factories/contracts/interfaces/index.d.ts +1 -0
  203. package/dist/types/factories/contracts/interfaces/index.d.ts.map +1 -1
  204. package/dist/types/factories/contracts/interfaces/index.js +1 -0
  205. package/dist/types/factories/contracts/registry/BondingRegistry__factory.d.ts +11 -1
  206. package/dist/types/factories/contracts/registry/BondingRegistry__factory.d.ts.map +1 -1
  207. package/dist/types/factories/contracts/registry/BondingRegistry__factory.js +14 -1
  208. package/dist/types/factories/contracts/registry/CiphernodeRegistryOwnable__factory.d.ts +62 -12
  209. package/dist/types/factories/contracts/registry/CiphernodeRegistryOwnable__factory.d.ts.map +1 -1
  210. package/dist/types/factories/contracts/registry/CiphernodeRegistryOwnable__factory.js +79 -13
  211. package/dist/types/factories/contracts/slashing/SlashingManager__factory.d.ts +1 -1
  212. package/dist/types/factories/contracts/slashing/SlashingManager__factory.d.ts.map +1 -1
  213. package/dist/types/factories/contracts/slashing/SlashingManager__factory.js +1 -1
  214. package/dist/types/factories/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistryEmptyKey__factory.d.ts +43 -5
  215. package/dist/types/factories/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistryEmptyKey__factory.d.ts.map +1 -1
  216. package/dist/types/factories/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistryEmptyKey__factory.js +55 -5
  217. package/dist/types/factories/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistry__factory.d.ts +43 -5
  218. package/dist/types/factories/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistry__factory.d.ts.map +1 -1
  219. package/dist/types/factories/contracts/test/MockCiphernodeRegistry.sol/MockCiphernodeRegistry__factory.js +55 -5
  220. package/dist/types/factories/contracts/test/MockComputeProvider__factory.d.ts +1 -1
  221. package/dist/types/factories/contracts/test/MockComputeProvider__factory.d.ts.map +1 -1
  222. package/dist/types/factories/contracts/test/MockComputeProvider__factory.js +1 -1
  223. package/dist/types/factories/contracts/test/MockE3Program__factory.d.ts +15 -19
  224. package/dist/types/factories/contracts/test/MockE3Program__factory.d.ts.map +1 -1
  225. package/dist/types/factories/contracts/test/MockE3Program__factory.js +19 -24
  226. package/dist/types/factories/contracts/test/MockStableToken.sol/MockUSDC__factory.d.ts +1 -1
  227. package/dist/types/factories/contracts/test/MockStableToken.sol/MockUSDC__factory.d.ts.map +1 -1
  228. package/dist/types/factories/contracts/test/MockStableToken.sol/MockUSDC__factory.js +1 -1
  229. package/dist/types/factories/contracts/token/EnclaveTicketToken__factory.d.ts +1 -1
  230. package/dist/types/factories/contracts/token/EnclaveTicketToken__factory.d.ts.map +1 -1
  231. package/dist/types/factories/contracts/token/EnclaveTicketToken__factory.js +1 -1
  232. package/dist/types/factories/contracts/token/EnclaveToken__factory.d.ts +1 -1
  233. package/dist/types/factories/contracts/token/EnclaveToken__factory.d.ts.map +1 -1
  234. package/dist/types/factories/contracts/token/EnclaveToken__factory.js +1 -1
  235. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/BaseZKHonkVerifier__factory.d.ts +66 -0
  236. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/BaseZKHonkVerifier__factory.d.ts.map +1 -0
  237. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/BaseZKHonkVerifier__factory.js +90 -0
  238. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/DkgPkVerifier__factory.d.ts +87 -0
  239. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/DkgPkVerifier__factory.d.ts.map +1 -0
  240. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/DkgPkVerifier__factory.js +122 -0
  241. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/IVerifier__factory.d.ts +26 -0
  242. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/IVerifier__factory.d.ts.map +1 -0
  243. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/IVerifier__factory.js +39 -0
  244. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/ZKTranscriptLib__factory.d.ts +323 -0
  245. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/ZKTranscriptLib__factory.d.ts.map +1 -0
  246. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/ZKTranscriptLib__factory.js +422 -0
  247. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/index.d.ts +5 -0
  248. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/index.d.ts.map +1 -0
  249. package/dist/types/factories/contracts/verifier/DkgPkVerifier.sol/index.js +7 -0
  250. package/dist/types/factories/contracts/verifier/index.d.ts +2 -0
  251. package/dist/types/factories/contracts/verifier/index.d.ts.map +1 -0
  252. package/dist/types/factories/contracts/verifier/index.js +4 -0
  253. package/dist/types/index.d.ts +12 -0
  254. package/dist/types/index.d.ts.map +1 -1
  255. package/dist/types/index.js +6 -0
  256. package/package.json +17 -3
  257. package/artifacts/build-info/solc-0_8_28-c77ac33099bb85c15f46d194dd2b735e036cb799.output.json +0 -1
@@ -0,0 +1,3140 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2022 Aztec
3
+ pragma solidity >=0.8.27;
4
+
5
+ uint256 constant N = 8192;
6
+ uint256 constant LOG_N = 13;
7
+ uint256 constant NUMBER_OF_PUBLIC_INPUTS = 17;
8
+ uint256 constant VK_HASH = 0x170affbea8713b79ad326398ea7b49424c51fa4dca10a65185ad33dbce4d6001;
9
+ library HonkVerificationKey {
10
+ function loadVerificationKey()
11
+ internal
12
+ pure
13
+ returns (Honk.VerificationKey memory)
14
+ {
15
+ Honk.VerificationKey memory vk = Honk.VerificationKey({
16
+ circuitSize: uint256(8192),
17
+ logCircuitSize: uint256(13),
18
+ publicInputsSize: uint256(17),
19
+ ql: Honk.G1Point({
20
+ x: uint256(
21
+ 0x22a702d6d3957500783049fee5af2a27155cfdf1b6c2958942f5cde4bc63d163
22
+ ),
23
+ y: uint256(
24
+ 0x003567b43861479b2347249040b9a4c4423f494e6dd8a7de9a4e3900741c4551
25
+ )
26
+ }),
27
+ qr: Honk.G1Point({
28
+ x: uint256(
29
+ 0x1333cd6f8595ef95ab9d9744d1d00175a56c1b0bc60000ac6d4eb9ec7315c70a
30
+ ),
31
+ y: uint256(
32
+ 0x1c891650f45fe25cf375ea0b322372757b89799546eed2152766130e6b99efa0
33
+ )
34
+ }),
35
+ qo: Honk.G1Point({
36
+ x: uint256(
37
+ 0x251fdc445de2b90170e8c86c41a81303bb3de75352f2bd6f095bdab77486445a
38
+ ),
39
+ y: uint256(
40
+ 0x06f20c995414f9b6bdb794492d328124e2b7676329a5a1724365076751ad2a8a
41
+ )
42
+ }),
43
+ q4: Honk.G1Point({
44
+ x: uint256(
45
+ 0x12600bb185b845c63e4b9d5c310db2d257aa5d1d09090ef3c8bdd7334e8991d0
46
+ ),
47
+ y: uint256(
48
+ 0x017ccf0bdad7381ff8a3bef25259d90c296b71c037ee58bcce51cb0b7a6e97f4
49
+ )
50
+ }),
51
+ qm: Honk.G1Point({
52
+ x: uint256(
53
+ 0x1a5c96bf5dac44c45e28380daccedfec1d9a8919999a0d748a8686f7f42cba76
54
+ ),
55
+ y: uint256(
56
+ 0x28c5876a4c88720ff49870cbc3b7f41c26a131f4d57ce95cbc6127859c08931f
57
+ )
58
+ }),
59
+ qc: Honk.G1Point({
60
+ x: uint256(
61
+ 0x2c740230a118ad04f1482eeef2e75a14aed0f961b763120de34d0fbe63ca12b0
62
+ ),
63
+ y: uint256(
64
+ 0x1b9aa7fd5bf93acbaadd615b6e0829e714539fe471bece34b359cd6a96d00294
65
+ )
66
+ }),
67
+ qLookup: Honk.G1Point({
68
+ x: uint256(
69
+ 0x0c4032c3079594eb75a8449d3d5ce8bc3661650d53f9b24d923d8f404cb0bbc9
70
+ ),
71
+ y: uint256(
72
+ 0x1084d709650356d40f0158fd6da81f54eb5fe796a0ca89441369b7c24301f851
73
+ )
74
+ }),
75
+ qArith: Honk.G1Point({
76
+ x: uint256(
77
+ 0x1f13031b7801d2da6d5206a7da087d7661d87905cef81f24e3cbe9e7a1c51488
78
+ ),
79
+ y: uint256(
80
+ 0x2d93aa6923ac15844842bd024199117f43ca14c883f37570030fdf385356a18a
81
+ )
82
+ }),
83
+ qDeltaRange: Honk.G1Point({
84
+ x: uint256(
85
+ 0x300557c1eda8ed63912d72e051bb3431bd54f7395755b820a59ff85295eb36d9
86
+ ),
87
+ y: uint256(
88
+ 0x227e5f5f62555201e96e188514b5387fb7e026a4af0ac209ec6730c4e0e6cc76
89
+ )
90
+ }),
91
+ qElliptic: Honk.G1Point({
92
+ x: uint256(
93
+ 0x20a7925feb244b2ba41d31db4651a6c6c6be672ed0e7711f2ef4c2b89f9c4a5f
94
+ ),
95
+ y: uint256(
96
+ 0x2472b531a32a7d7f80ec3c3375977ba4968f326786473e34d1fd73e6236cf661
97
+ )
98
+ }),
99
+ qMemory: Honk.G1Point({
100
+ x: uint256(
101
+ 0x02095e5acd019e4edaf8d736615b4a159deafdb98a171db591ed499b0219fb4b
102
+ ),
103
+ y: uint256(
104
+ 0x0644f4dc54ac72663d956a233412f748e74b1591553ecbca703829acf75e471a
105
+ )
106
+ }),
107
+ qNnf: Honk.G1Point({
108
+ x: uint256(
109
+ 0x022bae55678012a184d4cb970b8f9a6d1334097d611de534bef96fc9f8d9d011
110
+ ),
111
+ y: uint256(
112
+ 0x284ee2d499274885bcb7a0d77b0a261d9192ec413b0c0a86fb27ae88cdd5a72c
113
+ )
114
+ }),
115
+ qPoseidon2External: Honk.G1Point({
116
+ x: uint256(
117
+ 0x2dd8c7e5ce5f6a7053c173bb140d46830ab962c6c45d637d66171ee540bb21d5
118
+ ),
119
+ y: uint256(
120
+ 0x033b47f5f8496af8d227ef175c47b3f7cd666ebc94f0e63562ebfcf30d73f6e2
121
+ )
122
+ }),
123
+ qPoseidon2Internal: Honk.G1Point({
124
+ x: uint256(
125
+ 0x2940b2ab034af88869e264e12ee268b16c221b5f2cdd96748cce870c1a7bb24a
126
+ ),
127
+ y: uint256(
128
+ 0x04cfb9bfe08adf0e6f25c2cc9e83448d8f23d9fb3a0efba8d41768520d62d0e8
129
+ )
130
+ }),
131
+ s1: Honk.G1Point({
132
+ x: uint256(
133
+ 0x1b300dbb752984d39a06a3278fc9048a525d0fdf14ef98f17ffb42a971fb9032
134
+ ),
135
+ y: uint256(
136
+ 0x01ccd716ea4eeba47b57e3110f305af0d1e2feec11f2656816dbb234ea0b3b1b
137
+ )
138
+ }),
139
+ s2: Honk.G1Point({
140
+ x: uint256(
141
+ 0x0d2e187f65cf5ab43eac061f54e93bdcc292b2f518ee632b030ea3290143139c
142
+ ),
143
+ y: uint256(
144
+ 0x03ff9967978b924f43af1e71f6281ee36a96c1b647bbf8c17e3cb4626068b78b
145
+ )
146
+ }),
147
+ s3: Honk.G1Point({
148
+ x: uint256(
149
+ 0x2106e82e5e59b21be7c8ac07ede04efc6445f01e31b5ce7894444cb081df43d1
150
+ ),
151
+ y: uint256(
152
+ 0x0571641ab150cfa4371421f984cc897945b69ca100d0960c2ee5ca1d17cd9670
153
+ )
154
+ }),
155
+ s4: Honk.G1Point({
156
+ x: uint256(
157
+ 0x27599a711decc65fa4aad9515655e029868cc54d495fb8b53fa44e165702a5ee
158
+ ),
159
+ y: uint256(
160
+ 0x1d9db80b8419761979511454f69fa448fc50d15062e434c6994c4ccc4912f672
161
+ )
162
+ }),
163
+ t1: Honk.G1Point({
164
+ x: uint256(
165
+ 0x099e3bd5a0a00ab7fe18040105b9b395b5d8b7b4a63b05df652b0d10ef146d26
166
+ ),
167
+ y: uint256(
168
+ 0x0015b8d2515d76e2ccec99dcd194592129af3a637f5a622a32440f860d1e2a7f
169
+ )
170
+ }),
171
+ t2: Honk.G1Point({
172
+ x: uint256(
173
+ 0x1b917517920bad3d8bc01c9595092a222b888108dc25d1aa450e0b4bc212c37e
174
+ ),
175
+ y: uint256(
176
+ 0x305e8992b148eedb22e6e992077a84482141c7ebe42000a1d58ccb74381f6d19
177
+ )
178
+ }),
179
+ t3: Honk.G1Point({
180
+ x: uint256(
181
+ 0x13567e3b915c81013ada15236ba5cfa60111b440400b2bca37e2b1085e924a77
182
+ ),
183
+ y: uint256(
184
+ 0x0148d22589b91f0d8f4674af5744dedafd63caea904b434e748f9713de8cc3d7
185
+ )
186
+ }),
187
+ t4: Honk.G1Point({
188
+ x: uint256(
189
+ 0x043d063b130adfb37342af45d0155a28edd1a7e46c840d9c943fdf45521c64ce
190
+ ),
191
+ y: uint256(
192
+ 0x261522c4089330646aff96736194949330952ae74c573d1686d9cb4a00733854
193
+ )
194
+ }),
195
+ id1: Honk.G1Point({
196
+ x: uint256(
197
+ 0x1fa05f284bf1410f37f0d556ccfeb052395ec8625620cf724d146a3b15496d4d
198
+ ),
199
+ y: uint256(
200
+ 0x0c8fc17b9b81b4f93a7b9bdd1cc5f01a30ef6e808409c456f6d6d13fe7d2eb17
201
+ )
202
+ }),
203
+ id2: Honk.G1Point({
204
+ x: uint256(
205
+ 0x05798d2cd96b3294d8cc2f0120fa58ffea3a662e32039784f0b0b051e34e8718
206
+ ),
207
+ y: uint256(
208
+ 0x02d377efbb702de6d6a38e5c42c6aaf56cc11762d724a635ea4d5dc72eb9e0ca
209
+ )
210
+ }),
211
+ id3: Honk.G1Point({
212
+ x: uint256(
213
+ 0x110bd6ab5007b97692cd6e8ea8cab85d8b039d9e8dc2a9931fa6dcd72e0adac8
214
+ ),
215
+ y: uint256(
216
+ 0x2e418397e17371fcf5a1a5c614f4dfe9727b79d5aa127ab98c04a7a4c06ccb9f
217
+ )
218
+ }),
219
+ id4: Honk.G1Point({
220
+ x: uint256(
221
+ 0x0ccf438e4b27c76e599cda77ba04ad29cbaf538ded427e979eef69a5a9884b78
222
+ ),
223
+ y: uint256(
224
+ 0x09117b0cb34fc65ed20f92de70c6f8e073c755fb4acf2d74f402c6a97ee3d01a
225
+ )
226
+ }),
227
+ lagrangeFirst: Honk.G1Point({
228
+ x: uint256(
229
+ 0x0000000000000000000000000000000000000000000000000000000000000001
230
+ ),
231
+ y: uint256(
232
+ 0x0000000000000000000000000000000000000000000000000000000000000002
233
+ )
234
+ }),
235
+ lagrangeLast: Honk.G1Point({
236
+ x: uint256(
237
+ 0x22671e023cbbeb82d51b48eb911951a7a1f9c2bb913f3f42a56f272e205d4624
238
+ ),
239
+ y: uint256(
240
+ 0x139bdfe9fe99633e5abe888702fa64a75c80d62184d0a16bd999840553954bb1
241
+ )
242
+ })
243
+ });
244
+ return vk;
245
+ }
246
+ }
247
+
248
+ pragma solidity ^0.8.27;
249
+
250
+ interface IVerifier {
251
+ function verify(
252
+ bytes calldata _proof,
253
+ bytes32[] calldata _publicInputs
254
+ ) external returns (bool);
255
+ }
256
+
257
+ type Fr is uint256;
258
+
259
+ using { add as + } for Fr global;
260
+ using { sub as - } for Fr global;
261
+ using { mul as * } for Fr global;
262
+
263
+ using { exp as ^ } for Fr global;
264
+ using { notEqual as != } for Fr global;
265
+ using { equal as == } for Fr global;
266
+
267
+ uint256 constant SUBGROUP_SIZE = 256;
268
+ uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order
269
+ uint256 constant P = MODULUS;
270
+ Fr constant SUBGROUP_GENERATOR = Fr.wrap(
271
+ 0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76
272
+ );
273
+ Fr constant SUBGROUP_GENERATOR_INVERSE = Fr.wrap(
274
+ 0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6
275
+ );
276
+ Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1);
277
+ Fr constant ONE = Fr.wrap(1);
278
+ Fr constant ZERO = Fr.wrap(0);
279
+ // Instantiation
280
+
281
+ library FrLib {
282
+ function from(uint256 value) internal pure returns (Fr) {
283
+ unchecked {
284
+ return Fr.wrap(value % MODULUS);
285
+ }
286
+ }
287
+
288
+ function fromBytes32(bytes32 value) internal pure returns (Fr) {
289
+ unchecked {
290
+ return Fr.wrap(uint256(value) % MODULUS);
291
+ }
292
+ }
293
+
294
+ function toBytes32(Fr value) internal pure returns (bytes32) {
295
+ unchecked {
296
+ return bytes32(Fr.unwrap(value));
297
+ }
298
+ }
299
+
300
+ function invert(Fr value) internal view returns (Fr) {
301
+ uint256 v = Fr.unwrap(value);
302
+ uint256 result;
303
+
304
+ // Call the modexp precompile to invert in the field
305
+ assembly {
306
+ let free := mload(0x40)
307
+ mstore(free, 0x20)
308
+ mstore(add(free, 0x20), 0x20)
309
+ mstore(add(free, 0x40), 0x20)
310
+ mstore(add(free, 0x60), v)
311
+ mstore(add(free, 0x80), sub(MODULUS, 2))
312
+ mstore(add(free, 0xa0), MODULUS)
313
+ let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20)
314
+ if iszero(success) {
315
+ revert(0, 0)
316
+ }
317
+ result := mload(0x00)
318
+ mstore(0x40, add(free, 0x80))
319
+ }
320
+
321
+ return Fr.wrap(result);
322
+ }
323
+
324
+ function pow(Fr base, uint256 v) internal view returns (Fr) {
325
+ uint256 b = Fr.unwrap(base);
326
+ uint256 result;
327
+
328
+ // Call the modexp precompile to invert in the field
329
+ assembly {
330
+ let free := mload(0x40)
331
+ mstore(free, 0x20)
332
+ mstore(add(free, 0x20), 0x20)
333
+ mstore(add(free, 0x40), 0x20)
334
+ mstore(add(free, 0x60), b)
335
+ mstore(add(free, 0x80), v)
336
+ mstore(add(free, 0xa0), MODULUS)
337
+ let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20)
338
+ if iszero(success) {
339
+ revert(0, 0)
340
+ }
341
+ result := mload(0x00)
342
+ mstore(0x40, add(free, 0x80))
343
+ }
344
+
345
+ return Fr.wrap(result);
346
+ }
347
+
348
+ function div(Fr numerator, Fr denominator) internal view returns (Fr) {
349
+ unchecked {
350
+ return numerator * invert(denominator);
351
+ }
352
+ }
353
+
354
+ function sqr(Fr value) internal pure returns (Fr) {
355
+ unchecked {
356
+ return value * value;
357
+ }
358
+ }
359
+
360
+ function unwrap(Fr value) internal pure returns (uint256) {
361
+ unchecked {
362
+ return Fr.unwrap(value);
363
+ }
364
+ }
365
+
366
+ function neg(Fr value) internal pure returns (Fr) {
367
+ unchecked {
368
+ return Fr.wrap(MODULUS - Fr.unwrap(value));
369
+ }
370
+ }
371
+ }
372
+
373
+ // Free functions
374
+ function add(Fr a, Fr b) pure returns (Fr) {
375
+ unchecked {
376
+ return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS));
377
+ }
378
+ }
379
+
380
+ function mul(Fr a, Fr b) pure returns (Fr) {
381
+ unchecked {
382
+ return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS));
383
+ }
384
+ }
385
+
386
+ function sub(Fr a, Fr b) pure returns (Fr) {
387
+ unchecked {
388
+ return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS));
389
+ }
390
+ }
391
+
392
+ function exp(Fr base, Fr exponent) pure returns (Fr) {
393
+ if (Fr.unwrap(exponent) == 0) return Fr.wrap(1);
394
+ // Implement exponent with a loop as we will overflow otherwise
395
+ for (uint256 i = 1; i < Fr.unwrap(exponent); i += i) {
396
+ base = base * base;
397
+ }
398
+ return base;
399
+ }
400
+
401
+ function notEqual(Fr a, Fr b) pure returns (bool) {
402
+ unchecked {
403
+ return Fr.unwrap(a) != Fr.unwrap(b);
404
+ }
405
+ }
406
+
407
+ function equal(Fr a, Fr b) pure returns (bool) {
408
+ unchecked {
409
+ return Fr.unwrap(a) == Fr.unwrap(b);
410
+ }
411
+ }
412
+
413
+ uint256 constant CONST_PROOF_SIZE_LOG_N = 28;
414
+
415
+ uint256 constant NUMBER_OF_SUBRELATIONS = 28;
416
+ uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8;
417
+ uint256 constant ZK_BATCHED_RELATION_PARTIAL_LENGTH = 9;
418
+ uint256 constant NUMBER_OF_ENTITIES = 41;
419
+ uint256 constant NUMBER_UNSHIFTED = 36;
420
+ uint256 constant NUMBER_TO_BE_SHIFTED = 5;
421
+ uint256 constant PAIRING_POINTS_SIZE = 16;
422
+
423
+ uint256 constant FIELD_ELEMENT_SIZE = 0x20;
424
+ uint256 constant GROUP_ELEMENT_SIZE = 0x40;
425
+
426
+ // Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1
427
+ uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1;
428
+
429
+ // ENUM FOR WIRES
430
+ enum WIRE {
431
+ Q_M,
432
+ Q_C,
433
+ Q_L,
434
+ Q_R,
435
+ Q_O,
436
+ Q_4,
437
+ Q_LOOKUP,
438
+ Q_ARITH,
439
+ Q_RANGE,
440
+ Q_ELLIPTIC,
441
+ Q_MEMORY,
442
+ Q_NNF,
443
+ Q_POSEIDON2_EXTERNAL,
444
+ Q_POSEIDON2_INTERNAL,
445
+ SIGMA_1,
446
+ SIGMA_2,
447
+ SIGMA_3,
448
+ SIGMA_4,
449
+ ID_1,
450
+ ID_2,
451
+ ID_3,
452
+ ID_4,
453
+ TABLE_1,
454
+ TABLE_2,
455
+ TABLE_3,
456
+ TABLE_4,
457
+ LAGRANGE_FIRST,
458
+ LAGRANGE_LAST,
459
+ W_L,
460
+ W_R,
461
+ W_O,
462
+ W_4,
463
+ Z_PERM,
464
+ LOOKUP_INVERSES,
465
+ LOOKUP_READ_COUNTS,
466
+ LOOKUP_READ_TAGS,
467
+ W_L_SHIFT,
468
+ W_R_SHIFT,
469
+ W_O_SHIFT,
470
+ W_4_SHIFT,
471
+ Z_PERM_SHIFT
472
+ }
473
+
474
+ library Honk {
475
+ struct G1Point {
476
+ uint256 x;
477
+ uint256 y;
478
+ }
479
+
480
+ struct VerificationKey {
481
+ // Misc Params
482
+ uint256 circuitSize;
483
+ uint256 logCircuitSize;
484
+ uint256 publicInputsSize;
485
+ // Selectors
486
+ G1Point qm;
487
+ G1Point qc;
488
+ G1Point ql;
489
+ G1Point qr;
490
+ G1Point qo;
491
+ G1Point q4;
492
+ G1Point qLookup; // Lookup
493
+ G1Point qArith; // Arithmetic widget
494
+ G1Point qDeltaRange; // Delta Range sort
495
+ G1Point qMemory; // Memory
496
+ G1Point qNnf; // Non-native Field
497
+ G1Point qElliptic; // Auxillary
498
+ G1Point qPoseidon2External;
499
+ G1Point qPoseidon2Internal;
500
+ // Copy cnstraints
501
+ G1Point s1;
502
+ G1Point s2;
503
+ G1Point s3;
504
+ G1Point s4;
505
+ // Copy identity
506
+ G1Point id1;
507
+ G1Point id2;
508
+ G1Point id3;
509
+ G1Point id4;
510
+ // Precomputed lookup table
511
+ G1Point t1;
512
+ G1Point t2;
513
+ G1Point t3;
514
+ G1Point t4;
515
+ // Fixed first and last
516
+ G1Point lagrangeFirst;
517
+ G1Point lagrangeLast;
518
+ }
519
+
520
+ struct RelationParameters {
521
+ // challenges
522
+ Fr eta;
523
+ Fr etaTwo;
524
+ Fr etaThree;
525
+ Fr beta;
526
+ Fr gamma;
527
+ // derived
528
+ Fr publicInputsDelta;
529
+ }
530
+
531
+ struct Proof {
532
+ // Pairing point object
533
+ Fr[PAIRING_POINTS_SIZE] pairingPointObject;
534
+ // Free wires
535
+ G1Point w1;
536
+ G1Point w2;
537
+ G1Point w3;
538
+ G1Point w4;
539
+ // Lookup helpers - Permutations
540
+ G1Point zPerm;
541
+ // Lookup helpers - logup
542
+ G1Point lookupReadCounts;
543
+ G1Point lookupReadTags;
544
+ G1Point lookupInverses;
545
+ // Sumcheck
546
+ Fr[BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates;
547
+ Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations;
548
+ // Shplemini
549
+ G1Point[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms;
550
+ Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations;
551
+ G1Point shplonkQ;
552
+ G1Point kzgQuotient;
553
+ }
554
+
555
+ struct ZKProof {
556
+ // Pairing point object
557
+ Fr[PAIRING_POINTS_SIZE] pairingPointObject;
558
+ // Commitments to wire polynomials
559
+ G1Point w1;
560
+ G1Point w2;
561
+ G1Point w3;
562
+ G1Point w4;
563
+ // Commitments to logup witness polynomials
564
+ G1Point lookupReadCounts;
565
+ G1Point lookupReadTags;
566
+ G1Point lookupInverses;
567
+ // Commitment to grand permutation polynomial
568
+ G1Point zPerm;
569
+ G1Point[3] libraCommitments;
570
+ // Sumcheck
571
+ Fr libraSum;
572
+ Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates;
573
+ Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations;
574
+ Fr libraEvaluation;
575
+ // ZK
576
+ G1Point geminiMaskingPoly;
577
+ Fr geminiMaskingEval;
578
+ // Shplemini
579
+ G1Point[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms;
580
+ Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations;
581
+ Fr[4] libraPolyEvals;
582
+ G1Point shplonkQ;
583
+ G1Point kzgQuotient;
584
+ }
585
+ }
586
+
587
+ // ZKTranscript library to generate fiat shamir challenges, the ZK transcript only differest
588
+ struct ZKTranscript {
589
+ // Oink
590
+ Honk.RelationParameters relationParameters;
591
+ Fr[NUMBER_OF_ALPHAS] alphas;
592
+ Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges;
593
+ // Sumcheck
594
+ Fr libraChallenge;
595
+ Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges;
596
+ // Shplemini
597
+ Fr rho;
598
+ Fr geminiR;
599
+ Fr shplonkNu;
600
+ Fr shplonkZ;
601
+ // Derived
602
+ Fr publicInputsDelta;
603
+ }
604
+
605
+ library ZKTranscriptLib {
606
+ function generateTranscript(
607
+ Honk.ZKProof memory proof,
608
+ bytes32[] calldata publicInputs,
609
+ uint256 vkHash,
610
+ uint256 publicInputsSize,
611
+ uint256 logN
612
+ ) external pure returns (ZKTranscript memory t) {
613
+ Fr previousChallenge;
614
+ (
615
+ t.relationParameters,
616
+ previousChallenge
617
+ ) = generateRelationParametersChallenges(
618
+ proof,
619
+ publicInputs,
620
+ vkHash,
621
+ publicInputsSize,
622
+ previousChallenge
623
+ );
624
+
625
+ (t.alphas, previousChallenge) = generateAlphaChallenges(
626
+ previousChallenge,
627
+ proof
628
+ );
629
+
630
+ (t.gateChallenges, previousChallenge) = generateGateChallenges(
631
+ previousChallenge,
632
+ logN
633
+ );
634
+ (t.libraChallenge, previousChallenge) = generateLibraChallenge(
635
+ previousChallenge,
636
+ proof
637
+ );
638
+ (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(
639
+ proof,
640
+ previousChallenge,
641
+ logN
642
+ );
643
+
644
+ (t.rho, previousChallenge) = generateRhoChallenge(
645
+ proof,
646
+ previousChallenge
647
+ );
648
+
649
+ (t.geminiR, previousChallenge) = generateGeminiRChallenge(
650
+ proof,
651
+ previousChallenge,
652
+ logN
653
+ );
654
+
655
+ (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(
656
+ proof,
657
+ previousChallenge,
658
+ logN
659
+ );
660
+
661
+ (t.shplonkZ, previousChallenge) = generateShplonkZChallenge(
662
+ proof,
663
+ previousChallenge
664
+ );
665
+ return t;
666
+ }
667
+
668
+ function splitChallenge(
669
+ Fr challenge
670
+ ) internal pure returns (Fr first, Fr second) {
671
+ uint256 challengeU256 = uint256(Fr.unwrap(challenge));
672
+ uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
673
+ uint256 hi = challengeU256 >> 128;
674
+ first = FrLib.fromBytes32(bytes32(lo));
675
+ second = FrLib.fromBytes32(bytes32(hi));
676
+ }
677
+
678
+ function generateRelationParametersChallenges(
679
+ Honk.ZKProof memory proof,
680
+ bytes32[] calldata publicInputs,
681
+ uint256 vkHash,
682
+ uint256 publicInputsSize,
683
+ Fr previousChallenge
684
+ )
685
+ internal
686
+ pure
687
+ returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge)
688
+ {
689
+ (
690
+ rp.eta,
691
+ rp.etaTwo,
692
+ rp.etaThree,
693
+ previousChallenge
694
+ ) = generateEtaChallenge(proof, publicInputs, vkHash, publicInputsSize);
695
+
696
+ (
697
+ rp.beta,
698
+ rp.gamma,
699
+ nextPreviousChallenge
700
+ ) = generateBetaAndGammaChallenges(previousChallenge, proof);
701
+ }
702
+
703
+ function generateEtaChallenge(
704
+ Honk.ZKProof memory proof,
705
+ bytes32[] calldata publicInputs,
706
+ uint256 vkHash,
707
+ uint256 publicInputsSize
708
+ )
709
+ internal
710
+ pure
711
+ returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge)
712
+ {
713
+ bytes32[] memory round0 = new bytes32[](1 + publicInputsSize + 6);
714
+ round0[0] = bytes32(vkHash);
715
+
716
+ for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) {
717
+ round0[1 + i] = bytes32(publicInputs[i]);
718
+ }
719
+ for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
720
+ round0[1 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib
721
+ .toBytes32(proof.pairingPointObject[i]);
722
+ }
723
+
724
+ // Create the first challenge
725
+ // Note: w4 is added to the challenge later on
726
+ round0[1 + publicInputsSize] = bytes32(proof.w1.x);
727
+ round0[1 + publicInputsSize + 1] = bytes32(proof.w1.y);
728
+ round0[1 + publicInputsSize + 2] = bytes32(proof.w2.x);
729
+ round0[1 + publicInputsSize + 3] = bytes32(proof.w2.y);
730
+ round0[1 + publicInputsSize + 4] = bytes32(proof.w3.x);
731
+ round0[1 + publicInputsSize + 5] = bytes32(proof.w3.y);
732
+
733
+ previousChallenge = FrLib.fromBytes32(
734
+ keccak256(abi.encodePacked(round0))
735
+ );
736
+ (eta, etaTwo) = splitChallenge(previousChallenge);
737
+ previousChallenge = FrLib.fromBytes32(
738
+ keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))
739
+ );
740
+
741
+ (etaThree, ) = splitChallenge(previousChallenge);
742
+ }
743
+
744
+ function generateBetaAndGammaChallenges(
745
+ Fr previousChallenge,
746
+ Honk.ZKProof memory proof
747
+ ) internal pure returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) {
748
+ bytes32[7] memory round1;
749
+ round1[0] = FrLib.toBytes32(previousChallenge);
750
+ round1[1] = bytes32(proof.lookupReadCounts.x);
751
+ round1[2] = bytes32(proof.lookupReadCounts.y);
752
+ round1[3] = bytes32(proof.lookupReadTags.x);
753
+ round1[4] = bytes32(proof.lookupReadTags.y);
754
+ round1[5] = bytes32(proof.w4.x);
755
+ round1[6] = bytes32(proof.w4.y);
756
+
757
+ nextPreviousChallenge = FrLib.fromBytes32(
758
+ keccak256(abi.encodePacked(round1))
759
+ );
760
+ (beta, gamma) = splitChallenge(nextPreviousChallenge);
761
+ }
762
+
763
+ // Alpha challenges non-linearise the gate contributions
764
+ function generateAlphaChallenges(
765
+ Fr previousChallenge,
766
+ Honk.ZKProof memory proof
767
+ )
768
+ internal
769
+ pure
770
+ returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge)
771
+ {
772
+ // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup
773
+ uint256[5] memory alpha0;
774
+ alpha0[0] = Fr.unwrap(previousChallenge);
775
+ alpha0[1] = proof.lookupInverses.x;
776
+ alpha0[2] = proof.lookupInverses.y;
777
+ alpha0[3] = proof.zPerm.x;
778
+ alpha0[4] = proof.zPerm.y;
779
+
780
+ nextPreviousChallenge = FrLib.fromBytes32(
781
+ keccak256(abi.encodePacked(alpha0))
782
+ );
783
+ Fr alpha;
784
+ (alpha, ) = splitChallenge(nextPreviousChallenge);
785
+
786
+ // Compute powers of alpha for batching subrelations
787
+ alphas[0] = alpha;
788
+ for (uint256 i = 1; i < NUMBER_OF_ALPHAS; i++) {
789
+ alphas[i] = alphas[i - 1] * alpha;
790
+ }
791
+ }
792
+
793
+ function generateGateChallenges(
794
+ Fr previousChallenge,
795
+ uint256 logN
796
+ )
797
+ internal
798
+ pure
799
+ returns (
800
+ Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges,
801
+ Fr nextPreviousChallenge
802
+ )
803
+ {
804
+ previousChallenge = FrLib.fromBytes32(
805
+ keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))
806
+ );
807
+ (gateChallenges[0], ) = splitChallenge(previousChallenge);
808
+ for (uint256 i = 1; i < logN; i++) {
809
+ gateChallenges[i] = gateChallenges[i - 1] * gateChallenges[i - 1];
810
+ }
811
+ nextPreviousChallenge = previousChallenge;
812
+ }
813
+
814
+ function generateLibraChallenge(
815
+ Fr previousChallenge,
816
+ Honk.ZKProof memory proof
817
+ ) internal pure returns (Fr libraChallenge, Fr nextPreviousChallenge) {
818
+ // 2 comm, 1 sum, 1 challenge
819
+ uint256[4] memory challengeData;
820
+ challengeData[0] = Fr.unwrap(previousChallenge);
821
+ challengeData[1] = proof.libraCommitments[0].x;
822
+ challengeData[2] = proof.libraCommitments[0].y;
823
+ challengeData[3] = Fr.unwrap(proof.libraSum);
824
+ nextPreviousChallenge = FrLib.fromBytes32(
825
+ keccak256(abi.encodePacked(challengeData))
826
+ );
827
+ (libraChallenge, ) = splitChallenge(nextPreviousChallenge);
828
+ }
829
+
830
+ function generateSumcheckChallenges(
831
+ Honk.ZKProof memory proof,
832
+ Fr prevChallenge,
833
+ uint256 logN
834
+ )
835
+ internal
836
+ pure
837
+ returns (
838
+ Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges,
839
+ Fr nextPreviousChallenge
840
+ )
841
+ {
842
+ for (uint256 i = 0; i < logN; i++) {
843
+ Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal;
844
+ univariateChal[0] = prevChallenge;
845
+
846
+ for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) {
847
+ univariateChal[j + 1] = proof.sumcheckUnivariates[i][j];
848
+ }
849
+ prevChallenge = FrLib.fromBytes32(
850
+ keccak256(abi.encodePacked(univariateChal))
851
+ );
852
+
853
+ (sumcheckChallenges[i], ) = splitChallenge(prevChallenge);
854
+ }
855
+ nextPreviousChallenge = prevChallenge;
856
+ }
857
+
858
+ // We add Libra claimed eval + 3 comm + 1 more eval
859
+ function generateRhoChallenge(
860
+ Honk.ZKProof memory proof,
861
+ Fr prevChallenge
862
+ ) internal pure returns (Fr rho, Fr nextPreviousChallenge) {
863
+ uint256[NUMBER_OF_ENTITIES + 9] memory rhoChallengeElements;
864
+ rhoChallengeElements[0] = Fr.unwrap(prevChallenge);
865
+ uint256 i;
866
+ for (i = 1; i <= NUMBER_OF_ENTITIES; i++) {
867
+ rhoChallengeElements[i] = Fr.unwrap(
868
+ proof.sumcheckEvaluations[i - 1]
869
+ );
870
+ }
871
+ rhoChallengeElements[i] = Fr.unwrap(proof.libraEvaluation);
872
+
873
+ i += 1;
874
+ rhoChallengeElements[i] = proof.libraCommitments[1].x;
875
+ rhoChallengeElements[i + 1] = proof.libraCommitments[1].y;
876
+ i += 2;
877
+ rhoChallengeElements[i] = proof.libraCommitments[2].x;
878
+ rhoChallengeElements[i + 1] = proof.libraCommitments[2].y;
879
+ i += 2;
880
+ rhoChallengeElements[i] = proof.geminiMaskingPoly.x;
881
+ rhoChallengeElements[i + 1] = proof.geminiMaskingPoly.y;
882
+
883
+ i += 2;
884
+ rhoChallengeElements[i] = Fr.unwrap(proof.geminiMaskingEval);
885
+
886
+ nextPreviousChallenge = FrLib.fromBytes32(
887
+ keccak256(abi.encodePacked(rhoChallengeElements))
888
+ );
889
+ (rho, ) = splitChallenge(nextPreviousChallenge);
890
+ }
891
+
892
+ function generateGeminiRChallenge(
893
+ Honk.ZKProof memory proof,
894
+ Fr prevChallenge,
895
+ uint256 logN
896
+ ) internal pure returns (Fr geminiR, Fr nextPreviousChallenge) {
897
+ uint256[] memory gR = new uint256[]((logN - 1) * 2 + 1);
898
+ gR[0] = Fr.unwrap(prevChallenge);
899
+
900
+ for (uint256 i = 0; i < logN - 1; i++) {
901
+ gR[1 + i * 2] = proof.geminiFoldComms[i].x;
902
+ gR[2 + i * 2] = proof.geminiFoldComms[i].y;
903
+ }
904
+
905
+ nextPreviousChallenge = FrLib.fromBytes32(
906
+ keccak256(abi.encodePacked(gR))
907
+ );
908
+
909
+ (geminiR, ) = splitChallenge(nextPreviousChallenge);
910
+ }
911
+
912
+ function generateShplonkNuChallenge(
913
+ Honk.ZKProof memory proof,
914
+ Fr prevChallenge,
915
+ uint256 logN
916
+ ) internal pure returns (Fr shplonkNu, Fr nextPreviousChallenge) {
917
+ uint256[] memory shplonkNuChallengeElements = new uint256[](
918
+ logN + 1 + 4
919
+ );
920
+ shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge);
921
+
922
+ for (uint256 i = 1; i <= logN; i++) {
923
+ shplonkNuChallengeElements[i] = Fr.unwrap(
924
+ proof.geminiAEvaluations[i - 1]
925
+ );
926
+ }
927
+
928
+ uint256 libraIdx = 0;
929
+ for (uint256 i = logN + 1; i <= logN + 4; i++) {
930
+ shplonkNuChallengeElements[i] = Fr.unwrap(
931
+ proof.libraPolyEvals[libraIdx]
932
+ );
933
+ libraIdx++;
934
+ }
935
+
936
+ nextPreviousChallenge = FrLib.fromBytes32(
937
+ keccak256(abi.encodePacked(shplonkNuChallengeElements))
938
+ );
939
+ (shplonkNu, ) = splitChallenge(nextPreviousChallenge);
940
+ }
941
+
942
+ function generateShplonkZChallenge(
943
+ Honk.ZKProof memory proof,
944
+ Fr prevChallenge
945
+ ) internal pure returns (Fr shplonkZ, Fr nextPreviousChallenge) {
946
+ uint256[3] memory shplonkZChallengeElements;
947
+ shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge);
948
+
949
+ shplonkZChallengeElements[1] = proof.shplonkQ.x;
950
+ shplonkZChallengeElements[2] = proof.shplonkQ.y;
951
+
952
+ nextPreviousChallenge = FrLib.fromBytes32(
953
+ keccak256(abi.encodePacked(shplonkZChallengeElements))
954
+ );
955
+ (shplonkZ, ) = splitChallenge(nextPreviousChallenge);
956
+ }
957
+
958
+ function loadProof(
959
+ bytes calldata proof,
960
+ uint256 logN
961
+ ) internal pure returns (Honk.ZKProof memory p) {
962
+ uint256 boundary = 0x0;
963
+
964
+ // Pairing point object
965
+ for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
966
+ p.pairingPointObject[i] = bytesToFr(
967
+ proof[boundary:boundary + FIELD_ELEMENT_SIZE]
968
+ );
969
+ boundary += FIELD_ELEMENT_SIZE;
970
+ }
971
+ // Commitments
972
+ p.w1 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
973
+ boundary += GROUP_ELEMENT_SIZE;
974
+ p.w2 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
975
+ boundary += GROUP_ELEMENT_SIZE;
976
+ p.w3 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
977
+ boundary += GROUP_ELEMENT_SIZE;
978
+
979
+ // Lookup / Permutation Helper Commitments
980
+ p.lookupReadCounts = bytesToG1Point(
981
+ proof[boundary:boundary + GROUP_ELEMENT_SIZE]
982
+ );
983
+ boundary += GROUP_ELEMENT_SIZE;
984
+ p.lookupReadTags = bytesToG1Point(
985
+ proof[boundary:boundary + GROUP_ELEMENT_SIZE]
986
+ );
987
+ boundary += GROUP_ELEMENT_SIZE;
988
+ p.w4 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
989
+ boundary += GROUP_ELEMENT_SIZE;
990
+ p.lookupInverses = bytesToG1Point(
991
+ proof[boundary:boundary + GROUP_ELEMENT_SIZE]
992
+ );
993
+ boundary += GROUP_ELEMENT_SIZE;
994
+ p.zPerm = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
995
+ boundary += GROUP_ELEMENT_SIZE;
996
+ p.libraCommitments[0] = bytesToG1Point(
997
+ proof[boundary:boundary + GROUP_ELEMENT_SIZE]
998
+ );
999
+ boundary += GROUP_ELEMENT_SIZE;
1000
+
1001
+ p.libraSum = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
1002
+ boundary += FIELD_ELEMENT_SIZE;
1003
+ // Sumcheck univariates
1004
+ for (uint256 i = 0; i < logN; i++) {
1005
+ for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) {
1006
+ p.sumcheckUnivariates[i][j] = bytesToFr(
1007
+ proof[boundary:boundary + FIELD_ELEMENT_SIZE]
1008
+ );
1009
+ boundary += FIELD_ELEMENT_SIZE;
1010
+ }
1011
+ }
1012
+
1013
+ // Sumcheck evaluations
1014
+ for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) {
1015
+ p.sumcheckEvaluations[i] = bytesToFr(
1016
+ proof[boundary:boundary + FIELD_ELEMENT_SIZE]
1017
+ );
1018
+ boundary += FIELD_ELEMENT_SIZE;
1019
+ }
1020
+
1021
+ p.libraEvaluation = bytesToFr(
1022
+ proof[boundary:boundary + FIELD_ELEMENT_SIZE]
1023
+ );
1024
+ boundary += FIELD_ELEMENT_SIZE;
1025
+
1026
+ p.libraCommitments[1] = bytesToG1Point(
1027
+ proof[boundary:boundary + GROUP_ELEMENT_SIZE]
1028
+ );
1029
+ boundary += GROUP_ELEMENT_SIZE;
1030
+ p.libraCommitments[2] = bytesToG1Point(
1031
+ proof[boundary:boundary + GROUP_ELEMENT_SIZE]
1032
+ );
1033
+ boundary += GROUP_ELEMENT_SIZE;
1034
+ p.geminiMaskingPoly = bytesToG1Point(
1035
+ proof[boundary:boundary + GROUP_ELEMENT_SIZE]
1036
+ );
1037
+ boundary += GROUP_ELEMENT_SIZE;
1038
+ p.geminiMaskingEval = bytesToFr(
1039
+ proof[boundary:boundary + FIELD_ELEMENT_SIZE]
1040
+ );
1041
+ boundary += FIELD_ELEMENT_SIZE;
1042
+
1043
+ // Gemini
1044
+ // Read gemini fold univariates
1045
+ for (uint256 i = 0; i < logN - 1; i++) {
1046
+ p.geminiFoldComms[i] = bytesToG1Point(
1047
+ proof[boundary:boundary + GROUP_ELEMENT_SIZE]
1048
+ );
1049
+ boundary += GROUP_ELEMENT_SIZE;
1050
+ }
1051
+
1052
+ // Read gemini a evaluations
1053
+ for (uint256 i = 0; i < logN; i++) {
1054
+ p.geminiAEvaluations[i] = bytesToFr(
1055
+ proof[boundary:boundary + FIELD_ELEMENT_SIZE]
1056
+ );
1057
+ boundary += FIELD_ELEMENT_SIZE;
1058
+ }
1059
+
1060
+ for (uint256 i = 0; i < 4; i++) {
1061
+ p.libraPolyEvals[i] = bytesToFr(
1062
+ proof[boundary:boundary + FIELD_ELEMENT_SIZE]
1063
+ );
1064
+ boundary += FIELD_ELEMENT_SIZE;
1065
+ }
1066
+
1067
+ // Shplonk
1068
+ p.shplonkQ = bytesToG1Point(
1069
+ proof[boundary:boundary + GROUP_ELEMENT_SIZE]
1070
+ );
1071
+ boundary += GROUP_ELEMENT_SIZE;
1072
+ // KZG
1073
+ p.kzgQuotient = bytesToG1Point(
1074
+ proof[boundary:boundary + GROUP_ELEMENT_SIZE]
1075
+ );
1076
+ }
1077
+ }
1078
+
1079
+ // Field arithmetic libraries
1080
+
1081
+ library RelationsLib {
1082
+ Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17)
1083
+
1084
+ function accumulateRelationEvaluations(
1085
+ Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations,
1086
+ Honk.RelationParameters memory rp,
1087
+ Fr[NUMBER_OF_ALPHAS] memory alphas,
1088
+ Fr powPartialEval
1089
+ ) internal pure returns (Fr accumulator) {
1090
+ Fr[NUMBER_OF_SUBRELATIONS] memory evaluations;
1091
+
1092
+ // Accumulate all relations in Ultra Honk - each with varying number of subrelations
1093
+ accumulateArithmeticRelation(
1094
+ purportedEvaluations,
1095
+ evaluations,
1096
+ powPartialEval
1097
+ );
1098
+ accumulatePermutationRelation(
1099
+ purportedEvaluations,
1100
+ rp,
1101
+ evaluations,
1102
+ powPartialEval
1103
+ );
1104
+ accumulateLogDerivativeLookupRelation(
1105
+ purportedEvaluations,
1106
+ rp,
1107
+ evaluations,
1108
+ powPartialEval
1109
+ );
1110
+ accumulateDeltaRangeRelation(
1111
+ purportedEvaluations,
1112
+ evaluations,
1113
+ powPartialEval
1114
+ );
1115
+ accumulateEllipticRelation(
1116
+ purportedEvaluations,
1117
+ evaluations,
1118
+ powPartialEval
1119
+ );
1120
+ accumulateMemoryRelation(
1121
+ purportedEvaluations,
1122
+ rp,
1123
+ evaluations,
1124
+ powPartialEval
1125
+ );
1126
+ accumulateNnfRelation(
1127
+ purportedEvaluations,
1128
+ evaluations,
1129
+ powPartialEval
1130
+ );
1131
+ accumulatePoseidonExternalRelation(
1132
+ purportedEvaluations,
1133
+ evaluations,
1134
+ powPartialEval
1135
+ );
1136
+ accumulatePoseidonInternalRelation(
1137
+ purportedEvaluations,
1138
+ evaluations,
1139
+ powPartialEval
1140
+ );
1141
+
1142
+ // batch the subrelations with the alpha challenges to obtain the full honk relation
1143
+ accumulator = scaleAndBatchSubrelations(evaluations, alphas);
1144
+ }
1145
+
1146
+ /**
1147
+ * Aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids
1148
+ * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code
1149
+ * editors, and thus is noisy.
1150
+ */
1151
+ function wire(
1152
+ Fr[NUMBER_OF_ENTITIES] memory p,
1153
+ WIRE _wire
1154
+ ) internal pure returns (Fr) {
1155
+ return p[uint256(_wire)];
1156
+ }
1157
+
1158
+ uint256 internal constant NEG_HALF_MODULO_P =
1159
+ 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000;
1160
+ /**
1161
+ * Ultra Arithmetic Relation
1162
+ *
1163
+ */
1164
+
1165
+ function accumulateArithmeticRelation(
1166
+ Fr[NUMBER_OF_ENTITIES] memory p,
1167
+ Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1168
+ Fr domainSep
1169
+ ) internal pure {
1170
+ // Relation 0
1171
+ Fr q_arith = wire(p, WIRE.Q_ARITH);
1172
+ {
1173
+ Fr neg_half = Fr.wrap(NEG_HALF_MODULO_P);
1174
+
1175
+ Fr accum = (q_arith - Fr.wrap(3)) *
1176
+ (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) *
1177
+ neg_half;
1178
+ accum =
1179
+ accum +
1180
+ (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) +
1181
+ (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) +
1182
+ (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) +
1183
+ (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) +
1184
+ wire(p, WIRE.Q_C);
1185
+ accum = accum + (q_arith - ONE) * wire(p, WIRE.W_4_SHIFT);
1186
+ accum = accum * q_arith;
1187
+ accum = accum * domainSep;
1188
+ evals[0] = accum;
1189
+ }
1190
+
1191
+ // Relation 1
1192
+ {
1193
+ Fr accum = wire(p, WIRE.W_L) +
1194
+ wire(p, WIRE.W_4) -
1195
+ wire(p, WIRE.W_L_SHIFT) +
1196
+ wire(p, WIRE.Q_M);
1197
+ accum = accum * (q_arith - Fr.wrap(2));
1198
+ accum = accum * (q_arith - ONE);
1199
+ accum = accum * q_arith;
1200
+ accum = accum * domainSep;
1201
+ evals[1] = accum;
1202
+ }
1203
+ }
1204
+
1205
+ function accumulatePermutationRelation(
1206
+ Fr[NUMBER_OF_ENTITIES] memory p,
1207
+ Honk.RelationParameters memory rp,
1208
+ Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1209
+ Fr domainSep
1210
+ ) internal pure {
1211
+ Fr grand_product_numerator;
1212
+ Fr grand_product_denominator;
1213
+
1214
+ {
1215
+ Fr num = wire(p, WIRE.W_L) +
1216
+ wire(p, WIRE.ID_1) *
1217
+ rp.beta +
1218
+ rp.gamma;
1219
+ num =
1220
+ num *
1221
+ (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * rp.beta + rp.gamma);
1222
+ num =
1223
+ num *
1224
+ (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * rp.beta + rp.gamma);
1225
+ num =
1226
+ num *
1227
+ (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * rp.beta + rp.gamma);
1228
+
1229
+ grand_product_numerator = num;
1230
+ }
1231
+ {
1232
+ Fr den = wire(p, WIRE.W_L) +
1233
+ wire(p, WIRE.SIGMA_1) *
1234
+ rp.beta +
1235
+ rp.gamma;
1236
+ den =
1237
+ den *
1238
+ (wire(p, WIRE.W_R) +
1239
+ wire(p, WIRE.SIGMA_2) *
1240
+ rp.beta +
1241
+ rp.gamma);
1242
+ den =
1243
+ den *
1244
+ (wire(p, WIRE.W_O) +
1245
+ wire(p, WIRE.SIGMA_3) *
1246
+ rp.beta +
1247
+ rp.gamma);
1248
+ den =
1249
+ den *
1250
+ (wire(p, WIRE.W_4) +
1251
+ wire(p, WIRE.SIGMA_4) *
1252
+ rp.beta +
1253
+ rp.gamma);
1254
+
1255
+ grand_product_denominator = den;
1256
+ }
1257
+
1258
+ // Contribution 2
1259
+ {
1260
+ Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) *
1261
+ grand_product_numerator;
1262
+
1263
+ acc =
1264
+ acc -
1265
+ ((wire(p, WIRE.Z_PERM_SHIFT) +
1266
+ (wire(p, WIRE.LAGRANGE_LAST) * rp.publicInputsDelta)) *
1267
+ grand_product_denominator);
1268
+ acc = acc * domainSep;
1269
+ evals[2] = acc;
1270
+ }
1271
+
1272
+ // Contribution 3
1273
+ {
1274
+ Fr acc = (wire(p, WIRE.LAGRANGE_LAST) *
1275
+ wire(p, WIRE.Z_PERM_SHIFT)) * domainSep;
1276
+ evals[3] = acc;
1277
+ }
1278
+ }
1279
+
1280
+ function accumulateLogDerivativeLookupRelation(
1281
+ Fr[NUMBER_OF_ENTITIES] memory p,
1282
+ Honk.RelationParameters memory rp,
1283
+ Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1284
+ Fr domainSep
1285
+ ) internal pure {
1286
+ Fr write_term;
1287
+ Fr read_term;
1288
+
1289
+ // Calculate the write term (the table accumulation)
1290
+ {
1291
+ write_term =
1292
+ wire(p, WIRE.TABLE_1) +
1293
+ rp.gamma +
1294
+ (wire(p, WIRE.TABLE_2) * rp.eta) +
1295
+ (wire(p, WIRE.TABLE_3) * rp.etaTwo) +
1296
+ (wire(p, WIRE.TABLE_4) * rp.etaThree);
1297
+ }
1298
+
1299
+ // Calculate the write term
1300
+ {
1301
+ Fr derived_entry_1 = wire(p, WIRE.W_L) +
1302
+ rp.gamma +
1303
+ (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT));
1304
+ Fr derived_entry_2 = wire(p, WIRE.W_R) +
1305
+ wire(p, WIRE.Q_M) *
1306
+ wire(p, WIRE.W_R_SHIFT);
1307
+ Fr derived_entry_3 = wire(p, WIRE.W_O) +
1308
+ wire(p, WIRE.Q_C) *
1309
+ wire(p, WIRE.W_O_SHIFT);
1310
+
1311
+ read_term =
1312
+ derived_entry_1 +
1313
+ (derived_entry_2 * rp.eta) +
1314
+ (derived_entry_3 * rp.etaTwo) +
1315
+ (wire(p, WIRE.Q_O) * rp.etaThree);
1316
+ }
1317
+
1318
+ Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term;
1319
+ Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term;
1320
+
1321
+ Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) +
1322
+ wire(p, WIRE.Q_LOOKUP) -
1323
+ (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP));
1324
+
1325
+ // Inverse calculated correctly relation
1326
+ Fr accumulatorNone = read_term *
1327
+ write_term *
1328
+ wire(p, WIRE.LOOKUP_INVERSES) -
1329
+ inverse_exists_xor;
1330
+ accumulatorNone = accumulatorNone * domainSep;
1331
+
1332
+ // Inverse
1333
+ Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) *
1334
+ read_inverse -
1335
+ wire(p, WIRE.LOOKUP_READ_COUNTS) *
1336
+ write_inverse;
1337
+
1338
+ Fr read_tag = wire(p, WIRE.LOOKUP_READ_TAGS);
1339
+
1340
+ Fr read_tag_boolean_relation = read_tag * read_tag - read_tag;
1341
+
1342
+ evals[4] = accumulatorNone;
1343
+ evals[5] = accumulatorOne;
1344
+ evals[6] = read_tag_boolean_relation * domainSep;
1345
+ }
1346
+
1347
+ function accumulateDeltaRangeRelation(
1348
+ Fr[NUMBER_OF_ENTITIES] memory p,
1349
+ Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1350
+ Fr domainSep
1351
+ ) internal pure {
1352
+ Fr minus_one = ZERO - ONE;
1353
+ Fr minus_two = ZERO - Fr.wrap(2);
1354
+ Fr minus_three = ZERO - Fr.wrap(3);
1355
+
1356
+ // Compute wire differences
1357
+ Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L);
1358
+ Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R);
1359
+ Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O);
1360
+ Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4);
1361
+
1362
+ // Contribution 6
1363
+ {
1364
+ Fr acc = delta_1;
1365
+ acc = acc * (delta_1 + minus_one);
1366
+ acc = acc * (delta_1 + minus_two);
1367
+ acc = acc * (delta_1 + minus_three);
1368
+ acc = acc * wire(p, WIRE.Q_RANGE);
1369
+ acc = acc * domainSep;
1370
+ evals[7] = acc;
1371
+ }
1372
+
1373
+ // Contribution 7
1374
+ {
1375
+ Fr acc = delta_2;
1376
+ acc = acc * (delta_2 + minus_one);
1377
+ acc = acc * (delta_2 + minus_two);
1378
+ acc = acc * (delta_2 + minus_three);
1379
+ acc = acc * wire(p, WIRE.Q_RANGE);
1380
+ acc = acc * domainSep;
1381
+ evals[8] = acc;
1382
+ }
1383
+
1384
+ // Contribution 8
1385
+ {
1386
+ Fr acc = delta_3;
1387
+ acc = acc * (delta_3 + minus_one);
1388
+ acc = acc * (delta_3 + minus_two);
1389
+ acc = acc * (delta_3 + minus_three);
1390
+ acc = acc * wire(p, WIRE.Q_RANGE);
1391
+ acc = acc * domainSep;
1392
+ evals[9] = acc;
1393
+ }
1394
+
1395
+ // Contribution 9
1396
+ {
1397
+ Fr acc = delta_4;
1398
+ acc = acc * (delta_4 + minus_one);
1399
+ acc = acc * (delta_4 + minus_two);
1400
+ acc = acc * (delta_4 + minus_three);
1401
+ acc = acc * wire(p, WIRE.Q_RANGE);
1402
+ acc = acc * domainSep;
1403
+ evals[10] = acc;
1404
+ }
1405
+ }
1406
+
1407
+ struct EllipticParams {
1408
+ // Points
1409
+ Fr x_1;
1410
+ Fr y_1;
1411
+ Fr x_2;
1412
+ Fr y_2;
1413
+ Fr y_3;
1414
+ Fr x_3;
1415
+ // push accumulators into memory
1416
+ Fr x_double_identity;
1417
+ }
1418
+
1419
+ function accumulateEllipticRelation(
1420
+ Fr[NUMBER_OF_ENTITIES] memory p,
1421
+ Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1422
+ Fr domainSep
1423
+ ) internal pure {
1424
+ EllipticParams memory ep;
1425
+ ep.x_1 = wire(p, WIRE.W_R);
1426
+ ep.y_1 = wire(p, WIRE.W_O);
1427
+
1428
+ ep.x_2 = wire(p, WIRE.W_L_SHIFT);
1429
+ ep.y_2 = wire(p, WIRE.W_4_SHIFT);
1430
+ ep.y_3 = wire(p, WIRE.W_O_SHIFT);
1431
+ ep.x_3 = wire(p, WIRE.W_R_SHIFT);
1432
+
1433
+ Fr q_sign = wire(p, WIRE.Q_L);
1434
+ Fr q_is_double = wire(p, WIRE.Q_M);
1435
+
1436
+ // Contribution 10 point addition, x-coordinate check
1437
+ // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0
1438
+ Fr x_diff = (ep.x_2 - ep.x_1);
1439
+ Fr y1_sqr = (ep.y_1 * ep.y_1);
1440
+ {
1441
+ // Move to top
1442
+ Fr partialEval = domainSep;
1443
+
1444
+ Fr y2_sqr = (ep.y_2 * ep.y_2);
1445
+ Fr y1y2 = ep.y_1 * ep.y_2 * q_sign;
1446
+ Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1);
1447
+ x_add_identity = x_add_identity * x_diff * x_diff;
1448
+ x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2;
1449
+
1450
+ evals[11] =
1451
+ x_add_identity *
1452
+ partialEval *
1453
+ wire(p, WIRE.Q_ELLIPTIC) *
1454
+ (ONE - q_is_double);
1455
+ }
1456
+
1457
+ // Contribution 11 point addition, x-coordinate check
1458
+ // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0
1459
+ {
1460
+ Fr y1_plus_y3 = ep.y_1 + ep.y_3;
1461
+ Fr y_diff = ep.y_2 * q_sign - ep.y_1;
1462
+ Fr y_add_identity = y1_plus_y3 *
1463
+ x_diff +
1464
+ (ep.x_3 - ep.x_1) *
1465
+ y_diff;
1466
+ evals[12] =
1467
+ y_add_identity *
1468
+ domainSep *
1469
+ wire(p, WIRE.Q_ELLIPTIC) *
1470
+ (ONE - q_is_double);
1471
+ }
1472
+
1473
+ // Contribution 10 point doubling, x-coordinate check
1474
+ // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0
1475
+ // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1
1476
+ {
1477
+ Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1;
1478
+ Fr y1_sqr_mul_4 = y1_sqr + y1_sqr;
1479
+ y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4;
1480
+ Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9);
1481
+
1482
+ // NOTE: pushed into memory (stack >:'( )
1483
+ ep.x_double_identity =
1484
+ (ep.x_3 + ep.x_1 + ep.x_1) *
1485
+ y1_sqr_mul_4 -
1486
+ x1_pow_4_mul_9;
1487
+
1488
+ Fr acc = ep.x_double_identity *
1489
+ domainSep *
1490
+ wire(p, WIRE.Q_ELLIPTIC) *
1491
+ q_is_double;
1492
+ evals[11] = evals[11] + acc;
1493
+ }
1494
+
1495
+ // Contribution 11 point doubling, y-coordinate check
1496
+ // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0
1497
+ {
1498
+ Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1;
1499
+ Fr y_double_identity = x1_sqr_mul_3 *
1500
+ (ep.x_1 - ep.x_3) -
1501
+ (ep.y_1 + ep.y_1) *
1502
+ (ep.y_1 + ep.y_3);
1503
+ evals[12] =
1504
+ evals[12] +
1505
+ y_double_identity *
1506
+ domainSep *
1507
+ wire(p, WIRE.Q_ELLIPTIC) *
1508
+ q_is_double;
1509
+ }
1510
+ }
1511
+
1512
+ // Parameters used within the Memory Relation
1513
+ // A struct is used to work around stack too deep. This relation has alot of variables
1514
+ struct MemParams {
1515
+ Fr memory_record_check;
1516
+ Fr partial_record_check;
1517
+ Fr next_gate_access_type;
1518
+ Fr record_delta;
1519
+ Fr index_delta;
1520
+ Fr adjacent_values_match_if_adjacent_indices_match;
1521
+ Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation;
1522
+ Fr access_check;
1523
+ Fr next_gate_access_type_is_boolean;
1524
+ Fr ROM_consistency_check_identity;
1525
+ Fr RAM_consistency_check_identity;
1526
+ Fr timestamp_delta;
1527
+ Fr RAM_timestamp_check_identity;
1528
+ Fr memory_identity;
1529
+ Fr index_is_monotonically_increasing;
1530
+ }
1531
+
1532
+ function accumulateMemoryRelation(
1533
+ Fr[NUMBER_OF_ENTITIES] memory p,
1534
+ Honk.RelationParameters memory rp,
1535
+ Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1536
+ Fr domainSep
1537
+ ) internal pure {
1538
+ MemParams memory ap;
1539
+
1540
+ /**
1541
+ * MEMORY
1542
+ *
1543
+ * A RAM memory record contains a tuple of the following fields:
1544
+ * * i: `index` of memory cell being accessed
1545
+ * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM)
1546
+ * * v: `value` of memory cell being accessed
1547
+ * * a: `access` type of record. read: 0 = read, 1 = write
1548
+ * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three
1549
+ *
1550
+ * A ROM memory record contains a tuple of the following fields:
1551
+ * * i: `index` of memory cell being accessed
1552
+ * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index)
1553
+ * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index)
1554
+ * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three
1555
+ *
1556
+ * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires +
1557
+ * selectors, depending on whether the gate is a RAM read/write or a ROM read
1558
+ *
1559
+ * | gate type | i | v2/t | v | a | r |
1560
+ * | --------- | -- | ----- | -- | -- | -- |
1561
+ * | ROM | w1 | w2 | w3 | -- | w4 |
1562
+ * | RAM | w1 | w2 | w3 | qc | w4 |
1563
+ *
1564
+ * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on
1565
+ * `w2` to fix its value)
1566
+ *
1567
+ *
1568
+ */
1569
+
1570
+ /**
1571
+ * Memory Record Check
1572
+ * Partial degree: 1
1573
+ * Total degree: 4
1574
+ *
1575
+ * A ROM/ROM access gate can be evaluated with the identity:
1576
+ *
1577
+ * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0
1578
+ *
1579
+ * For ROM gates, qc = 0
1580
+ */
1581
+ ap.memory_record_check = wire(p, WIRE.W_O) * rp.etaThree;
1582
+ ap.memory_record_check =
1583
+ ap.memory_record_check +
1584
+ (wire(p, WIRE.W_R) * rp.etaTwo);
1585
+ ap.memory_record_check =
1586
+ ap.memory_record_check +
1587
+ (wire(p, WIRE.W_L) * rp.eta);
1588
+ ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C);
1589
+ ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4
1590
+ ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4);
1591
+
1592
+ /**
1593
+ * Contribution 13 & 14
1594
+ * ROM Consistency Check
1595
+ * Partial degree: 1
1596
+ * Total degree: 4
1597
+ *
1598
+ * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of
1599
+ * records that are sorted.
1600
+ *
1601
+ * We apply the following checks for the sorted records:
1602
+ *
1603
+ * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4
1604
+ * 2. index values for adjacent records are monotonically increasing
1605
+ * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1}
1606
+ *
1607
+ */
1608
+ ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L);
1609
+ ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4);
1610
+
1611
+ ap.index_is_monotonically_increasing =
1612
+ ap.index_delta *
1613
+ (ap.index_delta - Fr.wrap(1)); // deg 2
1614
+
1615
+ ap.adjacent_values_match_if_adjacent_indices_match =
1616
+ (ap.index_delta * MINUS_ONE + ONE) *
1617
+ ap.record_delta; // deg 2
1618
+
1619
+ evals[14] =
1620
+ ap.adjacent_values_match_if_adjacent_indices_match *
1621
+ (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) *
1622
+ (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5
1623
+ evals[15] =
1624
+ ap.index_is_monotonically_increasing *
1625
+ (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) *
1626
+ (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5
1627
+
1628
+ ap.ROM_consistency_check_identity =
1629
+ ap.memory_record_check *
1630
+ (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7
1631
+
1632
+ /**
1633
+ * Contributions 15,16,17
1634
+ * RAM Consistency Check
1635
+ *
1636
+ * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check`
1637
+ * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`.
1638
+ * This is validated by requiring `access` to be boolean
1639
+ *
1640
+ * For two adjacent entries in the sorted list if _both_
1641
+ * A) index values match
1642
+ * B) adjacent access value is 0 (i.e. next gate is a READ)
1643
+ * then
1644
+ * C) both values must match.
1645
+ * The gate boolean check is
1646
+ * (A && B) => C === !(A && B) || C === !A || !B || C
1647
+ *
1648
+ * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized
1649
+ * with a WRITE operation.
1650
+ */
1651
+ Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4
1652
+ ap.access_check = access_type * (access_type - Fr.wrap(1)); // check value is 0 or 1; deg 2 or 8
1653
+
1654
+ // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta
1655
+ // deg 1 or 4
1656
+ ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * rp.etaThree;
1657
+ ap.next_gate_access_type =
1658
+ ap.next_gate_access_type +
1659
+ (wire(p, WIRE.W_R_SHIFT) * rp.etaTwo);
1660
+ ap.next_gate_access_type =
1661
+ ap.next_gate_access_type +
1662
+ (wire(p, WIRE.W_L_SHIFT) * rp.eta);
1663
+ ap.next_gate_access_type =
1664
+ wire(p, WIRE.W_4_SHIFT) -
1665
+ ap.next_gate_access_type;
1666
+
1667
+ Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O);
1668
+ ap
1669
+ .adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation =
1670
+ (ap.index_delta * MINUS_ONE + ONE) *
1671
+ value_delta *
1672
+ (ap.next_gate_access_type * MINUS_ONE + ONE); // deg 3 or 6
1673
+
1674
+ // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the
1675
+ // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't
1676
+ // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access
1677
+ // type is correct, to cover this edge case
1678
+ // deg 2 or 4
1679
+ ap.next_gate_access_type_is_boolean =
1680
+ ap.next_gate_access_type *
1681
+ ap.next_gate_access_type -
1682
+ ap.next_gate_access_type;
1683
+
1684
+ // Putting it all together...
1685
+ evals[16] =
1686
+ ap
1687
+ .adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation *
1688
+ (wire(p, WIRE.Q_O)) *
1689
+ (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 or 8
1690
+ evals[17] =
1691
+ ap.index_is_monotonically_increasing *
1692
+ (wire(p, WIRE.Q_O)) *
1693
+ (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4
1694
+ evals[18] =
1695
+ ap.next_gate_access_type_is_boolean *
1696
+ (wire(p, WIRE.Q_O)) *
1697
+ (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 6
1698
+
1699
+ ap.RAM_consistency_check_identity =
1700
+ ap.access_check *
1701
+ (wire(p, WIRE.Q_O)); // deg 3 or 9
1702
+
1703
+ /**
1704
+ * RAM Timestamp Consistency Check
1705
+ *
1706
+ * | w1 | w2 | w3 | w4 |
1707
+ * | index | timestamp | timestamp_check | -- |
1708
+ *
1709
+ * Let delta_index = index_{i + 1} - index_{i}
1710
+ *
1711
+ * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i
1712
+ * Else timestamp_check = 0
1713
+ */
1714
+ ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R);
1715
+ ap.RAM_timestamp_check_identity =
1716
+ (ap.index_delta * MINUS_ONE + ONE) *
1717
+ ap.timestamp_delta -
1718
+ wire(p, WIRE.W_O); // deg 3
1719
+
1720
+ /**
1721
+ * Complete Contribution 12
1722
+ * The complete RAM/ROM memory identity
1723
+ * Partial degree:
1724
+ */
1725
+ ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6
1726
+ ap.memory_identity =
1727
+ ap.memory_identity +
1728
+ ap.RAM_timestamp_check_identity *
1729
+ (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4
1730
+ ap.memory_identity =
1731
+ ap.memory_identity +
1732
+ ap.memory_record_check *
1733
+ (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6
1734
+ ap.memory_identity =
1735
+ ap.memory_identity +
1736
+ ap.RAM_consistency_check_identity; // deg 3 or 9
1737
+
1738
+ // (deg 3 or 9) + (deg 4) + (deg 3)
1739
+ ap.memory_identity =
1740
+ ap.memory_identity *
1741
+ (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 10
1742
+ evals[13] = ap.memory_identity;
1743
+ }
1744
+
1745
+ // Constants for the Non-native Field relation
1746
+ Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68);
1747
+ Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14);
1748
+
1749
+ // Parameters used within the Non-Native Field Relation
1750
+ // A struct is used to work around stack too deep. This relation has alot of variables
1751
+ struct NnfParams {
1752
+ Fr limb_subproduct;
1753
+ Fr non_native_field_gate_1;
1754
+ Fr non_native_field_gate_2;
1755
+ Fr non_native_field_gate_3;
1756
+ Fr limb_accumulator_1;
1757
+ Fr limb_accumulator_2;
1758
+ Fr nnf_identity;
1759
+ }
1760
+
1761
+ function accumulateNnfRelation(
1762
+ Fr[NUMBER_OF_ENTITIES] memory p,
1763
+ Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1764
+ Fr domainSep
1765
+ ) internal pure {
1766
+ NnfParams memory ap;
1767
+
1768
+ /**
1769
+ * Contribution 12
1770
+ * Non native field arithmetic gate 2
1771
+ * deg 4
1772
+ *
1773
+ * _ _
1774
+ * / _ _ _ 14 \
1775
+ * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 |
1776
+ * \_ _/
1777
+ *
1778
+ *
1779
+ */
1780
+ ap.limb_subproduct =
1781
+ wire(p, WIRE.W_L) *
1782
+ wire(p, WIRE.W_R_SHIFT) +
1783
+ wire(p, WIRE.W_L_SHIFT) *
1784
+ wire(p, WIRE.W_R);
1785
+ ap.non_native_field_gate_2 = (wire(p, WIRE.W_L) *
1786
+ wire(p, WIRE.W_4) +
1787
+ wire(p, WIRE.W_R) *
1788
+ wire(p, WIRE.W_O) -
1789
+ wire(p, WIRE.W_O_SHIFT));
1790
+ ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE;
1791
+ ap.non_native_field_gate_2 =
1792
+ ap.non_native_field_gate_2 -
1793
+ wire(p, WIRE.W_4_SHIFT);
1794
+ ap.non_native_field_gate_2 =
1795
+ ap.non_native_field_gate_2 +
1796
+ ap.limb_subproduct;
1797
+ ap.non_native_field_gate_2 =
1798
+ ap.non_native_field_gate_2 *
1799
+ wire(p, WIRE.Q_4);
1800
+
1801
+ ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE;
1802
+ ap.limb_subproduct =
1803
+ ap.limb_subproduct +
1804
+ (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT));
1805
+ ap.non_native_field_gate_1 = ap.limb_subproduct;
1806
+ ap.non_native_field_gate_1 =
1807
+ ap.non_native_field_gate_1 -
1808
+ (wire(p, WIRE.W_O) + wire(p, WIRE.W_4));
1809
+ ap.non_native_field_gate_1 =
1810
+ ap.non_native_field_gate_1 *
1811
+ wire(p, WIRE.Q_O);
1812
+
1813
+ ap.non_native_field_gate_3 = ap.limb_subproduct;
1814
+ ap.non_native_field_gate_3 =
1815
+ ap.non_native_field_gate_3 +
1816
+ wire(p, WIRE.W_4);
1817
+ ap.non_native_field_gate_3 =
1818
+ ap.non_native_field_gate_3 -
1819
+ (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT));
1820
+ ap.non_native_field_gate_3 =
1821
+ ap.non_native_field_gate_3 *
1822
+ wire(p, WIRE.Q_M);
1823
+
1824
+ Fr non_native_field_identity = ap.non_native_field_gate_1 +
1825
+ ap.non_native_field_gate_2 +
1826
+ ap.non_native_field_gate_3;
1827
+ non_native_field_identity =
1828
+ non_native_field_identity *
1829
+ wire(p, WIRE.Q_R);
1830
+
1831
+ // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm
1832
+ // deg 2
1833
+ ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT;
1834
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT);
1835
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT;
1836
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O);
1837
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT;
1838
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R);
1839
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT;
1840
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L);
1841
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4);
1842
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4);
1843
+
1844
+ // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm
1845
+ // deg 2
1846
+ ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT;
1847
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT);
1848
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT;
1849
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT);
1850
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT;
1851
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4);
1852
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT;
1853
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O);
1854
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT);
1855
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M);
1856
+
1857
+ Fr limb_accumulator_identity = ap.limb_accumulator_1 +
1858
+ ap.limb_accumulator_2;
1859
+ limb_accumulator_identity =
1860
+ limb_accumulator_identity *
1861
+ wire(p, WIRE.Q_O); // deg 3
1862
+
1863
+ ap.nnf_identity = non_native_field_identity + limb_accumulator_identity;
1864
+ ap.nnf_identity = ap.nnf_identity * (wire(p, WIRE.Q_NNF) * domainSep);
1865
+ evals[19] = ap.nnf_identity;
1866
+ }
1867
+
1868
+ struct PoseidonExternalParams {
1869
+ Fr s1;
1870
+ Fr s2;
1871
+ Fr s3;
1872
+ Fr s4;
1873
+ Fr u1;
1874
+ Fr u2;
1875
+ Fr u3;
1876
+ Fr u4;
1877
+ Fr t0;
1878
+ Fr t1;
1879
+ Fr t2;
1880
+ Fr t3;
1881
+ Fr v1;
1882
+ Fr v2;
1883
+ Fr v3;
1884
+ Fr v4;
1885
+ Fr q_pos_by_scaling;
1886
+ }
1887
+
1888
+ function accumulatePoseidonExternalRelation(
1889
+ Fr[NUMBER_OF_ENTITIES] memory p,
1890
+ Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1891
+ Fr domainSep
1892
+ ) internal pure {
1893
+ PoseidonExternalParams memory ep;
1894
+
1895
+ ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L);
1896
+ ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R);
1897
+ ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O);
1898
+ ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4);
1899
+
1900
+ ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1;
1901
+ ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2;
1902
+ ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3;
1903
+ ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4;
1904
+ // matrix mul v = M_E * u with 14 additions
1905
+ ep.t0 = ep.u1 + ep.u2; // u_1 + u_2
1906
+ ep.t1 = ep.u3 + ep.u4; // u_3 + u_4
1907
+ ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2
1908
+ // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4
1909
+ ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4
1910
+ // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4
1911
+ ep.v4 = ep.t1 + ep.t1;
1912
+ ep.v4 = ep.v4 + ep.v4 + ep.t3;
1913
+ // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4
1914
+ ep.v2 = ep.t0 + ep.t0;
1915
+ ep.v2 = ep.v2 + ep.v2 + ep.t2;
1916
+ // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4
1917
+ ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4
1918
+ ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4
1919
+
1920
+ ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep;
1921
+ evals[20] =
1922
+ evals[20] +
1923
+ ep.q_pos_by_scaling *
1924
+ (ep.v1 - wire(p, WIRE.W_L_SHIFT));
1925
+
1926
+ evals[21] =
1927
+ evals[21] +
1928
+ ep.q_pos_by_scaling *
1929
+ (ep.v2 - wire(p, WIRE.W_R_SHIFT));
1930
+
1931
+ evals[22] =
1932
+ evals[22] +
1933
+ ep.q_pos_by_scaling *
1934
+ (ep.v3 - wire(p, WIRE.W_O_SHIFT));
1935
+
1936
+ evals[23] =
1937
+ evals[23] +
1938
+ ep.q_pos_by_scaling *
1939
+ (ep.v4 - wire(p, WIRE.W_4_SHIFT));
1940
+ }
1941
+
1942
+ struct PoseidonInternalParams {
1943
+ Fr u1;
1944
+ Fr u2;
1945
+ Fr u3;
1946
+ Fr u4;
1947
+ Fr u_sum;
1948
+ Fr v1;
1949
+ Fr v2;
1950
+ Fr v3;
1951
+ Fr v4;
1952
+ Fr s1;
1953
+ Fr q_pos_by_scaling;
1954
+ }
1955
+
1956
+ function accumulatePoseidonInternalRelation(
1957
+ Fr[NUMBER_OF_ENTITIES] memory p,
1958
+ Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1959
+ Fr domainSep
1960
+ ) internal pure {
1961
+ PoseidonInternalParams memory ip;
1962
+
1963
+ Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [
1964
+ FrLib.from(
1965
+ 0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7
1966
+ ),
1967
+ FrLib.from(
1968
+ 0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b
1969
+ ),
1970
+ FrLib.from(
1971
+ 0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15
1972
+ ),
1973
+ FrLib.from(
1974
+ 0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b
1975
+ )
1976
+ ];
1977
+
1978
+ // add round constants
1979
+ ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L);
1980
+
1981
+ // apply s-box round
1982
+ ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1;
1983
+ ip.u2 = wire(p, WIRE.W_R);
1984
+ ip.u3 = wire(p, WIRE.W_O);
1985
+ ip.u4 = wire(p, WIRE.W_4);
1986
+
1987
+ // matrix mul with v = M_I * u 4 muls and 7 additions
1988
+ ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4;
1989
+
1990
+ ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep;
1991
+
1992
+ ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum;
1993
+ evals[24] =
1994
+ evals[24] +
1995
+ ip.q_pos_by_scaling *
1996
+ (ip.v1 - wire(p, WIRE.W_L_SHIFT));
1997
+
1998
+ ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum;
1999
+ evals[25] =
2000
+ evals[25] +
2001
+ ip.q_pos_by_scaling *
2002
+ (ip.v2 - wire(p, WIRE.W_R_SHIFT));
2003
+
2004
+ ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum;
2005
+ evals[26] =
2006
+ evals[26] +
2007
+ ip.q_pos_by_scaling *
2008
+ (ip.v3 - wire(p, WIRE.W_O_SHIFT));
2009
+
2010
+ ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum;
2011
+ evals[27] =
2012
+ evals[27] +
2013
+ ip.q_pos_by_scaling *
2014
+ (ip.v4 - wire(p, WIRE.W_4_SHIFT));
2015
+ }
2016
+
2017
+ function scaleAndBatchSubrelations(
2018
+ Fr[NUMBER_OF_SUBRELATIONS] memory evaluations,
2019
+ Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges
2020
+ ) internal pure returns (Fr accumulator) {
2021
+ accumulator = evaluations[0];
2022
+
2023
+ for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) {
2024
+ accumulator =
2025
+ accumulator +
2026
+ evaluations[i] *
2027
+ subrelationChallenges[i - 1];
2028
+ }
2029
+ }
2030
+ }
2031
+
2032
+ // Field arithmetic libraries - prevent littering the code with modmul / addmul
2033
+
2034
+ library CommitmentSchemeLib {
2035
+ using FrLib for Fr;
2036
+
2037
+ // Avoid stack too deep
2038
+ struct ShpleminiIntermediates {
2039
+ Fr unshiftedScalar;
2040
+ Fr shiftedScalar;
2041
+ Fr unshiftedScalarNeg;
2042
+ Fr shiftedScalarNeg;
2043
+ // Scalar to be multiplied by [1]₁
2044
+ Fr constantTermAccumulator;
2045
+ // Accumulator for powers of rho
2046
+ Fr batchingChallenge;
2047
+ // Linear combination of multilinear (sumcheck) evaluations and powers of rho
2048
+ Fr batchedEvaluation;
2049
+ Fr[4] denominators;
2050
+ Fr[4] batchingScalars;
2051
+ // 1/(z - r^{2^i}) for i = 0, ..., logSize, dynamically updated
2052
+ Fr posInvertedDenominator;
2053
+ // 1/(z + r^{2^i}) for i = 0, ..., logSize, dynamically updated
2054
+ Fr negInvertedDenominator;
2055
+ // ν^{2i} * 1/(z - r^{2^i})
2056
+ Fr scalingFactorPos;
2057
+ // ν^{2i+1} * 1/(z + r^{2^i})
2058
+ Fr scalingFactorNeg;
2059
+ // Fold_i(r^{2^i}) reconstructed by Verifier
2060
+ Fr[] foldPosEvaluations;
2061
+ }
2062
+
2063
+ function computeSquares(
2064
+ Fr r,
2065
+ uint256 logN
2066
+ ) internal pure returns (Fr[] memory) {
2067
+ Fr[] memory squares = new Fr[](logN);
2068
+ squares[0] = r;
2069
+ for (uint256 i = 1; i < logN; ++i) {
2070
+ squares[i] = squares[i - 1].sqr();
2071
+ }
2072
+ return squares;
2073
+ }
2074
+ // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1
2075
+
2076
+ function computeFoldPosEvaluations(
2077
+ Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges,
2078
+ Fr batchedEvalAccumulator,
2079
+ Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations,
2080
+ Fr[] memory geminiEvalChallengePowers,
2081
+ uint256 logSize
2082
+ ) internal view returns (Fr[] memory) {
2083
+ Fr[] memory foldPosEvaluations = new Fr[](logSize);
2084
+ for (uint256 i = logSize; i > 0; --i) {
2085
+ Fr challengePower = geminiEvalChallengePowers[i - 1];
2086
+ Fr u = sumcheckUChallenges[i - 1];
2087
+
2088
+ Fr batchedEvalRoundAcc = ((challengePower *
2089
+ batchedEvalAccumulator *
2090
+ Fr.wrap(2)) -
2091
+ geminiEvaluations[i - 1] *
2092
+ (challengePower * (ONE - u) - u));
2093
+ // Divide by the denominator
2094
+ batchedEvalRoundAcc =
2095
+ batchedEvalRoundAcc *
2096
+ (challengePower * (ONE - u) + u).invert();
2097
+
2098
+ batchedEvalAccumulator = batchedEvalRoundAcc;
2099
+ foldPosEvaluations[i - 1] = batchedEvalRoundAcc;
2100
+ }
2101
+ return foldPosEvaluations;
2102
+ }
2103
+ }
2104
+
2105
+ uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q
2106
+
2107
+ function bytes32ToString(bytes32 value) pure returns (string memory result) {
2108
+ bytes memory alphabet = "0123456789abcdef";
2109
+
2110
+ bytes memory str = new bytes(66);
2111
+ str[0] = "0";
2112
+ str[1] = "x";
2113
+ for (uint256 i = 0; i < 32; i++) {
2114
+ str[2 + i * 2] = alphabet[uint8(value[i] >> 4)];
2115
+ str[3 + i * 2] = alphabet[uint8(value[i] & 0x0f)];
2116
+ }
2117
+ result = string(str);
2118
+ }
2119
+
2120
+ // Fr utility
2121
+
2122
+ function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) {
2123
+ scalar = FrLib.fromBytes32(bytes32(proofSection));
2124
+ }
2125
+
2126
+ // EC Point utilities
2127
+ function bytesToG1Point(
2128
+ bytes calldata proofSection
2129
+ ) pure returns (Honk.G1Point memory point) {
2130
+ point = Honk.G1Point({
2131
+ x: uint256(bytes32(proofSection[0x00:0x20])) % Q,
2132
+ y: uint256(bytes32(proofSection[0x20:0x40])) % Q
2133
+ });
2134
+ }
2135
+
2136
+ function negateInplace(
2137
+ Honk.G1Point memory point
2138
+ ) pure returns (Honk.G1Point memory) {
2139
+ point.y = (Q - point.y) % Q;
2140
+ return point;
2141
+ }
2142
+
2143
+ /**
2144
+ * Convert the pairing points to G1 points.
2145
+ *
2146
+ * The pairing points are serialised as an array of 68 bit limbs representing two points
2147
+ * The lhs of a pairing operation and the rhs of a pairing operation
2148
+ *
2149
+ * There are 4 fields for each group element, leaving 8 fields for each side of the pairing.
2150
+ *
2151
+ * @param pairingPoints The pairing points to convert.
2152
+ * @return lhs
2153
+ * @return rhs
2154
+ */
2155
+ function convertPairingPointsToG1(
2156
+ Fr[PAIRING_POINTS_SIZE] memory pairingPoints
2157
+ ) pure returns (Honk.G1Point memory lhs, Honk.G1Point memory rhs) {
2158
+ uint256 lhsX = Fr.unwrap(pairingPoints[0]);
2159
+ lhsX |= Fr.unwrap(pairingPoints[1]) << 68;
2160
+ lhsX |= Fr.unwrap(pairingPoints[2]) << 136;
2161
+ lhsX |= Fr.unwrap(pairingPoints[3]) << 204;
2162
+ lhs.x = lhsX;
2163
+
2164
+ uint256 lhsY = Fr.unwrap(pairingPoints[4]);
2165
+ lhsY |= Fr.unwrap(pairingPoints[5]) << 68;
2166
+ lhsY |= Fr.unwrap(pairingPoints[6]) << 136;
2167
+ lhsY |= Fr.unwrap(pairingPoints[7]) << 204;
2168
+ lhs.y = lhsY;
2169
+
2170
+ uint256 rhsX = Fr.unwrap(pairingPoints[8]);
2171
+ rhsX |= Fr.unwrap(pairingPoints[9]) << 68;
2172
+ rhsX |= Fr.unwrap(pairingPoints[10]) << 136;
2173
+ rhsX |= Fr.unwrap(pairingPoints[11]) << 204;
2174
+ rhs.x = rhsX;
2175
+
2176
+ uint256 rhsY = Fr.unwrap(pairingPoints[12]);
2177
+ rhsY |= Fr.unwrap(pairingPoints[13]) << 68;
2178
+ rhsY |= Fr.unwrap(pairingPoints[14]) << 136;
2179
+ rhsY |= Fr.unwrap(pairingPoints[15]) << 204;
2180
+ rhs.y = rhsY;
2181
+ }
2182
+
2183
+ /**
2184
+ * Hash the pairing inputs from the present verification context with those extracted from the public inputs.
2185
+ *
2186
+ * @param proofPairingPoints Pairing points from the proof - (public inputs).
2187
+ * @param accLhs Accumulator point for the left side - result of shplemini.
2188
+ * @param accRhs Accumulator point for the right side - result of shplemini.
2189
+ * @return recursionSeparator The recursion separator - generated from hashing the above.
2190
+ */
2191
+ function generateRecursionSeparator(
2192
+ Fr[PAIRING_POINTS_SIZE] memory proofPairingPoints,
2193
+ Honk.G1Point memory accLhs,
2194
+ Honk.G1Point memory accRhs
2195
+ ) pure returns (Fr recursionSeparator) {
2196
+ // hash the proof aggregated X
2197
+ // hash the proof aggregated Y
2198
+ // hash the accum X
2199
+ // hash the accum Y
2200
+
2201
+ (
2202
+ Honk.G1Point memory proofLhs,
2203
+ Honk.G1Point memory proofRhs
2204
+ ) = convertPairingPointsToG1(proofPairingPoints);
2205
+
2206
+ uint256[8] memory recursionSeparatorElements;
2207
+
2208
+ // Proof points
2209
+ recursionSeparatorElements[0] = proofLhs.x;
2210
+ recursionSeparatorElements[1] = proofLhs.y;
2211
+ recursionSeparatorElements[2] = proofRhs.x;
2212
+ recursionSeparatorElements[3] = proofRhs.y;
2213
+
2214
+ // Accumulator points
2215
+ recursionSeparatorElements[4] = accLhs.x;
2216
+ recursionSeparatorElements[5] = accLhs.y;
2217
+ recursionSeparatorElements[6] = accRhs.x;
2218
+ recursionSeparatorElements[7] = accRhs.y;
2219
+
2220
+ recursionSeparator = FrLib.fromBytes32(
2221
+ keccak256(abi.encodePacked(recursionSeparatorElements))
2222
+ );
2223
+ }
2224
+
2225
+ /**
2226
+ * G1 Mul with Separator
2227
+ * Using the ecAdd and ecMul precompiles
2228
+ *
2229
+ * @param basePoint The point to multiply.
2230
+ * @param other The other point to add.
2231
+ * @param recursionSeperator The separator to use for the multiplication.
2232
+ * @return `(recursionSeperator * basePoint) + other`.
2233
+ */
2234
+ function mulWithSeperator(
2235
+ Honk.G1Point memory basePoint,
2236
+ Honk.G1Point memory other,
2237
+ Fr recursionSeperator
2238
+ ) view returns (Honk.G1Point memory) {
2239
+ Honk.G1Point memory result;
2240
+
2241
+ result = ecMul(recursionSeperator, basePoint);
2242
+ result = ecAdd(result, other);
2243
+
2244
+ return result;
2245
+ }
2246
+
2247
+ /**
2248
+ * G1 Mul
2249
+ * Takes a Fr value and a G1 point and uses the ecMul precompile to return the result.
2250
+ *
2251
+ * @param value The value to multiply the point by.
2252
+ * @param point The point to multiply.
2253
+ * @return result The result of the multiplication.
2254
+ */
2255
+ function ecMul(
2256
+ Fr value,
2257
+ Honk.G1Point memory point
2258
+ ) view returns (Honk.G1Point memory) {
2259
+ Honk.G1Point memory result;
2260
+
2261
+ assembly {
2262
+ let free := mload(0x40)
2263
+ // Write the point into memory (two 32 byte words)
2264
+ // Memory layout:
2265
+ // Address | value
2266
+ // free | point.x
2267
+ // free + 0x20| point.y
2268
+ mstore(free, mload(point))
2269
+ mstore(add(free, 0x20), mload(add(point, 0x20)))
2270
+ // Write the scalar into memory (one 32 byte word)
2271
+ // Memory layout:
2272
+ // Address | value
2273
+ // free + 0x40| value
2274
+ mstore(add(free, 0x40), value)
2275
+
2276
+ // Call the ecMul precompile, it takes in the following
2277
+ // [point.x, point.y, scalar], and returns the result back into the free memory location.
2278
+ let success := staticcall(gas(), 0x07, free, 0x60, free, 0x40)
2279
+ if iszero(success) {
2280
+ revert(0, 0)
2281
+ }
2282
+ // Copy the result of the multiplication back into the result memory location.
2283
+ // Memory layout:
2284
+ // Address | value
2285
+ // result | result.x
2286
+ // result + 0x20| result.y
2287
+ mstore(result, mload(free))
2288
+ mstore(add(result, 0x20), mload(add(free, 0x20)))
2289
+
2290
+ mstore(0x40, add(free, 0x60))
2291
+ }
2292
+
2293
+ return result;
2294
+ }
2295
+
2296
+ /**
2297
+ * G1 Add
2298
+ * Takes two G1 points and uses the ecAdd precompile to return the result.
2299
+ *
2300
+ * @param lhs The left hand side of the addition.
2301
+ * @param rhs The right hand side of the addition.
2302
+ * @return result The result of the addition.
2303
+ */
2304
+ function ecAdd(
2305
+ Honk.G1Point memory lhs,
2306
+ Honk.G1Point memory rhs
2307
+ ) view returns (Honk.G1Point memory) {
2308
+ Honk.G1Point memory result;
2309
+
2310
+ assembly {
2311
+ let free := mload(0x40)
2312
+ // Write lhs into memory (two 32 byte words)
2313
+ // Memory layout:
2314
+ // Address | value
2315
+ // free | lhs.x
2316
+ // free + 0x20| lhs.y
2317
+ mstore(free, mload(lhs))
2318
+ mstore(add(free, 0x20), mload(add(lhs, 0x20)))
2319
+
2320
+ // Write rhs into memory (two 32 byte words)
2321
+ // Memory layout:
2322
+ // Address | value
2323
+ // free + 0x40| rhs.x
2324
+ // free + 0x60| rhs.y
2325
+ mstore(add(free, 0x40), mload(rhs))
2326
+ mstore(add(free, 0x60), mload(add(rhs, 0x20)))
2327
+
2328
+ // Call the ecAdd precompile, it takes in the following
2329
+ // [lhs.x, lhs.y, rhs.x, rhs.y], and returns their addition back into the free memory location.
2330
+ let success := staticcall(gas(), 0x06, free, 0x80, free, 0x40)
2331
+ if iszero(success) {
2332
+ revert(0, 0)
2333
+ }
2334
+
2335
+ // Copy the result of the addition back into the result memory location.
2336
+ // Memory layout:
2337
+ // Address | value
2338
+ // result | result.x
2339
+ // result + 0x20| result.y
2340
+ mstore(result, mload(free))
2341
+ mstore(add(result, 0x20), mload(add(free, 0x20)))
2342
+
2343
+ mstore(0x40, add(free, 0x80))
2344
+ }
2345
+
2346
+ return result;
2347
+ }
2348
+
2349
+ function validateOnCurve(Honk.G1Point memory point) pure {
2350
+ uint256 x = point.x;
2351
+ uint256 y = point.y;
2352
+
2353
+ bool success = false;
2354
+ assembly {
2355
+ let xx := mulmod(x, x, Q)
2356
+ success := eq(mulmod(y, y, Q), addmod(mulmod(x, xx, Q), 3, Q))
2357
+ }
2358
+
2359
+ require(success, "point is not on the curve");
2360
+ }
2361
+
2362
+ function pairing(
2363
+ Honk.G1Point memory rhs,
2364
+ Honk.G1Point memory lhs
2365
+ ) view returns (bool decodedResult) {
2366
+ bytes memory input = abi.encodePacked(
2367
+ rhs.x,
2368
+ rhs.y,
2369
+ // Fixed G2 point
2370
+ uint256(
2371
+ 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2
2372
+ ),
2373
+ uint256(
2374
+ 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed
2375
+ ),
2376
+ uint256(
2377
+ 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b
2378
+ ),
2379
+ uint256(
2380
+ 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa
2381
+ ),
2382
+ lhs.x,
2383
+ lhs.y,
2384
+ // G2 point from VK
2385
+ uint256(
2386
+ 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1
2387
+ ),
2388
+ uint256(
2389
+ 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0
2390
+ ),
2391
+ uint256(
2392
+ 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4
2393
+ ),
2394
+ uint256(
2395
+ 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55
2396
+ )
2397
+ );
2398
+
2399
+ (bool success, bytes memory result) = address(0x08).staticcall(input);
2400
+ decodedResult = success && abi.decode(result, (bool));
2401
+ }
2402
+
2403
+ // Field arithmetic libraries - prevent littering the code with modmul / addmul
2404
+
2405
+ abstract contract BaseZKHonkVerifier is IVerifier {
2406
+ using FrLib for Fr;
2407
+
2408
+ uint256 immutable $N;
2409
+ uint256 immutable $LOG_N;
2410
+ uint256 immutable $VK_HASH;
2411
+ uint256 immutable $NUM_PUBLIC_INPUTS;
2412
+
2413
+ constructor(
2414
+ uint256 _N,
2415
+ uint256 _logN,
2416
+ uint256 _vkHash,
2417
+ uint256 _numPublicInputs
2418
+ ) {
2419
+ $N = _N;
2420
+ $LOG_N = _logN;
2421
+ $VK_HASH = _vkHash;
2422
+ $NUM_PUBLIC_INPUTS = _numPublicInputs;
2423
+ }
2424
+
2425
+ // Errors
2426
+ error ProofLengthWrong();
2427
+ error ProofLengthWrongWithLogN(
2428
+ uint256 logN,
2429
+ uint256 actualLength,
2430
+ uint256 expectedLength
2431
+ );
2432
+ error PublicInputsLengthWrong();
2433
+ error SumcheckFailed();
2434
+ error ShpleminiFailed();
2435
+ error GeminiChallengeInSubgroup();
2436
+ error ConsistencyCheckFailed();
2437
+
2438
+ // Constants for proof length calculation (matching UltraKeccakZKFlavor)
2439
+ uint256 constant NUM_WITNESS_ENTITIES = 8;
2440
+ uint256 constant NUM_ELEMENTS_COMM = 2; // uint256 elements for curve points
2441
+ uint256 constant NUM_ELEMENTS_FR = 1; // uint256 elements for field elements
2442
+ uint256 constant NUM_LIBRA_EVALUATIONS = 4; // libra evaluations
2443
+
2444
+ // Calculate proof size based on log_n (matching UltraKeccakZKFlavor formula)
2445
+ function calculateProofSize(uint256 logN) internal pure returns (uint256) {
2446
+ // Witness and Libra commitments
2447
+ uint256 proofLength = NUM_WITNESS_ENTITIES * NUM_ELEMENTS_COMM; // witness commitments
2448
+ proofLength += NUM_ELEMENTS_COMM * 4; // Libra concat, grand sum, quotient comms + Gemini masking
2449
+
2450
+ // Sumcheck
2451
+ proofLength +=
2452
+ logN *
2453
+ ZK_BATCHED_RELATION_PARTIAL_LENGTH *
2454
+ NUM_ELEMENTS_FR; // sumcheck univariates
2455
+ proofLength += NUMBER_OF_ENTITIES * NUM_ELEMENTS_FR; // sumcheck evaluations
2456
+
2457
+ // Libra and Gemini
2458
+ proofLength += NUM_ELEMENTS_FR * 3; // Libra sum, claimed eval, Gemini masking eval
2459
+ proofLength += logN * NUM_ELEMENTS_FR; // Gemini a evaluations
2460
+ proofLength += NUM_LIBRA_EVALUATIONS * NUM_ELEMENTS_FR; // libra evaluations
2461
+
2462
+ // PCS commitments
2463
+ proofLength += (logN - 1) * NUM_ELEMENTS_COMM; // Gemini Fold commitments
2464
+ proofLength += NUM_ELEMENTS_COMM * 2; // Shplonk Q and KZG W commitments
2465
+
2466
+ // Pairing points
2467
+ proofLength += PAIRING_POINTS_SIZE; // pairing inputs carried on public inputs
2468
+
2469
+ return proofLength;
2470
+ }
2471
+
2472
+ uint256 constant SHIFTED_COMMITMENTS_START = 30;
2473
+
2474
+ function loadVerificationKey()
2475
+ internal
2476
+ pure
2477
+ virtual
2478
+ returns (Honk.VerificationKey memory);
2479
+
2480
+ function verify(
2481
+ bytes calldata proof,
2482
+ bytes32[] calldata publicInputs
2483
+ ) public view override returns (bool verified) {
2484
+ // Calculate expected proof size based on $LOG_N
2485
+ uint256 expectedProofSize = calculateProofSize($LOG_N);
2486
+
2487
+ // Check the received proof is the expected size where each field element is 32 bytes
2488
+ if (proof.length != expectedProofSize * 32) {
2489
+ revert ProofLengthWrongWithLogN(
2490
+ $LOG_N,
2491
+ proof.length,
2492
+ expectedProofSize * 32
2493
+ );
2494
+ }
2495
+
2496
+ Honk.VerificationKey memory vk = loadVerificationKey();
2497
+ Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof, $LOG_N);
2498
+
2499
+ if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) {
2500
+ revert PublicInputsLengthWrong();
2501
+ }
2502
+
2503
+ // Generate the fiat shamir challenges for the whole protocol
2504
+ ZKTranscript memory t = ZKTranscriptLib.generateTranscript(
2505
+ p,
2506
+ publicInputs,
2507
+ $VK_HASH,
2508
+ $NUM_PUBLIC_INPUTS,
2509
+ $LOG_N
2510
+ );
2511
+
2512
+ // Derive public input delta
2513
+ t.relationParameters.publicInputsDelta = computePublicInputDelta(
2514
+ publicInputs,
2515
+ p.pairingPointObject,
2516
+ t.relationParameters.beta,
2517
+ t.relationParameters.gamma /*pubInputsOffset=*/,
2518
+ 1
2519
+ );
2520
+
2521
+ // Sumcheck
2522
+ if (!verifySumcheck(p, t)) revert SumcheckFailed();
2523
+
2524
+ if (!verifyShplemini(p, vk, t)) revert ShpleminiFailed();
2525
+
2526
+ verified = true;
2527
+ }
2528
+
2529
+ uint256 constant PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28;
2530
+
2531
+ function computePublicInputDelta(
2532
+ bytes32[] memory publicInputs,
2533
+ Fr[PAIRING_POINTS_SIZE] memory pairingPointObject,
2534
+ Fr beta,
2535
+ Fr gamma,
2536
+ uint256 offset
2537
+ ) internal view returns (Fr publicInputDelta) {
2538
+ Fr numerator = Fr.wrap(1);
2539
+ Fr denominator = Fr.wrap(1);
2540
+
2541
+ Fr numeratorAcc = gamma +
2542
+ (beta * FrLib.from(PERMUTATION_ARGUMENT_VALUE_SEPARATOR + offset));
2543
+ Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1));
2544
+
2545
+ {
2546
+ for (
2547
+ uint256 i = 0;
2548
+ i < $NUM_PUBLIC_INPUTS - PAIRING_POINTS_SIZE;
2549
+ i++
2550
+ ) {
2551
+ Fr pubInput = FrLib.fromBytes32(publicInputs[i]);
2552
+
2553
+ numerator = numerator * (numeratorAcc + pubInput);
2554
+ denominator = denominator * (denominatorAcc + pubInput);
2555
+
2556
+ numeratorAcc = numeratorAcc + beta;
2557
+ denominatorAcc = denominatorAcc - beta;
2558
+ }
2559
+
2560
+ for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
2561
+ Fr pubInput = pairingPointObject[i];
2562
+
2563
+ numerator = numerator * (numeratorAcc + pubInput);
2564
+ denominator = denominator * (denominatorAcc + pubInput);
2565
+
2566
+ numeratorAcc = numeratorAcc + beta;
2567
+ denominatorAcc = denominatorAcc - beta;
2568
+ }
2569
+ }
2570
+
2571
+ // Fr delta = numerator / denominator; // TOOO: batch invert later?
2572
+ publicInputDelta = FrLib.div(numerator, denominator);
2573
+ }
2574
+
2575
+ function verifySumcheck(
2576
+ Honk.ZKProof memory proof,
2577
+ ZKTranscript memory tp
2578
+ ) internal view returns (bool verified) {
2579
+ Fr roundTargetSum = tp.libraChallenge * proof.libraSum; // default 0
2580
+ Fr powPartialEvaluation = Fr.wrap(1);
2581
+
2582
+ // We perform sumcheck reductions over log n rounds ( the multivariate degree )
2583
+ for (uint256 round; round < $LOG_N; ++round) {
2584
+ Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH]
2585
+ memory roundUnivariate = proof.sumcheckUnivariates[round];
2586
+ Fr totalSum = roundUnivariate[0] + roundUnivariate[1];
2587
+ if (totalSum != roundTargetSum) revert SumcheckFailed();
2588
+
2589
+ Fr roundChallenge = tp.sumCheckUChallenges[round];
2590
+
2591
+ // Update the round target for the next rounf
2592
+ roundTargetSum = computeNextTargetSum(
2593
+ roundUnivariate,
2594
+ roundChallenge
2595
+ );
2596
+ powPartialEvaluation =
2597
+ powPartialEvaluation *
2598
+ (Fr.wrap(1) +
2599
+ roundChallenge *
2600
+ (tp.gateChallenges[round] - Fr.wrap(1)));
2601
+ }
2602
+
2603
+ // Last round
2604
+ Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations(
2605
+ proof.sumcheckEvaluations,
2606
+ tp.relationParameters,
2607
+ tp.alphas,
2608
+ powPartialEvaluation
2609
+ );
2610
+
2611
+ Fr evaluation = Fr.wrap(1);
2612
+ for (uint256 i = 2; i < $LOG_N; i++) {
2613
+ evaluation = evaluation * tp.sumCheckUChallenges[i];
2614
+ }
2615
+
2616
+ grandHonkRelationSum =
2617
+ grandHonkRelationSum *
2618
+ (Fr.wrap(1) - evaluation) +
2619
+ proof.libraEvaluation *
2620
+ tp.libraChallenge;
2621
+ verified = (grandHonkRelationSum == roundTargetSum);
2622
+ }
2623
+
2624
+ // Return the new target sum for the next sumcheck round
2625
+ function computeNextTargetSum(
2626
+ Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates,
2627
+ Fr roundChallenge
2628
+ ) internal view returns (Fr targetSum) {
2629
+ Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH]
2630
+ memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [
2631
+ Fr.wrap(
2632
+ 0x0000000000000000000000000000000000000000000000000000000000009d80
2633
+ ),
2634
+ Fr.wrap(
2635
+ 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51
2636
+ ),
2637
+ Fr.wrap(
2638
+ 0x00000000000000000000000000000000000000000000000000000000000005a0
2639
+ ),
2640
+ Fr.wrap(
2641
+ 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31
2642
+ ),
2643
+ Fr.wrap(
2644
+ 0x0000000000000000000000000000000000000000000000000000000000000240
2645
+ ),
2646
+ Fr.wrap(
2647
+ 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31
2648
+ ),
2649
+ Fr.wrap(
2650
+ 0x00000000000000000000000000000000000000000000000000000000000005a0
2651
+ ),
2652
+ Fr.wrap(
2653
+ 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51
2654
+ ),
2655
+ Fr.wrap(
2656
+ 0x0000000000000000000000000000000000000000000000000000000000009d80
2657
+ )
2658
+ ];
2659
+
2660
+ // To compute the next target sum, we evaluate the given univariate at a point u (challenge).
2661
+
2662
+ // Performing Barycentric evaluations
2663
+ // Compute B(x)
2664
+ Fr numeratorValue = Fr.wrap(1);
2665
+ for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) {
2666
+ numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i));
2667
+ }
2668
+
2669
+ Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses;
2670
+ for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) {
2671
+ denominatorInverses[i] = FrLib.invert(
2672
+ BARYCENTRIC_LAGRANGE_DENOMINATORS[i] *
2673
+ (roundChallenge - Fr.wrap(i))
2674
+ );
2675
+ }
2676
+
2677
+ for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) {
2678
+ targetSum =
2679
+ targetSum +
2680
+ roundUnivariates[i] *
2681
+ denominatorInverses[i];
2682
+ }
2683
+
2684
+ // Scale the sum by the value of B(x)
2685
+ targetSum = targetSum * numeratorValue;
2686
+ }
2687
+
2688
+ uint256 constant LIBRA_COMMITMENTS = 3;
2689
+ uint256 constant LIBRA_EVALUATIONS = 4;
2690
+ uint256 constant LIBRA_UNIVARIATES_LENGTH = 9;
2691
+
2692
+ struct PairingInputs {
2693
+ Honk.G1Point P_0;
2694
+ Honk.G1Point P_1;
2695
+ }
2696
+
2697
+ function verifyShplemini(
2698
+ Honk.ZKProof memory proof,
2699
+ Honk.VerificationKey memory vk,
2700
+ ZKTranscript memory tp
2701
+ ) internal view returns (bool verified) {
2702
+ CommitmentSchemeLib.ShpleminiIntermediates memory mem; // stack
2703
+
2704
+ // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size
2705
+ Fr[] memory powers_of_evaluation_challenge = CommitmentSchemeLib
2706
+ .computeSquares(tp.geminiR, $LOG_N);
2707
+ // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings
2708
+ Fr[] memory scalars = new Fr[](
2709
+ NUMBER_UNSHIFTED + $LOG_N + LIBRA_COMMITMENTS + 3
2710
+ );
2711
+ Honk.G1Point[] memory commitments = new Honk.G1Point[](
2712
+ NUMBER_UNSHIFTED + $LOG_N + LIBRA_COMMITMENTS + 3
2713
+ );
2714
+
2715
+ mem.posInvertedDenominator = (tp.shplonkZ -
2716
+ powers_of_evaluation_challenge[0]).invert();
2717
+ mem.negInvertedDenominator = (tp.shplonkZ +
2718
+ powers_of_evaluation_challenge[0]).invert();
2719
+
2720
+ mem.unshiftedScalar =
2721
+ mem.posInvertedDenominator +
2722
+ (tp.shplonkNu * mem.negInvertedDenominator);
2723
+ mem.shiftedScalar =
2724
+ tp.geminiR.invert() *
2725
+ (mem.posInvertedDenominator -
2726
+ (tp.shplonkNu * mem.negInvertedDenominator));
2727
+
2728
+ scalars[0] = Fr.wrap(1);
2729
+ commitments[0] = proof.shplonkQ;
2730
+
2731
+ /* Batch multivariate opening claims, shifted and unshifted
2732
+ * The vector of scalars is populated as follows:
2733
+ * \f[
2734
+ * \left(
2735
+ * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right),
2736
+ * \ldots,
2737
+ * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right),
2738
+ * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right),
2739
+ * \ldots,
2740
+ * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right)
2741
+ * \right)
2742
+ * \f]
2743
+ *
2744
+ * The following vector is concatenated to the vector of commitments:
2745
+ * \f[
2746
+ * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1}
2747
+ * \f]
2748
+ *
2749
+ * Simultaneously, the evaluation of the multilinear polynomial
2750
+ * \f[
2751
+ * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i}
2752
+ * \f]
2753
+ * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed.
2754
+ *
2755
+ * This approach minimizes the number of iterations over the commitments to multilinear polynomials
2756
+ * and eliminates the need to store the powers of \f$ \rho \f$.
2757
+ */
2758
+ mem.batchedEvaluation = proof.geminiMaskingEval;
2759
+ mem.batchingChallenge = tp.rho;
2760
+ mem.unshiftedScalarNeg = mem.unshiftedScalar.neg();
2761
+ mem.shiftedScalarNeg = mem.shiftedScalar.neg();
2762
+
2763
+ scalars[1] = mem.unshiftedScalarNeg;
2764
+ for (uint256 i = 0; i < NUMBER_UNSHIFTED; ++i) {
2765
+ scalars[i + 2] = mem.unshiftedScalarNeg * mem.batchingChallenge;
2766
+ mem.batchedEvaluation =
2767
+ mem.batchedEvaluation +
2768
+ (proof.sumcheckEvaluations[i] * mem.batchingChallenge);
2769
+ mem.batchingChallenge = mem.batchingChallenge * tp.rho;
2770
+ }
2771
+ // g commitments are accumulated at r
2772
+ // For each of the to be shifted commitments perform the shift in place by
2773
+ // adding to the unshifted value.
2774
+ // We do so, as the values are to be used in batchMul later, and as
2775
+ // `a * c + b * c = (a + b) * c` this will allow us to reduce memory and compute.
2776
+ // Applied to w1, w2, w3, w4 and zPerm
2777
+ for (uint256 i = 0; i < NUMBER_TO_BE_SHIFTED; ++i) {
2778
+ uint256 scalarOff = i + SHIFTED_COMMITMENTS_START;
2779
+ uint256 evaluationOff = i + NUMBER_UNSHIFTED;
2780
+
2781
+ scalars[scalarOff] =
2782
+ scalars[scalarOff] +
2783
+ (mem.shiftedScalarNeg * mem.batchingChallenge);
2784
+ mem.batchedEvaluation =
2785
+ mem.batchedEvaluation +
2786
+ (proof.sumcheckEvaluations[evaluationOff] *
2787
+ mem.batchingChallenge);
2788
+ mem.batchingChallenge = mem.batchingChallenge * tp.rho;
2789
+ }
2790
+
2791
+ commitments[1] = proof.geminiMaskingPoly;
2792
+
2793
+ commitments[2] = vk.qm;
2794
+ commitments[3] = vk.qc;
2795
+ commitments[4] = vk.ql;
2796
+ commitments[5] = vk.qr;
2797
+ commitments[6] = vk.qo;
2798
+ commitments[7] = vk.q4;
2799
+ commitments[8] = vk.qLookup;
2800
+ commitments[9] = vk.qArith;
2801
+ commitments[10] = vk.qDeltaRange;
2802
+ commitments[11] = vk.qElliptic;
2803
+ commitments[12] = vk.qMemory;
2804
+ commitments[13] = vk.qNnf;
2805
+ commitments[14] = vk.qPoseidon2External;
2806
+ commitments[15] = vk.qPoseidon2Internal;
2807
+ commitments[16] = vk.s1;
2808
+ commitments[17] = vk.s2;
2809
+ commitments[18] = vk.s3;
2810
+ commitments[19] = vk.s4;
2811
+ commitments[20] = vk.id1;
2812
+ commitments[21] = vk.id2;
2813
+ commitments[22] = vk.id3;
2814
+ commitments[23] = vk.id4;
2815
+ commitments[24] = vk.t1;
2816
+ commitments[25] = vk.t2;
2817
+ commitments[26] = vk.t3;
2818
+ commitments[27] = vk.t4;
2819
+ commitments[28] = vk.lagrangeFirst;
2820
+ commitments[29] = vk.lagrangeLast;
2821
+
2822
+ // Accumulate proof points
2823
+ commitments[30] = proof.w1;
2824
+ commitments[31] = proof.w2;
2825
+ commitments[32] = proof.w3;
2826
+ commitments[33] = proof.w4;
2827
+ commitments[34] = proof.zPerm;
2828
+ commitments[35] = proof.lookupInverses;
2829
+ commitments[36] = proof.lookupReadCounts;
2830
+ commitments[37] = proof.lookupReadTags;
2831
+
2832
+ /* Batch gemini claims from the prover
2833
+ * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from
2834
+ * aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars
2835
+ *
2836
+ * 1. Moves the vector
2837
+ * \f[
2838
+ * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right)
2839
+ * \f]
2840
+ * to the 'commitments' vector.
2841
+ *
2842
+ * 2. Computes the scalars:
2843
+ * \f[
2844
+ * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}}
2845
+ * \f]
2846
+ * and places them into the 'scalars' vector.
2847
+ *
2848
+ * 3. Accumulates the summands of the constant term:
2849
+ * \f[
2850
+ * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}}
2851
+ * \f]
2852
+ * and adds them to the 'constant_term_accumulator'.
2853
+ */
2854
+
2855
+ // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator:
2856
+ // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., $LOG_N - 1
2857
+ Fr[] memory foldPosEvaluations = CommitmentSchemeLib
2858
+ .computeFoldPosEvaluations(
2859
+ tp.sumCheckUChallenges,
2860
+ mem.batchedEvaluation,
2861
+ proof.geminiAEvaluations,
2862
+ powers_of_evaluation_challenge,
2863
+ $LOG_N
2864
+ );
2865
+
2866
+ mem.constantTermAccumulator =
2867
+ foldPosEvaluations[0] *
2868
+ mem.posInvertedDenominator;
2869
+ mem.constantTermAccumulator =
2870
+ mem.constantTermAccumulator +
2871
+ (proof.geminiAEvaluations[0] *
2872
+ tp.shplonkNu *
2873
+ mem.negInvertedDenominator);
2874
+
2875
+ mem.batchingChallenge = tp.shplonkNu.sqr();
2876
+ uint256 boundary = NUMBER_UNSHIFTED + 2;
2877
+
2878
+ // Compute Shplonk constant term contributions from Aₗ(± r^{2ˡ}) for l = 1, ..., m-1;
2879
+ // Compute scalar multipliers for each fold commitment
2880
+ for (uint256 i = 0; i < $LOG_N - 1; ++i) {
2881
+ bool dummy_round = i >= ($LOG_N - 1);
2882
+
2883
+ if (!dummy_round) {
2884
+ // Update inverted denominators
2885
+ mem.posInvertedDenominator = (tp.shplonkZ -
2886
+ powers_of_evaluation_challenge[i + 1]).invert();
2887
+ mem.negInvertedDenominator = (tp.shplonkZ +
2888
+ powers_of_evaluation_challenge[i + 1]).invert();
2889
+
2890
+ // Compute the scalar multipliers for Aₗ(± r^{2ˡ}) and [Aₗ]
2891
+ mem.scalingFactorPos =
2892
+ mem.batchingChallenge *
2893
+ mem.posInvertedDenominator;
2894
+ mem.scalingFactorNeg =
2895
+ mem.batchingChallenge *
2896
+ tp.shplonkNu *
2897
+ mem.negInvertedDenominator;
2898
+ scalars[boundary + i] =
2899
+ mem.scalingFactorNeg.neg() +
2900
+ mem.scalingFactorPos.neg();
2901
+
2902
+ // Accumulate the const term contribution given by
2903
+ // v^{2l} * Aₗ(r^{2ˡ}) /(z-r^{2^l}) + v^{2l+1} * Aₗ(-r^{2ˡ}) /(z+ r^{2^l})
2904
+ Fr accumContribution = mem.scalingFactorNeg *
2905
+ proof.geminiAEvaluations[i + 1];
2906
+ accumContribution =
2907
+ accumContribution +
2908
+ mem.scalingFactorPos *
2909
+ foldPosEvaluations[i + 1];
2910
+ mem.constantTermAccumulator =
2911
+ mem.constantTermAccumulator +
2912
+ accumContribution;
2913
+ }
2914
+ // Update the running power of v
2915
+ mem.batchingChallenge =
2916
+ mem.batchingChallenge *
2917
+ tp.shplonkNu *
2918
+ tp.shplonkNu;
2919
+
2920
+ commitments[boundary + i] = proof.geminiFoldComms[i];
2921
+ }
2922
+
2923
+ boundary += $LOG_N - 1;
2924
+
2925
+ // Finalize the batch opening claim
2926
+ mem.denominators[0] = Fr.wrap(1).div(tp.shplonkZ - tp.geminiR);
2927
+ mem.denominators[1] = Fr.wrap(1).div(
2928
+ tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR
2929
+ );
2930
+ mem.denominators[2] = mem.denominators[0];
2931
+ mem.denominators[3] = mem.denominators[0];
2932
+
2933
+ mem.batchingChallenge =
2934
+ mem.batchingChallenge *
2935
+ tp.shplonkNu *
2936
+ tp.shplonkNu;
2937
+ for (uint256 i = 0; i < LIBRA_EVALUATIONS; i++) {
2938
+ Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge;
2939
+ mem.batchingScalars[i] = scalingFactor.neg();
2940
+ mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu;
2941
+ mem.constantTermAccumulator =
2942
+ mem.constantTermAccumulator +
2943
+ scalingFactor *
2944
+ proof.libraPolyEvals[i];
2945
+ }
2946
+ scalars[boundary] = mem.batchingScalars[0];
2947
+ scalars[boundary + 1] = mem.batchingScalars[1] + mem.batchingScalars[2];
2948
+ scalars[boundary + 2] = mem.batchingScalars[3];
2949
+
2950
+ for (uint256 i = 0; i < LIBRA_COMMITMENTS; i++) {
2951
+ commitments[boundary++] = proof.libraCommitments[i];
2952
+ }
2953
+
2954
+ commitments[boundary] = Honk.G1Point({ x: 1, y: 2 });
2955
+ scalars[boundary++] = mem.constantTermAccumulator;
2956
+
2957
+ if (
2958
+ !checkEvalsConsistency(
2959
+ proof.libraPolyEvals,
2960
+ tp.geminiR,
2961
+ tp.sumCheckUChallenges,
2962
+ proof.libraEvaluation
2963
+ )
2964
+ ) {
2965
+ revert ConsistencyCheckFailed();
2966
+ }
2967
+
2968
+ Honk.G1Point memory quotient_commitment = proof.kzgQuotient;
2969
+
2970
+ commitments[boundary] = quotient_commitment;
2971
+ scalars[boundary] = tp.shplonkZ; // evaluation challenge
2972
+
2973
+ PairingInputs memory pair;
2974
+ pair.P_0 = batchMul(commitments, scalars);
2975
+ pair.P_1 = negateInplace(quotient_commitment);
2976
+
2977
+ // Aggregate pairing points
2978
+ Fr recursionSeparator = generateRecursionSeparator(
2979
+ proof.pairingPointObject,
2980
+ pair.P_0,
2981
+ pair.P_1
2982
+ );
2983
+ (
2984
+ Honk.G1Point memory P_0_other,
2985
+ Honk.G1Point memory P_1_other
2986
+ ) = convertPairingPointsToG1(proof.pairingPointObject);
2987
+
2988
+ // Validate the points from the proof are on the curve
2989
+ validateOnCurve(P_0_other);
2990
+ validateOnCurve(P_1_other);
2991
+
2992
+ // accumulate with aggregate points in proof
2993
+ pair.P_0 = mulWithSeperator(pair.P_0, P_0_other, recursionSeparator);
2994
+ pair.P_1 = mulWithSeperator(pair.P_1, P_1_other, recursionSeparator);
2995
+
2996
+ return pairing(pair.P_0, pair.P_1);
2997
+ }
2998
+
2999
+ struct SmallSubgroupIpaIntermediates {
3000
+ Fr[SUBGROUP_SIZE] challengePolyLagrange;
3001
+ Fr challengePolyEval;
3002
+ Fr lagrangeFirst;
3003
+ Fr lagrangeLast;
3004
+ Fr rootPower;
3005
+ Fr[SUBGROUP_SIZE] denominators; // this has to disappear
3006
+ Fr diff;
3007
+ }
3008
+
3009
+ function checkEvalsConsistency(
3010
+ Fr[LIBRA_EVALUATIONS] memory libraPolyEvals,
3011
+ Fr geminiR,
3012
+ Fr[CONST_PROOF_SIZE_LOG_N] memory uChallenges,
3013
+ Fr libraEval
3014
+ ) internal view returns (bool check) {
3015
+ Fr one = Fr.wrap(1);
3016
+ Fr vanishingPolyEval = geminiR.pow(SUBGROUP_SIZE) - one;
3017
+ if (vanishingPolyEval == Fr.wrap(0)) {
3018
+ revert GeminiChallengeInSubgroup();
3019
+ }
3020
+
3021
+ SmallSubgroupIpaIntermediates memory mem;
3022
+ mem.challengePolyLagrange[0] = one;
3023
+ for (uint256 round = 0; round < $LOG_N; round++) {
3024
+ uint256 currIdx = 1 + LIBRA_UNIVARIATES_LENGTH * round;
3025
+ mem.challengePolyLagrange[currIdx] = one;
3026
+ for (
3027
+ uint256 idx = currIdx + 1;
3028
+ idx < currIdx + LIBRA_UNIVARIATES_LENGTH;
3029
+ idx++
3030
+ ) {
3031
+ mem.challengePolyLagrange[idx] =
3032
+ mem.challengePolyLagrange[idx - 1] *
3033
+ uChallenges[round];
3034
+ }
3035
+ }
3036
+
3037
+ mem.rootPower = one;
3038
+ mem.challengePolyEval = Fr.wrap(0);
3039
+ for (uint256 idx = 0; idx < SUBGROUP_SIZE; idx++) {
3040
+ mem.denominators[idx] = mem.rootPower * geminiR - one;
3041
+ mem.denominators[idx] = mem.denominators[idx].invert();
3042
+ mem.challengePolyEval =
3043
+ mem.challengePolyEval +
3044
+ mem.challengePolyLagrange[idx] *
3045
+ mem.denominators[idx];
3046
+ mem.rootPower = mem.rootPower * SUBGROUP_GENERATOR_INVERSE;
3047
+ }
3048
+
3049
+ Fr numerator = vanishingPolyEval * Fr.wrap(SUBGROUP_SIZE).invert();
3050
+ mem.challengePolyEval = mem.challengePolyEval * numerator;
3051
+ mem.lagrangeFirst = mem.denominators[0] * numerator;
3052
+ mem.lagrangeLast = mem.denominators[SUBGROUP_SIZE - 1] * numerator;
3053
+
3054
+ mem.diff = mem.lagrangeFirst * libraPolyEvals[2];
3055
+
3056
+ mem.diff =
3057
+ mem.diff +
3058
+ (geminiR - SUBGROUP_GENERATOR_INVERSE) *
3059
+ (libraPolyEvals[1] -
3060
+ libraPolyEvals[2] -
3061
+ libraPolyEvals[0] *
3062
+ mem.challengePolyEval);
3063
+ mem.diff =
3064
+ mem.diff +
3065
+ mem.lagrangeLast *
3066
+ (libraPolyEvals[2] - libraEval) -
3067
+ vanishingPolyEval *
3068
+ libraPolyEvals[3];
3069
+
3070
+ check = mem.diff == Fr.wrap(0);
3071
+ }
3072
+
3073
+ // This implementation is the same as above with different constants
3074
+ function batchMul(
3075
+ Honk.G1Point[] memory base,
3076
+ Fr[] memory scalars
3077
+ ) internal view returns (Honk.G1Point memory result) {
3078
+ uint256 limit = NUMBER_UNSHIFTED + $LOG_N + LIBRA_COMMITMENTS + 3;
3079
+
3080
+ // Validate all points are on the curve
3081
+ for (uint256 i = 0; i < limit; ++i) {
3082
+ validateOnCurve(base[i]);
3083
+ }
3084
+
3085
+ bool success = true;
3086
+ assembly {
3087
+ let free := mload(0x40)
3088
+
3089
+ let count := 0x01
3090
+ for {} lt(count, add(limit, 1)) {
3091
+ count := add(count, 1)
3092
+ } {
3093
+ // Get loop offsets
3094
+ let base_base := add(base, mul(count, 0x20))
3095
+ let scalar_base := add(scalars, mul(count, 0x20))
3096
+
3097
+ mstore(add(free, 0x40), mload(mload(base_base)))
3098
+ mstore(add(free, 0x60), mload(add(0x20, mload(base_base))))
3099
+ // Add scalar
3100
+ mstore(add(free, 0x80), mload(scalar_base))
3101
+
3102
+ success := and(
3103
+ success,
3104
+ staticcall(
3105
+ gas(),
3106
+ 7,
3107
+ add(free, 0x40),
3108
+ 0x60,
3109
+ add(free, 0x40),
3110
+ 0x40
3111
+ )
3112
+ )
3113
+ // accumulator = accumulator + accumulator_2
3114
+ success := and(
3115
+ success,
3116
+ staticcall(gas(), 6, free, 0x80, free, 0x40)
3117
+ )
3118
+ }
3119
+
3120
+ // Return the result
3121
+ mstore(result, mload(free))
3122
+ mstore(add(result, 0x20), mload(add(free, 0x20)))
3123
+ }
3124
+
3125
+ require(success, ShpleminiFailed());
3126
+ }
3127
+ }
3128
+
3129
+ contract DkgPkVerifier is
3130
+ BaseZKHonkVerifier(N, LOG_N, VK_HASH, NUMBER_OF_PUBLIC_INPUTS)
3131
+ {
3132
+ function loadVerificationKey()
3133
+ internal
3134
+ pure
3135
+ override
3136
+ returns (Honk.VerificationKey memory)
3137
+ {
3138
+ return HonkVerificationKey.loadVerificationKey();
3139
+ }
3140
+ }