@aztec/ivc-integration 1.2.1 → 2.0.0-nightly.20250813

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 (36) hide show
  1. package/artifacts/app_creator.json +1 -1
  2. package/artifacts/app_reader.json +1 -1
  3. package/artifacts/keys/app_creator.vk.data.json +115 -115
  4. package/artifacts/keys/app_reader.vk.data.json +115 -115
  5. package/artifacts/keys/mock_private_kernel_init.vk.data.json +120 -120
  6. package/artifacts/keys/mock_private_kernel_inner.vk.data.json +120 -120
  7. package/artifacts/keys/mock_private_kernel_reset.vk.data.json +120 -120
  8. package/artifacts/keys/mock_private_kernel_tail.ivc.vk +0 -0
  9. package/artifacts/keys/mock_private_kernel_tail.vk.data.json +120 -120
  10. package/artifacts/keys/mock_rollup_base_private.vk.data.json +94 -92
  11. package/artifacts/keys/mock_rollup_base_public.vk.data.json +94 -92
  12. package/artifacts/keys/mock_rollup_merge.vk.data.json +94 -92
  13. package/artifacts/keys/mock_rollup_root.vk.data.json +56 -108
  14. package/artifacts/keys/mock_rollup_root_verifier.sol +690 -412
  15. package/artifacts/mock_private_kernel_init.json +1 -1
  16. package/artifacts/mock_private_kernel_inner.json +1 -1
  17. package/artifacts/mock_private_kernel_reset.json +1 -1
  18. package/artifacts/mock_private_kernel_tail.json +1 -1
  19. package/artifacts/mock_rollup_base_private.json +1 -1
  20. package/artifacts/mock_rollup_base_public.json +1 -1
  21. package/artifacts/mock_rollup_merge.json +1 -1
  22. package/artifacts/mock_rollup_root.json +1 -1
  23. package/dest/prove_native.d.ts +1 -1
  24. package/dest/prove_wasm.d.ts +2 -2
  25. package/dest/prove_wasm.d.ts.map +1 -1
  26. package/dest/prove_wasm.js +4 -4
  27. package/dest/serve.js +2 -2
  28. package/dest/types/index.d.ts +2 -2
  29. package/dest/witgen.d.ts +2 -2
  30. package/dest/witgen.d.ts.map +1 -1
  31. package/dest/witgen.js +2 -2
  32. package/package.json +16 -16
  33. package/src/prove_wasm.ts +10 -2
  34. package/src/serve.ts +2 -2
  35. package/src/types/index.ts +2 -2
  36. package/src/witgen.ts +3 -3
@@ -5,6 +5,7 @@ pragma solidity >=0.8.21;
5
5
  uint256 constant N = 33554432;
6
6
  uint256 constant LOG_N = 25;
7
7
  uint256 constant NUMBER_OF_PUBLIC_INPUTS = 17;
8
+ uint256 constant VK_HASH = 0x1dedc46076638a43e3e87dccb659de3526d6cd94f5c7c4231b3f4e5bce79531b;
8
9
  library HonkVerificationKey {
9
10
  function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) {
10
11
  Honk.VerificationKey memory vk = Honk.VerificationKey({
@@ -12,72 +13,76 @@ library HonkVerificationKey {
12
13
  logCircuitSize: uint256(25),
13
14
  publicInputsSize: uint256(17),
14
15
  ql: Honk.G1Point({
15
- x: uint256(0x1213f7d2c0341c6a0e9f9c1039681356a5830e39413fd727cb4dfbfbe5485e3a),
16
- y: uint256(0x0469dd35956ac88de5160254fc0541bd6baecd8746e4070415be849b4ec7ca9b)
16
+ x: uint256(0x0c60b18c1ec8931d1840b9f11a36c44d2e7da517918c0415b7df490c5502fda8),
17
+ y: uint256(0x0b8ece93dfa56a4771be75be6555d227ae201bd3eea78ac86a87234c68812063)
17
18
  }),
18
19
  qr: Honk.G1Point({
19
- x: uint256(0x28856053b4624e25fd3a15b73523cba6b07f3c81d6325d7ef9fb2b0aeaffa727),
20
- y: uint256(0x0e4d093300265e6a9cea43e5809d6c45d6f3d9a97b1f47f364b91e0acfe33031)
20
+ x: uint256(0x06cd1d8188c7542849ef57e9cc8893473a712a6da6afa963eb8ee58de227b8b9),
21
+ y: uint256(0x1104e48d2014827b6b0e4bb5d5559319661ce7cc3565112a9d0e1b2fa2e30317)
21
22
  }),
22
23
  qo: Honk.G1Point({
23
- x: uint256(0x22eca78cfa4f01236320fa4ad44585649e0efef638cd72aa9e8c66747eb9321b),
24
- y: uint256(0x06516bf8a0859e0613ebce577d6879600364c64f72e209ed5d99ea57fb04de6a)
24
+ x: uint256(0x2f34d57f61daf01f4b9c1ef7d487f2b7b1836c9591424f005ba60ab95b3ef2ed),
25
+ y: uint256(0x2999e6f81261661d0962b31ff1d9f8bdc2d7ca8c2148b88282489e61e5360c28)
25
26
  }),
26
27
  q4: Honk.G1Point({
27
- x: uint256(0x2d514a28fc5b72fbf6faf29eff1bcc7dc1c51e60fb8ab8dc4a25f25c7b3c4be6),
28
- y: uint256(0x0a76e5ff708b342bac4078c59c2e7dde5ad6d5437fa2ad89c20936dd0b988f22)
28
+ x: uint256(0x1418fea5a0faa2ee54bf0248bd9ac390bbcacbc2996fefcc9bb4a6ba9dfd0260),
29
+ y: uint256(0x19fc8df0bcb4e09e25fd42c1926c5c7764d649b5cfd09c99e9dc051708fe61de)
29
30
  }),
30
31
  qm: Honk.G1Point({
31
- x: uint256(0x0ad7d8c7c736c4794943483ba77e4a2bef9ffd79c513f898b7be226a3a787265),
32
- y: uint256(0x2adbac1918fc5ea6d1abf847fc4d489b7c84c19a6a0adc964a924c607bbb664f)
32
+ x: uint256(0x2b4c9105b249d59815ecfa0a434c0d50f53739b3e0e27c75f9c3465b94f404db),
33
+ y: uint256(0x075c114babc04dcb4434585245be91f4fb30089f9e0fa8c4396d0899a746cd72)
33
34
  }),
34
35
  qc: Honk.G1Point({
35
- x: uint256(0x085d83856665f18b23b34365f1e8771f5a68299520c41f490fa5362a1d3b9a96),
36
- y: uint256(0x182a7219bcf5058a75aca939fbf0988f84b481fbdcacb3a9a2cd9f6ff5dfaa3b)
36
+ x: uint256(0x22ca8ad1d3239e920593662bc722ac69a1221b418cb13a1427142cdcb7331f1f),
37
+ y: uint256(0x0e45ff683339694e9f9a974fda1b976786a7cedef64effd3f174a8e7356df391)
38
+ }),
39
+ qLookup: Honk.G1Point({
40
+ x: uint256(0x0c4032c3079594eb75a8449d3d5ce8bc3661650d53f9b24d923d8f404cb0bbc9),
41
+ y: uint256(0x1084d709650356d40f0158fd6da81f54eb5fe796a0ca89441369b7c24301f851)
37
42
  }),
38
43
  qArith: Honk.G1Point({
39
- x: uint256(0x130a2cfdfcb0e0f4c3b69de2f5ee1c88ece12fc58ee3bf21bb741783b76cab8e),
40
- y: uint256(0x2a5f55bd35966e656447913a7a8fd5784843acd6da729b8140e233966b9e4711)
44
+ x: uint256(0x093cb4bb0b070139f3d1c6453dcc91e3b90706a60f383e4019fbbbc55f915593),
45
+ y: uint256(0x147b519bb194c3a0aab2193458b8a698136120695c10611e005fc52c5c62a810)
41
46
  }),
42
47
  qDeltaRange: Honk.G1Point({
43
- x: uint256(0x0f2825aa771b429a1ec00eac71705429c7c6ef5cd7b968f9bc1791d2530cc5d4),
44
- y: uint256(0x299291ac5ab2581fd0803b5232ff5cf71752f0c6880c4fe7493d4022af70cecb)
48
+ x: uint256(0x09314af86e789e03f6a4f885695305d59653d9dd77212d5d274cd2496d1fdd89),
49
+ y: uint256(0x18e29c2f6bf780beec6a0aa6ca5656e05cb888af61bc11690167176932720269)
45
50
  }),
46
51
  qElliptic: Honk.G1Point({
47
- x: uint256(0x02f95fdc9a38fc1c0db1f16bc1d716e8605f5269d5f51bd86cb5c4e4ceb01478),
48
- y: uint256(0x1494accf9b6033dba86c6010ae79cae575aa931d156af0fd94743bfbfa7cf573)
52
+ x: uint256(0x144cec3ddc9fdb04e1b743e1796d4497481b288bcb5662c8a814a36c91bba8a0),
53
+ y: uint256(0x1d44c2a0edb5be481f690aec0ec7b4d7d87fd015b326489b27c84b3395d52ada)
49
54
  }),
50
- qAux: Honk.G1Point({
51
- x: uint256(0x0dec7ad1aff55582269fddbbe12ad999713a2ae5712db4f4b4f33467b92be082),
52
- y: uint256(0x0d4942217ec350bad2b59e8888ac8041265b456f60edc3fea240ea4e72c197bf)
55
+ qMemory: Honk.G1Point({
56
+ x: uint256(0x1e32e3ddee17d0311af427f8a0c8c93ec03ee2552422e518956c914986f265ae),
57
+ y: uint256(0x21c1a895c48d67a0806a93b3b0c10e328cb81ac4d9770751d6d5034d765f2e75)
53
58
  }),
54
- qLookup: Honk.G1Point({
55
- x: uint256(0x0c4032c3079594eb75a8449d3d5ce8bc3661650d53f9b24d923d8f404cb0bbc9),
56
- y: uint256(0x1084d709650356d40f0158fd6da81f54eb5fe796a0ca89441369b7c24301f851)
59
+ qNnf: Honk.G1Point({
60
+ x: uint256(0x0d1378ced79a95272e49ca049e2d78a65681cf80bbe9b787bd2c086d4faf0236),
61
+ y: uint256(0x11e74523e66d06f858126bc5f3ddec4fc024ae8ebccedb2c782cfe3470a14f0d)
57
62
  }),
58
63
  qPoseidon2External: Honk.G1Point({
59
- x: uint256(0x2f21534cc373d5caef69db5248588a5a2c4135671cc44f4e45e525f89d3ff021),
60
- y: uint256(0x24bcb7d4ecdfb3721b53a90b1c3b19f5b87d0a30d141d9a5c1302125eb0d6715)
64
+ x: uint256(0x175ce7120e83243b00df020161b054ee52cef7e5c43ae9ed68d3ec1c31577e09),
65
+ y: uint256(0x014b2421ff7e799e69cd24e4ed9bf0b4c38b3f1bfede670cfd0a1bc143534c44)
61
66
  }),
62
67
  qPoseidon2Internal: Honk.G1Point({
63
- x: uint256(0x2ba1e3f38516f401b99d17d33e563e9555632f5404349db8b97fd62c76d53eca),
64
- y: uint256(0x006ff274711fb1107e6271ebb0e90a1ac8d52d4285112e1ff741770e31b77c88)
68
+ x: uint256(0x103f2560ed9a91a0d4dffa3ba8602815aa588ff32b5747719c0e6210240fc6f5),
69
+ y: uint256(0x2b28cd08de4e88139da28d5ce5a7ebd5e465a873d0b6069d40a9907adb9401fb)
65
70
  }),
66
71
  s1: Honk.G1Point({
67
- x: uint256(0x28fa85bc017e5fba790d8cfd43390e81fee45d088ffc4e0edc22fa6dad7ddbb2),
68
- y: uint256(0x222e4b865225737e92fb44cdbe8c5ddd87f8f86ee7283c6d808a416b103564df)
72
+ x: uint256(0x1effc069e3b7481d0a43665103f4a2680f4b65f53a59021953ab20862b24e29a),
73
+ y: uint256(0x00ae13c105d82c1ff5ca3cdd30c912e6fb24afb1893dd12f9c145a6c33ac6185)
69
74
  }),
70
75
  s2: Honk.G1Point({
71
- x: uint256(0x228576388b71ccfa4bd3c2fb168a62d51537af6c0a531efb723f25583d85d9a7),
72
- y: uint256(0x026bee612b55342f9778c219a6a79f62da559c77e0bf4b3306be29aad76600f2)
76
+ x: uint256(0x0f7f10529e5aae1e1e112792aa80e7707906f4f536fc96ffc7bc25774e9dba11),
77
+ y: uint256(0x2d1811e9ffa00409d48af6eeff991c6866765fcffd1863160c5c485c7bb6e923)
73
78
  }),
74
79
  s3: Honk.G1Point({
75
- x: uint256(0x22c1edc91013958cb7f238b321adf39cb653b33f82c78bf576bd613c0d7daa8a),
76
- y: uint256(0x023998a7d86fd915a50ab4da3bb76ccd25578bad7e127b7ca20c78bfdddde159)
80
+ x: uint256(0x257ee866e0c29c215e6379e784c662b59c214d687a0363934ef9c5c0a3331e59),
81
+ y: uint256(0x2f06bdee150a0dce94e73d65c819a345d07f4d146213d766b570bf2d82675078)
77
82
  }),
78
83
  s4: Honk.G1Point({
79
- x: uint256(0x26d828bdc943640f45ddf7736bbeae206ed47270967c7e6cf10b8c67d422be0c),
80
- y: uint256(0x00441afea684bdef5cbbfd0498eec4006249e9ee0d4bfdc120375825a88f4275)
84
+ x: uint256(0x1ec20ff0cfe053242bf60e957c106cfb1be5474d6b5f519c03ea9b494313b81d),
85
+ y: uint256(0x2ae607491a047d4905eb6b725c35e0fa2e393bdc1ce7b4b07832c77fdd1788b4)
81
86
  }),
82
87
  t1: Honk.G1Point({
83
88
  x: uint256(0x0450f8716810dff987300c3bc10a892b1c1c2637db3f8fecd9d8bb38442cc468),
@@ -88,36 +93,36 @@ library HonkVerificationKey {
88
93
  y: uint256(0x0c5d6e7a8b0b14d4ed8f51217ae8af4207277f4116e0af5a9268b38a5d34910b)
89
94
  }),
90
95
  t3: Honk.G1Point({
91
- x: uint256(0x187b9371870f579be414054241d418f5689db2f6cbfabe968378fd68e9b280c0),
92
- y: uint256(0x0964ab30f99cb72cc59d0f621604926cfebfcff535f724f619bb0e7a4853dbdb)
96
+ x: uint256(0x0924c2d3fa7bd443b6244e3f29179883c120acb66ce414b5147c31531392c530),
97
+ y: uint256(0x07e5e59aa353dc977d4e082214179998a8086106f1eaaf33ee0b012cbd77066f)
93
98
  }),
94
99
  t4: Honk.G1Point({
95
100
  x: uint256(0x132b76a71278e567595f3aaf837a72eb0ab515191143e5a3c8bd587526486628),
96
101
  y: uint256(0x2c6b2a0de0a3fefdfc4fb4f3b8381d2c37ccc495848c2887f98bfbaca776ca39)
97
102
  }),
98
103
  id1: Honk.G1Point({
99
- x: uint256(0x2ef40d11ac56d2ed8e03d31dc521f078f5e866cbde645f9eb678dfcd12066203),
100
- y: uint256(0x2019d7eb7fa2879ca7fc0c2319f8b4bc70b1ed31afe502744cf60aeb12f23491)
104
+ x: uint256(0x19f9495c2d7164bf4ffab93784be18f18967a11e13a767be733f5bef9d114231),
105
+ y: uint256(0x11d56b79e7120211adec0d6b193584d9334f869a77a5ef4a29fe921c0d736469)
101
106
  }),
102
107
  id2: Honk.G1Point({
103
- x: uint256(0x18eb9555275923fa7cc3a81375b61b42f7a3926f6578ec658b69bf401fca0217),
104
- y: uint256(0x22e5b72ce43640eec1ee08579b19b91ada1f87b9778e9b870ea3a98c6c79f0c0)
108
+ x: uint256(0x09843d6144239130855e359ebd182f506f038d894d75d4e670905e1ffcda9604),
109
+ y: uint256(0x0ec072a3e7b76b24db376094d63714c6627409d02b367881ae052a33fc4fdbcf)
105
110
  }),
106
111
  id3: Honk.G1Point({
107
- x: uint256(0x10e810f71b5f83ffe9b5307026b3ba3733de54a3c95957e558ed66028c32a139),
108
- y: uint256(0x185198d898c3e0db1ccf50ca9bdb467dcbe2424fcaf0f1a72dce1446d260cb6c)
112
+ x: uint256(0x277c18d61cf5c0872161a3223757324ce2ecc98f1dc98d03de20012b4d776ac8),
113
+ y: uint256(0x21591d35c338d60b8de7b9290653dcbd2c04e93c583791f6de6a2248905a224e)
109
114
  }),
110
115
  id4: Honk.G1Point({
111
- x: uint256(0x07b76b964b515ad4f0800bd4a9c4d6c752fccb6c48324322c1593fc387a88ab7),
112
- y: uint256(0x0271cb1e74de6ff3b23e8050962297d37a4fdea9b3b3eb8560776eb1090313a1)
116
+ x: uint256(0x2099170826e2cd5623c5f84808a673a34c8f3d652c1287f063e487db383940e5),
117
+ y: uint256(0x044349c5d22add7bf66a6d868e07cd83cb082165210033e64a748b0ef89c6a3b)
113
118
  }),
114
119
  lagrangeFirst: Honk.G1Point({
115
120
  x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001),
116
121
  y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002)
117
122
  }),
118
123
  lagrangeLast: Honk.G1Point({
119
- x: uint256(0x0e65125738a0d2558d62fd9facb705bae323a4e2936b098a1114e842246637ef),
120
- y: uint256(0x076de57c973ec9b9d5a46b63be972750c24628c1c58228e14349ffda833a7173)
124
+ x: uint256(0x3003e58cfbf4356eb3ed44fae37fa59ffb7f3aec9716c9a907c4066919f7c8d2),
125
+ y: uint256(0x26c6924d7409782397d7b873c141a2e20a1b3e185c2b454b06ce3a6fea22773f)
121
126
  })
122
127
  });
123
128
  return vk;
@@ -152,15 +157,21 @@ Fr constant ZERO = Fr.wrap(0);
152
157
 
153
158
  library FrLib {
154
159
  function from(uint256 value) internal pure returns (Fr) {
155
- return Fr.wrap(value % MODULUS);
160
+ unchecked {
161
+ return Fr.wrap(value % MODULUS);
162
+ }
156
163
  }
157
164
 
158
165
  function fromBytes32(bytes32 value) internal pure returns (Fr) {
159
- return Fr.wrap(uint256(value) % MODULUS);
166
+ unchecked {
167
+ return Fr.wrap(uint256(value) % MODULUS);
168
+ }
160
169
  }
161
170
 
162
171
  function toBytes32(Fr value) internal pure returns (bytes32) {
163
- return bytes32(Fr.unwrap(value));
172
+ unchecked {
173
+ return bytes32(Fr.unwrap(value));
174
+ }
164
175
  }
165
176
 
166
177
  function invert(Fr value) internal view returns (Fr) {
@@ -181,6 +192,7 @@ library FrLib {
181
192
  revert(0, 0)
182
193
  }
183
194
  result := mload(0x00)
195
+ mstore(0x40, add(free, 0x80))
184
196
  }
185
197
 
186
198
  return Fr.wrap(result);
@@ -204,39 +216,54 @@ library FrLib {
204
216
  revert(0, 0)
205
217
  }
206
218
  result := mload(0x00)
219
+ mstore(0x40, add(free, 0x80))
207
220
  }
208
221
 
209
222
  return Fr.wrap(result);
210
223
  }
211
224
 
212
225
  function div(Fr numerator, Fr denominator) internal view returns (Fr) {
213
- return numerator * invert(denominator);
226
+ unchecked {
227
+ return numerator * invert(denominator);
228
+ }
214
229
  }
215
230
 
216
231
  function sqr(Fr value) internal pure returns (Fr) {
217
- return value * value;
232
+ unchecked {
233
+ return value * value;
234
+ }
218
235
  }
219
236
 
220
237
  function unwrap(Fr value) internal pure returns (uint256) {
221
- return Fr.unwrap(value);
238
+ unchecked {
239
+ return Fr.unwrap(value);
240
+ }
222
241
  }
223
242
 
224
243
  function neg(Fr value) internal pure returns (Fr) {
225
- return Fr.wrap(MODULUS - Fr.unwrap(value));
244
+ unchecked {
245
+ return Fr.wrap(MODULUS - Fr.unwrap(value));
246
+ }
226
247
  }
227
248
  }
228
249
 
229
250
  // Free functions
230
251
  function add(Fr a, Fr b) pure returns (Fr) {
231
- return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS));
252
+ unchecked {
253
+ return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS));
254
+ }
232
255
  }
233
256
 
234
257
  function mul(Fr a, Fr b) pure returns (Fr) {
235
- return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS));
258
+ unchecked {
259
+ return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS));
260
+ }
236
261
  }
237
262
 
238
263
  function sub(Fr a, Fr b) pure returns (Fr) {
239
- return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS));
264
+ unchecked {
265
+ return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS));
266
+ }
240
267
  }
241
268
 
242
269
  function exp(Fr base, Fr exponent) pure returns (Fr) {
@@ -249,25 +276,32 @@ function exp(Fr base, Fr exponent) pure returns (Fr) {
249
276
  }
250
277
 
251
278
  function notEqual(Fr a, Fr b) pure returns (bool) {
252
- return Fr.unwrap(a) != Fr.unwrap(b);
279
+ unchecked {
280
+ return Fr.unwrap(a) != Fr.unwrap(b);
281
+ }
253
282
  }
254
283
 
255
284
  function equal(Fr a, Fr b) pure returns (bool) {
256
- return Fr.unwrap(a) == Fr.unwrap(b);
285
+ unchecked {
286
+ return Fr.unwrap(a) == Fr.unwrap(b);
287
+ }
257
288
  }
258
289
 
259
290
  uint256 constant CONST_PROOF_SIZE_LOG_N = 28;
260
291
 
261
- uint256 constant NUMBER_OF_SUBRELATIONS = 27;
292
+ uint256 constant NUMBER_OF_SUBRELATIONS = 28;
262
293
  uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8;
263
294
  uint256 constant ZK_BATCHED_RELATION_PARTIAL_LENGTH = 9;
264
- uint256 constant NUMBER_OF_ENTITIES = 40;
265
- uint256 constant NUMBER_UNSHIFTED = 35;
295
+ uint256 constant NUMBER_OF_ENTITIES = 41;
296
+ uint256 constant NUMBER_UNSHIFTED = 36;
266
297
  uint256 constant NUMBER_TO_BE_SHIFTED = 5;
267
298
  uint256 constant PAIRING_POINTS_SIZE = 16;
268
299
 
300
+ uint256 constant FIELD_ELEMENT_SIZE = 0x20;
301
+ uint256 constant GROUP_ELEMENT_SIZE = 0x40;
302
+
269
303
  // Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1
270
- uint256 constant NUMBER_OF_ALPHAS = 26;
304
+ uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1;
271
305
 
272
306
  // ENUM FOR WIRES
273
307
  enum WIRE {
@@ -281,7 +315,8 @@ enum WIRE {
281
315
  Q_ARITH,
282
316
  Q_RANGE,
283
317
  Q_ELLIPTIC,
284
- Q_AUX,
318
+ Q_MEMORY,
319
+ Q_NNF,
285
320
  Q_POSEIDON2_EXTERNAL,
286
321
  Q_POSEIDON2_INTERNAL,
287
322
  SIGMA_1,
@@ -319,13 +354,6 @@ library Honk {
319
354
  uint256 y;
320
355
  }
321
356
 
322
- struct G1ProofPoint {
323
- uint256 x_0;
324
- uint256 x_1;
325
- uint256 y_0;
326
- uint256 y_1;
327
- }
328
-
329
357
  struct VerificationKey {
330
358
  // Misc Params
331
359
  uint256 circuitSize;
@@ -341,7 +369,8 @@ library Honk {
341
369
  G1Point qLookup; // Lookup
342
370
  G1Point qArith; // Arithmetic widget
343
371
  G1Point qDeltaRange; // Delta Range sort
344
- G1Point qAux; // Auxillary
372
+ G1Point qMemory; // Memory
373
+ G1Point qNnf; // Non-native Field
345
374
  G1Point qElliptic; // Auxillary
346
375
  G1Point qPoseidon2External;
347
376
  G1Point qPoseidon2Internal;
@@ -380,55 +409,55 @@ library Honk {
380
409
  // Pairing point object
381
410
  Fr[PAIRING_POINTS_SIZE] pairingPointObject;
382
411
  // Free wires
383
- Honk.G1ProofPoint w1;
384
- Honk.G1ProofPoint w2;
385
- Honk.G1ProofPoint w3;
386
- Honk.G1ProofPoint w4;
412
+ G1Point w1;
413
+ G1Point w2;
414
+ G1Point w3;
415
+ G1Point w4;
387
416
  // Lookup helpers - Permutations
388
- Honk.G1ProofPoint zPerm;
417
+ G1Point zPerm;
389
418
  // Lookup helpers - logup
390
- Honk.G1ProofPoint lookupReadCounts;
391
- Honk.G1ProofPoint lookupReadTags;
392
- Honk.G1ProofPoint lookupInverses;
419
+ G1Point lookupReadCounts;
420
+ G1Point lookupReadTags;
421
+ G1Point lookupInverses;
393
422
  // Sumcheck
394
423
  Fr[BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates;
395
424
  Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations;
396
425
  // Shplemini
397
- Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms;
426
+ G1Point[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms;
398
427
  Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations;
399
- Honk.G1ProofPoint shplonkQ;
400
- Honk.G1ProofPoint kzgQuotient;
428
+ G1Point shplonkQ;
429
+ G1Point kzgQuotient;
401
430
  }
402
431
 
403
432
  struct ZKProof {
404
433
  // Pairing point object
405
434
  Fr[PAIRING_POINTS_SIZE] pairingPointObject;
406
435
  // Commitments to wire polynomials
407
- Honk.G1ProofPoint w1;
408
- Honk.G1ProofPoint w2;
409
- Honk.G1ProofPoint w3;
410
- Honk.G1ProofPoint w4;
436
+ G1Point w1;
437
+ G1Point w2;
438
+ G1Point w3;
439
+ G1Point w4;
411
440
  // Commitments to logup witness polynomials
412
- Honk.G1ProofPoint lookupReadCounts;
413
- Honk.G1ProofPoint lookupReadTags;
414
- Honk.G1ProofPoint lookupInverses;
441
+ G1Point lookupReadCounts;
442
+ G1Point lookupReadTags;
443
+ G1Point lookupInverses;
415
444
  // Commitment to grand permutation polynomial
416
- Honk.G1ProofPoint zPerm;
417
- Honk.G1ProofPoint[3] libraCommitments;
445
+ G1Point zPerm;
446
+ G1Point[3] libraCommitments;
418
447
  // Sumcheck
419
448
  Fr libraSum;
420
449
  Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates;
421
450
  Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations;
422
451
  Fr libraEvaluation;
423
452
  // ZK
424
- Honk.G1ProofPoint geminiMaskingPoly;
453
+ G1Point geminiMaskingPoly;
425
454
  Fr geminiMaskingEval;
426
455
  // Shplemini
427
- Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms;
456
+ G1Point[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms;
428
457
  Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations;
429
458
  Fr[4] libraPolyEvals;
430
- Honk.G1ProofPoint shplonkQ;
431
- Honk.G1ProofPoint kzgQuotient;
459
+ G1Point shplonkQ;
460
+ G1Point kzgQuotient;
432
461
  }
433
462
  }
434
463
 
@@ -452,26 +481,25 @@ library TranscriptLib {
452
481
  function generateTranscript(
453
482
  Honk.Proof memory proof,
454
483
  bytes32[] calldata publicInputs,
455
- uint256 circuitSize,
484
+ uint256 vkHash,
456
485
  uint256 publicInputsSize,
457
- uint256 pubInputsOffset
458
- ) internal pure returns (Transcript memory t) {
486
+ uint256 logN
487
+ ) internal view returns (Transcript memory t) {
459
488
  Fr previousChallenge;
460
- (t.relationParameters, previousChallenge) = generateRelationParametersChallenges(
461
- proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge
462
- );
489
+ (t.relationParameters, previousChallenge) =
490
+ generateRelationParametersChallenges(proof, publicInputs, vkHash, publicInputsSize, previousChallenge);
463
491
 
464
492
  (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof);
465
493
 
466
- (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge);
494
+ (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge, logN);
467
495
 
468
- (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge);
496
+ (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge, logN);
469
497
 
470
498
  (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge);
471
499
 
472
- (t.geminiR, previousChallenge) = generateGeminiRChallenge(proof, previousChallenge);
500
+ (t.geminiR, previousChallenge) = generateGeminiRChallenge(proof, previousChallenge, logN);
473
501
 
474
- (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(proof, previousChallenge);
502
+ (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(proof, previousChallenge, logN);
475
503
 
476
504
  (t.shplonkZ, previousChallenge) = generateShplonkZChallenge(proof, previousChallenge);
477
505
 
@@ -489,13 +517,12 @@ library TranscriptLib {
489
517
  function generateRelationParametersChallenges(
490
518
  Honk.Proof memory proof,
491
519
  bytes32[] calldata publicInputs,
492
- uint256 circuitSize,
520
+ uint256 vkHash,
493
521
  uint256 publicInputsSize,
494
- uint256 pubInputsOffset,
495
522
  Fr previousChallenge
496
523
  ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) {
497
524
  (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) =
498
- generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset);
525
+ generateEtaChallenge(proof, publicInputs, vkHash, publicInputsSize);
499
526
 
500
527
  (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof);
501
528
  }
@@ -503,38 +530,31 @@ library TranscriptLib {
503
530
  function generateEtaChallenge(
504
531
  Honk.Proof memory proof,
505
532
  bytes32[] calldata publicInputs,
506
- uint256 circuitSize,
507
- uint256 publicInputsSize,
508
- uint256 pubInputsOffset
533
+ uint256 vkHash,
534
+ uint256 publicInputsSize
509
535
  ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) {
510
- bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12);
511
- round0[0] = bytes32(circuitSize);
512
- round0[1] = bytes32(publicInputsSize);
513
- round0[2] = bytes32(pubInputsOffset);
536
+ bytes32[] memory round0 = new bytes32[](1 + publicInputsSize + 6);
537
+ round0[0] = bytes32(vkHash);
538
+
514
539
  for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) {
515
- round0[3 + i] = bytes32(publicInputs[i]);
540
+ round0[1 + i] = bytes32(publicInputs[i]);
516
541
  }
517
542
  for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
518
- round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]);
543
+ round0[1 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]);
519
544
  }
520
545
 
521
546
  // Create the first challenge
522
547
  // Note: w4 is added to the challenge later on
523
- round0[3 + publicInputsSize] = bytes32(proof.w1.x_0);
524
- round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1);
525
- round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0);
526
- round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1);
527
- round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0);
528
- round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1);
529
- round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0);
530
- round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1);
531
- round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0);
532
- round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1);
533
- round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0);
534
- round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1);
548
+ round0[1 + publicInputsSize] = bytes32(proof.w1.x);
549
+ round0[1 + publicInputsSize + 1] = bytes32(proof.w1.y);
550
+ round0[1 + publicInputsSize + 2] = bytes32(proof.w2.x);
551
+ round0[1 + publicInputsSize + 3] = bytes32(proof.w2.y);
552
+ round0[1 + publicInputsSize + 4] = bytes32(proof.w3.x);
553
+ round0[1 + publicInputsSize + 5] = bytes32(proof.w3.y);
535
554
 
536
555
  previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0)));
537
556
  (eta, etaTwo) = splitChallenge(previousChallenge);
557
+
538
558
  previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge))));
539
559
  Fr unused;
540
560
  (etaThree, unused) = splitChallenge(previousChallenge);
@@ -545,20 +565,14 @@ library TranscriptLib {
545
565
  pure
546
566
  returns (Fr beta, Fr gamma, Fr nextPreviousChallenge)
547
567
  {
548
- bytes32[13] memory round1;
568
+ bytes32[7] memory round1;
549
569
  round1[0] = FrLib.toBytes32(previousChallenge);
550
- round1[1] = bytes32(proof.lookupReadCounts.x_0);
551
- round1[2] = bytes32(proof.lookupReadCounts.x_1);
552
- round1[3] = bytes32(proof.lookupReadCounts.y_0);
553
- round1[4] = bytes32(proof.lookupReadCounts.y_1);
554
- round1[5] = bytes32(proof.lookupReadTags.x_0);
555
- round1[6] = bytes32(proof.lookupReadTags.x_1);
556
- round1[7] = bytes32(proof.lookupReadTags.y_0);
557
- round1[8] = bytes32(proof.lookupReadTags.y_1);
558
- round1[9] = bytes32(proof.w4.x_0);
559
- round1[10] = bytes32(proof.w4.x_1);
560
- round1[11] = bytes32(proof.w4.y_0);
561
- round1[12] = bytes32(proof.w4.y_1);
570
+ round1[1] = bytes32(proof.lookupReadCounts.x);
571
+ round1[2] = bytes32(proof.lookupReadCounts.y);
572
+ round1[3] = bytes32(proof.lookupReadTags.x);
573
+ round1[4] = bytes32(proof.lookupReadTags.y);
574
+ round1[5] = bytes32(proof.w4.x);
575
+ round1[6] = bytes32(proof.w4.y);
562
576
 
563
577
  nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1)));
564
578
  (beta, gamma) = splitChallenge(nextPreviousChallenge);
@@ -571,16 +585,12 @@ library TranscriptLib {
571
585
  returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge)
572
586
  {
573
587
  // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup
574
- uint256[9] memory alpha0;
588
+ uint256[5] memory alpha0;
575
589
  alpha0[0] = Fr.unwrap(previousChallenge);
576
- alpha0[1] = proof.lookupInverses.x_0;
577
- alpha0[2] = proof.lookupInverses.x_1;
578
- alpha0[3] = proof.lookupInverses.y_0;
579
- alpha0[4] = proof.lookupInverses.y_1;
580
- alpha0[5] = proof.zPerm.x_0;
581
- alpha0[6] = proof.zPerm.x_1;
582
- alpha0[7] = proof.zPerm.y_0;
583
- alpha0[8] = proof.zPerm.y_1;
590
+ alpha0[1] = proof.lookupInverses.x;
591
+ alpha0[2] = proof.lookupInverses.y;
592
+ alpha0[3] = proof.zPerm.x;
593
+ alpha0[4] = proof.zPerm.y;
584
594
 
585
595
  nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0)));
586
596
  (alphas[0], alphas[1]) = splitChallenge(nextPreviousChallenge);
@@ -596,12 +606,12 @@ library TranscriptLib {
596
606
  }
597
607
  }
598
608
 
599
- function generateGateChallenges(Fr previousChallenge)
609
+ function generateGateChallenges(Fr previousChallenge, uint256 logN)
600
610
  internal
601
611
  pure
602
612
  returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge)
603
613
  {
604
- for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) {
614
+ for (uint256 i = 0; i < logN; i++) {
605
615
  previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge))));
606
616
  Fr unused;
607
617
  (gateChallenges[i], unused) = splitChallenge(previousChallenge);
@@ -609,12 +619,12 @@ library TranscriptLib {
609
619
  nextPreviousChallenge = previousChallenge;
610
620
  }
611
621
 
612
- function generateSumcheckChallenges(Honk.Proof memory proof, Fr prevChallenge)
622
+ function generateSumcheckChallenges(Honk.Proof memory proof, Fr prevChallenge, uint256 logN)
613
623
  internal
614
624
  pure
615
625
  returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge)
616
626
  {
617
- for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) {
627
+ for (uint256 i = 0; i < logN; i++) {
618
628
  Fr[BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal;
619
629
  univariateChal[0] = prevChallenge;
620
630
 
@@ -645,19 +655,17 @@ library TranscriptLib {
645
655
  (rho, unused) = splitChallenge(nextPreviousChallenge);
646
656
  }
647
657
 
648
- function generateGeminiRChallenge(Honk.Proof memory proof, Fr prevChallenge)
658
+ function generateGeminiRChallenge(Honk.Proof memory proof, Fr prevChallenge, uint256 logN)
649
659
  internal
650
660
  pure
651
661
  returns (Fr geminiR, Fr nextPreviousChallenge)
652
662
  {
653
- uint256[(CONST_PROOF_SIZE_LOG_N - 1) * 4 + 1] memory gR;
663
+ uint256[] memory gR = new uint256[]((logN - 1) * 2 + 1);
654
664
  gR[0] = Fr.unwrap(prevChallenge);
655
665
 
656
- for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) {
657
- gR[1 + i * 4] = proof.geminiFoldComms[i].x_0;
658
- gR[2 + i * 4] = proof.geminiFoldComms[i].x_1;
659
- gR[3 + i * 4] = proof.geminiFoldComms[i].y_0;
660
- gR[4 + i * 4] = proof.geminiFoldComms[i].y_1;
666
+ for (uint256 i = 0; i < logN - 1; i++) {
667
+ gR[1 + i * 2] = proof.geminiFoldComms[i].x;
668
+ gR[2 + i * 2] = proof.geminiFoldComms[i].y;
661
669
  }
662
670
 
663
671
  nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR)));
@@ -665,15 +673,15 @@ library TranscriptLib {
665
673
  (geminiR, unused) = splitChallenge(nextPreviousChallenge);
666
674
  }
667
675
 
668
- function generateShplonkNuChallenge(Honk.Proof memory proof, Fr prevChallenge)
676
+ function generateShplonkNuChallenge(Honk.Proof memory proof, Fr prevChallenge, uint256 logN)
669
677
  internal
670
678
  pure
671
679
  returns (Fr shplonkNu, Fr nextPreviousChallenge)
672
680
  {
673
- uint256[(CONST_PROOF_SIZE_LOG_N) + 1] memory shplonkNuChallengeElements;
681
+ uint256[] memory shplonkNuChallengeElements = new uint256[](logN + 1);
674
682
  shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge);
675
683
 
676
- for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) {
684
+ for (uint256 i = 0; i < logN; i++) {
677
685
  shplonkNuChallengeElements[i + 1] = Fr.unwrap(proof.geminiAEvaluations[i]);
678
686
  }
679
687
 
@@ -684,81 +692,79 @@ library TranscriptLib {
684
692
 
685
693
  function generateShplonkZChallenge(Honk.Proof memory proof, Fr prevChallenge)
686
694
  internal
687
- pure
695
+ view
688
696
  returns (Fr shplonkZ, Fr nextPreviousChallenge)
689
697
  {
690
- uint256[5] memory shplonkZChallengeElements;
698
+ uint256[3] memory shplonkZChallengeElements;
691
699
  shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge);
692
700
 
693
- shplonkZChallengeElements[1] = proof.shplonkQ.x_0;
694
- shplonkZChallengeElements[2] = proof.shplonkQ.x_1;
695
- shplonkZChallengeElements[3] = proof.shplonkQ.y_0;
696
- shplonkZChallengeElements[4] = proof.shplonkQ.y_1;
701
+ shplonkZChallengeElements[1] = proof.shplonkQ.x;
702
+ shplonkZChallengeElements[2] = proof.shplonkQ.y;
697
703
 
698
704
  nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements)));
699
705
  Fr unused;
700
706
  (shplonkZ, unused) = splitChallenge(nextPreviousChallenge);
701
707
  }
702
708
 
703
- function loadProof(bytes calldata proof) internal pure returns (Honk.Proof memory p) {
704
- uint256 boundary = 0x0;
709
+ function loadProof(bytes calldata proof, uint256 logN) internal pure returns (Honk.Proof memory p) {
710
+ uint256 boundary = 0x00;
705
711
 
706
712
  // Pairing point object
707
713
  for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
708
- p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + 0x20]);
709
- boundary += 0x20;
714
+ p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
715
+ boundary += FIELD_ELEMENT_SIZE;
710
716
  }
711
717
  // Commitments
712
- p.w1 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
713
- boundary += 0x80;
714
- p.w2 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
715
- boundary += 0x80;
716
- p.w3 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
717
- boundary += 0x80;
718
+ p.w1 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
719
+ boundary += GROUP_ELEMENT_SIZE;
720
+ p.w2 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
721
+ boundary += GROUP_ELEMENT_SIZE;
722
+ p.w3 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
723
+ boundary += GROUP_ELEMENT_SIZE;
718
724
 
719
725
  // Lookup / Permutation Helper Commitments
720
- p.lookupReadCounts = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
721
- boundary += 0x80;
722
- p.lookupReadTags = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
723
- boundary += 0x80;
724
- p.w4 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
725
- boundary += 0x80;
726
- p.lookupInverses = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
727
- boundary += 0x80;
728
- p.zPerm = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
729
- boundary += 0x80;
726
+ p.lookupReadCounts = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
727
+ boundary += GROUP_ELEMENT_SIZE;
728
+ p.lookupReadTags = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
729
+ boundary += GROUP_ELEMENT_SIZE;
730
+ p.w4 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
731
+ boundary += GROUP_ELEMENT_SIZE;
732
+ p.lookupInverses = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
733
+ boundary += GROUP_ELEMENT_SIZE;
734
+ p.zPerm = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
735
+ boundary += GROUP_ELEMENT_SIZE;
730
736
 
731
737
  // Sumcheck univariates
732
- for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) {
738
+ for (uint256 i = 0; i < logN; i++) {
733
739
  for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) {
734
- p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + 0x20]);
735
- boundary += 0x20;
740
+ p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
741
+ boundary += FIELD_ELEMENT_SIZE;
736
742
  }
737
743
  }
738
744
  // Sumcheck evaluations
739
745
  for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) {
740
- p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]);
741
- boundary += 0x20;
746
+ p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
747
+ boundary += FIELD_ELEMENT_SIZE;
742
748
  }
743
749
 
744
750
  // Gemini
745
751
  // Read gemini fold univariates
746
- for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) {
747
- p.geminiFoldComms[i] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
748
- boundary += 0x80;
752
+ for (uint256 i = 0; i < logN - 1; i++) {
753
+ p.geminiFoldComms[i] = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
754
+ boundary += GROUP_ELEMENT_SIZE;
749
755
  }
750
756
 
751
757
  // Read gemini a evaluations
752
- for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) {
753
- p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]);
754
- boundary += 0x20;
758
+ for (uint256 i = 0; i < logN; i++) {
759
+ p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
760
+ boundary += FIELD_ELEMENT_SIZE;
755
761
  }
756
762
 
757
763
  // Shplonk
758
- p.shplonkQ = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
759
- boundary += 0x80;
764
+ p.shplonkQ = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
765
+ boundary += GROUP_ELEMENT_SIZE;
760
766
  // KZG
761
- p.kzgQuotient = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]);
767
+ p.kzgQuotient = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
762
768
  }
763
769
  }
764
770
 
@@ -781,7 +787,8 @@ library RelationsLib {
781
787
  accumulateLogDerivativeLookupRelation(purportedEvaluations, rp, evaluations, powPartialEval);
782
788
  accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval);
783
789
  accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval);
784
- accumulateAuxillaryRelation(purportedEvaluations, rp, evaluations, powPartialEval);
790
+ accumulateMemoryRelation(purportedEvaluations, rp, evaluations, powPartialEval);
791
+ accumulateNnfRelation(purportedEvaluations, evaluations, powPartialEval);
785
792
  accumulatePoseidonExternalRelation(purportedEvaluations, evaluations, powPartialEval);
786
793
  accumulatePoseidonInternalRelation(purportedEvaluations, evaluations, powPartialEval);
787
794
  // batch the subrelations with the alpha challenges to obtain the full honk relation
@@ -1066,19 +1073,9 @@ library RelationsLib {
1066
1073
  }
1067
1074
  }
1068
1075
 
1069
- // Constants for the auxiliary relation
1070
- Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68);
1071
- Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14);
1072
-
1073
- // Parameters used within the Auxiliary Relation
1076
+ // Parameters used within the Memory Relation
1074
1077
  // A struct is used to work around stack too deep. This relation has alot of variables
1075
- struct AuxParams {
1076
- Fr limb_subproduct;
1077
- Fr non_native_field_gate_1;
1078
- Fr non_native_field_gate_2;
1079
- Fr non_native_field_gate_3;
1080
- Fr limb_accumulator_1;
1081
- Fr limb_accumulator_2;
1078
+ struct MemParams {
1082
1079
  Fr memory_record_check;
1083
1080
  Fr partial_record_check;
1084
1081
  Fr next_gate_access_type;
@@ -1094,80 +1091,15 @@ library RelationsLib {
1094
1091
  Fr RAM_timestamp_check_identity;
1095
1092
  Fr memory_identity;
1096
1093
  Fr index_is_monotonically_increasing;
1097
- Fr auxiliary_identity;
1098
1094
  }
1099
1095
 
1100
- function accumulateAuxillaryRelation(
1096
+ function accumulateMemoryRelation(
1101
1097
  Fr[NUMBER_OF_ENTITIES] memory p,
1102
1098
  Honk.RelationParameters memory rp,
1103
1099
  Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1104
1100
  Fr domainSep
1105
1101
  ) internal pure {
1106
- AuxParams memory ap;
1107
-
1108
- /**
1109
- * Contribution 12
1110
- * Non native field arithmetic gate 2
1111
- * deg 4
1112
- *
1113
- * _ _
1114
- * / _ _ _ 14 \
1115
- * 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 |
1116
- * \_ _/
1117
- *
1118
- *
1119
- */
1120
- ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R);
1121
- ap.non_native_field_gate_2 =
1122
- (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT));
1123
- ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE;
1124
- ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT);
1125
- ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct;
1126
- ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4);
1127
-
1128
- ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE;
1129
- ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT));
1130
- ap.non_native_field_gate_1 = ap.limb_subproduct;
1131
- ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4));
1132
- ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O);
1133
-
1134
- ap.non_native_field_gate_3 = ap.limb_subproduct;
1135
- ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4);
1136
- ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT));
1137
- ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M);
1138
-
1139
- Fr non_native_field_identity =
1140
- ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3;
1141
- non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R);
1142
-
1143
- // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm
1144
- // deg 2
1145
- ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT;
1146
- ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT);
1147
- ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT;
1148
- ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O);
1149
- ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT;
1150
- ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R);
1151
- ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT;
1152
- ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L);
1153
- ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4);
1154
- ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4);
1155
-
1156
- // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm
1157
- // deg 2
1158
- ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT;
1159
- ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT);
1160
- ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT;
1161
- ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT);
1162
- ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT;
1163
- ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4);
1164
- ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT;
1165
- ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O);
1166
- ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT);
1167
- ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M);
1168
-
1169
- Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2;
1170
- limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3
1102
+ MemParams memory ap;
1171
1103
 
1172
1104
  /**
1173
1105
  * MEMORY
@@ -1241,9 +1173,9 @@ library RelationsLib {
1241
1173
  ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + ONE) * ap.record_delta; // deg 2
1242
1174
 
1243
1175
  evals[14] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R))
1244
- * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5
1176
+ * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5
1245
1177
  evals[15] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R))
1246
- * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5
1178
+ * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5
1247
1179
 
1248
1180
  ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7
1249
1181
 
@@ -1290,11 +1222,11 @@ library RelationsLib {
1290
1222
 
1291
1223
  // Putting it all together...
1292
1224
  evals[16] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation
1293
- * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 or 8
1294
- evals[17] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4
1295
- evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 6
1225
+ * (wire(p, WIRE.Q_O)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 or 8
1226
+ evals[17] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_O)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4
1227
+ evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_O)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 6
1296
1228
 
1297
- ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9
1229
+ ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_O)); // deg 3 or 9
1298
1230
 
1299
1231
  /**
1300
1232
  * RAM Timestamp Consistency Check
@@ -1322,9 +1254,100 @@ library RelationsLib {
1322
1254
  ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9
1323
1255
 
1324
1256
  // (deg 3 or 9) + (deg 4) + (deg 3)
1325
- ap.auxiliary_identity = ap.memory_identity + non_native_field_identity + limb_accumulator_identity;
1326
- ap.auxiliary_identity = ap.auxiliary_identity * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 10
1327
- evals[13] = ap.auxiliary_identity;
1257
+ ap.memory_identity = ap.memory_identity * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 10
1258
+ evals[13] = ap.memory_identity;
1259
+ }
1260
+
1261
+ // Constants for the Non-native Field relation
1262
+ Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68);
1263
+ Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14);
1264
+
1265
+ // Parameters used within the Non-Native Field Relation
1266
+ // A struct is used to work around stack too deep. This relation has alot of variables
1267
+ struct NnfParams {
1268
+ Fr limb_subproduct;
1269
+ Fr non_native_field_gate_1;
1270
+ Fr non_native_field_gate_2;
1271
+ Fr non_native_field_gate_3;
1272
+ Fr limb_accumulator_1;
1273
+ Fr limb_accumulator_2;
1274
+ Fr nnf_identity;
1275
+ }
1276
+
1277
+ function accumulateNnfRelation(
1278
+ Fr[NUMBER_OF_ENTITIES] memory p,
1279
+ Fr[NUMBER_OF_SUBRELATIONS] memory evals,
1280
+ Fr domainSep
1281
+ ) internal pure {
1282
+ NnfParams memory ap;
1283
+
1284
+ /**
1285
+ * Contribution 12
1286
+ * Non native field arithmetic gate 2
1287
+ * deg 4
1288
+ *
1289
+ * _ _
1290
+ * / _ _ _ 14 \
1291
+ * 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 |
1292
+ * \_ _/
1293
+ *
1294
+ *
1295
+ */
1296
+ ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R);
1297
+ ap.non_native_field_gate_2 =
1298
+ (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT));
1299
+ ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE;
1300
+ ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT);
1301
+ ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct;
1302
+ ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4);
1303
+
1304
+ ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE;
1305
+ ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT));
1306
+ ap.non_native_field_gate_1 = ap.limb_subproduct;
1307
+ ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4));
1308
+ ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O);
1309
+
1310
+ ap.non_native_field_gate_3 = ap.limb_subproduct;
1311
+ ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4);
1312
+ ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT));
1313
+ ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M);
1314
+
1315
+ Fr non_native_field_identity =
1316
+ ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3;
1317
+ non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R);
1318
+
1319
+ // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm
1320
+ // deg 2
1321
+ ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT;
1322
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT);
1323
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT;
1324
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O);
1325
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT;
1326
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R);
1327
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT;
1328
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L);
1329
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4);
1330
+ ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4);
1331
+
1332
+ // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm
1333
+ // deg 2
1334
+ ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT;
1335
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT);
1336
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT;
1337
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT);
1338
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT;
1339
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4);
1340
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT;
1341
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O);
1342
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT);
1343
+ ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M);
1344
+
1345
+ Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2;
1346
+ limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3
1347
+
1348
+ ap.nnf_identity = non_native_field_identity + limb_accumulator_identity;
1349
+ ap.nnf_identity = ap.nnf_identity * (wire(p, WIRE.Q_NNF) * domainSep);
1350
+ evals[19] = ap.nnf_identity;
1328
1351
  }
1329
1352
 
1330
1353
  struct PoseidonExternalParams {
@@ -1380,13 +1403,13 @@ library RelationsLib {
1380
1403
  ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4
1381
1404
 
1382
1405
  ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep;
1383
- evals[19] = evals[19] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT));
1406
+ evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT));
1384
1407
 
1385
- evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT));
1408
+ evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT));
1386
1409
 
1387
- evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT));
1410
+ evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT));
1388
1411
 
1389
- evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT));
1412
+ evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT));
1390
1413
  }
1391
1414
 
1392
1415
  struct PoseidonInternalParams {
@@ -1432,16 +1455,16 @@ library RelationsLib {
1432
1455
  ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep;
1433
1456
 
1434
1457
  ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum;
1435
- evals[23] = evals[23] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT));
1458
+ evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT));
1436
1459
 
1437
1460
  ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum;
1438
- evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT));
1461
+ evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT));
1439
1462
 
1440
1463
  ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum;
1441
- evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT));
1464
+ evals[26] = evals[26] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT));
1442
1465
 
1443
1466
  ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum;
1444
- evals[26] = evals[26] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT));
1467
+ evals[27] = evals[27] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT));
1445
1468
  }
1446
1469
 
1447
1470
  function scaleAndBatchSubrelations(
@@ -1465,6 +1488,8 @@ library CommitmentSchemeLib {
1465
1488
  struct ShpleminiIntermediates {
1466
1489
  Fr unshiftedScalar;
1467
1490
  Fr shiftedScalar;
1491
+ Fr unshiftedScalarNeg;
1492
+ Fr shiftedScalarNeg;
1468
1493
  // Scalar to be multiplied by [1]₁
1469
1494
  Fr constantTermAccumulator;
1470
1495
  // Accumulator for powers of rho
@@ -1482,14 +1507,16 @@ library CommitmentSchemeLib {
1482
1507
  // ν^{2i+1} * 1/(z + r^{2^i})
1483
1508
  Fr scalingFactorNeg;
1484
1509
  // Fold_i(r^{2^i}) reconstructed by Verifier
1485
- Fr[CONST_PROOF_SIZE_LOG_N] foldPosEvaluations;
1510
+ Fr[] foldPosEvaluations;
1486
1511
  }
1487
1512
 
1488
- function computeSquares(Fr r) internal pure returns (Fr[CONST_PROOF_SIZE_LOG_N] memory squares) {
1513
+ function computeSquares(Fr r, uint256 logN) internal pure returns (Fr[] memory) {
1514
+ Fr[] memory squares = new Fr[](logN);
1489
1515
  squares[0] = r;
1490
- for (uint256 i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) {
1516
+ for (uint256 i = 1; i < logN; ++i) {
1491
1517
  squares[i] = squares[i - 1].sqr();
1492
1518
  }
1519
+ return squares;
1493
1520
  }
1494
1521
  // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1
1495
1522
 
@@ -1497,10 +1524,11 @@ library CommitmentSchemeLib {
1497
1524
  Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges,
1498
1525
  Fr batchedEvalAccumulator,
1499
1526
  Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations,
1500
- Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers,
1527
+ Fr[] memory geminiEvalChallengePowers,
1501
1528
  uint256 logSize
1502
- ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations) {
1503
- for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) {
1529
+ ) internal view returns (Fr[] memory) {
1530
+ Fr[] memory foldPosEvaluations = new Fr[](logSize);
1531
+ for (uint256 i = logSize; i > 0; --i) {
1504
1532
  Fr challengePower = geminiEvalChallengePowers[i - 1];
1505
1533
  Fr u = sumcheckUChallenges[i - 1];
1506
1534
 
@@ -1515,12 +1543,12 @@ library CommitmentSchemeLib {
1515
1543
  foldPosEvaluations[i - 1] = batchedEvalRoundAcc;
1516
1544
  }
1517
1545
  }
1546
+ return foldPosEvaluations;
1518
1547
  }
1519
1548
  }
1520
1549
 
1521
1550
  uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q
1522
1551
 
1523
-
1524
1552
  function bytes32ToString(bytes32 value) pure returns (string memory result) {
1525
1553
  bytes memory alphabet = "0123456789abcdef";
1526
1554
 
@@ -1534,27 +1562,17 @@ function bytes32ToString(bytes32 value) pure returns (string memory result) {
1534
1562
  result = string(str);
1535
1563
  }
1536
1564
 
1537
-
1538
1565
  // Fr utility
1539
1566
 
1540
1567
  function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) {
1541
- require(proofSection.length == 0x20, "invalid number of bytes to construct Fr scalar");
1542
1568
  scalar = FrLib.fromBytes32(bytes32(proofSection));
1543
1569
  }
1544
1570
 
1545
1571
  // EC Point utilities
1546
-
1547
- function convertProofPoint(Honk.G1ProofPoint memory input) pure returns (Honk.G1Point memory point) {
1548
- point = Honk.G1Point({x: input.x_0 | (input.x_1 << 136), y: input.y_0 | (input.y_1 << 136)});
1549
- }
1550
-
1551
- function bytesToG1ProofPoint(bytes calldata proofSection) pure returns (Honk.G1ProofPoint memory point) {
1552
- require(proofSection.length == 0x80, "invalid number of bytes to construct a G1 point");
1553
- point = Honk.G1ProofPoint({
1554
- x_0: uint256(bytes32(proofSection[0x00:0x20])),
1555
- x_1: uint256(bytes32(proofSection[0x20:0x40])),
1556
- y_0: uint256(bytes32(proofSection[0x40:0x60])),
1557
- y_1: uint256(bytes32(proofSection[0x60:0x80]))
1572
+ function bytesToG1Point(bytes calldata proofSection) pure returns (Honk.G1Point memory point) {
1573
+ point = Honk.G1Point({
1574
+ x: uint256(bytes32(proofSection[0x00:0x20])) % Q,
1575
+ y: uint256(bytes32(proofSection[0x20:0x40])) % Q
1558
1576
  });
1559
1577
  }
1560
1578
 
@@ -1563,6 +1581,212 @@ function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point mem
1563
1581
  return point;
1564
1582
  }
1565
1583
 
1584
+ /**
1585
+ * Convert the pairing points to G1 points.
1586
+ *
1587
+ * The pairing points are serialised as an array of 68 bit limbs representing two points
1588
+ * The lhs of a pairing operation and the rhs of a pairing operation
1589
+ *
1590
+ * There are 4 fields for each group element, leaving 8 fields for each side of the pairing.
1591
+ *
1592
+ * @param pairingPoints The pairing points to convert.
1593
+ * @return lhs
1594
+ * @return rhs
1595
+ */
1596
+ function convertPairingPointsToG1(Fr[PAIRING_POINTS_SIZE] memory pairingPoints)
1597
+ pure
1598
+ returns (Honk.G1Point memory lhs, Honk.G1Point memory rhs)
1599
+ {
1600
+ uint256 lhsX = Fr.unwrap(pairingPoints[0]);
1601
+ lhsX |= Fr.unwrap(pairingPoints[1]) << 68;
1602
+ lhsX |= Fr.unwrap(pairingPoints[2]) << 136;
1603
+ lhsX |= Fr.unwrap(pairingPoints[3]) << 204;
1604
+ lhs.x = lhsX;
1605
+
1606
+ uint256 lhsY = Fr.unwrap(pairingPoints[4]);
1607
+ lhsY |= Fr.unwrap(pairingPoints[5]) << 68;
1608
+ lhsY |= Fr.unwrap(pairingPoints[6]) << 136;
1609
+ lhsY |= Fr.unwrap(pairingPoints[7]) << 204;
1610
+ lhs.y = lhsY;
1611
+
1612
+ uint256 rhsX = Fr.unwrap(pairingPoints[8]);
1613
+ rhsX |= Fr.unwrap(pairingPoints[9]) << 68;
1614
+ rhsX |= Fr.unwrap(pairingPoints[10]) << 136;
1615
+ rhsX |= Fr.unwrap(pairingPoints[11]) << 204;
1616
+ rhs.x = rhsX;
1617
+
1618
+ uint256 rhsY = Fr.unwrap(pairingPoints[12]);
1619
+ rhsY |= Fr.unwrap(pairingPoints[13]) << 68;
1620
+ rhsY |= Fr.unwrap(pairingPoints[14]) << 136;
1621
+ rhsY |= Fr.unwrap(pairingPoints[15]) << 204;
1622
+ rhs.y = rhsY;
1623
+ }
1624
+
1625
+ /**
1626
+ * Hash the pairing inputs from the present verification context with those extracted from the public inputs.
1627
+ *
1628
+ * @param proofPairingPoints Pairing points from the proof - (public inputs).
1629
+ * @param accLhs Accumulator point for the left side - result of shplemini.
1630
+ * @param accRhs Accumulator point for the right side - result of shplemini.
1631
+ * @return recursionSeparator The recursion separator - generated from hashing the above.
1632
+ */
1633
+ function generateRecursionSeparator(
1634
+ Fr[PAIRING_POINTS_SIZE] memory proofPairingPoints,
1635
+ Honk.G1Point memory accLhs,
1636
+ Honk.G1Point memory accRhs
1637
+ ) pure returns (Fr recursionSeparator) {
1638
+ // hash the proof aggregated X
1639
+ // hash the proof aggregated Y
1640
+ // hash the accum X
1641
+ // hash the accum Y
1642
+
1643
+ (Honk.G1Point memory proofLhs, Honk.G1Point memory proofRhs) = convertPairingPointsToG1(proofPairingPoints);
1644
+
1645
+ uint256[8] memory recursionSeparatorElements;
1646
+
1647
+ // Proof points
1648
+ recursionSeparatorElements[0] = proofLhs.x;
1649
+ recursionSeparatorElements[1] = proofLhs.y;
1650
+ recursionSeparatorElements[2] = proofRhs.x;
1651
+ recursionSeparatorElements[3] = proofRhs.y;
1652
+
1653
+ // Accumulator points
1654
+ recursionSeparatorElements[4] = accLhs.x;
1655
+ recursionSeparatorElements[5] = accLhs.y;
1656
+ recursionSeparatorElements[6] = accRhs.x;
1657
+ recursionSeparatorElements[7] = accRhs.y;
1658
+
1659
+ recursionSeparator = FrLib.fromBytes32(keccak256(abi.encodePacked(recursionSeparatorElements)));
1660
+ }
1661
+
1662
+ /**
1663
+ * G1 Mul with Separator
1664
+ * Using the ecAdd and ecMul precompiles
1665
+ *
1666
+ * @param basePoint The point to multiply.
1667
+ * @param other The other point to add.
1668
+ * @param recursionSeperator The separator to use for the multiplication.
1669
+ * @return `(recursionSeperator * basePoint) + other`.
1670
+ */
1671
+ function mulWithSeperator(Honk.G1Point memory basePoint, Honk.G1Point memory other, Fr recursionSeperator)
1672
+ view
1673
+ returns (Honk.G1Point memory)
1674
+ {
1675
+ Honk.G1Point memory result;
1676
+
1677
+ result = ecMul(recursionSeperator, basePoint);
1678
+ result = ecAdd(result, other);
1679
+
1680
+ return result;
1681
+ }
1682
+
1683
+ /**
1684
+ * G1 Mul
1685
+ * Takes a Fr value and a G1 point and uses the ecMul precompile to return the result.
1686
+ *
1687
+ * @param value The value to multiply the point by.
1688
+ * @param point The point to multiply.
1689
+ * @return result The result of the multiplication.
1690
+ */
1691
+ function ecMul(Fr value, Honk.G1Point memory point) view returns (Honk.G1Point memory) {
1692
+ Honk.G1Point memory result;
1693
+
1694
+ assembly {
1695
+ let free := mload(0x40)
1696
+ // Write the point into memory (two 32 byte words)
1697
+ // Memory layout:
1698
+ // Address | value
1699
+ // free | point.x
1700
+ // free + 0x20| point.y
1701
+ mstore(free, mload(point))
1702
+ mstore(add(free, 0x20), mload(add(point, 0x20)))
1703
+ // Write the scalar into memory (one 32 byte word)
1704
+ // Memory layout:
1705
+ // Address | value
1706
+ // free + 0x40| value
1707
+ mstore(add(free, 0x40), value)
1708
+
1709
+ // Call the ecMul precompile, it takes in the following
1710
+ // [point.x, point.y, scalar], and returns the result back into the free memory location.
1711
+ let success := staticcall(gas(), 0x07, free, 0x60, free, 0x40)
1712
+ if iszero(success) {
1713
+ revert(0, 0)
1714
+ }
1715
+ // Copy the result of the multiplication back into the result memory location.
1716
+ // Memory layout:
1717
+ // Address | value
1718
+ // result | result.x
1719
+ // result + 0x20| result.y
1720
+ mstore(result, mload(free))
1721
+ mstore(add(result, 0x20), mload(add(free, 0x20)))
1722
+
1723
+ mstore(0x40, add(free, 0x60))
1724
+ }
1725
+
1726
+ return result;
1727
+ }
1728
+
1729
+ /**
1730
+ * G1 Add
1731
+ * Takes two G1 points and uses the ecAdd precompile to return the result.
1732
+ *
1733
+ * @param lhs The left hand side of the addition.
1734
+ * @param rhs The right hand side of the addition.
1735
+ * @return result The result of the addition.
1736
+ */
1737
+ function ecAdd(Honk.G1Point memory lhs, Honk.G1Point memory rhs) view returns (Honk.G1Point memory) {
1738
+ Honk.G1Point memory result;
1739
+
1740
+ assembly {
1741
+ let free := mload(0x40)
1742
+ // Write lhs into memory (two 32 byte words)
1743
+ // Memory layout:
1744
+ // Address | value
1745
+ // free | lhs.x
1746
+ // free + 0x20| lhs.y
1747
+ mstore(free, mload(lhs))
1748
+ mstore(add(free, 0x20), mload(add(lhs, 0x20)))
1749
+
1750
+ // Write rhs into memory (two 32 byte words)
1751
+ // Memory layout:
1752
+ // Address | value
1753
+ // free + 0x40| rhs.x
1754
+ // free + 0x60| rhs.y
1755
+ mstore(add(free, 0x40), mload(rhs))
1756
+ mstore(add(free, 0x60), mload(add(rhs, 0x20)))
1757
+
1758
+ // Call the ecAdd precompile, it takes in the following
1759
+ // [lhs.x, lhs.y, rhs.x, rhs.y], and returns their addition back into the free memory location.
1760
+ let success := staticcall(gas(), 0x06, free, 0x80, free, 0x40)
1761
+ if iszero(success) { revert(0, 0) }
1762
+
1763
+ // Copy the result of the addition back into the result memory location.
1764
+ // Memory layout:
1765
+ // Address | value
1766
+ // result | result.x
1767
+ // result + 0x20| result.y
1768
+ mstore(result, mload(free))
1769
+ mstore(add(result, 0x20), mload(add(free, 0x20)))
1770
+
1771
+ mstore(0x40, add(free, 0x80))
1772
+ }
1773
+
1774
+ return result;
1775
+ }
1776
+
1777
+ function validateOnCurve(Honk.G1Point memory point) pure {
1778
+ uint256 x = point.x;
1779
+ uint256 y = point.y;
1780
+
1781
+ bool success = false;
1782
+ assembly {
1783
+ let xx := mulmod(x, x, Q)
1784
+ success := eq(mulmod(y, y, Q), addmod(mulmod(x, xx, Q), 3, Q))
1785
+ }
1786
+
1787
+ require(success, "point is not on the curve");
1788
+ }
1789
+
1566
1790
  function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) {
1567
1791
  bytes memory input = abi.encodePacked(
1568
1792
  rhs.x,
@@ -1585,7 +1809,6 @@ function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns
1585
1809
  decodedResult = success && abi.decode(result, (bool));
1586
1810
  }
1587
1811
 
1588
-
1589
1812
  // Field arithmetic libraries - prevent littering the code with modmul / addmul
1590
1813
 
1591
1814
 
@@ -1596,62 +1819,100 @@ abstract contract BaseHonkVerifier is IVerifier {
1596
1819
 
1597
1820
  uint256 immutable $N;
1598
1821
  uint256 immutable $LOG_N;
1822
+ uint256 immutable $VK_HASH;
1599
1823
  uint256 immutable $NUM_PUBLIC_INPUTS;
1600
1824
 
1601
- constructor(uint256 _N, uint256 _logN, uint256 _numPublicInputs) {
1825
+ constructor(uint256 _N, uint256 _logN, uint256 _vkHash, uint256 _numPublicInputs) {
1602
1826
  $N = _N;
1603
1827
  $LOG_N = _logN;
1828
+ $VK_HASH = _vkHash;
1604
1829
  $NUM_PUBLIC_INPUTS = _numPublicInputs;
1605
1830
  }
1606
1831
 
1607
1832
  // Errors
1608
1833
  error ProofLengthWrong();
1834
+ error ProofLengthWrongWithLogN(uint256 logN, uint256 actualLength, uint256 expectedLength);
1609
1835
  error PublicInputsLengthWrong();
1610
1836
  error SumcheckFailed();
1611
1837
  error ShpleminiFailed();
1612
1838
 
1613
- // Number of field elements in a ultra honk proof, including pairing point object.
1614
- uint256 constant PROOF_SIZE = 456;
1839
+ // Constants for proof length calculation (matching UltraKeccakFlavor)
1840
+ uint256 constant NUM_WITNESS_ENTITIES = 8;
1841
+ uint256 constant NUM_ELEMENTS_COMM = 2; // uint256 elements for curve points
1842
+ uint256 constant NUM_ELEMENTS_FR = 1; // uint256 elements for field elements
1843
+
1844
+ // Calculate proof size based on log_n (matching UltraKeccakFlavor formula)
1845
+ function calculateProofSize(uint256 logN) internal pure returns (uint256) {
1846
+ // Witness commitments
1847
+ uint256 proofLength = NUM_WITNESS_ENTITIES * NUM_ELEMENTS_COMM; // witness commitments
1848
+
1849
+ // Sumcheck
1850
+ proofLength += logN * BATCHED_RELATION_PARTIAL_LENGTH * NUM_ELEMENTS_FR; // sumcheck univariates
1851
+ proofLength += NUMBER_OF_ENTITIES * NUM_ELEMENTS_FR; // sumcheck evaluations
1852
+
1853
+ // Gemini
1854
+ proofLength += (logN - 1) * NUM_ELEMENTS_COMM; // Gemini Fold commitments
1855
+ proofLength += logN * NUM_ELEMENTS_FR; // Gemini evaluations
1856
+
1857
+ // Shplonk and KZG commitments
1858
+ proofLength += NUM_ELEMENTS_COMM * 2; // Shplonk Q and KZG W commitments
1859
+
1860
+ // Pairing points
1861
+ proofLength += PAIRING_POINTS_SIZE; // pairing inputs carried on public inputs
1862
+
1863
+ return proofLength;
1864
+ }
1865
+
1866
+ // Number of field elements in a ultra keccak honk proof for log_n = 25, including pairing point object.
1867
+ uint256 constant PROOF_SIZE = 350; // Legacy constant - will be replaced by calculateProofSize($LOG_N)
1868
+ uint256 constant SHIFTED_COMMITMENTS_START = 29;
1615
1869
 
1616
1870
  function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory);
1617
1871
 
1618
1872
  function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) {
1873
+ // Calculate expected proof size based on $LOG_N
1874
+ uint256 expectedProofSize = calculateProofSize($LOG_N);
1875
+
1619
1876
  // Check the received proof is the expected size where each field element is 32 bytes
1620
- if (proof.length != PROOF_SIZE * 32) {
1621
- revert ProofLengthWrong();
1877
+ if (proof.length != expectedProofSize * 32) {
1878
+ revert ProofLengthWrongWithLogN($LOG_N, proof.length, expectedProofSize * 32);
1622
1879
  }
1623
1880
 
1624
1881
  Honk.VerificationKey memory vk = loadVerificationKey();
1625
- Honk.Proof memory p = TranscriptLib.loadProof(proof);
1882
+ Honk.Proof memory p = TranscriptLib.loadProof(proof, $LOG_N);
1626
1883
  if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) {
1627
1884
  revert PublicInputsLengthWrong();
1628
1885
  }
1629
1886
 
1630
1887
  // Generate the fiat shamir challenges for the whole protocol
1631
- Transcript memory t =
1632
- TranscriptLib.generateTranscript(p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1);
1888
+ Transcript memory t = TranscriptLib.generateTranscript(p, publicInputs, $VK_HASH, $NUM_PUBLIC_INPUTS, $LOG_N);
1633
1889
 
1634
1890
  // Derive public input delta
1635
1891
  t.relationParameters.publicInputsDelta = computePublicInputDelta(
1636
- publicInputs, p.pairingPointObject, t.relationParameters.beta, t.relationParameters.gamma, /*pubInputsOffset=*/ 1
1892
+ publicInputs,
1893
+ p.pairingPointObject,
1894
+ t.relationParameters.beta,
1895
+ t.relationParameters.gamma, /*pubInputsOffset=*/
1896
+ 1
1637
1897
  );
1638
1898
 
1639
1899
  // Sumcheck
1640
1900
  bool sumcheckVerified = verifySumcheck(p, t);
1641
1901
  if (!sumcheckVerified) revert SumcheckFailed();
1642
1902
 
1643
-
1644
1903
  bool shpleminiVerified = verifyShplemini(p, vk, t);
1645
1904
  if (!shpleminiVerified) revert ShpleminiFailed();
1646
1905
 
1647
1906
  return sumcheckVerified && shpleminiVerified; // Boolean condition not required - nice for vanity :)
1648
1907
  }
1649
1908
 
1650
- function computePublicInputDelta(bytes32[] memory publicInputs, Fr[PAIRING_POINTS_SIZE] memory pairingPointObject, Fr beta, Fr gamma, uint256 offset)
1651
- internal
1652
- view
1653
- returns (Fr publicInputDelta)
1654
- {
1909
+ function computePublicInputDelta(
1910
+ bytes32[] memory publicInputs,
1911
+ Fr[PAIRING_POINTS_SIZE] memory pairingPointObject,
1912
+ Fr beta,
1913
+ Fr gamma,
1914
+ uint256 offset
1915
+ ) internal view returns (Fr publicInputDelta) {
1655
1916
  Fr numerator = ONE;
1656
1917
  Fr denominator = ONE;
1657
1918
 
@@ -1777,11 +2038,11 @@ abstract contract BaseHonkVerifier is IVerifier {
1777
2038
  CommitmentSchemeLib.ShpleminiIntermediates memory mem; // stack
1778
2039
 
1779
2040
  // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size
1780
- Fr[CONST_PROOF_SIZE_LOG_N] memory powers_of_evaluation_challenge = CommitmentSchemeLib.computeSquares(tp.geminiR);
2041
+ Fr[] memory powers_of_evaluation_challenge = CommitmentSchemeLib.computeSquares(tp.geminiR, $LOG_N);
1781
2042
 
1782
2043
  // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings
1783
- Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory scalars;
1784
- Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory commitments;
2044
+ Fr[] memory scalars = new Fr[](NUMBER_UNSHIFTED + $LOG_N + 2);
2045
+ Honk.G1Point[] memory commitments = new Honk.G1Point[](NUMBER_UNSHIFTED + $LOG_N + 2);
1785
2046
 
1786
2047
  mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[0]).invert();
1787
2048
  mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[0]).invert();
@@ -1791,7 +2052,7 @@ abstract contract BaseHonkVerifier is IVerifier {
1791
2052
  tp.geminiR.invert() * (mem.posInvertedDenominator - (tp.shplonkNu * mem.negInvertedDenominator));
1792
2053
 
1793
2054
  scalars[0] = ONE;
1794
- commitments[0] = convertProofPoint(proof.shplonkQ);
2055
+ commitments[0] = proof.shplonkQ;
1795
2056
 
1796
2057
  /* Batch multivariate opening claims, shifted and unshifted
1797
2058
  * The vector of scalars is populated as follows:
@@ -1823,15 +2084,26 @@ abstract contract BaseHonkVerifier is IVerifier {
1823
2084
  mem.batchingChallenge = ONE;
1824
2085
  mem.batchedEvaluation = ZERO;
1825
2086
 
2087
+ mem.unshiftedScalarNeg = mem.unshiftedScalar.neg();
2088
+ mem.shiftedScalarNeg = mem.shiftedScalar.neg();
1826
2089
  for (uint256 i = 1; i <= NUMBER_UNSHIFTED; ++i) {
1827
- scalars[i] = mem.unshiftedScalar.neg() * mem.batchingChallenge;
2090
+ scalars[i] = mem.unshiftedScalarNeg * mem.batchingChallenge;
1828
2091
  mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i - 1] * mem.batchingChallenge);
1829
2092
  mem.batchingChallenge = mem.batchingChallenge * tp.rho;
1830
2093
  }
1831
2094
  // g commitments are accumulated at r
1832
- for (uint256 i = NUMBER_UNSHIFTED + 1; i <= NUMBER_OF_ENTITIES; ++i) {
1833
- scalars[i] = mem.shiftedScalar.neg() * mem.batchingChallenge;
1834
- mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i - 1] * mem.batchingChallenge);
2095
+ // For each of the to be shifted commitments perform the shift in place by
2096
+ // adding to the unshifted value.
2097
+ // We do so, as the values are to be used in batchMul later, and as
2098
+ // `a * c + b * c = (a + b) * c` this will allow us to reduce memory and compute.
2099
+ // Applied to w1, w2, w3, w4 and zPerm
2100
+ for (uint256 i = 0; i < NUMBER_TO_BE_SHIFTED; ++i) {
2101
+ uint256 scalarOff = i + SHIFTED_COMMITMENTS_START;
2102
+ uint256 evaluationOff = i + NUMBER_UNSHIFTED;
2103
+
2104
+ scalars[scalarOff] = scalars[scalarOff] + (mem.shiftedScalarNeg * mem.batchingChallenge);
2105
+ mem.batchedEvaluation =
2106
+ mem.batchedEvaluation + (proof.sumcheckEvaluations[evaluationOff] * mem.batchingChallenge);
1835
2107
  mem.batchingChallenge = mem.batchingChallenge * tp.rho;
1836
2108
  }
1837
2109
 
@@ -1845,40 +2117,34 @@ abstract contract BaseHonkVerifier is IVerifier {
1845
2117
  commitments[8] = vk.qArith;
1846
2118
  commitments[9] = vk.qDeltaRange;
1847
2119
  commitments[10] = vk.qElliptic;
1848
- commitments[11] = vk.qAux;
1849
- commitments[12] = vk.qPoseidon2External;
1850
- commitments[13] = vk.qPoseidon2Internal;
1851
- commitments[14] = vk.s1;
1852
- commitments[15] = vk.s2;
1853
- commitments[16] = vk.s3;
1854
- commitments[17] = vk.s4;
1855
- commitments[18] = vk.id1;
1856
- commitments[19] = vk.id2;
1857
- commitments[20] = vk.id3;
1858
- commitments[21] = vk.id4;
1859
- commitments[22] = vk.t1;
1860
- commitments[23] = vk.t2;
1861
- commitments[24] = vk.t3;
1862
- commitments[25] = vk.t4;
1863
- commitments[26] = vk.lagrangeFirst;
1864
- commitments[27] = vk.lagrangeLast;
2120
+ commitments[11] = vk.qMemory;
2121
+ commitments[12] = vk.qNnf;
2122
+ commitments[13] = vk.qPoseidon2External;
2123
+ commitments[14] = vk.qPoseidon2Internal;
2124
+ commitments[15] = vk.s1;
2125
+ commitments[16] = vk.s2;
2126
+ commitments[17] = vk.s3;
2127
+ commitments[18] = vk.s4;
2128
+ commitments[19] = vk.id1;
2129
+ commitments[20] = vk.id2;
2130
+ commitments[21] = vk.id3;
2131
+ commitments[22] = vk.id4;
2132
+ commitments[23] = vk.t1;
2133
+ commitments[24] = vk.t2;
2134
+ commitments[25] = vk.t3;
2135
+ commitments[26] = vk.t4;
2136
+ commitments[27] = vk.lagrangeFirst;
2137
+ commitments[28] = vk.lagrangeLast;
1865
2138
 
1866
2139
  // Accumulate proof points
1867
- commitments[28] = convertProofPoint(proof.w1);
1868
- commitments[29] = convertProofPoint(proof.w2);
1869
- commitments[30] = convertProofPoint(proof.w3);
1870
- commitments[31] = convertProofPoint(proof.w4);
1871
- commitments[32] = convertProofPoint(proof.zPerm);
1872
- commitments[33] = convertProofPoint(proof.lookupInverses);
1873
- commitments[34] = convertProofPoint(proof.lookupReadCounts);
1874
- commitments[35] = convertProofPoint(proof.lookupReadTags);
1875
-
1876
- // to be Shifted
1877
- commitments[36] = convertProofPoint(proof.w1);
1878
- commitments[37] = convertProofPoint(proof.w2);
1879
- commitments[38] = convertProofPoint(proof.w3);
1880
- commitments[39] = convertProofPoint(proof.w4);
1881
- commitments[40] = convertProofPoint(proof.zPerm);
2140
+ commitments[29] = proof.w1;
2141
+ commitments[30] = proof.w2;
2142
+ commitments[31] = proof.w3;
2143
+ commitments[32] = proof.w4;
2144
+ commitments[33] = proof.zPerm;
2145
+ commitments[34] = proof.lookupInverses;
2146
+ commitments[35] = proof.lookupReadCounts;
2147
+ commitments[36] = proof.lookupReadTags;
1882
2148
 
1883
2149
  /* Batch gemini claims from the prover
1884
2150
  * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from
@@ -1904,7 +2170,7 @@ abstract contract BaseHonkVerifier is IVerifier {
1904
2170
  */
1905
2171
 
1906
2172
  // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., $LOG_N - 1
1907
- Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations = CommitmentSchemeLib.computeFoldPosEvaluations(
2173
+ Fr[] memory foldPosEvaluations = CommitmentSchemeLib.computeFoldPosEvaluations(
1908
2174
  tp.sumCheckUChallenges,
1909
2175
  mem.batchedEvaluation,
1910
2176
  proof.geminiAEvaluations,
@@ -1921,7 +2187,7 @@ abstract contract BaseHonkVerifier is IVerifier {
1921
2187
 
1922
2188
  // Compute Shplonk constant term contributions from Aₗ(± r^{2ˡ}) for l = 1, ..., m-1;
1923
2189
  // Compute scalar multipliers for each fold commitment
1924
- for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) {
2190
+ for (uint256 i = 0; i < $LOG_N - 1; ++i) {
1925
2191
  bool dummy_round = i >= ($LOG_N - 1);
1926
2192
 
1927
2193
  if (!dummy_round) {
@@ -1933,7 +2199,7 @@ abstract contract BaseHonkVerifier is IVerifier {
1933
2199
  mem.scalingFactorPos = mem.batchingChallenge * mem.posInvertedDenominator;
1934
2200
  mem.scalingFactorNeg = mem.batchingChallenge * tp.shplonkNu * mem.negInvertedDenominator;
1935
2201
  // [Aₗ] is multiplied by -v^{2l}/(z-r^{2^l}) - v^{2l+1} /(z+ r^{2^l})
1936
- scalars[NUMBER_OF_ENTITIES + 1 + i] = mem.scalingFactorNeg.neg() + mem.scalingFactorPos.neg();
2202
+ scalars[NUMBER_UNSHIFTED + 1 + i] = mem.scalingFactorNeg.neg() + mem.scalingFactorPos.neg();
1937
2203
 
1938
2204
  // Accumulate the const term contribution given by
1939
2205
  // v^{2l} * Aₗ(r^{2ˡ}) /(z-r^{2^l}) + v^{2l+1} * Aₗ(-r^{2ˡ}) /(z+ r^{2^l})
@@ -1944,45 +2210,55 @@ abstract contract BaseHonkVerifier is IVerifier {
1944
2210
  mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu;
1945
2211
  }
1946
2212
 
1947
- commitments[NUMBER_OF_ENTITIES + 1 + i] = convertProofPoint(proof.geminiFoldComms[i]);
2213
+ commitments[NUMBER_UNSHIFTED + 1 + i] = proof.geminiFoldComms[i];
1948
2214
  }
1949
2215
 
1950
2216
  // Finalise the batch opening claim
1951
- commitments[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N] = Honk.G1Point({x: 1, y: 2});
1952
- scalars[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N] = mem.constantTermAccumulator;
2217
+ commitments[NUMBER_UNSHIFTED + $LOG_N] = Honk.G1Point({x: 1, y: 2});
2218
+ scalars[NUMBER_UNSHIFTED + $LOG_N] = mem.constantTermAccumulator;
2219
+
2220
+ Honk.G1Point memory quotient_commitment = proof.kzgQuotient;
1953
2221
 
1954
- Honk.G1Point memory quotient_commitment = convertProofPoint(proof.kzgQuotient);
2222
+ commitments[NUMBER_UNSHIFTED + $LOG_N + 1] = quotient_commitment;
2223
+ scalars[NUMBER_UNSHIFTED + $LOG_N + 1] = tp.shplonkZ; // evaluation challenge
1955
2224
 
1956
- commitments[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 1] = quotient_commitment;
1957
- scalars[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 1] = tp.shplonkZ; // evaluation challenge
2225
+ Honk.G1Point memory P_0_agg = batchMul(commitments, scalars);
2226
+ Honk.G1Point memory P_1_agg = negateInplace(quotient_commitment);
1958
2227
 
1959
- Honk.G1Point memory P_0 = batchMul(commitments, scalars);
1960
- Honk.G1Point memory P_1 = negateInplace(quotient_commitment);
2228
+ // Aggregate pairing points
2229
+ Fr recursionSeparator = generateRecursionSeparator(proof.pairingPointObject, P_0_agg, P_1_agg);
2230
+ (Honk.G1Point memory P_0_other, Honk.G1Point memory P_1_other) =
2231
+ convertPairingPointsToG1(proof.pairingPointObject);
1961
2232
 
1962
- return pairing(P_0, P_1);
2233
+ // Validate the points from the proof are on the curve
2234
+ validateOnCurve(P_0_other);
2235
+ validateOnCurve(P_1_other);
2236
+
2237
+ // accumulate with aggregate points in proof
2238
+ P_0_agg = mulWithSeperator(P_0_agg, P_0_other, recursionSeparator);
2239
+ P_1_agg = mulWithSeperator(P_1_agg, P_1_other, recursionSeparator);
2240
+
2241
+ return pairing(P_0_agg, P_1_agg);
1963
2242
  }
1964
2243
 
1965
- // This implementation is the same as above with different constants
1966
- function batchMul(
1967
- Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory base,
1968
- Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory scalars
1969
- ) internal view returns (Honk.G1Point memory result) {
1970
- uint256 limit = NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2;
2244
+ function batchMul(Honk.G1Point[] memory base, Fr[] memory scalars)
2245
+ internal
2246
+ view
2247
+ returns (Honk.G1Point memory result)
2248
+ {
2249
+ uint256 limit = NUMBER_UNSHIFTED + $LOG_N + 2;
2250
+
2251
+ // Validate all points are on the curve
2252
+ for (uint256 i = 0; i < limit; ++i) {
2253
+ validateOnCurve(base[i]);
2254
+ }
2255
+
2256
+ bool success = true;
1971
2257
  assembly {
1972
- let success := 0x01
1973
2258
  let free := mload(0x40)
1974
2259
 
1975
- // Write the original into the accumulator
1976
- // Load into memory for ecMUL, leave offset for eccAdd result
1977
- // base is an array of pointers, so we have to dereference them
1978
- mstore(add(free, 0x40), mload(mload(base)))
1979
- mstore(add(free, 0x60), mload(add(0x20, mload(base))))
1980
- // Add scalar
1981
- mstore(add(free, 0x80), mload(scalars))
1982
- success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40))
1983
-
1984
2260
  let count := 0x01
1985
- for {} lt(count, limit) { count := add(count, 1) } {
2261
+ for {} lt(count, add(limit, 1)) { count := add(count, 1) } {
1986
2262
  // Get loop offsets
1987
2263
  let base_base := add(base, mul(count, 0x20))
1988
2264
  let scalar_base := add(scalars, mul(count, 0x20))
@@ -1997,14 +2273,16 @@ abstract contract BaseHonkVerifier is IVerifier {
1997
2273
  success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40))
1998
2274
  }
1999
2275
 
2000
- // Return the result - i hate this
2276
+ // Return the result
2001
2277
  mstore(result, mload(free))
2002
2278
  mstore(add(result, 0x20), mload(add(free, 0x20)))
2003
2279
  }
2280
+
2281
+ require(success, ShpleminiFailed());
2004
2282
  }
2005
2283
  }
2006
2284
 
2007
- contract HonkVerifier is BaseHonkVerifier(N, LOG_N, NUMBER_OF_PUBLIC_INPUTS) {
2285
+ contract HonkVerifier is BaseHonkVerifier(N, LOG_N, VK_HASH, NUMBER_OF_PUBLIC_INPUTS) {
2008
2286
  function loadVerificationKey() internal pure override returns (Honk.VerificationKey memory) {
2009
2287
  return HonkVerificationKey.loadVerificationKey();
2010
2288
  }